Example #1
0
def vms():
    cloud = "chameleon"
    provider = Provider(name=cloud)
    vms = provider.list()
    pprint(vms)
    h = provider.Print(vms, kind="vm", output="html")
    return h
Example #2
0
    def setup(self):
        print()
        self.user = Config()["cloudmesh"]["profile"]["user"]
        self.clouduser = '******'
        self.name_generator = Name(experiment="exp",
                                   group="grp",
                                   user=self.user,
                                   kind="vm",
                                   counter=1)

        self.name = str(self.name_generator)
        self.name_generator.incr()

        self.new_name = str(self.name_generator)

        variables = Variables()
        cloud = variables['cloud']

        self.p = Provider(name=cloud)

        self.secgroupname = "CM4TestSecGroup"
        self.secgrouprule = {
            "ip_protocol": "tcp",
            "from_port": 8080,
            "to_port": 8088,
            "ip_range": "129.79.0.0/16"
        }
        self.testnode = None
        print("\n")
def start_vm(cloud, name=None):
    #
    # complete me
    #
    provider = Provider(cloud)
    vm = provider.boot(name=name)
    vm.wiat()
    return vm
class Testazure(object):
    def setup(self):
        self.p = Provider(name="az")
        self.vm_name = VM
        self.group = self.p.credentials["resourcegroup"]
        self.location = self.p.credentials["location"]

    def test_config(self):
        print(self.p.name)
        print(self.p.kind)
        print(self.p.credentials)
        print(self.location)
        print(self.group)
        assert self.p.name == "az"

    def test_login(self):
        HEADING()
        r = self.p.login()

    def test_create_vm(self):
        HEADING()
        r = self.p.create(name=self.vm_name,
                          image="UbuntuLTS",
                          username="******")
        assert r["location"] == 'eastus'

    def test_list_vm(self):
        HEADING()
        r = self.p.list()
        assert r[0]["name"] == VM

    def test_ssh_vm(self):
        HEADING()
        self.p.ssh(user="******", name=self.vm_name, command="uname -a")

    def test_connect_vm(self):
        HEADING()
        r = self.p.connect(name=self.vm_name, user='******')
        assert r['status'] == 0

    def test_stop_vm(self):
        HEADING()
        r = self.p.stop(name=self.vm_name)
        # time.sleep(100)
        assert r['status'] == 0

    def test_start_vm(self):
        HEADING()
        r = self.p.start(name=self.vm_name)
        # time.sleep(100)
        assert r['status'] == 0

    def test_delete_vm(self):
        HEADING()
        r = self.p.delete(name=self.vm_name)
        assert r['status'] == 0

    def test_benchmark(self):
        Benchmark.print(csv=True, sysinfo=False, tag=CLOUD)
Example #5
0
class Testazure(object):

    def setup(self):
        self.p = Provider(name=CLOUD)
        self.name = VM
        self.group = "test"
        self.location = "eastus"

    def test_login(self):
        HEADING()
        r = self.p.login()

    def test_create_vm(self):
        HEADING()
        r = self.p.create_vm(resource_group=self.group,
                             name=self.name,
                             image="UbuntuLTS",
                             username="******")
        assert r["location"] == 'eastus'

    def test_list_vm(self):
        HEADING()
        r = self.p.list_vm(resource_group=self.group)
        assert r[0]["name"] == VM

    def test_04_ssh_vm(self):
        HEADING()
        self.p.ssh_vm(user="******",
                      resource_group=self.group,
                      name=self.name,
                      command="uname -a")

    def test_connect_vm(self):
        HEADING()
        r = self.p.connect_vm(resource_group=self.group,
                              name=self.name,
                              user='******')
        assert r['status'] == 0

    def test_stop_vm(self):
        HEADING()
        r = self.p.stop_vm(resource_group=self.group,
                           name=self.name)
        # time.sleep(100)
        assert r['status'] == 0

    def test_start_vm(self):
        HEADING()
        r = self.p.start_vm(resource_group=self.group,
                            name=self.name)
        # time.sleep(100)
        assert r['status'] == 0

    def test_delete_vm(self):
        HEADING()
        r = self.p.delete_vm(resource_group=self.group,
                             name=self.name)
        assert r['status'] == 0
Example #6
0
def image(service: str) -> list:
    """
    Lists the images on teh cloud service

    :param service: The name of the service
    :return: the information in json format
    """
    provider = Provider(name=service)
    result = provider.images()
    if flat and result:
        result = provider.Prints(result, kind="vm", output="flat")
    return result
Example #7
0
def boot(service: str) -> list:
    """
    Boots a VM on the cloud service

    :param service: The name of the service
    :return: the information in json format
    """
    # TODO: needs more work, read from yaml file defaults
    provider = Provider(name=service)
    result = provider.create()
    if flat and result:
        result = provider.Prints(result, kind="vm", output="flat")
    return result
Example #8
0
    def get_provider(kind=None, service=None):
        """
        Method to import the provider based on the service and kind.

        :param service: Type of the service e.g. compute or storage, volume
        :param kind: Name of the cloud e.g. google, azure, aws etc.
        :return: Provider class
        """
        Provider = None

        try:

            if service in ['compute', 'cloud']:

                if kind is None:
                    from cloudmesh.compute.vm.Provider import Provider
                else:
                    from cloudmesh.compute.vm.Provider import Provider as P
                    Provider = P.get_provider(kind)

            elif service == 'storage':

                from cloudmesh.storage.Provider import Provider as P
                if kind is None:
                    from cloudmesh.storage.Provider import Provider
                else:
                    Provider = P.get_provider(kind)

            elif service == 'volume':

                from cloudmesh.volume.Volume import Provider as P
                Provider = P.get_provider(kind)

        except Exception as e:
            Console.error(
                f"Registration failed kind={kind} and service={service}")
            print(e)
            return None

        if Provider is None:
            Console.error(
                f"Registration no Provider found for kind={kind} and service={service}"
            )
            return None

        # print("Provider:", Provider)

        p = Provider

        return p
Example #9
0
    def boot(self, order='price', refresh=False, cloud=None):

        clouds = ['aws', 'azure', 'gcp']
        if cloud in clouds:
            clouds = [cloud]

        Console.msg(f"Checking to see which providers are bootable ...")
        reachdict = {}

        for cloud in clouds:
            try:
                tempProv = Provider(
                    name=cloud, configuration="~/.cloudmesh/cloudmesh.yaml")
                Console.msg(cloud + " reachable ...")
                reachdict[cloud] = tempProv
            except:
                Console.msg(cloud + " not available ...")

        flavorframe = self.list(order, 10000000, refresh, printit=False)
        keysya = list(reachdict.keys())
        flavorframe = flavorframe[flavorframe['provider'].isin(keysya)]
        Console.msg(f"Showing top 5 options, booting first option now...")
        converted = flavorframe.head(5).to_dict('records')
        print(Printer.write(converted))
        cheapest = converted[0]
        var_list = Variables(filename="~/.cloudmesh/var-data")
        var_list['cloud'] = cheapest['provider']
        Console.msg(f'new cloud is ' + var_list['cloud'] +
                    ', booting up the vm with flavor ' +
                    cheapest['machine-name'])
        vmcom = VmCommand()
        vmcom.do_vm('boot --flavor=' + cheapest['machine-name'])
        return ""
Example #10
0
class TestName:
    def setup(self):
        print()
        self.user = Config()["cloudmesh"]["profile"]["user"]
        self.clouduser = '******'
        self.name_generator = Name(experiment="exp",
                                   group="grp",
                                   user=self.user,
                                   kind="vm",
                                   counter=1)

        self.name = str(self.name_generator)
        self.name_generator.incr()

        self.new_name = str(self.name_generator)

        self.p = Provider(name="chameleon")

        self.secgroupname = "CM4TestSecGroup"
        self.secgrouprule = {
            "ip_protocol": "tcp",
            "from_port": 8080,
            "to_port": 8088,
            "ip_range": "129.79.0.0/16"
        }
        self.testnode = None
        print("\n")

    def test_01_list_flavors(self):
        HEADING()
        flavors = self.p.flavors()

    def test_02_list_images(self):
        HEADING()
        flavors = self.p.images()

    def test_03_list_keys(self):
        HEADING()
        self.keys = self.p.keys()

    def test_03_list_nodes(self):
        HEADING()
        self.keys = self.p.list()
Example #11
0
    def upload(self, group=None, cloud=None, vm=None):

        # key group upload [--group=GROUPNAMES] [--cloud=CLOUDS] [ip/vm]

        groupkeys = group

        db_keys = self.cm.find(collection=f"{self.cloud}-key")
        db_keygroups = self.cm.find(collection=f"{self.cloud}-keygroup")

        keygroups = []
        for groups in db_keygroups:
            if groups["name"] == groupkeys:
                for x in groups["keys"]:
                    keygroups.append(x)

        provider = Provider(name=cloud)
        keys = ""
        for key in db_keys:
            if key["name"] in keygroups:
                keys += key["public_key"]
                keys += "\n"
                command = "echo " + keys + " >> " + "$HOME/.ssh/authorized_keys"
                # print(command, "\n")
                provider.ssh(vm, command)
    def __init__(self,
                 provider_name,
                 function_name,
                 setup_function=None,
                 validation=None):
        try:
            self.provider_name = provider_name
            self.function_name = function_name

            self.test_name = f"test_{provider_name}_{function_name}"

            self.provider = Provider(name=provider_name)
            #Gets the implementation tied to a specific provider as a wrapped function, so it can be invoked directly, without needing to pass a self object\
            self.function = getattr(self.provider, function_name)

            self._sf = setup_function if setup_function else self.no_setup
            self._vf = validation if validation else self.validate_result_exists

            self.result = ''
            self.status = False

        except Exception as e:
            print(e)
            self.result = f"{provider_name} {function_name} {False}"
Example #13
0
    def do_vm(self, args, arguments):
        """
        ::

            Usage:
                vm ping [NAMES] [--cloud=CLOUDS] [--count=N]
                vm check [NAMES] [--cloud=CLOUDS] [--username=USERNAME]
                vm status [NAMES] [--cloud=CLOUDS] [--output=OUTPUT]
                vm console [NAME] [--force]
                vm log [NAME] [--force]
                vm stop [NAMES]  [--dryrun]
                vm start [NAMES] [--dryrun]
                vm terminate [NAMES] [--cloud=CLOUD] [--dryrun]
                vm delete [NAMES] [--cloud=CLOUD] [--dryrun]
                vm refresh [--cloud=CLOUDS]
                vm list [NAMES]
                        [--cloud=CLOUDS]
                        [--output=OUTPUT]
                        [--refresh]
                vm boot [--n=COUNT]
                        [--name=VMNAMES]
                        [--cloud=CLOUD]
                        [--username=USERNAME]
                        [--image=IMAGE]
                        [--flavor=FLAVOR]
                        [--network=NETWORK]
                        [--public]
                        [--secgroup=SECGROUPs]
                        [--group=GROUPs]
                        [--key=KEY]
                        [--dryrun]
                        [-v]
                vm meta list [NAME]
                vm meta set [NAME] KEY=VALUE...
                vm meta delete [NAME] KEY...
                vm script [--name=NAMES]
                          [--username=USERNAME]
                          [--key=KEY]
                          [--dryrun]
                          [--dir=DESTINATION]
                          SCRIPT
                vm ip assign [NAMES]
                          [--cloud=CLOUD]
                vm ip show [NAMES]
                           [--group=GROUP]
                           [--cloud=CLOUD]
                           [--output=OUTPUT]
                           [--refresh]
                vm ip inventory [NAMES]
                vm ssh [NAMES]
                       [--username=USER]
                       [--quiet]
                       [--ip=IP]
                       [--key=KEY]
                       [--command=COMMAND]
                vm put SOURCE DESTINATION [NAMES]
                vm get SOURCE DESTINATION [NAMES]
                vm rename [OLDNAMES] [NEWNAMES] [--force] [--dryrun]
                vm wait [--cloud=CLOUD] [--interval=INTERVAL] [--timeout=TIMEOUT]
                vm info [--cloud=CLOUD]
                        [--output=OUTPUT]
                vm username USERNAME [NAMES] [--cloud=CLOUD]
                vm resize [NAMES] [--size=SIZE]

            Arguments:
                OUTPUT         the output format
                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 vm 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:
                -v             verbose, prints the dict at the end
                --output=OUTPUT   the output format
                -H --modify-knownhosts  Do not modify ~/.ssh/known_hosts file
                                      when ssh'ing into a machine
                --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, 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 vm 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.

                vm refresh [--cloud=CLOUDS]
                    this command refreshes the data for virtual machines,
                    images and flavors for the specified clouds.

                vm ping [NAMES] [--cloud=CLOUDS] [--count=N] [--processors=PROCESSORS]
                     pings the specified virtual machines, while using at most N pings.
                     The ping is executed in parallel.
                     If names are specifies the ping is restricted to the given names in
                     parameter format. If clouds are specified, names that are not in
                     these clouds are ignored. If the name is set in the variables
                     this name is used.

                cms vm ssh --command=\"uname -a\"

                      executes the uname command on the last booted vm

                vm script [--name=NAMES]
                          [--username=USERNAME]
                          [--key=KEY]
                          [--dryrun]
                          [--dir=DESTINATION]
                          [--shell=SHELL]
                          SCRIPT

                   The script command copies a shell script to the specified vms
                   into the DESTINATION directory and than execute it. With
                   SHELL you can set the shell for executing the command,
                   this coudl even be a python interpreter. Examples for
                   SHELL are /bin/sh, /usr/bin/env python

                vm put SOURCE DESTINATION [NAMES]

                    puts the file defined by SOURCE into the DESINATION folder
                    on the specified machines. If the file exists it is
                    overwritten, so be careful.

                vm get SOURCE DESTINATION [NAMES]

                    gets  the file defined by SOURCE into the DESINATION folder
                    on the specified machines. The SOURCE is on the remote
                    machine. If one machine is specified, the SOURCE is the same
                    name as on the remote machine. If multiple machines are
                    specified, the name of the machine will be a prefix to the
                    filename. If the filenames exists, they will be overwritten,
                    so be careful.

            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 gregor-004 --command=\"uname -a\"

            Limitations:

                Azure: rename is not supported
        """

        map_parameters(arguments, 'active', 'cloud', 'command', 'dryrun',
                       'flavor', 'force', 'group'
                       'output', 'group', 'image', 'interval', 'timeout', 'ip',
                       'key', 'modify-knownhosts', 'n', 'name', 'public',
                       'quiet', 'secgroup', 'size', 'username', 'output',
                       'count', 'network', 'refresh')

        variables = Variables()
        database = CmDatabase()

        arguments.output = Parameter.find("output", arguments, variables,
                                          "table")

        arguments.refresh = Parameter.find_bool("refresh", arguments,
                                                variables)

        if (arguments.meta and arguments.list):

            name = arguments.NAME
            if arguments.NAME is None:
                name = variables['vm']
                if name is None:
                    Console.error("No vm specified")

            cloud = "chameleon"
            # cloud = Parameter.find(arguments, variables)
            print(f"vm metadata for {name} on {cloud}")

            provider = Provider(name=cloud)
            r = provider.get_server_metadata(name)
            print(r)

        elif arguments.meta and arguments.set:

            metadata = {}
            pairs = arguments['KEY=VALUE']
            for pair in pairs:
                key, value = pair.split("=", 1)
                metadata[key] = value

            name = arguments.NAME
            if arguments.NAME is None:
                name = variables['vm']
                if name is None:
                    Console.error("No vm specified")

            cloud = "chameleon"
            # cloud = Parameter.find(arguments, variables)
            print(f"cloud {cloud} {name}")

            provider = Provider(name=cloud)
            provider.set_server_metadata(name, **metadata)
            r = provider.get_server_metadata(name)

            pprint(r)

        elif arguments.meta and arguments.delete:

            metadata = {}
            keys = arguments['KEY']

            name = arguments.NAME
            if arguments.NAME is None:
                name = variables['vm']
                if name is None:
                    Console.error("No vm specified")

            cloud = "chameleon"
            # cloud = Parameter.find(arguments, variables)
            print(f"cloud {cloud} {name}")

            provider = Provider(name=cloud)

            for key in keys:
                provider.delete_server_metadata(name, key)

            r = provider.get_server_metadata(name)

            pprint(r)

        elif arguments.list and arguments.refresh:

            names = []

            clouds, names = Arguments.get_cloud_and_names(
                "list", arguments, variables)

            for cloud in clouds:
                print(f"cloud {cloud}")
                provider = Provider(name=cloud)
                vms = provider.list()

                provider.Print(vms, output=arguments.output, kind="vm")

                return ""

        elif arguments.list:

            names = []

            clouds, names = Arguments.get_cloud_and_names(
                "list", arguments, variables)

            try:

                for cloud in clouds:
                    print(f"List {cloud}")
                    p = Provider(cloud)
                    kind = p.kind

                    collection = "{cloud}-vm".format(cloud=cloud, kind=p.kind)
                    db = CmDatabase()
                    vms = db.find(collection=collection)

                    p.Print(vms, output=arguments.output, kind="vm")

            except Exception as e:
                Console.error("Error in listing ", traceflag=True)
                VERBOSE(e)

            return ""

        elif arguments.ping:
            """
            vm ping [NAMES] [--cloud=CLOUDS] [--count=N]
            """
            if arguments.NAMES:
                variables['vm'] = arguments.NAMES
            if arguments['--cloud']:
                variables['cloud'] = arguments['--cloud']
            clouds, names = Arguments.get_cloud_and_names(
                "status", arguments, variables)

            count = arguments.count
            if arguments.count:
                count = int(count)
            else:
                count = 1

            def get_ips():
                ips = []
                for cloud in clouds:
                    params = {}
                    # gets public ips from database
                    cursor = database.db[f'{cloud}-vm']
                    for name in names:
                        for node in cursor.find({'name': name}):
                            ips.append(node['ip_public'])
                    ips = list(set(ips))
                    pprint(ips)
                return ips

            ips = get_ips()
            if len(ips) == 0:
                Console.warning("no public ip found.")
                for cloud in clouds:
                    print(f"refresh for cloud {cloud}")
                    provider = Provider(name=cloud)
                    vms = provider.list()
                ips = get_ips()

            if len(ips) == 0:
                Console.error("No vms with public IPS found.")
                Console.error("  Make sure to use cms vm list --refresh")

            for ip in ips:
                result = Shell.ping(host=ip, count=count)
                banner(ip)
                print(result)
                print()

        elif arguments.check:

            raise NotImplementedError
            """
            vm check [NAMES] [--cloud=CLOUDS] [--username=USERNAME]
            """
            """
            
            THIS IS ALL WRONG AS PROVIDER DEPENDENT !!!
            
            if arguments.NAMES:
                variables['vm'] = arguments.NAMES
            if arguments['--cloud']:
                variables['cloud'] = arguments['--cloud']
            clouds, names = Arguments.get_cloud_and_names("status", arguments, variables)

            for cloud in clouds:
                provider = Provider(cloud)
                params = {}

                params['key'] = \
                    provider.p.spec["credentials"]['EC2_PRIVATE_KEY_FILE_PATH'] + \
                    provider.p.spec["credentials"]['EC2_PRIVATE_KEY_FILE_NAME']

                params['username'] = arguments['--username']  # or get from db

                processors = arguments['--processors']
                if processors:
                    params['processors'] = int(processors[0])

                # gets public ips from database
                public_ips = []
                cursor = database.db['{cloud}-vm']
                for name in names:
                    for node in cursor.find({'name': name}):
                        public_ips.append(node['public_ips'])
                public_ips = [y for x in public_ips for y in x]

                Host.check(hosts=public_ips, **params)
            """

        elif arguments.status:
            if arguments.NAMES:
                variables['vm'] = arguments.NAMES
            if arguments['--cloud']:
                variables['cloud'] = arguments['--cloud']
            clouds, names = Arguments.get_cloud_and_names(
                "status", arguments, variables)

            # gets status from database
            for cloud in clouds:
                provider = Provider(cloud)
                status = []
                cursor = database.db[f'{cloud}-vm']
                print(cloud)
                for name in names:
                    for node in cursor.find({'name': name}):
                        status.append(node)

                provider.Print(status, output=arguments.output, kind="status")
                return ""

        elif arguments.start:
            # TODO: not tested
            if arguments.NAMES:
                names = variables['vm'] = arguments.NAMES

            if arguments['--cloud']:
                variables['cloud'] = arguments['--cloud']
            clouds, names = Arguments.get_cloud_and_names(
                "stop", arguments, variables)

            cloud = clouds[0]
            print(cloud)
            print(names)

            for name in names:

                provider = Provider(cloud)

                if arguments['--dryrun']:
                    print(f"start node {name}")
                else:
                    vms = provider.start(name=name, cloud=cloud)

                    provider.Print(vms, output=arguments.output, kind="vm")

            return ""

        elif arguments.stop:
            # TODO: not tested

            if arguments.NAMES:
                variables['vm'] = arguments.NAMES
            if arguments['--cloud']:
                variables['cloud'] = arguments['--cloud']
            clouds, names = Arguments.get_cloud_and_names(
                "stop", arguments, variables)

            for cloud in clouds:
                params = {}
                provider = Provider(cloud)

                if arguments['--dryrun']:
                    Console.ok(f"Dryrun stop: "
                               f"        {cloud}\n"
                               f"        {names}"
                               f"        {provider}")
                else:
                    for name in names:
                        vms = provider.stop(name)

                    provider.Print(vms, output=arguments.output, kind="vm")

        elif arguments.terminate:
            # TODO: not tested

            if arguments.NAMES:
                variables['vm'] = arguments.NAMES
            if arguments['--cloud']:
                variables['cloud'] = arguments['--cloud']
            clouds, names = Arguments.get_cloud_and_names(
                "stop", arguments, variables)

            for cloud in clouds:
                params = {}
                provider = Provider(cloud)

                if arguments['--dryrun']:
                    Console.ok(f"Dryrun terminate: "
                               f"        {cloud}\n"
                               f"        {names}"
                               f"        {provider}")
                else:
                    for name in names:
                        vms = provider.destroy(name)

                    provider.Print(vms, output=arguments.output, kind="vm")

        elif arguments.delete:

            if arguments.NAMES:
                variables['vm'] = arguments.NAMES
            if arguments['--cloud']:
                variables['cloud'] = arguments['--cloud']
            clouds, names = Arguments.get_cloud_and_names(
                "stop", arguments, variables)

            if names is not None:
                pass
            elif clouds is not None:
                for cloud in clouds:
                    provider = Provider(cloud)
                    vms = provider.list()
                    for vm in vms:
                        r = provider.destroy(name=vm)
                return ""
            else:
                return ""

            for cloud in clouds:
                provider = Provider(cloud)
                vms = provider.list()
                for vm in vms:
                    name = vm["cm"]["name"]
                    if name in names:
                        r = provider.destroy(name=name)

        # TODO: username, secgroup
        elif arguments.boot:
            # not everything works
            """
                vm boot 
                        [--name=VMNAMES]
                        [--cloud=CLOUD]
                        [--username=USERNAME]
                        [--image=IMAGE]
                        [--flavor=FLAVOR]
                        [--network=NETWORK]
                        [--public]
                        [--secgroup=SECGROUP]
                        [--key=KEY]
                        [--group=GROUP]
                        [--dryrun]
            """
            # for name in names:
            #    node = p.create(name=name, size=flavor, image=image)

            # VERBOSE(arguments)
            parameters = dotdict()

            names = Parameter.expand(arguments.name)

            cloud = Parameter.find("cloud", arguments, variables.dict())
            defaults = Config()[f"cloudmesh.cloud.{cloud}.default"]
            groups = Parameter.find("group", arguments, variables.dict(),
                                    {"group": "default"})

            parameters = dotdict()

            # parameters.names = arguments.name

            parameters.group = groups
            for attribute in [
                    "image", "username", "flavor", "key", "network", "secgroup"
            ]:
                parameters[attribute] = Parameter.find(attribute, arguments,
                                                       variables.dict(),
                                                       defaults)

            if arguments.username is None:
                parameters.user = Image.guess_username(parameters.image)

            provider = Provider(name=cloud)

            parameters.secgroup = arguments.secgroup or "default"

            #
            # determine names
            #

            if names and arguments.n and len(names) > 1:
                Console.error(
                    f"When using --n={arguments.n}, you can only specify one name"
                )
                return ""
            # cases
            #

            # only name --name = "a[1,2]"
            # name and count # --name="a" --n=3, names must be of length 1
            # only count --n=2 names are read form var
            # nothing, just use one vm

            # determin names
            _names = []
            if not names:

                if not arguments.n:
                    count = 1
                else:
                    count = int(arguments.n)

                for i in range(0, count):
                    if names is None:
                        n = Name()
                        n.incr()
                        name = str(n)
                    else:
                        n = names[i]
                        name = str(n)
                    _names.append(name)
                names = _names

            elif len(names) == 1 and arguments.n:

                name = names[0]
                for i in range(0, int(arguments.n)):
                    _names.append(f"{name}-{i}")
                names = _names

            # pprint(parameters)

            for name in names:

                parameters.name = name
                if arguments['--dryrun']:
                    banner("boot")

                    pprint(parameters)

                    Console.ok(f"Dryrun boot {name}: \n"
                               f"        cloud={cloud}\n"
                               f"        names={names}\n"
                               f"        provider={provider}")
                    print()
                    for attribute in parameters:
                        value = parameters[attribute]
                        Console.ok(f"        {attribute}={value}")

                else:

                    # parameters.progress = len(parameters.names) < 2

                    try:
                        vms = provider.create(**parameters)
                    except TimeoutError:
                        Console.error(
                            f"Timeout during vm creation. There may be a problem with the cloud {cloud}"
                        )

                    except Exception as e:
                        Console.error("create problem", traceflag=True)
                        print(e)
                        return ""

                    variables['vm'] = str(n)
                    if arguments["-v"]:
                        banner("Details")
                        pprint(vms)

            # provider.Print(arguments.output, "vm", vms)

        elif arguments.info:
            """
            vm info [--cloud=CLOUD] [--output=OUTPUT]
            """
            print("info for the vm")

            cloud, names = Arguments.get_cloud_and_names(
                "info", arguments, variables)

            raise NotImplementedError

        elif arguments.rename:
            raise NotImplementedError
            # Not tested
            print("rename the vm")

            v = Variables()
            cloud = v["cloud"]

            p = Provider(cloud)

            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",
                                  traceflag=False)
                else:
                    print(oldnames)
                    print(newnames)
                    for i in range(0, len(oldnames)):
                        oldname = oldnames[i]
                        newname = newnames[i]
                        if arguments["--dryrun"]:
                            Console.ok("Rename {} to {}".format(
                                oldname, newname))
                        else:
                            print(f"rename {oldname} -> {newname}")

                            p.rename(source=oldname, destination=newname)

                    msg = "info. OK."
                    Console.ok(msg)
            except Exception as e:
                Error.traceback(e)
                Console.error("Problem renaming instances", traceflag=True)

        elif arguments["ip"] and arguments["show"]:
            raise NotImplementedError

            print("show the ips")
            """
            vm ip show [NAMES]
                   [--group=GROUP]
                   [--cloud=CLOUD]
                   [--output=OUTPUT]
                   [--refresh]

            """

        elif arguments["ip"] and arguments["assign"]:
            raise NotImplementedError
            """
            vm ip assign [NAMES] [--cloud=CLOUD]
            """
            print("assign the public ip")

        elif arguments["ip"] and arguments["inventory"]:
            raise NotImplementedError
            """
            vm ip inventory [NAMES]

            """
            print("list ips that could be assigned")

        elif arguments.default:
            raise NotImplementedError

            print("sets defaults for the vm")

        elif arguments.script:
            raise NotImplementedError
            clouds, names = Arguments.get_cloud_and_names(
                "run", arguments, variables)
            username = arguments['--username']
            script = arguments.SCRIPT

            for cloud in clouds:
                provider = Provider(cloud)

                name_ips = {}
                cursor = database.db['{}-node'.format(cloud)]
                for name in names:
                    for node in cursor.find({'name': name}):
                        name_ips[name] = node['public_ips']

                if arguments['--dryrun']:
                    print("run script {} on vms: {}".format(script, names))
                else:
                    provider.ssh(name_ips, username=username, script=script)

        elif arguments.username:
            raise NotImplementedError
            """
            vm username USERNAME [NAMES] [--cloud=CLOUD]
            """
            print("sets the username for the vm")

        elif arguments.resize:
            raise NotImplementedError
            """
            vm resize [NAMES] [--size=SIZE]
            """
            pass

        elif arguments.ssh:
            """
            vm ssh [NAMES] [--username=USER]
                 [--quiet]
                 [--ip=IP]
                 [--key=KEY]
                 [--command=COMMAND]
            """

            # VERBOSE(arguments)
            clouds, names, command = Arguments.get_commands(
                "ssh", arguments, variables)

            # print (clouds)
            # print(names)
            # print (command)

            if arguments.command is None and len(names) > 1:
                Console.error("Interactive shell can only be done on one vm")
                return ""
            elif arguments.command is None and len(names) == 1:
                name = names[0]
                cloud = clouds[0]
                cm = CmDatabase()
                try:
                    vm = cm.find_name(name, "vm")[0]
                except IndexError:
                    Console.error(f"could not find vm {name}")
                    return ""
                # VERBOSE(vm)
                cloud = vm["cm"]["cloud"]
                provider = Provider(name=cloud)
                try:
                    provider.ssh(vm=vm)
                except KeyError:
                    vms = provider.list()

                    provider.Print(vms, output=arguments.output, kind="vm")

                    provider.ssh(vm=vm)
                return ""
            else:
                # command on all vms

                if clouds is None or names is None or command is None:
                    return ""
                else:
                    for cloud in clouds:
                        p = Provider(cloud)
                        for name in names:
                            cm = CmDatabase()
                            try:
                                vm = cm.find_name(name, "vm")[0]
                            except IndexError:
                                Console.error(f"could not find vm {name}")
                                continue
                            r = p.ssh(vm=vm, command=command)
                            print(r)
            return ""

        elif arguments.console:

            # why is this not vm
            clouds, names, command = Arguments.get_commands(
                "ssh", arguments, variables)

            print(clouds)
            print(names)
            print(command)

            for cloud in clouds:
                p = Provider(cloud)
                for name in names:
                    cm = CmDatabase()
                    try:
                        vm = cm.find_name(name, "vm")[0]
                    except IndexError:
                        Console.error(f"could not find vm {name}")
                        continue
                    r = p.console(vm=vm)
                    print(r)

            return ""

        elif arguments.log:

            # why is this not vm
            clouds, names, command = Arguments.get_commands(
                "ssh", arguments, variables)

            print(clouds)
            print(names)
            print(command)

            for cloud in clouds:
                p = Provider(cloud)
                for name in names:
                    cm = CmDatabase()
                    try:
                        vm = cm.find_name(name, "vm")[0]
                    except IndexError:
                        Console.error(f"could not find vm {name}")
                        continue
                    r = p.log(vm=vm)
                    print(r)

            return ""

        elif arguments.wait:
            """
            vm wait [--cloud=CLOUD] [--interval=INTERVAL] [--timeout=TIMEOUT]
            """

            # why is this not vm
            clouds, names, command = Arguments.get_commands(
                "ssh", arguments, variables)

            # print (clouds)
            # print (names)
            # print (command)

            for cloud in clouds:
                p = Provider(cloud)
                for name in names:
                    cm = CmDatabase()
                    try:
                        vm = cm.find_name(name, "vm")[0]
                    except IndexError:
                        Console.error(f"could not find vm {name}")
                        continue
                    r = p.wait(vm=vm,
                               interval=arguments.interval,
                               timeout=arguments.timeout)
                    if r:
                        Console.ok("Instance available for SSH")
                    else:
                        Console.error(
                            f"Instance unavailable after timeout of {arguments.timeout}"
                        )
                    # print(r)

            return ""

        elif arguments.put:
            """
            vm put SOURCE DESTINATION
            """
            clouds, names, command = Arguments.get_commands(
                "ssh", arguments, variables)

            key = variables['key']

            source = arguments['SOURCE']
            destination = arguments['DESTINATION']
            for cloud in clouds:
                p = Provider(name=cloud)
                cm = CmDatabase()
                for name in names:
                    try:
                        vms = cm.find_name(name, "vm")
                    except IndexError:
                        Console.error(f"could not find vm {name}")
                        return ""
                    # VERBOSE(vm)
                    for vm in vms:
                        try:
                            ip = vm['public_ips']
                        except:
                            try:
                                ip = p.get_public_ip(name=name)
                            except:
                                Console.error(
                                    f"could not find a public ip for vm {name}",
                                    traceflag=True)
                                return
                            Console.error(
                                f"could not find a public ip for vm {name}",
                                traceflag=True)
                            return

                        # get the username
                        try:
                            # username not in vm...guessing
                            imagename = list(
                                cm.collection(cloud + '-image').find(
                                    {'ImageId': vm['ImageId']}))[0]['name']
                            print(imagename)
                            user = Image.guess_username(image=imagename,
                                                        cloud=cloud)
                        except:
                            try:
                                user = vm['os_profile']['admin_username']
                            except:
                                Console.error(
                                    f"could not find a valid username for "
                                    f"{name}, try refreshing the image list",
                                    traceflag=True)
                                return
                            Console.error(
                                f"could not find a valid username for {name}, try refreshing the image list"
                            )
                            return

                        cmd = f'scp -i {key} {source} {user}@{ip}:{destination}'
                        print(cmd)
                        os.system(cmd)
            return ""
Example #14
0
class TestCloudAws:
    def setup(self):
        self.config = Config()
        self.provider = Provider(name="aws")
        self.test_node_name = 'test1'
        self.test_node_id = ''

    def _wait_and_get_state(self, name, how_long=15):
        time.sleep(how_long)
        node = self.provider.provider.driver._get_node(name)
        return node.state if node else None

    def test_create(self):
        HEADING()
        vm = self.provider.create(self.test_node_name)
        assert vm is not None

    def test_list(self):
        HEADING()
        results = self.provider.list()
        assert isinstance(results, list)

    def test__info(self):
        HEADING()
        info = self.provider.info(self.test_node_name)
        assert info is not None

    def test_suspend(self):
        HEADING()
        self.provider.suspend(name=self.test_node_name)
        # state = self._wait_and_get_state(self.test_node_name)
        # assert state == 'paused'

    def test_stop(self):
        HEADING()
        self.provider.stop(name=self.test_node_name)
        state = self._wait_and_get_state(self.test_node_name, 30)
        assert state == 'deallocating' or state == 'stopped'

    def test_start(self):
        HEADING()
        self.provider.start(name=self.test_node_name)
        state = self._wait_and_get_state(self.test_node_name, 30)
        assert state == 'running'

    def test_destroy(self):
        HEADING()
        self.provider.destroy(name=self.test_node_name)

    def test_list_sizes(self):
        HEADING()
        vols = self.provider.provider.list_sizes()
        assert vols is not None

    def test_benchmark(self):
        Benchmark.print(csv=True, sysinfo=False, tag=cloud)
Example #15
0
 def setup(self):
     self.config = Config()
     self.provider = Provider(name="aws")
     self.test_node_name = 'test1'
     self.test_node_id = ''
Example #16
0
    def do_key(self, args, arguments):
        """
        ::

           Usage:
             key  -h | --help
             key list --cloud=CLOUDS [--output=OUTPUT]
             key list --source=ssh [--dir=DIR] [--output=OUTPUT]
             key list --source=git [--output=OUTPUT] [--username=USERNAME]
             key list [--output=OUTPUT]
             key add NAME --filename=FILENAME [--output=OUTPUT]
             key add [NAME] [--source=FILENAME]
             key add [NAME] [--source=git]
             key add [NAME] [--source=ssh]
             key delete NAMES [--cloud=CLOUDS] [--dryrun]
             key upload [NAMES] [--cloud=CLOUDS] [--dryrun]
             key upload [NAMES] [VMS] [--dryrun]
             key group upload [NAMES] [--group=GROUPNAMES] [--cloud=CLOUDS] [--dryrun]
             key group add [--group=GROUPNAMES] [--cloud=CLOUDS] [--dryrun]
             key group add --file=FILENAME
             key group delete [--group=GROUPNAMES] [NAMES] [--dryrun]
             key group list [--group=GROUPNAMES] [--output=OUTPUT]
             key group export --group=GROUNAMES --filename=FILENAME


           Arguments:
             VMS            Parameterized list of virtual machines
             CLOUDS         The clouds
             NAME           The name of the key.
             SOURCE         db, ssh, all
             KEYNAME        The name of a key. For key upload it defaults to the default key name.
             OUTPUT         The format of the output (table, json, yaml)
             FILENAME       The filename with full path in which the key
                            is located

           Options:
              --dir=DIR                     the directory with keys [default: ~/.ssh]
              --output=OUTPUT               the format of the output [default: table]
              --source=SOURCE               the source for the keys
              --username=USERNAME           the source for the keys [default: none]
              --name=KEYNAME                The name of a key


           Description:

               Please note that some values are read from the cloudmesh.yaml
               file. One such value is cloudmesh.profile.user

               Manages public keys is an essential component of accessing
               virtual machine sin the cloud. There are a number of sources
               where you can find public keys. This includes teh ~/.ssh
               directory and for example github.

               Keys will be uploaded into cloudmesh database with the add
               command under the given NAME. If the name is not specified the name
               cloudmesh.profile.user is assumed.

                key add NAME  --source=ssh
                    adds the default key in ~/.ssh/id_rsa.pub
                key add NAME  --source=FILENAME
                    adds the key specified by the filename with the given name
                key add NAME --git --username=username
                    adds a named github key from a user with the given github
                    username.

               Once the keys are uploaded to github, they can be listed
               To list these keys the following list functions are provided.

                key list --source=git  [--username=USERNAME]
                    lists all keys in git for the specified user. If the
                    name is not specified it is read from cloudmesh.yaml
                key list --source=ssh  [--dir=DIR] [--output=OUTPUT]
                    lists all keys in the directory. If the directory is not
                    specified the default will be ~/.ssh

                key list NAMES
                    lists all keys in the named virtual machines.


                List command can use the [--output=OUTPUT] option

                    list the keys loaded to cloudmesh in the given format:
                    json, yaml, table. table is default. The NAME can be
                    specified and if omitted the name cloudmesh.profile.user
                    is assumed.

                To get keys from the cloudmesh database the following commands
                are available:

                key delete NAMES
                    deletes the Named keys. This may also have an impact on groups
                key rename NAME NEW
                    renames the key from NAME to NEW in the cloudmesh database.

               Group management of keys is an important concept in cloudmesh,
               allowing multiple users to be added to virtual machines while
               managing the keys associated with them. The keys must be uploaded
               to cloudmesh database with a name so they can be used in a
               group. The --dryrun option executes the command without
               uploading the information to the clouds. If no group name is
               specified the group name default is assumed. If no cloudnamesh
               are specified, all active clouds are assumed. active clouds
               can be set in the cloudmesh.yaml file.

                key group delete [GROUPNAMES] [NAMES] [--dryrun]
                    deletes the named keys from the named groups.

                key group list [GROUPNAMES] [--output=OUTPUT]
                    list the key names and details in the group.

                key group upload [GROUPNAMES] [CLOUDS] [--dryrun]
                    uploads the named groups to the specified clouds.

               In some cases you may want to store the public keys in files. For
               this reason we support the following commands.

                key group add --group=GROUPNAME --file=FILENAME
                    the command adds the keys to the given group. The keys are
                    written in the files in yaml format.


                key group export --group=GROUNAMES --filename=FILENAME
                    the command exports the keys to the given group. The keys are
                    written in the files in yaml format.


                The yaml format is as follows:

                cloudmesh:
                  keys:
                    NAMEOFKEY:
                      name: NAMEOFKEY
                      key: ssh-rsa AAAA..... comment
                      group:
                      - GROUPNAME
                    ...

                If a key is included in multiple groups they will be added
                to the grouplist of the key
        """
        def print_keys(keys):
            print(
                Printer.write(
                    keys,
                    sort_keys=["name"],
                    order=["name", "type", "fingerprint", "comment"],
                    header=["Name", "Type", "Fingerprint", "Comment"],
                    output=arguments.output))

        map_parameters(arguments, 'cloud', 'output', 'source', 'dir', 'output',
                       'source', 'dryrun')

        variables = Variables()

        if arguments.list and arguments.source == "git":

            config = Config()
            username = config["cloudmesh.profile.github"]
            keys = SSHkey().get_from_git(username)

            print_keys(keys)

            return ""

        elif arguments.list and arguments.source == "ssh":
            # this is much simpler

            sshkey = SSHkey()

            print_keys([sshkey])

            return ""

        elif arguments.list and arguments.cloud:

            clouds = Parameter.expand(arguments.cloud)

            if len(clouds) == 0:
                variables = Variables()
                cloudname = variables['cloud']
                clouds = [cloudname]
            keys = []

            for cloud in clouds:
                print(f"cloud {cloud}")
                provider = Provider(name=cloud)
                keys = provider.keys()

                provider.Print(keys, output=arguments.output, kind="key")

            return ""

        elif arguments.list:

            cloud = "local"
            db = CmDatabase()
            keys = db.find(collection=f"{cloud}-key")

            print_keys(keys)

            return ""

        elif arguments.add:
            """
             key add [NAME] [--source=FILENAME]
             key add [NAME] [--source=git]
             key add [NAME] [--source=ssh]
             """
            key = Key()

            source = arguments["--source"]
            if source == "ssh":
                name = arguments.NAME or "ssh"
                key.add(name, "ssh")
            elif source == "git":
                name = arguments.NAME or "git"
                key.add("git", "git")
            elif source is not None:
                name = arguments.NAME or source
                key.add(name, "input")
            else:
                config = Config()
                name = config["cloudmesh.profile.github"]
                kind = "ssh"
                key.add(name, kind)

        elif arguments.upload:
            """
            key upload [NAMES] [--cloud=CLOUDS] [--dryrun]
            key upload [NAMES] [VMS] [--dryrun]
            """

            names = Parameter.expand(arguments.NAMES)

            # this may have a bug if NAMES is ommitted

            #
            # Step 0. Set keyname to variable
            #

            if names is None or len(names) == 0:

                config = Config()
                username = config["cloudmesh.profile.user"]
                names = [username]

            if len(names) == 1:
                name = names[0]
                variables = Variables()
                if "key" in variables:
                    old = variables["key"]
                    if old != name:
                        Console.msg(
                            f"Changing defualt key from {old} to {name}")
                        variables["key"] = name

            #
            # Step 1. keys = find keys to upload
            #

            cloud = "local"
            db = CmDatabase()
            db_keys = db.find(collection=f"{cloud}-key")

            keys = []
            for key in db_keys:
                if key["name"] in names:
                    keys.append(key)

            if len(keys) == 0:
                Console.error(
                    f"No keys with the names {names} found in cloudmesh. \n"
                    "       Use the command 'key add' to add the key.")

            #
            # Step 2. iterate over the clouds to upload
            #

            clouds, names = Arguments.get_cloud_and_names(
                "list", arguments, variables)

            for cloud in clouds:
                print(f"cloud {cloud}")
                provider = Provider(name=cloud)
                for key in db_keys:
                    name = key['name']
                    if name in names:
                        try:
                            r = provider.key_upload(key)
                            Console.ok(f"upload key '{name} successful'. ")
                        except ValueError as e:
                            Console.error(
                                f"key '{name} already exists in {cloud}.")

            return ""

        elif arguments.delete and arguments.cloud and arguments.NAMES:

            # key delete NAMES --cloud=CLOUDS [--dryrun]
            names = Parameter.expand(arguments.NAMES)
            clouds = Parameter.expand(arguments.cloud)

            for cloud in clouds:
                provider = Provider(name=cloud)
                for name in names:
                    if arguments.dryrun:
                        Console.ok(f"Dryrun: delete {name} in {cloud}")
                    else:
                        images = provider.key_delete(name)

            return ""

        elif arguments.delete and arguments.NAMES:
            # key delete NAMES [--dryrun]

            names = Parameter.expand(arguments.NAMES)

            cloud = "local"
            db = CmDatabase()
            db_keys = db.find(collection=f"{cloud}-key")

            error = []
            for key in db_keys:
                name = key['name']
                if name in names:
                    if arguments.dryrun:
                        Console.ok(f"Dryrun: delete {name}")
                    else:
                        db.delete(collection="local-key", name=name)
                        Console.ok(f"delete {name}")
            return ""

        elif arguments.group:

            raise NotImplementedError

        return ""
Example #17
0
    def do_flavor(self, args, arguments):
        """
        ::

            Usage:
                flavor list [NAMES] [--cloud=CLOUD] [--refresh] [--output=OUTPUT]


            Options:
               --output=OUTPUT  the output format [default: table]
               --cloud=CLOUD    the ycloud name
               --refresh        refreshes the data before displaying it

            Description:

                This lists out the flavors present for a cloud

            Examples:
                cm flavor list --refresh
                cm flavor list
                cm flavor list --output=csv
                cm flavor list 58c9552c-8d93-42c0-9dea-5f48d90a3188 --refresh

                please remember that a uuid or the flavor name can be used to
                identify a flavor.
        """

        map_parameters(arguments,
                       "refresh",
                       "cloud",
                       "output")

        variables = Variables()

        arguments.output = Parameter.find("output",
                                          arguments,
                                          variables,
                                          "table")

        arguments.refresh = Parameter.find_bool("refresh",
                                                arguments,
                                                variables)

        if arguments.list and arguments.refresh:

            names = []

            clouds, names = Arguments.get_cloud_and_names("list",
                                                          arguments,
                                                          variables)

            for cloud in clouds:
                print(f"cloud {cloud}")
                provider = Provider(name=cloud)
                flavors = provider.flavors()

                provider.Print(flavors, output=arguments.output, kind="flavor")

            return ""

        elif arguments.list:

            names = []

            clouds, names = Arguments.get_cloud_and_names("list",
                                                          arguments,
                                                          variables)

            print(clouds, names)
            try:

                for cloud in clouds:
                    print(f"List {cloud}")
                    provider = Provider(cloud)

                    db = CmDatabase()
                    flavors = db.find(collection=f"{cloud}-flavor")

                    provider.Print(flavors, output=arguments.output, kind="flavor")

            except Exception as e:

                VERBOSE(e)

            return ""
Example #18
0
    def do_vm(self, args, arguments):
        """
        ::

            Usage:
                vm start [--cloud=CLOUD]
                         [--name=NAME]
                vm stop [--cloud=CLOUD]
                        [--name=NAME]
                vm delete [--cloud=CLOUD]
                          [--name=NAME]
                vm list [--cloud=CLOUDS]
                vm boot [--name=NAME]
                        [--cloud=CLOUD]
                        [--image=IMAGE]
                        [--flavor=FLAVOR]
                vm ssh  [--cloud=CLOUD]
                        [--name=NAME]
                        [--command=COMMAND]
                vm info [--cloud=CLOUD]
                        [--format=FORMAT]
                vm resize [NAMES] [--size=SIZE]
                vm images [--cloud=CLOUD]
                vm flavors [--cloud=CLOUD]

            Arguments:
                NAMES          server name. By default it is set to the name of last vm from database.
                NAME           server name.

            Options:
                --ip=IP           give the public ip of the server
                --cloud=CLOUD     give a cloud to work on, if not given, selected
                                  or default cloud will be used
                --flavor=FLAVOR   give the name or id of the flavor
                --image=IMAGE     give the name or id of the image
                --command=COMMAND specify the commands to be executed


            Description:
                commands used to boot, start or delete servers of a 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 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 the VM requested

                vm refresh [--cloud=CLOUDS]
                    this command refreshes the data for virtual machines,
                    images and flavors for the specified clouds.

            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\"

        """

        def map_parameters(arguments, *args):
            for arg in args:
                flag = "--" + arg
                if flag in arguments:
                    arguments[arg] = arguments[flag]
                else:
                    arguments[arg] = None

        def get_cloud_and_names(label, arguments):
            names = []
            clouds = []
            if arguments["--cloud"]:
                clouds = get_clouds(arguments, variables)
            else:
                clouds = get_clouds(arguments, variables)

            names = get_names(arguments, variables)

            return clouds, names

        def get_cloud_and_names_commands(label, arguments):
            names = []
            clouds = []
            commands = []
            if arguments["--cloud"]:
                clouds = get_clouds(arguments, variables)
            else:
                clouds = get_clouds(arguments, variables)
            names = get_names(arguments, variables)
            commands = get_commands(arguments, variables)
            return clouds, names, commands

        def get_clouds(arguments, variables):
        
            clouds = arguments["cloud"] or arguments["--cloud"]          
            if "active" == clouds:
                active = Active()
                clouds = active.clouds()
            else:
                clouds = clouds

            if (clouds is None) or (clouds == ""):
                Console.error("you need to specify a cloud")
                return None
            return clouds

        def get_names(arguments, variables):
            names = arguments["NAME"] or arguments["NAMES"] or arguments["--name"] or variables["vm"]
            if names is None:
                Console.error("you need to specify a vm")
                return None
            else:
                return names

        def get_image(arguments, variables):
            image = arguments["image"] or arguments["--image"]
            if image is None:
                Console.error("you need to specify an image")
                return None
            else:
                return image

        def get_command(arguments, variables):
            command = arguments["command"] or arguments["--command"]
            if command is None:
                Console.error("you need to specify a command")
                return None
            else:
                return command

        def get_flavor(arguments, variables):
            flavor = arguments["flavor"] or arguments["--flavor"]
            if flavor is None:
                Console.error("you need to specify a flavor")
                return None
            else:
                return flavor

        def get_commands(label, arguments):
            names = []
            if label in ["delete", "stop", "start"]:
                clouds = get_clouds(arguments, variables)
                names = get_names(arguments, variables)
                return clouds, names

            elif label in ["list", "flavors", "images"]:
                clouds = get_clouds(arguments, variables)
                return clouds

            elif "boot" == label:
                clouds = get_clouds(arguments, variables)
                names = get_names(arguments, variables)
                image = get_image(arguments, variables)
                flavor = get_flavor(arguments, variables)
                return clouds, names, image, flavor

            elif "ssh" == label:
                clouds = get_clouds(arguments, variables)
                names = get_names(arguments, variables)
                command = get_command(arguments, variables)
                return clouds, names, command

        map_parameters(arguments,
                       'cloud',
                       'command',
                       'flavor',
                       'format',
                       'image',
                       'ip',
                       'name',
                       'NAME')

        VERBOSE.print(arguments, verbose=9)

        variables = Variables()

        
        if arguments.images:
            clouds = get_commands("images", arguments)
            if clouds is None:
                return ""
            else:
                p = Provider(clouds)
                images = p.p.images()
                print(Printer.flatwrite(images,
                                sort_keys=("name"),
                                order=["name", "id", "driver"],
                                header=["Name", "Id", "Driver"])
                )
        elif arguments.flavors:
            clouds = get_commands("flavors", arguments)
            if clouds is None:
                return ""
            else:
                p = Provider(clouds)
                flavors = p.p.flavors()
                print(Printer.flatwrite(flavors,
                                sort_keys=("name", "disk"),
                                order=["name", "id", "ram", "disk"],
                                header=["Name", "Id", "RAM", "Disk"])
                )

        elif arguments.boot:

            print("Creating a new vm")
            clouds, names, image, flavor = get_commands("boot", arguments)
            if clouds is None or names is None or image is None or flavor is None:
                return ""
            else:
                p = Provider(clouds)
                node = p.p.create(name=names, size=flavor, image=image)
                print(Printer.flatwrite(node,
                                sort_keys=("name"),
                                order=["name", "state", "public_ips", "private_ips", "size", "image"],
                                header=["Name", "State", "Public IP", "Private IP", "Size", "Image"])
                )  
    
        elif arguments.start:
            print("Starting the requested vm")
            clouds, names = get_commands("start", arguments)
            if clouds is None or names is None:
                return ""
            else:
                p = Provider(clouds)
                node = p.p.start(name=names)

        elif arguments.stop:
            print("Stopping the requested vm")
            clouds, names = get_commands("stop", arguments)
            if clouds is None or names is None:
                return ""
            else:
                p = Provider(clouds)
                node = p.p.stop(name=names)


        elif arguments.delete:
            print("Delete the specified VM")
            clouds, names = get_commands("delete", arguments)
            if clouds is None or names is None:
                return ""
            else:
                p = Provider(clouds)
                p.p.destroy(name=names)

            return ""

        elif arguments.list:
            print("list the vms in the cloud")

            clouds = get_commands("list", arguments)
            if clouds is None:
                return ""
            else:
                p = Provider(clouds)
                vms = p.p.list()
                print(Printer.flatwrite(vms,
                                sort_keys=("name"),
                                order=["name", "state", "public_ips", "private_ips", "size", "image"],
                                header=["Name", "State", "Public IP", "Private IP", "Size", "Image"])
                )


        elif arguments.resize:
            """
            vm resize [NAMES] [--size=SIZE]
            """
            pass

        elif arguments.ssh:

            print("ssh  into the vm and execute command")

            clouds, names, command = get_commands("ssh", arguments)
            if clouds is None or names is None or command is None:
                return ""
            else:
                p = Provider(clouds)
                p.p.ssh(name=names, command=command)
Example #19
0
    def do_sec(self, args, arguments):
        """
        ::

            Usage:
                sec rule list [--cloud=CLOUDS] [--output=OUTPUT]
                sec rule add RULE FROMPORT TOPORT PROTOCOL CIDR
                sec rule delete RULE [--cloud=CLOUD]
                sec group list [--cloud=CLOUDS] [--output=OUTPUT]
                sec group add GROUP RULES DESCRIPTION
                sec group delete GROUP [--cloud=CLOUD]
                sec group load [GROUP] [--cloud=CLOUD]
                sec list [--output=OUTPUT]
                sec load
                sec clear

            Options:
                --output=OUTPUT Specify output format, in one of the following:
                                table, csv, json, yaml, dict
                                [default: table].
                --cloud=CLOUD   Name of the IaaS cloud e.g. kilo,chameleon.
                                The clouds are defined in the yaml file.
                                If the name "all" is used for the cloud all
                                clouds will be selected.
            Arguments:
                RULE          The security group rule name
                GROUP         The label/name of the security group
                FROMPORT      Staring port of the rule, e.g. 22
                TOPORT        Ending port of the rule, e.g. 22
                PROTOCOL      Protocol applied, e.g. TCP,UDP,ICMP
                CIDR          IP address range in CIDR format, e.g.,
                              129.79.0.0/16

            Examples:
                # sec load
                # sec group list
                # sec group add my_new_group webapp 8080 8080 tcp 0.0.0.0/0


            Bugs:
                # sec group list --cloud=chameleon
                # seg group delete my_group my_rule
                # sec group delete my_unused_group --cloud=kilo
                # sec group upload --cloud=kilo



            Description:


               Database commands:

                   sec clear
                       removes all rules and groups from the database

                   sec load
                        loads some default security groups and rules in the
                        database

                    sec clear
                        deletes all security groups and rules in the database

                    sec rule list  [--output=OUTPUT]
                        lists all security groups and rules in the database

                    sec rule add RULE FROMPORT TOPORT PROTOCOL CIDR
                        adds a security rule with the given group and the details
                        of the security rules

                    sec group add GROUP RULES DESCRIPTION
                        adds a security group with the given group and the
                        details of the security groups

                    sec rule delete RULE
                        deletes the rule form the database

                    sec group delete GROUP
                        deletes the group form the database


                Cloud commands:

                    sec rule list --cloud=CLOUDS [--output=OUTPUT]
                        lists all security rules in the specified cloud

                    sec group list --cloud=CLOUDS [--output=OUTPUT]
                        lists all security groups in the specified cloud

                    sec rule delete RULE --cloud=CLOUD
                        deletes the rule form the cloud

                    sec group delete GROUP [--cloud=CLOUD]
                        deletes the group from the cloud

                    sec load GROUP --cloud=CLOUD
                        uploads the group to the cloud with all its rules


        """

        map_parameters(arguments, 'cloud', 'output', 'name')

        rules = SecgroupRule()
        groups = Secgroup()

        def Print(kind, list):
            if kind == "group":
                output = ""
            else:
                output = groups.output

            print(
                Printer.write(list,
                              sort_keys=output[kind]['sort_keys'],
                              order=output[kind]['order'],
                              header=output[kind]['header'],
                              output=arguments.output))

        def list_all():

            data = []

            group_entries = groups.list()

            for group_entry in group_entries:
                group_name = group_entry['name']

                for rule_name in group_entry['rules']:
                    try:
                        rule_entry = rules.list(name=rule_name)[0]
                        rule_entry['rule'] = rule_name
                        rule_entry['group'] = group_name
                        data.append(rule_entry)
                    except:
                        pass
            Print("all", data)

        if (arguments.load and not arguments.group) or \
            (arguments.load and arguments.group and not arguments.GROUP):

            examples = SecgroupExamples()
            examples.load()
            list_all()

            return ""

        elif arguments.load and arguments.group and arguments.cloud:

            provider = Provider(name=arguments.cloud)
            provider.upload_secgroup(name=arguments.GROUP)

            return ""

        elif arguments.list and not arguments.rule and not arguments.group:

            found = groups.list()
            for entry in found:
                group_rules = entry['rules']
                if type(group_rules) == list:
                    entry['rules'] = ', '.join(group_rules)

            Print("secgroup", found)

            found = rules.list()
            Print("secrule", found)

        elif arguments.group and arguments.delete:

            if arguments.cloud:
                clouds = Parameter.expand(arguments.cloud)
                for cloud in clouds:
                    print(f"cloud {cloud}")
                    provider = Provider(name=cloud)
                    r = provider.remove_secgroup(name=arguments.GROUP)

            else:
                groups.remove(arguments.GROUP)

        elif (arguments.group or arguments.rule) and arguments.list and \
            arguments.cloud:

            clouds = Parameter.expand(arguments.cloud)
            if len(clouds) == 0:
                variables = Variables()
                cloudname = variables['cloud']
                clouds = [cloudname]
            keys = []

            for cloud in clouds:
                print(f"cloud {cloud}")
                provider = Provider(name=cloud)
                cloud_groups = provider.list_secgroups()

                if arguments.output == 'table':
                    result = []
                    for group in cloud_groups:
                        if cloud == "aws":
                            for rule in group['IpPermissions']:
                                rule['name'] = group['GroupName']
                                rule['direction'] = "Inbound"
                                if rule['UserIdGroupPairs']:
                                    rule['groupId'] = \
                                        rule['UserIdGroupPairs'][0]['GroupId']
                                if rule['IpRanges']:
                                    rule['ipRange'] = rule['IpRanges'][0][
                                        'CidrIp']

                                result.append(rule)
                        else:
                            for rule in group['security_group_rules']:
                                rule['name'] = group['name']
                                result.append(rule)
                        cloud_groups = result
                provider.p.Print(
                    cloud_groups,
                    output=arguments.output,
                    kind="secrule",
                )

            return ""

        elif arguments.group and arguments.list:
            found = groups.list()
            for entry in found:
                group_rules = entry['rules']
                if type(group_rules) == list:
                    entry['rules'] = ', '.join(group_rules)

            Print("secgroup", found)

            return ""

        elif arguments.rule and arguments.list:
            found = rules.list()
            Print("secrule", found)

            return ""

        elif arguments.rule and arguments.add:
            rules = SecgroupRule()
            #  name=None, protocol=None, ports=None, ip_range=None
            rules.add(name=arguments.RULE,
                      ports=f"{arguments.FROMPORT}" + ":" +
                      f"{arguments.TOPORT}",
                      protocol=arguments.PROTOCOL,
                      ip_range=arguments.CIDR)

            return ""

        elif arguments.group and arguments.add:
            group = Secgroup()
            group.add(name=arguments.GROUP,
                      rules=arguments.RULES,
                      description=arguments.DESCRIPTION)

            return ""

        elif arguments.list:

            found = rules.list()
            Print("secrule", found)

            return ""

        elif arguments.clear:

            groups.clear()
            rules.clear()

            return ""

        return ""
 def setup(self):
     self.p = Provider(name="az")
     self.vm_name = VM
     self.group = self.p.credentials["resourcegroup"]
     self.location = self.p.credentials["location"]
Example #21
0
    def do_key(self, args, arguments):
        """
        ::

           Usage:
             key  -h | --help
             key list --cloud=CLOUDS [--output=OUTPUT]
             key list --source=ssh [--dir=DIR] [--output=OUTPUT]
             key list --source=git [--output=OUTPUT] [--username=USERNAME]
             key list [--output=OUTPUT]
             key init
             key add NAME --filename=FILENAME [--output=OUTPUT]
             key add [NAME] [--source=FILENAME]
             key add [NAME] [--source=git]
             key add [NAME] [--source=ssh]
             key delete NAMES [--cloud=CLOUDS] [--dryrun]
             key upload [NAMES] [--cloud=CLOUDS] [--dryrun]
             key upload [NAMES] [VMS] [--dryrun]
             key group upload [NAMES] [--group=GROUPNAMES] [--cloud=CLOUDS] [--dryrun]
             key group add [NAMES] [--group=GROUPNAMES] [--cloud=CLOUDS] [--dryrun]
             key group delete [--group=GROUPNAMES] [NAMES] [--dryrun]
             key group list [--group=GROUPNAMES] [--output=OUTPUT]
             key group export --group=GROUNAMES --filename=FILENAME
             key gen (ssh | pem) [--filename=FILENAME] [--nopass] [--set_path] [--force]
             key reformat (ssh | pem) [--filename=FILENAME] [--format=FORMAT]
                                      [--nopass] [--pub]
             key verify (ssh | pem) [--filename=FILENAME] [--pub] [--check_pass]

           Arguments:
             VMS        Parameterized list of virtual machines
             CLOUDS     The clouds
             NAME       The name of the key.
             SOURCE     db, ssh, all
             OUTPUT     The format of the output (table, json, yaml)
             FILENAME   The filename with full path in which the key is located
             FORMAT     Desired key format (SubjectInfo, SSH, OpenSSL, PKCS8)

           Options:
              --dir=DIR             the directory with keys [default: ~/.ssh]
              --check_pass          Flag where program query user for password
              --filename=FILENAME   the name and full path to the file
              --nopass              Flag indicating if the key has no password
              --output=OUTPUT       the format of the output [default: table]
              --pub                 Indicates that the public key is passed in
              --set_path            Sets the cloudmesh encryption key path to
                                    the full path of the generated keys
              --source=SOURCE       the source for the keys
              --username=USERNAME   the source for the keys [default: none]


           Description:

               Please note that some values are read from the cloudmesh.yaml
               file. One such value is cloudmesh.profile.user

               Management of public keys is an essential component of accessing
               virtual machines in the cloud. There are a number of sources
               where you can find public keys. This includes the ~/.ssh
               directory and for example github. If you do not already have a
               public-private key pair they can be generated using cloudmesh

               key gen ssh 
                   This will create the public-private keypair of ~/.ssh/id_rsa
                   and ~/.ssh/id_rsa.pub in OpenSSH format

               key gen pem 
                   This will create the public-private keypair of ~/.ssh/id_rsa
                   and ~/.ssh/id_rsa.pub in PEM format

               key gen (ssh | pem) --filename=~/.cloudmesh/foobar
                   This will generate the public-private key pair of 
                   ~/.cloudmesh/foobar and ~/.cloudmesh/foobar.pub

               key gen (ssh | pem) --filename=~/.cloudmesh/foobar --set_path
                   This will generate the keys as stated above, but it will
                   also set cloudmesh to use these keys for encryption.

               Keys can also be verified for their formatting and passwords.
               By default cloudmesh checks ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub
               If the key is password protected the formatting can only be
               verified if the password is provided (--check_pass argument)

               key verify pem
                   Verifies that ~/.ssh/id_rsa has PEM format

               key verify ssh --pub
                   Verifies that ~/.ssh/id_rsa.pub has OpenSSH format

               key verify pem --filename=~/.cloudmesh/foobar
                   Verifies if the private key located at ~/.cloudmesh/foobar
                   is password protected

               key verify pem --filenam=~/.cloudmesh/foobar --check_pass
                   Request the password to the file, then checks if the
                   key is in proper PEM format

               You may find the need to keep the values of your keys but
               different encodings or formats. These aspects of your key can
               also be changed using cloudmesh.

               key reformat pem
                   Will reformat the ~/.id_rsa.pub key from PEM to OpenSSH

               key reformat ssh
                   Will reformat the ~/.id_rsa.pub key from OpenSSH to PEM

               key reformat --filename=~/.id_rsa --format=PKCS8
                   Will reformat the private key to PKCS8 format

               Keys will be uploaded into cloudmesh database with the add
               command under the given NAME. If the name is not specified the name
               cloudmesh.profile.user is assumed.

                key add NAME  --source=ssh
                    adds the default key in ~/.ssh/id_rsa.pub
                key add NAME  --source=FILENAME
                    adds the key specified by the filename with the given name
                key add NAME --git --username=username
                    adds a named github key from a user with the given github
                    username.

                key set
                    adds the ~/.ssh/id_rsa.pub key with the name specified in
                    cloudmesh.profile.user.
                    It also sets the variable key to that user.


               Once the keys are uploaded to github, they can be listed
               To list these keys the following list functions are provided.

                key list --source=git  [--username=USERNAME]
                    lists all keys in git for the specified user. If the
                    name is not specified it is read from cloudmesh.yaml
                key list --source=ssh  [--dir=DIR] [--output=OUTPUT]
                    lists all keys in the directory. If the directory is not
                    specified the default will be ~/.ssh

                key list NAMES
                    lists all keys in the named virtual machines.


                List command can use the [--output=OUTPUT] option

                    list the keys loaded to cloudmesh in the given format:
                    json, yaml, table. table is default. The NAME can be
                    specified and if omitted the name cloudmesh.profile.user
                    is assumed.

                To get keys from the cloudmesh database the following commands
                are available:

                key delete NAMES
                    deletes the Named keys. This may also have an impact on groups
                key rename NAME NEW
                    renames the key from NAME to NEW in the cloudmesh database.

               Group management of keys is an important concept in cloudmesh,
               allowing multiple users to be added to virtual machines while
               managing the keys associated with them. The keys must be uploaded
               to cloudmesh database with a name so they can be used in a
               group. The --dryrun option executes the command without
               uploading the information to the clouds. If no group name is
               specified the group name default is assumed. If no cloudnamesh
               are specified, all active clouds are assumed. active clouds
               can be set in the cloudmesh.yaml file.

                key group delete [GROUPNAMES] [NAMES] [--dryrun]
                    deletes the named keys from the named groups.

                key group list [GROUPNAMES] [--output=OUTPUT]
                    list the key names and details in the group.

                key group upload [GROUPNAMES] [CLOUDS] [--dryrun]
                    uploads the named groups to the specified clouds.

               In some cases you may want to store the public keys in files. For
               this reason we support the following commands.

                key group add --group=GROUPNAME --file=FILENAME
                    the command adds the keys to the given group. The keys are
                    written in the files in yaml format.


                key group export --group=GROUNAMES --filename=FILENAME
                    the command exports the keys to the given group. The keys are
                    written in the files in yaml format.


                The yaml format is as follows:

                cloudmesh:
                  keys:
                    NAMEOFKEY:
                      name: NAMEOFKEY
                      key: ssh-rsa AAAA..... comment
                      group:
                      - GROUPNAME
                    ...

                If a key is included in multiple groups they will be added
                to the grouplist of the key
        """
        def print_keys(keys):
            print(
                Printer.write(
                    keys,
                    sort_keys=["name"],
                    order=["name", "type", "fingerprint", "comment"],
                    header=["Name", "Type", "Fingerprint", "Comment"],
                    output=arguments.output))

        map_parameters(arguments, 'check_pass', 'cloud', 'dir', 'dryrun',
                       'filename', 'force', 'format', 'name', 'nopass',
                       'output', 'pub', 'pwd', 'set_path', 'source')

        variables = Variables()

        if arguments.list and arguments.source == "git":

            config = Config()
            username = config["cloudmesh.profile.github"]
            keys = SSHkey().get_from_git(username)

            print_keys(keys)

            return ""

        elif arguments.list and arguments.source == "ssh":
            # this is much simpler

            sshkey = SSHkey()

            print_keys([sshkey])

            return ""

        elif arguments.list and arguments.cloud:

            clouds = Parameter.expand(arguments.cloud)

            if len(clouds) == 0:
                variables = Variables()
                cloudname = variables['cloud']
                clouds = [cloudname]
            keys = []

            for cloud in clouds:
                print(f"cloud {cloud}")
                provider = Provider(name=cloud)
                keys = provider.keys()

                provider.Print(keys, output=arguments.output, kind="key")

            return ""

        elif arguments.list:

            cloud = "local"
            db = CmDatabase()
            keys = db.find(collection=f"{cloud}-key")

            print_keys(keys)

            return ""

        elif arguments.add:
            """
            key add [NAME] [--source=FILENAME] # NOT IMPLEMENTED YET
            key add [NAME] [--source=git]
            key add [NAME] [--source=ssh]
            """

            key = Key()

            if arguments["--source"] == "ssh":
                name = arguments.NAME or "ssh"
                key.add(name, "ssh")
            elif arguments["--source"] == "git":
                name = arguments.NAME or "git"
                key.add("git", "git")
            else:
                config = Config()
                name = config["cloudmesh.profile.user"]
                kind = "ssh"
                key.add(name, kind)

        elif arguments.init:
            """
            key init 
            """

            config = Config()
            username = config["cloudmesh.profile.user"]

            if username == "TBD":
                Console.error(
                    "Please set cloudmesh.profile.user in ~/.cloudmesh.yaml")
                u = os.environ["USER"].lower().replace(" ", "")
                Console.msg(
                    f"To change it you can use the command. Define a NAME such as '{u}' e.g."
                )
                Console.msg("")
                Console.msg(f"  cms config set cloudmesh.profile.user={u}")
                Console.msg("")
                return ""

            key = Key()

            key.add(username, "ssh")
            variables['key'] = username

        elif arguments.upload:
            """
            key upload [NAMES] [--cloud=CLOUDS] [--dryrun]
            key upload [NAMES] [VMS] [--dryrun]
            """

            names = Parameter.expand(arguments.NAMES)

            # this may have a bug if NAMES is ommitted

            #
            # Step 0. Set keyname to variable
            #

            if names is None or len(names) == 0:
                config = Config()
                username = config["cloudmesh.profile.user"]
                names = [username]

            if len(names) == 1:
                name = names[0]
                variables = Variables()
                if "key" in variables:
                    old = variables["key"]
                    if old != name:
                        Console.msg(
                            f"Changing default key from {old} to {name}")
                        variables["key"] = name

            #
            # Step 1. keys = find keys to upload
            #

            cloud = "local"
            db = CmDatabase()
            db_keys = db.find(collection=f"{cloud}-key")

            keys = []
            for key in db_keys:
                if key["name"] in names:
                    keys.append(key)

            if len(keys) == 0:
                Console.error(
                    f"No keys with the names {names} found in cloudmesh. \n"
                    "       Use the command 'key add' to add the key.")

            #
            # Step 2. iterate over the clouds to upload
            #

            clouds, vmnames = Arguments.get_cloud_and_names(
                "list", arguments, variables)

            for cloud in clouds:
                print(f"cloud {cloud}")
                provider = Provider(name=cloud)
                for key in db_keys:
                    name = key['name']
                    if name in names:
                        try:
                            r = provider.key_upload(key)
                            Console.ok(f"upload key '{name} successful'. ")
                        except ValueError as e:
                            Console.error(
                                f"key '{name} already exists in {cloud}.")

            return ""

        elif arguments.delete and arguments.cloud and arguments.NAMES:

            # key delete NAMES --cloud=CLOUDS [--dryrun]
            names = Parameter.expand(arguments.NAMES)
            clouds = Parameter.expand(arguments.cloud)

            for cloud in clouds:
                provider = Provider(name=cloud)
                for name in names:
                    if arguments.dryrun:
                        Console.ok(f"Dryrun: delete {name} in {cloud}")
                    else:
                        images = provider.key_delete(name)

            return ""

        elif arguments.gen:
            """
            key gen (ssh | pem) [--filename=FILENAME] [--nopass] [--set_path]
                    [--force]
            Generate an RSA key pair with pem or ssh encoding for the public
            key. The private key is always encoded as a PEM file.
            """
            config = Config()

            # Check if password will be requested
            ap = not arguments.nopass

            if not ap:
                Console.warning("Private key will NOT have a password")
                cnt = yn_choice(message="Continue, despite risk?", default="N")
                if not cnt:
                    sys.exit()

            # Discern the name of the public and private keys
            rk_path = None
            uk_path = None
            if arguments.filename:
                fp = path_expand(arguments.filename)
                fname, fext = os.path.splitext(fp)
                if fext == ".pub" or fext == ".ssh":
                    rk_path = fname
                    uk_path = fp
                elif fext == ".priv" or fext == ".pem":
                    rk_path = fp
                    uk_path = fname + ".pub"
                else:
                    rk_path = fp
                    uk_path = rk_path + ".pub"
            else:
                rk_path = path_expand("~/.ssh/id_rsa")
                uk_path = rk_path + ".pub"

            # Check if the file exist, if so confirm overwrite
            def check_exists(path):
                if os.path.exists(path):
                    Console.info(f"{path} already exists")
                    ovwr_r = yn_choice(message=f"overwrite {path}?",
                                       default="N")
                    if not ovwr_r:
                        Console.info(f"Not overwriting {path}. Quitting")
                        sys.exit()

            if not arguments.force:
                check_exists(rk_path)
                check_exists(uk_path)

            # Set the path if requested
            if arguments.set_path:
                config['cloudmesh.security.privatekey'] = rk_path
                config['cloudmesh.security.publickey'] = uk_path
                config.save()

            Console.msg(f"\nPrivate key: {rk_path}")
            Console.msg(f"Public  key: {uk_path}\n")

            # Generate the Private and Public keys
            kh = KeyHandler()
            r = kh.new_rsa_key()
            u = kh.get_pub_key(priv=r)

            # Serialize and write the private key to the path
            sr = kh.serialize_key(key=r,
                                  key_type="PRIV",
                                  encoding="PEM",
                                  format="PKCS8",
                                  ask_pass=ap)

            # Force write the key (since we check file existence above)
            kh.write_key(key=sr, path=rk_path, force=True)

            # Determine the public key format and encoding
            enc = None
            forma = None
            if arguments.ssh:
                enc = "SSH"
                forma = "SSH"
            elif arguments.pem:
                enc = "PEM"
                forma = "SubjectInfo"

            # Serialize and write the public key to the path
            su = kh.serialize_key(key=u,
                                  key_type="PUB",
                                  encoding=enc,
                                  format=forma,
                                  ask_pass=False)

            # Force write the key (since we check file existence above)
            kh.write_key(key=su, path=uk_path, force=True)

            Console.ok("Success")

        elif arguments.verify:
            """
            key verify (ssh | pem) [--filename=FILENAME] [--pub] [--check_pass]
            Verifies the encoding (pem or ssh) of the key (private or public)
            """
            # Initialize variables
            kh = KeyHandler()

            # Determine filepath
            fp = None
            if arguments.filename is None:
                config = Config()
                kp = path_expand("~/.ssh/id_rsa")
                if arguments.pub:
                    fp = kp + ".pub"
                else:
                    fp = kp
            else:
                fp = arguments.filename

            # Discern key type
            kt = enc = None
            ap = True
            if arguments.pub:
                # Load the public key, if no error occurs formatting is correct
                kt, kta, ap = "public", "PUB", False
                # Discern public key encoding
                if arguments.ssh:
                    enc, e = "OpenSSH", "SSH"
                elif arguments.pem:  # PEM encoding
                    enc = e = "PEM"
            else:
                # Load the private key to verify the format and password of the
                # key file. If no error occurs the format and pwd are correct
                kt, kta = "private", "PRIV"
                enc = e = "PEM"
                ap = False
                if arguments.check_pass:
                    ap = True

            try:
                k = kh.load_key(path=fp, key_type=kta, encoding=e, ask_pass=ap)
                m = f"Success the {kt} key {fp} has proper {enc} format"
                Console.ok(m)
            except ValueError as e:
                # The formatting was incorrect
                m = f"Failure, {kt} key {fp} does not have proper {enc} format"
                Console.error(m)
                raise e
            except TypeError as e:
                # Success, we didn't ask the user for the key password and
                # we received an error for not entering the password, thus
                # the key is password protectd
                if not arguments.check_pass:
                    Console.ok("The key is password protected")
                else:
                    # Error Message handled in kh.load_key()
                    raise e

        elif arguments.reformat:
            """
            key reformat (ssh | pem) [--filename=FILENAME] [--format=FORMAT]
                                      [--nopass] [--pub]
            Restructures a key's format, encoding, and password
            """

            # Initialize variables
            kh = KeyHandler()

            # Determine key type
            fname, fext = os.path.splitext(arguments.filename)
            kt = "PRIV"
            if arguments.pub or fext == ".pub":
                kt = "PUB"

            # Determine new encoding
            use_pem = True
            if arguments.ssh:
                use_pem = False

            kh.reformat_key(path=arguments.filename,
                            key_type=kt,
                            use_pem=use_pem,
                            new_format=arguments.format,
                            ask_pass=not arguments.nopass)

        elif arguments.delete and arguments.NAMES:
            # key delete NAMES [--dryrun]

            names = Parameter.expand(arguments.NAMES)

            cloud = "local"
            db = CmDatabase()
            db_keys = db.find(collection=f"{cloud}-key")

            error = []
            for key in db_keys:
                name = key['name']
                if name in names:
                    if arguments.dryrun:
                        Console.ok(f"Dryrun: delete {name}")
                    else:
                        db.delete(collection="local-key", name=name)
                        Console.ok(f"delete {name}")
            return ""

        elif arguments.group:

            raise NotImplementedError

        return ""
class Test_Compute_Database:
    def setup(self):
        print()
        self.user = Config()["cloudmesh"]["profile"]["user"]
        self.clouduser = '******'
        self.name_generator = Name(experiment="exp",
                                   group="grp",
                                   user=self.user,
                                   kind="vm",
                                   counter=1)

        self.name = str(self.name_generator)
        self.name_generator.incr()

        self.new_name = str(self.name_generator)

        variables = Variables()
        clouds = Parameter.expand(variables['cloud'])
        cloud = clouds[0]

        self.p = Provider(name=cloud)

        self.secgroupname = "CM4TestSecGroup"
        self.secgrouprule = {
            "ip_protocol": "tcp",
            "from_port": 8080,
            "to_port": 8088,
            "ip_range": "129.79.0.0/16"
        }
        self.testnode = None
        print("\n")

    def test_00_banner(self):
        StopWatch.start("banner")
        banner("START", color="RED")
        StopWatch.stop("banner")

    def test_01_list_flavors(self):
        HEADING()
        StopWatch.start("list flavors")
        flavors = self.p.flavors()
        StopWatch.stop("list flavors")

    def test_02_list_images(self):
        HEADING()
        StopWatch.start("list images")
        images = self.p.images()
        StopWatch.stop("list images")

    def test_03_list_nodes(self):
        HEADING()
        StopWatch.start("list nodes")
        nodes = self.p.list()
        StopWatch.stop("list nodes")

    def test_04_list_keys(self):
        HEADING()
        StopWatch.start("list keys")
        self.keys = self.p.keys()

        # pprint(self.keys)

        # print(Printer.flatwrite(self.keys,
        #                    sort_keys=["name"],
        #                    order=["name", "fingerprint"],
        #                    header=["Name", "Fingerprint"])
        #      )

        StopWatch.stop("list keys")

    def test_05_key_upload(self):
        HEADING()
        StopWatch.start("key upload")
        key = SSHkey()
        print(key.__dict__)

        self.p.key_upload(key)

        self.test_04_list_keys()
        StopWatch.stop("key upload")

    def test_06_list_images(self):
        HEADING()
        StopWatch.start("list images2")
        images = self.p.images()
        # pprint(images)
        sort_keys = self.p.p.output['image']['sort_keys']  # not pretty
        order = self.p.p.output['image']['order']  # not pretty
        header = self.p.p.output['image']['header']  # not pretty

        print(
            Printer.flatwrite(images,
                              sort_keys=sort_keys,
                              order=order,
                              header=header))
        StopWatch.stop("list images2")

    def test_07_list_vm(self):
        HEADING()
        StopWatch.start("list vm")
        vms = self.p.list()
        # pprint (vms)

        sort_keys = self.p.p.output['vm']['sort_keys']  # not pretty
        order = self.p.p.output['vm']['order']  # not pretty
        header = self.p.p.output['vm']['header']  # not pretty

        print(
            Printer.flatwrite(vms,
                              sort_keys=sort_keys,
                              order=order,
                              header=header))

        StopWatch.stop("list vm")

    def test_print(self):
        HEADING()
        StopWatch.benchmark()
Example #23
0
 def setup(self):
     self.p = Provider(name=CLOUD)
     self.name = VM
     self.group = "test"
     self.location = "eastus"
Example #24
0
    def do_image(self, args, arguments):
        """
        ::

            Usage:
                image list [NAMES] [--cloud=CLOUD] [--refresh] [--output=OUTPUT] [--query=QUERY]

            Options:
               --output=OUTPUT  the output format [default: table]
               --cloud=CLOUD    the cloud name
               --refresh        live data taken from the cloud

            Description:
                image list
                image list --cloud=aws --refresh
                image list --output=csv
                image list 58c9552c-8d93-42c0-9dea-5f48d90a3188 --refresh
        """

        map_parameters(arguments, "query", "refresh", "cloud", "output")

        variables = Variables()

        arguments.output = Parameter.find("output", arguments, variables,
                                          "table")

        arguments.refresh = Parameter.find_bool("refresh", arguments,
                                                variables)
        if arguments.list and arguments["--query"]:

            names = []

            clouds, names = Arguments.get_cloud_and_names(
                "list", arguments, variables)

            for cloud in clouds:
                print(f"cloud {cloud} query={arguments.query}")
                provider = Provider(name=cloud)
                if arguments.query is not None:
                    query = eval(arguments.query)
                    images = provider.images(**query)
                else:
                    images = provider.images()

                provider.Print(images, output=arguments.output, kind="image")

            return ""

        if arguments.list and arguments.refresh:

            names = []

            clouds, names = Arguments.get_cloud_and_names(
                "list", arguments, variables)

            for cloud in clouds:
                print(f"cloud {cloud}")
                provider = Provider(name=cloud)
                images = provider.images()

                provider.Print(images, output=arguments.output, kind="image")

            return ""

        elif arguments.list:

            clouds, names = Arguments.get_cloud_and_names(
                "list", arguments, variables)

            print(clouds)
            print("find images")

            try:

                for cloud in clouds:
                    print(f"List {cloud} images")
                    provider = Provider(name=cloud)

                    db = CmDatabase()

                    images = db.find(collection=f"{cloud}-image")

                    provider.Print(images,
                                   output=arguments.output,
                                   kind="image")

            except Exception as e:

                VERBOSE(e)

            return ""
Example #25
0
    def do_image(self, args, arguments):
        """
        ::

            Usage:
                image list [NAMES] [--cloud=CLOUD] [--refresh] [--output=OUTPUT]

            Options:
               --output=OUTPUT  the output format [default: table]
               --cloud=CLOUD    the cloud name
               --refresh        live data taken from the cloud

            Description:
                cm image list
                cm image list --output=csv
                cm image list 58c9552c-8d93-42c0-9dea-5f48d90a3188 --refresh
        """

        map_parameters(arguments, "refresh", "cloud", "output")

        VERBOSE.print(arguments, verbose=9)

        variables = Variables()

        if arguments.list and arguments.refresh:

            names = []

            clouds, names = Arguments.get_cloud_and_names(
                "list", arguments, variables)

            print("AAA", clouds, names)

            for cloud in clouds:
                print(f"cloud {cloud}")
                provider = Provider(name=cloud)
                images = provider.images()

                order = provider.p.output['vm']['order']  # not pretty
                header = provider.p.output['vm']['header']  # not pretty

                print(
                    Printer.flatwrite(images,
                                      sort_keys=["name"],
                                      order=order,
                                      header=header,
                                      output=arguments.output))
            return ""

        elif arguments.list:

            names = []

            clouds, names = Arguments.get_cloud_and_names(
                "list", arguments, variables)

            print(clouds, names)
            try:

                for cloud in clouds:
                    print(f"List {cloud}")
                    p = Provider(cloud)
                    kind = p.kind

                    collection = "{cloud}-image".format(cloud=cloud,
                                                        kind=p.kind)
                    db = CmDatabase()
                    vms = db.find(collection=collection)

                    order = p.p.output['vm']['order']  # not pretty
                    header = p.p.output['vm']['header']  # not pretty

                    print(
                        Printer.flatwrite(vms,
                                          sort_keys=["name"],
                                          order=order,
                                          header=header,
                                          output=arguments.output))

            except Exception as e:

                VERBOSE.print(e, verbose=9)

            return ""
Example #26
0
    def do_key(self, args, arguments):
        """
        ::

           Usage:
             key  -h | --help
             key list --cloud=CLOUDS [--output=OUTPUT]
             key list --source=ssh [--dir=DIR] [--output=OUTPUT]
             key list --source=git [--output=OUTPUT] [--username=USERNAME]
             key list [--output=OUTPUT]
             key init
             key add NAME --filename=FILENAME [--output=OUTPUT]
             key add [NAME] [--source=FILENAME]
             key add [NAME] [--source=git]
             key add [NAME] [--source=ssh]
             key delete NAMES [--cloud=CLOUDS] [--dryrun]
             key upload [NAMES] [--cloud=CLOUDS] [--dryrun]
             key upload [NAMES] [VMS] [--dryrun]
             key group upload [NAMES] [--group=GROUPNAMES] [--cloud=CLOUDS] [--dryrun]
             key group add [--group=GROUPNAMES] [--cloud=CLOUDS] [--dryrun]
             key group add --file=FILENAME
             key group delete [--group=GROUPNAMES] [NAMES] [--dryrun]
             key group list [--group=GROUPNAMES] [--output=OUTPUT]
             key group export --group=GROUNAMES --filename=FILENAME
             key gen (rsa | ssh) [--filename=FILENAME] [--nopass] [--set_path]
             key verify (ssh | pem) --filename=FILENAME [--pub]

           Arguments:
             VMS            Parameterized list of virtual machines
             CLOUDS         The clouds
             NAME           The name of the key.
             SOURCE         db, ssh, all
             KEYNAME        The desired full path name to the key file
             OUTPUT         The format of the output (table, json, yaml)
             FILENAME       The filename with full path in which the key is located

           Options:
              --dir=DIR             the directory with keys [default: ~/.ssh]
              --filename=FILENAME   the name and full path to the file
              --nopass              Flag indicating if the key has no password
              --output=OUTPUT       the format of the output [default: table]
              --pub                 Indicates that the public key is passed in
              --set_path            Sets the security key paths to KEYNAME
              --source=SOURCE       the source for the keys
              --username=USERNAME   the source for the keys [default: none]


           Description:

               Please note that some values are read from the cloudmesh.yaml
               file. One such value is cloudmesh.profile.user

               Manages public keys is an essential component of accessing
               virtual machine sin the cloud. There are a number of sources
               where you can find public keys. This includes teh ~/.ssh
               directory and for example github.

               Keys will be uploaded into cloudmesh database with the add
               command under the given NAME. If the name is not specified the name
               cloudmesh.profile.user is assumed.

                key add NAME  --source=ssh
                    adds the default key in ~/.ssh/id_rsa.pub
                key add NAME  --source=FILENAME
                    adds the key specified by the filename with the given name
                key add NAME --git --username=username
                    adds a named github key from a user with the given github
                    username.

                key set
                    adds the ~/.ssh/id_rsa.pub key with the name specified in
                    cloudmesh.profile.user.
                    It also sets the variable key to that user.


               Once the keys are uploaded to github, they can be listed
               To list these keys the following list functions are provided.

                key list --source=git  [--username=USERNAME]
                    lists all keys in git for the specified user. If the
                    name is not specified it is read from cloudmesh.yaml
                key list --source=ssh  [--dir=DIR] [--output=OUTPUT]
                    lists all keys in the directory. If the directory is not
                    specified the default will be ~/.ssh

                key list NAMES
                    lists all keys in the named virtual machines.


                List command can use the [--output=OUTPUT] option

                    list the keys loaded to cloudmesh in the given format:
                    json, yaml, table. table is default. The NAME can be
                    specified and if omitted the name cloudmesh.profile.user
                    is assumed.

                To get keys from the cloudmesh database the following commands
                are available:

                key delete NAMES
                    deletes the Named keys. This may also have an impact on groups
                key rename NAME NEW
                    renames the key from NAME to NEW in the cloudmesh database.

               Group management of keys is an important concept in cloudmesh,
               allowing multiple users to be added to virtual machines while
               managing the keys associated with them. The keys must be uploaded
               to cloudmesh database with a name so they can be used in a
               group. The --dryrun option executes the command without
               uploading the information to the clouds. If no group name is
               specified the group name default is assumed. If no cloudnamesh
               are specified, all active clouds are assumed. active clouds
               can be set in the cloudmesh.yaml file.

                key group delete [GROUPNAMES] [NAMES] [--dryrun]
                    deletes the named keys from the named groups.

                key group list [GROUPNAMES] [--output=OUTPUT]
                    list the key names and details in the group.

                key group upload [GROUPNAMES] [CLOUDS] [--dryrun]
                    uploads the named groups to the specified clouds.

               In some cases you may want to store the public keys in files. For
               this reason we support the following commands.

                key group add --group=GROUPNAME --file=FILENAME
                    the command adds the keys to the given group. The keys are
                    written in the files in yaml format.


                key group export --group=GROUNAMES --filename=FILENAME
                    the command exports the keys to the given group. The keys are
                    written in the files in yaml format.


                The yaml format is as follows:

                cloudmesh:
                  keys:
                    NAMEOFKEY:
                      name: NAMEOFKEY
                      key: ssh-rsa AAAA..... comment
                      group:
                      - GROUPNAME
                    ...

                If a key is included in multiple groups they will be added
                to the grouplist of the key
        """
        def print_keys(keys):
            print(
                Printer.write(
                    keys,
                    sort_keys=["name"],
                    order=["name", "type", "fingerprint", "comment"],
                    header=["Name", "Type", "Fingerprint", "Comment"],
                    output=arguments.output))

        map_parameters(arguments, 'cloud', 'dir', 'dryrun', 'filename', 'name',
                       'nopass', 'output', 'pub', 'pwd', 'set_path', 'source')

        variables = Variables()

        if arguments.list and arguments.source == "git":

            config = Config()
            username = config["cloudmesh.profile.github"]
            keys = SSHkey().get_from_git(username)

            print_keys(keys)

            return ""

        elif arguments.list and arguments.source == "ssh":
            # this is much simpler

            sshkey = SSHkey()

            print_keys([sshkey])

            return ""

        elif arguments.list and arguments.cloud:

            clouds = Parameter.expand(arguments.cloud)

            if len(clouds) == 0:
                variables = Variables()
                cloudname = variables['cloud']
                clouds = [cloudname]
            keys = []

            for cloud in clouds:
                print(f"cloud {cloud}")
                provider = Provider(name=cloud)
                keys = provider.keys()

                provider.Print(keys, output=arguments.output, kind="key")

            return ""

        elif arguments.list:

            cloud = "local"
            db = CmDatabase()
            keys = db.find(collection=f"{cloud}-key")

            print_keys(keys)

            return ""

        elif arguments.add:
            """
             key add [NAME] [--source=FILENAME] # NOT IMPLEMENTED YET
             key add [NAME] [--source=git]
             key add [NAME] [--source=ssh]
             """
            key = Key()

            if arguments["--source"] == "ssh":
                name = arguments.NAME or "ssh"
                key.add(name, "ssh")
            elif arguments["--source"] == "git":
                name = arguments.NAME or "git"
                key.add("git", "git")
            else:
                config = Config()
                name = config["cloudmesh.profile.user"]
                kind = "ssh"
                key.add(name, kind)

        elif arguments.init:
            """
            key init 
            """

            config = Config()
            username = config["cloudmesh.profile.user"]

            if username == "TBD":
                Console.error(
                    "Please set cloudmesh.profile.user in ~/.cloudmesh.yaml")
                u = os.environ["USER"].lower().replace(" ", "")
                Console.msg(
                    f"To change it you can use the command. Define a NAME such as '{u}' e.g."
                )
                Console.msg("")
                Console.msg(f"  cms config set cloudmesh.profile.user={u}")
                Console.msg("")
                return ""

            key = Key()

            key.add(username, "ssh")
            variables['key'] = username

        elif arguments.upload:
            """
            key upload [NAMES] [--cloud=CLOUDS] [--dryrun]
            key upload [NAMES] [VMS] [--dryrun]
            """

            names = Parameter.expand(arguments.NAMES)

            # this may have a bug if NAMES is ommitted

            #
            # Step 0. Set keyname to variable
            #

            if names is None or len(names) == 0:
                config = Config()
                username = config["cloudmesh.profile.user"]
                names = [username]

            if len(names) == 1:
                name = names[0]
                variables = Variables()
                if "key" in variables:
                    old = variables["key"]
                    if old != name:
                        Console.msg(
                            f"Changing defualt key from {old} to {name}")
                        variables["key"] = name

            #
            # Step 1. keys = find keys to upload
            #

            cloud = "local"
            db = CmDatabase()
            db_keys = db.find(collection=f"{cloud}-key")

            keys = []
            for key in db_keys:
                if key["name"] in names:
                    keys.append(key)

            if len(keys) == 0:
                Console.error(
                    f"No keys with the names {names} found in cloudmesh. \n"
                    "       Use the command 'key add' to add the key.")

            #
            # Step 2. iterate over the clouds to upload
            #

            clouds, names = Arguments.get_cloud_and_names(
                "list", arguments, variables)

            for cloud in clouds:
                print(f"cloud {cloud}")
                provider = Provider(name=cloud)
                for key in db_keys:
                    name = key['name']
                    if name in names:
                        try:
                            r = provider.key_upload(key)
                            Console.ok(f"upload key '{name} successful'. ")
                        except ValueError as e:
                            Console.error(
                                f"key '{name} already exists in {cloud}.")

            return ""

        elif arguments.delete and arguments.cloud and arguments.NAMES:

            # key delete NAMES --cloud=CLOUDS [--dryrun]
            names = Parameter.expand(arguments.NAMES)
            clouds = Parameter.expand(arguments.cloud)

            for cloud in clouds:
                provider = Provider(name=cloud)
                for name in names:
                    if arguments.dryrun:
                        Console.ok(f"Dryrun: delete {name} in {cloud}")
                    else:
                        images = provider.key_delete(name)

            return ""

        elif arguments.gen:
            """
            key gen (rsa | ssh) [--filename=FILENAME] [--nopass] [--set_path]
            Generate an RSA key pair with pem or ssh encoding for the public
            key. The private key is always encoded as a PEM file.
            """
            config = Config()

            # Check if password will be requested
            ap = not arguments.nopass

            if not ap:
                Console.warning("Private key will NOT have a password")
                cnt = yn_choice(message="Continue, despite risk?", default="N")
                if not cnt:
                    sys.exit()

            # Discern the name of the public and private keys
            rk_path = None
            uk_path = None
            if arguments.filename:
                if arguments.filename[-4:] == ".pub":
                    rk_path = path_expand(arguments.name[-4:])
                    uk_path = path_expand(arguments.name)
                elif arguments.filename[-5:] == ".priv":
                    rk_path = path_expand(arguments.name)
                    uk_path = path_expand(arguments.name[-5:])
                else:
                    rk_path = path_expand(arguments.filename)
                    uk_path = rk_path + ".pub"
            else:
                rk_path = path_expand(config['cloudmesh.security.privatekey'])
                uk_path = path_expand(config['cloudmesh.security.publickey'])

            # Set the path if requested
            if arguments.set_path and arguments.filename:
                config['cloudmesh.security.privatekey'] = rk_path
                config['cloudmesh.security.publickey'] = uk_path
                config.save()

            Console.msg(f"\nPrivate key: {rk_path}")
            Console.msg(f"Public  key: {uk_path}\n")

            # Generate the Private and Public keys
            kh = KeyHandler()
            r = kh.new_rsa_key()
            u = kh.get_pub_key(priv=r)

            # Serialize and write the private key to the path
            sr = kh.serialize_key(key=r,
                                  key_type="PRIV",
                                  encoding="PEM",
                                  format="PKCS8",
                                  ask_pass=ap)
            kh.write_key(key=sr, path=rk_path)

            # Determine the public key format and encoding
            enc = None
            forma = None
            if arguments.ssh:
                enc = "SSH"
                forma = "SSH"
            elif arguments.rsa:
                enc = "PEM"
                forma = "SubjectInfo"

            # Serialize and write the public key to the path
            su = kh.serialize_key(key=u,
                                  key_type="PUB",
                                  encoding=enc,
                                  format=forma,
                                  ask_pass=False)
            kh.write_key(key=su, path=uk_path)

            Console.ok("Success")

        elif arguments.verify:
            """
            key verify (ssh | pem) --filename=FILENAME --pub
            Verifies the encoding (pem or ssh) of the key (private or public)
            """
            kh = KeyHandler()
            fp = arguments.filename
            kt = None
            enc = None

            # Discern key type
            if arguments.pub:
                kt = "public"
                # Discern public key encoding
                if arguments.ssh:
                    enc, e = "OpenSSH", "SSH"
                elif arguments.pem:  #PEM encoding
                    enc = e = "PEM"

                # Load the public key, if no error occurs formatting is correct
                u = kh.load_key(path=fp,
                                key_type="PUB",
                                encoding=e,
                                ask_pass=False)

            else:
                kt, enc = "private", "PEM"

                # Load the private key to verify the formatting and password of
                # the key file. If no error occurs the format and pwd are correct
                r = kh.load_key(path=fp,
                                key_type="PRIV",
                                encoding=enc,
                                ask_pass=True)

            m = f"Success the {kt} key {fp} has proper {enc} format"
            Console.ok(m)

        elif arguments.delete and arguments.NAMES:
            # key delete NAMES [--dryrun]

            names = Parameter.expand(arguments.NAMES)

            cloud = "local"
            db = CmDatabase()
            db_keys = db.find(collection=f"{cloud}-key")

            error = []
            for key in db_keys:
                name = key['name']
                if name in names:
                    if arguments.dryrun:
                        Console.ok(f"Dryrun: delete {name}")
                    else:
                        db.delete(collection="local-key", name=name)
                        Console.ok(f"delete {name}")
            return ""

        elif arguments.group:

            raise NotImplementedError

        return ""
Example #27
0
    def do_key(self, args, arguments):
        """
        ::

           Usage:
             key  -h | --help
             key list --cloud=CLOUDS [--output=OUTPUT]
             key list --source=ssh [--dir=DIR] [--output=OUTPUT]
             key list --source=git [--output=OUTPUT] [--username=USERNAME]
             key list [--output=OUTPUT]
             key init
             key add NAME --filename=FILENAME [--output=OUTPUT]
             key add [NAME] [--source=FILENAME]
             key add [NAME] [--source=git]
             key add [NAME] [--source=ssh]
             key delete NAMES [--cloud=CLOUDS] [--dryrun]
             key upload [NAMES] [--cloud=CLOUDS] [--dryrun]
             key upload [NAMES] [VMS] [--dryrun]
             key group upload [NAMES] [--group=GROUPNAMES] [--cloud=CLOUDS] [--dryrun]
             key group add [NAMES] [--group=GROUPNAMES] [--cloud=CLOUDS] [--dryrun]
             key group delete [--group=GROUPNAMES] [NAMES] [--dryrun]
             key group list [--group=GROUPNAMES] [--output=OUTPUT]
             key group export --group=GROUNAMES --filename=FILENAME
             key gen (ssh | pem) [--filename=FILENAME] [--nopass] [--set_path] [--force]
             key reformat (ssh | pem) [--filename=FILENAME] [--format=FORMAT]
                                      [--nopass] [--pub]
             key verify (ssh | pem) [--filename=FILENAME] [--pub] [--check_pass]

           Arguments:
             VMS        Parameterized list of virtual machines
             CLOUDS     The clouds
             NAME       The name of the key.
             SOURCE     db, ssh, all
             OUTPUT     The format of the output (table, json, yaml)
             FILENAME   The filename with full path in which the key is located
             FORMAT     Desired key format (SubjectInfo, SSH, OpenSSL, PKCS8)

           Options:
              --dir=DIR             the directory with keys [default: ~/.ssh]
              --check_pass          Flag where program query user for password
              --filename=FILENAME   the name and full path to the file
              --nopass              Flag indicating if the key has no password
              --output=OUTPUT       the format of the output [default: table]
              --pub                 Indicates that the public key is passed in
              --set_path            Sets the cloudmesh encryption key path to
                                    the full path of the generated keys
              --source=SOURCE       the source for the keys
              --username=USERNAME   the source for the keys [default: none]


           Description:

               Please note that some values are read from the cloudmesh.yaml
               file. One such value is cloudmesh.profile.user

               Management of public keys is an essential component of accessing
               virtual machines in the cloud. There are a number of sources
               where you can find public keys. This includes the ~/.ssh
               directory and for example github. If you do not already have a
               public-private key pair they can be generated using cloudmesh

               key gen ssh 
                   This will create the public-private keypair of ~/.ssh/id_rsa
                   and ~/.ssh/id_rsa.pub in OpenSSH format

               key gen pem 
                   This will create the public-private keypair of ~/.ssh/id_rsa
                   and ~/.ssh/id_rsa.pub in PEM format

               key gen (ssh | pem) --filename=~/.cloudmesh/foobar
                   This will generate the public-private key pair of 
                   ~/.cloudmesh/foobar and ~/.cloudmesh/foobar.pub

               key gen (ssh | pem) --filename=~/.cloudmesh/foobar --set_path
                   This will generate the keys as stated above, but it will
                   also set cloudmesh to use these keys for encryption.

               Keys can also be verified for their formatting and passwords.
               By default cloudmesh checks ~/.ssh/id_rsa and ~/.ssh/id_rsa.pub
               If the key is password protected the formatting can only be
               verified if the password is provided (--check_pass argument)

               key verify pem
                   Verifies that ~/.ssh/id_rsa has PEM format

               key verify ssh --pub
                   Verifies that ~/.ssh/id_rsa.pub has OpenSSH format

               key verify pem --filename=~/.cloudmesh/foobar
                   Verifies if the private key located at ~/.cloudmesh/foobar
                   is password protected

               key verify pem --filenam=~/.cloudmesh/foobar --check_pass
                   Request the password to the file, then checks if the
                   key is in proper PEM format

               You may find the need to keep the values of your keys but
               different encodings or formats. These aspects of your key can
               also be changed using cloudmesh.

               key reformat pem
                   Will reformat the ~/.id_rsa.pub key from PEM to OpenSSH

               key reformat ssh
                   Will reformat the ~/.id_rsa.pub key from OpenSSH to PEM

               key reformat --filename=~/.id_rsa --format=PKCS8
                   Will reformat the private key to PKCS8 format

               Keys will be uploaded into cloudmesh database with the add
               command under the given NAME. If the name is not specified the name
               cloudmesh.profile.user is assumed.

                key add NAME  --source=ssh
                    adds the default key in ~/.ssh/id_rsa.pub
                key add NAME  --source=FILENAME
                    adds the key specified by the filename with the given name
                key add NAME --git --username=username
                    adds a named github key from a user with the given github
                    username.

                key set
                    adds the ~/.ssh/id_rsa.pub key with the name specified in
                    cloudmesh.profile.user.
                    It also sets the variable key to that user.


               Once the keys are uploaded to github, they can be listed
               To list these keys the following list functions are provided.

                key list --source=git  [--username=USERNAME]
                    lists all keys in git for the specified user. If the
                    name is not specified it is read from cloudmesh.yaml
                key list --source=ssh  [--dir=DIR] [--output=OUTPUT]
                    lists all keys in the directory. If the directory is not
                    specified the default will be ~/.ssh

                key list NAMES
                    lists all keys in the named virtual machines.


                List command can use the [--output=OUTPUT] option

                    list the keys loaded to cloudmesh in the given format:
                    json, yaml, table. table is default. The NAME can be
                    specified and if omitted the name cloudmesh.profile.user
                    is assumed.

                To get keys from the cloudmesh database the following commands
                are available:

                key delete NAMES
                    deletes the Named keys. This may also have an impact on groups
                key rename NAME NEW
                    renames the key from NAME to NEW in the cloudmesh database.

               Group management of keys is an important concept in cloudmesh,
               allowing multiple users to be added to virtual machines while
               managing the keys associated with them. The keys must be uploaded
               to cloudmesh database with a name so they can be used in a
               group. The --dryrun option executes the command without
               uploading the information to the clouds. If no group name is
               specified the group name default is assumed. If no cloudnamesh
               are specified, all active clouds are assumed. active clouds
               can be set in the cloudmesh.yaml file.

                key group delete [GROUPNAMES] [NAMES] [--dryrun]
                    deletes the named keys from the named groups.

                key group list [GROUPNAMES] [--output=OUTPUT]
                    list the key names and details in the group.

                key group upload [GROUPNAMES] [CLOUDS] [--dryrun]
                    uploads the named groups to the specified clouds.

               In some cases you may want to store the public keys in files. For
               this reason we support the following commands.

                key group add --group=GROUPNAME --file=FILENAME
                    the command adds the keys to the given group. The keys are
                    written in the files in yaml format.


                key group export --group=GROUNAMES --filename=FILENAME
                    the command exports the keys to the given group. The keys are
                    written in the files in yaml format.


                The yaml format is as follows:

                cloudmesh:
                  keys:
                    NAMEOFKEY:
                      name: NAMEOFKEY
                      key: ssh-rsa AAAA..... comment
                      group:
                      - GROUPNAME
                    ...

                If a key is included in multiple groups they will be added
                to the grouplist of the key
        """

        def print_keys(keys):
            print(Printer.write(
                keys,
                sort_keys=["name"],
                order=["name", "type", "fingerprint", "comment"],
                header=["Name", "Type", "Fingerprint", "Comment"],
                output=arguments.output)
            )

        map_parameters(arguments,
                       'check_pass',
                       'cloud',
                       'dir',
                       'dryrun',
                       'filename',
                       'force',
                       'format',
                       'name',
                       'nopass',
                       'output',
                       'pub',
                       'pwd',
                       'set_path',
                       'source')

        variables = Variables()

        if arguments.list and arguments.source == "git":

            config = Config()
            username = config["cloudmesh.profile.github"]
            keys = SSHkey().get_from_git(username)

            print_keys(keys)

            return ""

        elif arguments.list and arguments.source == "ssh":
            # this is much simpler

            sshkey = SSHkey()

            print_keys([sshkey])

            return ""

        elif arguments.list and arguments.cloud:

            clouds = Parameter.expand(arguments.cloud)

            if len(clouds) == 0:
                variables = Variables()
                cloudname = variables['cloud']
                clouds = [cloudname]
            keys = []

            for cloud in clouds:
                print(f"cloud {cloud}")
                provider = Provider(name=cloud)
                keys = provider.keys()

                provider.Print(keys, output=arguments.output, kind="key")

            return ""

        elif arguments.list:

            cloud = "local"
            db = CmDatabase()
            keys = db.find(collection=f"{cloud}-key")

            print_keys(keys)

            return ""


        elif arguments.add:

            """
            key add [NAME] [--source=FILENAME] # NOT IMPLEMENTED YET
            key add [NAME] [--source=git]
            key add [NAME] [--source=ssh]
            """

            key = Key()

            if arguments["--source"] == "ssh":
                name = arguments.NAME or "ssh"
                key.add(name, "ssh")
            elif arguments["--source"] == "git":
                name = arguments.NAME or "git"
                key.add("git", "git")
            else:
                config = Config()
                name = config["cloudmesh.profile.user"]
                kind = "ssh"
                key.add(name, kind)

        elif arguments.init:

            """
            key init 
            """

            config = Config()
            username = config["cloudmesh.profile.user"]

            if username == "TBD":
                Console.error(
                    "Please set cloudmesh.profile.user in ~/.cloudmesh.yaml")
                u = os.environ["USER"].lower().replace(" ", "")
                Console.msg(
                    f"To change it you can use the command. Define a NAME such as '{u}' e.g.")
                Console.msg("")
                Console.msg(f"  cms config set cloudmesh.profile.user={u}")
                Console.msg("")
                return ""

            key = Key()

            key.add(username, "ssh")
            variables['key'] = username

        elif arguments.upload:

            """
            key upload [NAMES] [--cloud=CLOUDS] [--dryrun]
            key upload [NAMES] [VMS] [--dryrun]
            """

            names = Parameter.expand(arguments.NAMES)

            # this may have a bug if NAMES is ommitted

            #
            # Step 0. Set keyname to variable
            #

            if names is None or len(names) == 0:
                config = Config()
                username = config["cloudmesh.profile.user"]
                names = [username]

            if len(names) == 1:
                name = names[0]
                variables = Variables()
                if "key" in variables:
                    old = variables["key"]
                    if old != name:
                        Console.msg(
                            f"Changing default key from {old} to {name}")
                        variables["key"] = name

            #
            # Step 1. keys = find keys to upload
            #

            cloud = "local"
            db = CmDatabase()
            db_keys = db.find(collection=f"{cloud}-key")

            keys = []
            for key in db_keys:
                if key["name"] in names:
                    keys.append(key)

            if len(keys) == 0:
                Console.error(
                    f"No keys with the names {names} found in cloudmesh. \n"
                    "       Use the command 'key add' to add the key.")

            #
            # Step 2. iterate over the clouds to upload
            #

            clouds, vmnames = Arguments.get_cloud_and_names("list",
                                                            arguments,
                                                            variables)

            for cloud in clouds:
                print(f"cloud {cloud}")
                provider = Provider(name=cloud)
                for key in db_keys:
                    name = key['name']
                    if name in names:
                        try:
                            r = provider.key_upload(key)
                            Console.ok(f"upload key '{name} successful'. ")
                        except ValueError as e:
                            Console.error(
                                f"key '{name} already exists in {cloud}.")

            return ""


        elif arguments.delete and arguments.cloud and arguments.NAMES:

            # key delete NAMES --cloud=CLOUDS [--dryrun]
            names = Parameter.expand(arguments.NAMES)
            clouds = Parameter.expand(arguments.cloud)

            for cloud in clouds:
                provider = Provider(name=cloud)
                for name in names:
                    if arguments.dryrun:
                        Console.ok(f"Dryrun: delete {name} in {cloud}")
                    else:
                        images = provider.key_delete(name)

            return ""

        elif arguments.group:

            raise NotImplementedError

        return ""
Example #28
0
    def do_vm(self, args, arguments):
        """
        ::

            Usage:
                vm ping [NAMES] [--cloud=CLOUDS] [--count=N] [--processors=PROCESSORS]
                vm check [NAMES] [--cloud=CLOUDS] [--processors=PROCESSORS]
                vm status [NAMES] [--cloud=CLOUDS]
                vm console [NAME] [--force]
                vm start [NAMES] [--cloud=CLOUD] [--dryrun]
                vm stop [NAMES] [--cloud=CLOUD] [--dryrun]
                vm terminate [NAMES] [--cloud=CLOUD] [--dryrun]
                vm delete [NAMES] [--cloud=CLOUD] [--dryrun]
                vm refresh [--cloud=CLOUDS]
                vm list [NAMES]
                        [--cloud=CLOUDS]
                        [--output=OUTPUT]
                        [--refresh]
                vm boot [--name=VMNAMES]
                        [--cloud=CLOUD]
                        [--username=USERNAME]
                        [--image=IMAGE]
                        [--flavor=FLAVOR]
                        [--public]
                        [--secgroup=SECGROUPs]
                        [--key=KEY]
                        [--dryrun]
                vm boot [--n=COUNT]
                        [--cloud=CLOUD]
                        [--username=USERNAME]
                        [--image=IMAGE]
                        [--flavor=FLAVOR]
                        [--public]
                        [--secgroup=SECGROUPS]
                        [--key=KEY]
                        [--dryrun]
                vm run [--name=VMNAMES] [--username=USERNAME] [--dryrun] COMMAND
                vm script [--name=NAMES] [--username=USERNAME] [--dryrun] SCRIPT
                vm ip assign [NAMES]
                          [--cloud=CLOUD]
                vm ip show [NAMES]
                           [--group=GROUP]
                           [--cloud=CLOUD]
                           [--output=OUTPUT]
                           [--refresh]
                vm ip inventory [NAMES]
                vm ssh [NAMES] [--username=USER]
                         [--quiet]
                         [--ip=IP]
                         [--key=KEY]
                         [--command=COMMAND]
                         [--modify-knownhosts]
                vm rename [OLDNAMES] [NEWNAMES] [--force] [--dryrun]
                vm wait [--cloud=CLOUD] [--interval=SECONDS]
                vm info [--cloud=CLOUD]
                        [--output=OUTPUT]
                vm username USERNAME [NAMES] [--cloud=CLOUD]
                vm resize [NAMES] [--size=SIZE]

            Arguments:
                OUTPUT         the output format
                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 vm 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:
                --output=OUTPUT   the output format [default: table]
                -H --modify-knownhosts  Do not modify ~/.ssh/known_hosts file
                                      when ssh'ing into a machine
                --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, 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 vm 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.

                vm refresh [--cloud=CLOUDS]
                    this command refreshes the data for virtual machines,
                    images and flavors for the specified clouds.

                vm ping [NAMES] [--cloud=CLOUDS] [--count=N] [--processors=PROCESSORS]
                     pings the specified virtual machines, while using at most N pings.
                     The ping is executed in parallel.
                     If names are specifies the ping is restricted to the given names in
                     parameter format. If clouds are specified, names that are not in
                     these clouds are ignored. If the name is set in the variables
                     this name is used.

            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\"

            Limitations:

                Azure: rename is not supported
        """

        map_parameters(arguments, 'active', 'cloud', 'command', 'dryrun',
                       'flavor', 'force', 'output', 'group', 'image',
                       'interval', 'ip', 'key', 'modify-knownhosts', 'n',
                       'name', 'public', 'quiet', 'secgroup', 'size',
                       'username')

        VERBOSE(arguments)

        variables = Variables()

        if arguments.refresh:

            names = []

            clouds, names = Arguments.get_cloud_and_names(
                "refresh", arguments, variables)

            return ""

        elif arguments.ping:

            # TODO: IMPLEMENT
            names = []
            pings = int(arguments.N or 3)

            names = []

            clouds, names = Arguments.get_cloud_and_names(
                "ping", arguments, variables)

            for name in names:

                ping = Shell.live("ping -c {N} {name}".format(name=name,
                                                              N=arguments.N))
                print(ping)
            else:
                return True

            return ""

        elif arguments.check:

            names = []

            clouds, names = Arguments.get_cloud_and_names(
                "check", arguments, variables)

            return ""

        elif arguments.status:

            names = []

            clouds, names = Arguments.get_cloud_and_names(
                "status", arguments, variables)

            return ""

        elif arguments.start:

            names = []

            clouds, names = Arguments.get_cloud_and_names(
                "start", arguments, variables)

            return ""

        elif arguments.stop:

            names = []

            clouds, names = Arguments.get_cloud_and_names(
                "stop", arguments, variables)

            return ""

        elif arguments.terminate:

            names = []

            clouds, names = Arguments.get_cloud_and_names(
                "terminate", arguments, variables)

            return ""

        elif arguments.delete:

            clouds, names = Arguments.get_cloud_and_names(
                "delete", arguments, variables)

            return ""

        elif arguments.boot:

            print("boot the vm")

        elif arguments.list:
            # vm list [NAMES]
            #   [--cloud=CLOUDS]
            #   [--output=OUPTUT]
            #   [--refresh]

            # if no clouds find the clouds of all specified vms by name
            # find all vms of the clouds,
            # print only those vms specified by name, if no name is given print all for the cloud
            # print("list the vms")

            clouds, names = Arguments.get_cloud_and_names(
                "list", arguments, variables)

            # print("Clouds:", clouds)

            if arguments.NAMES is not None:
                names = Parameter.expand(arguments.NAMES)
                Console.error("NAMES, not yet implemented" + str(names))

                try:
                    if arguments["--refresh"]:
                        pass
                        # find all clouds in db
                        # iterate over the clouds
                        # for each name in name queue, find it and add it to the cloud vm list
                        # for each cloud print the vms
                    else:
                        pass
                        # find all clouds in db
                        # iterate over all clouds
                        # find the vm with the name
                        # add it to the cloud list
                        # for each cloud print the vms
                except Exception as e:

                    VERBOSE(e)

                return ""
            else:
                try:
                    if arguments["--refresh"]:
                        for cloud in clouds:
                            Console.ok("refresh " + cloud)

                            p = Provider(cloud)
                            vms = p.list()

                            order = p.p.output['vm']['order']  # not pretty
                            header = p.p.output['vm']['header']  # not pretty

                            print(
                                Printer.flatwrite(vms,
                                                  sort_keys=["cm.name"],
                                                  order=order,
                                                  header=header,
                                                  output=arguments.output))

                    else:
                        for cloud in clouds:
                            p = Provider(cloud)
                            kind = p.kind

                            # pprint(p.__dict__)
                            # pprint(p.p.__dict__) # not pretty

                            collection = "{cloud}-node".format(cloud=cloud,
                                                               kind=p.kind)
                            db = CmDatabase()
                            vms = db.find(collection=collection)

                            # pprint(vms)
                            # print(arguments.output)
                            # print(p.p.output['vm'])

                            order = p.p.output['vm']['order']  # not pretty
                            header = p.p.output['vm']['header']  # not pretty

                            print(
                                Printer.flatwrite(vms,
                                                  sort_keys=["cm.name"],
                                                  order=order,
                                                  header=header,
                                                  output=arguments.output))

                except Exception as e:

                    VERBOSE(e)

            return ""

        elif arguments.info:
            """
            vm info [--cloud=CLOUD] [--output=OUTPUT]
            """
            print("info for the vm")

            cloud, names = Arguments.get_cloud_and_names(
                "info", arguments, variables)

        elif arguments.rename:

            print("rename the vm")

            v = Variables()
            cloud = v["cloud"]

            p = Provider(cloud)

            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",
                                  traceflag=False)
                else:
                    print(oldnames)
                    print(newnames)
                    for i in range(0, len(oldnames)):
                        oldname = oldnames[i]
                        newname = newnames[i]
                        if arguments["--dryrun"]:
                            Console.ok("Rename {} to {}".format(
                                oldname, newname))
                        else:
                            print(f"rename {oldname} -> {newname}")

                            p.rename(source=oldname, destination=newname)

                    msg = "info. OK."
                    Console.ok(msg)
            except Exception as e:
                Error.traceback(e)
                Console.error("Problem renameing instances", traceflag=True)

        elif arguments["ip"] and arguments["show"]:

            print("show the ips")
            """
            vm ip show [NAMES]
                   [--group=GROUP]
                   [--cloud=CLOUD]
                   [--output=OUTPUT]
                   [--refresh]

            """

        elif arguments["ip"] and arguments["assign"]:
            """
            vm ip assign [NAMES] [--cloud=CLOUD]
            """
            print("assign the public ip")

        elif arguments["ip"] and arguments["inventory"]:
            """
            vm ip inventory [NAMES]

            """
            print("list ips that could be assigned")

        elif arguments.username:
            """
            vm username USERNAME [NAMES] [--cloud=CLOUD]
            """
            print("sets the username for the vm")

        elif arguments.default:

            print("sets defaults for the vm")

        elif arguments.run:
            """
            vm run [--name=NAMES] [--username=USERNAME] [--dryrun] COMMAND

            """
            pass
        elif arguments.script:
            """
            vm script [--name=NAMES] [--username=USERNAME] [--dryrun] SCRIPT
            """
            pass

        elif arguments.resize:
            """
            vm resize [NAMES] [--size=SIZE]
            """
            pass

        elif arguments.ssh:
            """
            vm ssh [NAMES] [--username=USER]
                 [--quiet]
                 [--ip=IP]
                 [--key=KEY]
                 [--command=COMMAND]
                 [--modify-knownhosts]
            """
            print("ssh  the vm")

        elif arguments.console:
            # vm console [NAME] [--force]

            names = Arguments.get_names(arguments, variables)

            for name in names:
                # r = vm.console(name,force=argument.force)
                Console.msg("{label} {name}".format(label="console",
                                                    name=name))
            return

        elif arguments.wait:
            """
            vm wait [--cloud=CLOUD] [--interval=SECONDS]
            """
            print("waits for the vm till its ready and one can login")
VERBOSE(variables.dict())

cloud = variables.parameter('cloud')

print(f"Test run for {cloud}")

if cloud is None:
    raise ValueError("cloud is not not set")

name_generator = Name()
name_generator.set(f"benchmark-{user}-vm-" + "{counter}")
# name_generator.reset()

name = str(name_generator)

provider = Provider(name=cloud)


def Print():
    data = provider.list()
    print(provider.Print(data=data, output='table', kind='vm'))


current_vms = 0

repeat = 100


def generate_names(n):
    names = []
    for i in range(0, n):
Example #30
0
    def do_flavor(self, args, arguments):
        """
        ::

            Usage:
                flavor list [NAMES] [--cloud=CLOUD] [--refresh] [--output=OUTPUT] [--query=QUERY]


            Options:
               --output=OUTPUT  the output format [default: table]
               --cloud=CLOUD    the ycloud name
               --refresh        refreshes the data before displaying it

            Description:

                This lists out the flavors present for a cloud

            Examples:
                cm flavor list --refresh
                cm flavor list
                cm flavor list --output=csv
                cm flavor list 58c9552c-8d93-42c0-9dea-5f48d90a3188 --refresh

                please remember that a uuid or the flavor name can be used to
                identify a flavor.


                cms flavor list --refresh --query=\'{\"a\": \"b\"}\'

            OpenStack Query Example:

                cms flavor list --refresh --query=\'{\"minDisk\": \"80\"}\'
                cms flavor list --refresh --query=\'{\"name\": \"m1.large\"}\'

                supported query parameters for OpenStack:

                        min_disk
                        min_ram
                        name


        """

        map_parameters(arguments, "query", "refresh", "cloud", "output")

        variables = Variables()

        arguments.output = Parameter.find("output", arguments, variables,
                                          "table")

        arguments.refresh = Parameter.find_bool("refresh", arguments,
                                                variables)

        if arguments.list and arguments.refresh:

            names = []

            clouds, names = Arguments.get_cloud_and_names(
                "list", arguments, variables)

            for cloud in clouds:
                print(f"cloud {cloud} query={arguments.query}")
                provider = Provider(name=cloud)
                if arguments.query is not None:
                    query = eval(arguments.query)
                    flavors = provider.flavors(**query)
                else:
                    flavors = provider.flavors()

                provider.Print(flavors, output=arguments.output, kind="flavor")

            return ""

        elif arguments.list:

            names = []

            clouds, names = Arguments.get_cloud_and_names(
                "list", arguments, variables)

            try:

                for cloud in clouds:
                    if arguments.output in ["table"]:
                        print(f"List {cloud}")
                    provider = Provider(name=cloud)

                    db = CmDatabase()
                    flavors = db.find(collection=f"{cloud}-flavor")
                    provider.Print(flavors,
                                   output=arguments.output,
                                   kind="flavor")

            except Exception as e:

                VERBOSE(e)

            return ""