Exemplo n.º 1
0
    def do_multipass(self, args, arguments):
        """
        ::

          Usage:
                multipass deploy [--dryrun]
                multipass list [--output=OUTPUT] [--dryrun]
                multipass images [--output=OUTPUT] [--dryrun]
                multipass create NAMES [--image=IMAGE]
                                       [--size=SIZE]
                                       [--mem=MEMORY]
                                       [--cpus=CPUS]
                                       [--cloud-init=FILE]
                                       [--dryrun]
                multipass delete NAMES [--output=OUTPUT][--dryrun]
                multipass destroy NAMES [--output=OUTPUT][--dryrun]
                multipass shell NAMES [--dryrun]
                multipass run COMMAND NAMES [--output=OUTPUT] [--dryrun]
                multipass info NAMES [--output=OUTPUT] [--dryrun]
                multipass suspend NAMES [--output=OUTPUT] [--dryrun]
                multipass resume NAMES [--output=OUTPUT] [--dryrun]
                multipass start NAMES [--output=OUTPUT] [--dryrun]
                multipass stop NAMES [--output=OUTPUT] [--dryrun]
                multipass reboot NAMES [--output=OUTPUT] [--dryrun]
                multipass mount SOURCE DESTINATION [--dryrun]
                multipass umount SOURCE [--dryrun]
                multipass transfer SOURCE DESTINATION [--dryrun]
                multipass set key=VALUE [--dryrun]
                multipass get [key] [--dryrun]
                multipass deploy [--dryrun]
                multipass rename NAMES [--dryrun]
                multipass version

          Interface to multipass

          Options:
               --output=OUTPUT    the output format [default: table]. Other
                                  values are yaml, csv and json.

               --image=IMAGE      the image name to be used to create a VM.

               --cpus=CPUS        Number of CPUs to allocate.
                                  Minimum: 1, default: 1.

               --size=SIZE        Disk space to allocate. Positive integers,
                                  in bytes, or with K, M, G suffix.
                                  Minimum: 512M, default: 5G.

               --mem=MEMORY       Amount of memory to allocate. Positive
                                  integers, in bytes, or with K, M, G suffix.
                                  Minimum: 128M, default: 1G.

               --cloud-init=FILE  Path to a user-data cloud-init configuration

          Arguments:
              NAMES   the names of the virtual machine

          Description:

              The NAMES can be a parameterized hostname such as

                red[0-1,5] = red0,red1,red5

          Commands:

            First you can see the supported multipass images with

                cms multipass images

            Create and launch a new vm using

                cms multipass create NAMES

                Optionally you can provide image name, size, memory,
                number of cpus to create an instance.

            Start one or multiple multipass vms with

                cms multipass start NAMES

            Stop one or multiple vms with

                cms multipass stop NAMES

            Gets all multipass internal key values with

              cms multipass get

            Gets a specific internal key.

              cms multipass get KEY

              Known keys
       
                  client.gui.autostart
                  client.primary-name
                  local.driver

                  are there more?

            Reboot (stop and then start) vms with

                cms multipass reboot NAMES

            Delete one of multiple vms without purging with

                cms multipass delete NAMES

            Destory multipass vms (delete and purge) with

                cms multipass destroy NAMES

                Caution: Once destroyed everything in vm will be deleted
                         and cannot be recovered.

            WHEN YOU IMPLEMENT A FUNCTION INCLUDE MINIMAL
              DOCUMENTATION HERE
        """
        name = arguments.NAME

        map_parameters(arguments, "dryrun", "refresh", "cloud", "image",
                       "size", "mem", "cpus", "cloud-init", "output")
        # so we can use arguments.cloudinit
        arguments["cloudinit"] = arguments["--cloud-init"]

        image = arguments.image
        variables = Variables()

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

        names = Parameter.expand(arguments.NAMES)

        VERBOSE(arguments)

        if arguments.version:

            if arguments.dryrun:
                banner("dryrun list")
            else:
                provider = Provider()
                version = provider.version()
                del version["name"]

                print(Printer.attribute(version, header=["Program",
                                                         "Version"]))

            return ""

        elif arguments.list:

            if arguments.dryrun:
                banner("dryrun list")
            else:
                provider = Provider()
                list = provider.list()

                print(
                    provider.Print(list, kind='image',
                                   output=arguments.output))

            return ""

        elif arguments.images:

            if arguments.dryrun:
                banner("dryrun images")
            else:

                provider = Provider()
                images = provider.images()

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

            return ""

        elif arguments.run:

            if arguments.dryrun:
                banner("dryrun run")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"run {name} {arguments.COMMAND}")
                else:

                    provider = Provider()
                    provider.run(name, arguments.COMMAND)

            return ""

        elif arguments.create:

            result = ""

            if arguments.dryrun:
                banner("create")

            timeout = 360
            group = None
            kwargs = {
                "cloud_init": arguments.cloud_init,
                "cpus": arguments.cpus,
                "memory": arguments.mem
            }

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun create {name} {image}")
                else:
                    provider = Provider()
                    result = provider.create(name, image, arguments.size,
                                             timeout, group, **kwargs)
                    VERBOSE(result)

            return result

        elif arguments.start:

            result = ""

            if arguments.dryrun:
                banner("start")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun start {name}")
                else:
                    provider = Provider()
                    result = provider.start(name)
                    VERBOSE(result)

            return result

        elif arguments.stop:

            result = ""

            if arguments.dryrun:
                banner("stop")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun stop {name}")
                else:
                    provider = Provider(name=name)
                    result = provider.stop(name)
                    VERBOSE(result)

            return result

        elif arguments.delete:

            result = ""

            if arguments.dryrun:
                banner("delete")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun delete {name}")
                else:
                    provider = Provider()
                    # Default purge is false. Is this ok?
                    result = provider.delete(name)
                    VERBOSE(result)

            return result

        elif arguments.info:

            result = ""

            if arguments.dryrun:
                banner(f"info {name}")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun info {name}")
                else:
                    provider = Provider()
                    # Default purge is false. Is this ok?
                    result = provider.info(name)
                    VERBOSE(result)

            return result

        elif arguments.rename:

            result = ""

            if arguments.dryrun:
                banner(f"Current Name: {names[0]}" f"New Name: {names[1]}")

            if names.len() > 2:
                Console.error("You have entered too many names."
                              "Only enter TWO names at a time.")
            else:
                old_name = names[0]
                new_name = names[1]

                provider = Provider()
                result = provider.rename(old_name, new_name)
                VERBOSE(result)

            return result

        elif arguments.suspend:

            result = ""

            if arguments.dryrun:
                banner("suspend")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun suspend {name}")
                else:
                    provider = Provider()
                    result = provider.suspend(name)
                    VERBOSE(result)

            return result

        elif arguments.resume:

            result = ""

            if arguments.dryrun:
                banner("resume")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun resume {name}")
                else:
                    provider = Provider()
                    result = provider.resume(name)
                    VERBOSE(result)

            return result

        elif arguments.destroy:

            result = ""

            if arguments.dryrun:
                banner("destroy")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun destroy {name}")
                else:
                    provider = Provider()
                    result = provider.destroy(name)
                    VERBOSE(result)

            return result

        elif arguments.reboot:

            result = ""

            if arguments.dryrun:
                banner("reboot")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun reboot {name}")
                else:
                    provider = Provider()
                    result = provider.reboot(name)
                    VERBOSE(result)

            return result

        elif arguments.shell:

            if len(names) > 1:
                Console.error("shell must only have one host")
                return ""

            name = names[0]

            if arguments.dryrun:
                banner("dryrun shell {name}")
            else:
                provider = Provider()
                provider.shell()

            return ""

        elif arguments.info:

            if arguments.dryrun:
                banner("dryrun info")
            else:
                provider = Provider()
                info = provider.info()
                print(
                    provider.Print(info, kind='info', output=arguments.output))

            return ""

        elif arguments.mount:

            if arguments.dryrun:
                banner(
                    f"dryrun mount {arguments.SOURCE} {arguments.DESTINATION}")
            else:
                provider = Provider()
                provider.mount(arguments.SOURCE, arguments.DESTINATION)

                # list the mounts and display as table

            return ""

        elif arguments.deploy:
            provider = Deploy(dryrun=arguments.dryrun)
            provider.install()

        else:
            Console.error("Not yet implemented")
        return ""
Exemplo n.º 2
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 ""
Exemplo n.º 3
0
    def do_volume(self, args, arguments):
        """
        ::

          Usage:
            volume list [NAMES]
                        [--vm=VM]
                        [--region=REGION]
                        [--cloud=CLOUD]
                        [--refresh]
                        [--dryrun]
                        [--output=FORMAT]
            volume create [NAME]
                        [--size=SIZE]
                        [--volume_type=TYPE]
                        [--description=DESCRIPTION]
                        [--dryrun]
                        [--region=REGION]
                        [--path=PATH]
            volume attach [NAMES] [--vm=VM]
            volume detach [NAMES]
            volume delete [NAMES]
            volume add_tag [NAME]
                        [--key=KEY]
                        [--value=VALUE]
            volume status [NAME]
            volume migrate [NAME]
                        [--vm=VM]
                        [--cloud=CLOUD]
            volume sync [NAMES]
                        [--cloud=CLOUD]
            volume purge [--cloud=CLOUD]

          This command manages volumes across different clouds

          Arguments:
              NAME   the name of the volume
              NAMES  the names of multiple volumes

          Options:
              --vm=VM              The name of the virtual machine
              --region=REGION      The name of the region
              --cloud=CLOUD        The name of the cloud
              --refresh            If refresh the info is taken from the cloud
              --volume_type=TYPE   The type of the volume
              --output=FORMAT      Output format [default: table]
              --key=KEY            The tag key
              --value=VALUE        The value of tag key
              --snapshot           The snapshot of volume
              --path=PATH          The path of local volume

          Description:

            volume list [NAMES]
                        [--vm=VM]
                        [--region=REGION]
                        [--cloud=CLOUD]
                        [--refresh]
                        [--dryrun]
                        [--output=FORMAT]
                List all the volumes for certain vm, region, or cloud.

            volume create [NAME]
                          [--size=SIZE]
                          [--volume_type=TYPE]
                          [--description=DESCRIPTION]
                          [--dryrun]
                          [--snapshot=SNAPSHOT]
                          [--region=REGION]
                Creates a volume

            volume status [NAMES]
                          [--cloud=CLOUD]
                Get the status (e.g. 'available', 'READY', 'in-use') of a volume

            volume attach [NAMES]
                          [--vm=VM]
                Attach volume to a vm

            volume detach [NAMES]
                Detach volume from a vm

            volume delete [NAMES]
                Delete the named volumes

            volume migrate [NAME]
                           [--vm=VM]
                           [--cloud=CLOUD]
                 Migrate volume from one vm to another vm in the same provider.

            volume sync [NAMES]
                        [--cloud=CLOUD]
                Volume sync allows for data to be shared between two volumes.

            volume purge [--cloud=CLOUD]
                Volume purge delete all the "deleted" volumes in MongoDB
                database

        """

        VERBOSE(arguments)
        variables = Variables()

        def get_last_volume():
            """
            get the last volume name

            :return: string
            """
            config = Config()

            n = VolumeName(user=config["cloudmesh.profile.user"],
                           kind="volume",
                           path=f"{config.location}/volume.yaml",
                           schema="{user}-volume-{counter}")
            last_volume_name = n

            return str(last_volume_name)

        def create_name():
            """
            Create volume name if name is not specified

            :return: string
            """

            config = Config()

            n = VolumeName(user=config["cloudmesh.profile.user"],
                           kind="volume",
                           path=f"{config.location}/volume.yaml",
                           schema="{user}-volume-{counter}")
            n.incr()
            return n

        map_parameters(arguments, "cloud", "vm", "region", "refresh", "dryrun",
                       "output", "size", "volume_type", "description", "key",
                       "value", "snapshot", "path")

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

        cloud = variables['cloud']

        if arguments.list:
            if arguments.NAMES:
                names = Parameter.expand(arguments["NAMES"])
                if arguments.cloud:
                    # "cms volume list NAMES --cloud=aws1"
                    provider = Provider(name=arguments.cloud)

                    result = provider.list(**arguments)
                    print(
                        provider.Print(result,
                                       kind='volume',
                                       output=arguments.output))
                else:
                    # if "cms volume list NAMES"
                    config = Config()
                    clouds = list(config["cloudmesh.volume"].keys())
                    for cloud in clouds:
                        if len(names) != 0:
                            banner(f"listing volume info from {cloud}")
                        else:
                            banner("End of listing Volumes")
                            break
                        active = config[f"cloudmesh.volume.{cloud}.cm.active"]
                        if active:
                            provider = Provider(name=cloud)
                            listed = []
                            for name in names:
                                volume = provider.search(name=name)
                                if volume:
                                    arguments.NAME = name
                                    result = provider.list(**arguments)
                                    print(
                                        provider.Print(
                                            result,
                                            kind='volume',
                                            output=arguments.output))
                                    listed.append(name)
                            if len(listed) > 0:
                                # delete all listed volumes in names
                                for name in listed:
                                    names.remove(name)

            else:
                if arguments.cloud:
                    # "cms volume list --cloud=aws1"
                    provider = Provider(name=arguments.cloud)

                    result = provider.list(**arguments)
                    print(
                        provider.Print(result,
                                       kind='volume',
                                       output=arguments.output))
                else:
                    # "cms volume list"
                    arguments['cloud'] = cloud
                    provider = Provider(name=arguments.cloud)

                    result = provider.list(**arguments)
                    print(
                        provider.Print(result,
                                       kind='volume',
                                       output=arguments.output))

            return ""

        elif arguments.create:
            if arguments.cloud is None:
                arguments['cloud'] = cloud
            if arguments.NAME is None:
                arguments.NAME = str(create_name())
            provider = Provider(name=arguments.cloud)
            result = provider.create(**arguments)
            print(
                provider.Print(result, kind='volume', output=arguments.output))

        elif arguments.delete:
            names = arguments.NAMES or variables["volume"]
            names = Parameter.expand(names)
            if names is None:
                Console.error("No volume specified or found")
                return ""
            config = Config()
            clouds = list(config["cloudmesh.volume"].keys())
            for cloud in clouds:
                # if len(names) != 0:
                #     banner(f"Deleting volumes from {cloud}")
                # else:
                #     banner("End of Deleting Volumes")
                active = config[f"cloudmesh.volume.{cloud}.cm.active"]
                if active:
                    provider = Provider(name=cloud)
                    deleted = []
                    for name in names:
                        volume = provider.search(name=name)
                        if volume:
                            result = provider.delete(name=name)
                            deleted.append(name)
                    if len(deleted) > 0:
                        # delete all deleted volumes in names
                        for name in deleted:
                            names.remove(name)

        elif arguments.attach:
            arguments.cloud = arguments.cloud or cloud
            names = arguments.NAMES or variables["volume"]
            vm = arguments.vm or variables["vm"]
            if names is None:
                Console.error("No Volume specified or found")
                return ""
            if vm is None:
                Console.error("No vm specified or found")
                return ""
            names = Parameter.expand(names)
            # banner(f"Attaching {names} to {arguments.vm}")
            provider = Provider(name=arguments.cloud)
            result = provider.attach(names, vm)
            print(
                provider.Print(result, kind='volume', output=arguments.output))

        elif arguments.detach:
            config = Config()
            clouds = list(config["cloudmesh.volume"].keys())
            volumes = arguments.NAMES or variables["volume"]
            if volumes is None:
                Console.error("No volume specified or found")
                return ""
            volumes = Parameter.expand(volumes)
            for cloud in clouds:
                # if len(volumes) != 0:
                #     banner(f"Detaching volumes from {cloud}")
                # else:
                #     banner("End of Detaching Volumes")
                #     break
                active = config[f"cloudmesh.volume.{cloud}.cm.active"]
                if active:
                    detached = []
                    provider = Provider(name=cloud)
                    for name in volumes:
                        # returns volume name if found in the cloud,
                        # None if it is not in the cloud
                        volume = provider.search(name=name)
                        if volume:
                            # banner(f"Detaching {name} from {cloud}")
                            result = provider.detach(name=name)
                            detached.append(name)
                            print(
                                provider.Print(result,
                                               kind='volume',
                                               output=arguments.output))
                    if len(detached) > 0:
                        # delete all detached volumes in volumes
                        for name in detached:
                            volumes.remove(name)

        elif arguments.add_tag:
            arguments.cloud = arguments.cloud or cloud
            name = arguments.NAME or variables["volume"] or get_last_volume()
            arguments.NAME = name
            provider = Provider(name=arguments.cloud)
            result = provider.add_tag(**arguments)
            print(
                provider.Print(result, kind='volume', output=arguments.output))

        elif arguments.status:
            arguments.cloud = arguments.cloud or cloud
            name = arguments.NAME or variables["volume"] or get_last_volume()
            arguments.NAME = name
            provider = Provider(name=arguments.cloud)
            result = provider.status(name=name)
            print(
                provider.Print(result, kind='volume', output=arguments.output))

        elif arguments.migrate:
            if arguments.cloud:
                # "cms volume migrate NAME --vm=VM --cloud=aws1"
                # if no given volume, get the current volume
                # or get the last volume,
                name = arguments.NAME or variables[
                    "volume"] or get_last_volume()
                arguments.NAME = name
                provider = Provider(name=arguments.cloud)
                result = provider.migrate(**arguments)
                print(
                    provider.Print(result,
                                   kind='volume',
                                   output=arguments.output))
            else:
                raise NotImplementedError

        elif arguments.sync:
            # "cms volume sync NAMES --cloud=CLOUD"
            # when len(NAMES)==2, sync volume (NAMES[0]) with volume (NAMES[1])
            # when len(NAMES)==1, sync current volume with volume(NAMES[0])
            # what it actually does is copy second volume and overwrite
            # the other (current volume or first volume in NAMES)

            if len([arguments.NAMES]) == 1:
                volumes = [
                    variables["volume"] or get_last_volume(), arguments.NAMES
                ]
                arguments.NAMES = volumes
            elif len([arguments.NAMES]) == 2:
                volumes = arguments.NAMES
            else:
                Console.error("Two volumes should be specified")
            # if arguments.cloud:
            arguments.cloud = cloud
            provider = Provider(name=arguments.cloud)
            result = provider.sync(**arguments)
            print(
                provider.Print(result, kind='volume', output=arguments.output))
            # else:
            #     raise NotImplementedError

        elif arguments.purge:
            arguments.cloud = arguments.cloud or cloud
            provider = Provider(name=arguments.cloud)
            provider.purge(**arguments)
            result = provider.list()
            print(
                provider.Print(result, kind='volume', output=arguments.output))
Exemplo n.º 4
0
    def do_check(self, args, arguments):
        """
        ::

            Usage:
                check [KEYWORDS...] [--output=OUTPUT]


            Options:
               --output=OUTPUT  the output format [default: table]

            Description:

                checks if some programs are available to cms in the system. This
                includes

                    mongodb
                    ssh

                These can also be passed as optional keywords

        """

        map_parameters(arguments, "output")

        variables = Variables()

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

        keywords = arguments.KEYWORDS or ['mongo', "mongod", "mongoimport"]

        def check_ssh():
            cmd = "ssh " \
                  "-o StrictHostKeyChecking=no " \
                  "-o UserKnownHostsFile=/dev/null " \
                  f"-v localhost date"
            r = Shell.run(cmd)
            return "Connection refused" not in r

        def get_info(shell_command):
            v = "unkown"
            path = Shell.which(shell_command)
            if shell_command == "ssh":
                v = Shell.run(f"{shell_command} -V")
            elif path and len(path) > 0:
                try:
                    v = Shell.run(f"{shell_command} --version")
                    if shell_command.endswith("mongo"):
                        v = v.splitlines()[0].replace("MongoDB shell version ",
                                                      "")
                    elif shell_command.endswith("mongod"):
                        v = v.splitlines()[0].replace("db version ", "")
                    elif shell_command.endswith("mongoimport"):
                        v = v.splitlines()[0].replace("mongoimport version: ",
                                                      "")

                except:
                    v = "unkown"
            return path, v

        config = Config()
        try:
            machine = sys.platform
            mongo_path = config[
                f"cloudmesh.data.mongo.MONGO_DOWNLOAD.{machine}.MONGO_HOME"]
        except:
            mongo_path = None
        data = {}

        for keyword in keywords:

            #
            # probe system mongo
            #
            path, version_string = get_info(keyword)

            entry = {
                'system': {
                    'name': keyword,
                    'path': path,
                    'version': version_string
                }
            }

            data[keyword] = entry

            #
            # probe cloudmesh mongo
            #

            if "mongo" in ['mongo', 'mongod', 'mongoimport']:
                if mongo_path:

                    path = str(Path(path_expand(mongo_path)) / "bin" / keyword)

                    p, v = get_info(path)

                    try:

                        entry = {
                            'cloudmesh': {
                                'name': keyword,
                                'path': path,
                                'version': v
                            }
                        }

                    except:
                        Console.error(f"{keyword}")

                data[keyword].update(entry)

        path, v = get_info('ssh')
        data['ssh'] = {
            'system': {
                'name': 'ssh',
                'path': path,
                'version': v.strip(),
                'enabled': check_ssh()
            }
        }

        #
        # probe ssh commands
        #
        for c in ["ssh-keygen", "ssh-add", "ssh-agent"]:
            data[c] = {
                'system': {
                    'name': c,
                    'path': Shell.which(c),
                }
            }

        if len(data) > 0:
            banner("ssh, mongo, mongod, mongoimport")
            print(json.dumps(data, indent=2))

        banner("os.environ")
        for attribute in os.environ:
            print(attribute, os.environ[attribute])

        banner("Shell.run")

        for c in ["echo $0", "echo $SHELL"]:
            try:
                r = Shell.run(c).strip()
            except:
                r = 'error'
            print(f"Shell.run('{c}')", r)

        return ""
Exemplo n.º 5
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 ""
Exemplo n.º 6
0
    def do_ssh(self, args, arguments):
        """
        ::

            Usage:
                ssh config list [--output=OUTPUT]
                ssh config add NAME IP [USER] [KEY]
                ssh config delete NAME

            Arguments:
              NAME        Name or ip of the machine to log in
              list        Lists the machines that are registered and
                          the commands to login to them
              PARAMETERS  Register te resource and add the given
                          parameters to the ssh config file.  if the
                          resource exists, it will be overwritten. The
                          information will be written in /.ssh/config
              USER        The username for the ssh resource
              KEY         The location of the public keye used for
                          authentication to the host

            Options:
               --output=OUTPUT   the format in which this list is given
                                 formats includes cat, table, json, yaml,
                                 dict. If cat is used, it is just printed as
                                 is. [default: table]

            Description:
                ssh config list
                    lists the hostsnames that are present in the ~/.ssh/config file

                ssh config add NAME IP [USER] [KEY]
                    registers a host i ~/.ssh/config file
                    Parameters are attribute=value pairs

                ssh config delete NAME
                    deletes the named host from the ssh config file

            Examples:

                 ssh config add blue 192.168.1.245 gregor

                     Adds the following to the !/.ssh/config file

                     Host blue
                          HostName 192.168.1.245
                          User gergor
                          IdentityFile ~/.ssh/id_rsa.pub

        """

        map_parameters(arguments, "output")

        if arguments.config and arguments.list:
            # ssh config list [--output=OUTPUT]"

            hosts = dict(ssh_config().hosts)

            # Make keywords uniform
            for host in hosts:

                if "HostName" in hosts[host]:
                    hosts[host]["Hostname"] = hosts[host]["HostName"]
                    del hosts[host]["HostName"]
                if "Identityfile" in hosts[host]:
                    hosts[host]["IdentityFile"] = hosts[host]["Identityfile"]
                    del hosts[host]["Identityfile"]

            print(Printer.write(hosts,
                                order=['host', 'Hostname', 'User', 'IdentityFile']))

        elif arguments.config and arguments.add:
            # ssh config add NAME IP [USER] [KEY]

            variables = Variables()

            user = Parameter.find("user",
                                  arguments,
                                  variables.dict())

            key = Parameter.find("key",
                                 arguments,
                                 variables.dict(),
                                 {"key": "~/.ssh/id_rsa.pub"})

            name = arguments.NAME or variables['vm']

            ip = arguments.IP

            hosts = ssh_config()

            if name in hosts.hosts:
                Console.error("Host already in ~/.ssh/config")
                return ""

            hosts.generate(host=name, hostname=ip, identity=key, user=user)

        elif arguments.config and arguments.add:
            # ssh host add NAME

            location = path_expand("~/.ssh/known_hosts")
            name = arguments.NAME
            os.system("ssh-keygen -R {name}")
            os.system(f"ssh-keyscan -H {name} >> {location}")

        elif arguments.config and arguments.delete:
            # ssh host delete NAME

            name = arguments.NAME
            try:
                os.system("ssh-keygen -R {name}")
            except:
                pass
            ssh_config.delete(name)
Exemplo n.º 7
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 ""
Exemplo n.º 8
0
    def do_volume(self, args, arguments):
        """
        ::

          Usage:
            volume register which
            volume register [NAME] [--cloud=CLOUD] [ARGUMENTS...]
            volume list [NAMES]
                        [--vm=VM]
                        [--region=REGION]
                        [--cloud=CLOUD]
                        [--refresh]
                        [--dryrun]
                        [--output=FORMAT]
            volume create [NAME]
                      [--size=SIZE]
                      [--volume_type=TYPE]
                      [--description=DESCRIPTION]
                      [--dryrun]
                      [ARGUMENTS...]
            volume status [NAMES]
                      [--cloud=CLOUD]
            volume attach [NAMES] [--vm=VM]
            volume detach [NAMES]
            volume delete NAMES
            volume migrate NAME FROM_VM TO_VM
            volume sync FROM_VOLUME TO_VOLUME

          This command manages volumes accross different clouds

          Arguments:
              NAME   the name of the volume
              vm     the name of the vm

          Options:
              --vm=VMNAME        The name of the virtual machine
              --region=REGION    The name of the region
              --cloud=CLOUD      The name of the cloud
              --refresh          If refresh the information is taken from the cloud
              --volume_type=TYPE  The type of the volume
              --output=FORMAT    Output format [default: table]

          Description:

             TBD
        """

        VERBOSE(arguments)
        variables = Variables()

        def get_last_volume():
            cm = CmDatabase()
            cloud = arguments['--cloud'] or variables["cloud"]
            #how to get updated cloud names? or only search the last volume in --cloud?
            last_entry = cm.find(cloud=cloud, kind='volume')[-1]
            cm.close_client()
            for tag in last_entry['Tags']:
                if tag['key'] == 'Name':
                    name = tag['Value']
                else:
                    raise ("Please name the volume!")
            return name

        def create_name():
            """
            Gregor suggests to use

            from cloudmesh.management.configuration.Name import Name as VolumeName

            config = Config()

            n = VolumeName(
                    user=config["cloudmesh.profile.username"],
                    kind="volume",
                    path=f"{config.location}/volume.yaml",
                    schema="{user}-volume-{counter}"
                    counter=1)
            n.incr()
            counter = n.get()

            :return:
            """

            # please edit ~ /.cloudmesh / volume.yaml as following:
            # counter: 1
            # kind: volume

            config = Config()
            directory = f"{config.location}"
            volume_yaml = path_expand(f"{directory}/volume.yaml")

            try:
                with open(volume_yaml) as file:
                    dic = yaml.load(file, Loader=yaml.FullLoader)
                counter = dic["counter"]
                user = dic["user"]
                created_name = f"{user}-{cloud}-{counter}"
                dic["counter"] += 1
                with open(volume_yaml, 'w') as file:
                    documents = yaml.dump(dic, file)
            except:
                Console.error("the volume.yaml file does not exist."
                              "You need to implement "
                              "the case so it gets autogenerated")
                raise NotImplementedError

            return created_name

        map_parameters(
            arguments,
            "cloud",
            "vm",
            "region",
            "refresh",
            "dryrun",
            "output",
            "size",
            "volume_type",
            "description",
        )

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

        arguments.NAME = arguments.NAME or variables[
            "volume"]  #or get_last_volume()
        #path = arguments.PATH
        cloud = variables['cloud']

        if arguments.list:
            if arguments.NAMES:
                raise NotImplementedError
                names = Parameter.expand(arguments.NAMES)

                for name in names:
                    # kind = cm.kind
                    provider = Provider(name=name)
                    # result = provider.list(???)
                    result = provider.list()
            elif arguments.cloud:
                # banner(f'get in arguments.cloud {arguments.cloud}')
                #print (arguments.cloud)
                provider = Provider(name=arguments.cloud)

                result = provider.list(**arguments)
                print(
                    provider.Print(result,
                                   kind='volume',
                                   output=arguments.output))

                #from pprint import pprint
                #pprint (result)
            return ""

        elif arguments.create:
            #parameters = Parameter.arguments_to_dict(arguments.ARGUMENTS)
            #print("parameters",parameters)

            if arguments.cloud == None:
                arguments['cloud'] = cloud  #cloud from variable['volume']
            if arguments.NAME == None:
                arguments.NAME = str(create_name())
            provider = Provider(name=arguments.cloud)
            result = provider.create(**arguments)
            print(
                provider.Print(result, kind='volume', output=arguments.output))

        elif arguments.delete:
            names = Parameter.expand(arguments["NAMES"])

            config = Config()
            clouds = list(config["cloudmesh.volume"].keys())
            for cloud in clouds:
                active = config[f"cloudmesh.volume.{cloud}.cm.active"]
                if active:
                    p = Provider(name=cloud)
                    deleted = []
                    for name in names:
                        result = p.delete(
                            name)  # returns None if it is not in the cloud
                        if result:
                            deleted.append(name)
                        if len(deleted) > 0:
                            for name in deleted:
                                del names[name]
            """
            2 spaces not fout !

            cloudmesh:
                volume:
                    aws1:                    
                        cm:
                            active: cloudmesh.cloud.aws.cm.active

            names = Parametrs.expnad(arguments.NAMES)



            config = Config()
            clouds = list(config["cloudmesh.volume"].keys())

            for cloud in clouds : 
                active = config[f"cloudmesh.volume.{cloud}.cm.active"]

                if active:
                    found = []
                    # from cloudmesh.volume.Provider import Provider
                    p = Provider(name=cloud)
                    for name in names:
                        volume = p.list(name=name)
                            found = found.append(name)
                    p.destroy(','.join(found)
                    # delete all found volumes in the cloud
            """

        elif arguments.attach:

            # cloud from variable['volume']
            arguments.cloud = arguments.cloud or cloud

            names = arguments.NAMES or variables["volume"]
            vm = arguments.vm or variables["vm"]

            if names is None:
                Console.error("No Volume specified or found")
                return ""

            if vm is None:
                Console.error("No vm specified or found")
                return ""

            names = Parameter.expand(names)

            banner(f"Attach {arguments.NAMES} to {arguments.vm}")
            provider = Provider(name=arguments.cloud)
            for name in names:
                result = provider.attach(name, vm)
                print(
                    provider.Print(result,
                                   kind='volume',
                                   output=arguments.output))

        elif arguments.detach:
            #
            # this has a bug as the general provider needs a serach that finds
            # the vm given a volume name to find the vm it is attached to
            # this way you can write just a loop such as
            #
            # for volume in volumes:
            #    v = provider.serach(volume)
            #    if v['vm'] and v['cm.cloud'] == v['cm.cloud']:
            #        result = provider.detach(name)
            #
            # or something similar dependent on how you defined the datastructure
            # cm. for a volume
            #

            volumes = arguments.NAMES or variables["volume"]
            if volumes is None:
                Console.error("No volumes specified or found")
                return ""

            volumes = Parameter.expand(volumes)

            banner(f"Detach {volumes}")

            for name in volumes:
                volume = Provider.search(name=name)
                cloud = volume["cm"]["cloud"]
                provider = Provider(name=cloud)
                result = provider.detach(name=name)

                print(
                    provider.Print(result,
                                   kind='volume',
                                   output=arguments.output))
Exemplo n.º 9
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 ""
Exemplo n.º 10
0
    def do_multipass(self, args, arguments):
        """
        ::

          Usage:
                multipass list [--output=OUTPUT] [--dryrun]
                multipass images [--output=OUTPUT] [--dryrun]
                multipass start NAMES [--output=OUTPUT] [--dryrun]
                multipass stop NAMES [--output=OUTPUT] [--dryrun]
                multipass reboot NAMES [--output=OUTPUT] [--dryrun]
                multipass delete NAMES [--output=OUTPUT][--dryrun]
                multipass destroy NAMES [--output=OUTPUT][--dryrun]
                multipass shell NAMES [--dryrun]
                multipass run COMMAND NAMES [--output=OUTPUT] [--dryrun]
                multipass info NAMES [--output=OUTPUT] [--dryrun]
                multipass suspend NAMES [--output=OUTPUT] [--dryrun]
                multipass resume NAMES [--output=OUTPUT] [--dryrun]
                multipass destroy NAMES [--dryrun]
                multipass create NAMES [--image=IMAGE]
                                       [--size=SIZE]
                                       [--mem=MEMORY]
                                       [--cpus=CPUS]
                                       [--cloud-init=CLOUDINIT]
                                       [--dryrun]
                multipass reboot NAMES [--dryrun]
                multipass mount SOURCE DESTINATION [--dryrun]
                multipass umount SOURCE [--dryrun]
                multipass transfer SOURCE DESTINATION [--dryrun]
                multipass set key=VALUE [--dryrun]
                multipass get [key] [--dryrun]

          Interface to multipass

          Options:
               --output=OUTPUT  the output format [default: table]. Other values are yaml, csv and json.

               --image=IMAGE    the image name to be used to create a VM.

          Arguments:
              NAMES   the names of the virtual machine

          Description:

              The NAMES can be a parameterized hostname such as

                red[0-1,5] = red0,red1,red5

          Commands:

            First you can see the supported multipass images with

                cms multipass images

            Create and launch a new vm using

                cms multipass create NAMES

                Optionally you can provide image name, size, memory, # of cpus to create an instance.

            Start one or multiple multipass vms with

                cms multipass start NAMES

            Stop one or multiple vms with

                cms multipass stop NAMES

            Gets all multipass internal key values with

              cms multipass get

            Gets a specific internal key.

              cms multipass get KEY

              Known keys
       
                  client.gui.autostart
                  client.primary-name
                  local.driver

                  are there more?

            Reboot (stop and then start) vms with

                cms multipass reboot NAMES

            Delete one of multiple vms without purging with

                cms multipass delete NAMES

            Destory multipass vms (delete and purge) with

                cms multipass destroy NAMES

                Caution: Once destroyed everything in vm will be deleted and cannot be recovered.

            WHEN YOU IMPLEMENT A FUNCTION INCLUDE MINIMAL
              DOCUMENTATION HERE
        """
        name = arguments.NAME

        map_parameters(arguments, "dryrun", "refresh", "cloud", "image",
                       "size", "mem", "cpus", "output")
        # so we can use arguments.cloudinit
        arguments["cloudinit"] = arguments["--cloud-init"]

        image = arguments.image
        variables = Variables()

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

        names = Parameter.expand(arguments.NAMES)

        VERBOSE(arguments)

        if arguments.list:

            if arguments.dryrun:
                banner("dryrun list")
            else:
                provider = Provider()
                provider.list()

            return ""

        elif arguments.images:

            if arguments.dryrun:
                banner("dryrun images")
            else:

                provider = Provider()
                images = provider.images()

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

            return ""

        elif arguments.run:

            if arguments.dryrun:
                banner("dryrun run")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"run {name} {arguments.COMMAND}")
                else:

                    provider = Provider()
                    provider.run(name, arguments.COMMAND)

            return ""

        elif arguments.create:

            result = ""

            if arguments.dryrun:
                banner("create")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun create {name} {image}")
                else:
                    provider = Provider()
                    result = provider.create(name, image)
                    VERBOSE(result)

            return result

        elif arguments.start:

            result = ""

            if arguments.dryrun:
                banner("start")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun start {name}")
                else:
                    provider = Provider()
                    result = provider.start(name)
                    VERBOSE(result)

            return result

        elif arguments.stop:

            result = ""

            if arguments.dryrun:
                banner("stop")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun stop {name}")
                else:
                    provider = Provider(name=name)
                    result = provider.stop(name)
                    VERBOSE(result)

            return result

        elif arguments.delete:

            result = ""

            if arguments.dryrun:
                banner("delete")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun delete {name}")
                else:
                    provider = Provider()
                    # Default purge is false. Is this ok?
                    result = provider.delete(name)
                    VERBOSE(result)

            return result

        elif arguments.info:

            result = ""

            if arguments.dryrun:
                banner(f"info {name}")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun info {name}")
                else:
                    provider = Provider()
                    # Default purge is false. Is this ok?
                    result = provider.info(name)
                    VERBOSE(result)

            return result

        elif arguments.suspend:

            result = ""

            if arguments.dryrun:
                banner("suspend")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun suspend {name}")
                else:
                    provider = Provider()
                    result = provider.suspend(name)
                    VERBOSE(result)

            return result

        elif arguments.resume:

            result = ""

            if arguments.dryrun:
                banner("resume")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun resume {name}")
                else:
                    provider = Provider()
                    result = provider.resume(name)
                    VERBOSE(result)

            return result

        elif arguments.destroy:

            result = ""

            if arguments.dryrun:
                banner("destroy")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun destroy {name}")
                else:
                    provider = Provider()
                    result = provider.destroy(name)
                    VERBOSE(result)

            return result

        elif arguments.reboot:

            result = ""

            if arguments.dryrun:
                banner("reboot")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun reboot {name}")
                else:
                    provider = Provider()
                    result = provider.reboot(name)
                    VERBOSE(result)

            return result

        elif arguments.shell:

            if len(names) > 1:
                Console.error("shell must only have one host")
                return ""

            name = names[0]

            if arguments.dryrun:
                banner("dryrun shell {name}")
            else:
                provider = Provider()
                provider.shell()

            return ""

        elif arguments.info:

            if arguments.dryrun:
                banner("dryrun info")
            else:
                provider = Provider()
                info = provider.info()
                print(
                    provider.Print(info, kind='info', output=arguments.output))

            return ""

        elif arguments.mount:

            if arguments.dryrun:
                banner(
                    f"dryrun mount {arguments.SOURCE} {arguments.DESTINATION}")
            else:
                provider = Provider()
                provider.mount(arguments.SOURCE, arguments.DESTINATION)

                # list the mounts and display as table

            return ""

        else:
            Console.error("Not yet implemented")
        return ""
Exemplo n.º 11
0
    def do_iu(self, args, arguments):
        """
        ::

          Usage:
                iu [--user=USERNAME] [--host=HOST] [--node=NUMBER] [--gpu=GPUS]
                   [--res=RESERVATION]
                iu status
                iu res
                iu setup --user=USERNAME

          This command allows you to inteactively log into roeo or volta

          Arguments:
              FILE    a file name
              HOST    the host is either rome or volta [default: romeo]
              NUMBER  is a number that specifies where to login
              GPUS    the number of GPU's to be used

          Options:
              --res=RESERVATION  [default: lijguo_11]

          Example:

              cms iu
                 logs in on the first available node, and uses 1 GPU
                 BUG: some reservation are not detected

              cms iu --node=random
                 logs in on the first available node and uses 1 GPU

              cms iu status
                 lists the status of rome and volta. The output will look like:


                    +-------------+-----------+
                    | romeo       | Used GPUs |
                    +-------------+-----------+
                    | r-001       |           |
                    | r-002       | 7         |
                    | r-003       | 7         |
                    | r-004       | 7         |
                    +-------------+-----------+

                    +-------+-----------+
                    | volta | Used GPUs |
                    +-------+-----------+
                    | r-005 | 5         |
                    | r-006 | 7         |
                    +-------+-----------+

                    Users on romeo

                        user1

                    Users on volta

                        user2
        """
        VERBOSE(arguments)
        map_parameters(arguments,
                       "user",
                       "host",
                       "node",
                       "gpu")

        variables = Variables()
        #arguments["user"] = Parameter.find("user", arguments, variables)
        # if arguments.user is None:
        #    config = Config()
        #    arguments.user = config["cloudmesh.iu.user"]

        iu = Manager(user=arguments.user)

        if arguments.setup:

            iu.setup(user=arguments.user)

            return ""

        if arguments.status:

            iu.status(user=arguments.user)

            return ""

        elif arguments.res:

            iu.reservations(user=arguments.user)

            return ""

        else:

            arguments["host"] = Parameter.find("host", arguments, variables,
                                               {"host": "romeo"})
            arguments["node"] = Parameter.find("node", arguments, variables)
            arguments["gpu"] = int(Parameter.find("gpu", arguments, variables,
                                                  {"gpu": "1"}))

            # VERBOSE(arguments)

            banner(f"Login {arguments.host}")

            #iu.login(user=arguments.user,
            #               host=arguments.host,
            #               node=arguments.node,
            #               gpus=arguments.gpu)

            iu.smart_login(user=arguments.user,
                           host=arguments.host,
                           node=arguments.node,
                           gpus=arguments.gpu)

        return ""
Exemplo n.º 12
0
    def do_ip(self, args, arguments):
        """
        ::

            Usage:
                ip list  [--cloud=CLOUD] [--output=OUTPUT]
                ip create [N] [--cloud=CLOUD]
                ip delete [IP] [--cloud=CLOUD]
                ip attach [NAME] [IP]
                ip detach [NAME] [IP]


            Options:
                -h                          help message
                --cloud=CLOUD               Name of the cloud
                --output=OUTPUT             The output format [default: table]

            Arguments:
                N         Number of IPS to create
                IP        IP Address
                NAME      Name of the service


            Description:
                ip list floating [--cloud=CLOUD] [--output=OUTPUT]
                    returns a list of all the floating IPS in the cloud

                ip add floating [--cloud=CLOUD]
                    adds a floating ip to the pool of available floating ips

                ip delete floating [IP] [--cloud=CLOUD]
                    deletes a floating ip to the pool of available
                    floating ips

                ip add NAME [IP]
                    add the ip to the named vm

                ip delete NAME [IP]
                    deletes the ip from the vm

        """
        def get_ip(ip):

            if ip is None:
                # find a free one
                try:
                    ip = provider.find_available_public_ip()
                    return ip
                except Exception as e:
                    Console.error("No free floating ip found")
                    return ""

        map_parameters(arguments, "cloud", "output")
        arguments.vm = arguments.NAME

        variables = Variables()

        if arguments.list:

            cloud = Parameter.find("cloud", arguments, variables)

            print(f"cloud {cloud}")
            provider = Provider(name=cloud)
            ips = provider.list_public_ips()

            provider.Print(ips, output=arguments.output, kind="ip")

        elif arguments.create:

            cloud = Parameter.find("cloud", arguments, variables)

            n = arguments.N or 1

            print(f"cloud {cloud}")
            provider = Provider(name=cloud)

            for i in range(0, int(n)):
                ips = provider.create_public_ip()
            ips = provider.list_public_ips()

            provider.Print(ips, output=arguments.output, kind="ip")

        elif arguments.delete:

            cloud = Parameter.find("cloud", arguments, variables)

            print(f"cloud {cloud}")
            provider = Provider(name=cloud)

            ip = arguments.IP

            ip = get_ip(arguments.IP)

            ips = provider.delete_public_ip(ip)
            ips = provider.list_public_ips()

            provider.Print(ips, output=arguments.output, kind="ip")

        elif arguments.attach:

            name = Parameter.find("vm", arguments, variables)
            cm = CmDatabase()
            vm = cm.find_name(name, kind="vm")[0]
            cloud = vm["cm"]["cloud"]

            print(f"cloud {cloud}")
            provider = Provider(name=cloud)

            ip = get_ip(arguments.IP)
            try:
                ips = provider.attach_public_ip(name=name, ip=ip)
            except Exception as e:
                print(e)
                Console.error("Could not assign public ip.")

        elif arguments.detach:
            name = Parameter.find("vm", arguments, variables)
            cm = CmDatabase()
            vm = cm.find_name(name, kind="vm")[0]
            cloud = vm["cm"]["cloud"]

            print(f"cloud {cloud}")
            provider = Provider(name=cloud)
            ip = provider.get_public_ip(name=name)

            print(name, ip)

            try:
                ips = provider.detach_public_ip(name=name, ip=ip)
            except Exception as e:
                print(e)
                Console.error("can not detach ip")
Exemplo n.º 13
0
    def do_ssh(self, args, arguments):
        """
        ::

            Usage:
                ssh
                ssh config list [--output=OUTPUT]
                ssh config add NAME IP [USER] [KEY]
                ssh config delete NAME
                ssh host delete NAME
                ssh host add NAME
                ssh [--name=VMs] [--user=USERs] [COMMAND]

            Arguments:
              NAME        Name or ip of the machine to log in
              list        Lists the machines that are registered and
                          the commands to login to them
              PARAMETERS  Register te resource and add the given
                          parameters to the ssh config file.  if the
                          resource exists, it will be overwritten. The
                          information will be written in /.ssh/config

            Options:
               -v                verbose mode
               --output=OUTPUT   the format in which this list is given
                                 formats includes cat, table, json, yaml,
                                 dict. If cat is used, it is just printed as
                                 is. [default: table]
               --user=USERs      overwrites the username that is
                                 specified in ~/.ssh/config
               --name=CMs        the names of the VMS to execute the
                                 command on

            Description:
                ssh config list
                    lists the hostsnames that are present in the
                    ~/.ssh/config file

                ssh config add NAME IP [USER] [KEY]
                    registers a host i ~/.ssh/config file
                    Parameters are attribute=value pairs
                    Note: Note yet implemented

                ssh [--name=VMs] [--user=USERs] [COMMAND]
                    executes the command on the named hosts. If user is
                    specified and is greater than 1, it must be specified for
                    each vm. If only one username is specified it is used for
                    all vms. However, as the user is typically specified in the
                    cloudmesh database, you probably do not have to specify
                    it as it is automatically found.

            Examples:


                 ssh config add blue 192.168.1.245 blue

                     Adds the following to the !/.ssh/config file

                     Host blue
                          HostName 192.168.1.245
                          User blue
                          IdentityFile ~/.ssh/id_rsa.pub



        """

        map_parameters(arguments, "name", "user", "output")

        if arguments.config and arguments.list:
            # ssh config list [--output=OUTPUT]"

            hosts = dict(ssh_config().hosts)

            print(
                Printer.dict_table(
                    hosts, order=['host', 'HostName', 'User', 'IdentityFile']))

        elif arguments.config and arguments.add:
            # ssh config add NAME IP [USER] [KEY]

            variables = Variables()

            user = Parameter.find("user", arguments, variables.dict())

            key = Parameter.find("key", arguments, variables.dict(),
                                 {"key": "~/.ssh/id_rsa.pub"})

            name = arguments.NAME or variables['vm']

            ip = arguments.IP

            hosts = ssh_config()

            if name in hosts.hosts:
                Console.error("Host already in ~/.ssh/config")
                return ""

            hosts.generate(host=name, hostname=ip, identity=key, user=user)

        elif arguments.config and arguments.delete:
            # ssh config delete NAME

            raise NotImplementedError

        elif arguments.config and arguments.add:
            # ssh host add NAME

            location = path_expand("~/.ssh/known_hosts")
            name = arguments.NAME
            os.system("ssh-keygen -R {name}")
            os.system(f"ssh-keyscan -H {name} >> {location}")

        elif arguments.config and arguments.delete:
            # ssh host delete NAME

            name = arguments.NAME
            os.system("ssh-keygen -R {name}")

        elif (arguments.name and arguments.COMMAND) or arguments.COMMAND:
            # ssh [--name=VMs] [--user=USERs] [COMMAND]"

            variables = Variables()

            if arguments.name is None:
                name = arguments.NAME or variables['vm']
                names = [name]
            else:
                names = Parameter.expand(arguments.name)
            users = Parameter.expand(arguments.users)
            command = arguments.COMMAND

            if command is None and len(names) > 1:
                raise ValueError("For interactive shells the number of vms "
                                 "must be 1")
            elif command is None and len(names) == 1:

                # find the cloud

                cm = CmDatabase()
                vm = cm.find_name(names[0], kind="vm")[0]
                cloud = vm['cm']['cloud']

                # update the cloud
                provider = Provider(name=cloud)

                # update the vm
                provider.list()
                vm = cm.find_name(names[0], kind="vm")[0]

                # run ssh
                result = provider.ssh(vm=vm, command=command)
                print(result)
                return ""

            if len(names) > 1 and len(users) == 1:
                users = [users] * len(names)

            if len(names) > 1 and len(users) > 1 and len(names) != len(users):
                raise ValueError("vms and users have different length")

            for name in names:
                cm = CmDatabase()
                try:
                    vm = cm.find_name(name, kind="vm")[0]
                except IndexError:
                    Console.error(
                        "VM not found, make sure the vm exists in the list below: "
                    )
                    os.system('cms vm list')
                    return

                cloud = vm['cm']['cloud']
                provider = Provider(name=cloud)
                result = provider.ssh(vm=vm, command=command)
                print(result)
        else:  # ssh with no argument
            last_vm = Variables()['vm']
            cm = CmDatabase()
            vm = cm.find_name(last_vm, kind="vm")[0]
            cloud = vm['cm']['cloud']
            provider = Provider(name=cloud)
            provider.ssh(vm=vm)
Exemplo n.º 14
0
    def do_iu(self, args, arguments):
        """
        ::

          Usage:
                iu lab [--port=PORT]
                iu connect [--port=PORT]
                iu config
                iu allocate
                iu ps
                iu info
                iu kill
                iu status
                iu jupyter [--port=PORT]
                iu port [--port=PORT]
                iu view
                iu [--user=USERNAME]
                   [--host=HOST]
                   [--node=NUMBER]
                   [--gpu=GPUS]
                   [--res=RESERVATION]
                iu res
                iu setup --user=USERNAME
                iu romeo [--user=USERNAME]

          This command allows you to inteactively log into roeo or volta

          Arguments:
              FILE    a file name
              HOST    the host is either rome or volta [default: romeo]
              NUMBER  is a number that specifies where to login
              GPUS    the number of GPU's to be used

          Options:
              --res=RESERVATION  [default: lijguo_11]

          Example:

              cms iu
                 logs in on the first available node, and uses 1 GPU
                 BUG: some reservation are not detected

              cms iu --node=random
                 logs in on the first available node and uses 1 GPU

              cms iu status
                 lists the status of rome and volta. The output will look like:


                    +-------------+-----------+
                    | romeo       | Used GPUs |
                    +-------------+-----------+
                    | r-001       |           |
                    | r-002       | 7         |
                    | r-003       | 7         |
                    | r-004       | 7         |
                    +-------------+-----------+

                    +-------+-----------+
                    | volta | Used GPUs |
                    +-------+-----------+
                    | r-005 | 5         |
                    | r-006 | 7         |
                    +-------+-----------+

                    Users on romeo

                        user1

                    Users on volta

                        user2
        """
        # VERBOSE(arguments)
        config = Config()["cloudmesh.iu"]
        config["port"] = arguments["--port"] or config["port"]

        # pprint (config)

        map_parameters(arguments,
                       "user",
                       "host",
                       "node",
                       "gpu")

        variables = Variables()
        # arguments["user"] = Parameter.find("user", arguments, variables)
        # if arguments.user is None:
        #    config = Config()
        #    arguments.user = config["cloudmesh.iu.user"]

        iu = Manager(config=config)

        if arguments.setup:

            iu.setup()
            return ""

        elif arguments.config:

            iu.config(config)

            return ""

        if arguments.status:

            iu.status(user=arguments.user)

            return ""

        elif arguments.res:

            iu.reservations(user=arguments.user)

            return ""

        elif arguments.allocate:

            iu.allocate(config)

            return ""

        elif arguments.ps:

            found = iu.ps(config)
            print("\n".join(found))
            return ""

        elif arguments.info:

            r = iu.info(config)
            print(Printer.attribute(r))
            return ""


        elif arguments.jupyter:

            found = iu.jupyter(config)
            # print ("\n".join(found))
            return ""

        elif arguments.connect:

            found = iu.connect(config)
            return ""

        elif arguments.port:

            found = iu.set_port(config)
            return ""

        elif arguments.view:

            found = iu.view(config)
            return ""

        elif arguments.lab:

            found = iu.lab(config)
            return ""

        elif arguments.kill:

            found = iu.ps(config)
            for line in found:
                line = line.replace("     ", " ")
                line = line.replace("    ", " ")
                line = line.replace("   ", " ")
                line = line.replace("  ", " ")
                parameter = line.split(" ", 3)
                if "python" in line:
                    id = parameter[1]
                    r = iu.kill(config, id)
                    print(r)
            return ""


        # elif arguments.romeo(user=arguments.user):

        #    iu.reservations(user=arguments.user)

        #    return ""

        else:

            arguments["host"] = Parameter.find("host", arguments, variables,
                                               {"host": "romeo"})
            arguments["node"] = Parameter.find("node", arguments, variables)
            arguments["gpu"] = int(Parameter.find("gpu", arguments, variables,
                                                  {"gpu": "1"}))

            # VERBOSE(arguments)

            banner(f"Login {arguments.host}")

            # iu.login(user=arguments.user,
            #               host=arguments.host,
            #               node=arguments.node,
            #               gpus=arguments.gpu)

            iu.smart_login(user=arguments.user,
                           host=arguments.host,
                           node=arguments.node,
                           gpus=arguments.gpu)

        return ""
Exemplo n.º 15
0
    def do_multipass(self, args, arguments):
        """
        ::

          Usage:
                multipass list [--output=OUTPUT] [--dryrun]
                multipass images [--output=OUTPUT] [--dryrun]
                multipass start NAMES [--output=OUTPUT] [--dryrun]
                multipass stop NAMES [--output=OUTPUT] [--dryrun]
                multipass delete NAMES [--output=OUTPUT][--dryrun]
                multipass shell NAMES [--dryrun]
                multipass run COMMAND NAMES [--output=OUTPUT] [--dryrun]

          Interface to multipass

          Options:
               --output=OUTPUT  the output format [default: table]

          Arguments:
              NAMES   the names of the virtual machine

          Description:

              cms multipass start host[01-03]

                 start multiple vms

              The NAMES can be a parameterized hostname

        """
        name = arguments.NAME

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

        variables = Variables()

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

        names = Parameter.expand(arguments.NAMES)

        VERBOSE(arguments)

        if arguments.list:

            if arguments.dryrun:
                banner("dryrun list")
            else:
                provider = Provider()
                provider.list()

            return ""

        elif arguments.images:

            if arguments.dryrun:
                banner("dryrun images")
            else:

                provider = Provider()
                images = provider.images()

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

            return ""

        elif arguments.run:

            if arguments.dryrun:
                banner("dryrun run")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"run {name} {arguments.COMMAND}")
                else:

                    provider = Provider(name=name)
                    provider.run(arguments.COMMAND)

            return ""

        elif arguments.start:

            if arguments.dryrun:
                banner("start")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun start {name}")
                else:
                    provider = Provider(name=name)
                    provider.start()

            return ""

        elif arguments.stop:

            if arguments.dryrun:
                banner("stop")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun stop {name}")
                else:
                    provider = Provider(name=name)
                    provider.stop()

            return ""

        elif arguments.delete:

            if arguments.dryrun:
                banner("delete")

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

            return ""


        elif arguments.shell:

            if len(names) > 1:
                Console.error("shell must only have one host")
                return ""

            name = names[0]

            if arguments.dryrun:
                banner("dryrun shell {name}")
            else:
                provider = Provider(name=name)
                provider.shell()

            return ""


        else:
            Console.error("Not yet implemented")
        return ""
Exemplo n.º 16
0
    def do_multipass(self, args, arguments):
        """
        ::

          Usage:
                multipass list [--output=OUTPUT] [--dryrun]
                multipass images [--output=OUTPUT] [--dryrun]
                multipass start NAMES [--output=OUTPUT] [--dryrun]
                multipass stop NAMES [--output=OUTPUT] [--dryrun]
                multipass delete NAMES [--output=OUTPUT][--dryrun]
                multipass shell NAMES [--dryrun]
                multipass run COMMAND NAMES [--output=OUTPUT] [--dryrun]
                multipass info NAMES [--output=OUTPUT] [--dryrun]
                multipass suspend NAMES [--output=OUTPUT] [--dryrun]
                multipass resume NAMES [--output=OUTPUT] [--dryrun]
                multipass destroy NAMES [--dryrun]
                multipass create NAMES [--image=IMAGE]
                                       [--size=SIZE]
                                       [--mem=MEMORY]
                                       [--cpus=CPUS]
                                       [--cloud-init=CLOUDINIT]
                                       [--dryrun]
                multipass reboot NAMES [--dryrun]

          Interface to multipass

          Options:
               --output=OUTPUT  the output format [default: table]

          Arguments:
              NAMES   the names of the virtual machine

          Description:

              The NAMES can be a parameterized hostname such as

                red[0-1,5] = red0,red1,red5

              cms multipass start vm1,vm2

                 start multiple vms

              WHEN YOU IMPLEMENT A FUNCTION INCLUDE MINIMAL
              DOCUMENTATION HERE

        """
        name = arguments.NAME

        map_parameters(arguments,
                       "dryrun",
                       "refresh",
                       "cloud",
                       "image",
                       "size",
                       "mem",
                       "cpus",
                       "output")
        # so we can use arguments.cloudinit
        arguments["cloudinit"] = arguments["--cloud-init"]

        image = arguments.image
        variables = Variables()

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

        names = Parameter.expand(arguments.NAMES)

        VERBOSE(arguments)

        if arguments.list:

            if arguments.dryrun:
                banner("dryrun list")
            else:
                provider = Provider()
                provider.list()

            return ""

        elif arguments.images:

            if arguments.dryrun:
                banner("dryrun images")
            else:

                provider = Provider()
                images = provider.images()

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

            return ""

        elif arguments.run:

            if arguments.dryrun:
                banner("dryrun run")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"run {name} {arguments.COMMAND}")
                else:

                    provider = Provider()
                    provider.run(name, arguments.COMMAND)

            return ""

        elif arguments.create:

            result = ""

            if arguments.dryrun:
                banner("create")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun create {name} {image}")
                else:
                    provider = Provider()
                    result = provider.create(name, image)
                    VERBOSE(result)

            return result

        elif arguments.start:

            result = ""

            if arguments.dryrun:
                banner("start")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun start {name}")
                else:
                    provider = Provider()
                    result = provider.start(name)
                    VERBOSE(result)

            return result

        elif arguments.stop:

            result = ""

            if arguments.dryrun:
                banner("stop")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun stop {name}")
                else:
                    provider = Provider(name=name)
                    result = provider.stop(name)
                    VERBOSE(result)

            return result

        elif arguments.delete:

            result = ""

            if arguments.dryrun:
                banner("delete")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun delete {name}")
                else:
                    provider = Provider()
                    # Default purge is false. Is this ok?
                    result = provider.delete(name)
                    VERBOSE(result)

            return result

        elif arguments.info:

            result = ""

            if arguments.dryrun:
                banner(f"info {name}")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun info {name}")
                else:
                    provider = Provider()
                    # Default purge is false. Is this ok?
                    result = provider.info(name)
                    VERBOSE(result)

            return result

        elif arguments.suspend:

            result = ""

            if arguments.dryrun:
                banner("suspend")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun suspend {name}")
                else:
                    provider = Provider()
                    result = provider.suspend(name)
                    VERBOSE(result)

            return result

        elif arguments.resume:

            result = ""

            if arguments.dryrun:
                banner("resume")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun resume {name}")
                else:
                    provider = Provider()
                    result = provider.resume(name)
                    VERBOSE(result)

            return result

        elif arguments.destroy:

            result = ""

            if arguments.dryrun:
                banner("destroy")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun destroy {name}")
                else:
                    provider = Provider()
                    result = provider.destroy(name)
                    VERBOSE(result)

            return result

        elif arguments.reboot:

            result = ""

            if arguments.dryrun:
                banner("reboot")

            for name in names:
                if arguments.dryrun:
                    Console.ok(f"dryrun reboot {name}")
                else:
                    provider = Provider()
                    result = provider.reboot(name)
                    VERBOSE(result)

            return result

        elif arguments.shell:

            if len(names) > 1:
                Console.error("shell must only have one host")
                return ""

            name = names[0]

            if arguments.dryrun:
                banner("dryrun shell {name}")
            else:
                provider = Provider()
                provider.shell()

            return ""

        elif arguments.info:

            if arguments.dryrun:
                banner("dryrun info")
            else:
                provider = Provider()
                info = provider.info()
                print(
                    provider.Print(info,
                                   kind='info',
                                   output=arguments.output))

            return ""

        else:
            Console.error("Not yet implemented")
        return ""