class TestName: image_test = False vbox = '6.0.4' image_name = "generic/ubuntu1810" size = 1024 cloud = "vagrant" def print_images(self): images = self.p.images() print( Printer.flatwrite(images, sort_keys=["name"], order=["name", "provider", "version"], header=["Name", "Provider", "Version"])) def next_name(self): self.name_generator.incr() self.new_name = str(self.name_generator) return self.new_name def setup(self): banner("setup", c="-") self.user = Config()["cloudmesh.profile.user"] self.name_generator = Name(experiment="exp", group="grp", user=self.user, kind="vm", counter=1) self.name = str(self.name_generator) self.name_generator.incr() self.new_name = str(self.name_generator) self.p = Provider(name=self.cloud) def test_01_version(self): HEADING() r = self.p.version() pprint(r) assert self.vbox_version == r["virtualbox"]["extension"]["version"] assert self.vbox_version == r["virtualbox"]["version"] def test_02_list_os(self): HEADING() ostypes = self.p.list_os() print( Printer.write(ostypes, order=[ "id", "64_bit", "description", "family_descr", "family_id" ], header=[ "id", "64_bit", "description", "family_descr", "family_id" ])) def test_03_name(self): HEADING() print(self.name) assert self.name == "exp-grp-{user}-vm-1".format(user=self.user) def test_04_list_images(self): HEADING() self.print_images() def test_05_delete_image(self): HEADING() if self.image_test: name = "generic/ubuntu1810" try: images = self.p.delete_image(self.image_name) print("delete", self.image_name) except: print("image", self.image_name, "nor found") self.print_images() else: print("not executed as image_test is not True. ok") def test_06_add_image(self): HEADING() if self.image_test: images = self.p.add_image(self.image_name) print("I", images) self.print_images() assert images.status == 0 else: print("not executed as image_test is not True. ok") def test_07_list_vm(self): HEADING() vms = self.p.info() pprint(vms) print( Printer.flatwrite( vms, order=[ "vagrant.name", "vbox.name", "vagrant.id", "vagrant.provider", "vagrant.state", "vagrant.hostname" ], header=["name", "vbox", "id", "provider", "state", "hostname"])) def test_10_create(self): HEADING() name = self.next_name() print("Name", name) self.p.create( name=self.name, image=self.image_name, size=self.size, # username as the keypair name based on # the key implementation logic ex_keyname=self.user, ex_security_groups=['default']) directory = Path( path_expand("~/.cloudmesh/vagrant/exp-grp-gregor-vm-1")) assert directory.is_dir() time.sleep(5) nodes = self.p.list() pprint(nodes) node = self.p.find(nodes, name=self.name) pprint(node) nodes = self.p.list(raw=False) for node in nodes: if node.name == self.name: self.testnode = node break assert node is not None
class Provider(object): def __init__(self, name=None, configuration="~/.cloudmesh/.cloudmesh4.yaml"): self.kind = Config( configuration)["cloudmesh"]["cloud"][name]["cm"]["kind"] self.name = name # Console.msg("FOUND Kind", self.kind) if self.kind in ["openstack", "aws"]: self.p = LibCloudProvider(name=name, configuration=configuration) elif self.kind in ["vagrant", "virtualbox"]: self.p = VirtualboxCloudProvider(name=name, configuration=configuration) def cloudname(self): return self.name @DatabaseUpdate() def keys(self): return self.p.keys() @DatabaseUpdate() def list(self): return self.p.list() @DatabaseUpdate() def images(self): return self.p.images() @DatabaseUpdate() def flavor(self): return self.p.flavors() def add_collection(self, d, *args): if d is None: return None label = '-'.join(args) for entry in d: entry['collection'] = label return d @DatabaseUpdate() def images(self): return self.p.images() # name # cloud # kind @DatabaseUpdate() def flavors(self): return self.p.flavors() def start(self, name=None): return self.p.start(name=name) def stop(self, name=None): return self.p.stop(name=name) def info(self, name=None): return self.p.info(name=name) def resume(self, name=None): return self.p.resume(name=name) def reboot(self, name=None): return self.p.reboot(name=name) def create(self, name=None, image=None, size=None, timeout=360, **kwargs): self.p.create(name=name, image=image, size=size, timeout=360, **kwargs) def rename(self, name=None, destination=None): self.p.rename(name=name, destination=name)
class Vm(ComputeNodeABC): def __init__(self, cloud): self.mongo = CmDatabase() self.config = Config().data["cloudmesh"] self.kind = self.config["cloudmesh"][cloud]["cm"]["kind"] super().__init__(cloud, self.config) if self.kind == 'azure': self.provider = LibcloudProvider(self.config) elif self.kind == 'aws': self.provider = LibcloudProvider(self.config) elif self.kind == 'vm': self.provider = LibcloudProvider("chameleon") elif self.kind == "vbox": # not sure about vbox vs vagrant in vbox provider self.provider = VboxProvider("vagrant") else: raise NotImplementedError(f"Cloud `{self.kind}` not supported.") @DatabaseUpdate(collection="cloudmesh", ComputeNodeABC.map_default) def start(self, name): """ start the node based on the id :param name: :return: VM document """ info = self.info(name) if info["state"] != "running": info = self.provider.start(name) return info @DatabaseUpdate(collection="cloudmesh", ComputeNodeABC.map_default) def stop(self, name=None): """ stop the node based on the ide :param name: :return: VM document """ return self.provider.stop(name) @DatabaseUpdate(collection="cloudmesh", ComputeNodeABC.map_default) def resume(self, name=None): """ start the node based on id :param name: """ return self.start(name) @DatabaseUpdate(collection="cloudmesh", ComputeNodeABC.map_default) def suspend(self, name=None): """ stop the node based on id :param name: """ return self.provider.suspend(name) @DatabaseUpdate(collection="cloudmesh", ComputeNodeABC.map_default) def destroy(self, name=None): """ delete the node based on id :param name: :return: True/False """ result = self.provider.destroy(name) # self.mongo.delete_document('cloud', 'name', name) return result @DatabaseUpdate(collection="cloudmesh", ComputeNodeABC.map_vm_create) def create(self, name=None): """ create a new node :param name: the name for the new node :return: """ name = name or self.new_name() return self.provider.create(name=name) @DatabaseUpdate(collection="cloudmesh", ComputeNodeABC.map_default) def nodes(self): return self.provider.vagrant_nodes() # @DatabaseUpdate(collection="cloudmesh", ComputeNodeManagerABC._map_default) def info(self, name=None): """ show node information based on id TODO: seems like this should look in mongo, not self.nodes probably the solution is a more broad change to dynamically set the provider based on a name/cloud lookup in mongo. :param name: :return: all information about one node """ return self.provider.info(name) def new_name(self, experiment=None, group=None, user=None): """ Generate a VM name with the format `experiment-group-name-<counter>` where `counter` represents a running count of VMs created. Defaults can be modified in the cloudmesh4.yaml file. :param experiment: :param group: :param user: :return: The generated name. """ experiment = experiment or self.config["default"]["experiment"] group = group or self.config["default"]["group"] user = user or getpass.getuser() counter = Counter() count = counter.get() name = Name() name_format = { 'experiment': experiment, 'group': group, 'user': user, 'counter': count } name.set_schema('instance') counter.incr() return name.get(name_format) def get_public_ips(self, name=None): """ Returns all the public ips available if a name is not given. If a name is provided, the ip of the vm name would be returned. :param name: name of the VM. :return: Dictionary of VMs with their public ips """ if name is None: filters = {"$exists": True, "$not": {"$size": 0}} documents = self.mongo.find('cloud', 'public_ips', filters) if documents is None: return None else: result = {} for document in documents: result[document['name']] = document['public_ips'] return result else: public_ips = self.mongo.find_document('cloud', 'name', name)['public_ips'] if not public_ips: return None else: return {name: public_ips} def set_public_ip(self, name, public_ip): """ Assign the given public ip to the given VM. :param name: name of the VM :param public_ip: public ip to be assigned. """ if name is not None and public_ip is not None: self.provider.set_public_ip(name, public_ip) def remove_public_ip(self, name): """ Deletes the public ip of the given VM. :param name: name of the VM """ if name is not None: self.provider.remove_public_ip(name)