X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=openmano;h=c34d831f3e24c7ed7cbdc067d5de0493934b1eef;hb=06e6c396413630640cafae3488442a0869f1642d;hp=b207d2913ea6c0ff65e5fd2f0d80b24d2baf7431;hpb=392f28583d8750e7e2c2c5f2341688ec5acdf824;p=osm%2FRO.git diff --git a/openmano b/openmano index b207d291..c34d831f 100755 --- a/openmano +++ b/openmano @@ -28,8 +28,8 @@ openmano client used to interact with openmano-server (openmanod) ''' __author__="Alfonso Tierno, Gerardo Garcia" __date__ ="$09-oct-2014 09:09:48$" -__version__="0.4.3-r467" -version_date="Mar 2016" +__version__="0.4.11-r517" +version_date="Jan 2017" from argcomplete.completers import FilesCompleter import os @@ -59,8 +59,37 @@ class ThrowingArgumentParser(argparse.ArgumentParser): def config(args): print "OPENMANO_HOST: %s" %mano_host print "OPENMANO_PORT: %s" %mano_port - print "OPENMANO_TENANT: %s" %mano_tenant - print "OPENMANO_DATACENTER: %s" %str (mano_datacenter) + if args.n: + logger.debug("resolving tenant and datacenter names") + mano_tenant_id = "None" + mano_tenant_name = "None" + mano_datacenter_id = "None" + mano_datacenter_name = "None" + try: + mano_tenant_id = _get_item_uuid("tenants", mano_tenant) + URLrequest = "http://%s:%s/openmano/tenants/%s" %(mano_host, mano_port, mano_tenant_id) + mano_response = requests.get(URLrequest) + logger.debug("openmano response: %s", mano_response.text ) + content = mano_response.json() + mano_tenant_name = content["tenant"]["name"] + URLrequest = "http://%s:%s/openmano/%s/datacenters/%s" %(mano_host, mano_port, mano_tenant_id, mano_datacenter) + mano_response = requests.get(URLrequest) + logger.debug("openmano response: %s", mano_response.text ) + content = mano_response.json() + if "error" not in content: + mano_datacenter_id = content["datacenter"]["uuid"] + mano_datacenter_name = content["datacenter"]["name"] + except OpenmanoCLIError: + pass + print "OPENMANO_TENANT: %s" %mano_tenant + print " Id: %s" %mano_tenant_id + print " Name: %s" %mano_tenant_name + print "OPENMANO_DATACENTER: %s" %str (mano_datacenter) + print " Id: %s" %mano_datacenter_id + print " Name: %s" %mano_datacenter_name + else: + print "OPENMANO_TENANT: %s" %mano_tenant + print "OPENMANO_DATACENTER: %s" %str (mano_datacenter) def _print_verbose(mano_response, verbose_level=0): content = mano_response.json() @@ -98,20 +127,25 @@ def _print_verbose(mano_response, verbose_level=0): uuid = content['id'] elif "vim_id" in content: uuid = content['vim_id'] - myoutput = "%s %s" %(uuid.ljust(38),content['name'].ljust(20)) - if "status" in content: + name = content.get('name'); + if not uuid: + uuid = "" + if not name: + name = "" + myoutput = "%s %s" %(uuid.ljust(38),name.ljust(20)) + if content.get("status"): myoutput += " " + content['status'].ljust(20) elif "enabled" in content and not content["enabled"]: myoutput += " enabled=False".ljust(20) if verbose_level >=1: - if 'created_at' in content: + if content.get('created_at'): myoutput += " " + content['created_at'].ljust(20) if verbose_level >=2: new_line='\n' - if 'type' in content and content['type']!=None: + if content.get('type'): myoutput += new_line + " Type: " + content['type'].ljust(29) new_line='' - if 'description' in content and content['description']!=None: + if content.get('description'): myoutput += new_line + " Description: " + content['description'].ljust(20) print myoutput else: @@ -222,7 +256,7 @@ def vnf_create(args): tenant = _get_tenant() myvnf = _load_file_or_yaml(args.file) - if args.name or args.description or args.image_path: + if args.name or args.description or args.image_path or args.image_name or args.image_checksum: #print args.name try: if args.name: @@ -234,6 +268,22 @@ def vnf_create(args): for image_path_ in args.image_path.split(","): #print "image-path", image_path_ myvnf['vnf']['VNFC'][index]['VNFC image']=image_path_ + if "image name" in myvnf['vnf']['VNFC'][index]: + del myvnf['vnf']['VNFC'][index]["image name"] + if "image checksum" in myvnf['vnf']['VNFC'][index]: + del myvnf['vnf']['VNFC'][index]["image checksum"] + index=index+1 + if args.image_name: #image name precedes if both are supplied + index=0 + for image_name_ in args.image_name.split(","): + myvnf['vnf']['VNFC'][index]['image name']=image_name_ + if "VNFC image" in myvnf['vnf']['VNFC'][index]: + del myvnf['vnf']['VNFC'][index]["VNFC image"] + index=index+1 + if args.image_checksum: + index=0 + for image_checksum_ in args.image_checksum.split(","): + myvnf['vnf']['VNFC'][index]['image checksum']=image_checksum_ index=index+1 except (KeyError, TypeError), e: if str(e)=='vnf': error_pos= "missing field 'vnf'" @@ -242,6 +292,8 @@ def vnf_create(args): elif str(e)=='VNFC': error_pos= "missing field 'vnf':'VNFC'" elif str(e)==str(index): error_pos= "field 'vnf':'VNFC' must be an array" elif str(e)=='VNFC image': error_pos= "missing field 'vnf':'VNFC'['VNFC image']" + elif str(e)=='image name': error_pos= "missing field 'vnf':'VNFC'['image name']" + elif str(e)=='image checksum': error_pos= "missing field 'vnf':'VNFC'['image checksum']" else: error_pos="wrong format" print "Wrong VNF descriptor: " + error_pos return -1 @@ -310,7 +362,7 @@ def vnf_list(args): print " External interfaces:" for interface in vnf['external-connections']: print " %s %s %s %s" %(interface['external_name'].ljust(20), interface['vm_name'].ljust(20), interface['internal_name'].ljust(20), \ - interface['vpci'].ljust(14)) + interface.get('vpci',"").ljust(14)) else: print content['error']['description'] if args.verbose: @@ -451,6 +503,8 @@ def scenario_deploy(args): args.file = None args.netmap_use = None args.netmap_create = None + args.keypair = None + args.keypair_auto = None return instance_create(args) # #print "scenario-deploy",args @@ -548,7 +602,7 @@ def instance_create(args): if args.scenario != None: scenario = args.scenario if not scenario: - print "you must provide an scenario in the file descriptor or with --scenario" + print "you must provide a scenario in the file descriptor or with --scenario" return -1 myInstance["instance"]["scenario"] = _get_item_uuid("scenarios", scenario, tenant) if args.netmap_use: @@ -565,7 +619,9 @@ def instance_create(args): net_datacenter = net_tuple[1].strip() if net_scenario not in myInstance["instance"]["networks"]: myInstance["instance"]["networks"][net_scenario] = {} - myInstance["instance"]["networks"][net_scenario]["netmap-use"] = net_datacenter + if "sites" not in myInstance["instance"]["networks"][net_scenario]: + myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ] + myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-use"] = net_datacenter if args.netmap_create: if "networks" not in myInstance["instance"]: myInstance["instance"]["networks"] = {} @@ -584,7 +640,52 @@ def instance_create(args): return if net_scenario not in myInstance["instance"]["networks"]: myInstance["instance"]["networks"][net_scenario] = {} - myInstance["instance"]["networks"][net_scenario]["netmap-create"] = net_datacenter + if "sites" not in myInstance["instance"]["networks"][net_scenario]: + myInstance["instance"]["networks"][net_scenario]["sites"] = [ {} ] + myInstance["instance"]["networks"][net_scenario]["sites"][0]["netmap-create"] = net_datacenter + if args.keypair: + if "cloud-config" not in myInstance["instance"]: + myInstance["instance"]["cloud-config"] = {} + cloud_config = myInstance["instance"]["cloud-config"] + for key in args.keypair: + index = key.find(":") + if index<0: + if "key-pairs" not in cloud_config: + cloud_config["key-pairs"] = [] + cloud_config["key-pairs"].append(key) + else: + user = key[:index] + key_ = key[index+1:] + key_list = key_.split(",") + if "users" not in cloud_config: + cloud_config["users"] = [] + cloud_config["users"].append({"name": user, "key-pairs": key_list }) + if args.keypair_auto: + try: + keys=[] + home = os.getenv("HOME") + user = os.getenv("USER") + files = os.listdir(home+'/.ssh') + for file in files: + if file[-4:] == ".pub": + with open(home+'/.ssh/'+file, 'r') as f: + keys.append(f.read()) + if not keys: + print "Cannot obtain any public ssh key from '{}'. Try not using --keymap-auto".format(home+'/.ssh') + return 1 + except Exception as e: + print "Cannot obtain any public ssh key. Error '{}'. Try not using --keymap-auto".format(str(e)) + return 1 + + if "cloud-config" not in myInstance["instance"]: + myInstance["instance"]["cloud-config"] = {} + cloud_config = myInstance["instance"]["cloud-config"] + if "key-pairs" not in cloud_config: + cloud_config["key-pairs"] = [] + if user: + if "users" not in cloud_config: + cloud_config["users"] = [] + cloud_config["users"].append({"name": user, "key-pairs": keys }) payload_req = yaml.safe_dump(myInstance, explicit_start=True, indent=4, default_flow_style=False, tags=False, encoding='utf-8', allow_unicode=True) logger.debug("openmano request: %s", payload_req) @@ -664,12 +765,12 @@ def instance_scenario_list(args): print "---------------------------------------" print "Internal nets:" for net in instance['nets']: - if not net['external']: + if net['created']: print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id']) print "---------------------------------------" print "External nets:" for net in instance['nets']: - if net['external']: + if not net['created']: print " %s %s VIM ID: %s" %(net['uuid'].ljust(38), net['status'].ljust(12), net['vim_net_id']) print "---------------------------------------" print "VM instances:" @@ -811,6 +912,8 @@ def datacenter_attach(args): datacenter_dict['vim_username'] = args.user if args.password != None: datacenter_dict['vim_password'] = args.password + if args.config!=None: + datacenter_dict["config"] = _load_file_or_yaml(args.config) payload_req = json.dumps( {"datacenter": datacenter_dict }) #print payload_req @@ -964,7 +1067,7 @@ def vim_action(args): 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-upload' instead!!!" + print "This command is deprecated, use 'openmano datacenter-netmap-delete --all' and 'openmano datacenter-netmap-import' instead!!!" print args.action = "netmap-delete" args.netmap = None @@ -972,7 +1075,7 @@ def datacenter_net_action(args): r = datacenter_netmap_action(args) if r == 0: args.force = True - args.action = "netmap-upload" + args.action = "netmap-import" r = datacenter_netmap_action(args) return r @@ -1018,7 +1121,7 @@ def datacenter_netmap_action(args): elif args.all: force_text="Delete all default netmaps from datacenter '%s' (y/N)? " % (datacenter) else: - print "you must a netmap name or the option --all" + print "you must specify a netmap name or the option --all" return 1 if not args.force: r = raw_input(force_text) @@ -1027,7 +1130,7 @@ def datacenter_netmap_action(args): else: return 0 mano_response = requests.delete(URLrequest, headers=headers_req) - elif args.action=="netmap-upload": + elif args.action=="netmap-import": if not args.force: r = raw_input("Create all the available networks from datacenter '%s' as default netmaps (y/N)? " % (datacenter)) if len(r)>0 and r[0].lower()=="y": @@ -1114,18 +1217,21 @@ if __name__=="__main__": subparsers = main_parser.add_subparsers(help='commands') - config_parser = subparsers.add_parser('config', help="prints configuration values") - config_parser.set_defaults(func=config) - parent_parser = argparse.ArgumentParser(add_help=False) parent_parser.add_argument('--verbose', '-v', action='count', help="increase verbosity level. Use several times") parent_parser.add_argument('--debug', '-d', action='store_true', help="show debug information") + config_parser = subparsers.add_parser('config', parents=[parent_parser], help="prints configuration values") + config_parser.add_argument("-n", action="store_true", help="resolves tenant and datacenter names") + config_parser.set_defaults(func=config) + vnf_create_parser = subparsers.add_parser('vnf-create', parents=[parent_parser], help="adds a vnf into the catalogue") vnf_create_parser.add_argument("file", action="store", help="location of the JSON file describing the VNF").completer = FilesCompleter vnf_create_parser.add_argument("--name", action="store", help="name of the VNF (if it exists in the VNF descriptor, it is overwritten)") vnf_create_parser.add_argument("--description", action="store", help="description of the VNF (if it exists in the VNF descriptor, it is overwritten)") vnf_create_parser.add_argument("--image-path", action="store", help="change image path locations (overwritten)") + vnf_create_parser.add_argument("--image-name", action="store", help="change image name (overwritten)") + vnf_create_parser.add_argument("--image-checksum", action="store", help="change image checksum (overwritten)") vnf_create_parser.set_defaults(func=vnf_create) vnf_list_parser = subparsers.add_parser('vnf-list', parents=[parent_parser], help="lists information about a vnf") @@ -1179,6 +1285,8 @@ if __name__=="__main__": instance_scenario_create_parser.add_argument("--datacenter", action="store", help="specifies the datacenter. Needed if several datacenters are available") instance_scenario_create_parser.add_argument("--netmap-use", action="append", type=str, dest="netmap_use", help="indicates a datacenter network to map a scenario network 'scenario-network=datacenter-network'. Can be used several times") instance_scenario_create_parser.add_argument("--netmap-create", action="append", type=str, dest="netmap_create", help="the scenario network must be created at datacenter 'scenario-network[=datacenter-network-name]' . Can be used several times") + instance_scenario_create_parser.add_argument("--keypair", action="append", type=str, dest="keypair", help="public key for ssh access. Format '[user:]key1[,key2...]'. Can be used several times") + instance_scenario_create_parser.add_argument("--keypair-auto", action="store_true", dest="keypair_auto", help="Inject the user ssh-keys found at $HOME/.ssh directory") instance_scenario_create_parser.add_argument("--description", action="store", help="description of the instance") instance_scenario_create_parser.set_defaults(func=instance_create) @@ -1254,6 +1362,7 @@ if __name__=="__main__": datacenter_attach_parser.add_argument('--vim-tenant-name', action='store', help="specify a datacenter tenant name.") datacenter_attach_parser.add_argument("--user", action="store", help="user credentials for the datacenter") datacenter_attach_parser.add_argument("--password", action="store", help="password credentials for the datacenter") + datacenter_attach_parser.add_argument("--config", action="store", help="aditional configuration in json/yaml format") datacenter_attach_parser.set_defaults(func=datacenter_attach) datacenter_detach_parser = subparsers.add_parser('datacenter-detach', parents=[parent_parser], help="removes the association between a datacenter and the operating tenant") @@ -1279,7 +1388,7 @@ if __name__=="__main__": datacenter_action_parser.set_defaults(func=datacenter_net_action, action=item) - action_dict={'netmap-upload': 'create network senario netmap base on the datacenter networks', + action_dict={'netmap-import': 'create network senario netmap base on the datacenter networks', 'netmap-create': 'create a new network senario netmap', 'netmap-edit': 'edit name of a network senario netmap', 'netmap-delete': 'deletes a network scenario netmap (--all for clearing all)', @@ -1307,11 +1416,11 @@ if __name__=="__main__": datacenter_action_parser.add_argument("--name", action='store', help="name to assign to the datacenter netmap, by default same as vim-name") datacenter_action_parser.add_argument('--vim-id', action='store', help="specify vim network uuid") datacenter_action_parser.add_argument('--vim-name', action='store', help="specify vim network name") - if item=='netmap-upload': + 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) - for item in ("network", "tenant"): + for item in ("network", "tenant", "image"): if item=="network": commnad_name = 'vim-net' else: @@ -1326,17 +1435,18 @@ if __name__=="__main__": 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") - vim_item_create_parser = subparsers.add_parser(commnad_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") - if item=="network": - vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge") - vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared") - vim_item_create_parser.add_argument("--bind-net", action="store", help="For openvim datacenter type, net to be bind to, for vlan type, use sufix ':'") - else: - vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item) - vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create") + 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.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") + if item=="network": + vim_item_create_parser.add_argument("--type", action="store", help="type of network, data, ptp, bridge") + vim_item_create_parser.add_argument("--shared", action="store_true", help="Private or shared") + vim_item_create_parser.add_argument("--bind-net", action="store", help="For openvim datacenter type, net to be bind to, for vlan type, use sufix ':'") + else: + vim_item_create_parser.add_argument("--description", action="store", help="description of the %s" % item) + vim_item_create_parser.set_defaults(func=vim_action, item=item, action="create") argcomplete.autocomplete(main_parser)