def filter_by(cls, **kwargs): """ This method returns either a) an array of objects from the database in dict format, that match a particular kind. If the kind is not specified vm is used. one of the arguments must be scope="all" b) a single entry that matches the first occurance of the query specified by kwargs, such as name="vm_001" :param kwargs: the arguments to be matched, scope defines if all or just the first value is returned. first is default. :return: a list of objects, if scope is first a single object in dotdict format is returned """ scope = kwargs.pop("scope", "all") result = [] for t in cls.tables: part = cls.session.query(t).filter_by(**kwargs) result.extend(cls.to_list(part)) objects = result if scope == "first" and objects is not None: objects = dotdict(result[0]) return objects
def stop(cls, **kwargs): arg = dotdict(kwargs) cloud_provider = CloudProvider(arg.cloud).provider for server in kwargs["servers"]: cloud_provider.stop_vm(server) Console.ok("Machine {:} is being stopped on {:} Cloud..." .format(server, cloud_provider.cloud))
def convert(line): entry = (' '.join(line.split())).split(' ') data = dotdict() data.id = entry[0] data.name = entry[1] data.provider = entry[2] data.state = entry[3] data.directory = entry[4] return data
def convert(line): line = line.replace("(", "") line = line.replace(")", "") line = line.replace(",", "") entry = line.split(" ") data = dotdict() data.name = entry[0] data.provider = entry[1] data.date = entry[2] return data
def boot_from_args(arg): arg.username = arg.username or Image.guess_username(arg.image) is_name_provided = arg.name is not None arg.user = Default.user for index in range(0, arg.count): vm_details = dotdict({ "cloud": arg.cloud, "name": Vm.get_vm_name(arg.name, index), "image": arg.image, "flavor": arg.flavor, "key": arg.key, "secgroup": arg.secgroup, "group": arg.group, "username": arg.username, "user": arg.user }) # correct the username vm_details.username = Image.guess_username_from_category( vm_details.cloud, vm_details.image, username=arg.username) try: if arg.dryrun: print(Printer.attribute(vm_details, output=arg.format)) msg = "dryrun info. OK." Console.ok(msg) else: vm_id = Vm.boot(**vm_details) if vm_id is None: msg = "info. failed." Console.error(msg, traceflag=False) return "" # set name and counter in defaults Default.set_vm(value=vm_details.name) if is_name_provided is False: Default.incr_counter("name") # Add to group if vm_id is not None: Group.add(name=vm_details.group, species="vm", member=vm_details.name, category=vm_details.cloud) msg = "info. OK." Console.ok(msg) except Exception as e: Console.error("Problem booting instance {name}".format(**vm_details), traceflag=False)
def create(cls, **kwargs): arg = dotdict(kwargs) if not os.path.exists(arg.name): os.makedirs(arg.name) config = cls.vagrantfile(**kwargs) with open('{name}/Vagrantfile'.format(**arg), 'w') as f: f.write(config)
def set(cls, name, attribute, value, provider=None, kind=None, scope="all" ): if scope == "first" and provider is None: elements = cls.filter_by(name=name, kind=kind)[0] # pprint(elements) o = dotdict(elements) # print("PPPP", kind, name, attribute, value, o) if o[attribute] != value: cls.update(kind=o["kind"], provider=o["provider"], filter={'name': name}, update={attribute: value} ) elif scope == "first": o = dotdict(cls.filter_by(name=name, provider=provider, kind=kind)[0]) # print("PPPP", provider, kind, name, attribute, value, o) if o[attribute] != value: cls.update(kind=o["kind"], provider=o["provider"], filter={'name': name}, update={attribute: value} ) elif provider is None or kind is None or scope == "all": o = cls.filter_by(name=name) cls.update(kind=o["kind"], provider=o["provider"], filter={'name': name}, update={attribute: value} ) else: Console.error("Problem setting attributes")
def set(cls, name, attribute, value, provider=None, kind=None, scope="all" ): if scope == "first" and provider is None: elements = cls.filter_by(name=name, kind=kind)[0] # pprint(elements) o = dotdict(elements) # print("PPPP", kind, name, attribute, value, o) if o[attribute] != value: cls.update(kind=o["kind"], provider=o["provider"], filter={'name': name}, update={attribute: value} ) elif scope == "first": o = dotdict(cls.filter_by(name=name, provider=provider, kind=kind)[0]) # print("PPPP", provider, kind, name, attribute, value, o) if o[attribute] != value: cls.update(kind=o["kind"], provider=o["provider"], filter={'name': name}, update={attribute: value} ) elif provider is None or kind is None or scope == "all": o = cls.filter_by(name=name) cls.update(kind=o["kind"], provider=o["provider"], filter={'name': name}, update={attribute: value} ) else: Console.error("Problem setting attributes")
def defaults(): """ default values :return: a number of default values for memory, image, and script :rtype: dotdict """ d = dotdict() d.memory = 1024 # d.image = "ubuntu/xenial64" d.image = "ubuntu/trusty64" d.port = 8080 d.script = None return d
def defaults(): """ default values :return: a number of default values for memory, image, and script :rtype: dotdict """ d = dotdict() d.memory = 1024 # d.image = "ubuntu/xenial64" d.image = "ubuntu/trusty64" d.port = 8080 d.script = None return d
def do_info(self, args, arguments): """ :: Usage: info [--cloud=CLOUD] [--format=FORMAT] Options: --format=FORMAT the output format [default: table] --cloud=CLOUD the cloud name Examples: cm info """ arg = dotdict(arguments) arg.cloud = arguments["--cloud"] or Default.cloud arg.FORMAT = arguments["--format"] or "table" d = { "cloud": arg.cloud, "key": Default.key, "user": Default.user, "vm": Default.vm, "group": Default.group, "secgroup": Default.secgroup, "counter": Default.get_counter(name="name"), "image": Default.get_image(category=arg.cloud), "flavor": Default.get_flavor(category=arg.cloud), "refresh": str(Default.refresh), "debug": str(Default.debug), "interactive": str(Default.interactive), "purge": str(Default.purge), } order = [ "cloud", "key", "user", "vm", "group", "secgroup", "counter", "image", "flavor", "refresh", "debug", "interactive", "purge" ] print( Printer.attribute(d, order=order, output=arg.FORMAT, sort_keys=False)) if d["key"] in ["TBD", ""] or d["user"] in ["TBD", ""]: msg = "Please replace the TBD values" msg = msg + "\nSee Also: \n\n" \ + " cm register profile \n" \ + " cm default user=YOURUSERNAME\n" Console.error(msg, traceflag=False) return ""
def list(cls, group=None, name=None, category='general', output='table', scope='all'): """ This method queries the database to fetch list of secgroups filtered by cloud. :param cloud: :return: """ query = dotdict({ "kind": "secgrouprule", "scope": "all" }) if category is "general": if group is not None: query.group = group if name is not None: query.name = name query.category = category elements = cls.cm.find(**query) else: elements = CloudProvider(category).provider.list_secgroup_rules(category) if elements is None: return None else: # pprint(elements) # # BUG this should not depend on cloud, but on "general" # # (order, header) = CloudProvider(cloud).get_attributes("secgroup") order = ['name', 'group', 'fromPort', 'toPort', 'cidr', 'protocol'] header = None return Printer.write(elements, order=order, header=header, output=output)
def list(cls, group=None, name=None, category='general', output='table', scope='all'): """ This method queries the database to fetch list of secgroups filtered by cloud. :param cloud: :return: """ query = dotdict({ "kind": "secgrouprule", "scope": "all" }) if category is "general": if group is not None: query.group = group if name is not None: query.name = name query.category = category elements = cls.cm.find(**query) else: elements = CloudProvider(category).provider.list_secgroup_rules(category) if elements is None: return None else: # pprint(elements) # # BUG this should not depend on cloud, but on "general" # # (order, header) = CloudProvider(cloud).get_attributes("secgroup") order = ['name', 'group', 'fromPort', 'toPort', 'cidr', 'protocol'] header = None return Printer.write(elements, order=order, header=header, output=output)
class Test_script: """tests script command""" data = dotdict({"cloud": Default.cloud, "group": "mygroup"}) def run(self, command): command = command.format(**self.data) banner(command, c="-") print(command) parameter = command.split(" ") shell_command = parameter[0] args = parameter[1:] result = Shell.execute(shell_command, args) print(result) return str(result) def setup(self): self.scripts = [ ("bash.cm", "README.rst"), ("comment.cm", "/* test"), ("var.cm", "username"), ("py.cm", "2"), ("terminal.cm", ""), # ("hpc.cm", "bravo"), ("key.cm", ""), ("reservedemo.cm", "cloudnauts"), # ("cloud.cm", "Active"), # ("nova.cm", "Status"), # ("demo.cm", "ephemeral_disk"), # BROKEN: # ("group.cm", ""), # ("sync.cm", ""), # ("secgroup.cm", ""), # ("cluster.cm", ""), # ("vm.cm", ""), # ("network.cm", ""), ] pass # noinspection PyPep8Naming def tearDown(self): pass def test_001(self): HEADING("cm script set india") for self.data["script"], self.data["check"] in self.scripts: result = self.run("cm scripts/{script}") assert self.data["check"] in result
def do_hadoop(self, arg, arguments): """ :: Usage: hadoop start [-f NAME] [-i NAME] [-u NAME] [COUNT] [ADDON]... hadoop list hadoop switch NAME hadoop delete [-a] [NAME]... Arguments: COUNT ADDON NAME Options: -a --all -f --flavor=NAME -i --image=NAME -u --username=NAME """ arguments = dotdict(arguments) cmd = Command() if arguments.start: cmd.start( count=arguments.COUNT or 3, addons=arguments.ADDON, flavor=arguments['--flavor'], image=arguments['--image'], username=arguments['--username'], ) elif arguments.list: cmd.list() elif arguments.switch: cmd.switch(arguments.NAME) elif arguments.delete: cmd.delete(arguments.NAME, all=arguments['--all'])
def rename(cls, **kwargs): arg = dotdict(kwargs) cloud_provider = CloudProvider(kwargs["cloud"]).provider # Check for vms with duplicate names in DB. vms = cls.get_vms_by_name(name=arg.oldname, cloud=arg.cloud) if len(vms) > 1: users_choice = "y" if not arg.force: print("More than 1 vms found with the same name as {}." .format(server)) users_choice = input( "Would you like to auto-order the new names? (y/n): ") if users_choice.strip() == "y": count = 1 for index in vms: count_new_name = "{0}{1}".format(arg.newname, count) # print(vms[index]) cloud_provider.rename_vm(vms[index]["uuid"], count_new_name) print( "Machine {0} with UUID {1} renamed to {2} on {3} cloud" .format(vms[index]["name"], vms[index]["uuid"], count_new_name, cloud_provider.cloud)) count += 1 elif users_choice.strip() == "n": cloud_provider.rename_vm(arg.oldname, arg.newname) print( "Machine {0} renamed to {1} on {2} Cloud..." .format(arg.oldname, arg.newname, cloud_provider.cloud)) else: Console.error("Invalid Choice.") return else: cloud_provider.rename_vm(arg.oldname, arg.newname) print("Machine {0} renamed to {1} on {2} Cloud..." .format(arg.oldname, arg.newname, cloud_provider.cloud)) # Explicit refresh called after VM rename, to update db. cls.refresh(cloud=arg.cloud)
def do_info(self, args, arguments): """ :: Usage: info [--cloud=CLOUD] [--format=FORMAT] Options: --format=FORMAT the output format [default: table] --cloud=CLOUD the cloud name Examples: cm info """ arg = dotdict(arguments) arg.cloud = arguments["--cloud"] or Default.cloud arg.FORMAT = arguments["--format"] or "table" d = { "cloud": arg.cloud, "key": Default.key, "user": Default.user, "vm": Default.vm, "group": Default.group, "secgroup": Default.secgroup, "counter": Default.get_counter(name="name"), "image": Default.get_image(category=arg.cloud), "flavor": Default.get_flavor(category=arg.cloud), "refresh": str(Default.refresh), "debug": str(Default.debug), "interactive": str(Default.interactive), "purge": str(Default.purge), } order = ["cloud", "key", "user", "vm", "group", "secgroup", "counter", "image", "flavor", "refresh", "debug", "interactive", "purge"] print(Printer.attribute(d, order=order, output=arg.FORMAT, sort_keys=False)) if d["key"] in ["TBD", ""] or d["user"] in ["TBD", ""]: msg = "Please replace the TBD values" msg = msg + "\nSee Also: \n\n" \ + " cm register profile \n" \ + " cm default user=YOURUSERNAME\n" Console.error(msg, traceflag=False) return ""
def rename(cls, **kwargs): arg = dotdict(kwargs) cloud_provider = CloudProvider(kwargs["cloud"]).provider # Check for vms with duplicate names in DB. vms = cls.get_vms_by_name(name=arg.oldname, cloud=arg.cloud) if len(vms) > 1: users_choice = "y" if not arg.force: print("More than 1 vms found with the same name as {}.".format( server)) users_choice = input( "Would you like to auto-order the new names? (y/n): ") if users_choice.strip() == "y": count = 1 for index in vms: count_new_name = "{0}{1}".format(arg.newname, count) # print(vms[index]) cloud_provider.rename_vm(vms[index]["uuid"], count_new_name) print( "Machine {0} with UUID {1} renamed to {2} on {3} cloud" .format(vms[index]["name"], vms[index]["uuid"], count_new_name, cloud_provider.cloud)) count += 1 elif users_choice.strip() == "n": cloud_provider.rename_vm(arg.oldname, arg.newname) print("Machine {0} renamed to {1} on {2} Cloud...".format( arg.oldname, arg.newname, cloud_provider.cloud)) else: Console.error("Invalid Choice.") return else: cloud_provider.rename_vm(arg.oldname, arg.newname) print("Machine {0} renamed to {1} on {2} Cloud...".format( arg.oldname, arg.newname, cloud_provider.cloud)) # Explicit refresh called after VM rename, to update db. cls.refresh(cloud=arg.cloud)
def do_deploy(self, args, arguments): """ :: Usage: deploy ansible role [-c CLUSTER] [-u NAME] [-N] [-H HOST] [-b] URI... Commands: ansible Ansible deployment Ansible Commands: playbook Deploy a pre-prepared playbook role Deploy a role to all nodes Arguments: CLUSTER Cluster name to deploy to NAME Alphanumeric name COUNT Integer > 0 URI Location of the item as a uri HOST Host matching pattern Options: -c --cluster=CLUSTER Cluster name to operate on (defaults to active) -N --no-modify-known-hosts Don't let ssh update ~/.ssh/known_hosts -u --username=NAME Username of the nodes to manage -H HOST --hosts=HOST Host matching pattern [default: all] -b --no-become Don't become privileged user """ arguments = dotdict(arguments) from pprint import pprint pprint(arguments) if arguments.ansible and arguments.role: ansible = AnsibleCommand() ansible.role( cluster = arguments.CLUSTER, hostsPattern = arguments['--hosts'], uris = arguments.URI, become = not arguments['--no-become'], username = arguments['--username'], modifyKnownHosts = not arguments['--no-modify-known-hosts'], )
def do_load(self, args, arguments): """ :: Usage: load MODULE [PYPI] ARGUMENTS: MODULE The name of the module PREDEFINED MODULE NAMES: vbox loads vbox command Examples: cm load cloudmesh_vagrant.cm_vbox.do_vbox lists the plugins currently loaded """ arg = dotdict(arguments) # importlib.import_module('matplotlib.text') plugins = ConfigDict(filename="cloudmesh.yaml") if arg.MODULE == "vbox": arg.MODULE = "cloudmesh_vagrant.cm_vbox.do_vbox" arg.PYPI = "cloudmesh_vagrant" if arg.PYPI is not None: try: import cloudmesh_vagrant except: os.system("pip install cloudmesh_vagrant") try: print("LOADING ->", arg.MODULE) self.load_instancemethod(arg.MODULE) except: Console.error("Problem loading module {}".format(arg.MODULE), traceflag=True) return ""
def do_load(self, args, arguments): """ :: Usage: load MODULE [PYPI] ARGUMENTS: MODULE The name of the module PREDEFINED MODULE NAMES: vbox loads vbox command Examples: cm load cloudmesh_vagrant.cm_vbox.do_vbox lists the plugins currently loaded """ arg = dotdict(arguments) # importlib.import_module('matplotlib.text') plugins = ConfigDict(filename="cloudmesh.yaml") if arg.MODULE == "vbox": arg.MODULE = "cloudmesh_vagrant.cm_vbox.do_vbox" arg.PYPI = "cloudmesh_vagrant" if arg.PYPI is not None: try: import cloudmesh_vagrant except: os.system("pip install cloudmesh_vagrant") try: print("LOADING ->", arg.MODULE) self.load_instancemethod(arg.MODULE) except: Console.error("Problem loading module {}".format(arg.MODULE), traceflag=True) return ""
class Test_aws_API: data = dotdict({ "cloud": Default.cloud, "format": "json", "user": "******", "wrong_cloud": "no_cloud", "key": "my_default_key", "value": "my_default_value" }) def run(self, command): command = command.format(**self.data) banner(command, c="-") print(command) parameter = command.split(" ") shell_command = parameter[0] args = parameter[1:] result = Shell.execute(shell_command, args) print(result) return str(result) def setup(self): pass # noinspection PyPep8Naming def tearDown(self): pass def test_001(self): HEADING("aws API") cloudname = 'aws' d = ConfigDict("cloudmesh.yaml") cloud_details = d["cloudmesh"]["clouds"][cloudname] cp = CloudProviderAwsAPI(cloudname, cloud_details) #pprint(cp.list_flavor(cloudname)) # pprint(cp.list_image(cloudname)) pprint(cp.list_vm(cloudname))
def add(cls, name=None, species="vm", member=None, category=None): """ Add an instance to a new group or add it to an existing one :param name: :param species: :param member: :param cloud: :return: """ # user logged into cloudmesh #user = ConfigDict.getUser(category) or cls.cm.user user = cls.cm.user category = category or "general" try: # See if group already exists. If yes, add id to the group data = dotdict({ 'member': member, 'name': name, 'kind': 'group', 'provider': 'general' }) group = cls.cm.find(**data) if group is None: t = cls.cm.table(provider="general", kind="group") group = t(name=name, member=member, category="general", user=user, species=species ) cls.cm.add(group, replace=False) return except Exception as ex: Console.error(ex.message) return
class Test_quota: """ This class tests the QuotaCommand """ data = dotdict({ "cloud": Default.cloud, "format": "csv", "wrong_cloud": "no_cloud" }) def run(self, command): command = command.format(**self.data) banner(command, c="-") print(command) parameter = command.split(" ") shell_command = parameter[0] args = parameter[1:] result = Shell.execute(shell_command, args) print(result) return str(result) def setup(self): pass # noinspection PyPep8Naming def tearDown(self): pass def test_001(self): HEADING("test quota list") result = self.run("cm quota list") assert "Quota" in result def test_002(self): HEADING("test quota list with csv output") result = self.run("cm quota list --cloud={cloud} --format={format}") assert "ram" in result def test_003(self): HEADING("test quota class where cloud doesnt exist") result = self.run("cm quota list --cloud={wrong_cloud}") assert "is not defined in the yaml file" in result
class Test_hpc: """ This class tests the HpcCommand """ # noinspection PyTypeChecker data = dotdict({ "cluster": "comet", }) def run(self, command): command = command.format(**self.data) banner(command, c="-") print(command) parameter = command.split(" ") shell_command = parameter[0] args = parameter[1:] result = Shell.execute(shell_command, args) print(result) return str(result) # noinspection PyPep8Naming def tearDown(self): pass def setup(self): HEADING("set default cluster") result = self.run("cm default cluster={cluster}") assert "{cluster}".format(**self.data) in result def test_001(self): HEADING("test hpc info") result = self.run("cm hpc info --cluster={cluster}") assert "{cluster}".format(**self.data) in result def test_002(self): HEADING("test hpc queue ") result = self.run("cm hpc queue --cluster={cluster}") assert "{cluster}".format(**self.data) in result def test_003(self): HEADING(" test hpc status ") result = self.run("cm hpc status --cluster={cluster}") assert "{cluster}".format(**self.data) in result
def add(cls, name=None, species="vm", member=None, category=None): """ Add an instance to a new group or add it to an existing one :param name: :param species: :param member: :param cloud: :return: """ # user logged into cloudmesh #user = ConfigDict.getUser(category) or cls.cm.user user = cls.cm.user category = category or "general" try: # See if group already exists. If yes, add id to the group data = dotdict({ 'member': member, 'name': name, 'kind': 'group', 'provider': 'general' }) group = cls.cm.find(**data) if group is None: t = cls.cm.table(provider="general", kind="group") group = t(name=name, member=member, category="general", user=user, species=species) cls.cm.add(group, replace=False) return except Exception as ex: Console.error(ex.message) return
def do_setup(self, args, arguments): """ :: Usage: setup Examples: cm setup """ arg = dotdict(arguments) #if Default.key in ["TBD", ""] or Default.user in ["TBD", ""]: os.system("cm register profile") os.system("cm reset") os.system("cm key add --ssh") os.system("cm info") return ""
def do_setup(self, args, arguments): """ :: Usage: setup Examples: cm setup """ arg = dotdict(arguments) #if Default.key in ["TBD", ""] or Default.user in ["TBD", ""]: os.system ("cm register profile") os.system ("cm reset") os.system ("cm key add --ssh") os.system ("cm info") return ""
def _find(cls, scope='all', provider=None, kind=None, output='dict', table=None, **kwargs ): """ find (category="openstack", kind="vm", name="vm_002") find (VM_OPENSTACK, kind="vm", name="vm_002") # do not use this one its only used internally :param category: :param kind: :param table: :param kwargs: :return: """ t = table if table is None: if provider is None and kind is None: Console.error("No provider or kind specified in find") else: t = cls.table(provider=provider, kind=kind) elements = cls.session.query(t).filter_by(**kwargs) if scope == 'first': result = elements.first() if result is None: return None if output == 'dict': result = dotdict(cls.to_list([result])[0]) elif output == 'dict': result = cls.to_list(elements) elif output == 'namedict': result = cls.to_dict(elements) return result
def _find(cls, scope='all', provider=None, kind=None, output='dict', table=None, **kwargs ): """ find (category="openstack", kind="vm", name="vm_002") find (VM_OPENSTACK, kind="vm", name="vm_002") # do not use this one its only used internally :param category: :param kind: :param table: :param kwargs: :return: """ t = table if table is None: if provider is None and kind is None: Console.error("No provider or kind specified in find") else: t = cls.table(provider=provider, kind=kind) elements = cls.session.query(t).filter_by(**kwargs) if scope == 'first': result = elements.first() if result is None: return None if output == 'dict': result = dotdict(cls.to_list([result])[0]) elif output == 'dict': result = cls.to_list(elements) elif output == 'namedict': result = cls.to_dict(elements) return result
def boot(cls, **kwargs): arg = dotdict(kwargs) arg.cwd = kwargs.get("cwd", None) vms = cls.to_dict(cls.list()) if arg.name in vms: Console.error("vm {name} already booted".format(**arg), traceflag=False) return None # print result else: cls.create(**kwargs) Console.ok("{name} created".format(**arg)) Console.ok("{name} booting ...".format(**arg)) result = Shell.execute("vagrant", ["up", arg.name], cwd=arg.name) Console.ok("{name} ok.".format(**arg)) return result
def vagrantfile(cls, **kwargs): arg = dotdict(kwargs) provision = kwargs.get("script", None) if provision is not None: arg.provision = 'config.vm.provision "shell", inline: <<-SHELL\n' for line in textwrap.dedent(provision).split("\n"): if line.strip() != "": arg.provision += 12 * " " + " " + line + "\n" arg.provision += 12 * " " + " " + "SHELL\n" else: arg.provision = "" # the 12 is derived from the indentation of Vagrant in the script script = textwrap.dedent(""" Vagrant.configure(2) do |config| config.vm.define "{name}" config.vm.hostname = "{name}" config.vm.box = "{image}" config.vm.box_check_update = true config.vm.network "forwarded_port", guest: 80, host: {port} config.vm.network "private_network", type: "dhcp" # config.vm.network "public_network" # config.vm.synced_folder "../data", "/vagrant_data" config.vm.provider "virtualbox" do |vb| # vb.gui = true vb.memory = "{memory}" end {provision} end """.format(**arg)) return script
def do_info(self, args, arguments): """ :: Usage: info [--cloud=CLOUD] [--format=FORMAT] Options: --format=FORMAT the output format [default: table] --cloud=CLOUD the cloud name Examples: cm info """ arg = dotdict(arguments) arg.cloud = arguments["--cloud"] or Default.cloud arg.FORMAT = arguments["--format"] or "table" d = { "cloud": arg.cloud, "key": Default.key, "user": Default.user, "vm": Default.vm, "group": Default.group, "secgroup": Default.secgroup, "counter": Default.get_counter(name="name"), "image": Default.get_image(category=arg.cloud), "flavor": Default.get_flavor(category=arg.cloud), "refresh": str(Default.refresh), "debug": str(Default.debug), "interactive": str(Default.interactive), "purge": str(Default.purge), } order = ["cloud", "key", "user", "vm", "group", "secgroup", "counter", "image", "flavor", "refresh", "debug", "interactive", "purge"] print(Printer.attribute(d, order=order, output=arg.FORMAT, sort_keys=False)) return ""
def boot(cls, **kwargs): arg = dotdict(kwargs) arg.cwd = kwargs.get("cwd", None) vms = cls.to_dict(cls.list()) if arg.name in vms: Console.error("vm {name} already booted".format(**arg), traceflag=False) return None # print result else: cls.create(**kwargs) Console.ok("{name} created".format(**arg)) Console.ok("{name} booting ...".format(**arg)) result = Shell.execute("vagrant", ["up", arg.name], cwd=arg.name) Console.ok("{name} ok.".format(**arg)) return result
class Test_base: """ This class tests the FlavorCommand """ # noinspection PyTypeChecker data = dotdict({ "cloud": Default.cloud, }) def run(self, command): command = command.format(**self.data) banner(command, c="-") print(command) parameter = command.split(" ") shell_command = parameter[0] args = parameter[1:] result = Shell.execute(shell_command, args) print(result) return str(result) def setup(self): pass # noinspection PyPep8Naming def tearDown(self): pass def test_001(self): HEADING("test flavor refresh") result = self.run("cm default cloud={cloud}") assert "ok" in result def test_002(self): HEADING("get default cloud") result = self.run("cm default cloud") print(result)
def vagrantfile(cls, **kwargs): arg = dotdict(kwargs) provision = kwargs.get("script", None) if provision is not None: arg.provision = 'config.vm.provision "shell", inline: <<-SHELL\n' for line in textwrap.dedent(provision).split("\n"): if line.strip() != "": arg.provision += 12 * " " + " " + line + "\n" arg.provision += 12 * " " + " " + "SHELL\n" else: arg.provision = "" # the 12 is derived from the indentation of Vagrant in the script script = textwrap.dedent(""" Vagrant.configure(2) do |config| config.vm.define "{name}" config.vm.hostname = "{name}" config.vm.box = "{image}" config.vm.box_check_update = true config.vm.network "forwarded_port", guest: 80, host: {port} config.vm.network "private_network", type: "dhcp" # config.vm.network "public_network" # config.vm.synced_folder "../data", "/vagrant_data" config.vm.provider "virtualbox" do |vb| # vb.gui = true vb.memory = "{memory}" end {provision} end """.format(**arg)) return script
def find(cls, **kwargs): """ This method returns either a) an array of objects from the database in dict format, that match a particular kind. If the kind is not specified vm is used. one of the arguments must be scope="all" b) a single entry that matches the first occurance of the query specified by kwargs, such as name="vm_001" :param kwargs: the arguments to be matched, scope defines if all or just the first value is returned. first is default. :return: a list of objects, if scope is first a single object in dotdict format is returned """ scope = kwargs.pop("scope", "all") output = kwargs.pop("output", "dict") table = kwargs.pop("table", None) result = [] if table is not None: part = cls.session.query(table).filter_by(**kwargs) result.extend(cls.to_list(part)) else: category = kwargs.get("category", None) provider = kwargs.get("provider", None) kind = kwargs.get("kind", None) if provider is not None and kind is not None: t = cls.table(provider, kind) part = cls.session.query(t).filter_by(**kwargs) if output == 'dict': result.extend(cls.to_list(part)) else: result.extend(part) elif provider is None: for t in cls.tables: # print ("CCCC", t.__kind__, t.__provider__, kwargs) if (t.__kind__ == kind): part = cls.session.query(t).filter_by(**kwargs) if output == 'dict': result.extend(cls.to_list(part)) else: result.extend(part) else: Console.error("nothing searched {}".format(kwargs)) objects = result ''' if len(objects) == 0 and scope == "first": objects = None elif len(objects) != 0: if scope == "first": if output == 'dict': objects = dotdict(result[0]) else: objects = result[0] ''' if len(objects) == 0: return None elif scope == "first": if output == 'dict': objects = dotdict(result[0]) else: objects = result[0] return objects
def do_vc(self, args, arguments): """ :: Usage: vc key add KEYFILE NAMES [--username=USERNAME] [--proxy=PROXY] vc key distribute NAMES [--username=USERNAME] [--proxy=PROXY] vc key list NAMES [--usort] [--username=USERNAME] [--proxy=PROXY] [--format=FORMAT] vc key proxy NAMES [--username=USERNAME] [--proxy=PROXY] Options: --format=FORMAT the output format [default: table] Description: see examples Examples: cm vc key add keys.txt gregor-[001-010] adds the keys in the file keys.txt to the authorized_keys file in the user that is registered for the vm cm vc key add keys.txt gregor-[001-010] --username=ubuntu adds the keys in the file keys.txt to the authorized_keys file in the user ubuntu for each of the vms vc key distribute gregor-[001-010] gathers the keys from the host gathers it into a single file and adds them to the authorized keys file. Duplicated keys will be ignored. vc key list gregor-[001-010] [--usort] creates a table with all keys in authorized_keys from all of the remote machines. If the parameter usort is specified it only lists the key once, but lists in the host column the list of all host on which the key is stored Proxy server vc key proxy NAMES sometimes you may not have enough floating IPs so it is possible to dedicate one machine as a proxy server that has such a floating ip. The way this is done is that you need to set up ssh tunnels via the proxy server in your .ssh/config file. The command will print a template that you could include in your .ssh/config file to gain easily access to your other machines without floating ip. For example it will generate the following for a given PROXY host, USERNAME, and vm1 is the name of the first vm in NAMES Host vm1 User USERNAME Hostname PROXY ProxyCommand ssh 10.1.1.2 nc %h %p ForwardX11 yes Note: this is just a draft and will be improved upon discussion with the team """ arg = dotdict(arguments) arg.usort = arguments["--usort"] arg.format = arguments["--format"] arg.username = arguments["--username"] arg.proxy = arguments["--proxy"] if arg.NAMES is not None: arg.names = Parameter.expand(arg.NAMES) else: arg.names = None pprint (arg) if arg.add: print("vc key add KEYFILE NAMES --username=USERNAME") print(arg.username) print(arg.names) print(arg.KEYFILE) print(arg.proxy) Console.TODO("not yet implemented") return "" elif arg.distribute: print("vc key distribute NAMES --username=USERNAME") print(arg.names) print(arg.username) print(arg.proxy) Console.TODO("not yet implemented") return "" elif arg.list: print("vc key list NAMES [--usort] [--format=FORMAT]") print(arg.names) print(arg.username) print(arg.format) print(arg.usort) print(arg.proxy) result = Vc.list(names=arg.names) # dont forget format and sort Console.TODO("not yet implemented") return "" elif arg.proxy: print("vc key proxy NAMES [--username=USERNAME] [--proxy=PROXY]") print(arg.names) print(arg.username) print(arg.format) print(arg.usort) print(arg.proxy) result = Vc.list(names=arg.names) # dont forget format and sort Console.TODO("not yet implemented") return ""
def find_new(cls, **kwargs): """ This method returns either a) an array of objects from the database in dict format, that match a particular kind. If the kind is not specified vm is used. one of the arguments must be scope="all" b) a single entry that matches the first occurance of the query specified by kwargs, such as name="vm_001" :param kwargs: the arguments to be matched, scope defines if all or just the first value is returned. first is default. :return: a list of objects, if scope is first a single object in dotdict format is returned """ """ parameters: output="dict" key="name" output: name1: element["name"] attribute ... name2: .... parameters: output="dict" key="id" output: "0": index in the list of elements attribute ... "1": .... parameters: output="list" key="id" output: [element0, element1, element2] each of which is a dot dict other things scope = "first" -> one elemnet only as dotdict (not an list) scope = "all" -> any of the above but each element is a dotdict returns either list or dict find -> list to_dict(list, key="name") to_dict(find(...), key="name") - dict of dotdicts <-- or None if we do not find ??? too complex to implement, find(...).dict(key="name") - dict of dotdicts Default.purge = True -> when delete vm it deletes vm from db, if not keep the vm Vm.names -> list names of all vms in db if newvmname in Vm.names: error vm already exists cls.replace cls.add -> cls.upsert just keep add for now but introduce new upser that just calls current add? or do refactor on add and replaces with upsert """ scope = kwargs.pop("scope", "all") output = kwargs.pop("output", "dict") table = kwargs.pop("table", None) result = [] if table is not None: part = cls.session.query(table).filter_by(**kwargs) result.extend(cls.to_list(part)) else: category = kwargs.get("category", None) provider = kwargs.get("provider", None) kind = kwargs.get("kind", None) if provider is not None and kind is not None: t = cls.table(provider, kind) part = cls.session.query(t).filter_by(**kwargs) if output == 'dict': result.extend(cls.to_list(part)) else: result.extend(part) elif provider is None: for t in cls.tables: # print ("CCCC", t.__kind__, t.__provider__, kwargs) if (t.__kind__ == kind): part = cls.session.query(t).filter_by(**kwargs) if output == 'dict': result.extend(cls.to_list(part)) else: result.extend(part) else: Console.error("nothing searched {}".format(kwargs)) objects = result if len(objects) == 0: return None elif scope == "first": if output == 'dict': objects = dotdict(result[0]) else: objects = result[0] return objects
def do_cluster(self, args, arguments): """ :: Usage: cluster define [-n NAME] [-c COUNT] [-C CLOUD] [-u NAME] [-i IMAGE] [-f FLAVOR] [-k KEY] [-s NAME] [-AI] cluster undefine [--all] [NAME]... cluster avail cluster use <NAME> cluster allocate cluster cross_ssh cluster list cluster nodes [CLUSTER] cluster delete [--all] [--force] [NAME]... cluster get [-n NAME] PROPERTY cluster inventory [-F NAME] [-o PATH] [NAME] Commands: define Create a cluster specification undefine Delete the active or given specifications avail Show available cluster specifications use Activate the specification with the given name allocate Create a cluster from the active specification nodes Show the nodes of the cluster list List the available clusters inventory Obtain an inventory file delete Delete clusters and associated instances get Get properties of a cluster/nodes in a cluster Arguments: NAME Alphanumeric name COUNT Integer > 0 PATH Path to entry on the filesystem Options: -A --no-activate Don't activate this cluster -I --no-floating-ip Don't assign floating IPs -n NAME --name=NAME Name of the cluster -c COUNT --count=COUNT Number of nodes in the cluster -C NAME --cloud=NAME Name of the cloud -u NAME --username=NAME Name of the image login user -i NAME --image=NAME Name of the image -f NAME --flavor=NAME Name of the flavor -k NAME --key=NAME Name of the key -s NAME --secgroup=NAME NAME of the security group -F NAME --format=NAME Name of the output format -o PATH --path=PATH Output to this path --force --all Inventory File Format: ansible [default] Ansible-compatible inventory """ arguments = dotdict(arguments) cmd = Command() if arguments.define: cmd.define( clustername = arguments['--name'], count=arguments['--count'] or 1, cloud=arguments['--cloud'] or Default.cloud, username=arguments['--username'], image=arguments['--image'] or Default.image, flavor=arguments['--flavor'] or Default.flavor, key=arguments['--key'] or Default.key, secgroup=arguments['--secgroup'] or Default.secgroup, assignFloatingIP=not arguments['--no-floating-ip'], ) elif arguments.undefine: if arguments['NAME']: for specname in arguments['NAME']: cmd.undefine(specname=specname, all=arguments['--all']) else: cmd.undefine(all=arguments['--all']) elif arguments.avail: cmd.avail() elif arguments.use: cmd.use(arguments['<NAME>']) elif arguments.allocate: cmd.allocate() elif arguments.cross_ssh: cmd.cross_ssh() elif arguments.list: try: active, inactive = cmd.list() except NoActiveClusterException: return def show(cluster, isactive=False, stream=sys.stdout): if not cluster: return if isactive: stream.write('> ') else: stream.write(' ') stream.write(cluster.name) stream.write('\n') stream.flush() show(active, isactive=True) map(show, inactive) elif arguments.nodes: nodes = cmd.nodes(cluster=arguments['CLUSTER']) for node in nodes: print(node.name, node.floating_ip) elif arguments.delete: cmd.delete( arguments.NAME, force=arguments['--force'], all=arguments['--all'] ) elif arguments['get']: values = cmd.get(arguments['PROPERTY'], cluster=arguments['--name']) for v in values: print(v) elif arguments.inventory: cmd.inventory( cluster=arguments.NAME, format=arguments['--format'], path=arguments['--path'], )
def boot(cls, **kwargs): arg = dotdict(kwargs) for a in ["key", "name", "image", "flavor"]: if a not in kwargs: raise ValueError(a + " not in arguments to vm boot") conf = ConfigDict("cloudmesh.yaml") arg.user = arg.user or conf["cloudmesh"]["profile"]["user"] arg.group = arg.group or Default.group cloud_provider = CloudProvider(arg.cloud).provider if "nics" in arg: nics = arg.nics else: nics = None basic_dict = { "cloud": arg.cloud, "name": arg.name, "image": arg.image, "flavor": arg.flavor, "key": arg.key, "secgroup": [arg.secgroup], "nics": nics, "meta": { 'kind': 'cloudmesh', 'group': arg.group, 'cluster': arg.get('cluster', None), 'image': arg.image, 'flavor': arg.flavor, 'key': arg.key, 'category': arg.cloud } } # Special case for Azure where certificate details needs to be added if arg.cloud == "azure": kwargs = dict() kwargs['kind'] = "key_azure" db_result = cls.cm.find(**kwargs) # pprint("Key DB results") key_result = None try: for key in db_result: if key['name'] == arg.key: pprint("Found the key") key_result = key break if key_result is not None: new_dict_items = dict() new_dict_items['cert_thumbprint'] = key_result[ 'fingerprint'] new_dict_items['pub_key_path'] = key_result['key_path'] new_dict_items['cert_path'] = key_result['certificate'] new_dict_items['pfx_path'] = key_result['pfx_path'] basic_dict.update(new_dict_items) else: pprint("None found in DB") except: traceback.print_exc() pprint("Exception while processing azure boot arguments") d = dotdict(basic_dict) Console.ok( "Machine {name} is being booted on cloud {cloud} ...".format( **arg)) print(Printer.attribute(d)) vm = cloud_provider.boot_vm(**d) if vm is not None: cls.refresh(cloud=arg.cloud) try: # TODO: Repair db schema for vm_azure, vm_libcloud, # vm_openstack. The following set only works with # openstack, no libcloud, no azure cls.cm.set(d.name, "key", d.key, scope="first", kind="vm") cls.cm.set(d.name, "image", d.image, scope="first", kind="vm") cls.cm.set(d.name, "flavor", d.flavor, scope="first", kind="vm") cls.cm.set(d.name, "group", arg.group, scope="first", kind="vm") cls.cm.set(d.name, "user", arg.user, scope="first", kind="vm") cls.cm.set(d.name, 'username', arg.username, scope='first', kind='vm') cls.cm.set(d.name, 'cluster', arg.cluster, scope='first', kind='vm') except: # cm.set error is identified as a warning, not an error import sys Console.warning("cls.cm.set error: %s" % (sys.exc_info()[0])) # update group and key # # cls.cm.update("vm", name=data.name) return vm
def do_launcher(self, args, arguments): """ :: Usage: launcher repo add NAME URL launcher repo delete NAME launcher repo list launcher repo launcher list [NAMES] [--cloud=CLOUD] [--format=FORMAT] [--source=db|dir] launcher add NAME SOURCE launcher delete [NAMES] [--cloud=CLOUD] launcher clear launcher run [NAME] launcher resume [NAME] launcher suspend [NAME] launcher refresh launcher log [NAME] launcher status [NAME] Arguments: KEY the name of the launcher Options: --cloud=CLOUD the name of the cloud --format=FORMAT the output format [launcher: table] --all lists all the launcher values Description: Launcher is a command line tool to test the portal launch functionalities through command line. The current launcher values can by listed with --all option:( if you have a launcher cloud specified. You can also add a cloud parameter to apply the command to a specific cloud) launcher list A launcher can be deleted with launcher delete KEY Examples: launcher list --all launcher list --cloud=general launcher delete <KEY> """ print("AAA") arg = dotdict(arguments) if arg.NAMES is not None: arg.names = Parameter.expand(arg.NAMES) else: arg.names = None if arg.name == ["all"]: arg.names = None arg.cloud = arguments["--cloud"] or Default.cloud arg.output = arguments['--format'] or 'table' arg.source = arguments['--source'] or 'db' print("BBB") pprint(arg) # arg.cloud = arguments["--cloud"] or Default.cloud # c = arg.list # print ("Hallo {cloud} is list={list}".format(**arg)) # launcher = Launcher(kind=None) if arg.cloud is None: Console.error("Default arg.cloud not set") return result = "" if arguments["repo"] and arguments["list"]: print("repo list") launchers = ConfigDict( filename="cm_launcher.yaml")["cloudmesh"]["repo"] print("repo add") d = {} for name in launchers: location = launchers[name]["location"] d[name] = {"name": name, "location": location} print(Printer.dict_table(d)) return "" elif arguments["repo"] and arguments["add"]: launchers = ConfigDict(filename="cm_launcher.yaml") print("repo add") print(launchers) return "" elif arguments["repo"] and arguments["delete"]: print("repo delete") return "" elif arguments["repo"] and not arguments["list"]: print(arg.names) result = Launcher.list(name=arg.names, output=arg.output) elif arguments["add"]: result = Launcher.add(name=arg.NAME, source=arg.SOURCE) elif arguments["delete"]: # if arg.name is not None: # result = Launcher.delete(name=arg.name, category=arg.cloud) # else: # result = Launcher.delete(name=None) for name in arg.names: result = Launcher.delete(name=name, category=arg.cloud) elif arguments["run"]: result = Launcher.run() elif arguments["resume"]: result = Launcher.resume(name=arg.name) elif arguments["suspend"]: result = Launcher.suspend(name=arg.name) elif arguments["details"]: result = Launcher.details(name=arg.name) elif arguments["clear"]: result = Launcher.clear() elif arguments["refresh"]: result = Launcher.refresh(name=arg.name) print(result)
def do_workflow(self, args, arguments): """ :: Usage: workflow refresh [--cloud=CLOUD] [-v] workflow list [ID] [--cloud=CLOUD] [--format=FORMAT] [--refresh] [-v] workflow add NAME LOCATION workflow delete NAMES workflow status [NAMES] workflow show NAMES This lists out the workflows present for a cloud Options: --format=FORMAT the output format [default: table] --cloud=CLOUD the cloud name --refresh refreshes the data before displaying it from the cloud Examples: cm workflow refresh cm workflow list cm workflow list --format=csv cm workflow show 58c9552c-8d93-42c0-9dea-5f48d90a3188 --refresh """ arg = dotdict(arguments) if arg.NAMES is not None: arg.names = Parameter.expand(arg.NAMES) else: arg.names = None pprint (arg) cloud = arguments["--cloud"] or Default.cloud if cloud is None: Console.error("Default cloud doesn't exist") return if arguments["-v"]: print("Cloud: {}".format(cloud)) if arguments["refresh"] or Default.refresh: msg = "Refresh workflow for cloud {:}.".format(cloud) if Workflow.refresh(cloud): Console.ok("{:} ok".format(msg)) else: Console.error("{:} failed".format(msg)) return "" if arguments["list"]: id = arguments['ID'] live = arguments['--refresh'] output_format = arguments["--format"] counter = 0 result = None while counter < 2: if id is None: result = Workflow.list(cloud, output_format) else: result = Workflow.details(cloud, id, live, output_format) if counter == 0 and result is None: if not Workflow.refresh(cloud): msg = "Refresh workflow for cloud {:}.".format(cloud) Console.error("{:} failed.".format(msg)) counter += 1 if result is None: Console.error("No workflow(s) found. Failed.") else: print(result) return "" elif arguments["show"]: Console.ok("I executed show")
def do_vm(self, args, arguments): """ :: Usage: vm default [--cloud=CLOUD][--format=FORMAT] vm refresh [all][--cloud=CLOUD] vm boot [--name=NAME] [--cloud=CLOUD] [--username=USERNAME] [--image=IMAGE] [--flavor=FLAVOR] [--group=GROUP] [--public] [--secgroup=SECGROUP] [--key=KEY] [--dryrun] vm boot [--n=COUNT] [--cloud=CLOUD] [--username=USERNAME] [--image=IMAGE] [--flavor=FLAVOR] [--group=GROUP] [--public] [--secgroup=SECGROUP] [--key=KEY] [--dryrun] vm ping [NAME] [N] vm console [NAME] [--group=GROUP] [--cloud=CLOUD] [--force] vm start [NAMES] [--group=GROUP] [--cloud=CLOUD] [--force] vm stop [NAMES] [--group=GROUP] [--cloud=CLOUD] [--force] vm terminate [NAMES] [--group=GROUP] [--cloud=CLOUD] [--force] vm delete [NAMES] [--group=GROUP] [--cloud=CLOUD] [--keep] [--dryrun] vm ip assign [NAMES] [--cloud=CLOUD] vm ip show [NAMES] [--group=GROUP] [--cloud=CLOUD] [--format=FORMAT] [--refresh] vm ip inventory [NAMES] [--header=HEADER] [--file=FILE] vm ssh [NAME] [--username=USER] [--quiet] [--ip=IP] [--cloud=CLOUD] [--key=KEY] [--command=COMMAND] vm rename [OLDNAMES] [NEWNAMES] [--force] [--dryrun] vm list [NAMES] [--cloud=CLOUDS|--active] [--group=GROUP] [--format=FORMAT] [--refresh] vm status [NAMES] vm wait [--cloud=CLOUD] [--interval=SECONDS] vm info [--cloud=CLOUD] [--format=FORMAT] vm check NAME vm username USERNAME [NAMES] [--cloud=CLOUD] 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. NAMES server name. By default it is set to the name of last vm from database. KEYPAIR_NAME Name of the openstack keypair to be used to create VM. Note this is not a path to key. NEWNAMES New names of the VM while renaming. OLDNAMES Old names of the VM while renaming. Options: --username=USERNAME the username to login into the vm. If not specified it will be guessed from the image name and the cloud --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 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 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 rename/ delete vms without user's confirmation --command=COMMAND specify the commands to be executed Description: commands used to boot, start or delete servers of a cloud vm default [options...] Displays default parameters that are set for vm boot either on the default cloud or the specified cloud. 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 ssh [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'] Quoting commands: cm vm login gvonlasz-004 --command=\"uname -a\" """ """ # terminate # issues a termination to the cloud, keeps vm in database # delete # issues a terminate if not already done # (remember you do not have to go to cloud if state is already terminated) # deletes the vm from database # # bulk rename rename abc[0-1] def[3-4] renames the abc0,abc1 -> def3,def4 if arguments["rename"]: oldnames = Parameter.expand(arguments["OLDNAME"]) newnames = Parameter.expand(arguments["NEWNAME"]) # check if new names ar not already taken # to be implemented if len(oldnames) == len(newnames): for i in range(0, len(oldnames)): oldname = oldnames[i] newname = newnames[i] if newname is None or newname == '': print("New node name cannot be empty") else: print(Cluster.rename_node(clusterid, oldname, newname)) """ cm = CloudmeshDatabase() def _print_dict(d, header=None, output='table'): return Printer.write(d, order=["id", "name", "status"], output=output, sort_keys=True) def _print_dict_ip(d, header=None, output='table'): return Printer.write(d, order=["network", "version", "addr"], output=output, sort_keys=True) def get_vm_name(name=None, offset=0, fill=3): if name is None: count = Default.get_counter(name='name') + offset prefix = Default.user if prefix is None or count is None: Console.error("Prefix and Count could not be retrieved correctly.", traceflag=False) return name = prefix + "-" + str(count).zfill(fill) return name def _refresh_cloud(cloud): try: msg = "Refresh VMs for cloud {:}.".format(cloud) if Vm.refresh(cloud=cloud): Console.ok("{:} OK.".format(msg)) else: Console.error("{:} failed".format(msg), traceflag=False) except Exception as e: Console.error("Problem running VM refresh", traceflag=False) def _get_vm_names(): vm_list = cm.find(kind="vm") vms = [vm["name"] for vm in vm_list] names = pattern = arguments["NAMES"] if pattern is not None: if "*" in pattern: names = search(vms, pattern) else: names = Parameter.expand(names) if names == ['last'] or names is None: names == [Default.vm] return vm_list, names cloud = arguments["--cloud"] or Default.cloud config = ConfigDict("cloudmesh.yaml") active_clouds = config["cloudmesh"]["active"] def _refresh(cloud): all = arguments["all"] or None if all is None: _refresh_cloud(cloud) else: for cloud in active_clouds: _refresh_cloud(cloud) arg = dotdict(arguments) arg.cloud = arguments["--cloud"] or Default.cloud arg.image = arguments["--image"] or Default.get(name="image", category=arg.cloud) arg.flavor = arguments["--flavor"] or Default.get(name="flavor", category=arg.cloud) arg.group = arguments["--group"] or Default.group arg.secgroup = arguments["--secgroup"] or Default.secgroup arg.key = arguments["--key"] or Default.key arg.dryrun = arguments["--dryrun"] arg.name = arguments["--name"] arg.format = arguments["--format"] or 'table' arg.refresh = Default.refresh or arguments["--refresh"] arg.count = int(arguments["--n"] or 1) arg.dryrun = arguments["--dryrun"] arg.verbose = not arguments["--quiet"] # # in many cases use NAMES # if arg.NAMES is not None: # arg.names = Parameter.expand(arg.NAMES) # gvonlasz[001-002] gives ["gvonlasz-001", "gvonlasz-002"] # else: # arg.names = None # if arguments["boot"]: arg.username = arguments["--username"] or Image.guess_username(arg.image) is_name_provided = arg.name is not None arg.user = Default.user for index in range(0, arg.count): vm_details = dotdict({ "cloud": arg.cloud, "name": get_vm_name(arg.name, index), "image": arg.image, "flavor": arg.flavor, "key": arg.key, "secgroup": arg.secgroup, "group": arg.group, "username": arg.username, "user": arg.user }) # correct the username vm_details.username = Image.guess_username_from_category( vm_details.cloud, vm_details.image, username=arg.username) try: if arg.dryrun: print(Printer.attribute(vm_details, output=arg.format)) msg = "dryrun info. OK." Console.ok(msg) else: vm_id = Vm.boot(**vm_details) if vm_id is None: msg = "info. failed." Console.error(msg, traceflag=False) return "" # set name and counter in defaults Default.set_vm(value=vm_details.name) if is_name_provided is False: Default.incr_counter("name") # Add to group if vm_id is not None: Group.add(name=vm_details.group, species="vm", member=vm_details.name, category=vm_details.cloud) msg = "info. OK." Console.ok(msg) except Exception as e: Console.error("Problem booting instance {name}".format(**vm_details), traceflag=False) elif arguments["username"]: arg.username = arguments["--username"] or Image.guess_username(arg.image) cloud = arg.cloud username = arg.USERNAME if arg.NAMES is None: names = [Default.vm] else: names = Parameter.expand(arg.NAMES) if len(names) == 0: return for name in names: arg.name = name Console.ok("Set username for {cloud}:{name} to {USERNAME}".format(**arg)) Vm.set_login_user(name=name, cloud=cloud, username=username) elif arguments["default"]: try: count = Default.get_counter() prefix = Username() if prefix is None or count is None: Console.error("Prefix and Count could not be retrieved correctly.", traceflag=False) return vm_name = prefix + "-" + str(count).zfill(3) arg = { "name": vm_name, "cloud": arguments["--cloud"] or Default.cloud } for attribute in ["image", "flavor"]: arg[attribute] = Default.get(name=attribute, category=cloud) for attribute in ["key", "group", "secgroup"]: arg[attribute] = Default.get(name=attribute, category='general') output = arguments["--format"] or "table" print(Printer.attribute(arg, output=output)) 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", traceflag=False) elif arguments["ping"]: try: if arguments["NAME"] is None and arguments["N"] is None: name = arguments["NAME"] or Default.vm n = arguments["N"] or 1 elif arguments["NAME"].isdigit(): n = arguments["NAME"] name = Default.vm else: name = arguments["NAME"] or Default.vm n = arguments["N"] or 1 print("Ping:", name, str(n)) vm = dotdict(Vm.list(name=name, category=cloud, output="dict")["dict"]) ip = vm.floating_ip result = Shell.ping(host=ip, count=n) print(result) except Exception as e: Console.error(e.message, traceflag=False) elif arguments["console"]: try: name = arguments["NAME"] or Default.vm vm = dotdict(Vm.list(name=name, category=cloud, output="dict")["dict"]) cloud_provider = CloudProvider(cloud).provider vm_list = cloud_provider.list_console(vm.uuid) print(vm_list) msg = "info. OK." Console.ok(msg) except Exception as e: # Error.traceback(e) Console.error("Problem retrieving status of the VM", traceflag=False) elif arguments["status"]: try: cloud_provider = CloudProvider(cloud).provider vm_list = cloud_provider.list_vm(cloud) vms = [vm_list[i]["name"] for i in vm_list ] print ("V", vms) pattern = arguments["NAMES"] if pattern is not None: if "*" in pattern: print ("serach") names = search(vms, pattern) else: names = Parameter.expand() for i in vm_list: if vm_list[i]["name"] in names: print("{} {}".format(vm_list[i]["status"], vm_list[i]["name"])) else: print("{} {}".format(vm_list[0]["status"], vm_list[0]["name"])) except Exception as e: # Error.traceback(e) Console.error("Problem retrieving status of the VM", traceflag=True) elif arguments["wait"]: interval = arguments["--interval"] or 5 try: cloud_provider = CloudProvider(cloud).provider for i in range(1,10): vm_list = cloud_provider.list_vm(cloud) time.sleep(float(1)) d = {} for id in vm_list: vm = vm_list[id] d[vm["name"]] = vm["status"] print (d) print("{} {}".format(vm_list[0]["status"], vm_list[0]["name"])) if vm_list[0]["status"] in ['ACTIVE']: return except Exception as e: # Error.traceback(e) Console.error("Problem retrieving status of the VM", traceflag=True) 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(Printer.attribute(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", traceflag=False) elif arguments["check"]: test = {} try: names = Parameter.expand(arguments["NAME"]) id = 0 for name in names: print("Not implemented: {}".format(name)) # TODO: check the status of the vms status = "active" # TODO: check if they have a floating ip # TODO: get ip floating_ip = "127.0.0.1" ip = True # ping # TODO: ping the machine with the shell command ping = True # check if one can login and run a command check = False try: r = Shell.execute("uname", "-a") # do a real check check = True except: check = False test[name] = { "id": id, "name": name, "status": status, "ip": ip, "ping": ping, "login": check } id += 1 pprint(test) print(Printer.write(test, order=["id", "name", "status", "ip", "ping", "login"], output="table", sort_keys=True)) msg = "not yet implemented. failed." Console.error(msg, traceflag=False) except Exception as e: # Error.traceback(e) Console.error("Problem retrieving status of the VM", traceflag=False) elif arguments["start"]: try: servers = Parameter.expand(arguments["NAMES"]) # If names not provided, take the last vm from DB. if len(servers) == 0: last_vm = Default.vm if last_vm is None: Console.error("No VM records in database. Please run vm refresh.", traceflag=False) 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.", traceflag=False) 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", traceflag=False) elif arguments["stop"]: try: servers = Parameter.expand(arguments["NAMES"]) # If names not provided, take the last vm from DB. if servers is None or len(servers) == 0: last_vm = Default.vm if last_vm is None: Console.error("No VM records in database. Please run vm refresh.", traceflag=False) 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.", traceflag=False) 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", traceflag=False) elif arguments["refresh"]: _refresh(cloud) elif arguments["delete"]: dryrun = arguments["--dryrun"] group = arguments["--group"] force = not arguments["--keep"] cloud = arguments["--cloud"] vms, servers = _get_vm_names() if servers in [None, []]: Console.error("No vms found.", traceflag=False) return "" for server in servers: if dryrun: Console.ok("Dryrun: delete {}".format(server)) else: Vm.delete(servers=[server], force=force) return "" elif arguments["ip"] and arguments["assign"]: if arguments["NAMES"] is None: names = [Default.vm] else: names = Parameter.expand(arguments["NAMES"]) for name in names: # ip = Network.get_floatingip(....) vm = dotdict(Vm.list(name=name, category=cloud, output="dict")["dict"]) if vm.floating_ip is None: Console.ok("Assign IP to {}".format(name)) try: floating_ip = Network.find_assign_floating_ip(cloudname=cloud, instance_id=name) Vm.refresh(cloud=cloud) if floating_ip is not None: print( "Floating IP assigned to {:} is {:}".format( name, floating_ip)) msg = "info. OK." Console.ok(msg) except Exception as e: Console.error("Problem assigning floating ips.", traceflag=False) else: Console.error("VM {} already has a floating ip: {}".format(name, vm.floating_ip), traceflag=False) elif arguments["ip"] and arguments["inventory"]: vms, names = _get_vm_names() if names in [None, []]: if str(Default.vm) in ['None', None]: Console.error("The default vm is not set.", traceflag=False) return "" else: names = [Default.vm] header = arguments["--header"] or "[servers]" filename = arguments["--file"] or "inventory.txt" try: vm_ips = [] for vm in vms: if vm["name"] in names: print (vm["name"]) vm_ips.append(vm["floating_ip"]) result = header + "\n" result += '\n'.join(vm_ips) Console.ok("Creating inventory file: {}".format(filename)) Console.ok(result) with open(filename, 'w') as f: f.write(result) except Exception as e: Console.error("Problem getting ip addresses for instance", traceflag=True) elif arguments["ip"] and arguments["show"]: if arguments["NAMES"] is None: if str(Default.vm) in ['None', None]: Console.error("The default vm is not set.", traceflag=False) return "" else: names = [Default.vm] else: names = Parameter.expand(arguments["NAMES"]) group = arguments["--group"] output_format = arguments["--format"] or "table" refresh = arguments["--refresh"] try: ips = Ip.list(cloud=arg.cloud, output=output_format, names=names) print(ips) except Exception as e: Console.error("Problem getting ip addresses for instance", traceflag=False) elif arguments["ssh"]: def _print(msg): if arg.verbose: Console.msg(msg) chameleon = "chameleon" in ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["clouds"][arg.cloud][ "cm_host"] if chameleon: arg.username = "******" elif arg.cloud == "azure": arg.username = ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["clouds"]["azure"]["default"]["username"] else: if arg.username is None: Console.error("Could not guess the username of the vm", traceflag=False) return arg.username = arguments["--username"] or Image.guess_username(arg.image) arg.command = arguments["--command"] data = dotdict({ 'name': arguments["NAME"] or Default.vm, 'username': arg.username, 'cloud': arg.cloud, 'command': arg.command }) _print("login {cloud}:{username}@{name}".format(**data)) vm = Vm.get(data.name, category=data.cloud) Vm.set_login_user(name=data.name, cloud=data.cloud, username=data.username) data.floating_ip = vm.floating_ip data.key = arguments["--key"] or Default.key _print(Printer.attribute(data)) ''' if vm.username is None: user_from_db = Vm.get_login_user(vm.name, vm.cloud) user_suggest = user_from_db or Default.user username = input("Username (Default: {}):".format(user_suggest)) or user_suggest Vm.set_login_user(name=data.name, cloud=cloud, username=data.username) ''' ip = arguments["--ip"] commands = arguments["--command"] ip_addresses = [] cloud_provider = CloudProvider(cloud).provider ip_addr = cloud_provider.get_ips(vm.name) ipaddr_dict = Vm.construct_ip_dict(ip_addr, cloud) for entry in ipaddr_dict: ip_addresses.append(ipaddr_dict[entry]["addr"]) if len(ip_addresses) > 0: if ip is not None: if ip not in ip_addresses: Console.error("IP Address specified does not match with the host.", traceflag=False) 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: # Evading ping test, as ping is not enabled for VMs on Azure cloud # 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("Unable to connect to the machine") return "" else: _print("IP to be used is: {:}".format(ip)) # # TODO: is this correctly implemented # if not cloud == 'azure': SecGroup.enable_ssh(cloud=cloud) if arg.verbose: Console.info("Connecting to Instance at IP:" + format(ip)) # Constructing the ssh command to connect to the machine. sshcommand = "ssh" if arg.key is not None: sshcommand += " -i {:}".format(arg.key) sshcommand += " -o StrictHostKeyChecking=no" sshcommand += " {:}@{:}".format(data.username, ip) if commands is not None: sshcommand += " \"{:}\"".format(commands) # print(sshcommand) os.system(sshcommand) else: Console.error("No Public IPs found for the instance", traceflag=False) elif arguments["list"]: # groups = Group.list(output="dict") arg = dotdict(arguments) arg.names = arguments["NAMES"] arg.group = arguments["--group"] if arg.group is None: arg.group = [] else: arg.group = Parameter.expand(arguments["--group"]) arg.refresh = arguments["--refresh"] or Default.refresh if arg.NAMES is not None: arg.names = Parameter.expand(arguments["NAMES"]) else: arg.names = ["all"] _format = arguments["--format"] or "table" if arguments["--active"]: clouds = active_clouds else: if arguments["--cloud"]: clouds = Parameter.expand(arguments["--cloud"]) else: clouds = [Default.cloud] try: d = ConfigDict("cloudmesh.yaml") for cloud in clouds: if arg.refresh: _refresh(cloud) Console.ok("Listing VMs on Cloud: {:}".format(cloud)) vms = Vm.list(category=cloud, output="raw") # print ("XXX", type(vms), vms) if vms is None: break result = [] if "all" in arg.names: if result is None: result = [] else: result = vms elif arg.group is not None and len(arg.group) > 0: for vm in vms: if vm["group"] in arg.group: result.append(vm) elif arg.names is not None and len(arg.names) > 0: for vm in vms: if vm["name"] in arg.names: result.append(vm) if len(result) > 0: # print(result) (order, header) = CloudProvider(cloud).get_attributes("vm") print(Printer.write(result, order=order, output=_format) ) else: Console.error("No data found with requested parameters.", traceflag=False) except Exception as e: # Error.traceback(e) Console.error("Problem listing all instances", traceflag=False) elif arguments["rename"]: try: oldnames = Parameter.expand(arguments["OLDNAMES"]) newnames = Parameter.expand(arguments["NEWNAMES"]) force = arguments["--force"] if oldnames is None or newnames is None: Console.error("Wrong VMs specified for rename", traceflag=False) elif len(oldnames) != len(newnames): Console.error("The number of VMs to be renamed is wrong", traceflat=False) else: for i in range(0, len(oldnames)): oldname = oldnames[i] newname = newnames[i] if arguments["--dryrun"]: Console.ok("Rename {} to {}".format(oldname, newname)) else: Vm.rename(cloud=cloud, oldname=oldname, newname=newname, force=force ) msg = "info. OK." Console.ok(msg) except Exception as e: # Error.traceback(e) Console.error("Problem deleting instances", traceflag=False) return ""
def do_workflow(self, args, arguments): """ :: Usage: workflow refresh [--cloud=CLOUD] [-v] workflow list [ID] [NAME] [--cloud=CLOUD] [--format=FORMAT] [--refresh] [-v] workflow add NAME LOCATION workflow delete ID workflow status [NAMES] workflow show ID workflow save NAME WORKFLOWSTR workflow run NAME workflow service start workflow service stop This lists out the workflows present for a cloud Options: --format=FORMAT the output format [default: table] --cloud=CLOUD the cloud name --refresh refreshes the data before displaying it from the cloud Examples: cm workflow refresh cm workflow list cm workflow list --format=csv cm workflow show 58c9552c-8d93-42c0-9dea-5f48d90a3188 --refresh cm workflow run workflow1 """ arg = dotdict(arguments) if arg.NAMES is not None: arg.names = Parameter.expand(arg.NAMES) else: arg.names = None pprint (arg) cloud = arguments["--cloud"] or Default.cloud if cloud is None: Console.error("Default cloud doesn't exist") return if arguments["-v"]: print("Cloud: {}".format(cloud)) if arguments["refresh"] or Default.refresh: msg = "Refresh workflow for cloud {:}.".format(cloud) if Workflow.refresh(cloud): Console.ok("{:} ok".format(msg)) else: Console.error("{:} failed".format(msg)) return "" if arguments["list"]: id = arguments['ID'] live = arguments['--refresh'] output_format = arguments["--format"] result = None if id is None: result = Workflow.list(cloud, output_format) else: result = Workflow.details(cloud, id, live, output_format) if result is None: Console.error("No workflow(s) found. Failed.") else: print(result) return "" elif arguments["show"]: workflow_id = arguments["ID"] Console.ok("I executed show") # Console.msg(workflow_id) if workflow_id is None: Console.msg("Please enter a Workflow Id to execute workflow") else: result = Workflow.run(cloud,workflow_id) # print (result) if result is None: Console.msg("Use workflow list to view existing workflows or do workflow save to save a new one") else: # Console.msg(result) # Console.msg(result[0]) Console.msg(result[0]['workflow_str']) # entry_point(result[0]['workflow_str']) Console.msg("All Set to execute") elif arguments["save"]: workflow_name = arguments["NAME"] workflow_str = arguments["WORKFLOWSTR"] result = Workflow.save(cloud=cloud, name=workflow_name, str=workflow_str) if result is not None: Console.ok(result) else: Console.error("Failed to save workflow!") elif arguments["run"]: Console.msg("Execute Run") workflow_name = arguments["NAME"] # cm_id = arguments["ID"] result = Workflow.run(cloud,name=workflow_name) elif arguments["delete"]: workflow_id = arguments["ID"] result = Workflow.delete(cloud,workflow_id) if result is not None: Console.msg(result) else: Console.error("Failed to save workflow!") elif arguments["service"] and arguments["start"]: # Console.msg() # mkdir -pf ~/.cloudmesh/workflow pass
def do_admin(self, args, arguments): """ :: Usage: admin [db|rest] start admin [db|rest] stop admin db backup admin db reset admin status Description: db start starts the database service db stop stops the database service db backup creates abackup of the database db reset resets the database Arguments: FILE a file name Options: -f specify the file """ arguments = dotdict(arguments) print(arguments) if arguments.db and arguments.stop: print("PLEASE stop db") m = Mongo() m.stop() elif arguments.db and arguments.start: print("PLEASE start db") m = Mongo() m.start() elif arguments.rest and arguments.start: print("PLEASE start rest") # m = Eve() # m.start() elif arguments.rest and arguments.stop: print("PLEASE stop rest") # m = Eve() # m.stop() elif arguments.start: m = Mongo() r = m.start() print(r) # start mong, start eve pass elif arguments.stop: m = Mongo() r = m.stop() print(r) # stop eve pass elif arguments.status: m = Mongo() r = m.status() print(r)
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
class Test_reservation: data = dotdict({ "cloud": Default.cloud, "json": "json", "yaml": "yaml", "user": "******", "name": "test_name", "project": "cloudmesh", "wrong_cloud": "no_cloud", "category": Default.cloud }) def run(self, command): command = command.format(**self.data) banner(command, c="-") print(command) parameter = command.split(" ") shell_command = parameter[0] args = parameter[1:] result = Shell.execute(shell_command, args) print(result) return str(result) def setup(self): pass # noinspection PyPep8Naming def tearDown(self): pass def test_001(self): HEADING("cm reservation add --name=test " "--start='10/31/1988\ at\ 8:09\ pm' " "--end='10/21/2015\ at\ 9:00\ pm' " "--user=albert --project=cloudmesh " "--hosts=host001 --description=desc") result = self.run("cm reservation add --name={name} " "--start='10/31/1988\ at\ 8:09\ pm' " "--end='10/21/2015\ at\ 9:00\ pm' " "--user={user} --project={project}") assert "OK." in result def test_002(self): HEADING("cm reservation list") result = self.run("cm reservation list") assert "OK." in result def test_003(self): HEADING("cm reservation list --user=albert") result = self.run("cm reservation list --user={user}") assert "OK." in result def test_004(self): HEADING("cm reservation list --user=albert --format=json") result = self.run("cm reservation list --user={user} --format={json}") assert "OK." in result def test_005(self): HEADING("cm reservation list --user=albert --format=yaml") result = self.run("cm reservation list --user={user} --format={yaml}") assert "OK." in result def test_006(self): HEADING( "cm reservation update --name=test_name --project=another_proj") result = self.run( "cm reservation update --name={name} --project=another_proj") assert "OK." in result def test_007(self): HEADING("cm reservation delete --name=test_name") result = self.run("cm reservation delete --name={name}") assert "OK." in result def test_008(self): HEADING("cm reservation delete all") result = self.run("cm reservation delete all") assert "OK." in result
def do_workflow(self, args, arguments): """ :: Usage: workflow refresh [--cloud=CLOUD] [-v] workflow list [ID] [NAME] [--cloud=CLOUD] [--format=FORMAT] [--refresh] [-v] workflow add NAME LOCATION workflow delete ID workflow status [NAMES] workflow show ID workflow save NAME WORKFLOWSTR workflow run NAME workflow service start workflow service stop This lists out the workflows present for a cloud Options: --format=FORMAT the output format [default: table] --cloud=CLOUD the cloud name --refresh refreshes the data before displaying it from the cloud Examples: cm workflow refresh cm workflow list cm workflow list --format=csv cm workflow show 58c9552c-8d93-42c0-9dea-5f48d90a3188 --refresh cm workflow run workflow1 """ arg = dotdict(arguments) if arg.NAMES is not None: arg.names = Parameter.expand(arg.NAMES) else: arg.names = None pprint(arg) cloud = arguments["--cloud"] or Default.cloud if cloud is None: Console.error("Default cloud doesn't exist") return if arguments["-v"]: print("Cloud: {}".format(cloud)) if arguments["refresh"] or Default.refresh: msg = "Refresh workflow for cloud {:}.".format(cloud) if Workflow.refresh(cloud): Console.ok("{:} ok".format(msg)) else: Console.error("{:} failed".format(msg)) return "" if arguments["list"]: id = arguments['ID'] live = arguments['--refresh'] output_format = arguments["--format"] result = None if id is None: result = Workflow.list(cloud, output_format) else: result = Workflow.details(cloud, id, live, output_format) if result is None: Console.error("No workflow(s) found. Failed.") else: print(result) return "" elif arguments["show"]: workflow_id = arguments["ID"] Console.ok("I executed show") # Console.msg(workflow_id) if workflow_id is None: Console.msg("Please enter a Workflow Id to execute workflow") else: result = Workflow.run(cloud, workflow_id) # print (result) if result is None: Console.msg( "Use workflow list to view existing workflows or do workflow save to save a new one" ) else: # Console.msg(result) # Console.msg(result[0]) Console.msg(result[0]['workflow_str']) # entry_point(result[0]['workflow_str']) Console.msg("All Set to execute") elif arguments["save"]: workflow_name = arguments["NAME"] workflow_str = arguments["WORKFLOWSTR"] result = Workflow.save(cloud=cloud, name=workflow_name, str=workflow_str) if result is not None: Console.ok(result) else: Console.error("Failed to save workflow!") elif arguments["run"]: Console.msg("Execute Run") workflow_name = arguments["NAME"] # cm_id = arguments["ID"] result = Workflow.run(cloud, name=workflow_name) elif arguments["delete"]: workflow_id = arguments["ID"] result = Workflow.delete(cloud, workflow_id) if result is not None: Console.msg(result) else: Console.error("Failed to save workflow!") elif arguments["service"] and arguments["start"]: # Console.msg() # mkdir -pf ~/.cloudmesh/workflow pass
def do_cluster(self, args, arguments): """ :: Usage: cluster list [--format=FORMAT] cluster list NAME [--format=FORMAT] [--column=COLUMN] [--short] cluster create NAME [--count=COUNT] [--login=USERNAME] [--cloud=CLOUD] [--image=IMAGE] [--flavor=FLAVOR] [--add] cluster delete NAME cluster setup NAME [--username] cluster inventory NAME Description: with the help of the cluster command you can create a number of virtual machines that are integrated in a named virtual cluster. You will be able to login between the nodes of the virtual cluster while using public keys. cluster setup NAME sets up the keys between the cluster node as well as the machine that executes the cm command cluster inventory NAME creates an inventory.txt file to be used by ansible in the current directory cluster create NAME creates the virtual machines used for the cluster cluster list NAME lists selected details of the vms for the cluster cluster delete NAME remove the cluster and its VMs Examples: cluster list list the clusters cluster create NAME --count=COUNT --login=USERNAME [options...] Start a cluster of VMs, and each of them can log into each other. CAUTION: you should specify defaults before using this command: 1. select cloud to work on, e.g. cloud select kilo default cloud=kilo 2. test if you can create a single VM on the cloud to see if everything is set up 3. set the default key to start VMs, e.g. key default [USERNAME-key] 5. set image of VMs, e.g. default image 6. set flavor of VMs, e.g. default flavor 7. Make sure to use a new unused group name Arguments: NAME cluster name or group name Options: --count=COUNT give the number of VMs to add into the cluster --login=USERNAME give a login name for the VMs, e.g. ubuntu --cloud=CLOUD give a cloud to work on --flavor=FLAVOR give the name of the flavor or flavor id --image=IMAGE give the name of the image or image id --add if a group exists and there are VMs in it additional vms will be added to this cluster and the keys will be added to each other so one can login between them FORMAT output format: table, json, csv COLUMN customize what information to display, for example: --column=status,addresses prints the columns status and addresses --detail for table print format, a brief version is used as default, use this flag to print detailed table """ def get_vms(group_name): groups = Vm.get_vms_by_group(group_name) vms = [] for group in groups: name = group["member"] print(name) vm = Vm.get_vm(name) vm['cluster'] = group_name vms.append(vm) return vms def _print(f): print(f) def write(filename, msg): with open(path_expand(filename), 'w') as f: output = f.write(msg) arg = dotdict(arguments) arg.format = arguments["--format"] or "table" arg.count = int(arguments["--count"] or 1) arg.username = arguments["--login"] arg.cloud = arguments["--cloud"] or Default.cloud arg.image = arguments["--image"] or Default.get(name="image", category=arg.cloud) arg.flavor = arguments["--flavor"] or Default.get(name="flavor", category=arg.cloud) arg.add = arguments["--add"] arg.group = arg.NAME arg.name = None arg.key = Default.key arg.secgroup = Default.secgroup arg.group = arg.NAME arg.short = arguments["--short"] if arg.create: boot_from_args(arg) elif arg.inventory: group = Vm.get_vms_by_group(arg.group) result = "" if arg.format is "table": result = "[servers]\n" for element in group: name = element["member"] vm = Vm.get_vm(name)[0] vm['cluster'] = arg.group result += "{floating_ip}\n".format(**vm) Console.ok("Writing ips to inventory.txt") print(result) write("inventory.txt", result) Console.ok(".ok") return "" elif arg.list and arg.NAME is not None: if arg.short: vms = Vm.get_vms_by_group(arg.group) if vms is None: Console.error("no vms found for {}".format(arg.group)) else: print( Printer.list(vms, header=['Group', 'Vm'], order=['name', 'member'], output=arg.format)) else: groups = Vm.get_vms_by_group(arg.group) pprint(groups) vms = [] for group in groups: name = group["member"] vm = Vm.get_vm(name)[0] vm['cluster'] = arg.group if vm is not None: vms.append(vm) pprint(vms) if vms is None: Console.error("no vms found for {}".format(arg.group)) else: print( Printer.list(vms, order=[ 'name', 'cluster', 'flavor', 'image', 'status', 'user_id', 'floating_ip' ], output=arg.format)) return "" elif arg.setup: def push(from_path, vm): vm.ip = vm.floating_ip if vm.ip is not None: if arg.verbose: Console.info("Connecting to Instance at IP:" + format(vm.ip)) sshcommand = "scp" sshcommand += " -o StrictHostKeyChecking=no" sshcommand += " {:}".format(from_path) sshcommand += " {username}@{ip}:.ssh/authorized_keys".format( **vm) print(sshcommand) os.system(sshcommand) else: Console.error("No Public IPs found for the instance", traceflag=False) groups = Vm.get_vms_by_group(arg.group) pprint(groups) vms = [] for group in groups: name = group["member"] vm = Vm.get_vm(name)[0] vm['cluster'] = arg.group if vm is not None: vms.append(vm) pprint(vms) if vms is None: Console.error("no vms found for {}".format(arg.group)) else: print( Printer.list(vms, order=[ 'name', 'cluster', 'flavor', 'image', 'status', 'user_id', 'floating_ip' ], output=arg.format)) keys = "" for vm in vms: vm = dotdict(vm) cloud = vm.category if vm.username is None: vm.username = arguments[ "--username"] or Image.guess_username(arg.image) chameleon = "chameleon" in ConfigDict( filename="cloudmesh.yaml" )["cloudmesh"]["clouds"][cloud]["cm_host"] print("C", chameleon) if chameleon: vm.username = "******" elif vm.category == "azure": vm.username = ConfigDict( filename="cloudmesh.yaml")["cloudmesh"]["clouds"][ "azure"]["default"]["username"] else: if vm.username is None: Console.error( "Could not guess the username of the vm", traceflag=False) return Vm.set_login_user(name=vm.name, cloud=vm.category, username=vm.username) vm.ip = vm.floating_ip def execute(commands): if vm.ip is not None: if arg.verbose: Console.info("Connecting to Instance at IP:" + format(vm.ip)) sshcommand = "ssh" if arg.key is not None: sshcommand += " -i {:}".format(arg.key) sshcommand += " -o StrictHostKeyChecking=no" sshcommand += " {username}@{ip}".format(**vm) sshcommand += " \'{:}\'".format(commands) print(sshcommand) os.system(sshcommand) else: Console.error( "No Public IPs found for the instance", traceflag=False) def copy(commands): if vm.ip is not None: if arg.verbose: Console.info("Connecting to Instance at IP:" + format(vm.ip)) sshcommand = "scp" sshcommand += " -o StrictHostKeyChecking=no" sshcommand += " {username}@{ip}".format(**vm) sshcommand += ":{:}".format(commands) print(sshcommand) os.system(sshcommand) else: Console.error( "No Public IPs found for the instance", traceflag=False) def cat(filename): with open(path_expand(filename), 'r') as f: output = f.read() return output execute('cat /dev/zero | ssh-keygen -q -N ""') copy(".ssh/id_rsa.pub ~/.ssh/id_rsa_{name}.pub".format( **vm)) output = "~/.ssh/id_rsa_{name}.pub".format(**vm) keys = keys + cat(output) print("WRITE KEYS") keys = keys + cat("~/.ssh/id_rsa.pub") output = "~/.ssh/id_rsa_{group}.pub".format(**arg) write(output, keys) print("PUSH KEYS") for vm in vms: vm = dotdict(vm) push("~/.ssh/id_rsa_{group}.pub".format(**arg), vm) return ""
def do_hadoop(self, arg, arguments): """ :: Usage: hadoop sync hadoop addons hadoop define [-r REPO] [-b NAME] [-d COUNT] [ADDON]... hadoop undefine [NAME]... hadoop avail hadoop use NAME hadoop deploy Arguments: REPO Repository location CLUSTER Name of a cluster ADDON Big Data Stack addon (eg: spark, hbase, pig) NAME Alphanumeric name COUNT Integer greater than zero Commands: sync Checkout / synchronize the Big Data Stack addons List available addons define Create a deployment specification undefine Delete the active or given specifications avail Show available deployment specifications use Activate the specification with the given name deploy Deploy the active specification onto the active cluster Options: -r --repo=REPO Location of the repository -b --branch=NAME Branch to use -d --depth=COUNT Clone depth """ arguments = dotdict(arguments) cmd = Command() if arguments.sync: cmd.sync() elif arguments.addons: addons = cmd.addons() for name in addons: print(name) elif arguments.define: cmd.define( addons=arguments['ADDON'], repo=arguments['--repo'], branch=arguments['--branch'], depth=arguments['--depth'], ) elif arguments.undefine: cmd.undefine(names=arguments['NAME']) elif arguments.avail: active, specs = cmd.avail() for spec in specs: marker = '>' if spec.name == active else ' ' print('{} {}'.format(marker, spec.name)) for k, v in spec.get().iteritems(): print('{:>4}{:<30}: {}'.format('', k, v)) elif arguments.use: cmd.use(arguments['NAME'][0]) elif arguments.deploy: cmd.deploy() else: raise NotImplementedError(args, arguments)
def delete(cls, **kwargs): arg = dotdict(kwargs) force = kwargs.get("force", Default.purge) if "cloud" in arg: cloud_provider = CloudProvider(arg.cloud).provider for server in kwargs["servers"]: vm = cls.cm.find(name=server, kind="vm", cloud=arg.cloud, scope="first") #vm_by_id = cls.cm.find(cm_id=server, kind="vm", cloud=arg.cloud, scope="first") #print (vm) #print(vm_by_id) #vm = vm or vm_by_id if vm: provider = vm["provider"] cloud = vm["category"] # If server has a floating ip associated, release it server_dict = Network.get_instance_dict( cloudname=arg.cloud, instance_id=server) floating_ip = server_dict["floating_ip"] if floating_ip is not None: Network.disassociate_floating_ip( cloudname=arg.cloud, instance_name=server, floating_ip=floating_ip) cloud_provider.delete_vm(server) if force: cls.cm.delete(kind="vm", provider=provider, category=cloud, name=server) # delete the record from db Console.ok( "VM record {:} is being deleted from the local database..." .format(server)) else: cls.cm.set(server, "status", "deleted", kind="vm", scope="first") # Console.ok("VM {:} is being deleted on {:} cloud...".format(server, cloud_provider.cloud)) else: Console.error("VM {:} can not be found.".format(server), traceflag=False) else: clouds = set() for server in arg.servers: vm = cls.cm.find(kind="vm", name=server, scope="first") if vm: cloud = vm["category"] provider = vm["provider"] cloud_provider = CloudProvider(cloud).provider clouds.add(cloud) cloud_provider.delete_vm(server) if force: cls.cm.delete(kind="vm", provider=provider, category=cloud, name=server) Console.ok( "VM record {:} is being deleted from the local database..." .format(server)) else: cls.cm.set(server, "status", "deleted", kind="vm", scope="first") # Console.ok("VM {:} is being deleted on {:} cloud...".format(server, cloud)) else: Console.error("VM {:} can not be found.".format(server), traceflag=False)
def do_vbox(argv): """ :: Usage: vbox version [--format=FORMAT] vbox image list [--format=FORMAT] vbox image find NAME vbox image add NAME vbox vm list [--format=FORMAT] [-v] vbox vm delete NAME vbox vm config NAME vbox vm ip NAME [--all] vbox create NAME ([--memory=MEMORY] [--image=IMAGE] [--script=SCRIPT] | list) vbox vm boot NAME ([--memory=MEMORY] [--image=IMAGE] [--port=PORT] [--script=SCRIPT] | list) vbox vm ssh NAME [-e COMMAND] """ arg = dotdict(docopt(do_vbox.__doc__, argv)) arg.format = arg["--format"] or "table" arg.verbose = arg["-v"] arg.all = arg["--all"] if arg.version: versions = { "vagrant": { "attribute": "Vagrant Version", "version": vagrant.version(), }, "cloudmesh-vbox": { "attribute":"cloudmesh vbox Version", "version": __version__ } } _LIST_PRINT(versions, arg.format) elif arg.image and arg.list: l = vagrant.image.list(verbose=arg.verbose) _LIST_PRINT(l, arg.format, order=["name", "provider", "date"]) elif arg.image and arg.add: l = vagrant.image.add(arg.NAME) print(l) elif arg.image and arg.find: l = vagrant.image.find(arg.NAME) print(l) elif arg.vm and arg.list: l = vagrant.vm.list() _LIST_PRINT(l, arg.format, order=["name", "state", "id", "provider", "directory"]) elif arg.create and arg.list: result = Shell.cat("{NAME}/Vagrantfile".format(**arg)) print (result) elif arg.create: d = defaults() arg.memory = arg["--memory"] or d.memory arg.image = arg["--image"] or d.image arg.script = arg["--script"] or d.script vagrant.vm.create( name=arg.NAME, memory=arg.memory, image=arg.image, script=arg.script) elif arg.config: # arg.NAME d = vagrant.vm.info(name=arg.NAME) result = Printer.attribute(d, output=arg.format) print (result) elif arg.ip: data = [] result = vagrant.vm.execute(arg.NAME, "ifconfig") if result is not None: lines = result.splitlines()[:-1] for line in lines: if "inet addr" in line: line = line.replace("inet addr", "ip") line = ' '.join(line.split()) _adresses = line.split(" ") address = {} for element in _adresses: attribute, value = element.split(":") address[attribute] = value data.append(address) if arg.all: d = {} i = 0 for e in data: d[str(i)] = e i = i + 1 result = Printer.attribute(d, output=arg.format) print(result) else: for element in data: ip = element['ip'] if ip == "127.0.0.1" or ip.startswith("10."): pass else: print (element['ip']) elif arg.boot: d = defaults() arg.memory = arg["--memory"] or d.memory arg.image = arg["--image"] or d.image arg.script = arg["--script"] or d.script arg.port = arg["--port"] or d.port vagrant.vm.boot( name=arg.NAME, memory=arg.memory, image=arg.image, script=arg.script, port=arg.port) elif arg.delete: result = vagrant.vm.delete(name=arg.NAME) print(result) elif arg.ssh: if arg.COMMAND is None: os.system("cd {NAME}; vagrant ssh {NAME}".format(**arg)) else: result = vagrant.vm.execute(arg.NAME, arg.COMMAND) if result is not None: lines = result.splitlines()[:-1] for line in lines: print (line) else: print ("use help")
def list(cls, **kwargs): """ This method lists all VMs of the cloud """ arg = dotdict(kwargs) if "name" in arg: arg.name = arg.name arg.output = arg.output or 'table' # pprint (kwargs) # prevent circular dependency def vm_groups(vm): """ :param vm: name of the vm :return: a list of groups the vm is in """ try: query = { 'kind': "group", 'provider': 'general', "species": "vm", "member": vm, "scope": 'all', "output": 'dict' } d = cls.cm.find(**query) groups_vm = set() if d is not None and len(d) > 0: for vm in d: groups_vm.add(vm['name']) return list(groups_vm) except Exception as ex: Console.error(ex.message) return [] try: if "name" in arg and arg.name is not None: if cls.isUuid(arg.name): elements = cls.cm.find(kind="vm", category=arg.category, uuid=arg.name) else: elements = cls.cm.find(kind="vm", category=arg.category, label=arg.name) else: elements = cls.cm.find(kind="vm", category=arg.category) if elements is None or len(elements) == 0: return None for elem in elements: element = elem name = element["name"] groups = vm_groups(name) element["group"] = ','.join(groups) # print(elements) # order = ['id', 'uuid', 'name', 'cloud'] (order, header) = CloudProvider(arg.category).get_attributes("vm") # order = None if "name" in arg and arg.name is not None: return Printer.attribute(elements[0], output=arg.output) else: return Printer.write(elements, order=order, output=arg.output) except Exception as ex: Console.error(ex.message)
def do_test(self, args, arguments): """ :: Usage: test list test [TEST] [NUMBER] [--test=TESTER] This is an internal command and is ment for developers. If executed, in the source directory, it will execute the specified series of tests in the tests directory. managing the admins test test test test Arguments: TEST the name of the test directory NUMBER the number of a specific test Options: --test=TESTER nosetests or py.test. [default: nosetests -v --nocapture] Examples: cm test var finds the first test that contains var and than executes all tests in it cm test var 4 finds the first test that contains var and than executes the test with number 004 """ data = dotdict({ 'test': arguments["TEST"], 'number': arguments["NUMBER"], "tester": arguments["--test"] }) def get_file(): data.file = None for file in files: if data.test in file: break data.file = file def run(command): command = command.format(**data) banner(command, c="-") parameter = command.split(" ") os.system(command) # shell_command = parameter[0] # args = parameter[1:] # result = Shell.execute(shell_command, args) # print(result) # return str(result) # command = "nosetests -v --nocapture {0}:{1}.{2}".format(filename, classname, name) files = [] dirs = [] for root, dirnames, filenames in os.walk('tests'): for filename in filenames: if ".pyc" in filename: continue if ".py" not in filename: dirs.append(os.path.join(root, filename)) elif filename not in ["__init__.py"]: files.append(os.path.join(root, filename)) if arguments["list"]: print('\n'.join(files)) # find tests return "" if data.test is None: command = "{tester}" elif data.test in dirs: command = "{tester} {test}" elif data.number is None: get_file() command = "{tester} {file}" # run all in that file else: # run specific test get_file() # python setup.py install; nosetests -v --nocapture tests/cm_cloud/test_group.py:Test_group.test_001 data.basename = os.path.basename(data.file).replace(".py", "") data.basename = data.basename.replace("test_", "") data.number = data.number.zfill(3) command = "{tester} {file}:Test_{basename}.test_{number}" run(command) return ""
def do_cluster(self, args, arguments): """ :: Usage: cluster list [--format=FORMAT] cluster list NAME [--format=FORMAT] [--column=COLUMN] [--short] cluster create NAME [--count=COUNT] [--login=USERNAME] [--cloud=CLOUD] [--image=IMAGE] [--flavor=FLAVOR] [--add] cluster delete NAME cluster setup NAME [--username] cluster inventory NAME Description: with the help of the cluster command you can create a number of virtual machines that are integrated in a named virtual cluster. You will be able to login between the nodes of the virtual cluster while using public keys. cluster setup NAME sets up the keys between the cluster node as well as the machine that executes the cm command cluster inventory NAME creates an inventory.txt file to be used by ansible in the current directory cluster create NAME creates the virtual machines used for the cluster cluster list NAME lists selected details of the vms for the cluster cluster delete NAME remove the cluster and its VMs Examples: cluster list list the clusters cluster create NAME --count=COUNT --login=USERNAME [options...] Start a cluster of VMs, and each of them can log into each other. CAUTION: you should specify defaults before using this command: 1. select cloud to work on, e.g. cloud select kilo default cloud=kilo 2. test if you can create a single VM on the cloud to see if everything is set up 3. set the default key to start VMs, e.g. key default [USERNAME-key] 5. set image of VMs, e.g. default image 6. set flavor of VMs, e.g. default flavor 7. Make sure to use a new unused group name Arguments: NAME cluster name or group name Options: --count=COUNT give the number of VMs to add into the cluster --login=USERNAME give a login name for the VMs, e.g. ubuntu --cloud=CLOUD give a cloud to work on --flavor=FLAVOR give the name of the flavor or flavor id --image=IMAGE give the name of the image or image id --add if a group exists and there are VMs in it additional vms will be added to this cluster and the keys will be added to each other so one can login between them FORMAT output format: table, json, csv COLUMN customize what information to display, for example: --column=status,addresses prints the columns status and addresses --detail for table print format, a brief version is used as default, use this flag to print detailed table """ def get_vms(group_name): groups = Vm.get_vms_by_group(group_name) vms = [] for group in groups: name = group["member"] print(name) vm = Vm.get_vm(name) vm['cluster'] = group_name vms.append(vm) return vms def _print(f): print (f) def write(filename, msg): with open(path_expand(filename), 'w') as f: output = f.write(msg) arg = dotdict(arguments) arg.format = arguments["--format"] or "table" arg.count = int(arguments["--count"] or 1) arg.username = arguments["--login"] arg.cloud = arguments["--cloud"] or Default.cloud arg.image = arguments["--image"] or Default.get(name="image", category=arg.cloud) arg.flavor = arguments["--flavor"] or Default.get(name="flavor", category=arg.cloud) arg.add = arguments["--add"] arg.group = arg.NAME arg.name = None arg.key = Default.key arg.secgroup = Default.secgroup arg.group = arg.NAME arg.short = arguments["--short"] if arg.create: boot_from_args(arg) elif arg.inventory: group = Vm.get_vms_by_group(arg.group) result = "" if arg.format is "table": result = "[servers]\n" for element in group: name = element["member"] vm = Vm.get_vm(name)[0] vm['cluster'] = arg.group result += "{floating_ip}\n".format(**vm) Console.ok("Writing ips to inventory.txt") print(result) write("inventory.txt", result) Console.ok(".ok") return "" elif arg.list and arg.NAME is not None: if arg.short: vms = Vm.get_vms_by_group(arg.group) if vms is None: Console.error("no vms found for {}".format(arg.group)) else: print(Printer.list(vms, header=['Group', 'Vm'], order=['name', 'member'], output=arg.format)) else: groups = Vm.get_vms_by_group(arg.group) pprint(groups) vms = [] for group in groups: name = group["member"] vm = Vm.get_vm(name)[0] vm['cluster'] = arg.group if vm is not None: vms.append(vm) pprint(vms) if vms is None: Console.error("no vms found for {}".format(arg.group)) else: print(Printer.list(vms, order=['name', 'cluster', 'flavor', 'image', 'status', 'user_id', 'floating_ip'], output=arg.format)) return "" elif arg.setup: def push(from_path, vm): vm.ip = vm.floating_ip if vm.ip is not None: if arg.verbose: Console.info("Connecting to Instance at IP:" + format(vm.ip)) sshcommand = "scp" sshcommand += " -o StrictHostKeyChecking=no" sshcommand += " {:}".format(from_path) sshcommand += " {username}@{ip}:.ssh/authorized_keys".format(**vm) print(sshcommand) os.system(sshcommand) else: Console.error("No Public IPs found for the instance", traceflag=False) groups = Vm.get_vms_by_group(arg.group) pprint (groups) vms = [] for group in groups: name = group["member"] vm = Vm.get_vm(name)[0] vm['cluster'] = arg.group if vm is not None: vms.append(vm) pprint(vms) if vms is None: Console.error("no vms found for {}".format(arg.group)) else: print(Printer.list(vms, order=['name', 'cluster', 'flavor', 'image', 'status', 'user_id', 'floating_ip'], output=arg.format)) keys = "" for vm in vms: vm = dotdict(vm) cloud = vm.category if vm.username is None: vm.username = arguments["--username"] or Image.guess_username(arg.image) chameleon = "chameleon" in ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["clouds"][cloud][ "cm_host"] print ("C", chameleon) if chameleon: vm.username = "******" elif vm.category == "azure": vm.username = ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["clouds"]["azure"]["default"][ "username"] else: if vm.username is None: Console.error("Could not guess the username of the vm", traceflag=False) return Vm.set_login_user(name=vm.name, cloud=vm.category, username=vm.username) vm.ip = vm.floating_ip def execute(commands): if vm.ip is not None: if arg.verbose: Console.info("Connecting to Instance at IP:" + format(vm.ip)) sshcommand = "ssh" if arg.key is not None: sshcommand += " -i {:}".format(arg.key) sshcommand += " -o StrictHostKeyChecking=no" sshcommand += " {username}@{ip}".format(**vm) sshcommand += " \'{:}\'".format(commands) print(sshcommand) os.system(sshcommand) else: Console.error("No Public IPs found for the instance", traceflag=False) def copy(commands): if vm.ip is not None: if arg.verbose: Console.info("Connecting to Instance at IP:" + format(vm.ip)) sshcommand = "scp" sshcommand += " -o StrictHostKeyChecking=no" sshcommand += " {username}@{ip}".format(**vm) sshcommand += ":{:}".format(commands) print(sshcommand) os.system(sshcommand) else: Console.error("No Public IPs found for the instance", traceflag=False) def cat(filename): with open(path_expand(filename), 'r') as f: output = f.read() return output execute('cat /dev/zero | ssh-keygen -q -N ""') copy(".ssh/id_rsa.pub ~/.ssh/id_rsa_{name}.pub".format(**vm)) output = "~/.ssh/id_rsa_{name}.pub".format(**vm) keys = keys + cat(output) print ("WRITE KEYS") keys = keys + cat("~/.ssh/id_rsa.pub") output = "~/.ssh/id_rsa_{group}.pub".format(**arg) write(output, keys) print("PUSH KEYS") for vm in vms: vm = dotdict(vm) push("~/.ssh/id_rsa_{group}.pub".format(**arg), vm) return ""
class Test_register: """ # tests # for india only """ data = dotdict({ # "cloud": Default.cloud, # only retrieving for india kilo "cloud": "kilo", "group": "test", "vm": "testvm", "flavor": "TBD", "image": "TBD", "wrong_cloud": "no_cloud", "cert": "~/.cloudmesh/clouds/india/{cloud}/cacert.pem", "yaml": "cloudmesh1.yaml" }) data.image = Default.get_image() data.flavor = Default.get_flavor() def run(self, command): command = command.format(**self.data) banner(command, c="-") print(command) parameter = command.split(" ") shell_command = parameter[0] args = parameter[1:] result = Shell.execute(shell_command, args) print(result) return str(result) def setup(self): pass def tearDown(self): pass def test_001(self): HEADING("cm register remote {cloud}".format(**self.data)) # os.sytem("yes | cm register india") result = self.run("cm register remote {cloud}") print(result) #result = Shell.cm("register", "india", "--force") assert "{cloud}".format(**self.data) in result assert "OS_AUTH_URL" in result assert "https://kilo.futuresystems.org:5000/v3" in result def test_002(self): HEADING("testing cm register random1") result = self.run("cm register remote doesnotexist") assert "ERROR: executing" in result def test_003(self): HEADING("testing cm register list") result = self.run("cm register list") assert "{cloud}".format(**self.data) in result def test_004(self): HEADING("testing cm register info") result = self.run("cm register info") assert "exists" in result def test_005(self): HEADING("testing cm register cat") result = self.run("cm register cat") assert "version:" in result def test_006(self): HEADING("testing cm register cat --yaml={yaml}".format(**self.data)) result = self.run("cm register cat --yaml={yaml}") assert "ERROR: executing command" in result def test_007(self): HEADING("testing cm register edit --yaml=cloudmesh_doesnotexist.yaml") result = self.run("cm register edit --yaml=cloudmesh_doesnotexit.yaml") assert "ERROR: executing command" in result def test_008(self): HEADING("testing cm register list ssh") result = self.run("cm register list ssh") assert "| host" in result def test_009(self): HEADING("testing cm register remote") result = self.run("cm register remote") assert "Reading rc file from" in result def test_010(self): HEADING("cm register json {cloud}".format(**self.data)) result = self.run("cm register json {cloud}") assert "openstack" in result def test_011(self): HEADING("testing cm register json hadoop") result = self.run("cm register json hadoop") assert "Cloud hadoop is not described in cloudmesh.yaml" in result