def __init__(self, cloudname, user=None, flat=True): super(CloudProvider, self).__init__(cloudname, user=user) try: d = ConfigDict("cloudmesh.yaml") if not cloudname in d["cloudmesh"]["clouds"]: raise ValueError("the cloud {} is not defined in the yaml file. failed." .format(cloudname)) cloud_details = d["cloudmesh"]["clouds"][cloudname] if cloud_details["cm_type"] == "openstack": provider = CloudProviderOpenstackAPI( cloudname, cloud_details, flat=flat) self.provider = provider self.provider_class = CloudProviderOpenstackAPI if cloud_details["cm_type"] == "ec2": provider = CloudProviderLibcloudEC2( cloudname, cloud_details, flat=flat) self.provider = provider self.provider_class = CloudProviderLibcloudEC2 if cloud_details["cm_type"] == "azure": raise ValueError("azure cloud provider yet implemented. failed.") TODO.implement() except Exception as e: Error.traceback(e)
def construct_ip_dict(cls, ip_addr, name="kilo"): try: d = ConfigDict("cloudmesh.yaml") cloud_details = d["cloudmesh"]["clouds"][name] # Handle Openstack Specific Output if cloud_details["cm_type"] == "openstack": ipaddr = {} for network in ip_addr: index = 0 for ip in ip_addr[network]: ipaddr[index] = {} ipaddr[index]["network"] = network ipaddr[index]["version"] = ip["version"] ipaddr[index]["addr"] = ip["addr"] index += 1 return ipaddr # Handle EC2 Specific Output if cloud_details["cm_type"] == "ec2": print("ec2 ip dict yet to be implemented") TODO.implement() # Handle Azure Specific Output if cloud_details["cm_type"] == "azure": print("azure ip dict yet to be implemented") TODO.implement() except Exception as e: Error.error("error in vm construct dict", traceback=True)
def __init__(self, cloudname, user=None, flat=True): super(CloudProvider, self).__init__(cloudname, user=user) try: d = ConfigDict("cloudmesh.yaml") if not cloudname in d["cloudmesh"]["clouds"]: raise ValueError("the cloud {} is not defined in the yaml file" .format(cloudname)) cloud_details = d["cloudmesh"]["clouds"][cloudname] if cloud_details["cm_type"] == "openstack": provider = CloudProviderOpenstackAPI( cloudname, cloud_details, flat=flat) self.provider = provider self.provider_class = CloudProviderOpenstackAPI if cloud_details["cm_type"] == "ec2": print("ec2 cloud provider yet to be implemented") TODO.implement() if cloud_details["cm_type"] == "azure": print("azure cloud provider yet to be implemented") TODO.implement() except Exception, e: Error.traceback(e)
def __init__(self, cloudname, user=None, flat=True): super(CloudProvider, self).__init__(cloudname, user=user) try: d = ConfigDict("cloudmesh.yaml") if cloudname not in d["cloudmesh"]["clouds"]: Console.error("the cloud {} is not defined in the yaml file. failed." .format(cloudname), traceflag=False) return cloud_details = d["cloudmesh"]["clouds"][cloudname] if cloud_details["cm_type"] == "openstack": provider = CloudProviderOpenstackAPI( cloudname, cloud_details, flat=flat) self.provider = provider self.provider_class = CloudProviderOpenstackAPI if cloud_details["cm_type"] == "ec2": provider = CloudProviderLibcloudEC2( cloudname, cloud_details, flat=flat) self.provider = provider self.provider_class = CloudProviderLibcloudEC2 if cloud_details["cm_type"] == "azure": raise ValueError("azure cloud provider yet implemented. failed.") Console.TODO("Azure provider to be implemented") except Exception as e: Error.traceback(e)
def construct_ip_dict(cls, ip_addr, name="kilo"): try: d = ConfigDict("cloudmesh.yaml") cloud_details = d["cloudmesh"]["clouds"][name] # Handle Openstack Specific Output if cloud_details["cm_type"] == "openstack": ipaddr = {} for network in ip_addr: index = 0 for ip in ip_addr[network]: ipaddr[index] = {} ipaddr[index]["network"] = network ipaddr[index]["version"] = ip["version"] ipaddr[index]["addr"] = ip["addr"] index += 1 return ipaddr # Handle EC2 Specific Output if cloud_details["cm_type"] == "ec2": print("ec2 ip dict yet to be implemented") TODO.implement() # Handle Azure Specific Output if cloud_details["cm_type"] == "azure": print("azure ip dict yet to be implemented") TODO.implement() except Exception, e: Error.traceback(e)
def _refresh(): try: msg = "Refresh VMs for cloud {:}.".format(cloud) if Vm.refresh(cloud=cloud): Console.ok("{:} OK.".format(msg)) else: Console.error("{:} failed".format(msg)) except Exception as e: Error.traceback(e) Console.error("Problem running VM refresh")
def read_yaml_config(filename, check=True, osreplace=True, exit=True): """ reads in a yaml file from the specified filename. If check is set to true the code will fail if the file does not exist. However if it is set to false and the file does not exist, None is returned. :param filename: the file name :param check: if True fails if the file does not exist, if False and the file does not exist return will be None """ location = filename if location is not None: location = path_expand(location) if not os.path.exists(location) and not check: return None if check and os.path.exists(location): # test for tab in yaml file if check_file_for_tabs(location): log.error("The file {0} contains tabs. yaml " "Files are not allowed to contain tabs".format(location)) sys.exit() result = None try: if osreplace: result = open(location, 'r').read() t = Template(result) result = t.substitute(os.environ) # data = yaml.safe_load(result) data = ordered_load(result, yaml.SafeLoader) else: f = open(location, "r") # data = yaml.safe_load(f) data = ordered_load(result, yaml.SafeLoader) f.close() return data except Exception as e: log.error( "The file {0} fails with a yaml read error".format(filename)) Error.traceback(e) sys.exit() else: log.error("The file {0} does not exist.".format(filename)) if exit: sys.exit() return None
def BatchProvider(name, user=None): """ Returns a provider for a given batch system that is defined in the cloudmesh.yaml file. Here you find a section such as:: hpc: active: - india clusters: india: cm_heading: India HPC CLuster cm_host: india cm_label: indiahpc cm_type: slurm cm_type_version: 14.11.9 credentials: username: TBD project: None default: queue: delta experiment_dir: /N/u/{username}/experiment prefix: username: null You can define a new resource by copying this section under india and give it a name according to your cluster. Fill out the username, and if appropirate define a project, which is the account this queue is charged under Ussage:: provider = BatchProvider("india") Additional functions are defined as it inherits from BatchProviderBase and the provider type which is in the above example slurm :param name: name of the cluster in the cloudmesh yaml file :param user: cloudmesh user name associated with this queue. :return: the provider """ try: d = ConfigDict("cloudmesh.yaml") details = d["cloudmesh"]["hpc"]["clusters"][name] if details["cm_type"].lower() in ["slurm"]: return BatchProviderSLURM() else: ValueError("batch provider not supported.") except Exception as e: Error.traceback(e)
def queue(cls, cluster, format='json', job=None): try: args = 'squeue ' if job is not None: if job.isdigit(): args += ' -j {} '.format(str(job)) # search by job id else: args += ' -n {} '.format(job) # search by job name f = '--format=%all' args += f result = Shell.ssh(cluster, args) # TODO: process till header is found...(Need a better way) l = result.splitlines() for i, res in enumerate(l): if 'ACCOUNT|GRES|' in res: result = "\n".join(str(x) for x in l[i:]) break parser = TableParser(strip=True) d = parser.to_dict(result) # add cluster and updated to each entry for key in list(d.keys()): d[key]['cluster'] = cluster d[key]['updated'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S") if format == 'json': return json.dumps(d, indent=4, separators=(',', ': ')) else: return (Printer.write(d, order=['cluster', 'jobid', 'partition', 'name', 'user', 'st', 'time', 'nodes', 'nodelist', 'updated'], output=format)) except Exception as e: Error.traceback(e) return e
def construct_ip_dict(cls, ip_addr, name=None): # TODO kilo cloud as defualt should be avoided if name is None: Console.error("cloud name not set") return None try: d = ConfigDict("cloudmesh.yaml") cloud_details = d["cloudmesh"]["clouds"][name] # Handle Openstack Specific Output if cloud_details["cm_type"] == "openstack": ipaddr = {} for network in ip_addr: index = 0 for ip in ip_addr[network]: ipaddr[index] = {} ipaddr[index]["network"] = network ipaddr[index]["version"] = ip["version"] ipaddr[index]["addr"] = ip["addr"] index += 1 return ipaddr # Handle EC2 Specific Output if cloud_details["cm_type"] == "ec2": Console.TODO("ec2 ip dict yet to be implemented") TODO.implement() # Handle Azure Specific Output if cloud_details["cm_type"] == "azure": index = 0 ipaddr = {} for ip in ip_addr: ipaddr[index] = {} ipaddr[index]["network"] = ip ipaddr[index]["version"] = 'ipv4' ipaddr[index]["addr"] = ip index += 1 return ipaddr except Exception as e: Error.error("error in vm construct dict", traceback=True)
def __init__(self, cloudname, user=None, flat=True): super(CloudProvider, self).__init__(cloudname, user=user) try: d = ConfigDict("cloudmesh.yaml") if cloudname not in d["cloudmesh"]["clouds"]: Console.error( "the cloud {} is not defined in the yaml file. failed.". format(cloudname), traceflag=False) return cloud_details = d["cloudmesh"]["clouds"][cloudname] if cloud_details["cm_type"] == "openstack": provider = CloudProviderOpenstackAPI(cloudname, cloud_details, flat=flat) self.provider = provider self.provider_class = CloudProviderOpenstackAPI if cloud_details["cm_type"] == "ec2": provider = CloudProviderLibcloudEC2(cloudname, cloud_details, flat=flat) self.provider = provider self.provider_class = CloudProviderLibcloudEC2 if cloud_details["cm_type"] == "azure": # raise ValueError("azure cloud provider yet implemented. failed.") # Console.TODO("Azure provider to be implemented") provider = CloudProviderAzureAPI(cloudname, cloud_details) self.provider = provider self.provider_class = CloudProviderAzureAPI except Exception as e: Error.traceback(e)
def do_key(self, args, arguments): """ :: Usage: key -h | --help key list [--source=db] [--format=FORMAT] key list --source=cloudmesh [--format=FORMAT] key list --source=ssh [--dir=DIR] [--format=FORMAT] key load [--format=FORMAT] key list --source=git [--format=FORMAT] [--username=USERNAME] key add --git [--name=KEYNAME] FILENAME key add --ssh [--name=KEYNAME] key add [--name=KEYNAME] FILENAME key get NAME key default [KEYNAME | --select] key delete (KEYNAME | --select | --all) [--force] key upload [KEYNAME] [--cloud=CLOUD] key map [--cloud=CLOUD] Manages the keys Arguments: SOURCE db, ssh, all KEYNAME The name of a key. For key upload it defaults to the default key name. FORMAT The format of the output (table, json, yaml) FILENAME The filename with full path in which the key is located NAME_ON_CLOUD Typically the name of the keypair on the cloud. Options: --dir=DIR the directory with keys [default: ~/.ssh] --format=FORMAT the format of the output [default: table] --source=SOURCE the source for the keys [default: db] --username=USERNAME the source for the keys [default: none] --name=KEYNAME The name of a key --all delete all keys --force delete the key form the cloud --name_on_cloud=NAME_ON_CLOUD Typically the name of the keypair on the cloud. Description: key list --source=git [--username=USERNAME] lists all keys in git for the specified user. If the name is not specified it is read from cloudmesh.yaml key list --source=ssh [--dir=DIR] [--format=FORMAT] lists all keys in the directory. If the directory is not specified the default will be ~/.ssh key list --source=cloudmesh [--dir=DIR] [--format=FORMAT] lists all keys in cloudmesh.yaml file in the specified directory. dir is by default ~/.cloudmesh key list [--format=FORMAT] list the keys in teh giiven format: json, yaml, table. table is default key list Prints list of keys. NAME of the key can be specified key add [--name=keyname] FILENAME adds the key specifid by the filename to the key database key get NAME Retrieves the key indicated by the NAME parameter from database and prints its fingerprint. key default [NAME] Used to set a key from the key-list as the default key if NAME is given. Otherwise print the current default key key delete NAME deletes a key. In yaml mode it can delete only key that are not saved in the database key rename NAME NEW renames the key from NAME to NEW. """ # pprint(arguments) def _print_dict(d, header=None, format='table'): if format == "json": return json.dumps(d, indent=4) elif format == "yaml": return yaml.dump(d, default_flow_style=False) elif format == "table": return dict_printer(d, order=["name", "comment", "uri", "fingerprint", "source"], output="table", sort_keys=True) else: return d # return dict_printer(d,order=['cm_id, name, fingerprint']) directory = Config.path_expand(arguments["--dir"]) if arguments['list']: _format = arguments['--format'] _source = arguments['--source'] _dir = arguments['--dir'] if arguments['--source'] == 'ssh': try: sshm = SSHKeyManager() sshm.get_from_dir(directory) d = dict(sshm.__keys__) print(_print_dict(d, format=_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem listing keys from ssh") elif arguments['--source'] in ['cm', 'cloudmesh']: try: sshm = SSHKeyManager() m = sshm.get_from_yaml(load_order=directory) d = dict(m.__keys__) print(_print_dict(d, format=_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem listing keys from `{:}`".format(arguments['--source'])) elif arguments['--source'] in ['git']: username = arguments["--username"] # print(username) if username == 'none': conf = ConfigDict("cloudmesh.yaml") username = conf["cloudmesh.github.username"] sshm = SSHKeyManager() try: sshm.get_from_git(username) d = dict(sshm.__keys__) print(_print_dict(d, format=_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem listing git keys from database") return "" elif arguments['--source'] == 'db': try: sshdb = SSHKeyDBManager() d = sshdb.table_dict() if d != {}: print(_print_dict(d, format=arguments['--format'])) msg = "info. OK." Console.ok(msg) else: Console.error("No keys in the database") except Exception as e: Error.traceback(e) Console.error("Problem listing keys from database") elif arguments['load']: _format = arguments['--format'] _dir = arguments['--dir'] try: sshm = SSHKeyManager() m = sshm.get_from_yaml(load_order=directory) d = dict(m.__keys__) sshdb = SSHKeyDBManager() for keyname in m.__keys__: filename = m[keyname]["path"] try: sshdb.add(filename, keyname, source="yaml", uri="file://" + filename) except Exception as e: Console.error("problem adding key {}:{}".format( keyname, filename)) print(_print_dict(d, format=_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Console.error("Problem adding keys from yaml file") elif arguments['get']: try: name = arguments['NAME'] sshdb = SSHKeyDBManager() d = sshdb.table_dict() for i in d: if d[i]["name"] == name: key = d[i] print("{:}: {:}".format(key['name'], key['fingerprint'])) msg = "info. OK." Console.ok(msg) return "" else: pass Console.error("The key is not in the database") except Exception as e: Error.traceback(e) Console.error("The key is not in the database") # key add --git KEYNAME # key add --ssh KEYNAME # key add [--path=PATH] KEYNAME elif arguments['add'] and arguments["--git"]: print('git add') sshdb = SSHKeyDBManager() keyname = arguments['--name'] gitkeyname = arguments['NAME'] filename = arguments['FILENAME'] # Are we adding to the database as well? # sshdb.add(filename, keyname, source="ssh", uri="file://"+filename) username = arguments["--username"] if username == 'none': conf = ConfigDict("cloudmesh.yaml") username = conf["cloudmesh.github.username"] print(username) sshm = SSHKeyManager() try: sshm.get_from_git(username) d = dict(sshm.__keys__) print(d) except Exception as e: Error.traceback(e) Console.error("Problem adding keys to git for user: "******"" try: # FIXME: correct code to add to git d[gitkeyname]['keyname'] = keyname d[gitkeyname]['user'] = None d[gitkeyname]['source'] = 'git' # sshdb.add_from_dict(d[gitkeyname]) except Exception as e: Console.error("The key already exists") elif arguments['add'] and arguments["--ssh"]: # print('ssh add') sshdb = SSHKeyDBManager() keyname = arguments['--name'] filename = Config.path_expand("~/.ssh/id_rsa.pub") try: sshdb.add(filename, keyname, source="ssh", uri="file://" + filename) print("Key {:} successfully added to the database".format(keyname or "")) msg = "info. OK." Console.ok(msg) except Exception as e: """ Error.traceback(e) print (keyname) print (filename) """ Console.error("Problem adding the key `{}` from file `{}`".format(keyname, filename)) elif arguments['add'] and not arguments["--git"]: # print('ssh add') sshdb = SSHKeyDBManager() keyname = arguments['--name'] filename = arguments['FILENAME'] try: sshdb.add(filename, keyname, source="ssh", uri="file://" + filename) print("Key {:} successfully added to the database".format(keyname or "")) msg = "info. OK." Console.ok(msg) except ValueError as e: Console.error("The key `{}` already exists".format(keyname), traceflag=False) """ except Exception as e: Error.traceback(e) print (keyname) print (filename) Console.error("Problem adding the key `{}` from file `{}`".format(keyname, filename)) """ return "" elif arguments['default']: # print("default") if arguments['KEYNAME']: keyname = None try: keyname = arguments['KEYNAME'] sshdb = SSHKeyDBManager() sshdb.set_default(keyname) Default.set_key(keyname) print("Key {:} set as default".format(keyname)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Setting default for key {:} failed.".format(keyname)) elif arguments['--select']: keyname = None try: sshdb = SSHKeyDBManager() select = sshdb.select() if select != 'q': keyname = select.split(':')[0] print("Setting key: {:} as default.".format(keyname)) sshdb.set_default(keyname) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Setting default for selected key {:} failed.".format(keyname)) else: try: sshdb = SSHKeyDBManager() d = sshdb.table_dict() for i in d: if d[i]["is_default"] == "True": key = d[i] print("{:}: {:}".format(key['name'], key['fingerprint'])) msg = "info. OK." Console.ok(msg) return "" else: pass Console.error("The key is not in the database") except Exception as e: Error.traceback(e) Console.error("Problem retrieving default key.") elif arguments['delete']: delete_on_cloud = arguments["--force"] or False # print ("DDD", delete_on_cloud) if arguments['--all']: try: sshm = SSHKeyManager(delete_on_cloud=delete_on_cloud) sshm.delete_all_keys() print("All keys from the database deleted successfully.") msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem deleting keys") elif arguments['--select']: keyname = None sshdb = SSHKeyDBManager() select = sshdb.select() if select != 'q': try: keyname = select.split(':')[0] print("Deleting key: {:}...".format(keyname)) sshm = SSHKeyManager(delete_on_cloud=delete_on_cloud) sshm.delete_key(keyname) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem deleting the key `{:}`".format(keyname)) else: keyname = None try: keyname = arguments['KEYNAME'] sshm = SSHKeyManager(delete_on_cloud=delete_on_cloud) sshm.delete_key(keyname) print("Key {:} deleted successfully from database.".format(keyname)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem deleting the key `{:}`".format(keyname)) elif arguments['upload']: try: # # get username # conf = ConfigDict("cloudmesh.yaml") username = conf["cloudmesh"]["profile"]["username"] if username in ['None', 'TBD']: username = None # # get cloudnames # clouds = [] cloud = arguments["--cloud"] or Default.get_cloud() if cloud == "all": config = ConfigDict("cloudmesh.yaml") clouds = config["cloudmesh"]["clouds"] else: clouds.append(cloud) # # get keyname # for cloud in clouds: status = 0 sshdb = SSHKeyDBManager() sshm = SSHKeyManager() keys = sshdb.find_all() for keyid in keys: key = keys[keyid] print ("upload key {} -> {}".format(key["name"], cloud)) try: status = sshm.add_key_to_cloud( username, key["name"], cloud, key["name"]) except Exception as e: print (e) if "already exists" in str(e): print ("key already exists. Skipping " "upload. ok.") if status == 1: print("Problem uploading key. failed.") msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem adding key to cloud") elif arguments['map']: try: cloud = arguments["--cloud"] or Default.get_cloud() sshm = SSHKeyManager() map_dict = sshm.get_key_cloud_maps(cloud) print(dict_printer(map_dict, order=["user", "key_name", "cloud_name", "key_name_on_cloud"])) except Exception as e: Error.traceback(e) Console.error("Problem adding key to cloud")
def main(): """cm. Usage: cm --help cm [--debug] [--nosplash] [--file=SCRIPT] [-i] [COMMAND ...] Arguments: COMMAND A command to be executed Options: --file=SCRIPT -f SCRIPT Executes the script -i After start keep the shell interactive, otherwise quit [default: False] --nosplash do not show the banner [default: False] """ try: arg = docopt(main.__doc__, help=True) if arg['--help']: print(main.__doc__) sys.exit() # fixing the help parameter parsing # arguments['COMMAND'] = ['help'] # arguments['help'] = 'False' script_file = arg['--file'] except: script_file = None interactive = False arguments = sys.argv[1:] arg = { '--debug': '--debug' in arguments, '--nosplash': '--nosplash' in arguments, '-i': '-i' in arguments} for a in arg: if arg[a]: arguments.remove(a) arg['COMMAND'] = [' '.join(arguments)] splash = not arg['--nosplash'] debug = arg['--debug'] interactive = arg['-i'] context = CloudmeshContext(debug=debug, splash=splash) cmd = CloudmeshConsole(context) # TODO: check if cludmesh_yaml exists and if not create it # also creat .cloudmesh dir if it not exists """ from cloudmesh_client.common import cloudmesh_yaml create_cmd3_yaml_file(force=False, verbose=False) filename = cloudmesh_yaml try: module_config = ConfigDict(filename=filename) modules = module_config["cmd3"]["modules"] properties = module_config["cmd3"]["properties"] except: modules = ['cloudmesh_cmd3.plugins'] for module_name in modules: #print ("INSTALL", module_name) try: plugins.append(dict(get_plugins_from_module(module_name))) except: # print "WARNING: could not find", module_name pass """ # if script_file is not None: # cmd.do_exec(script_file) if len(arg['COMMAND']) > 0: user_cmd = None try: user_cmd = " ".join(arg['COMMAND']) if debug: print(">", user_cmd) cmd.onecmd(user_cmd) except Exception as e: print("ERROR: executing command '{0}'".format(user_cmd)) print(70 * "=") print(e) print(70 * "=") Error.traceback() if interactive: cmd.cmdloop() elif not script_file or interactive: cmd.cmdloop()
def do_register(self, args, arguments): """ :: Usage: register info register backup register new [--force] [--dryrun] register clean [--force] register list ssh [--format=FORMAT] register list [--yaml=FILENAME][--info][--format=FORMAT] register cat [--yaml=FILENAME] register edit [--yaml=FILENAME] register user [USERNAME] register cloud [CLOUD] [--force] register remote [CLOUD] [--force] register export HOST [--password] [--format=FORMAT] register source HOST register merge FILEPATH register form [--yaml=FILENAME] register check [--yaml=FILENAME] register test [--yaml=FILENAME] register json HOST register env [--provider=PROVIDER] register ec2 CLOUD EC2ZIP register ENTRY managing the registered clouds in the cloudmesh.yaml file. It looks for it in the current directory, and than in ~/.cloudmesh. If the file with the cloudmesh.yaml name is there it will use it. If neither location has one a new file will be created in ~/.cloudmesh/cloudmesh.yaml. Some defaults will be provided. However you will still need to fill it out with valid entries. Arguments: HOST the host name USER the user name FILEPATH the path of the file CLOUD the cloud name PROVIDER the provider or type of cloud [Default: openstack] USERNAME Username that would be registered in yaml. Defaults to OS username. Options: --provider=PROVIDER Provider to be used for cloud. Values are: openstack, azure, ec2. --version=VERSION Version of the openstack cloud. --openrc=OPENRC The location of the openrc file --password Prints the password --force ignore interactive questions and execute the action Description: register info lists the clouds specified in the cloudmesh.yaml file in the current directory, and then in ~/.cloudmesh register list [--yaml=FILENAME] [--name] [--info] lists the clouds specified in the cloudmesh.yaml file. If info is specified it also prints the location of the yaml file. register list ssh lists hosts from ~/.ssh/config register cat [--yaml=FILENAME] outputs the cloudmesh.yaml file register edit [--yaml=FILENAME] edits the cloudmesh.yaml file register export HOST [--format=FORMAT] prints the contents of an openrc.sh file based on the information found in the cloudmesh.yaml file. register remote CLOUD [--force] reads the Openstack OPENRC file from a remote host that is described in cloudmesh.yaml file. We assume that the file has already a template for this host. If not it can be created from other examples before you run this command. It uses the OS_OPENRC variable to locate the file and copy it onto your computer. register merge FILENAME Replaces the TBD in cloudmesh.yaml with the contents present in the named file register form [--yaml=FILENAME] interactively fills out the form wherever we find TBD. register check [--yaml=FILENAME] checks the yaml file for completness register test [--yaml=FILENAME] checks the yaml file and executes tests to check if we can use the cloud. TODO: maybe this should be in a test command register json host displays the host details in json format register remote CLOUD registers a remote cloud and copies the openrc file specified in the credentials of the cloudmesh.yaml register CLOUD --dir Copies the entire directory from the cloud and puts it in ~/.cloudmesh/clouds/host For kilo, The directory would be copied to ~/.cloudmesh/clouds/kilo register env [--provider=PROVIDER] [HOSTNAME] Reads env OS_* variables and registers a new cloud in yaml, interactively. Default PROVIDER is openstack and HOSTNAME is localhost. register user [USERNAME] Sets the user in yaml with the value provided. """ # from pprint import pprint # pprint(arguments) def _get_config_yaml_file(arguments): filename = arguments["--yaml"] or "cloudmesh.yaml" filename = Config.find_file(filename) return filename def exists(filename): return os.path.isfile(filename) def export(host, output): config = ConfigDict("cloudmesh.yaml") credentials = dict( config["cloudmesh"]["clouds"][host]["credentials"]) if not arguments["--password"]: credentials["OS_PASSWORD"] = "******" if output is None: for attribute, value in credentials.items(): print("export {}={}".format(attribute, value)) elif output == "table": print(Printer.attribute(credentials)) else: print(Printer.write(credentials, output=output)) # TODO: bug csv does not work if arguments["info"]: filename = _get_config_yaml_file(arguments) if os.path.isfile(filename): Console.ok("File '{}' exists. ok.".format(filename)) Console.ok("The yaml file contains the following templates:") d = CloudRegister.list(filename, Default.cloud, info=False, output="table") print(d) else: Console.error("File {} does not exist".format(filename)) return "" elif arguments["backup"]: name = backup_name("~/.cloudmesh/cloudmesh.yaml") configfile = path_expand("~/.cloudmesh/cloudmesh.yaml") print (name) try: copy(configfile, name) Console.ok("Bakup copy created: {}. ok.".format(name)) except: Console.error("Could not create a backup copy from {}".format(configfile)) return "" elif arguments["new"]: import shutil import cloudmesh_client.etc config = ConfigDict("cloudmesh.yaml") data = dotdict({ 'dir': cloudmesh_client.etc.__file__, 'filename': os.path.join( os.path.dirname(cloudmesh_client.etc.__file__), "cloudmesh.yaml"), 'yamlfile': path_expand("~/.cloudmesh/cloudmesh.yaml"), 'dryrun': arguments['--dryrun'] }) Console.ok(data.filename) force = arguments["--force"] if not force: force = yn_choice("Would you like create a new configuration file at {}".format(data.yamlfile)) if force: if not data.dryrun: config.make_a_copy(location=data.yamlfile) shutil.copyfile(data.filename, data.yamlfile) print("copy ") print("From: ", data.filename) print("To: ", data.yamlfile) # filename = _get_config_yaml_file(arguments) # if _exists(filename): # Console.ok("File '{}' exists. ok.".format(filename)) # else: # Console.error("File {} does not exist".format(filename)) return "" elif arguments["clean"]: filename = _get_config_yaml_file(arguments) force = arguments["--force"] or False if filename is not None: print(filename, force) if exists(filename): print("Delete cloudmesh.yaml file:", filename) if not force: force = yn_choice("Would you like to delete the " "cloudmesh.yaml file") print(force) if force: os.remove(filename) Console.ok("Deleted the file " + filename + ". ok.") else: Console.ok("Please use Y to delete the file.") pass else: Console.error("File {} does not exist".format(filename)) else: Console.error("No cloudmesh.yaml file found.") return "" elif arguments["cat"]: filename = _get_config_yaml_file(arguments) if exists(filename): with open(filename, 'r') as f: lines = f.read().split("\n") print('\n'.join(lines)) else: Console.error("File {} does not exist".format(filename)) return "" elif arguments["edit"]: filename = _get_config_yaml_file(arguments) if exists(filename): try: data = {"editor": os.environ["EDITOR"], "filename": filename} Console.ok("editing file " + filename) os.system("{editor} {filename}".format(**data)) except: Console.error("No operating system environment variable EDITOR set.", traceflag=False) else: Console.error("File {} does not exist".format(filename), traceflag=False) return "" elif arguments['list'] and arguments['ssh']: output = arguments['--format'] or 'table' hosts = CloudRegister.list_ssh() print(Printer.list(hosts, output=output)) return "" elif arguments['list']: filename = _get_config_yaml_file(arguments) info = arguments["--info"] or False output = arguments["--format"] or "table" if not filename: Console.error("File {} doesn't exist".format(filename)) else: d = CloudRegister.list(filename, Default.cloud, info=info, output=output) print(d) return "" elif arguments['check']: filename = _get_config_yaml_file(arguments) if not filename: Console.error("File {} doesn't exist".format( arguments["--yaml"] or 'cloudmesh.yaml')) else: CloudRegister.check_yaml_for_completeness(filename) return "" elif arguments['merge']: filename = arguments['FILENAME'] CloudRegister.from_file(filename) return "" elif arguments['test']: filename = _get_config_yaml_file(arguments) CloudRegister.test(filename) return "" elif arguments['form']: filename = _get_config_yaml_file(arguments) if not filename: Console.error("File {} doesn't exist".format( arguments["--yaml"] or 'cloudmesh.yaml')) else: CloudRegister.fill_out_form(filename) return "" elif arguments['source']: host = arguments['HOST'] config = ConfigDict("cloudmesh.yaml") credentials = dict( config["cloudmesh"]["clouds"][host]["credentials"]) # unset variables = list(os.environ) for attribute in variables: if attribute.startswith("OS_"): print("x ", attribute) del os.environ[attribute] # set for attribute, value in credentials.items(): os.putenv(attribute, value) print("+ ", attribute) export(host, "table") return "" elif arguments['export']: output = arguments['--format'] host = arguments['HOST'] try: variables = list(os.environ) for attribute in variables: if attribute.startswith("OS_"): print("unset ", attribute) del os.environ[attribute] export(host, output) except: Console.error ("The export may not include all values", traceflag=False) return "" elif arguments['json']: host = arguments['HOST'] result = CloudRegister.get(host) if result: print(json.dumps(result, indent=4)) else: print("Cloud {:} is not described in cloudmesh.yaml".format( host)) return "" elif arguments['remote']: force = arguments['--force'] cloud = arguments['CLOUD'] if cloud is None: # clouds = [ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["active"][0]] clouds = ["kilo"] # hardcode to kilo for now else: clouds = [cloud] for cloud in clouds: CloudRegister.remote(cloud, force) export(cloud, "table") config = ConfigDict("cloudmesh.yaml") if config["cloudmesh.profile.user"] == "TBD": name = config["cloudmesh.clouds.kilo.credentials.OS_USERNAME"] config["cloudmesh"]["profile"]["user"] = name config.save() return "" elif arguments['ec2']: cloud = arguments['CLOUD'] zipfile = arguments['EC2ZIP'] if cloud is None: clouds = [ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["active"][0]] else: clouds = [cloud] for cloud in clouds: CloudRegister.ec2(cloud, zipfile) export(cloud, "table") return "" elif arguments['env']: try: CloudRegister.from_environ(arguments['--provider']) except Exception as e: Error.traceback(e) return "" elif arguments['cloud']: """ if arguments['--dir']: cloud = arguments['--name'] directory = arguments['--dir'] Console.ok(directory) CloudRegister.directory(cloud, directory) else: """ values_to_replace = ['tbd', 'null', 'tbd_not_used'] cloud = arguments['CLOUD'] if cloud is None: clouds = [ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["active"][0]] else: clouds = [cloud] for cloud in clouds: config = ConfigDict("cloudmesh.yaml") cloud_config = config["cloudmesh.clouds"][cloud] # Checking credentials print("Checking cloud credentials...") for prop in cloud_config["credentials"]: if cloud_config["credentials"][prop].lower() in values_to_replace: value = input(prop + "(" + cloud_config["credentials"][prop] + "): ") cloud_config["credentials"][prop] = value # Checking defaults print("Checking cloud defaults...") for prop in cloud_config["default"]: if cloud_config["default"][prop].lower() in values_to_replace: value = input(prop + "(" + cloud_config["default"][prop] + "): ") cloud_config["default"][prop] = value config.save() export(cloud, "table") return "" elif arguments['user']: username = arguments["USERNAME"] or getpass.getuser() CloudRegister.set_username(username) Console.ok("Setting profile user to {} in the yaml file.".format(username)) hosts = ssh_config() hosts.generate(key="india", username=username, verbose=True) return "" elif arguments['ENTRY'].lower() in ['chameleon']: config = ConfigDict("cloudmesh.yaml") credentials = dotdict(config["cloudmesh.clouds.chameleon.credentials"]) default = credentials.OS_USERNAME username = input("Please enter the username for {:} [{}]: ".format("chameleon", default)) username = username or default while True: default = credentials.OS_PROJECT_NAME project = input("Please enter the project id for {:} [{}]: ".format("chameleon", default)) project = project or default if project.isdigit(): project = "CH-{}".format(project) break else: try: prefix, number = project.split("-") if not (prefix in ["CH"] and number.isdigit()): Console.error("This is not a valid Chameleon.org cloud project", traceflag=False) else: break except: Console.error("This is not a valid Chameleon.org cloud project", traceflag=False) password = getpass.getpass("Please enter the password for {:}: ".format("chameleon", credentials.OS_PASSWORD)) credentials.OS_TENENT_ID = credentials.OS_PROJECT_NAME credentials.OS_TENENT_NAME = credentials.OS_PROJECT_NAME credentials.OS_USERNAME = username credentials.OS_PASSWORD = password config.save() return "" elif arguments['ENTRY'] is not None: name = arguments['ENTRY'] Register.entry(name) return "" # if all fails do a simple list filename = _get_config_yaml_file(arguments) CloudRegister.list(filename) pass
def main(): """cm. Usage: cm --help cm [--echo] [--debug] [--nosplash] [-i] [COMMAND ...] Arguments: COMMAND A command to be executed Options: --file=SCRIPT -f SCRIPT Executes the script -i After start keep the shell interactive, otherwise quit [default: False] --nosplash do not show the banner [default: False] """ def manual(): print(main.__doc__) args = sys.argv[1:] arguments = { '--echo': '--echo' in args, '--help': '--help' in args, '--debug': '--debug' in args, '--nosplash': '--nosplash' in args, '-i': '-i' in args } echo = arguments["--echo"] if arguments['--help']: manual() sys.exit() for a in args: if a in arguments: args.remove(a) arguments['COMMAND'] = [' '.join(args)] commands = arguments["COMMAND"] if len(commands) > 0: if ".cm" in commands[0]: arguments["SCRIPT"] = commands[0] commands = commands[1:] else: arguments["SCRIPT"] = None arguments["COMMAND"] = ' '.join(commands) if arguments["COMMAND"] == '': arguments["COMMAND"] = None # noinspection PySimplifyBooleanCheck if arguments['COMMAND'] == []: arguments['COMMAND'] = None splash = not arguments['--nosplash'] debug = arguments['--debug'] interactive = arguments['-i'] script = arguments["SCRIPT"] command = arguments["COMMAND"] context = CloudmeshContext(interactive=interactive, debug=debug, echo=echo, splash=splash) cmd = CloudmeshConsole(context) if script is not None: cmd.do_exec(script) try: if echo: print("cm>", command) if command is not None: cmd.precmd(command) stop = cmd.onecmd(command) cmd.postcmd(stop, command) except Exception as e: print("ERROR: executing command '{0}'".format(command)) print(70 * "=") print(e) print(70 * "=") Error.traceback() if interactive or (command is None and script is None): cmd.cmdloop()
def do_reservation(self, args, arguments): """ :: Usage: reservation info --user=USER --project=PROJECT reservation list [--name=NAME] [--user=USER] [--project=PROJECT] [--hosts=HOSTS] [--start=TIME_START] [--end=TIME_END] [--format=FORMAT] reservation delete [all] [--user=USER] [--project=PROJECT] [--name=NAME] [--start=TIME_START] [--end=TIME_END] [--hosts=HOSTS] reservation delete --file=FILE reservation update --name=NAME [--start=TIME_START] [--end=TIME_END] [--user=USER] [--project=PROJECT] [--hosts=HOSTS] [--description=DESCRIPTION] reservation add --name=NAME [--start=TIME_START] [--end=TIME_END] [--user=USER] [--project=PROJECT] [--hosts=HOSTS] [--description=DESCRIPTION] reservation add --file=FILE Arguments: NAME Name of the reservation USER Registration will be done for this user PROJECT Project to be used HOSTS Hosts to reserve TIME_START Start time of reservation TIME_END End time of reservation FORMAT Format of output DESCRIPTION Description for reservation FILE File that contains reservation data to be added/ deleted Options: --name=NAME Names of the reservation --user=USER user name --project=PROJECT project id --start=TIME_START Start time of the reservation, in MM/DD/YYYY at hh:mm aa format. (default value: 01/01/1901 at 12:00 am]) --end=TIME_END End time of the reservation, in MM/DD/YYYY at hh:mm aa format. (default value: 12/31/2100 at 11:59 pm]) --host=HOSTS host name --description=DESCRIPTION description summary of the reservation --file=FILE Adding multiple reservations from one file --format=FORMAT Format is either table, json, yaml or csv [default: table] Description: reservation info lists the resources that support reservation for a given user or project. """ # print (arguments) def _print_dict(d, header=None, format='table'): if format == "json": return json.dumps(d, indent=4) elif format == "yaml": return pyaml.dump(d) elif format == "table": return dict_printer(d, order=["id", "name", "start_time", "end_time", "user", "project", "hosts", "description", "cloud"], output="table", sort_keys=True) elif format == "csv": TODO.implement() else: return d # return dict_printer(d,order=['cm_id, name, fingerprint']) def _get_db_date_format(date): """ Utility Function that accepts instance of Date object and returns a string with Datetime for DB. :param date: Date object :return: Date as string with format expected in DB. """ db_date = "{:}-{:}-{:} {:}:{:}".format(str(date.month).zfill(2), str(date.day).zfill(2), str(date.year).zfill(4), str(date.hour).zfill(2), str(date.minute).zfill(2)) return db_date if arguments["info"]: TODO.implement() elif arguments["list"]: try: _name = arguments['--name'] _user = arguments['--user'] _project = arguments['--project'] _format = arguments['--format'] _hosts = arguments['--hosts'] _start = arguments['--start'] _end = arguments['--end'] _format = arguments['--format'] reserve = Reservation() dictionary = reserve.list(_name, _start, _end, _user, _project, _hosts) print(_print_dict(dictionary, format=_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem listing reservations") elif arguments["delete"]: if arguments["all"]: try: reserve = Reservation() reserve.delete() msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem deleting all reservations") else: try: _name = arguments['--name'] _user = arguments['--user'] _project = arguments['--project'] _format = arguments['--format'] _hosts = arguments['--hosts'] _start = arguments['--start'] _end = arguments['--end'] _format = arguments['--format'] reserve = Reservation() reserve.delete(_name, _start, _end, _user, _project, _hosts) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem deleting reservations") elif arguments["add"]: if arguments["--file"] is None: name = None try: name = arguments["--name"] hosts = arguments["--hosts"] user = arguments["--user"] project = arguments["--project"] description = arguments["--description"] start_time = arguments["--start"] or "01/01/1901 at 07:30 pm" end_time = arguments["--end"] or "12/31/2100 at 11:59 pm" stime = Date(start_time) etime = Date(end_time) reserve = Reservation() reserve.add(name, _get_db_date_format(stime), _get_db_date_format(etime), hosts=hosts, user=user, project=project, description=description) print("Reservation {:} added successfully".format(name)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error( "Problem adding reservation {:}".format(name)) else: try: TODO.implement() """ with open(os.path.join(sys.path[0], arguments["--file"])) as file: reader = csv.reader(file) for row in reader: reservations = Reservation(cm_id=row[0], label=row[1], user=row[2], project=row[3], start_time=row[4], end_time=row[5], host=row[6], summary=row[7]) db.add() """ except Exception as e: print("Error in adding from file. ", e) elif arguments["update"]: name = None try: name = arguments["--name"] hosts = arguments["--hosts"] user = arguments["--user"] project = arguments["--project"] description = arguments["--description"] start_time = arguments["--start"] or "01/01/1901 at 07:30 pm" end_time = arguments["--end"] or "12/31/2100 at 11:59 pm" stime = Date(start_time) etime = Date(end_time) reserve = Reservation() reserve.update(name, _get_db_date_format(stime), _get_db_date_format(etime), hosts=hosts, user=user, project=project, description=description) print("Reservation {:} updated successfully".format(name)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem updating reservation {:}".format(name)) return ""
def do_vm(self, args, arguments): """ :: Usage: vm default [--cloud=CLOUD][--format=FORMAT] vm refresh [--cloud=CLOUD] vm boot [--name=NAME] [--cloud=CLOUD] [--image=IMAGE_OR_ID] [--flavor=FLAVOR_OR_ID] [--group=GROUP] [--secgroup=SECGROUP] [--key=KEY] [--dryrun] vm start [NAME]... [--group=GROUP] [--cloud=CLOUD] [--force] vm stop [NAME]... [--group=GROUP] [--cloud=CLOUD] [--force] vm delete [NAME]... [--group=GROUP] [--cloud=CLOUD] [--force] vm ip assign [NAME]... [--cloud=CLOUD] vm ip show [NAME]... [--group=GROUP] [--cloud=CLOUD] [--format=FORMAT] [--refresh] vm login [NAME] [--user=USER] [--ip=IP] [--cloud=CLOUD] [--key=KEY] [--command=COMMAND] vm rename [NAME]... [--new=NEWNAME] [--cloud=CLOUD] vm list [NAME_OR_ID] [--cloud=CLOUD|--all] [--group=GROUP] [--format=FORMAT] [--refresh] vm status [--cloud=CLOUD] vm info [--cloud=CLOUD] [--format=FORMAT] Arguments: COMMAND positional arguments, the commands you want to execute on the server(e.g. ls -a) separated by ';', you will get a return of executing result instead of login to the server, note that type in -- is suggested before you input the commands NAME server name. By default it is set to the name of last vm from database. NAME_OR_ID server name or ID KEYPAIR_NAME Name of the openstack keypair to be used to create VM. Note this is not a path to key. NEWNAME New name of the VM while renaming. Options: --ip=IP give the public ip of the server --cloud=CLOUD give a cloud to work on, if not given, selected or default cloud will be used --count=COUNT give the number of servers to start --detail for table print format, a brief version is used as default, use this flag to print detailed table --flavor=FLAVOR_OR_ID give the name or id of the flavor --group=GROUP give the group name of server --secgroup=SECGROUP security group name for the server --image=IMAGE_OR_ID give the name or id of the image --key=KEY specify a key to use, input a string which is the full path to the private key file --keypair_name=KEYPAIR_NAME Name of the openstack keypair to be used to create VM. Note this is not a path to key. --user=USER give the user name of the server that you want to use to login --name=NAME give the name of the virtual machine --force delete vms without user's confirmation --command=COMMAND specify the commands to be executed --new=NEWNAME Specify the new name for a VM while renaming. By default, this will be set to <username>-<count> format. Description: commands used to boot, start or delete servers of a cloud vm default [options...] Displays default parameters that are set for VM boot. vm boot [options...] Boots servers on a cloud, user may specify flavor, image .etc, otherwise default values will be used, see how to set default values of a cloud: cloud help vm start [options...] Starts a suspended or stopped vm instance. vm stop [options...] Stops a vm instance . vm delete [options...] delete servers of a cloud, user may delete a server by its name or id, delete servers of a group or servers of a cloud, give prefix and/or range to find servers by their names. Or user may specify more options to narrow the search vm floating_ip_assign [options...] assign a public ip to a VM of a cloud vm ip show [options...] show the ips of VMs vm login [options...] login to a server or execute commands on it vm list [options...] same as command "list vm", please refer to it vm status [options...] Retrieves status of last VM booted on cloud and displays it. Tip: give the VM name, but in a hostlist style, which is very convenient when you need a range of VMs e.g. sample[1-3] => ['sample1', 'sample2', 'sample3'] sample[1-3,18] => ['sample1', 'sample2', 'sample3', 'sample18'] """ def _print_dict(d, header=None, format='table'): if format == "json": return json.dumps(d, indent=4) elif format == "yaml": return pyaml.dump(d) elif format == "table": return dict_printer(d, order=["id", "name", "status"], output="table", sort_keys=True) else: return d def _print_dict_ip(d, header=None, format='table'): if format == "json": return json.dumps(d, indent=4) elif format == "yaml": return pyaml.dump(d) elif format == "table": return dict_printer(d, order=["network", "version", "addr"], output="table", sort_keys=True) else: return d """ def list_vms_on_cloud(cloud="kilo", group=None, format="table"): Utility reusable function to list vms on the cloud. :param cloud: :param group: :param format: :return: _cloud = cloud _group = group _format = format cloud_provider = CloudProvider(_cloud).provider servers = cloud_provider.list_vm(_cloud) server_list = {} index = 0 # TODO: Improve the implementation to display more fields if required. for server in servers: server_list[index] = {} server_list[index]["name"] = server.name server_list[index]["id"] = server.id server_list[index]["status"] = server.status index += 1 # TODO: Get this printed in a table print("Print table") dict_printer(servers, output=_format) """ # pprint(arguments) def _refresh(): try: msg = "Refresh VMs for cloud {:}.".format(cloud) if Vm.refresh(cloud=cloud): Console.ok("{:} OK.".format(msg)) else: Console.error("{:} failed".format(msg)) except Exception as e: Error.traceback(e) Console.error("Problem running VM refresh") cloud = arguments["--cloud"] or Default.get_cloud() if arguments["boot"]: name = None try: name = arguments["--name"] is_name_provided = True if name is None: is_name_provided = False count = Counter.get() prefix = Username() if prefix is None or count is None: Console.error("Prefix and Count could not be retrieved correctly.") return # BUG THE Z FILL SHOULD BE detected from yaml file name = prefix + "-" + str(count).zfill(3) # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" image = arguments["--image"] or Default.get("image", category=cloud) # if default image not set, return error if not image: Console.error("Default image not set.") return "" flavor = arguments["--flavor"] or Default.get("flavor", category=cloud) # if default flavor not set, return error if not flavor: Console.error("Default flavor not set.") return "" group = arguments["--group"] or Default.get_group() # if default group not set, return error if not group: group = "default" Default.set_group(group) secgroup = arguments["--secgroup"] or Default.get( "secgroup", category=cloud) # print("SecurityGrp : {:}".format(secgroup)) secgroup_list = ["default"] if secgroup is not None: secgroup_list.append(secgroup) key_name = arguments["--key"] or Default.get_key() # if default keypair not set, return error if not key_name: Console.error("Default key not set.") return "" if arguments["--dryrun"]: data = { "cloud": cloud, "name": name, "image": image, "flavor": flavor, "key_name": key_name, "secgroup_list": secgroup_list, "group": group } print (attribute_printer(data, output="table")) msg = "dryrun info. OK." Console.ok(msg) else: vm_id = Vm.boot(cloud=cloud, name=name, image=image, flavor=flavor, key_name=key_name, secgroup_list=secgroup_list) Default.set("last_vm_id", vm_id) Default.set("last_vm_name", name) # SHOULD WE NOT DO THIS BY DEFAULT EVEN IF WE SPECIFY THE NAME? if is_name_provided is False: # Incrementing count Counter.incr() # Add to group if vm_id is not None: Group.add(name=group, type="vm", id=name, category=cloud) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem booting instance {:}".format(name)) elif arguments["default"]: try: count = Counter.get() prefix = Username() if prefix is None or count is None: Console.error("Prefix and Count could not be retrieved correctly.") return vm_name = prefix + "-" + str(count).zfill(3) data = {"name": vm_name, "cloud": arguments["--cloud"] or Default.get_cloud()} for attribute in ["image", "flavor", "key", "login_key", "group", "secgroup"]: data[attribute] = Default.get(attribute, category=cloud) output_format = arguments["--format"] or "table" print (attribute_printer(data, output=output_format)) msg = "info. OK." Console.ok(msg) ValueError("default command not implemented properly. Upon " "first install the defaults should be read from yaml.") except Exception as e: Error.traceback(e) Console.error("Problem listing defaults") elif arguments["status"]: try: cloud_provider = CloudProvider(cloud).provider vm_list = cloud_provider.list_vm(cloud) print("Status of VM {} is {}".format(vm_list[0]["name"], vm_list[0]["status"])) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem retrieving status of the VM") elif arguments["info"]: try: cloud_provider = CloudProvider(cloud).provider vms = cloud_provider.list_vm(cloud) vm = vms[0] output_format = arguments["--format"] or "table" print (attribute_printer(vm, output=output_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem retrieving status of the VM") elif arguments["start"]: try: servers = arguments["NAME"] # If names not provided, take the last vm from DB. if servers is None or len(servers) == 0: last_vm = Vm.get_last_vm(cloud=cloud) if last_vm is None: Console.error("No VM records in database. Please run vm refresh.") return "" name = last_vm["name"] # print(name) servers = list() servers.append(name) group = arguments["--group"] force = arguments["--force"] # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" Vm.start(cloud=cloud, servers=servers) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem starting instances") elif arguments["stop"]: try: servers = arguments["NAME"] # If names not provided, take the last vm from DB. if servers is None or len(servers) == 0: last_vm = Vm.get_last_vm(cloud=cloud) if last_vm is None: Console.error("No VM records in database. Please run vm refresh.") return "" name = last_vm["name"] # print(name) servers = list() servers.append(name) group = arguments["--group"] force = arguments["--force"] # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" Vm.stop(cloud=cloud, servers=servers) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem stopping instances") elif arguments["refresh"]: _refresh() elif arguments["delete"]: try: servers = arguments["NAME"] # If names not provided, take the last vm from DB. if servers is None or len(servers) == 0: last_vm = Vm.get_last_vm(cloud=cloud) if last_vm is None: Console.error("No VM records in database. Please run vm refresh.") return "" name = last_vm["name"] servers = list() servers.append(name) group = arguments["--group"] force = arguments["--force"] # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" Vm.delete(cloud=cloud, servers=servers) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem deleting instances") elif arguments["ip"] and arguments["assign"]: vmids = arguments["NAME"] # If names not provided, take the last vm from DB. if vmids is None or len(vmids) == 0: last_vm = Vm.get_last_vm(cloud=cloud) if last_vm is None: Console.error("No VM records in database. Please run vm refresh.") return "" name = last_vm["name"] vmids = list() vmids.append(name) # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" try: cloud_provider = CloudProvider(cloud).provider for sname in vmids: floating_ip = cloud_provider.create_assign_floating_ip( sname) if floating_ip is not None: print( "Floating IP assigned to {:} successfully and it is: {:}".format( sname, floating_ip)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem assigning floating ips.") elif arguments["ip"] and arguments["show"]: vmids = arguments["NAME"] # If names not provided, take the last vm from DB. if vmids is None or len(vmids) == 0: last_vm = Vm.get_last_vm(cloud=cloud) if last_vm is None: Console.error("No VM records in database. Please run vm refresh.") return "" name = last_vm["name"] vmids = list() vmids.append(name) group = arguments["--group"] output_format = arguments["--format"] or "table" refresh = arguments["--refresh"] # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" try: cloud_provider = CloudProvider(cloud).provider for server in vmids: ip_addr = cloud_provider.get_ips(server) ipaddr_dict = Vm.construct_ip_dict(ip_addr, cloud) print( "IP Addresses of instance {:} are as follows:-".format( server)) print(_print_dict_ip(ipaddr_dict, format=output_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error( "Problem getting ip addresses for instance {:}".format(id)) elif arguments["login"]: vm_names = arguments["NAME"] # If names not provided, take the last vm from DB. if vm_names is None or len(vm_names) == 0: last_vm = Vm.get_last_vm(cloud=cloud) if last_vm is None: Console.error("No VM records in database. Please run vm refresh.") return "" name = last_vm["name"] else: name = vm_names[0] print("Logging in into {:} machine...".format(name)) user = arguments["--user"] # Get user if user argument not specified. if user is None: user_from_db = Vm.get_vm_login_user(name, cloud) user_suggest = user_from_db or getpass.getuser() user = input("Enter the user to login (Default: {}):".format(user_suggest)) or user_suggest Vm.set_vm_login_user(name, cloud, user) ip = arguments["--ip"] commands = arguments["--command"] # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" key = arguments["--key"] or Default.get("login_key", category=cloud) if not key: Console.error("Default login_key not set.") return "" cloud_provider = CloudProvider(cloud).provider # print("Name : {:}".format(name)) ip_addr = cloud_provider.get_ips(name) ip_addresses = [] ipaddr_dict = Vm.construct_ip_dict(ip_addr, cloud) for entry in ipaddr_dict: ip_addresses.append(ipaddr_dict[entry]["addr"]) if ip is not None: if ip not in ip_addresses: print( "ERROR: IP Address specified does not match with the host.") return "" else: print("Determining IP Address to use with a ping test.") # This part assumes that the ping is allowed to the machine. for ipadd in ip_addresses: print("Checking {:}...".format(ipadd)) try: socket.gethostbyaddr(ipadd) # ip will be set if above command is successful. ip = ipadd except socket.herror: print("Cannot reach {:}.".format(ipadd)) if ip is None: print("SORRY. Unable to connect to the machine") return "" else: print("IP to be used is: {:}".format(ip)) SecGroup.enable_ssh(cloud=cloud) # print("COMMANDS : {:}".format(commands)) # Constructing the ssh command to connect to the machine. sshcommand = "ssh" if key is not None: sshcommand += " -i {:}".format(key) sshcommand += " -o StrictHostKeyChecking=no" sshcommand += " {:}@{:}".format(user, ip) if commands is not None: sshcommand += " \"{:}\"".format(commands) # print(sshcommand) os.system(sshcommand) elif arguments["list"]: if arguments["--all"]: try: _format = arguments["--format"] or "table" d = ConfigDict("cloudmesh.yaml") for cloud in d["cloudmesh"]["clouds"]: if arguments["--refresh"] or Default.refresh(): _refresh() print("Listing VMs on Cloud: {:}".format(cloud)) result = Vm.list(cloud=cloud, output_format=_format) if result is not None: print(result) else: print("Sorry. No data found with requested parameters in DB.") msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem listing all instances") else: # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" try: name_or_id = arguments["NAME_OR_ID"] group = arguments["--group"] _format = arguments["--format"] or "table" # list_vms_on_cloud(cloud, group, _format) if arguments["--refresh"] or Default.refresh(): _refresh() result = Vm.list(name_or_id=name_or_id, cloud=cloud, output_format=_format) if result is not None: print(result) else: print("No data found with the requested parameters.") msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error( "Problem listing instances on cloud {:}".format(cloud)) elif arguments["rename"]: try: servers = arguments["NAME"] # If names not provided, take the last vm from DB. if servers is None or len(servers) == 0: last_vm = Vm.get_last_vm(cloud=cloud) if last_vm is None: Console.error("No VM records in database. Please run vm refresh.") return "" name = last_vm["name"] servers = list() servers.append(name) # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" new_name = arguments["--new"] is_name_provided = True # If the new name is not provided, make the new new name in format username-count. if new_name is None or len(new_name) == 0: is_name_provided = False count = Counter.get() prefix = Username() if prefix is None or count is None: Console.error("Prefix and Count could not be retrieved correctly.") return # BUG THE Z FILL SHOULD BE detected from yaml file new_name = prefix + "-" + str(count).zfill(3) Vm.rename(cloud=cloud, servers=servers, new_name=new_name) if is_name_provided is False: # Incrementing count Counter.incr() msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem deleting instances") return ""
def do_key(self, args, arguments): """ :: Usage: key -h | --help key list --cloud=CLOUD key list --source=db [--format=FORMAT] key list --source=yaml [--format=FORMAT] key list --source=ssh [--dir=DIR] [--format=FORMAT] key list --source=git [--format=FORMAT] [--username=USERNAME] key list key load [--format=FORMAT] key add [NAME] [--source=FILENAME] key add [NAME] [--git] key add [NAME] [--ssh] key get NAME key default --select key delete (NAME | --select | --all) key delete NAME --cloud=CLOUD key upload [NAME] [--cloud=CLOUD] key upload [NAME] --active Manages the keys Arguments: CLOUD The cloud NAME The name of the key. SOURCE db, ssh, all KEYNAME The name of a key. For key upload it defaults to the default key name. FORMAT The format of the output (table, json, yaml) FILENAME The filename with full path in which the key is located NAME_ON_CLOUD Typically the name of the keypair on the cloud. Options: --dir=DIR the directory with keys [default: ~/.ssh] --format=FORMAT the format of the output [default: table] --source=SOURCE the source for the keys [default: db] --username=USERNAME the source for the keys [default: none] --name=KEYNAME The name of a key --all delete all keys --force delete the key form the cloud --name_on_cloud=NAME_ON_CLOUD Typically the name of the keypair on the cloud. Description: key list --source=git [--username=USERNAME] lists all keys in git for the specified user. If the name is not specified it is read from cloudmesh.yaml key list --source=ssh [--dir=DIR] [--format=FORMAT] lists all keys in the directory. If the directory is not specified the default will be ~/.ssh key list --source=yaml [--dir=DIR] [--format=FORMAT] lists all keys in cloudmesh.yaml file in the specified directory. dir is by default ~/.cloudmesh key list [--format=FORMAT] list the keys in the giiven format: json, yaml, table. table is default key list Prints list of keys. NAME of the key can be specified key add [--name=keyname] FILENAME adds the key specifid by the filename to the key database key get NAME Retrieves the key indicated by the NAME parameter from database and prints its fingerprint. key default --select Select the default key interactively key delete NAME deletes a key. In yaml mode it can delete only key that are not saved in the database key rename NAME NEW renames the key from NAME to NEW. """ # pprint(arguments) invalid_names = ['tbd', 'none', "", 'id_rsa'] def _print_dict(d, header=None, format='table'): msg = Printer.write(d, order=["name", "comment", "uri", "fingerprint", "source"], output=format, sort_keys=True) if msg is None: Console.error("No keys found.", traceflag=False) return None else: return msg directory = Config.path_expand(arguments["--dir"]) cloud = arguments["--cloud"] or Default.cloud if arguments['list']: _format = arguments['--format'] _source = arguments['--source'] _dir = arguments['--dir'] if "--source" not in arguments and "--cloud" not in arguments: arguments["--source"] = 'db' if arguments['--cloud']: # # get key list from openstack cloud # #keys = Key.list(cloud, output=_format) #keys = Key.list_on_cloud(cloud, live=True, format=_format) keys = Key.get_from_cloud(cloud, live=True, format=_format) if keys is None: Console.ok("The Key list is empty") else: print(Printer.write(keys, order=["name", "fingerprint"], output=_format or "table")) return "" elif arguments['--source'] == 'ssh': try: #sshm = SSHKeyManager() d = Key.get_from_dir(directory, store=False) #print("SSS", type(Key.__keys__)) #d = dict(Key.all()) #print(d) print(Printer.write(d, order=["name", "comment", "uri", "fingerprint", "source"], output="table")) # d = dict(sshm.__keys__) # print(_print_dict(d, format=_format)) msg = "info. OK." Console.ok(msg) return "" except Exception as e: Error.traceback(e) Console.error("Problem listing keys from ssh") elif arguments['--source'] in ['cm', 'cloudmesh', 'yaml']: try: #sshm = SSHKeyManager() d = Key.get_from_yaml(load_order=directory, store=False) print(Printer.write(d, order=["name", "comment", "uri", "fingerprint", "source"], output=_format)) return "" except Exception as e: Error.traceback(e) Console.error("Problem listing keys from `{:}`".format(arguments['--source'])) elif arguments['--source'] in ['git']: username = arguments["--username"] # print(username) if username == 'none': conf = ConfigDict("cloudmesh.yaml") username = conf["cloudmesh.github.username"] #sshm = SSHKeyManager() try: d = Key.get_from_git(username, store=False) print(Printer.write(d, order=["name", "comment", "uri", "fingerprint", "source"], output=_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem listing git keys from database") return "" elif arguments['--source'] == 'db': try: #sshdb = SSHKeyDBManager() d = Key.all(output='dict') if d is not None or d != []: print(Printer.write(d, order=["name", "comment", "uri", "fingerprint", "source"], output=_format)) # print(_print_dict(d, output=arguments['--format'])) msg = "info. OK." Console.ok(msg) else: Console.error("No keys in the database") except Exception as e: Error.traceback(e) Console.error("Problem listing keys from database") elif arguments['get']: try: name = arguments['NAME'] #sshdb = SSHKeyDBManager() d = Key.all(output="dict") for key in d: if key["name"] == name: print("{:}: {:}".format(key['name'], key['fingerprint'])) msg = "info. OK." Console.ok(msg) return "" else: pass Console.error("The key is not in the database") except Exception as e: Error.traceback(e) Console.error("The key is not in the database") # key add [NAME] [--source=FILENAME] # key add [NAME] [--git] elif arguments['add'] and arguments["--git"]: # Console.error("This feature is not yet implemented", traceflag=False) # return "" print('git add') #sshdb = SSHKeyDBManager() data = dotdict(arguments) keyname = data.NAME # # get name # conf = ConfigDict("cloudmesh.yaml") data.username = conf["cloudmesh.github.username"] data.name = arguments['NAME'] or data.username # # get git username # data.username = ConfigDict("cloudmesh.yaml")["cloudmesh.github.username"] if str(data.name).lower() in invalid_names: Console.error("The github user name is not set in the yaml file", traceflag=False) return "" try: Console.msg("Retrieving github ssh keys for user {username}".format(**data)) #sshm = SSHKeyManager() Key.get_from_git(data.username) d = Key.all() # pprint(d) except Exception as e: Console.error("Problem adding keys to git for user: {username}".format(**data)) return "" for key in d: if key is not None: key["name"] = key["name"].replace("-", "_") key["source"] = "git" key["user"] = data.name try: o = dict(key) o['value'] = key["string"] Key.add_from_dict(key) except Exception as e: Console.error("The key {name} with that finger print already exists".format(**key), traceflag=False) elif arguments['add'] and not arguments["--git"]: # key add [NAME] [--source=FILENAME] # key add [NAME] [--git] #sshdb = SSHKeyDBManager() data = dotdict() # # get name # conf = ConfigDict("cloudmesh.yaml") data.username = conf["cloudmesh.profile.user"] data.name = arguments['NAME'] or data.username data.filename = arguments['--source'] if data.filename == "db" or data.filename is None: data.filename = Config.path_expand("~/.ssh/id_rsa.pub") if str(data.name).lower() in invalid_names: msg = ("Your choice of keyname {name} is insufficient. \n" "You must be chosing a keyname that is distingct on all clouds. \n" "Possible choices are your gmail name, your XSEDE name, or \n" "some name that is uniqe. " "Best is also to set this name in \n" "cloudmesh.profile.user as " "part of your \n~/cloudmesh/cloudmesh.yaml file.") Console.error(msg.format(**data), traceflag=False) return "" try: Key.add_from_path(data.filename, data.name, source="ssh", uri="file://" + data.filename) print("Key {name} successfully added to the database".format(**data)) msg = "info. OK." Console.ok(msg) except ValueError as e: Console.error("A key with this fingerprint already exists".format(**data), traceflag=False) Console.msg("Please use check with: key list") return "" elif arguments['default']: # print("default") if arguments['--select']: keyname = None try: #sshdb = SSHKeyDBManager() select = Key.select() if select != 'q': keyname = select.split(':')[0] print("Setting key: {:} as default.".format(keyname)) Default.key = keyname msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Setting default for selected key {:} failed.".format(keyname)) else: try: #sshdb = SSHKeyDBManager() d = Key.table_dict() for i in d: if d[i]["is_default"] == "True": key = d[i] print("{:}: {:}".format(key['name'], key['fingerprint'])) msg = "info. OK." Console.ok(msg) return "" else: pass Console.error("The key is not in the database") except Exception as e: Error.traceback(e) Console.error("Problem retrieving default key.") elif arguments['delete'] and arguments["--cloud"]: key = dotdict({ 'cloud': arguments["--cloud"], 'name': arguments["NAME"] }) try: Key.delete(key.name, key.cloud) msg = "info. OK." Console.ok(msg) except: Console.error("Problem deleting the key {name} on the cloud {cloud}".format(**key)) elif arguments['delete']: # key delete (NAME | --select| --all) data = dotdict({ 'all': arguments['--all'] or False, 'select': arguments['--select'] or False, 'name': arguments['NAME'] or False, }) pprint(data) # BUG delete all is not properly implemented if data.all: Console.TODO("Delete --all is not yet implemented.") # Key.delete() elif data.select: key = Key.select() print (key) else: # name Key.delete(data.name) msg = "info. OK." Console.ok(msg) elif arguments['upload']: # pprint(arguments) try: # # get username # conf = ConfigDict("cloudmesh.yaml") username = conf["cloudmesh"]["profile"]["user"] if username in ['None', 'TBD']: username = None # # get cloudnames # clouds = [] if arguments["--active"]: cloud = 'active' else: cloud = arguments["--cloud"] or Default.cloud if cloud == "all": config = ConfigDict("cloudmesh.yaml") clouds = config["cloudmesh"]["clouds"] elif cloud == 'active': config = ConfigDict("cloudmesh.yaml") clouds = config["cloudmesh"]["active"] else: clouds.append(cloud) # # get keyname # for cloud in clouds: status = 0 #sshdb = SSHKeyDBManager() #sshm = SSHKeyManager() keys = Key.all() for key in keys: print("upload key {} -> {}".format(key["name"], cloud)) try: status = Key.add_key_to_cloud( username, key["name"], cloud) except Exception as e: Console.error("problem") if "already exists" in str(e): print("key already exists. Skipping upload. OK.") if status == 1: print("Problem uploading key {} to {}. failed.".format(key["name"], cloud)) except Exception as e: Console.error("Problem adding key to cloud")
def do_register(self, args, arguments): """ :: Usage: register info register new register clean [--force] register list ssh [--format=FORMAT] register list [--yaml=FILENAME][--info][--format=FORMAT] register cat [--yaml=FILENAME] register edit [--yaml=FILENAME] register export HOST [--password] [--format=FORMAT] register source HOST register merge FILEPATH register form [--yaml=FILENAME] register check [--yaml=FILENAME] register test [--yaml=FILENAME] register json HOST register remote [CLOUD] [--force] register env [--provider=PROVIDER] register profile --username=[USERNAME] register yaml ENTRY register CLOUD [--force] register CLOUD [--dir=DIR] register ec2 CLOUD EC2ZIP managing the registered clouds in the cloudmesh.yaml file. It looks for it in the current directory, and than in ~/.cloudmesh. If the file with the cloudmesh.yaml name is there it will use it. If neither location has one a new file will be created in ~/.cloudmesh/cloudmesh.yaml. Some defaults will be provided. However you will still need to fill it out with valid entries. Arguments: HOST the host name USER the user name FILEPATH the path of the file CLOUD the cloud name PROVIDER the provider or type of cloud [Default: openstack] USERNAME Username that would be registered in yaml. Defaults to OS username. Options: --provider=PROVIDER Provider to be used for cloud. Values are: openstack, azure, ec2. --version=VERSION Version of the openstack cloud. --openrc=OPENRC The location of the openrc file --password Prints the password --force ignore interactive questions and execute the action Description: register info It looks out for the cloudmesh.yaml file in the current directory, and then in ~/.cloudmesh register list [--yaml=FILENAME] [--name] [--info] lists the clouds specified in the cloudmesh.yaml file. If info is specified it also prints the location of the yaml file. register list ssh lists hosts from ~/.ssh/config register cat [--yaml=FILENAME] outputs the cloudmesh.yaml file register edit [--yaml=FILENAME] edits the cloudmesh.yaml file register export HOST [--format=FORMAT] prints the contents of an openrc.sh file based on the information found in the cloudmesh.yaml file. register remote CLOUD [--force] reads the Openstack OPENRC file from a remote host that is described in cloudmesh.yaml file. We assume that the file has already a template for this host. If not it can be created from other examples before you run this command. It uses the OS_OPENRC variable to locate the file and copy it onto your computer. register merge FILENAME Replaces the TBD in cloudmesh.yaml with the contents present in the named file register form [--yaml=FILENAME] interactively fills out the form wherever we find TBD. register check [--yaml=FILENAME] checks the yaml file for completness register test [--yaml=FILENAME] checks the yaml file and executes tests to check if we can use the cloud. TODO: maybe this should be in a test command register json host displays the host details in json format register remote CLOUD registers a remote cloud and copies the openrc file specified in the credentials of the cloudmesh.yaml register CLOUD --dir Copies the entire directory from the cloud and puts it in ~/.cloudmesh/clouds/host For kilo, The directory would be copied to ~/.cloudmesh/clouds/kilo register env [--provider=PROVIDER] [HOSTNAME] Reads env OS_* variables and registers a new cloud in yaml, interactively. Default PROVIDER is openstack and HOSTNAME is localhost. register username [USERNAME] Sets the username in yaml with the value provided. """ # from pprint import pprint # pprint(arguments) def _get_config_yaml_file(arguments): filename = arguments["--yaml"] or "cloudmesh.yaml" filename = Config.find_file(filename) return filename def exists(filename): return os.path.isfile(filename) def export(host, output): config = ConfigDict("cloudmesh.yaml") credentials = dict( config["cloudmesh"]["clouds"][host]["credentials"]) if not arguments["--password"]: credentials["OS_PASSWORD"] = "******" if output is None: for attribute, value in credentials.items(): print("export {}={}".format(attribute, value)) elif output == "table": print(attribute_printer(credentials)) else: print(dict_printer(credentials, output=output)) # TODO: bug csv does not work return "" if arguments["info"]: filename = _get_config_yaml_file(arguments) if os.path.isfile(filename): Console.ok("File '{}' exists. ok.".format(filename)) Console.ok("The yaml file contains the following templates:") d = CloudRegister.list(filename, info=False, output="table") print(d) else: Console.error("File {} does not exist".format(filename)) return "" elif arguments["new"]: import shutil import cloudmesh_client.etc print(cloudmesh_client.etc.__file__) filename = os.path.join( os.path.dirname(cloudmesh_client.etc.__file__), "cloudmesh.yaml") Console.ok(filename) yamlfile = path_expand("~/.cloudmesh/cloudmesh.yaml") shutil.copyfile(filename, yamlfile) print("copy ") print("From: ", filename) print("To: ", yamlfile) # filename = _get_config_yaml_file(arguments) # if _exists(filename): # Console.ok("File '{}' exists. ok.".format(filename)) # else: # Console.error("File {} does not exist".format(filename)) return "" elif arguments["clean"]: filename = _get_config_yaml_file(arguments) force = arguments["--force"] or False if filename is not None: print(filename, force) if exists(filename): print("Delete cloudmesh.yaml file:", filename) if not force: force = yn_choice("Would you like to delete the " "cloudmesh.yaml file") print(force) if force: os.remove(filename) Console.ok("Deleted the file " + filename + ". ok.") else: Console.ok("Please use Y to delete the file.") pass else: Console.error("File {} does not exist".format(filename)) else: Console.error("No cloudmesh.yaml file found.") return "" elif arguments["cat"]: filename = _get_config_yaml_file(arguments) if exists(filename): with open(filename, 'r') as f: lines = f.read().split("\n") print('\n'.join(lines)) else: Console.error("File {} does not exist".format(filename)) return "" elif arguments["edit"]: filename = _get_config_yaml_file(arguments) if exists(filename): try: data = {"editor": os.environ["EDITOR"], "filename": filename} Console.ok("editing file " + filename) os.system("{editor} {filename}".format(**data)) except: Console.error("No EDITOR variable set in shell.") else: Console.error("File {} does not exist".format(filename)) return "" elif arguments['list'] and arguments['ssh']: output = arguments['--format'] or 'table' hosts = CloudRegister.list_ssh() print(print_list(hosts, output=output)) return "" elif arguments['list']: filename = _get_config_yaml_file(arguments) info = arguments["--info"] or False output = arguments["--format"] or "table" if not filename: Console.error("File {} doesn't exist".format(filename)) else: d = CloudRegister.list(filename, info=info, output=output) print(d) return "" elif arguments['check']: filename = _get_config_yaml_file(arguments) if not filename: Console.error("File {} doesn't exist".format( arguments["--yaml"] or 'cloudmesh.yaml')) else: CloudRegister.check_yaml_for_completeness(filename) return "" elif arguments['merge']: filename = arguments['FILENAME'] CloudRegister.from_file(filename) return elif arguments['test']: filename = _get_config_yaml_file(arguments) CloudRegister.test(filename) return "" elif arguments['form']: filename = _get_config_yaml_file(arguments) if not filename: Console.error("File {} doesn't exist".format( arguments["--yaml"] or 'cloudmesh.yaml')) else: CloudRegister.fill_out_form(filename) return "" elif arguments['source']: host = arguments['HOST'] config = ConfigDict("cloudmesh.yaml") credentials = dict( config["cloudmesh"]["clouds"][host]["credentials"]) # unset variables = list(os.environ) for attribute in variables: if attribute.startswith("OS_"): print("x ", attribute) del os.environ[attribute] # set for attribute, value in credentials.items(): os.putenv(attribute, value) print("+ ", attribute) export(host, "table") return "" elif arguments['export']: output = arguments['--format'] host = arguments['HOST'] variables = list(os.environ) for attribute in variables: if attribute.startswith("OS_"): print("unset ", attribute) del os.environ[attribute] export(host, output) elif arguments['json']: host = arguments['HOST'] result = CloudRegister.get(host) if result: print(json.dumps(result, indent=4)) else: print("Cloud {:} is not described in cloudmesh.yaml".format( host)) return "" elif arguments['remote']: force = arguments['--force'] cloud = arguments['CLOUD'] if cloud is None: clouds = ["kilo"] else: clouds = [cloud] for cloud in clouds: CloudRegister.remote(cloud, force) export(cloud, "table") config = ConfigDict("cloudmesh.yaml") if config["cloudmesh.profile.username"] == "TBD": name = config["cloudmesh.clouds.kilo.credentials.OS_USERNAME"] config["cloudmesh"]["profile"]["username"] = name config.save() else: print("KKK") return "" elif arguments['ec2']: cloud = arguments['CLOUD'] zipfile = arguments['EC2ZIP'] if cloud is None: clouds = ["kilo"] else: clouds = [cloud] for cloud in clouds: CloudRegister.ec2(cloud, zipfile) export(cloud, "table") elif arguments['env']: try: CloudRegister.from_environ(arguments['--provider']) except Exception as e: Error.traceback(e) return "" elif arguments['CLOUD']: if arguments['--dir']: cloud = arguments['CLOUD'] directory = arguments['--dir'] Console.ok(directory) CloudRegister.directory(cloud, directory) else: cloud = arguments['CLOUD'] if cloud is None: clouds = ["kilo"] else: clouds = [cloud] for cloud in clouds: CloudRegister.remote(cloud, True) export(cloud, "table") return "" elif arguments['profile']: username = arguments["--username"] or getpass.getuser() CloudRegister.set_username(username) Console.ok("Username {} set successfully in the yaml settings.".format(username)) return "" elif arguments['yaml']: name = arguments['ENTRY'] Register.entry(name) return "" # if all fails do a simple list filename = _get_config_yaml_file(arguments) CloudRegister.list(filename) pass
def do_register(self, args, arguments): """ :: Usage: register info register backup register new [--force] [--dryrun] register clean [--force] register list ssh [--format=FORMAT] register list [--yaml=FILENAME][--info][--format=FORMAT] register cat [--yaml=FILENAME] register edit [--yaml=FILENAME] register user [USERNAME] register cloud [CLOUD] [--force] register remote [CLOUD] [--force] register export HOST [--password] [--format=FORMAT] register source HOST register merge FILEPATH register form [--yaml=FILENAME] register check [--yaml=FILENAME] register test [--yaml=FILENAME] register json HOST register env [--provider=PROVIDER] register ec2 CLOUD EC2ZIP register ENTRY managing the registered clouds in the cloudmesh.yaml file. It looks for it in the current directory, and than in ~/.cloudmesh. If the file with the cloudmesh.yaml name is there it will use it. If neither location has one a new file will be created in ~/.cloudmesh/cloudmesh.yaml. Some defaults will be provided. However you will still need to fill it out with valid entries. Arguments: HOST the host name USER the user name FILEPATH the path of the file CLOUD the cloud name PROVIDER the provider or type of cloud [Default: openstack] USERNAME Username that would be registered in yaml. Defaults to OS username. Options: --provider=PROVIDER Provider to be used for cloud. Values are: openstack, azure, ec2. --version=VERSION Version of the openstack cloud. --openrc=OPENRC The location of the openrc file --password Prints the password --force ignore interactive questions and execute the action Description: register info lists the clouds specified in the cloudmesh.yaml file in the current directory, and then in ~/.cloudmesh register list [--yaml=FILENAME] [--name] [--info] lists the clouds specified in the cloudmesh.yaml file. If info is specified it also prints the location of the yaml file. register list ssh lists hosts from ~/.ssh/config register cat [--yaml=FILENAME] outputs the cloudmesh.yaml file register edit [--yaml=FILENAME] edits the cloudmesh.yaml file register export HOST [--format=FORMAT] prints the contents of an openrc.sh file based on the information found in the cloudmesh.yaml file. register remote CLOUD [--force] reads the Openstack OPENRC file from a remote host that is described in cloudmesh.yaml file. We assume that the file has already a template for this host. If not it can be created from other examples before you run this command. It uses the OS_OPENRC variable to locate the file and copy it onto your computer. register merge FILENAME Replaces the TBD in cloudmesh.yaml with the contents present in the named file register form [--yaml=FILENAME] interactively fills out the form wherever we find TBD. register check [--yaml=FILENAME] checks the yaml file for completness register test [--yaml=FILENAME] checks the yaml file and executes tests to check if we can use the cloud. TODO: maybe this should be in a test command register json host displays the host details in json format register remote CLOUD registers a remote cloud and copies the openrc file specified in the credentials of the cloudmesh.yaml register CLOUD --dir Copies the entire directory from the cloud and puts it in ~/.cloudmesh/clouds/host For kilo, The directory would be copied to ~/.cloudmesh/clouds/kilo register env [--provider=PROVIDER] [HOSTNAME] Reads env OS_* variables and registers a new cloud in yaml, interactively. Default PROVIDER is openstack and HOSTNAME is localhost. register user [USERNAME] Sets the user in yaml with the value provided. """ # from pprint import pprint # pprint(arguments) def _get_config_yaml_file(arguments): filename = arguments["--yaml"] or "cloudmesh.yaml" filename = Config.find_file(filename) return filename def exists(filename): return os.path.isfile(filename) def export(host, output): config = ConfigDict("cloudmesh.yaml") credentials = dict( config["cloudmesh"]["clouds"][host]["credentials"]) if not arguments["--password"]: credentials["OS_PASSWORD"] = "******" if output is None: for attribute, value in credentials.items(): print("export {}={}".format(attribute, value)) elif output == "table": print(Printer.attribute(credentials)) else: print(Printer.write(credentials, output=output)) # TODO: bug csv does not work if arguments["info"]: filename = _get_config_yaml_file(arguments) if os.path.isfile(filename): Console.ok("File '{}' exists. ok.".format(filename)) Console.ok("The yaml file contains the following templates:") d = CloudRegister.list(filename, Default.cloud, info=False, output="table") print(d) else: Console.error("File {} does not exist".format(filename)) return "" elif arguments["backup"]: name = backup_name("~/.cloudmesh/cloudmesh.yaml") configfile = path_expand("~/.cloudmesh/cloudmesh.yaml") print(name) try: copy(configfile, name) Console.ok("Bakup copy created: {}. ok.".format(name)) except: Console.error("Could not create a backup copy from {}".format( configfile)) return "" elif arguments["new"]: import shutil import cloudmesh_client.etc config = ConfigDict("cloudmesh.yaml") data = dotdict({ 'dir': cloudmesh_client.etc.__file__, 'filename': os.path.join(os.path.dirname(cloudmesh_client.etc.__file__), "cloudmesh.yaml"), 'yamlfile': path_expand("~/.cloudmesh/cloudmesh.yaml"), 'dryrun': arguments['--dryrun'] }) Console.ok(data.filename) force = arguments["--force"] if not force: force = yn_choice( "Would you like create a new configuration file at {}". format(data.yamlfile)) if force: if not data.dryrun: config.make_a_copy(location=data.yamlfile) shutil.copyfile(data.filename, data.yamlfile) print("copy ") print("From: ", data.filename) print("To: ", data.yamlfile) # filename = _get_config_yaml_file(arguments) # if _exists(filename): # Console.ok("File '{}' exists. ok.".format(filename)) # else: # Console.error("File {} does not exist".format(filename)) return "" elif arguments["clean"]: filename = _get_config_yaml_file(arguments) force = arguments["--force"] or False if filename is not None: print(filename, force) if exists(filename): print("Delete cloudmesh.yaml file:", filename) if not force: force = yn_choice("Would you like to delete the " "cloudmesh.yaml file") print(force) if force: os.remove(filename) Console.ok("Deleted the file " + filename + ". ok.") else: Console.ok("Please use Y to delete the file.") pass else: Console.error("File {} does not exist".format(filename)) else: Console.error("No cloudmesh.yaml file found.") return "" elif arguments["cat"]: filename = _get_config_yaml_file(arguments) if exists(filename): with open(filename, 'r') as f: lines = f.read().split("\n") print('\n'.join(lines)) else: Console.error("File {} does not exist".format(filename)) return "" elif arguments["edit"]: filename = _get_config_yaml_file(arguments) if exists(filename): try: data = { "editor": os.environ["EDITOR"], "filename": filename } Console.ok("editing file " + filename) os.system("{editor} {filename}".format(**data)) except: Console.error( "No operating system environment variable EDITOR set.", traceflag=False) else: Console.error("File {} does not exist".format(filename), traceflag=False) return "" elif arguments['list'] and arguments['ssh']: output = arguments['--format'] or 'table' hosts = CloudRegister.list_ssh() print(Printer.list(hosts, output=output)) return "" elif arguments['list']: filename = _get_config_yaml_file(arguments) info = arguments["--info"] or False output = arguments["--format"] or "table" if not filename: Console.error("File {} doesn't exist".format(filename)) else: d = CloudRegister.list(filename, Default.cloud, info=info, output=output) print(d) return "" elif arguments['check']: filename = _get_config_yaml_file(arguments) if not filename: Console.error("File {} doesn't exist".format( arguments["--yaml"] or 'cloudmesh.yaml')) else: CloudRegister.check_yaml_for_completeness(filename) return "" elif arguments['merge']: filename = arguments['FILENAME'] CloudRegister.from_file(filename) return "" elif arguments['test']: filename = _get_config_yaml_file(arguments) CloudRegister.test(filename) return "" elif arguments['form']: filename = _get_config_yaml_file(arguments) if not filename: Console.error("File {} doesn't exist".format( arguments["--yaml"] or 'cloudmesh.yaml')) else: CloudRegister.fill_out_form(filename) return "" elif arguments['source']: host = arguments['HOST'] config = ConfigDict("cloudmesh.yaml") credentials = dict( config["cloudmesh"]["clouds"][host]["credentials"]) # unset variables = list(os.environ) for attribute in variables: if attribute.startswith("OS_"): print("x ", attribute) del os.environ[attribute] # set for attribute, value in credentials.items(): os.putenv(attribute, value) print("+ ", attribute) export(host, "table") return "" elif arguments['export']: output = arguments['--format'] host = arguments['HOST'] try: variables = list(os.environ) for attribute in variables: if attribute.startswith("OS_"): print("unset ", attribute) del os.environ[attribute] export(host, output) except: Console.error("The export may not include all values", traceflag=False) return "" elif arguments['json']: host = arguments['HOST'] result = CloudRegister.get(host) if result: print(json.dumps(result, indent=4)) else: print("Cloud {:} is not described in cloudmesh.yaml".format( host)) return "" elif arguments['remote']: force = arguments['--force'] cloud = arguments['CLOUD'] if cloud is None: # clouds = [ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["active"][0]] clouds = ["kilo"] # hardcode to kilo for now else: clouds = [cloud] for cloud in clouds: CloudRegister.remote(cloud, force) export(cloud, "table") config = ConfigDict("cloudmesh.yaml") if config["cloudmesh.profile.user"] == "TBD": name = config["cloudmesh.clouds.kilo.credentials.OS_USERNAME"] config["cloudmesh"]["profile"]["user"] = name config.save() return "" elif arguments['ec2']: cloud = arguments['CLOUD'] zipfile = arguments['EC2ZIP'] if cloud is None: clouds = [ ConfigDict( filename="cloudmesh.yaml")["cloudmesh"]["active"][0] ] else: clouds = [cloud] for cloud in clouds: CloudRegister.ec2(cloud, zipfile) export(cloud, "table") return "" elif arguments['env']: try: CloudRegister.from_environ(arguments['--provider']) except Exception as e: Error.traceback(e) return "" elif arguments['cloud']: """ if arguments['--dir']: cloud = arguments['--name'] directory = arguments['--dir'] Console.ok(directory) CloudRegister.directory(cloud, directory) else: """ values_to_replace = ['tbd', 'null', 'tbd_not_used'] cloud = arguments['CLOUD'] if cloud is None: clouds = [ ConfigDict( filename="cloudmesh.yaml")["cloudmesh"]["active"][0] ] else: clouds = [cloud] for cloud in clouds: config = ConfigDict("cloudmesh.yaml") cloud_config = config["cloudmesh.clouds"][cloud] # Checking credentials print("Checking cloud credentials...") for prop in cloud_config["credentials"]: if cloud_config["credentials"][prop].lower( ) in values_to_replace: value = input(prop + "(" + cloud_config["credentials"][prop] + "): ") cloud_config["credentials"][prop] = value # Checking defaults print("Checking cloud defaults...") for prop in cloud_config["default"]: if cloud_config["default"][prop].lower( ) in values_to_replace: value = input(prop + "(" + cloud_config["default"][prop] + "): ") cloud_config["default"][prop] = value config.save() export(cloud, "table") return "" elif arguments['user']: username = arguments["USERNAME"] or getpass.getuser() CloudRegister.set_username(username) Console.ok("Setting profile user to {} in the yaml file.".format( username)) hosts = ssh_config() hosts.generate(key="india", username=username, verbose=True) return "" elif arguments['ENTRY'] is not None: name = arguments['ENTRY'] Register.entry(name) return "" # if all fails do a simple list filename = _get_config_yaml_file(arguments) CloudRegister.list(filename) pass
def do_vm(self, args, arguments): """ :: Usage: vm default [--cloud=CLOUD][--format=FORMAT] vm refresh [--cloud=CLOUD] vm boot [--name=NAME] [--cloud=CLOUD] [--image=IMAGE_OR_ID] [--flavor=FLAVOR_OR_ID] [--group=GROUP] [--secgroup=SECGROUP] [--key=KEY] [--dryrun] vm start [NAME]... [--group=GROUP] [--cloud=CLOUD] [--force] vm stop [NAME]... [--group=GROUP] [--cloud=CLOUD] [--force] vm delete [NAME]... [--group=GROUP] [--cloud=CLOUD] [--force] vm ip assign [NAME]... [--cloud=CLOUD] vm ip show [NAME]... [--group=GROUP] [--cloud=CLOUD] [--format=FORMAT] [--refresh] vm login [NAME] [--user=USER] [--ip=IP] [--cloud=CLOUD] [--key=KEY] [--command=COMMAND] vm rename [NAME]... [--new=NEWNAME] [--cloud=CLOUD] vm list [NAME_OR_ID] [--cloud=CLOUD|--all] [--group=GROUP] [--format=FORMAT] [--refresh] vm status [--cloud=CLOUD] vm info [--cloud=CLOUD] [--format=FORMAT] Arguments: COMMAND positional arguments, the commands you want to execute on the server(e.g. ls -a) separated by ';', you will get a return of executing result instead of login to the server, note that type in -- is suggested before you input the commands NAME server name. By default it is set to the name of last vm from database. NAME_OR_ID server name or ID KEYPAIR_NAME Name of the openstack keypair to be used to create VM. Note this is not a path to key. NEWNAME New name of the VM while renaming. Options: --ip=IP give the public ip of the server --cloud=CLOUD give a cloud to work on, if not given, selected or default cloud will be used --count=COUNT give the number of servers to start --detail for table print format, a brief version is used as default, use this flag to print detailed table --flavor=FLAVOR_OR_ID give the name or id of the flavor --group=GROUP give the group name of server --secgroup=SECGROUP security group name for the server --image=IMAGE_OR_ID give the name or id of the image --key=KEY specify a key to use, input a string which is the full path to the private key file --keypair_name=KEYPAIR_NAME Name of the openstack keypair to be used to create VM. Note this is not a path to key. --user=USER give the user name of the server that you want to use to login --name=NAME give the name of the virtual machine --force delete vms without user's confirmation --command=COMMAND specify the commands to be executed --new=NEWNAME Specify the new name for a VM while renaming. By default, this will be set to <username>-<count> format. Description: commands used to boot, start or delete servers of a cloud vm default [options...] Displays default parameters that are set for VM boot. vm boot [options...] Boots servers on a cloud, user may specify flavor, image .etc, otherwise default values will be used, see how to set default values of a cloud: cloud help vm start [options...] Starts a suspended or stopped vm instance. vm stop [options...] Stops a vm instance . vm delete [options...] delete servers of a cloud, user may delete a server by its name or id, delete servers of a group or servers of a cloud, give prefix and/or range to find servers by their names. Or user may specify more options to narrow the search vm floating_ip_assign [options...] assign a public ip to a VM of a cloud vm ip show [options...] show the ips of VMs vm login [options...] login to a server or execute commands on it vm list [options...] same as command "list vm", please refer to it vm status [options...] Retrieves status of last VM booted on cloud and displays it. Tip: give the VM name, but in a hostlist style, which is very convenient when you need a range of VMs e.g. sample[1-3] => ['sample1', 'sample2', 'sample3'] sample[1-3,18] => ['sample1', 'sample2', 'sample3', 'sample18'] """ def _print_dict(d, header=None, format='table'): if format == "json": return json.dumps(d, indent=4) elif format == "yaml": return pyaml.dump(d) elif format == "table": return dict_printer(d, order=["id", "name", "status"], output="table", sort_keys=True) else: return d def _print_dict_ip(d, header=None, format='table'): if format == "json": return json.dumps(d, indent=4) elif format == "yaml": return pyaml.dump(d) elif format == "table": return dict_printer(d, order=["network", "version", "addr"], output="table", sort_keys=True) else: return d """ def list_vms_on_cloud(cloud="kilo", group=None, format="table"): Utility reusable function to list vms on the cloud. :param cloud: :param group: :param format: :return: _cloud = cloud _group = group _format = format cloud_provider = CloudProvider(_cloud).provider servers = cloud_provider.list_vm(_cloud) server_list = {} index = 0 # TODO: Improve the implementation to display more fields if required. for server in servers: server_list[index] = {} server_list[index]["name"] = server.name server_list[index]["id"] = server.id server_list[index]["status"] = server.status index += 1 # TODO: Get this printed in a table print("Print table") dict_printer(servers, output=_format) """ # pprint(arguments) def _refresh(): try: msg = "Refresh VMs for cloud {:}.".format(cloud) if Vm.refresh(cloud=cloud): Console.ok("{:} OK.".format(msg)) else: Console.error("{:} failed".format(msg)) except Exception as e: Error.traceback(e) Console.error("Problem running VM refresh") cloud = arguments["--cloud"] or Default.get_cloud() if arguments["boot"]: name = None try: name = arguments["--name"] is_name_provided = True if name is None: is_name_provided = False count = Counter.get() prefix = Username() if prefix is None or count is None: Console.error( "Prefix and Count could not be retrieved correctly." ) return # BUG THE Z FILL SHOULD BE detected from yaml file name = prefix + "-" + str(count).zfill(3) # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" image = arguments["--image"] or Default.get("image", category=cloud) # if default image not set, return error if not image: Console.error("Default image not set.") return "" flavor = arguments["--flavor"] or Default.get("flavor", category=cloud) # if default flavor not set, return error if not flavor: Console.error("Default flavor not set.") return "" group = arguments["--group"] or Default.get_group() # if default group not set, return error if not group: group = "default" Default.set_group(group) secgroup = arguments["--secgroup"] or Default.get( "secgroup", category=cloud) # print("SecurityGrp : {:}".format(secgroup)) secgroup_list = ["default"] if secgroup is not None: secgroup_list.append(secgroup) key_name = arguments["--key"] or Default.get_key() # if default keypair not set, return error if not key_name: Console.error("Default key not set.") return "" if arguments["--dryrun"]: data = { "cloud": cloud, "name": name, "image": image, "flavor": flavor, "key_name": key_name, "secgroup_list": secgroup_list, "group": group } print(attribute_printer(data, output="table")) msg = "dryrun info. OK." Console.ok(msg) else: vm_id = Vm.boot(cloud=cloud, name=name, image=image, flavor=flavor, key_name=key_name, secgroup_list=secgroup_list) Default.set("last_vm_id", vm_id) Default.set("last_vm_name", name) # SHOULD WE NOT DO THIS BY DEFAULT EVEN IF WE SPECIFY THE NAME? if is_name_provided is False: # Incrementing count Counter.incr() # Add to group if vm_id is not None: Group.add(name=group, type="vm", id=name, category=cloud) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem booting instance {:}".format(name)) elif arguments["default"]: try: count = Counter.get() prefix = Username() if prefix is None or count is None: Console.error( "Prefix and Count could not be retrieved correctly.") return vm_name = prefix + "-" + str(count).zfill(3) data = { "name": vm_name, "cloud": arguments["--cloud"] or Default.get_cloud() } for attribute in [ "image", "flavor", "key", "login_key", "group", "secgroup" ]: data[attribute] = Default.get(attribute, category=cloud) output_format = arguments["--format"] or "table" print(attribute_printer(data, output=output_format)) msg = "info. OK." Console.ok(msg) ValueError( "default command not implemented properly. Upon " "first install the defaults should be read from yaml.") except Exception as e: Error.traceback(e) Console.error("Problem listing defaults") elif arguments["status"]: try: cloud_provider = CloudProvider(cloud).provider vm_list = cloud_provider.list_vm(cloud) print("Status of VM {} is {}".format(vm_list[0]["name"], vm_list[0]["status"])) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem retrieving status of the VM") elif arguments["info"]: try: cloud_provider = CloudProvider(cloud).provider vms = cloud_provider.list_vm(cloud) vm = vms[0] output_format = arguments["--format"] or "table" print(attribute_printer(vm, output=output_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem retrieving status of the VM") elif arguments["start"]: try: servers = arguments["NAME"] # If names not provided, take the last vm from DB. if servers is None or len(servers) == 0: last_vm = Vm.get_last_vm(cloud=cloud) if last_vm is None: Console.error( "No VM records in database. Please run vm refresh." ) return "" name = last_vm["name"] # print(name) servers = list() servers.append(name) group = arguments["--group"] force = arguments["--force"] # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" Vm.start(cloud=cloud, servers=servers) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem starting instances") elif arguments["stop"]: try: servers = arguments["NAME"] # If names not provided, take the last vm from DB. if servers is None or len(servers) == 0: last_vm = Vm.get_last_vm(cloud=cloud) if last_vm is None: Console.error( "No VM records in database. Please run vm refresh." ) return "" name = last_vm["name"] # print(name) servers = list() servers.append(name) group = arguments["--group"] force = arguments["--force"] # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" Vm.stop(cloud=cloud, servers=servers) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem stopping instances") elif arguments["refresh"]: _refresh() elif arguments["delete"]: try: servers = arguments["NAME"] # If names not provided, take the last vm from DB. if servers is None or len(servers) == 0: last_vm = Vm.get_last_vm(cloud=cloud) if last_vm is None: Console.error( "No VM records in database. Please run vm refresh." ) return "" name = last_vm["name"] servers = list() servers.append(name) group = arguments["--group"] force = arguments["--force"] # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" Vm.delete(cloud=cloud, servers=servers) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem deleting instances") elif arguments["ip"] and arguments["assign"]: vmids = arguments["NAME"] # If names not provided, take the last vm from DB. if vmids is None or len(vmids) == 0: last_vm = Vm.get_last_vm(cloud=cloud) if last_vm is None: Console.error( "No VM records in database. Please run vm refresh.") return "" name = last_vm["name"] vmids = list() vmids.append(name) # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" try: cloud_provider = CloudProvider(cloud).provider for sname in vmids: floating_ip = cloud_provider.create_assign_floating_ip( sname) if floating_ip is not None: print( "Floating IP assigned to {:} successfully and it is: {:}" .format(sname, floating_ip)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem assigning floating ips.") elif arguments["ip"] and arguments["show"]: vmids = arguments["NAME"] # If names not provided, take the last vm from DB. if vmids is None or len(vmids) == 0: last_vm = Vm.get_last_vm(cloud=cloud) if last_vm is None: Console.error( "No VM records in database. Please run vm refresh.") return "" name = last_vm["name"] vmids = list() vmids.append(name) group = arguments["--group"] output_format = arguments["--format"] or "table" refresh = arguments["--refresh"] # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" try: cloud_provider = CloudProvider(cloud).provider for server in vmids: ip_addr = cloud_provider.get_ips(server) ipaddr_dict = Vm.construct_ip_dict(ip_addr, cloud) print( "IP Addresses of instance {:} are as follows:-".format( server)) print(_print_dict_ip(ipaddr_dict, format=output_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error( "Problem getting ip addresses for instance {:}".format(id)) elif arguments["login"]: vm_names = arguments["NAME"] # If names not provided, take the last vm from DB. if vm_names is None or len(vm_names) == 0: last_vm = Vm.get_last_vm(cloud=cloud) if last_vm is None: Console.error( "No VM records in database. Please run vm refresh.") return "" name = last_vm["name"] else: name = vm_names[0] print("Logging in into {:} machine...".format(name)) user = arguments["--user"] # Get user if user argument not specified. if user is None: user_from_db = Vm.get_vm_login_user(name, cloud) user_suggest = user_from_db or getpass.getuser() user = input("Enter the user to login (Default: {}):".format( user_suggest)) or user_suggest Vm.set_vm_login_user(name, cloud, user) ip = arguments["--ip"] commands = arguments["--command"] # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" key = arguments["--key"] or Default.get("login_key", category=cloud) if not key: Console.error("Default login_key not set.") return "" cloud_provider = CloudProvider(cloud).provider # print("Name : {:}".format(name)) ip_addr = cloud_provider.get_ips(name) ip_addresses = [] ipaddr_dict = Vm.construct_ip_dict(ip_addr, cloud) for entry in ipaddr_dict: ip_addresses.append(ipaddr_dict[entry]["addr"]) if ip is not None: if ip not in ip_addresses: print( "ERROR: IP Address specified does not match with the host." ) return "" else: print("Determining IP Address to use with a ping test.") # This part assumes that the ping is allowed to the machine. for ipadd in ip_addresses: print("Checking {:}...".format(ipadd)) try: socket.gethostbyaddr(ipadd) # ip will be set if above command is successful. ip = ipadd except socket.herror: print("Cannot reach {:}.".format(ipadd)) if ip is None: print("SORRY. Unable to connect to the machine") return "" else: print("IP to be used is: {:}".format(ip)) SecGroup.enable_ssh(cloud=cloud) # print("COMMANDS : {:}".format(commands)) # Constructing the ssh command to connect to the machine. sshcommand = "ssh" if key is not None: sshcommand += " -i {:}".format(key) sshcommand += " -o StrictHostKeyChecking=no" sshcommand += " {:}@{:}".format(user, ip) if commands is not None: sshcommand += " \"{:}\"".format(commands) # print(sshcommand) os.system(sshcommand) elif arguments["list"]: if arguments["--all"]: try: _format = arguments["--format"] or "table" d = ConfigDict("cloudmesh.yaml") for cloud in d["cloudmesh"]["clouds"]: if arguments["--refresh"] or Default.refresh(): _refresh() print("Listing VMs on Cloud: {:}".format(cloud)) result = Vm.list(cloud=cloud, output_format=_format) if result is not None: print(result) else: print( "Sorry. No data found with requested parameters in DB." ) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem listing all instances") else: # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" try: name_or_id = arguments["NAME_OR_ID"] group = arguments["--group"] _format = arguments["--format"] or "table" # list_vms_on_cloud(cloud, group, _format) if arguments["--refresh"] or Default.refresh(): _refresh() result = Vm.list(name_or_id=name_or_id, cloud=cloud, output_format=_format) if result is not None: print(result) else: print("No data found with the requested parameters.") msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error( "Problem listing instances on cloud {:}".format(cloud)) elif arguments["rename"]: try: servers = arguments["NAME"] # If names not provided, take the last vm from DB. if servers is None or len(servers) == 0: last_vm = Vm.get_last_vm(cloud=cloud) if last_vm is None: Console.error( "No VM records in database. Please run vm refresh." ) return "" name = last_vm["name"] servers = list() servers.append(name) # if default cloud not set, return error if not cloud: Console.error("Default cloud not set.") return "" new_name = arguments["--new"] is_name_provided = True # If the new name is not provided, make the new new name in format username-count. if new_name is None or len(new_name) == 0: is_name_provided = False count = Counter.get() prefix = Username() if prefix is None or count is None: Console.error( "Prefix and Count could not be retrieved correctly." ) return # BUG THE Z FILL SHOULD BE detected from yaml file new_name = prefix + "-" + str(count).zfill(3) Vm.rename(cloud=cloud, servers=servers, new_name=new_name) if is_name_provided is False: # Incrementing count Counter.incr() msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem deleting instances") return ""
def main(): """cm. Usage: cm --help cm [--echo] [--debug] [--nosplash] [-i] [COMMAND ...] Arguments: COMMAND A command to be executed Options: --file=SCRIPT -f SCRIPT Executes the script -i After start keep the shell interactive, otherwise quit [default: False] --nosplash do not show the banner [default: False] """ def manual(): print(main.__doc__) args = sys.argv[1:] arguments = { '--echo': '--echo' in args, '--help': '--help' in args, '--debug': '--debug' in args, '--nosplash': '--nosplash' in args, '-i': '-i' in args} echo = arguments["--echo"] if arguments['--help']: manual() sys.exit() for a in args: if a in arguments: args.remove(a) arguments['COMMAND'] = [' '.join(args)] commands = arguments["COMMAND"] if len(commands) > 0: if ".cm" in commands[0]: arguments["SCRIPT"] = commands[0] commands = commands[1:] else: arguments["SCRIPT"] = None arguments["COMMAND"] = ' '.join(commands) if arguments["COMMAND"] == '': arguments["COMMAND"] = None # noinspection PySimplifyBooleanCheck if arguments['COMMAND'] == []: arguments['COMMAND'] = None splash = not arguments['--nosplash'] debug = arguments['--debug'] interactive = arguments['-i'] script = arguments["SCRIPT"] command = arguments["COMMAND"] context = CloudmeshContext( interactive=interactive, debug=debug, echo=echo, splash=splash) cmd = CloudmeshConsole(context) if script is not None: cmd.do_exec(script) try: if echo: print("cm>", command) if command is not None: cmd.precmd(command) stop = cmd.onecmd(command) cmd.postcmd(stop, command) except Exception as e: print("ERROR: executing command '{0}'".format(command)) print(70 * "=") print(e) print(70 * "=") Error.traceback() if interactive or (command is None and script is None): cmd.cmdloop()
def do_key(self, args, arguments): """ :: Usage: key -h | --help key list [--source=db] [--format=FORMAT] key list --source=cloudmesh [--format=FORMAT] key list --source=ssh [--dir=DIR] [--format=FORMAT] key load [--format=FORMAT] key list --source=git [--format=FORMAT] [--username=USERNAME] key add --git [--name=KEYNAME] FILENAME key add --ssh [--name=KEYNAME] key add [--name=KEYNAME] FILENAME key get NAME key default [KEYNAME | --select] key delete (KEYNAME | --select | --all) [--force] key upload [KEYNAME] [--cloud=CLOUD] key map [--cloud=CLOUD] Manages the keys Arguments: SOURCE db, ssh, all KEYNAME The name of a key. For key upload it defaults to the default key name. FORMAT The format of the output (table, json, yaml) FILENAME The filename with full path in which the key is located NAME_ON_CLOUD Typically the name of the keypair on the cloud. Options: --dir=DIR the directory with keys [default: ~/.ssh] --format=FORMAT the format of the output [default: table] --source=SOURCE the source for the keys [default: db] --username=USERNAME the source for the keys [default: none] --name=KEYNAME The name of a key --all delete all keys --force delete the key form the cloud --name_on_cloud=NAME_ON_CLOUD Typically the name of the keypair on the cloud. Description: key list --source=git [--username=USERNAME] lists all keys in git for the specified user. If the name is not specified it is read from cloudmesh.yaml key list --source=ssh [--dir=DIR] [--format=FORMAT] lists all keys in the directory. If the directory is not specified the default will be ~/.ssh key list --source=cloudmesh [--dir=DIR] [--format=FORMAT] lists all keys in cloudmesh.yaml file in the specified directory. dir is by default ~/.cloudmesh key list [--format=FORMAT] list the keys in teh giiven format: json, yaml, table. table is default key list Prints list of keys. NAME of the key can be specified key add [--name=keyname] FILENAME adds the key specifid by the filename to the key database key get NAME Retrieves the key indicated by the NAME parameter from database and prints its fingerprint. key default [NAME] Used to set a key from the key-list as the default key if NAME is given. Otherwise print the current default key key delete NAME deletes a key. In yaml mode it can delete only key that are not saved in the database key rename NAME NEW renames the key from NAME to NEW. """ # pprint(arguments) def _print_dict(d, header=None, format='table'): if format == "json": return json.dumps(d, indent=4) elif format == "yaml": return yaml.dump(d, default_flow_style=False) elif format == "table": return dict_printer( d, order=["name", "comment", "uri", "fingerprint", "source"], output="table", sort_keys=True) else: return d # return dict_printer(d,order=['cm_id, name, fingerprint']) directory = Config.path_expand(arguments["--dir"]) if arguments['list']: _format = arguments['--format'] _source = arguments['--source'] _dir = arguments['--dir'] if arguments['--source'] == 'ssh': try: sshm = SSHKeyManager() sshm.get_from_dir(directory) d = dict(sshm.__keys__) print(_print_dict(d, format=_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem listing keys from ssh") elif arguments['--source'] in ['cm', 'cloudmesh']: try: sshm = SSHKeyManager() m = sshm.get_from_yaml(load_order=directory) d = dict(m.__keys__) print(_print_dict(d, format=_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem listing keys from `{:}`".format( arguments['--source'])) elif arguments['--source'] in ['git']: username = arguments["--username"] # print(username) if username == 'none': conf = ConfigDict("cloudmesh.yaml") username = conf["cloudmesh.github.username"] sshm = SSHKeyManager() try: sshm.get_from_git(username) d = dict(sshm.__keys__) print(_print_dict(d, format=_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem listing git keys from database") return "" elif arguments['--source'] == 'db': try: sshdb = SSHKeyDBManager() d = sshdb.table_dict() if d != {}: print(_print_dict(d, format=arguments['--format'])) msg = "info. OK." Console.ok(msg) else: Console.error("No keys in the database") except Exception as e: Error.traceback(e) Console.error("Problem listing keys from database") elif arguments['load']: _format = arguments['--format'] _dir = arguments['--dir'] try: sshm = SSHKeyManager() m = sshm.get_from_yaml(load_order=directory) d = dict(m.__keys__) sshdb = SSHKeyDBManager() for keyname in m.__keys__: filename = m[keyname]["path"] try: sshdb.add(filename, keyname, source="yaml", uri="file://" + filename) except Exception as e: Console.error("problem adding key {}:{}".format( keyname, filename)) print(_print_dict(d, format=_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Console.error("Problem adding keys from yaml file") elif arguments['get']: try: name = arguments['NAME'] sshdb = SSHKeyDBManager() d = sshdb.table_dict() for i in d: if d[i]["name"] == name: key = d[i] print("{:}: {:}".format(key['name'], key['fingerprint'])) msg = "info. OK." Console.ok(msg) return "" else: pass Console.error("The key is not in the database") except Exception as e: Error.traceback(e) Console.error("The key is not in the database") # key add --git KEYNAME # key add --ssh KEYNAME # key add [--path=PATH] KEYNAME elif arguments['add'] and arguments["--git"]: print('git add') sshdb = SSHKeyDBManager() keyname = arguments['--name'] gitkeyname = arguments['NAME'] filename = arguments['FILENAME'] # Are we adding to the database as well? # sshdb.add(filename, keyname, source="ssh", uri="file://"+filename) username = arguments["--username"] if username == 'none': conf = ConfigDict("cloudmesh.yaml") username = conf["cloudmesh.github.username"] print(username) sshm = SSHKeyManager() try: sshm.get_from_git(username) d = dict(sshm.__keys__) print(d) except Exception as e: Error.traceback(e) Console.error("Problem adding keys to git for user: "******"" try: # FIXME: correct code to add to git d[gitkeyname]['keyname'] = keyname d[gitkeyname]['user'] = None d[gitkeyname]['source'] = 'git' # sshdb.add_from_dict(d[gitkeyname]) except Exception as e: Console.error("The key already exists") elif arguments['add'] and arguments["--ssh"]: # print('ssh add') sshdb = SSHKeyDBManager() keyname = arguments['--name'] filename = Config.path_expand("~/.ssh/id_rsa.pub") try: sshdb.add(filename, keyname, source="ssh", uri="file://" + filename) print("Key {:} successfully added to the database".format( keyname or "")) msg = "info. OK." Console.ok(msg) except Exception as e: """ Error.traceback(e) print (keyname) print (filename) """ Console.error( "Problem adding the key `{}` from file `{}`".format( keyname, filename)) elif arguments['add'] and not arguments["--git"]: # print('ssh add') sshdb = SSHKeyDBManager() keyname = arguments['--name'] filename = arguments['FILENAME'] try: sshdb.add(filename, keyname, source="ssh", uri="file://" + filename) print("Key {:} successfully added to the database".format( keyname or "")) msg = "info. OK." Console.ok(msg) except ValueError as e: Console.error("The key `{}` already exists".format(keyname), traceflag=False) """ except Exception as e: Error.traceback(e) print (keyname) print (filename) Console.error("Problem adding the key `{}` from file `{}`".format(keyname, filename)) """ return "" elif arguments['default']: # print("default") if arguments['KEYNAME']: keyname = None try: keyname = arguments['KEYNAME'] sshdb = SSHKeyDBManager() sshdb.set_default(keyname) Default.set_key(keyname) print("Key {:} set as default".format(keyname)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error( "Setting default for key {:} failed.".format(keyname)) elif arguments['--select']: keyname = None try: sshdb = SSHKeyDBManager() select = sshdb.select() if select != 'q': keyname = select.split(':')[0] print("Setting key: {:} as default.".format(keyname)) sshdb.set_default(keyname) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error( "Setting default for selected key {:} failed.".format( keyname)) else: try: sshdb = SSHKeyDBManager() d = sshdb.table_dict() for i in d: if d[i]["is_default"] == "True": key = d[i] print("{:}: {:}".format(key['name'], key['fingerprint'])) msg = "info. OK." Console.ok(msg) return "" else: pass Console.error("The key is not in the database") except Exception as e: Error.traceback(e) Console.error("Problem retrieving default key.") elif arguments['delete']: delete_on_cloud = arguments["--force"] or False # print ("DDD", delete_on_cloud) if arguments['--all']: try: sshm = SSHKeyManager(delete_on_cloud=delete_on_cloud) sshm.delete_all_keys() print("All keys from the database deleted successfully.") msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem deleting keys") elif arguments['--select']: keyname = None sshdb = SSHKeyDBManager() select = sshdb.select() if select != 'q': try: keyname = select.split(':')[0] print("Deleting key: {:}...".format(keyname)) sshm = SSHKeyManager(delete_on_cloud=delete_on_cloud) sshm.delete_key(keyname) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error( "Problem deleting the key `{:}`".format(keyname)) else: keyname = None try: keyname = arguments['KEYNAME'] sshm = SSHKeyManager(delete_on_cloud=delete_on_cloud) sshm.delete_key(keyname) print("Key {:} deleted successfully from database.".format( keyname)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error( "Problem deleting the key `{:}`".format(keyname)) elif arguments['upload']: try: # # get username # conf = ConfigDict("cloudmesh.yaml") username = conf["cloudmesh"]["profile"]["username"] if username in ['None', 'TBD']: username = None # # get cloudnames # clouds = [] cloud = arguments["--cloud"] or Default.get_cloud() if cloud == "all": config = ConfigDict("cloudmesh.yaml") clouds = config["cloudmesh"]["clouds"] else: clouds.append(cloud) # # get keyname # for cloud in clouds: status = 0 sshdb = SSHKeyDBManager() sshm = SSHKeyManager() keys = sshdb.find_all() for keyid in keys: key = keys[keyid] print("upload key {} -> {}".format(key["name"], cloud)) try: status = sshm.add_key_to_cloud( username, key["name"], cloud, key["name"]) except Exception as e: print(e) if "already exists" in str(e): print("key already exists. Skipping " "upload. ok.") if status == 1: print("Problem uploading key. failed.") msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem adding key to cloud") elif arguments['map']: try: cloud = arguments["--cloud"] or Default.get_cloud() sshm = SSHKeyManager() map_dict = sshm.get_key_cloud_maps(cloud) print( dict_printer(map_dict, order=[ "user", "key_name", "cloud_name", "key_name_on_cloud" ])) except Exception as e: Error.traceback(e) Console.error("Problem adding key to cloud")
def do_key(self, args, arguments): """ :: Usage: key -h | --help key list --cloud=CLOUD key list --source=db [--format=FORMAT] key list --source=yaml [--format=FORMAT] key list --source=ssh [--dir=DIR] [--format=FORMAT] key list --source=git [--format=FORMAT] [--username=USERNAME] key list key load [--format=FORMAT] key add [NAME] [--source=FILENAME] key add [NAME] [--git] key add [NAME] [--ssh] key get NAME key default --select key delete (NAME | --select | --all) key delete NAME --cloud=CLOUD key upload [NAME] [--cloud=CLOUD] key upload [NAME] --active Manages the keys Arguments: CLOUD The cloud NAME The name of the key. SOURCE db, ssh, all KEYNAME The name of a key. For key upload it defaults to the default key name. FORMAT The format of the output (table, json, yaml) FILENAME The filename with full path in which the key is located NAME_ON_CLOUD Typically the name of the keypair on the cloud. Options: --dir=DIR the directory with keys [default: ~/.ssh] --format=FORMAT the format of the output [default: table] --source=SOURCE the source for the keys [default: db] --username=USERNAME the source for the keys [default: none] --name=KEYNAME The name of a key --all delete all keys --force delete the key form the cloud --name_on_cloud=NAME_ON_CLOUD Typically the name of the keypair on the cloud. Description: key list --source=git [--username=USERNAME] lists all keys in git for the specified user. If the name is not specified it is read from cloudmesh.yaml key list --source=ssh [--dir=DIR] [--format=FORMAT] lists all keys in the directory. If the directory is not specified the default will be ~/.ssh key list --source=yaml [--dir=DIR] [--format=FORMAT] lists all keys in cloudmesh.yaml file in the specified directory. dir is by default ~/.cloudmesh key list [--format=FORMAT] list the keys in the giiven format: json, yaml, table. table is default key list Prints list of keys. NAME of the key can be specified key add [--name=keyname] FILENAME adds the key specifid by the filename to the key database key get NAME Retrieves the key indicated by the NAME parameter from database and prints its fingerprint. key default --select Select the default key interactively key delete NAME deletes a key. In yaml mode it can delete only key that are not saved in the database key rename NAME NEW renames the key from NAME to NEW. """ # pprint(arguments) invalid_names = ['tbd', 'none', "", 'id_rsa'] def _print_dict(d, header=None, format='table'): msg = Printer.write( d, order=["name", "comment", "uri", "fingerprint", "source"], output=format, sort_keys=True) if msg is None: Console.error("No keys found.", traceflag=False) return None else: return msg directory = Config.path_expand(arguments["--dir"]) cloud = arguments["--cloud"] or Default.cloud if arguments['list']: _format = arguments['--format'] _source = arguments['--source'] _dir = arguments['--dir'] if "--source" not in arguments and "--cloud" not in arguments: arguments["--source"] = 'db' if arguments['--cloud']: # # get key list from openstack cloud # #keys = Key.list(cloud, output=_format) keys = Key.list_on_cloud(cloud, live=True, format=_format) if keys is None: Console.ok("The Key list is empty") else: print(keys) return "" elif arguments['--source'] == 'ssh': try: #sshm = SSHKeyManager() d = Key.get_from_dir(directory, store=False) #print("SSS", type(Key.__keys__)) #d = dict(Key.all()) #print(d) print( Printer.write(d, order=[ "name", "comment", "uri", "fingerprint", "source" ], output="table")) # d = dict(sshm.__keys__) # print(_print_dict(d, format=_format)) msg = "info. OK." Console.ok(msg) return "" except Exception as e: Error.traceback(e) Console.error("Problem listing keys from ssh") elif arguments['--source'] in ['cm', 'cloudmesh', 'yaml']: try: #sshm = SSHKeyManager() d = Key.get_from_yaml(load_order=directory, store=False) print( Printer.write(d, order=[ "name", "comment", "uri", "fingerprint", "source" ], output=_format)) return "" except Exception as e: Error.traceback(e) Console.error("Problem listing keys from `{:}`".format( arguments['--source'])) elif arguments['--source'] in ['git']: username = arguments["--username"] # print(username) if username == 'none': conf = ConfigDict("cloudmesh.yaml") username = conf["cloudmesh.github.username"] #sshm = SSHKeyManager() try: d = Key.get_from_git(username, store=False) print( Printer.write(d, order=[ "name", "comment", "uri", "fingerprint", "source" ], output=_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem listing git keys from database") return "" elif arguments['--source'] == 'db': try: #sshdb = SSHKeyDBManager() d = Key.all(output='dict') if d is not None or d != []: print( Printer.write(d, order=[ "name", "comment", "uri", "fingerprint", "source" ], output=_format)) # print(_print_dict(d, output=arguments['--format'])) msg = "info. OK." Console.ok(msg) else: Console.error("No keys in the database") except Exception as e: Error.traceback(e) Console.error("Problem listing keys from database") elif arguments['get']: try: name = arguments['NAME'] #sshdb = SSHKeyDBManager() d = Key.all(output="dict") for key in d: if key["name"] == name: print("{:}: {:}".format(key['name'], key['fingerprint'])) msg = "info. OK." Console.ok(msg) return "" else: pass Console.error("The key is not in the database") except Exception as e: Error.traceback(e) Console.error("The key is not in the database") # key add [NAME] [--source=FILENAME] # key add [NAME] [--git] elif arguments['add'] and arguments["--git"]: # Console.error("This feature is not yet implemented", traceflag=False) # return "" print('git add') #sshdb = SSHKeyDBManager() data = dotdict(arguments) keyname = data.NAME # # get name # conf = ConfigDict("cloudmesh.yaml") data.username = conf["cloudmesh.github.username"] data.name = arguments['NAME'] or data.username # # get git username # data.username = ConfigDict( "cloudmesh.yaml")["cloudmesh.github.username"] if str(data.name).lower() in invalid_names: Console.error( "The github user name is not set in the yaml file", traceflag=False) return "" try: Console.msg( "Retrieving github ssh keys for user {username}".format( **data)) #sshm = SSHKeyManager() Key.get_from_git(data.username) d = Key.all() # pprint(d) except Exception as e: Console.error( "Problem adding keys to git for user: {username}".format( **data)) return "" for key in d: if key is not None: key["name"] = key["name"].replace("-", "_") key["source"] = "git" key["user"] = data.name try: o = dict(key) o['value'] = key["string"] Key.add_from_dict(key) except Exception as e: Console.error( "The key {name} with that finger print already exists" .format(**key), traceflag=False) elif arguments['add'] and not arguments["--git"]: # key add [NAME] [--source=FILENAME] # key add [NAME] [--git] #sshdb = SSHKeyDBManager() data = dotdict() # # get name # conf = ConfigDict("cloudmesh.yaml") data.username = conf["cloudmesh.profile.user"] data.name = arguments['NAME'] or data.username data.filename = arguments['--source'] if data.filename == "db" or data.filename is None: data.filename = Config.path_expand("~/.ssh/id_rsa.pub") if str(data.name).lower() in invalid_names: msg = ( "Your choice of keyname {name} is insufficient. \n" "You must be chosing a keyname that is distingct on all clouds. \n" "Possible choices are your gmail name, your XSEDE name, or \n" "some name that is uniqe. " "Best is also to set this name in \n" "cloudmesh.profile.user as " "part of your \n~/cloudmesh/cloudmesh.yaml file.") Console.error(msg.format(**data), traceflag=False) return "" try: Key.add_from_path(data.filename, data.name, source="ssh", uri="file://" + data.filename) print("Key {name} successfully added to the database".format( **data)) msg = "info. OK." Console.ok(msg) except ValueError as e: Console.error( "A key with this fingerprint already exists".format( **data), traceflag=False) Console.msg("Please use check with: key list") return "" elif arguments['default']: # print("default") if arguments['--select']: keyname = None try: #sshdb = SSHKeyDBManager() select = Key.select() if select != 'q': keyname = select.split(':')[0] print("Setting key: {:} as default.".format(keyname)) Default.key = keyname msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error( "Setting default for selected key {:} failed.".format( keyname)) else: try: #sshdb = SSHKeyDBManager() d = Key.table_dict() for i in d: if d[i]["is_default"] == "True": key = d[i] print("{:}: {:}".format(key['name'], key['fingerprint'])) msg = "info. OK." Console.ok(msg) return "" else: pass Console.error("The key is not in the database") except Exception as e: Error.traceback(e) Console.error("Problem retrieving default key.") elif arguments['delete'] and arguments["--cloud"]: key = dotdict({ 'cloud': arguments["--cloud"], 'name': arguments["NAME"] }) try: Key.delete(key.name, key.cloud) msg = "info. OK." Console.ok(msg) except: Console.error( "Problem deleting the key {name} on the cloud {cloud}". format(**key)) elif arguments['delete']: # key delete (NAME | --select| --all) data = dotdict({ 'all': arguments['--all'] or False, 'select': arguments['--select'] or False, 'name': arguments['NAME'] or False, }) pprint(data) # BUG delete all is not properly implemented if data.all: Console.TODO("Delete --all is not yet implemented.") # Key.delete() elif data.select: key = Key.select() print(key) else: # name Key.delete(data.name) msg = "info. OK." Console.ok(msg) elif arguments['upload']: # pprint(arguments) try: # # get username # conf = ConfigDict("cloudmesh.yaml") username = conf["cloudmesh"]["profile"]["user"] if username in ['None', 'TBD']: username = None # # get cloudnames # clouds = [] if arguments["--active"]: cloud = 'active' else: cloud = arguments["--cloud"] or Default.cloud if cloud == "all": config = ConfigDict("cloudmesh.yaml") clouds = config["cloudmesh"]["clouds"] elif cloud == 'active': config = ConfigDict("cloudmesh.yaml") clouds = config["cloudmesh"]["active"] else: clouds.append(cloud) # # get keyname # for cloud in clouds: status = 0 #sshdb = SSHKeyDBManager() #sshm = SSHKeyManager() keys = Key.all() for key in keys: print("upload key {} -> {}".format(key["name"], cloud)) try: status = Key.add_key_to_cloud( username, key["name"], cloud) except Exception as e: Console.error("problem") if "already exists" in str(e): print( "key already exists. Skipping upload. OK.") if status == 1: print("Problem uploading key {} to {}. failed.". format(key["name"], cloud)) except Exception as e: Console.error("Problem adding key to cloud")
def do_reservation(self, args, arguments): """ :: Usage: reservation info --user=USER --project=PROJECT reservation list [--name=NAME] [--user=USER] [--project=PROJECT] [--hosts=HOSTS] [--start=TIME_START] [--end=TIME_END] [--format=FORMAT] reservation delete [all] [--user=USER] [--project=PROJECT] [--name=NAME] [--start=TIME_START] [--end=TIME_END] [--hosts=HOSTS] reservation delete --file=FILE reservation update --name=NAME [--start=TIME_START] [--end=TIME_END] [--user=USER] [--project=PROJECT] [--hosts=HOSTS] [--description=DESCRIPTION] reservation add --name=NAME [--start=TIME_START] [--end=TIME_END] [--user=USER] [--project=PROJECT] [--hosts=HOSTS] [--description=DESCRIPTION] reservation add --file=FILE Arguments: NAME Name of the reservation USER Registration will be done for this user PROJECT Project to be used HOSTS Hosts to reserve TIME_START Start time of reservation TIME_END End time of reservation FORMAT Format of output DESCRIPTION Description for reservation FILE File that contains reservation data to be added/ deleted Options: --name=NAME Names of the reservation --user=USER user name --project=PROJECT project id --start=TIME_START Start time of the reservation, in MM/DD/YYYY at hh:mm aa format. (default value: 01/01/1901 at 12:00 am]) --end=TIME_END End time of the reservation, in MM/DD/YYYY at hh:mm aa format. (default value: 12/31/2100 at 11:59 pm]) --host=HOSTS host name --description=DESCRIPTION description summary of the reservation --file=FILE Adding multiple reservations from one file --format=FORMAT Format is either table, json, yaml or csv [default: table] Description: reservation info lists the resources that support reservation for a given user or project. """ # print (arguments) def _print_dict(d, header=None, format='table'): if format == "json": return json.dumps(d, indent=4) elif format == "yaml": return pyaml.dump(d) elif format == "table": return Printer.write(d, order=[ "id", "name", "start_time", "end_time", "user", "project", "hosts", "description", "cloud" ], output="table", sort_keys=True) elif format == "csv": TODO.implement() else: return d # return Printer.write(d,order=['cm_id, name, fingerprint']) def _get_db_date_format(date): """ Utility Function that accepts instance of Date object and returns a string with Datetime for DB. :param date: Date object :return: Date as string with format expected in DB. """ db_date = "{:}-{:}-{:} {:}:{:}".format( str(date.month).zfill(2), str(date.day).zfill(2), str(date.year).zfill(4), str(date.hour).zfill(2), str(date.minute).zfill(2)) return db_date if arguments["info"]: TODO.implement() elif arguments["list"]: try: _name = arguments['--name'] _user = arguments['--user'] _project = arguments['--project'] _format = arguments['--format'] _hosts = arguments['--hosts'] _start = arguments['--start'] _end = arguments['--end'] _format = arguments['--format'] reserve = Reservation() dictionary = reserve.list(_name, _start, _end, _user, _project, _hosts) print(_print_dict(dictionary, format=_format)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem listing reservations") elif arguments["delete"]: if arguments["all"]: try: reserve = Reservation() reserve.delete() msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem deleting all reservations") else: try: _name = arguments['--name'] _user = arguments['--user'] _project = arguments['--project'] _format = arguments['--format'] _hosts = arguments['--hosts'] _start = arguments['--start'] _end = arguments['--end'] _format = arguments['--format'] reserve = Reservation() reserve.delete(_name, _start, _end, _user, _project, _hosts) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem deleting reservations") elif arguments["add"]: if arguments["--file"] is None: name = None try: name = arguments["--name"] hosts = arguments["--hosts"] user = arguments["--user"] project = arguments["--project"] description = arguments["--description"] start_time = arguments[ "--start"] or "01/01/1901 at 07:30 pm" end_time = arguments["--end"] or "12/31/2100 at 11:59 pm" stime = Date(start_time) etime = Date(end_time) reserve = Reservation() reserve.add(name, _get_db_date_format(stime), _get_db_date_format(etime), hosts=hosts, user=user, project=project, description=description) print("Reservation {:} added successfully".format(name)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error( "Problem adding reservation {:}".format(name)) else: try: TODO.implement() """ with open(os.path.join(sys.path[0], arguments["--file"])) as file: reader = csv.reader(file) for row in reader: reservations = Reservation(cm_id=row[0], label=row[1], user=row[2], project=row[3], start_time=row[4], end_time=row[5], host=row[6], summary=row[7]) db.add() """ except Exception as e: print("Error in adding from file. ", e) elif arguments["update"]: name = None try: name = arguments["--name"] hosts = arguments["--hosts"] user = arguments["--user"] project = arguments["--project"] description = arguments["--description"] start_time = arguments["--start"] or "01/01/1901 at 07:30 pm" end_time = arguments["--end"] or "12/31/2100 at 11:59 pm" stime = Date(start_time) etime = Date(end_time) reserve = Reservation() reserve.update(name, _get_db_date_format(stime), _get_db_date_format(etime), hosts=hosts, user=user, project=project, description=description) print("Reservation {:} updated successfully".format(name)) msg = "info. OK." Console.ok(msg) except Exception as e: Error.traceback(e) Console.error("Problem updating reservation {:}".format(name)) return ""
def main(): """cm. Usage: cm --help cm [--debug] [--nosplash] [-i] [COMMAND ...] Arguments: COMMAND A command to be executed Options: --file=SCRIPT -f SCRIPT Executes the script -i After start keep the shell interactive, otherwise quit [default: False] --nosplash do not show the banner [default: False] """ def manual(): print(main.__doc__) args = sys.argv[1:] arguments = { '--debug': '--debug' in args, '--nosplash': '--nosplash' in args, '-i': '-i' in args} for a in args: if a in arguments: args.remove(a) arguments['COMMAND'] = [' '.join(args)] commands = arguments["COMMAND"] if len(commands) > 0: if ".cm" in commands[0]: arguments["SCRIPT"] = commands[0] commands = commands[1:] else: arguments["SCRIPT"] = None arguments["COMMAND"] = ' '.join(commands) if arguments["COMMAND"] == '': arguments["COMMAND"] = None if arguments['COMMAND'] == []: arguments['COMMAND'] = None splash = not arguments['--nosplash'] debug = arguments['--debug'] interactive = arguments['-i'] script = arguments["SCRIPT"] command = arguments["COMMAND"] context = CloudmeshContext(debug=debug, splash=splash) cmd = CloudmeshConsole(context) if script is not None: cmd.do_exec(script) try: if debug: print(">", command) if command is not None: cmd.onecmd(command) except Exception, e: print("ERROR: executing command '{0}'".format(command)) print(70 * "=") print(e) print(70 * "=") Error.traceback()