# vim: tabstop=4 shiftwidth=4 softtabstop=4 # # Copyright 2011 Cisco Systems, Inc. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # # Initial structure and framework of this CLI has been borrowed from Quantum, # written by the following authors # @author: Somik Behera, Nicira Networks, Inc. # @author: Brad Hall, Nicira Networks, Inc. # @author: Salvatore Orlando, Citrix # # Cisco adaptation for extensions # @author: Sumit Naiksatam, Cisco Systems, Inc. # @author: Ying Liu, Cisco Systems, Inc. import logging import logging.handlers from optparse import OptionParser import os import sys import quantumclient.cli as qcli from quantumclient import Client LOG = logging.getLogger('quantum') FORMAT = 'json' #ACTION_PREFIX_EXT = '/v1.0' #ACTION_PREFIX_CSCO = ACTION_PREFIX_EXT + \ # '/extensions/csco/tenants/{tenant_id}' VERSION = '1.0' URI_PREFIX_EXT = '' URI_PREFIX_CSCO = '/extensions/csco/tenants/{tenant_id}' TENANT_ID = 'nova' CSCO_EXT_NAME = 'Cisco Nova Tenant' DEFAULT_QUANTUM_VERSION = '1.1' def help(): """Help for CLI""" print "\nCisco Extension Commands:" for key in COMMANDS.keys(): print " %s %s" % ( key, " ".join(["<%s>" % y for y in COMMANDS[key]["args"]])) def build_args(cmd, cmdargs, arglist): """Building the list of args for a particular CLI""" args = [] orig_arglist = arglist[:] try: for cmdarg in cmdargs: args.append(arglist[0]) del arglist[0] except: LOG.error("Not enough arguments for \"%s\" (expected: %d, got: %d)" % ( cmd, len(cmdargs), len(orig_arglist))) print "Usage:\n %s %s" % ( cmd, " ".join(["<%s>" % y for y in COMMANDS[cmd]["args"]])) sys.exit() if len(arglist) > 0: LOG.error("Too many arguments for \"%s\" (expected: %d, got: %d)" % ( cmd, len(cmdargs), len(orig_arglist))) print "Usage:\n %s %s" % ( cmd, " ".join(["<%s>" % y for y in COMMANDS[cmd]["args"]])) sys.exit() return args def list_extensions(*args): """Invoking the action to get the supported extensions""" request_url = "/extensions" client = Client(HOST, PORT, USE_SSL, format='json', version=VERSION, uri_prefix=URI_PREFIX_EXT, tenant="dummy") data = client.do_request('GET', request_url) print("Obtained supported extensions from Quantum: %s" % data) def schedule_host(tenant_id, instance_id, user_id=None): """Gets the host name from the Quantum service""" project_id = tenant_id instance_data_dict = { 'novatenant': { 'instance_id': instance_id, 'instance_desc': { 'user_id': user_id, 'project_id': project_id, }, }, } request_url = "/novatenants/" + project_id + "/schedule_host" client = Client(HOST, PORT, USE_SSL, format='json', tenant=TENANT_ID, version=VERSION, uri_prefix=URI_PREFIX_CSCO) data = client.do_request('PUT', request_url, body=instance_data_dict) hostname = data["host_list"]["host_1"] if not hostname: print("Scheduler was unable to locate a host" " for this request. Is the appropriate" " service running?") print("Quantum service returned host: %s" % hostname) def create_multiport(tenant_id, net_id_list, *args): """Creates ports on a single host""" net_list = net_id_list.split(",") ports_info = {'multiport': {'status': 'ACTIVE', 'net_id_list': net_list, 'ports_desc': {'key': 'value'}}} request_url = "/multiport" client = Client(HOST, PORT, USE_SSL, format='json', tenant=tenant_id, version=VERSION, uri_prefix=URI_PREFIX_CSCO) data = client.do_request('POST', request_url, body=ports_info) print("Created ports: %s" % data) COMMANDS = { "create_multiport": { "func": create_multiport, "args": ["tenant-id", "net-id-list (comma separated list of netword IDs)"], }, "list_extensions": { "func": list_extensions, "args": [], }, "schedule_host": { "func": schedule_host, "args": ["tenant-id", "instance-id"], }, } def main(): import cli usagestr = "Usage: %prog [OPTIONS] [args]" PARSER = OptionParser(usage=usagestr) PARSER.add_option("-H", "--host", dest="host", type="string", default="127.0.0.1", help="ip address of api host") PARSER.add_option("-p", "--port", dest="port", type="int", default=9696, help="api poort") PARSER.add_option("-s", "--ssl", dest="ssl", action="store_true", default=False, help="use ssl") PARSER.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False, help="turn on verbose logging") PARSER.add_option("-f", "--logfile", dest="logfile", type="string", default="syslog", help="log file path") PARSER.add_option( '--version', default=DEFAULT_QUANTUM_VERSION, help='Accepts 1.1 and 1.0, defaults to env[QUANTUM_VERSION].') options, args = PARSER.parse_args() if options.verbose: LOG.setLevel(logging.DEBUG) else: LOG.setLevel(logging.WARN) if options.logfile == "syslog": LOG.addHandler(logging.handlers.SysLogHandler(address='/dev/log')) else: LOG.addHandler(logging.handlers.WatchedFileHandler(options.logfile)) os.chmod(options.logfile, 0644) version = options.version if len(args) < 1: PARSER.print_help() qcli.help(version) help() sys.exit(1) CMD = args[0] if CMD in qcli.commands['1.1'].keys(): qcli.main() sys.exit(1) if CMD not in COMMANDS.keys(): LOG.error("Unknown command: %s" % CMD) qcli.help(version) help() sys.exit(1) args = build_args(CMD, COMMANDS[CMD]["args"], args[1:]) LOG.info("Executing command \"%s\" with args: %s" % (CMD, args)) HOST = options.host PORT = options.port USE_SSL = options.ssl COMMANDS[CMD]["func"](*args) LOG.info("Command execution completed") sys.exit(0) if __name__ == "__main__": main()