X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=openmano;h=ec588a98546b3997d22e64c0679959bddcc75252;hb=5461675ac6705ee92916ed741da1914bd2162482;hp=111df432858a1e616859172bd561e74ec59e43a9;hpb=72a08d7e3b63e0c671e5c6bea57c1ffdcfb2f1fe;p=osm%2FRO.git diff --git a/openmano b/openmano index 111df432..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.14-r521" -version_date = "May 2017" +__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'): @@ -1030,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() @@ -1047,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) @@ -1055,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() @@ -1086,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() @@ -1097,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 @@ -1140,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) @@ -1183,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'} @@ -1203,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() @@ -1218,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 @@ -1280,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!!!" @@ -1390,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'} @@ -1463,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) @@ -1798,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")