X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=openmano;h=ec588a98546b3997d22e64c0679959bddcc75252;hb=5461675ac6705ee92916ed741da1914bd2162482;hp=7b33cb46dbecf8fc9796472ffade370127101557;hpb=b36e75da99170c650c999ab2b985a14f3b9a7b5a;p=osm%2FRO.git diff --git a/openmano b/openmano index 7b33cb46..ec588a98 100755 --- a/openmano +++ b/openmano @@ -23,13 +23,13 @@ # contact with: nfvlabs@tid.es ## -''' +""" openmano client used to interact with openmano-server (openmanod) -''' -__author__="Alfonso Tierno, Gerardo Garcia, Pablo Montes" -__date__ ="$09-oct-2014 09:09:48$" -__version__="0.4.13-r519" -version_date="Mar 2017" +""" +__author__ = "Alfonso Tierno, Gerardo Garcia, Pablo Montes" +__date__ = "$09-oct-2014 09:09:48$" +__version__ = "0.4.15-r525" +version_date = "Jul 2017" from argcomplete.completers import FilesCompleter import os @@ -141,6 +141,9 @@ def _print_verbose(mano_response, verbose_level=0): if verbose_level >=1: if content.get('created_at'): myoutput += " " + content['created_at'].ljust(20) + if content.get('sdn_attached_ports'): + #myoutput += " " + str(content['sdn_attached_ports']).ljust(20) + myoutput += "\nsdn_attached_ports:\n" + yaml.safe_dump(content['sdn_attached_ports'], indent=4, default_flow_style=False) if verbose_level >=2: new_line='\n' if content.get('type'): @@ -556,6 +559,7 @@ def scenario_deploy(args): def scenario_verify(args): #print "scenario-verify",args + tenant = _get_tenant() headers_req = {'content-type': 'application/json'} action = {} action["verify"] = {} @@ -563,7 +567,7 @@ def scenario_verify(args): payload_req = json.dumps(action, indent=4) #print payload_req - URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, mano_tenant, args.scenario) + URLrequest = "http://%s:%s/openmano/%s/scenarios/%s/action" %(mano_host, mano_port, tenant, args.scenario) logger.debug("openmano request: %s", payload_req) mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req) logger.debug("openmano response: %s", mano_response.text ) @@ -1029,6 +1033,7 @@ def datacenter_delete(args): print content['error']['description'] return result + def datacenter_list(args): #print "datacenter-list",args tenant='any' if args.all else _get_tenant() @@ -1046,6 +1051,7 @@ def datacenter_list(args): args.verbose += 1 return _print_verbose(mano_response, args.verbose) + def datacenter_sdn_port_mapping_set(args): tenant = _get_tenant() datacenter = _get_datacenter(args.name, tenant) @@ -1054,28 +1060,37 @@ def datacenter_sdn_port_mapping_set(args): if not args.file: raise OpenmanoCLIError( "No yaml/json has been provided specifying the SDN port mapping") + sdn_port_mapping = _load_file_or_yaml(args.file) + payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping}) - port_mapping = yaml.load(datacenter_sdn_port_mapping_list(args)) + # read + URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter) + mano_response = requests.get(URLrequest) + logger.debug("openmano response: %s", mano_response.text) + port_mapping = mano_response.json() + if mano_response.status_code != 200: + str(mano_response.json()) + raise OpenmanoCLIError("openmano client error: {}".format(port_mapping['error']['description'])) if len(port_mapping["sdn_port_mapping"]["ports_mapping"]) > 0: if not args.force: r = raw_input("Datacenter %s already contains a port mapping. Overwrite? (y/N)? " % (datacenter)) if not (len(r) > 0 and r[0].lower() == "y"): return 0 - args.force = True - print datacenter_sdn_port_mapping_clear(args) - sdn_port_mapping = _load_file_or_yaml(args.file) - payload_req = json.dumps({"sdn_port_mapping": sdn_port_mapping}) + # clear + URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter) + mano_response = requests.delete(URLrequest) + logger.debug("openmano response: %s", mano_response.text) + if mano_response.status_code != 200: + return _print_verbose(mano_response, args.verbose) + # set URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter) logger.debug("openmano request: %s", payload_req) mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req) logger.debug("openmano response: %s", mano_response.text) + return _print_verbose(mano_response, args.verbose) - if mano_response.status_code == 200: - return yaml.safe_dump(mano_response.json()) - else: - return mano_response.content def datacenter_sdn_port_mapping_list(args): tenant = _get_tenant() @@ -1085,10 +1100,8 @@ def datacenter_sdn_port_mapping_list(args): mano_response = requests.get(URLrequest) logger.debug("openmano response: %s", mano_response.text) - if mano_response.status_code != 200: - return mano_response.content + return _print_verbose(mano_response, 4) - return yaml.safe_dump(mano_response.json()) def datacenter_sdn_port_mapping_clear(args): tenant = _get_tenant() @@ -1096,26 +1109,27 @@ def datacenter_sdn_port_mapping_clear(args): if not args.force: r = raw_input("Clean SDN port mapping for datacenter %s (y/N)? " %(datacenter)) - if not (len(r)>0 and r[0].lower()=="y"): + if not (len(r) > 0 and r[0].lower() == "y"): return 0 URLrequest = "http://%s:%s/openmano/%s/datacenters/%s/sdn_mapping" % (mano_host, mano_port, tenant, datacenter) mano_response = requests.delete(URLrequest) logger.debug("openmano response: %s", mano_response.text) - if mano_response.status_code != 200: - if "No port mapping for datacenter" in mano_response.content: - return "No port mapping for datacenter " + datacenter + " has been found" - return mano_response.content + return _print_verbose(mano_response, args.verbose) - return yaml.safe_dump(mano_response.json()) def sdn_controller_create(args): tenant = _get_tenant() headers_req = {'Accept': 'application/json', 'content-type': 'application/json'} - if not (args.ip and args.port and args.dpid and args.type): - raise OpenmanoCLIError("The following arguments are required: ip, port, dpid, type") + error_msg=[] + if not args.ip: error_msg.append("'ip'") + if not args.port: error_msg.append("'port'") + if not args.dpid: error_msg.append("'dpid'") + if not args.type: error_msg.append("'type'") + if error_msg: + raise OpenmanoCLIError("The following arguments are required: " + ",".join(error_msg)) controller_dict = {} controller_dict['name'] = args.name @@ -1139,42 +1153,41 @@ def sdn_controller_create(args): mano_response = requests.post(URLrequest, headers=headers_req, data=payload_req) logger.debug("openmano response: %s", mano_response.text) result = _print_verbose(mano_response, args.verbose) - return result + def sdn_controller_edit(args): tenant = _get_tenant() controller_uuid = _get_item_uuid("sdn_controllers", args.name, tenant) headers_req = {'Accept': 'application/json', 'content-type': 'application/json'} - if not (args.new_name or args.ip or args.port or args.dpid or args.type): - raise OpenmanoCLIError("At least one parameter must be editd") - - if not args.force: - r = raw_input("Update SDN controller %s (y/N)? " %(args.name)) - if not (len(r)>0 and r[0].lower()=="y"): - return 0 - controller_dict = {} - if args.new_name != None: + if args.new_name: controller_dict['name'] = args.new_name - if args.ip != None: + if args.ip: controller_dict['ip'] = args.ip - if args.port != None: + if args.port: controller_dict['port'] = int(args.port) - if args.dpid != None: + if args.dpid: controller_dict['dpid'] = args.dpid - if args.type != None: + if args.type: controller_dict['type'] = args.type - if args.description != None: + if args.description: controller_dict['description'] = args.description - if args.user != None: + if args.user: controller_dict['user'] = args.user - if args.password != None: + if args.password: controller_dict['password'] = args.password - payload_req = json.dumps({"sdn_controller": controller_dict}) + if not controller_dict: + raise OpenmanoCLIError("At least one parameter must be edited") + if not args.force: + r = raw_input("Update SDN controller {} (y/N)? ".format(args.name)) + if not (len(r) > 0 and r[0].lower() == "y"): + return 0 + + payload_req = json.dumps({"sdn_controller": controller_dict}) # print payload_req URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid) @@ -1182,9 +1195,9 @@ def sdn_controller_edit(args): mano_response = requests.put(URLrequest, headers=headers_req, data=payload_req) logger.debug("openmano response: %s", mano_response.text) result = _print_verbose(mano_response, args.verbose) - return result + def sdn_controller_list(args): tenant = _get_tenant() headers_req = {'Accept': 'application/json', 'content-type': 'application/json'} @@ -1202,8 +1215,9 @@ def sdn_controller_list(args): if args.name!=None: args.verbose += 1 - result = json.dumps(mano_response.json(), indent=4) - return result + # json.dumps(mano_response.json(), indent=4) + return _print_verbose(mano_response, args.verbose) + def sdn_controller_delete(args): tenant = _get_tenant() @@ -1217,9 +1231,7 @@ def sdn_controller_delete(args): URLrequest = "http://%s:%s/openmano/%s/sdn_controllers/%s" % (mano_host, mano_port, tenant, controller_uuid) mano_response = requests.delete(URLrequest) logger.debug("openmano response: %s", mano_response.text) - result = _print_verbose(mano_response, args.verbose) - - return result + return _print_verbose(mano_response, args.verbose) def vim_action(args): #print "datacenter-net-action",args @@ -1271,7 +1283,7 @@ def vim_action(args): return payload_req = yaml.safe_dump(create_dict, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True) logger.debug("openmano request: %s", payload_req) - URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, mano_tenant, datacenter, args.item) + URLrequest = "http://%s:%s/openmano/%s/vim/%s/%ss" %(mano_host, mano_port, tenant, datacenter, args.item) mano_response = requests.post(URLrequest, headers = headers_req, data=payload_req) logger.debug("openmano response: %s", mano_response.text ) if args.verbose==None: @@ -1279,6 +1291,83 @@ def vim_action(args): return _print_verbose(mano_response, args.verbose) +def _get_items(item, item_name_id=None, datacenter=None, tenant=None): + URLrequest = "http://%s:%s/openmano" %(mano_host, mano_port) + if tenant: + URLrequest += "/" + tenant + if datacenter: + URLrequest += "/vim/" + datacenter + if item: + URLrequest += "/" + item +"s" + if item_name_id: + URLrequest += "/" + item_name_id + mano_response = requests.get(URLrequest) + logger.debug("openmano response: %s", mano_response.text ) + + return mano_response + + +def vim_net_sdn_attach(args): + #Verify the network exists in the vim + tenant = _get_tenant() + datacenter = _get_datacenter(args.datacenter, tenant) + result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant) + content = yaml.load(result.content) + if 'networks' in content: + raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead') + if 'error' in content: + raise OpenmanoCLIError(yaml.safe_dump(content)) + network_uuid = content['network']['id'] + + #Make call to attach the dataplane port to the SND network associated to the vim network + headers_req = {'content-type': 'application/yaml'} + payload_req = {'port': args.port} + if args.vlan: + payload_req['vlan'] = int(args.vlan) + if args.mac: + payload_req['mac'] = args.mac + + URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/attach" % (mano_host, mano_port, tenant, datacenter, network_uuid) + logger.debug("openmano request: %s", payload_req) + mano_response = requests.post(URLrequest, headers=headers_req, data=json.dumps(payload_req)) + logger.debug("openmano response: %s", mano_response.text) + result = _print_verbose(mano_response, args.verbose) + return result + + +def vim_net_sdn_detach(args): + if not args.all and not args.id: + print "--all or --id must be used" + return 1 + + # Verify the network exists in the vim + tenant = _get_tenant() + datacenter = _get_datacenter(args.datacenter, tenant) + result = _get_items('network', item_name_id=args.vim_net, datacenter=datacenter, tenant=tenant) + content = yaml.load(result.content) + if 'networks' in content: + raise OpenmanoCLIError('More than one network in the vim named ' + args.vim_net + '. Use uuid instead') + if 'error' in content: + raise OpenmanoCLIError(yaml.safe_dump(content)) + network_uuid = content['network']['id'] + + if not args.force: + r = raw_input("Confirm action' (y/N)? ") + if len(r) == 0 or r[0].lower() != "y": + return 0 + + if args.id: + URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach/%s" % ( + mano_host, mano_port, tenant, datacenter, network_uuid, args.id) + else: + URLrequest = "http://%s:%s/openmano/%s/vim/%s/network/%s/detach" % ( + mano_host, mano_port, tenant, datacenter, network_uuid) + mano_response = requests.delete(URLrequest) + logger.debug("openmano response: %s", mano_response.text) + result = _print_verbose(mano_response, args.verbose) + return result + + def datacenter_net_action(args): if args.action == "net-update": print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!" @@ -1389,6 +1478,7 @@ def datacenter_netmap_action(args): logger.debug("openmano response: %s", mano_response.text ) return _print_verbose(mano_response, args.verbose) + def element_edit(args): element = _get_item_uuid(args.element, args.name) headers_req = {'Accept': 'application/json', 'content-type': 'application/json'} @@ -1462,6 +1552,7 @@ def datacenter_edit(args): args.verbose += 1 return _print_verbose(mano_response, args.verbose) + def version(args): headers_req = {'Accept': 'application/json', 'content-type': 'application/json'} URLrequest = "http://%s:%s/openmano/version" % (mano_host, mano_port) @@ -1797,24 +1888,50 @@ if __name__=="__main__": if item=='netmap-import': datacenter_action_parser.add_argument("-f","--force", action="store_true", help="do not prompt for confirmation") datacenter_action_parser.set_defaults(func=datacenter_netmap_action, action=item) - + + # =======================vim_net_sdn_xxx section======================= + # vim_net_sdn_attach + vim_net_sdn_attach_parser = subparsers.add_parser('vim-net-sdn-attach', + parents=[parent_parser], + help="Specify the port to access to an external network using SDN") + vim_net_sdn_attach_parser.add_argument("vim_net", action="store", + help="Name/id of the network in the vim that will be used to connect to the external network") + vim_net_sdn_attach_parser.add_argument("port", action="store", help="Specifies the port in the dataplane switch to access to the external network") + vim_net_sdn_attach_parser.add_argument("--vlan", action="store", help="Specifies the vlan (if any) to use in the defined port") + vim_net_sdn_attach_parser.add_argument("--mac", action="store", help="Specifies the MAC (if known) of the physical device that will be reachable by this external port") + vim_net_sdn_attach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter") + vim_net_sdn_attach_parser.set_defaults(func=vim_net_sdn_attach) + + # vim_net_sdn_detach + vim_net_sdn_detach_parser = subparsers.add_parser('vim-net-sdn-detach', + parents=[parent_parser], + help="Remove the port information to access to an external network using SDN") + + vim_net_sdn_detach_parser.add_argument("vim_net", action="store", help="Name/id of the vim network") + vim_net_sdn_detach_parser.add_argument("--id", action="store",help="Specify the uuid of the external ports from this network to be detached") + vim_net_sdn_detach_parser.add_argument("--all", action="store_true", help="Detach all external ports from this network") + vim_net_sdn_detach_parser.add_argument("-f", "--force", action="store_true", help="forces clearing without asking") + vim_net_sdn_detach_parser.add_argument("--datacenter", action="store", help="specifies the datacenter") + vim_net_sdn_detach_parser.set_defaults(func=vim_net_sdn_detach) + # ======================= + for item in ("network", "tenant", "image"): if item=="network": - commnad_name = 'vim-net' + command_name = 'vim-net' else: - commnad_name = 'vim-'+item - vim_item_list_parser = subparsers.add_parser(commnad_name + '-list', parents=[parent_parser], help="list the vim " + item + "s") + command_name = 'vim-'+item + vim_item_list_parser = subparsers.add_parser(command_name + '-list', parents=[parent_parser], help="list the vim " + item + "s") vim_item_list_parser.add_argument("name", nargs='?', help="name or uuid of the " + item + "s") vim_item_list_parser.add_argument("--datacenter", action="store", help="specifies the datacenter") vim_item_list_parser.set_defaults(func=vim_action, item=item, action="list") - vim_item_del_parser = subparsers.add_parser(commnad_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s") + vim_item_del_parser = subparsers.add_parser(command_name + '-delete', parents=[parent_parser], help="list the vim " + item + "s") vim_item_del_parser.add_argument("name", help="name or uuid of the " + item + "s") vim_item_del_parser.add_argument("--datacenter", action="store", help="specifies the datacenter") vim_item_del_parser.set_defaults(func=vim_action, item=item, action="delete") if item == "network" or item == "tenant": - vim_item_create_parser = subparsers.add_parser(commnad_name + '-create', parents=[parent_parser], help="create a "+item+" at vim") + vim_item_create_parser = subparsers.add_parser(command_name + '-create', parents=[parent_parser], help="create a "+item+" at vim") vim_item_create_parser.add_argument("file", nargs='?', help="descriptor of the %s. Must be a file or yaml/json text" % item).completer = FilesCompleter vim_item_create_parser.add_argument("--name", action="store", help="name of the %s" % item ) vim_item_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter")