def details(self, kind, cloud, id, format="table"):
        from cloudmesh_client.db.CloudmeshDatabase import CloudmeshDatabase
        try:
            cm = CloudmeshDatabase()

            if kind not in self.kind:
                raise ValueError('{} not defined'.format(kind))

            elements = None
            for idkey in ["name", "uuid", "id"]:
                s = {idkey: id}
                try:
                    elements = cm.find(kind, cloud=cloud, **s)
                except:
                    pass
                if len(elements) > 0:
                    break

            if len(elements) == 0:
                return None

            if format == "table":
                element = elements.values()[0]
                return attribute_printer(element)
            else:
                return dict_printer(elements,
                                    output=format)
        except Exception as ex:
            Console.error(ex.message, ex)
    def details(self, kind, cloud, id, format="table"):
        from cloudmesh_client.db.CloudmeshDatabase import CloudmeshDatabase
        try:
            cm = CloudmeshDatabase()

            if kind not in self.kind:
                raise ValueError('{} not defined'.format(kind))

            elements = None
            for idkey in ["name", "uuid", "id"]:
                s = {idkey: id}
                try:
                    elements = cm.find(kind, category=cloud, **s)
                except:
                    pass
                if len(elements) > 0:
                    break

            if len(elements) == 0:
                return None

            if format == "table":
                element = list(elements.values())[0]
                return attribute_printer(element)
            else:
                return dict_printer(elements, output=format)
        except Exception as ex:
            Console.error(ex.message, ex)
Exemple #3
0
    def get_instance_dict(cls, **kwargs):
        """
        Method to get instance dict
        :param kwargs:
        :return: instance dict
        """
        cloudname = kwargs["cloudname"]
        instance_id = kwargs["instance_id"]

        # Cloudmesh database instance
        db = CloudmeshDatabase()

        # Lookup instance details from db
        if cls.isUuid(instance_id):
            instance_dict = db.find(kind="vm", cloud=cloudname, uuid=instance_id)
        else:
            instance_dict = db.find(kind="vm", cloud=cloudname, name=instance_id)

        # Instance not found in DB
        if cls.isDictEmpty(instance_dict):
            # auto detect instance_id feature
            vms = db.find("vm", cloud=cloudname)
            # check for each instance in db
            for vm in vms.values():
                # if match found in either name/id
                if vm["uuid"].startswith(instance_id) or vm["name"].startswith(instance_id):
                    # confirm choice with user
                    print("Did you mean instance [{}] ? (y/n)".format(vm["name"]))
                    choice = raw_input().lower()
                    # if yes, return dict
                    if choice == "y":
                        return vm
            return None
        else:
            return instance_dict.values()[0]
Exemple #4
0
    def details(self, kind, category, id, format="table"):

        from cloudmesh_client.db.CloudmeshDatabase import CloudmeshDatabase

        cm = CloudmeshDatabase()

        try:
            if kind not in self.kind:
                raise ValueError('{} not defined'.format(kind))

            elements = None
            for idkey in ["cm_id", "name", "uuid", "id", "cm_id"]:
                s = {idkey: id}
                try:
                    elements = cm.find(kind=kind, category=category, **s)
                except:
                    pass
                if elements is not None:
                    break

            if elements is None:
                return None

            if len(elements) > 0:
                element = elements[0]
                if format == "table":
                    return Printer.attribute(element)
                else:
                    return Printer.write(element, output=format)
            else:
                return None

        except Exception as ex:
            Console.error(ex.message)
    def details(self, kind, category, id, format="table"):

        from cloudmesh_client.db.CloudmeshDatabase import CloudmeshDatabase

        cm = CloudmeshDatabase()

        try:
            if kind not in self.kind:
                raise ValueError('{} not defined'.format(kind))

            elements = None
            for idkey in ["cm_id", "name", "uuid", "id", "cm_id"]:
                s = {idkey: id}
                try:
                    elements = cm.find(kind=kind, category=category, **s)
                except:
                    pass
                if elements is not None:
                    break

            if elements is None:
                return None

            if len(elements) > 0:
                element = elements[0]
                if format == "table":
                    return Printer.attribute(element)
                else:
                    return Printer.write(element,
                                         output=format)
            else:
                return None

        except Exception as ex:
            Console.error(ex.message)
    def add_db(cls, **kwargs):
        cm = CloudmeshDatabase()

        kwargs['name'] = kwargs.get('script_name')

        db_obj = {0: {"batchjob": kwargs}}
        cm.add_obj(db_obj)
        cm.save()
    def test_002_find_all(self):
        """testing cm list --cloud ... default"""
        HEADING()
        cm = CloudmeshDatabase(user="******")
        m = DEFAULT("hallo", "world")

        n = cm.find("default", scope="all", name='hallo')
        print(n.keys())
        assert (len(n.keys()) > 0)
    def test_003_find_filter(self):
        """testing cm list --cloud india default"""
        HEADING()
        cm = CloudmeshDatabase(user="******")
        m = DEFAULT("hallo", "world")

        n = cm.find("default", scope="all", name="hallo")
        print(n.keys())
        assert len(n.keys()) > 0
    def test_003_find_filter(self):
        """testing cm list --cloud ... default"""
        HEADING()
        cm = CloudmeshDatabase(user="******")
        m = DEFAULT("hallo", "world")

        n = cm.find("default", scope="all", name='hallo')
        print(list(n))
        assert (len(list(n)) > 0)
    def test_002_find_first(self):
        """testing cm list --cloud ... default"""
        HEADING()
        cm = CloudmeshDatabase(user="******")
        m = DEFAULT("hallo", "world")

        n = cm.find("default", scope="first", name='hallo')
        first = list(n)[0]
        pprint(n)

        assert n["name"] == 'hallo'
        assert n["value"] == 'world'
    def test_002_find_first(self):
        """testing cm list --cloud india default"""
        HEADING()
        cm = CloudmeshDatabase(user="******")
        m = DEFAULT("hallo", "world")

        n = cm.find("default", scope="first", name="hallo")
        first = n.keys()[0]
        pprint(n)

        assert n["name"] == "hallo"
        assert n["value"] == "world"
Exemple #12
0
    def delete(cls, cluster, job, group=None):
        """
        This method is used to terminate a job with the specified or a group of jobs
        job_id or job_name in a given cluster
        :param group:
        :param cluster: the cluster like comet
        :param job: the job id or name
        :return: success message or error
        """
        try:
            if group is not None:
                # get the job ids from the db
                cm = CloudmeshDatabase()
                arguments = {'cluster': cluster,
                             'group': group}
                db_jobs = cm.find('batchjob',
                                  **arguments)

                list1 = []
                for i in db_jobs:
                    list1.append(db_jobs[i]['job_id'])

                # read active jobs
                active_jobs = json.loads(cls.queue(cluster))
                list2 = []
                for i in active_jobs:
                    list2.append(active_jobs[i]['jobid'])

                # find intersection
                res = set(list1).intersection(set(list2))

                if res is not None:
                    for j in res:
                        cmd = 'scancel {}'.format(str(j))
                        Shell.ssh(cluster, cmd)
                        print("Deleted {}".format(j))

                return "All jobs for group {} killed successfully".format(group)

            else:
                args = 'scancel '
                if job.isdigit():
                    args += job
                else:
                    args += "-n {}".format(job)

                Shell.ssh(cluster, args)
                return "Job {} killed successfully".format(job)
        except Exception as ex:
            print("in exceptio")
            print(ex)
            return ex
    def delete(cls, cluster, job, group=None):
        """
        This method is used to terminate a job with the specified or a group of jobs
        job_id or job_name in a given cluster
        :param group:
        :param cluster: the cluster like comet
        :param job: the job id or name
        :return: success message or error
        """
        try:
            if group is not None:
                # get the job ids from the db
                cm = CloudmeshDatabase()
                arguments = {'cluster': cluster,
                             'group': group}
                db_jobs = cm.find('batchjob',
                                  **arguments)

                list1 = []
                for i in db_jobs:
                    list1.append(db_jobs[i]['job_id'])

                # read active jobs
                active_jobs = json.loads(cls.queue(cluster))
                list2 = []
                for i in active_jobs:
                    list2.append(active_jobs[i]['jobid'])

                # find intersection
                res = set(list1).intersection(set(list2))

                if res is not None:
                    for j in res:
                        cmd = 'scancel {}'.format(str(j))
                        Shell.ssh(cluster, cmd)
                        print("Deleted {}".format(j))

                return "All jobs for group {} killed successfully".format(group)

            else:
                args = 'scancel '
                if job.isdigit():
                    args += job
                else:
                    args += "-n {}".format(job)

                Shell.ssh(cluster, args)
                return "Job {} killed successfully".format(job)
        except Exception as ex:
            print("in exceptio")
            print(ex)
            return ex
Exemple #14
0
    def add_db(cls, **kwargs):
        cm = CloudmeshDatabase()

        # replace options with correct values
        kwargs['dir'] = kwargs.pop('-D')
        kwargs['nodes'] = kwargs.pop('-N')
        kwargs['output_file'] = kwargs.pop('-o')
        kwargs['output_file'] = kwargs.pop('-t')
        kwargs['name'] = kwargs.get('script_name')

        db_obj = {0: {"batchjob": kwargs}}
        cm.add_obj(db_obj)
        cm.save()
    def test_001_query(self):
        """testing cm list --cloud ... default"""
        HEADING()
        cm = CloudmeshDatabase(user="******")
        m = DEFAULT("hallo", "world")
        cm.add(m)

        n = cm.query(DEFAULT).filter_by(name='hallo').first()

        print(n.__dict__)

        #assert n.__dict__["name"] == 'hallo'
        #assert n.__dict__["value"] == 'world'

        pprint(n.__dict__)
    def test_001_query(self):
        """testing cm list --cloud india default"""
        HEADING()
        cm = CloudmeshDatabase(user="******")
        m = DEFAULT("hallo", "world")
        cm.add(m)

        n = cm.query(DEFAULT).filter_by(name="hallo").first()

        print(n.__dict__)

        # assert n.__dict__["name"] == 'hallo'
        # assert n.__dict__["value"] == 'world'

        pprint(n.__dict__)
Exemple #17
0
class Ip(ListResource):
    cm = CloudmeshDatabase()

    @classmethod
    def list(cls, cloud=None, names=None, output='table', live=False):

        try:

            if live:
                cls.refresh(cloud)

            elements = cls.cm.find(kind="vm", category=cloud)
            result = []
            if "all" in names:
                for element in elements:
                    result.append(element)
            elif names is not None:
                for element in elements:
                    if element["name"] in names:
                        result.append(element)

            (order, header) = CloudProvider(cloud).get_attributes("ip")

            return Printer.write(result,
                                 order=order,
                                 header=header,
                                 output=output)
        except Exception as ex:
            Console.error(ex.message)
Exemple #18
0
    def test_001(self):
        HEADING()
        d = self.d

        banner("VM Data")
        pprint(d.__dict__)

        banner("Add VM")
        cm = CloudmeshDatabase()

        name = "vm1"
        uuid = d.id

        vm = VM(name=name,
                uuid=uuid,
                user="******",
                type="VM",
                category="mycloud",
                **d)
        banner("VM added")

        pprint(vm.__dict__)
        vm.bla = "bla"
        cm.add(vm)
        cm.save()

        banner("Get VM from Database")

        o = cm.find(VM, name=name)
        #o = cm.find_by_name(VM, name)
        pprint(o)

        assert True
Exemple #19
0
    def find_instance_name(cls, **kwargs):
        """
        Method to find instance name
        :param kwargs:
        :return: instance_name
        """
        cloudname = kwargs["cloudname"]
        instance_id = kwargs["instance_id"]

        # Cloudmesh database instance
        db = CloudmeshDatabase()

        # Lookup instance details from db
        instance_dict = db.find(kind="vm", cloud=cloudname, uuid=instance_id)

        # Get instance_name for vm
        if len(instance_dict) > 0:
            instance_name = instance_dict.values()[0]["name"]

            return instance_name
Exemple #20
0
    def get_instance_dict(cls, **kwargs):
        """
        Method to get instance dict
        :param kwargs:
        :return: instance dict
        """
        cloudname = kwargs["cloudname"]
        instance_id = kwargs["instance_id"]

        # Cloudmesh database instance
        db = CloudmeshDatabase()

        # Lookup instance details from db
        if cls.isUuid(instance_id):
            instance_dict = db.find(kind="vm",
                                    category=cloudname,
                                    uuid=instance_id)
        else:
            instance_dict = db.find(kind="vm",
                                    category=cloudname,
                                    name=instance_id)

        # Instance not found in DB
        if cls.isDictEmpty(instance_dict):
            # auto detect instance_id feature
            vms = db.find("vm", category=cloudname)
            # check for each instance in db
            for vm in list(vms.values()):
                # if match found in either name/id
                if vm["uuid"].startswith(instance_id) or \
                        vm["name"].startswith(instance_id):
                    # confirm choice with user
                    print("Did you mean instance [{}] ? (y/n)".format(
                        vm["name"]))
                    choice = input().lower()
                    # if yes, return dict
                    if choice == 'y':
                        return vm
            return None
        else:
            return list(instance_dict.values())[0]
    def test_001(self):
        HEADING()
        d = self.d

        banner("VM Data")
        pprint(d.__dict__)

        banner("Add VM")
        cm = CloudmeshDatabase()

        name = "vm1"
        uuid = d.id

        vm = VM(name=name,
                uuid=uuid,
                type="VM",
                cloud="mycloud",
                **d)

        pprint (vm.__dict__)
        vm.bla = "bla"
        cm.add(vm)
        cm.save()


        banner("Get VM from Database")

        o = cm.find(VM, name=name).first()
        #o = cm.find_by_name(VM, name)
        pprint (o.__dict__)


        assert True
Exemple #22
0
    def find_instance_name(cls, **kwargs):
        """
        Method to find instance name
        :param kwargs:
        :return: instance_name
        """
        cloudname = kwargs["cloudname"]
        instance_id = kwargs["instance_id"]

        # Cloudmesh database instance
        db = CloudmeshDatabase()

        # Lookup instance details from db
        instance_dict = db.find(kind="vm",
                                category=cloudname,
                                uuid=instance_id)

        # Get instance_name for vm
        if len(instance_dict) > 0:
            instance_name = list(instance_dict.values())[0]["name"]

            return instance_name
Exemple #23
0
    def add_db(cls, **kwargs):
        cm = CloudmeshDatabase()

        kwargs['name'] = kwargs.get('script_name')

        db_obj = {0: {"batchjob": kwargs}}
        cm.add_obj(db_obj)
        cm.save()
Exemple #24
0
class Flavor(ListResource):
    cm = CloudmeshDatabase()

    @classmethod
    def refresh(cls, cloud):
        """
        This method would refresh the flavor list by first clearing
        the database, then inserting new data
        :param cloud: the cloud name
        """
        return cls.cm.refresh('flavor', cloud)

    @classmethod
    def list(cls, cloud, live=False, format="table"):
        """
        This method lists all flavors of the cloud
        :param cloud: the cloud name
        """
        # cm = CloudmeshDatabase()
        try:

            if live:
                cls.refresh(cloud)

            elements = cls.cm.find("flavor", category=cloud)

            # pprint(elements)

            (order, header) = CloudProvider(cloud).get_attributes("flavor")

            return dict_printer(elements,
                                order=order,
                                header=header,
                                output=format)
        except Exception as ex:
            Console.error(ex.message, ex)

    @classmethod
    def details(cls, cloud, id, live=False, format="table"):
        if live:
            cls.refresh(cloud)

        return CloudProvider(cloud).details('flavor', cloud, id, format)
Exemple #25
0
class Image(ListResource):
    cm = CloudmeshDatabase()

    @classmethod
    def refresh(cls, cloud):
        """
        This method would refresh the image list by first clearing
        the database, then inserting new data
        :param cloud: the cloud name
        """
        # Newly implemented refresh
        result = cls.cm.refresh("image", cloud)
        return result

    @classmethod
    def list(cls, cloud, format="table"):
        """
        This method lists all images of the cloud
        :param cloud: the cloud name
        """
        # TODO: make a CloudmeshDatabase without requiring the user=
        # cm = CloudmeshDatabase()

        try:
            elements = cls.cm.find("image", category=cloud)

            (order, header) = CloudProvider(cloud).get_attributes("image")

            return dict_printer(elements,
                                order=order,
                                header=header,
                                output=format)

        except Exception as ex:
            Console.error(ex.message, ex)

    @classmethod
    def details(cls, cloud, id, live=False, format="table"):
        if live:
            cls.refresh(cloud)

        return CloudProvider(cloud).details('image', cloud, id, format)
Exemple #26
0
class Counter(object):
    """
    A counter is used to keep track of some value that can be increased
    and is associated with a user. Typically it is used to increment the
    vm id or the job id.
    """
    cm = CloudmeshDatabase()

    @classmethod
    def incr(cls, name='counter', user=None):
        """
        increments the counter by one

        :param name: name of the counter
        :param user: username associated with the counter
        :return:
        """
        cls.cm.counter_incr(name=name, user=user)

    @classmethod
    def get(cls, name='counter', user=None):
        """
        returns the value of the counter

        :param name: name of the counter
        :param user: username associated with the counter
        :return: the value of the counter
        """
        return cls.cm.counter_get(name=name, user=user)

    @classmethod
    def set(cls, name='counter', value=None, user=None):
        """
        sets a counter associated with a particular user
        :param name: name of the counter
        :param user: username associated with the counter
        :param value: the value
        :return:
        """
        cls.cm.counter_set(name=name, value=value, user=user)
Exemple #27
0
class Mesh(object):
    """
    Design decision. Bellow we like to implement actually a type detection that based on
    one specifying a single string or a list does the right things
    I am not yet sure how to reflect this in the :type: but we can probably sat
    str or list of str

    example:

    delete("myvm1")
    delete("myvm2")
    delete("myvm1", "myvm2")
    delete(["myvm1", "myvm2"])

    are doing all the same thing

    the way we do this is we implement for lists and than mak the other call
    recursively to a list

    We start simply with a print msg

    """

    t_flavour = "flavour"
    t_image = "image"
    t_vm = "vm"

    def __init__(self):
        self.db = CloudmeshDatabase()

    @classmethod
    def clouds(self, format='json', order=None):
        filename = "cloudmesh.yaml"
        config = ConfigDict(filename)
        yaml_clouds = dict(config["cloudmesh"]["clouds"])
        return dict_printer(yaml_clouds, output=format, order=order)

    @classmethod
    def verify(self):
        print("verify")

    @classmethod
    def refresh(self):
        print("refresh")

    @classmethod
    def register(self):
        print("register")
        self.db.update(['vm', 'image', 'flavor'], ['india', 'aws', 'azure'])

    """
    @classmethod
    def key_add(self, *args):
        print ("key add")
        sshm = SSHKeyManager()
        sshdb = SSHKeyDBManager()
        print len(args)
        if len(args) == 1:
            if os.path.isdir(path_expand(args[0])):
                sshm.get_from_dir(args[0])
                print sshm
                for key in sshm.__keys__:
                    print key
                    print sshm.__keys__[key]['comment']
                    sshdb.add_from_sshkey(sshm.__keys__[key], key)
            else:  # args is the github username
                sshm.get_from_git(args[0])
                print args[0]
                for key in sshm.__keys__:
                    sshdb.add_from_sshkey(sshm.__keys__[key], key)
        elif len(args) == 2:
            keyname = args[0]
            path = path_expand(args[1])
            sshdb.add(path, keyname)


    def key_delete(self, keynames):
        sshdb = SSHKeyDBManager()
        names = keynames.split(',')
        for name in names:
            sshdb.delete(name)
    """

    @classmethod
    def clear(self):
        print("clear")
        self.db.delete_all(["VM", "FLAVOR", "IMAGE", "DFAULT"])

    @classmethod
    def dump(self, filename):
        """

        :param filename: name of the db file that will receive the content of cloudmesh.db
        :return:
        """
        from_file = path_expand("~/.cloudmesh/cloudmesh.db")
        to_file = path_expand("~/.cloudmesh/{}".format(filename))
        shutil.copyfile(from_file, to_file)
        print("dump")

    @classmethod
    def load(self, filename):
        """

        :param filename: name of the db file located on ./cloudmesh that will be copied do cloudmesh.db
        :return:
        """
        print("load")
        from_file = path_expand("~/.cloudmesh/{}".format(filename))
        to_file = path_expand("~/.cloudmesh/cloudmesh.db")
        shutil.copyfile(from_file, to_file)

    @classmethod
    def vms(self, clouds):
        if isinstance(clouds, str):
            return self.vms(kind, [clouds], output)

        for cloud in clouds:
            print("get vm ids from ", cloud)

    @classmethod
    def list(self, kind, clouds, output="table"):
        """
        Lists the IaaS objects such as flavors, images, vms in the specified output format.

        :param kind: flavor, image, vm
        :type kind: str
        :param clouds: list of clouds we list
        :type clouds: list of str
        :param output: json, yaml, table
        :type output: str
        :return:
        """
        if isinstance(clouds, str):
            return self.list(kind, [clouds], output)

        for cloud in clouds:
            if kind in ["f", "flavour"]:
                print("flavor", cloud)
            elif kind in ["v", "vm"]:
                print("vm", cloud)
            elif kind in ["i", "image"]:
                print("image", cloud)
            else:
                print("kind", kind, "not supported")
        return "done"

    @classmethod
    def boot(self,
             cloud=None,
             image=None,
             flavor=None,
             key=None,
             arguments=None):
        """
        Boots the image on a specified cloud

        :param image: The name of the image
        :type image: str
        :param flavor: The name of the flavor
        :type flavor: str
        :param key: The name of the key
        :type key: str
        :param cloud: The name of the cloud
        :type cloud: str
        :param arguments: An array of arguments
        :type arguments: list of str
        :return: the id of the vm
        :rtype: str
        """
        if cloud is None:
            cloud = Default.get("cloud", "general")
            print("get default cloud: " + str(cloud))
        if image is None:
            image = Default.get("image", cloud)
            print("get default image ", str(image))
        if flavor is None:
            flavor = Default.get("flavor", cloud)
            print("get default flavor ", str(flavor))
        if key is None:
            key = Default.get("key", str(cloud))
            print("get default key ", str(key))

        # command_key

        print("boot an image", image, flavor, key, cloud, arguments)
        pass

    @classmethod
    def delete(self, ids):
        """
        delete the vms

        Example:

            delete("gregor-[001-010]")

        :param ids: host ids specified in hostlist format
        :return:
        """
        names = Parameter.expand(ids)
        for name in names:
            print("delete", name)

    @classmethod
    def _generate_name(self, prefix, number, padding):
        """
        method to create a vm name from a prefix, with given padding of 0

        :param prefix: the prefix of the name
        :type prefix: str
        :param number: the number
        :type number: str or int
        :param padding: the number of 0 that are used for padding
        :type padding: str or int
        :return:
        """
        format_string = prefix + "-{0:0" + str(padding) + "}"
        return format_string.format(number)

    @classmethod
    def _parse_name(self, name):
        """
        returns the prefix, the number and the padding length

        :param name: the name to parse
        :type name: str
        :return: prefix, number, padding length
        :rtype: str, int, int
        """
        prefix, number = name.rsplit('-', 1)
        n = int(number)
        padding = len(number)
        return prefix, n, padding

    @classmethod
    def next_name(self, name):
        """
        generates the next name.

        Example:

            next_name("gregor-0001")

            gregor-0002

        :param name: the name
        :type name: str
        :return: the new name
        :rtype: str
        """
        prefix, n, padding = self._parse_name(name)
        n += 1
        return self._generate_name(prefix, n, padding)

    @classmethod
    def get_name(self):
        """gets the next name of a vm while increasing its index."""
        # the name format is written to the database based on a set_name
        # the database will contain an index that stores the current index.
        # if no name hase bee defined and this is accessed first the name
        # username-0001 will be used where username is your username
        return "notimplemented-0001"

    @classmethod
    def set_name(self, name):
        """

        :param name:
        :return:
        """
        """sets the name of a vm.
        The name is ended by a simple number. The number of 0 in it wil be used for padding.

        set_name("gregor-001")
        This information will be used when getting the next index. If the next index exceeds the padding
        we simply just increase the number.

        """
        prefix, n, padding = self.parse_name(name)
Exemple #28
0
 def __init__(self):
     self.db = CloudmeshDatabase()
Exemple #29
0
    def start(cls, name, count, cloud, image, flavor, group):
        """
        TODO: group has not been used yet. fix that

        starts a virtual Machine (VM) or a set of VMs

        :param name: name of the virtual machine
        :type name: string, None
        :param count: give the number of servers to start
        :type count: integer, None
        :param cloud: give a cloud to work on, if not given, selected or default cloud will be used
        :type cloud: integer, None
        :param image: image name
        :type image: string, None
        :param flavor:flavor name. m1.medium, for example
        :type flavor: string, None
        :param group: the group name of server
        :type group: string, None
        :return:
        """

        # TODO: vm start (without arguments) use default cloud, image, flavor, group.
        if cloud is None:  # use default values for cloud, image and flavor
            pass


        config = CloudRegister.get(cloud)
        if cm_type in ["openstack"]:
            provider = Provider.OPENSTACK
            OpenStack = get_driver(provider)
            try:
                cloud_credentials = config['credentials']
            except Exception, e:
                Console.error(e.message)
                return

            # TODO: THIS MAY BE JUST TRUE IF THE CERT PATH EXISTS IN CREDENTIAL

            # set path to cacert and enable ssl connection
            libcloud.security.CA_CERTS_PATH = [Config.path_expand(cloud_credentials['OS_CACERT'])]
            libcloud.security.VERIFY_SSL_CERT = True

            auth_url = "%s/tokens/" % cloud_credentials['OS_AUTH_URL']

            driver = OpenStack(cloud_credentials['OS_USERNAME'],
                               cloud_credentials['OS_PASSWORD'],
                               ex_force_auth_url=auth_url,
                               ex_tenant_name=cloud_credentials['OS_TENANT_NAME'],
                               ex_force_auth_version='2.0_password',
                               ex_force_service_region='regionOne')

            # obtain available images
            # type of images: <class 'libcloud.compute.base.NodeImage'>
            images = driver.list()
            if not [i for i in images if i.name == image]:
                Console.error("Image {:} not found".format(image))
                return
            image = [i for i in images if i.name == image][0]

            # sizes/flavors
            sizes = driver.list_sizes()
            if not [i for i in sizes if i.name == flavor]:
                Console.error("Flavor {:} not found".format(flavor))
                return
            size = [i for i in sizes if i.name == flavor][0]

            if count is None:
                count = 1
            count = int(count)

            def __findsufix():
                # TODO: THIS IS A BIG BUG AS THE NEXT VM NAME IS NOT MANAGED BY SUFFIX
                """
                    Virtual machine name (VM) format:
                      string-001, string-002, ..., string-n
                    returns the max sufix from the VM list. It will be used in the new vm name in order to avoid
                    VMs with the same name.

                    :return: max sufix
                    :return type: string
                """
                nodes = driver.list_nodes()
                sufix = 1
                for i in nodes:
                    n = 0
                    try:
                        n = int(i.name.split('-', 1)[1])  # not always is int(i.name.split('-', 1)[1] a digit
                    except:
                        pass
                    if sufix <= n:
                        sufix = n + 1
                sufix = str(sufix).zfill(3)
                return sufix

            # set vm name
            sufix = __findsufix()
            c = CloudmeshDatabase()
            if name is None:
                c.name(cloud_credentials['OS_USERNAME'] + "-" + sufix)
            else:
                c.name(name + "-" + sufix)

            # launch a new VM
            Console.ok("Booting Virtual Machine...")
            for i in range(0, count):
                name = c.get_name()
                try:
                    node = driver.create_node(name=name, image=image, size=size)
                except Exception, e:
                    Console.error("{:} virtual machines have not been created. {:}".format(count - i, e.message))
                    return
                c.name(c.next_name())
Exemple #30
0
    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 ""
Exemple #31
0
class Test_cloud_model(object):
    cm = CloudmeshDatabase()

    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):
        self.d = {
            'name': 'vm1',
            'cloud': 'india',
            'update': '2015-06-18 22:11:48 UTC',
            'user': '******',
            'extra': {'created': '2015-05-21T20:37:10Z',
                      'metadata': {'base_image_ref': '398746398798372493287',
                                   'description': None,
                                   'image_location': 'snapshot',
                                   'image_state': 'available',
                                   'image_type': 'snapshot',
                                   'instance_type_ephemeral_gb': '0',
                                   'instance_type_flavorid': '3',
                                   'instance_type_id': '1',
                                   'instance_type_memory_mb': '4096',
                                   'instance_type_name': 'm1.medium',
                                   'instance_type_root_gb': '40',
                                   'instance_type_rxtx_factor': '1.0',
                                   'instance_type_swap': '0',
                                   'instance_type_vcpus': '2',
                                   'instance_uuid': '386473678463876387',
                                   'kernel_id': None,
                                   'network_allocated': 'True',
                                   'owner_id': '36487264932876984723649',
                                   'ramdisk_id': None,
                                   'user_id': '762387463827463278649837'},
                      'minDisk': 40,
                      'minRam': 0,
                      'progress': 100,
                      'serverId': 'yiuksajhlkjahl',
                      'status': 'ACTIVE',
                      'updated': '2015-05-27T02:11:48Z'},
            'id': '39276498376478936247832687',
            'name': 'VM with Cloudmesh Configured Completely'
        }

        self.vm = {
            'extra': {'access_ip': '',
                      'availability_zone': 'nova',
                      'config_drive': '',
                      'created': '2015-06-19T00:06:58Z',
                      'disk_config': 'MANUAL',
                      'flavorId': '1',
                      'hostId': '',
                      'imageId': 'abcd',
                      'key_name': None,
                      'metadata': {},
                      'password': '******',
                      'tenantId': '1234',
                      'updated': '2015-06-19T00:06:58Z',
                      'uri': 'http://i5r.idp.iu.futuregrid.org/v2/1234/servers/abcd'},
            'id': '67f6bsf67a6b',
            'image': None,
            'name': 'vm2',
            'private_ips': [],
            'public_ips': [],
            'size': None,
            'state': 3
        }

        self.d = FlatDict(self.vm)

    # noinspection PyPep8Naming
    def tearDown(self):
        pass

    def test_000(self):
        result = self.run("cm refresh off")
        print

    def test_001(self):
        HEADING("check the model")

        self.cm.clean()

        d = self.d

        banner("VM Data", c='-')
        pprint(d.__dict__)
        assert d['extra__imageId'] == 'abcd'

        banner("Add VM", c='-')

        name = "vm1"
        uuid = d.id

        vm = VM_OPENSTACK(name=name,
                          user="******",
                          category=self.data.cloud,
                          **d)
        print(vm)
        banner("VM added", c='-')

        self.cm.add(vm)

        banner("Add VM", c='-')

        name = "vm2"
        uuid = d.id

        vm = VM_OPENSTACK(name=name,
                          user="******",
                          category=self.data.cloud,
                          **d)
        print(vm)
        banner("VM added", c='-')

        # pprint(vm.__dict__)
        # vm.bla = "bla"
        self.cm.add(vm)
        # self.cm.save()

        banner("Get VM from Database", c='-')

        vms = self.cm.find(kind="vm", name=name, output='dict')
        pprint(vms)
        assert len(vms) == 1
        assert vms[0]["name"] == name

    def test_002(self):
        HEADING("VM DB test")
        self.cm.clean()

        print("ADD TO OS ")

        d = {
            'user': "******",
            'category': self.data.cloud
        }
        for index in range(1, 6):
            name = "vm_" + str(index).zfill(3)
            banner(name)
            print("ADD", name)
            try:
                d['name'] = name
                d['uuid'] = "uuid_" + str(index)
                vm = VM_OPENSTACK(**d)
                pprint(vm.__dict__)
            except Exception as e:
                Console.error("issue adding vm", traceflag=True)
            self.cm.add(vm)
            print("VM added. ok")
        print("ADD TO LIBCLOUD ")
        for index in range(6, 11):
            name = "vm_" + str(index).zfill(3)
            banner(name)
            print("ADD", name)
            d['name'] = name
            d['uuid'] = "uuid_" + str(index)
            vm = VM_LIBCLOUD(**d)
            print("VM", vm.__dict__)
            self.cm.add(vm)
        self.cm.save()

        result = self.run("cm refresh off")
        print(result)

        vms = self.cm.find(kind="vm", scope="all", output='dict')
        pprint(vms)
        print (len(vms))
        assert len(vms) == 10


    def test_003(self):
        HEADING("find vm tables")

        print("---------")
        all_tables = self.cm.tables
        for t in all_tables:
            print(t.__tablename__, t.__kind__)

        print(all_tables)
        assert 'DEFAULT' in str(all_tables)

        # print ("---------")
        # vm_tables = self.cm.tables(kind="vm")
        # for t in vm_tables:
        #     print (t.__tablename__, t.__kind__)
        # assert len(vm_tables) == 2

    def test_004(self):
        HEADING("find vm tables")

        print("-------------")
        vm = self.cm.find(kind="vm", name="vm_001", scope='first')
        pprint(vm)
        assert vm.name == 'vm_001'

        print("-------------")
        vm = self.cm.find(kind="vm", name="vm_006", scope='first')
        pprint(vm)
        assert vm.name == 'vm_006'

        print("-------------")
        vms = self.cm.find(kind="vm", scope="all")
        pprint(vms)
        print(len(vms))
        assert len(vms) == 10
Exemple #32
0
from cmd3.console import Console
from cloudmesh_base.Shell import Shell
from os.path import expanduser
from libcloud.compute.types import Provider
from libcloud.compute.providers import get_driver
from cloudmesh_client.common.ConfigDict import ConfigDict
import libcloud.security
from cloudmesh_client.common.ConfigDict import Config
from time import sleep
from cloudmesh_client.db.CloudmeshDatabase import CloudmeshDatabase
from cloudmesh_client.common.hostlist import Parameter

cm = CloudmeshDatabase()


class Command_vm(object):
    # TODO DOES NOT INTERFACE WITH DATABASE

    @classmethod
    def start(cls, name, count, cloud, image, flavor, group):
        """
        TODO: group has not been used yet. fix that

        starts a virtual Machine (VM) or a set of VMs

        :param name: name of the virtual machine
        :type name: string, None
        :param count: give the number of servers to start
        :type count: integer, None
        :param cloud: give a cloud to work on, if not given, selected or default cloud will be used
        :type cloud: integer, None
Exemple #33
0
class Var(ListResource):
    """
    Cloudmesh contains the concept of defaults. Defaults can have
    categories (we will rename cloud to categories). A category can be a
    cloud name or the name 'general'. The category general is a 'global'
    name space and contains defaults of global value (in future we will
    rename the value to global).

    """

    cm = CloudmeshDatabase()
    """cm is  a static variable so that db is used uniformly."""
    @classmethod
    def list(cls, format="table", order=None, output=format):
        """
        lists the default values in the specified format.
        TODO: This method has a bug as it uses format and output,
        only one should be used.

        :param category: the category of the default value. If general is used
                      it is a special category that is used for global values.
        :param format: json, table, yaml, dict, csv
        :param order: The order in which the attributes are returned
        :param output: The output format.
        :return:
        """
        if order is None:
            order = ['name', 'value', 'user']
        try:
            d = cls.cm.all("var")
            return (Printer.dict_printer(d, order=order, output=format))
        except:
            return None

    #
    # GENERAL SETTER AND GETTER METHOD
    #

    @classmethod
    def set(cls, key, value, user=None):
        """
        sets the default value for a given category
        :param key: the dictionary key of the value to store it at.
        :param value: the value
        :param user: the username to store this default value at.
        :return:
        """
        try:
            o = cls.get_object(key)

            me = cls.cm.user or user
            if o is None:
                o = cls.cm.db_obj_dict('var',
                                       name=key,
                                       value=value,
                                       category="var",
                                       user=me)
                cls.cm.add_obj(o)
            else:
                o.value = value
                cls.cm.add(o)
                # cls.cm.update(o)
            cls.cm.save()
        except:
            return None

    @classmethod
    def get_object(cls, key):
        """
        returns the first object that matches the key in teh Default
        database.

        :param key: The dictionary key
        :param category: The category
        :return:
        """
        try:
            arguments = {'name': key}
            o = cls.cm.find('var', output='object', **arguments).first()
            return o
        except Exception:
            return None

    @classmethod
    def get(cls, key):
        """
        returns the value of the first objects matching the key
        with the given category.

        :param key: The dictionary key
        :param category: The category
        :return:
        """
        arguments = {'name': key}
        o = cls.cm.find('var', output='dict', scope='first', **arguments)
        if o is not None:
            return o['value']
        else:
            return None

    @classmethod
    def delete(cls, key):
        try:
            o = Var.get_object(key)
            if o is not None:
                cls.cm.delete(o)
                return "Deletion. ok."
            else:
                return None
        except:
            return None

    @classmethod
    def clear(cls):
        """
        deletes all default values in the database.
        :return:
        """
        try:
            d = cls.cm.all('var')
            for item in d:
                name = d[item]["name"]
                cls.cm.delete_by_name('var', name)
            cls.cm.save()
        except:
            return None
Exemple #34
0
class Vm(ListResource):
    cm = CloudmeshDatabase()

    @classmethod
    def construct_ip_dict(cls, ip_addr, name="kilo"):
        try:
            d = ConfigDict("cloudmesh.yaml")
            cloud_details = d["cloudmesh"]["clouds"][name]

            # Handle Openstack Specific Output
            if cloud_details["cm_type"] == "openstack":
                ipaddr = {}
                for network in ip_addr:
                    index = 0
                    for ip in ip_addr[network]:
                        ipaddr[index] = {}
                        ipaddr[index]["network"] = network
                        ipaddr[index]["version"] = ip["version"]
                        ipaddr[index]["addr"] = ip["addr"]
                        index += 1
                return ipaddr

            # Handle EC2 Specific Output
            if cloud_details["cm_type"] == "ec2":
                print("ec2 ip dict yet to be implemented")
                TODO.implement()

            # Handle Azure Specific Output
            if cloud_details["cm_type"] == "azure":
                print("azure ip dict yet to be implemented")
                TODO.implement()

        except Exception as e:
            Error.error("error in vm construct dict", traceback=True)

    @classmethod
    def isUuid(cls, name):
        try:
            UUID(name, version=4)
            return True
        except ValueError:
            return False

    @classmethod
    def boot(cls, **kwargs):

        key_name = kwargs["key_name"]
        cloud_name = kwargs["cloud"]

        conf = ConfigDict("cloudmesh.yaml")
        username = conf["cloudmesh"]["profile"]["username"]

        keycloudmap = cls.cm.get_key_cloud_mapping(username, key_name, cloud_name)

        if keycloudmap is None or len(keycloudmap) == 0:
            raise RuntimeError("No key cloud mapping found for user {:}, key name {:} and cloud {:} in database."
                               .format(username, key_name, cloud_name))

        # print("Keycloudmap = {:}".format(keycloudmap))
        key_name_on_cloud = keycloudmap["key_name_on_cloud"]

        # print("Booting with key_name_on_cloud as " + key_name_on_cloud)

        cloud_provider = CloudProvider(cloud_name).provider

        if "nics" in kwargs:
            vm = cloud_provider.boot_vm(kwargs["name"],
                                        kwargs["image"],
                                        kwargs["flavor"],
                                        key=key_name_on_cloud,
                                        secgroup=kwargs["secgroup_list"],
                                        nics=kwargs["nics"])
        else:
            vm = cloud_provider.boot_vm(kwargs["name"],
                                        kwargs["image"],
                                        kwargs["flavor"],
                                        key=key_name_on_cloud,
                                        secgroup=kwargs["secgroup_list"],
                                        nics=None)

        print("Machine {:} is being booted on {:} Cloud...".format(kwargs["name"], cloud_provider.cloud))
        return vm

    @classmethod
    def start(cls, **kwargs):
        cloud_provider = CloudProvider(kwargs["cloud"]).provider
        for server in kwargs["servers"]:
            cloud_provider.start_vm(server)
            print("Machine {:} is being started on {:} Cloud...".format(server, cloud_provider.cloud))

            # Explicit refresh called after VM start, to update db.
            # cls.refresh(cloud=kwargs["cloud"])

    @classmethod
    def stop(cls, **kwargs):
        cloud_provider = CloudProvider(kwargs["cloud"]).provider
        for server in kwargs["servers"]:
            cloud_provider.stop_vm(server)
            print("Machine {:} is being stopped on {:} Cloud...".format(server, cloud_provider.cloud))

            # Explicit refresh called after VM stop, to update db.
            # cls.refresh(cloud=kwargs["cloud"])

    @classmethod
    def delete(cls, **kwargs):
        cloud_provider = CloudProvider(kwargs["cloud"]).provider
        for server in kwargs["servers"]:
            cloud_provider.delete_vm(server)
            print("Machine {:} is being deleted on {:} Cloud...".format(server, cloud_provider.cloud))

            # Explicit refresh called after VM delete, to update db.
            cls.refresh(cloud=kwargs["cloud"])

    @classmethod
    def rename(cls, **kwargs):
        cloud_provider = CloudProvider(kwargs["cloud"]).provider
        new_name = kwargs["new_name"]
        for server in kwargs["servers"]:
            cloud_provider.rename_vm(server, new_name)
            print("Machine {:} renamed to {:} on {:} Cloud...".format(server, new_name, cloud_provider.cloud))

            # Explicit refresh called after VM delete, to update db.
            cls.refresh(cloud=kwargs["cloud"])

    @classmethod
    def info(cls, **kwargs):
        raise NotImplementedError()

    @classmethod
    def list(cls, **kwargs):
        """
        This method lists all VMs of the cloud
        """

        try:
            if "name_or_id" in kwargs and kwargs["name_or_id"] is not None:
                if cls.isUuid(kwargs["name_or_id"]):
                    elements = cls.cm.find("vm",
                                           category=kwargs["cloud"],
                                           uuid=kwargs["name_or_id"])
                else:
                    elements = cls.cm.find("vm",
                                           category=kwargs["cloud"],
                                           label=kwargs["name_or_id"])
            else:
                elements = cls.cm.find("vm",
                                       category=kwargs["cloud"])

            # print(elements)

            # order = ['id', 'uuid', 'name', 'cloud']
            (order, header) = CloudProvider(kwargs["cloud"]).get_attributes("vm")

            # order = None
            if "name_or_id" in kwargs and kwargs["name_or_id"] is not None:
                return attribute_printer(list(elements.values())[0],
                                         output=kwargs["output_format"])
            else:
                return dict_printer(elements,
                                    order=order,
                                    output=kwargs["output_format"])
        except Exception as ex:
            Console.error(ex.message, ex)

    @classmethod
    def clear(cls, **kwargs):
        raise NotImplementedError()

    @classmethod
    def refresh(cls, **kwargs):
        # print("Inside refresh")
        return cls.cm.refresh("vm", kwargs["cloud"])

    @classmethod
    def status_from_cloud(cls, **kwargs):
        cloud_provider = CloudProvider(kwargs["cloud"]).provider
        vm = cloud_provider.get_vm(name=kwargs["name_or_id"])
        return vm["status"]

    @classmethod
    def set_vm_login_user(cls, name_or_id, cloud, username):

        if cls.isUuid(name_or_id):
            uuid = name_or_id
        else:
            vm_data = cls.cm.find("vm", category=cloud, label=name_or_id)
            if vm_data is None or len(vm_data) == 0:
                raise RuntimeError("VM with label {} not found in database.".format(name_or_id))
            uuid = list(vm_data.values())[0]["uuid"]

        user_map_entry = cls.cm.find("VMUSERMAP", vm_uuid=uuid)

        if user_map_entry is None or len(user_map_entry) == 0:
            user_map_dict = cls.cm.db_obj_dict("VMUSERMAP", vm_uuid=uuid, username=username)
            cls.cm.add_obj(user_map_dict)
            cls.cm.save()
        else:
            cls.cm.update_vm_username(vm_uuid=uuid, username=username)

    @classmethod
    def get_vm_login_user(cls, name_or_id, cloud):

        if cls.isUuid(name_or_id):
            uuid = name_or_id
        else:
            vm_data = cls.cm.find("vm", category=cloud, label=name_or_id)
            if vm_data is None or len(vm_data) == 0:
                raise RuntimeError("VM with label {} not found in database.".format(name_or_id))
            uuid = list(vm_data.values())[0]["uuid"]

        # print(uuid)

        user_map_entry = cls.cm.find("VMUSERMAP", vm_uuid=uuid)

        # print(user_map_entry)

        if user_map_entry is None or len(user_map_entry) == 0:
            return None
        else:
            return list(user_map_entry.values())[0]["username"]

    @classmethod
    def get_last_vm(cls, cloud):
        vm_data = cls.cm.find("vm", scope="first", category=cloud)
        if vm_data is None or len(vm_data) == 0:
            raise RuntimeError("VM data not found in database.")
        return vm_data
Exemple #35
0
    def start(cls, name, count, cloud, image, flavor, group):
        """
        TODO: group has not been used yet. fix that

        starts a virtual Machine (VM) or a set of VMs

        :param name: name of the virtual machine
        :type name: string, None
        :param count: give the number of servers to start
        :type count: integer, None
        :param cloud: give a cloud to work on, if not given, selected or default cloud will be used
        :type cloud: integer, None
        :param image: image name
        :type image: string, None
        :param flavor:flavor name. m1.medium, for example
        :type flavor: string, None
        :param group: the group name of server
        :type group: string, None
        :return:
        """

        # TODO: vm start (without arguments) use default cloud, image, flavor, group.
        if cloud is None:  # use default values for cloud, image and flavor
            pass


        config = CloudRegister.get(cloud)
        if cm_type in ["openstack"]:
            provider = Provider.OPENSTACK
            OpenStack = get_driver(provider)
            try:
                cloud_credentials = config['credentials']
            except Exception as e:
                Console.error(e.message)
                return

            # TODO: THIS MAY BE JUST TRUE IF THE CERT PATH EXISTS IN CREDENTIAL

            # set path to cacert and enable ssl connection
            libcloud.security.CA_CERTS_PATH = [Config.path_expand(cloud_credentials['OS_CACERT'])]
            libcloud.security.VERIFY_SSL_CERT = True

            auth_url = "%s/tokens/" % cloud_credentials['OS_AUTH_URL']

            driver = OpenStack(cloud_credentials['OS_USERNAME'],
                               cloud_credentials['OS_PASSWORD'],
                               ex_force_auth_url=auth_url,
                               ex_tenant_name=cloud_credentials['OS_TENANT_NAME'],
                               ex_force_auth_version='2.0_password',
                               ex_force_service_region='regionOne')

            # obtain available images
            # type of images: <class 'libcloud.compute.base.NodeImage'>
            images = driver.list()
            if not [i for i in images if i.name == image]:
                Console.error("Image {:} not found".format(image))
                return
            image = [i for i in images if i.name == image][0]

            # sizes/flavors
            sizes = driver.list_sizes()
            if not [i for i in sizes if i.name == flavor]:
                Console.error("Flavor {:} not found".format(flavor))
                return
            size = [i for i in sizes if i.name == flavor][0]

            if count is None:
                count = 1
            count = int(count)

            def __findsufix():
                # TODO: THIS IS A BIG BUG AS THE NEXT VM NAME IS NOT MANAGED BY SUFFIX
                """
                    Virtual machine name (VM) format:
                      string-001, string-002, ..., string-n
                    returns the max sufix from the VM list. It will be used in the new vm name in order to avoid
                    VMs with the same name.

                    :return: max sufix
                    :return type: string
                """
                nodes = driver.list_nodes()
                sufix = 1
                for i in nodes:
                    n = 0
                    try:
                        n = int(i.name.split('-', 1)[1])  # not always is int(i.name.split('-', 1)[1] a digit
                    except:
                        pass
                    if sufix <= n:
                        sufix = n + 1
                sufix = str(sufix).zfill(3)
                return sufix

            # set vm name
            sufix = __findsufix()
            c = CloudmeshDatabase()
            if name is None:
                c.name(cloud_credentials['OS_USERNAME'] + "-" + sufix)
            else:
                c.name(name + "-" + sufix)

            # launch a new VM
            Console.ok("Booting Virtual Machine...")
            for i in range(0, count):
                name = c.get_name()
                try:
                    node = driver.create_node(name=name, image=image, size=size)
                except Exception as e:
                    Console.error("{:} virtual machines have not been created. {:}".format(count - i, e.message))
                    return
                c.name(c.next_name())

            # wait the node to be ready before assigning public IP
            sleep(10)
            Console.ok("Virtual Machine created")
        else:
            Console.error('cloud {:} not found'.format(cloud))
Exemple #36
0
class SecGroup(ListResource):
    cm_db = CloudmeshDatabase(
    )  # Instance to communicate with the cloudmesh database

    @classmethod
    def convert_list_to_dict(cls, os_result):
        d = {}
        for i, obj in enumerate(os_result):
            d[i] = {}
            d[i]["Id"] = obj.id
            d[i]["Name"] = obj.name
            d[i]["Description"] = obj.description
        return d

    # noinspection PyPep8
    @classmethod
    def convert_rules_to_dict(cls, os_result):
        d = {}
        for i, obj in enumerate(os_result):
            d[i] = {}
            d[i]["IP Protocol"] = obj["ip_protocol"]
            d[i]["From Port"] = obj["from_port"]
            d[i]["To Port"] = obj["to_port"]
            if obj["ip_range"]["cidr"]:
                ip_range = obj["ip_range"]["cidr"]
            else:
                ip_range = "0.0.0.0/0"
            d[i]["IP Range"] = ip_range

        return d

    @classmethod
    def refresh(cls, cloud):
        """
        This method would refresh the secgroup list by first clearing
        the database, then inserting new data
        :param cloud: the cloud name
        """
        return cls.cm_db.refresh('secgroup', cloud)

    # noinspection PyPep8Naming
    @classmethod
    def remove_subjectAltName_warning(cls, content):
        result = []
        for line in content.split("\n"):
            if "Certificate has no `subjectAltName`" in line:
                pass
            elif "SecurityWarning" in line:
                pass
            else:
                result.append(line)
        return "\n".join(result)

    @classmethod
    def create(cls, label, cloud=None):
        """
        Method creates a new security group in database
        & returns the uuid of the created group
        :param label:
        :param cloud:
        :param tenant:
        :return:
        """
        # Create the security group in given cloud
        try:
            cloud_provider = CloudProvider(cloud).provider
            secgroup = cloud_provider.create_secgroup(label)
            if secgroup:
                uuid = secgroup.id
                return uuid
            else:
                print("Failed to create security group, {}".format(secgroup))
        except Exception as e:
            print("Exception creating security group in cloud, {}".format(e))

        return None

    @classmethod
    def list(cls, cloud="general", format="table"):
        """
        This method queries the database to fetch list of secgroups
        filtered by cloud.
        :param cloud:
        :return:
        """
        try:
            elements = cls.cm_db.find("secgroup", category=cloud)
            #pprint(elements)
            (order, header) = CloudProvider(cloud).get_attributes("secgroup")

            return dict_printer(elements,
                                order=order,
                                header=header,
                                output=format)

        except Exception as ex:
            Console.error(ex.message, ex)

    @classmethod
    def enable_ssh(cls, secgroup_name='default', cloud="general"):
        ret = False
        cloud_provider = CloudProvider(cloud).provider.provider
        secgroups = cloud_provider.security_groups.list()
        for asecgroup in secgroups:
            if asecgroup.name == secgroup_name:
                rules = asecgroup.rules
                rule_exists = False
                # structure of a secgroup rule:
                # {u'from_port': 22, u'group': {}, u'ip_protocol': u'tcp', u'to_port': 22, u'parent_group_id': u'UUIDHERE', u'ip_range': {u'cidr': u'0.0.0.0/0'}, u'id': u'UUIDHERE'}
                for arule in rules:
                    if arule["from_port"] == 22 and \
                                    arule["to_port"] == 22 and \
                                    arule["ip_protocol"] == 'tcp' and \
                                    arule["ip_range"] == {'cidr': '0.0.0.0/0'}:
                        # print (arule["id"])
                        rule_exists = True
                        break
                if not rule_exists:
                    cloud_provider.security_group_rules.create(
                        asecgroup.id,
                        ip_protocol='tcp',
                        from_port=22,
                        to_port=22,
                        cidr='0.0.0.0/0')
                # else:
                #    print ("The rule allowing ssh login did exist!")
                ret = True
                break

        # print ("*" * 80)
        # d = SecGroup.convert_list_to_dict(secgroups)
        # print (d)
        return ret

    @classmethod
    def get(cls, name, cloud="general"):
        """
        This method queries the database to fetch secgroup
        with given name filtered by cloud.
        :param name:
        :param cloud:
        :return:
        """
        try:
            args = {
                "name": name,
                "category": cloud,
            }
            secgroup = cls.cm_db.find("secgroup", output="object",
                                      **args).first()
            return secgroup

        except Exception as ex:
            Console.error(ex.message, ex)

    @classmethod
    def add_rule(cls, cloud, secgroup, from_port, to_port, protocol, cidr):
        try:
            # Get the nova client object
            cloud_provider = CloudProvider(cloud).provider

            # Create add secgroup rules to the cloud
            args = {
                'uuid': secgroup.uuid,
                'protocol': protocol,
                'from_port': from_port,
                'to_port': to_port,
                'cidr': cidr
            }
            rule_id = cloud_provider.add_secgroup_rule(**args)

            # create local db record
            ruleObj = cls.cm_db.db_obj_dict("secgrouprule",
                                            uuid=str(rule_id),
                                            name=secgroup.name,
                                            groupid=secgroup.uuid,
                                            category=secgroup.category,
                                            user=secgroup.user,
                                            project=secgroup.project,
                                            fromPort=from_port,
                                            toPort=to_port,
                                            protocol=protocol,
                                            cidr=cidr)

            cls.cm_db.add_obj(ruleObj)
            cls.cm_db.save()

            Console.ok(
                "Added rule [{} | {} | {} | {}] to secgroup [{}]".format(
                    from_port, to_port, protocol, cidr, secgroup.name))
        except Exception as ex:
            if "This rule already exists" in ex.message:
                Console.ok("Rule already exists. Added rule.")
                return
            else:
                Console.error(ex.message, ex)
        return

    @classmethod
    def get_rules(cls, uuid):
        """
        This method gets the security group rule
        from the cloudmesh database
        :param uuid:
        :return:
        """
        try:
            args = {"groupid": uuid}

            rule = cls.cm_db.find("secgrouprule", **args)

            # check if rules exist
            if rule is None:
                return "No rules for security group [{}] in the database. Try cm secgroup refresh."

            # return table
            return (dict_printer(rule,
                                 order=[
                                     "user", "category", "name", "fromPort",
                                     "toPort", "protocol", "cidr"
                                 ],
                                 output="table"))

        except Exception as ex:
            Console.error(ex.message, ex)

        return None

    @classmethod
    def delete_secgroup(cls, label, cloud):
        try:
            # Find the secgroup from the cloud
            cloud_provider = CloudProvider(cloud).provider
            result = cloud_provider.delete_secgroup(label)
            return result
        except Exception as ex:
            Console.error(ex.message, ex)

    @classmethod
    def delete_rule(cls, cloud, secgroup, from_port, to_port, protocol, cidr):
        try:
            args = {
                "groupid": secgroup.uuid,
                "fromPort": from_port,
                "toPort": to_port,
                "protocol": protocol,
                "cidr": cidr
            }

            rule = cls.cm_db.find("secgrouprule", output="object",
                                  **args).first()

            if rule is not None:
                # get the nova client for cloud
                cloud_provider = CloudProvider(cloud).provider
                # delete the rule from the cloud
                cloud_provider.delete_secgroup_rule(rule.uuid)
                # delete the local db record
                cls.cm_db.delete(rule)
                return "Rule [{} | {} | {} | {}] deleted" \
                    .format(from_port, to_port, protocol, cidr)
            else:
                return None

        except Exception as ex:
            Console.error(ex.message, ex)

        return

    @classmethod
    def delete_all_rules(cls, secgroup):
        try:

            args = {"groupid": secgroup.uuid}
            rules = cls.cm_db.find("secgrouprule", output="object", **args)

            if rules is not None:
                for rule in rules:
                    cls.cm_db.delete(rule)
                    Console.ok("Rule [{} | {} | {} | {}] deleted".format(
                        rule.fromPort, rule.toPort, rule.protocol, rule.cidr))
            else:
                pass
        except Exception as ex:
            Console.error(ex.message, ex)

        return

    @classmethod
    def toDict(cls, item):
        """
        Method converts the item to a dict
        :param item:
        :return:
        """
        # Convert to dict & print table
        d = {}
        # If list, iterate to form dict
        if isinstance(item, list):
            for element in item:
                d[element.id] = {}
                for key in element.__dict__.keys():
                    if not key.startswith("_sa"):
                        d[element.id][key] = str(element.__dict__[key])
        # Form dict without iterating
        else:
            d[item.id] = {}
            for key in item.__dict__.keys():
                if not key.startswith("_sa"):
                    d[item.id][key] = str(item.__dict__[key])

        # return the dict
        return d
Exemple #37
0
class List(object):
    cm = CloudmeshDatabase()
    # Instance to communicate with the cloudmesh database

    @classmethod
    def list(cls,
             kind,
             cloud,
             user=None,
             tenant=None,
             order=None,
             header=None,
             output="table"):
        """
        Method lists the data in the db for
        given cloud and of given kind
        :param kind:
        :param cloud:
        :param tenant:
        :param user:
        :param order:
        :param header:
        :param output:
        :return:
        """
        try:
            # get the model object
            table = cls.cm.get_table(kind)

            filter = {}
            if cloud is not None:
                filter["category"] = cloud
            if user is not None:
                filter["user"] = user
            if tenant is not None:
                filter["tenant"] = tenant

            elements = cls.cm.find(table, **filter)

            if elements is not None or elements is not {}:
                # convert the output to a dict
                return (dict_printer(elements,
                                     order=order,
                                     header=header,
                                     output=output))
            else:
                return None

        except Exception as ex:
            Console.error(ex.message, ex)

    #
    # TODO: don't we have not already a conversion method
    #
    @classmethod
    def toDict(cls, item):
        """
        Method converts the item to a dict
        :param item:
        :return:
        """
        # Convert to dict & print table
        d = {}
        # If list, iterate to form dict
        if isinstance(item, list):
            for element in item:
                d[element.id] = {}
                for key in list(element.__dict__.keys()):
                    if not key.startswith("_sa"):
                        d[element.id][key] = str(element.__dict__[key])
        # Form dict without iterating
        else:
            d[item.id] = {}
            for key in list(item.__dict__.keys()):
                if not key.startswith("_sa"):
                    d[item.id][key] = str(item.__dict__[key])

        # return the dict
        return d
Exemple #38
0
class Mesh(object):
    """
    Design decision. Bellow we like to implement actually a type detection that based on
    one specifying a single string or a list does the right things
    I am not yet sure how to reflect this in the :type: but we can probably sat
    str or list of str

    example:

    delete("myvm1")
    delete("myvm2")
    delete("myvm1", "myvm2")
    delete(["myvm1", "myvm2"])

    are doing all the same thing

    the way we do this is we implement for lists and than mak the other call
    recursively to a list

    We start simply with a print msg

    """

    t_flavour = "flavour"
    t_image = "image"
    t_vm = "vm"

    def __init__(self):
        self.db = CloudmeshDatabase()

    @classmethod
    def clouds(self, format="json", order=None):
        filename = "cloudmesh.yaml"
        config = ConfigDict(filename)
        yaml_clouds = dict(config["cloudmesh"]["clouds"])
        return dict_printer(yaml_clouds, output=format, order=order)

    @classmethod
    def verify(self):
        print("verify")

    @classmethod
    def refresh(self):
        print("refresh")

    @classmethod
    def register(self):
        print("register")
        self.db.update(["vm", "image", "flavor"], ["india", "aws", "azure"])

    """
    @classmethod
    def key_add(self, *args):
        print ("key add")
        sshm = SSHKeyManager()
        sshdb = SSHKeyDBManager()
        print len(args)
        if len(args) == 1:
            if os.path.isdir(path_expand(args[0])):
                sshm.get_from_dir(args[0])
                print sshm
                for key in sshm.__keys__:
                    print key
                    print sshm.__keys__[key]['comment']
                    sshdb.add_from_sshkey(sshm.__keys__[key], key)
            else:  # args is the github username
                sshm.get_from_git(args[0])
                print args[0]
                for key in sshm.__keys__:
                    sshdb.add_from_sshkey(sshm.__keys__[key], key)
        elif len(args) == 2:
            keyname = args[0]
            path = path_expand(args[1])
            sshdb.add(path, keyname)


    def key_delete(self, keynames):
        sshdb = SSHKeyDBManager()
        names = keynames.split(',')
        for name in names:
            sshdb.delete(name)
    """

    @classmethod
    def clear(self):
        print("clear")
        self.db.delete_all(["VM", "FLAVOR", "IMAGE", "DFAULT"])

    @classmethod
    def dump(self, filename):
        """

        :param filename: name of the db file that will receive the content of cloudmesh.db
        :return:
        """
        from_file = path_expand("~/.cloudmesh/cloudmesh.db")
        to_file = path_expand("~/.cloudmesh/{}".format(filename))
        shutil.copyfile(from_file, to_file)
        print("dump")

    @classmethod
    def load(self, filename):
        """

        :param filename: name of the db file located on ./cloudmesh that will be copied do cloudmesh.db
        :return:
        """
        print("load")
        from_file = path_expand("~/.cloudmesh/{}".format(filename))
        to_file = path_expand("~/.cloudmesh/cloudmesh.db")
        shutil.copyfile(from_file, to_file)

    @classmethod
    def vms(self, clouds):
        if isinstance(clouds, str):
            return self.vms(kind, [clouds], output)

        for cloud in clouds:
            print("get vm ids from ", cloud)

    @classmethod
    def list(self, kind, clouds, output="table"):
        """
        Lists the IaaS objects such as flavors, images, vms in the specified output format.

        :param kind: flavor, image, vm
        :type kind: str
        :param clouds: list of clouds we list
        :type clouds: list of str
        :param output: json, yaml, table
        :type output: str
        :return:
        """
        if isinstance(clouds, str):
            return self.list(kind, [clouds], output)

        for cloud in clouds:
            if kind in ["f", "flavour"]:
                print("flavor", cloud)
            elif kind in ["v", "vm"]:
                print("vm", cloud)
            elif kind in ["i", "image"]:
                print("image", cloud)
            else:
                print("kind", kind, "not supported")
        return "done"

    @classmethod
    def boot(self, cloud=None, image=None, flavor=None, key=None, arguments=None):
        """
        Boots the image on a specified cloud

        :param image: The name of the image
        :type image: str
        :param flavor: The name of the flavor
        :type flavor: str
        :param key: The name of the key
        :type key: str
        :param cloud: The name of the cloud
        :type cloud: str
        :param arguments: An array of arguments
        :type arguments: list of str
        :return: the id of the vm
        :rtype: str
        """
        if cloud is None:
            cloud = Default.get("cloud", "general")
            print("get default cloud: " + str(cloud))
        if image is None:
            image = Default.get("image", cloud)
            print("get default image ", str(image))
        if flavor is None:
            flavor = Default.get("flavor", cloud)
            print("get default flavor ", str(flavor))
        if key is None:
            key = Default.get("key", str(cloud))
            print("get default key ", str(key))

        # command_key

        print("boot an image", image, flavor, key, cloud, arguments)
        pass

    @classmethod
    def delete(self, ids):
        """
        delete the vms

        Example:

            delete("gregor-[001-010]")

        :param ids: host ids specified in hostlist format
        :return:
        """
        names = Parameter.expand(ids)
        for name in names:
            print("delete", name)

    @classmethod
    def _generate_name(self, prefix, number, padding):
        """
        method to create a vm name from a prefix, with given padding of 0

        :param prefix: the prefix of the name
        :type prefix: str
        :param number: the number
        :type number: str or int
        :param padding: the number of 0 that are used for padding
        :type padding: str or int
        :return:
        """
        format_string = prefix + "-{0:0" + str(padding) + "}"
        return format_string.format(number)

    @classmethod
    def _parse_name(self, name):
        """
        returns the prefix, the number and the padding length

        :param name: the name to parse
        :type name: str
        :return: prefix, number, padding length
        :rtype: str, int, int
        """
        prefix, number = name.rsplit("-", 1)
        n = int(number)
        padding = len(number)
        return prefix, n, padding

    @classmethod
    def next_name(self, name):
        """
        generates the next name.

        Example:

            next_name("gregor-0001")

            gregor-0002

        :param name: the name
        :type name: str
        :return: the new name
        :rtype: str
        """
        prefix, n, padding = self._parse_name(name)
        n += 1
        return self._generate_name(prefix, n, padding)

    @classmethod
    def get_name(self):
        """gets the next name of a vm while increasing its index."""
        # the name format is written to the database based on a set_name
        # the database will contain an index that stores the current index.
        # if no name hase bee defined and this is accessed first the name
        # username-0001 will be used where username is your username
        return "notimplemented-0001"

    @classmethod
    def set_name(self, name):
        """

        :param name:
        :return:
        """
        """sets the name of a vm.
        The name is ended by a simple number. The number of 0 in it wil be used for padding.

        set_name("gregor-001")
        This information will be used when getting the next index. If the next index exceeds the padding
        we simply just increase the number.

        """
        prefix, n, padding = self.parse_name(name)
Exemple #39
0
 def __init__(self):
     self.db = CloudmeshDatabase()
Exemple #40
0
class Network(ListResource):
    cm = CloudmeshDatabase()

    @classmethod
    def get_fixed_ip(cls, cloudname, fixed_ip_addr, output='table'):
        """
        Method retrieves fixed ip info
        :param cloudname:
        :param fixed_ip_addr:
        :return: fixed_ip_info
        """
        try:
            cloud_provider = CloudProvider(cloudname).provider
            result = cloud_provider.get_fixed_ip(fixed_ip_addr=fixed_ip_addr)

            return Printer.attribute(result,
                                     header=["name", "value"],
                                     output=output)
        except Exception as ex:
            Console.error(ex.message)

        return

    @classmethod
    def get_floating_ip(cls, cloudname, floating_ip_or_id, output='table'):
        """
        Method to get floating ip info
        :param cloudname:
        :param floating_ip_or_id:
        :return: floating ip info
        """
        try:
            cloud_provider = CloudProvider(cloudname).provider
            result = None

            # check if argument is ip or uuid
            if cls.isIPAddr(ip_or_id=floating_ip_or_id):
                # get floating ip list
                floating_ips = cls.get_floating_ip_list(cloudname)
                for floating_ip in list(floating_ips):
                    ip_addr = floating_ip["ip"]

                    # if argument ip matches floating ip addr
                    if ip_addr == floating_ip_or_id:
                        result = floating_ip
                        break
            else:
                # find by floating ip uuid
                result = cloud_provider.get_floating_ip(
                    floating_ip_id=floating_ip_or_id)

            # Could not find floating IP from given args
            if result is None:
                return None

            instance_id = result["instance_id"]
            instance_name = None

            if instance_id is not None:
                # lookup instance_name from id
                instance_name = cls.find_instance_name(cloudname=cloudname,
                                                       instance_id=instance_id)

            # add instance_name to dict
            result["instance_name"] = instance_name

            # add misc details to response
            result["cloud"] = cloudname
            result["user"] = cloud_provider.cloud_details["credentials"][
                "OS_USERNAME"]
            result["project"] = cloud_provider.cloud_details["credentials"][
                "OS_TENANT_NAME"]

            return Printer.attribute(result,
                                     header=["name", "value"],
                                     output=output)
        except Exception:
            # auto detect floating-ip-id
            floating_ips = cls.get_floating_ip_list(cloudname)
            # for each floating-ip from list
            for floating_ip in list(floating_ips):
                if floating_ip["id"].startswith(floating_ip_or_id) or \
                        floating_ip["ip"].startswith(floating_ip_or_id):
                    # confirm choice with user
                    print("Did you mean floating-ip [{}] ? (y/n)".format(
                        floating_ip["ip"]))
                    choice = input().lower()
                    # if yes, return dict
                    if choice == 'y':
                        return Printer.attribute(floating_ip,
                                                 header=["name", "value"],
                                                 output=output)
                        # Console.error(ex.message)
        return

    @classmethod
    def reserve_fixed_ip(cls, cloudname, fixed_ip_addr):
        """
        Reserve a fixed ip address
        :param cloudname:
        :param fixed_ip_addr:
        :return:
        """
        try:
            cloud_provider = CloudProvider(cloudname).provider
            cloud_provider.reserve_fixed_ip(fixed_ip_addr=fixed_ip_addr)
            return "Success."
        except Exception as ex:
            Console.error(ex.message)

        return

    @classmethod
    def unreserve_fixed_ip(cls, cloudname, fixed_ip_addr):
        """
        Unreserve a fixed ip address
        :param cloudname:
        :param fixed_ip_addr:
        :return:
        """
        try:
            cloud_provider = CloudProvider(cloudname).provider
            cloud_provider.unreserve_fixed_ip(fixed_ip_addr=fixed_ip_addr)
            return "Success."
        except Exception as ex:
            Console.error(ex.message)
            return ex

    @classmethod
    def associate_floating_ip(cls, cloudname, instance_name, floating_ip):
        """
        Method to associate floating ip to an instance
        :param cloudname:
        :param instance_name:
        :param floating_ip:
        :return:
        """
        try:
            cloud_provider = CloudProvider(cloudname).provider
            # Find the server instance
            server = cloud_provider.provider.servers.find(name=instance_name)
            # Add the floating ip to the instance
            server.add_floating_ip(floating_ip)
            return "Success."
        except Exception as ex:
            if "already has a floating" in ex.message:
                Console.error("VM has already floating ip", traceflag=False)
            else:
                Console.error(ex.message)
                return ex
        pass

    @classmethod
    def disassociate_floating_ip(cls, cloudname, instance_name, floating_ip):
        """
        Disassociates a floating ip from an instance
        :param cloudname:
        :param instance_name:
        :param floating_ip:
        :return:
        """
        try:
            cloud_provider = CloudProvider(cloudname).provider
            # Find the server instance
            server = cloud_provider.provider.servers.find(name=instance_name)
            # Remove the floating ip from the instance
            server.remove_floating_ip(floating_ip)
            # Release the floating ip to the pool
            cls.delete_floating_ip(cloudname=cloudname,
                                   floating_ip_or_id=floating_ip)
            return "Success."
        except Exception as ex:
            Console.error(ex.message)
            return ex
        pass

    @classmethod
    def create_assign_floating_ip(cls, cloudname, instance_name):
        """
        Method to create a new floating-ip
        and associate it with the instance
        :param cloudname: cloud
        :param instance_name: name of instance
        :return: floating_ip
        """
        try:
            cloud_provider = CloudProvider(cloudname).provider
            floating_ip = cloud_provider.create_assign_floating_ip(
                instance_name)
            return floating_ip
        except Exception as ex:
            Console.error(ex.message)
            return

    @classmethod
    def create_floating_ip(cls, cloudname, floating_pool=None):
        """
        Method to create a floating ip address under a pool
        :param cloudname:
        :param floating_pool:
        :return: floating ip addr
        """
        try:
            cloud_provider = CloudProvider(cloudname).provider
            # If floating pool is not given,
            # get first from list
            if floating_pool is None:
                floating_pool = cloud_provider.provider.floating_ip_pools.list(
                )[0].name
                Console.ok(
                    "Floating pool not provided, selected [{}] as the pool.".
                    format(floating_pool))

            floating_ip = cloud_provider.create_floating_ip(
                float_pool=floating_pool)
            return floating_ip
        except Exception as ex:
            Console.error(ex.message)
            return

    @classmethod
    def delete_floating_ip(cls, cloudname, floating_ip_or_id):
        """
        Method to delete a floating ip address
        :param cloudname:
        :param floating_ip_or_id:
        :return:
        """
        try:
            cloud_provider = CloudProvider(cloudname).provider
            floating_ip_dict = None

            # check if argument is ip or uuid
            if cls.isIPAddr(ip_or_id=floating_ip_or_id):
                # get floating ip list
                floating_ips = cls.get_floating_ip_list(cloudname)
                for floating_ip in list(floating_ips):
                    ip_addr = floating_ip["ip"]

                    # if argument ip matches floating ip addr
                    if ip_addr == floating_ip_or_id:
                        floating_ip_dict = floating_ip
                        break
            else:
                # find by floating ip uuid
                floating_ip_dict = cloud_provider.get_floating_ip(
                    floating_ip_id=floating_ip_or_id)

            # Could not find floating IP from given args
            if floating_ip_dict is None:
                return None

            # Delete the floating ip; returns None if success
            result = cloud_provider.delete_floating_ip(floating_ip_dict["id"])

            if not result:
                return "Floating IP [{}] deleted successfully!" \
                    .format(floating_ip_dict["ip"])

        except Exception as ex:
            Console.error(ex.message)
            return

    @classmethod
    def list_floating_ip(cls, cloudname, output='table'):
        """
        Method to list floating ips
        :param cloudname:
        :return: floating ip list
        """
        try:
            floating_ips = cls.get_floating_ip_list(cloudname)

            for floating_ip in list(floating_ips.values()):
                # Get instance_id associated with instance
                instance_id = floating_ip["instance_id"]

                if instance_id is not None:
                    try:
                        instance_name = cls.find_instance_name(
                            cloudname=cloudname, instance_id=instance_id)
                        # Assign it to the dict
                        floating_ip["instance_name"] = instance_name
                        floating_ip["cloud"] = cloudname
                    except Exception as ex:
                        Console.error(ex.message)
                        continue
                else:
                    # If no instance associated, keep None
                    floating_ip["instance_name"] = None

            (order,
             header) = CloudProvider(cloudname).get_attributes("floating_ip")

            return Printer.write(floating_ips,
                                 order=order,
                                 header=header,
                                 output=output)
        except Exception as ex:
            Console.error(ex.message)

        return

    @classmethod
    def list_unused_floating_ip(cls, cloudname, output='table'):
        """
        Method to list unused floating ips
        These floating ips are not associated with any instance
        :param cloudname:
        :return: floating ip list
        """
        try:
            # fetch unused floating ips
            floating_ips = cls.get_unused_floating_ip_list(cloudname)

            # print the output
            return Printer.write(floating_ips,
                                 order=["ip", "pool", "id", "cloud"],
                                 header=[
                                     "floating_ip", "floating_ip_pool",
                                     "floating_ip_id", "cloud"
                                 ],
                                 output=output)
        except Exception as ex:
            Console.error(ex.message)

        return

    @classmethod
    def list_floating_ip_pool(cls, cloudname):
        """
        Method to list floating ip pool
        :param cloudname:
        :return:
        """
        try:
            cloud_provider = CloudProvider(cloudname).provider
            floating_ip_pools = cloud_provider.list_floating_ip_pools()

            (order, header
             ) = CloudProvider(cloudname).get_attributes("floating_ip_pool")

            return Printer.write(floating_ip_pools, order=order, header=header)

        except Exception as ex:
            Console.error(ex.message)
        pass

    @classmethod
    def isIPAddr(cls, ip_or_id):
        """
        Method to check if argument is IP address or notS
        :param ip_or_id:
        :return:
        """
        try:
            socket.inet_aton(ip_or_id)
            return True
        except:
            return False

    @classmethod
    def get_unused_floating_ip_list(cls, cloudname):
        """
        Method to get the unused floating IP list
        :param cloudname:
        :return: floating_ips
        """
        try:
            cloud_provider = CloudProvider(cloudname).provider
            floating_ips = cloud_provider.list_floating_ips()
            unused_floating_ips = list()

            for floating_ip in list(floating_ips.values()):
                if floating_ip["fixed_ip"] is None and \
                                floating_ip["instance_id"] is None:
                    # add to unused list
                    floating_ip["cloud"] = cloudname
                    unused_floating_ips.append(floating_ip)

            return unused_floating_ips
        except Exception as ex:
            Console.error(ex.message)

    @classmethod
    def get_floating_ip_list(cls, cloudname):
        """
        Method to get the floating IP list
        :param cloudname:
        :return: floating_ips
        """
        try:
            cloud_provider = CloudProvider(cloudname).provider
            floating_ips = cloud_provider.list_floating_ips()
            return floating_ips
        except Exception as ex:
            Console.error(ex.message)

    @classmethod
    def find_instance_name(cls, **kwargs):
        """
        Method to find instance name
        :param kwargs:
        :return: instance_name
        """
        cloudname = kwargs["cloudname"]
        instance_id = kwargs["instance_id"]

        # Cloudmesh database instance

        # Lookup instance details from db
        instance_dict = cls.cm.find(kind="vm",
                                    category=cloudname,
                                    uuid=instance_id)

        # Get instance_name for vm
        if len(instance_dict) > 0:
            instance_name = list(instance_dict)[0]["name"]
            return instance_name

    @classmethod
    def get_instance_dict(cls, **kwargs):
        """
        Method to get instance dict
        :param kwargs:
        :return: instance dict
        """
        cloudname = kwargs["cloudname"]
        instance_id = kwargs["instance_id"]

        # Cloudmesh database instance

        # Lookup instance details from db
        if cls.isUuid(instance_id):
            instance_dict = cls.cm.find(kind="vm",
                                        category=cloudname,
                                        uuid=instance_id)
        else:
            instance_dict = cls.cm.find(kind="vm",
                                        category=cloudname,
                                        name=instance_id)

        # Instance not found in DB
        if cls.isDictEmpty(instance_dict):
            # auto detect instance_id feature
            vms = cls.cm.find(kind="vm", category=cloudname)
            # check for each instance in db
            for vm in list(vms):
                # if match found in either name/id
                if vm["uuid"].startswith(instance_id) or \
                        vm["name"].startswith(instance_id):
                    # confirm choice with user
                    print("Did you mean instance [{}] ? (y/n)".format(
                        vm["name"]))
                    choice = input().lower()
                    # if yes, return dict
                    if choice == 'y':
                        return vm
            return None
        else:
            return list(instance_dict)[0]

    @classmethod
    def find_assign_floating_ip(cls, cloudname, instance_id):
        instance_dict = cls.get_instance_dict(cloudname=cloudname,
                                              instance_id=instance_id)
        # Instance not found
        if instance_dict is None:
            Console.error(
                "Instance [{}] not found in the cloudmesh database!".format(
                    instance_id))
            return None

        instance_name = instance_dict["name"]

        # Get an unused ip from pool if exist and associate
        unused_floating_ips = cls.get_unused_floating_ip_list(
            cloudname=cloudname)

        if unused_floating_ips:
            floating_ip = unused_floating_ips[0]["ip"]
            result = cls.assign_floating_ip(cloudname=cloudname,
                                            instance_id=instance_id,
                                            floating_ip=floating_ip)
            if result is None:
                Console.error("IP {} could not be assigned to VM {} ".format(
                    floating_ip, instance_name))
                return None
        else:
            # create a new ip and associate
            floating_ip = cls.create_assign_floating_ip(
                cloudname=cloudname, instance_name=instance_name)

        return floating_ip

    @classmethod
    def assign_floating_ip(cls, cloudname, instance_id, floating_ip):
        # find instance in db
        instance_dict = cls.get_instance_dict(cloudname=cloudname,
                                              instance_id=instance_id)
        # Instance not found
        if instance_dict is None:
            Console.error(
                "Instance [{}] not found in the cloudmesh database!".format(
                    instance_id))
            return None

        instance_name = instance_dict["name"]
        result = cls.associate_floating_ip(cloudname=cloudname,
                                           instance_name=instance_name,
                                           floating_ip=floating_ip)
        return result

    @classmethod
    def isUuid(cls, argument):
        """
        Method to check if arg is an UUID
        :param argument:
        :return:
        """
        try:
            UUID(argument, version=4)
            return True
        except ValueError:
            return False

    @classmethod
    def isDictEmpty(cls, dictionary):
        """
        Method to test empty Dict
        :param dictionary:
        :return:
        """
        if bool(dictionary):
            return False
        else:
            return True
Exemple #41
0
class Default(ListResource):
    """
    Cloudmesh contains the concept of defaults. Defaults can have
    categories (we will rename cloud to categories). A category can be a
    cloud name or the name 'general'. The category general is a 'global'
    name space and contains defaults of global value (in future we will
    rename the value to global).

    """

    cm = CloudmeshDatabase()
    """cm is  a static variable so that db is used uniformly."""

    @classmethod
    def list(cls,
             category=None,
             format="table",
             order=None,
             output=format):
        """
        lists the default values in the specified format.
        TODO: This method has a bug as it uses format and output,
        only one should be used.

        :param category: the category of the default value. If general is used
                      it is a special category that is used for global values.
        :param format: json, table, yaml, dict, csv
        :param order: The order in which the attributes are returned
        :param output: The output format.
        :return:
        """
        if order is None:
            order = ['user', 'category', 'name', 'value']
        try:
            if category is None:
                d = cls.cm.all("default")
            else:
                d = cls.cm.find('default', category=category)
            return (Printer.dict_printer(d,
                                         order=order,
                                         output=format))
        except:
            return None

    #
    # GENERAL SETTER AND GETTER METHOD
    #

    @classmethod
    def set(cls, key, value, category=None, user=None):
        """
        sets the default value for a given category
        :param key: the dictionary key of the value to store it at.
        :param value: the value
        :param category: the name of the category
        :param user: the username to store this default value at.
        :return:
        """
        try:
            o = Default.get_object(key, category)

            me = cls.cm.user or user
            if o is None:
                o = cls.cm.db_obj_dict('default',
                                       name=key,
                                       value=value,
                                       category=category,
                                       user=me)
                cls.cm.add_obj(o)
            else:
                o.value = value
                cls.cm.add(o)
                # cls.cm.update(o)
            cls.cm.save()
        except:
            return None

    @classmethod
    def get_object(cls, key, category="general"):
        """
        returns the first object that matches the key in teh Default
        database.

        :param key: The dictionary key
        :param category: The category
        :return:
        """
        try:
            arguments = {'name': key,
                         'category': category}
            o = cls.cm.find('default',
                            output='object',
                            **arguments).first()
            return o
        except Exception:
            return None

    @classmethod
    def get(cls, key, category="general"):
        """
        returns the value of the first objects matching the key
        with the given category.

        :param key: The dictionary key
        :param category: The category
        :return:
        """
        arguments = {'name': key,
                     'category': category}
        o = cls.cm.find('default',
                        output='dict',
                        scope='first',
                        **arguments)
        if o is not None:
            return o['value']
        else:
            return None

    @classmethod
    def delete(cls, key, category):
        #
        # TODO: this is wrong implemented,
        #
        try:
            o = Default.get_object(key, category)
            if o is not None:
                cls.cm.delete(o)
                return "Deletion. ok."
            else:
                return None
        except:
            return None

    @classmethod
    def clear(cls):
        """
        deletes all default values in the database.
        :return:
        """
        try:
            d = cls.cm.all('default')
            for item in d:
                name = d[item]["name"]
                cls.cm.delete_by_name('default', name)
            cls.cm.save()
        except:
            return None

    #
    # Set the default category
    #
    @classmethod
    def get_cloud(cls):
        """
        returns the cloud in teh category general
        :return:
        """
        o = cls.get("cloud", category="general")
        return o

    @classmethod
    def set_cloud(cls, value):
        """
        sets the cloud in the category general
        :param value: the cloud as defined in cloudmesh.yaml
        :return:
        """
        cls.set("cloud", value, category="general")

    #
    # Set the default image
    #

    @classmethod
    def set_image(cls, value, category):
        """
        sets the default image for a specific category.
        :param value: the image uuid or name
        :param category: the category
        :return:
        """
        cls.set("image", value, category=category)

    @classmethod
    def get_image(cls, category):
        """
        returns the image for a particular category
        :param category: the category
        :return:
        """
        return cls.get("image", category)

    #
    # Set the default flavor
    #

    @classmethod
    def set_flavor(cls, value, category):
        """
        sets the default flavor for a particular category
        :param value: teh flavor name or uuid
        :param category: the category
        :return:
        """
        cls.set("flavor", value, category=category)

    @classmethod
    def get_flavor(cls, category):
        """
        gets ths flavor default for a category
        :param category: the category
        :return:
        """
        return cls.get("flavor", category)

    #
    # Set the default group
    #

    @classmethod
    def set_group(cls, value):
        """
        sets the default group
        :param value: the group name
        :return:
        """
        cls.set("group", value, category="general")

    @classmethod
    def get_group(cls):
        """
        get the default group
        :return:
        """
        return cls.get("group", "general")

    #
    # Set the default key
    #

    @classmethod
    def set_key(cls, name):
        """
        :param name: the key name
        :return:
        """
        cls.set("key", name, category="general")

    @classmethod
    def get_key(cls):
        """
        get the default key name
        :return:
        """
        return cls.get("key", "general")

    #
    # Set the default cluster
    #

    @classmethod
    def set_cluster(cls, value):
        """
        sets the default cluster
        :param value: the cluster name as defined in the cloudmesh yaml file.
        :return:
        """
        cls.set("cluster", value, category="general")

    @classmethod
    def get_cluster(cls):
        """
        gets the default cluster name.

        :return:
        """
        return cls.get("cluster", "general")

    #
    # Set the default key
    #

    @classmethod
    def set_debug(cls, value):
        """
        enables debugging
        :param value: True/False
        :return:
        """
        cls.set("debug", value, category="general")

    @classmethod
    def get_debug(cls):
        """
        is debugging switched on?
        :return:
        """
        return cls.get("debug", "general")

    @classmethod
    def debug(cls):
        """
        :return: returns True if debugging is on
        """
        return cls.get("debug", "general")

    #
    # Set the default for refresh
    #

    @classmethod
    def set_refresh(cls, value):
        """
        sets the default for all clouds to refresh
        :param value:
        :return:
        """
        cls.set("refresh", value, "general")

    @classmethod
    def get_refresh(cls):
        """
        is refresh switched on?
        :return:
        """
        return cls.get("refresh", "general")

    @classmethod
    def refresh(cls):
        """
        :return: "on" if refresh is True, "off" otherwise
        """
        try:
            value = cls.get_refresh()
        except:
            cls.set_refresh("on")
            value = "on"
        return value == "on"

    # set default for timer

    @classmethod
    def set_timer(cls, value):
        """
        sets the default for all clouds to timer
        :param value:
        :return:
        """
        cls.set("timer", value, "general")

    @classmethod
    def get_timer(cls):
        """
        gets the timer
        :return: "on" if timer is True, "off" otherwise
        """
        try:
            value = cls.get("timer", "general")
        except:
            cls.set_timer("off")
            value = "off"
        return value

    @classmethod
    def timer(cls):
        """
        :return: "on" if timer is True, "off" otherwise
        """
        value = cls.get_timer()
        return value == "on"

    @classmethod
    def load(cls, filename):

        config = ConfigDict(filename=filename)["cloudmesh"]
        clouds = config["clouds"]

        # FINDING DEFAULTS FOR CLOUDS

        for cloud in clouds:

            db = {
                "image": cls.get("image", cloud),
                "flavor": cls.get("flavor", cloud),
            }
            defaults = clouds[cloud]["default"]
            for attribute in ["image", "flavor"]:
                value = db[attribute]
                if attribute in defaults:
                    value = db[attribute] or defaults[attribute]
                Default.set(attribute, value, category=cloud)

        # FINDING DEFAUlTS FOR KEYS
        # keys:
        #     default: id_rsa
        #     keylist:
        #       id_rsa: ~/.ssh/id_rsa.pub

        # key_db = SSHKeyDBManager()

        name_key = cls.get("key")

        keys = config["keys"]
        name = keys["default"]
        if name in keys["keylist"]:
            value = name_key or keys["keylist"][name]
            # key_db.add(value, keyname=name)

        Default.set_key(name)