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

            Usage:
                image refresh [--cloud=CLOUD]
                image list [ID] [--cloud=CLOUD] [--format=FORMAT] [--refresh]

                This lists out the images present for a cloud

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

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

        """
        cloud = arguments["--cloud"] or Default.cloud
        if cloud is None:
            Console.error("Default cloud doesn't exist")
            return

        if arguments["refresh"] or Default.refresh:
            msg = "Refresh image for cloud {:}.".format(cloud)
            if Image.refresh(cloud):
                Console.ok("{:} ok.".format(msg))
            else:
                Console.error("{:} failed.".format(msg))
                return ""

        if arguments["list"]:
            id = arguments['ID']
            live = arguments['--refresh']
            output_format = arguments["--format"]

            counter = 0

            result = None
            while counter < 2:
                if id is None:
                    result = Image.list(cloud, output_format)
                else:
                    result = Image.details(cloud, id, live, output_format)
                if counter == 0 and result is None:
                    if not Image.refresh(cloud):
                        msg = "Refresh image for cloud {:}.".format(cloud)
                        Console.error("{:} failed.".format(msg))
                counter += 1

            if result is None:
                Console.error("No image(s) found. Failed.")
            else:
                print(result)
            return ""
Example #2
0
def boot_from_args(arg):
    arg.username = arg.username or Image.guess_username(arg.image)
    is_name_provided = arg.name is not None

    arg.user = Default.user

    for index in range(0, arg.count):
        vm_details = dotdict({
            "cloud": arg.cloud,
            "name": Vm.get_vm_name(arg.name, index),
            "image": arg.image,
            "flavor": arg.flavor,
            "key": arg.key,
            "secgroup": arg.secgroup,
            "group": arg.group,
            "username": arg.username,
            "user": arg.user
        })
        # correct the username
        vm_details.username = Image.guess_username_from_category(
            vm_details.cloud,
            vm_details.image,
            username=arg.username)
        try:

            if arg.dryrun:
                print(Printer.attribute(vm_details, output=arg.format))
                msg = "dryrun info. OK."
                Console.ok(msg)
            else:
                vm_id = Vm.boot(**vm_details)

                if vm_id is None:
                    msg = "info. failed."
                    Console.error(msg, traceflag=False)
                    return ""

                # set name and counter in defaults
                Default.set_vm(value=vm_details.name)
                if is_name_provided is False:
                    Default.incr_counter("name")

                # Add to group
                if vm_id is not None:
                    Group.add(name=vm_details.group,
                              species="vm",
                              member=vm_details.name,
                              category=vm_details.cloud)

                msg = "info. OK."
                Console.ok(msg)

        except Exception as e:
            Console.error("Problem booting instance {name}".format(**vm_details), traceflag=False)
Example #3
0
    def test_009(self):
        HEADING("test image get username")

        # this test only works on chameleon
        if not Default.cloud in ["cm", "chameleon"]:
            assert True

        login  = Image.get_username("CC-Ubuntu14.04", Default.cloud, guess=True)

        print ("LOGIN", login)

        Image.set_username(name="CC-Ubuntu14.04", cloud=Default.cloud, username=login)

        result  = Image.get_username("CC-Ubuntu14.04", Default.cloud)


        print(result)
Example #4
0
    def test_007(self):
        HEADING("test image username guess")

        result = Image.guess_username("Ubuntu-image")
        print(result)
        assert result == "ubuntu"

        result = Image.guess_username("wily-image")
        print(result)
        assert result == "ubuntu"

        result = Image.guess_username("fedora-image")
        print(result)
        assert result == "root"

        result = Image.guess_username("image", description="image with wily")
        print(result)
        assert result == "ubuntu"
Example #5
0
def cloudmesh_refresh_db(request, action=None, cloud=None):

    if action is None:
        action = ['image']
    else:
        action = [action]

    print("******DEBUG*********")
    print("ACTION IS:",action)
    print("******DEBUG*********")

    if cloud is None:
        cloud = Default.cloud
    # TODO: make the cloudname a parameter
    data = Image.refresh(cloud)

    print("REFRESH IMAGE DATA",data)

    data = Image.list(cloud, format='dict')
    print(json.dumps(data, indent=4))
    # TODO set proper columns
    order = [
        'cm_id',
        'name',
        'category',
        'minDisk',
        'minRam',
        'os_image_size',
        'progress',
        'project',
        'status',
    ]

    return (dict_table(request,
                       title="Cloudmesh Images {}".format(cloud),
                       data=data,
                       order=order))
Example #6
0
def cloudmesh_images(request, cloud=None):
    banner("images")
    if cloud is None:
        cloud = Default.cloud
    # TODO: make the cloudname a parameter
    data = Image.list(cloud, format='dict')
    print (json.dumps(data, indent=4))
    # TODO set proper columns
    order = [
        'cm_id',
        'name',
        'category',
        'minDisk',
        'minRam',
        'os_image_size',
        'progress',
        'project',
        'status',
    ]
    return (dict_table(request,
                       title="Cloudmesh Images {}".format(cloud),
                       data=data,
                       order=order))
Example #7
0
    def test_008(self):
        HEADING("test image get username")

        # this test only works on chameleon
        if not Default.cloud in ["cm","chameleon"]:
            assert True

        result = self.run("cm image list --refresh")

        Image.set_username(name="CC-Ubuntu14.04", cloud=Default.cloud, username="undefined")
        result = Image.get_username("CC-Ubuntu14.04", Default.cloud)
        print ('Username:', result)
        assert "undefined" in result

        Image.set_username(name="CC-Ubuntu14.04", cloud=Default.cloud, username=None)
        result = Image.get_username("CC-Ubuntu14.04", Default.cloud, guess=True)
        print("Username:", result)


        assert "cc" in result
Example #8
0
    def do_cluster(self, args, arguments):
        """
        ::

          Usage:
              cluster list [--format=FORMAT]
              cluster list NAME
                           [--format=FORMAT]
                           [--column=COLUMN]
                           [--short]
              cluster create NAME
                             [--count=COUNT]
                             [--login=USERNAME]
                             [--cloud=CLOUD]
                             [--image=IMAGE]
                             [--flavor=FLAVOR]
                             [--add]
              cluster delete NAME
              cluster setup NAME [--username]
              cluster inventory NAME

          Description:
              with the help of the cluster command you can create a number
              of virtual machines that are integrated in a named virtual cluster.
              You will be able to login between the nodes of the virtual cluster
              while using public keys.

              cluster setup NAME
                sets up the keys between the cluster node as well as the machine that
                executes the cm command

              cluster inventory NAME
                creates an inventory.txt file to be used by ansible in the current directory

              cluster create NAME
                 creates the virtual machines used for the cluster

              cluster list NAME
                 lists selected details of the vms for the cluster

              cluster delete NAME
                  remove the cluster and its VMs

          Examples:
              cluster list
                  list the clusters

              cluster create NAME --count=COUNT --login=USERNAME [options...]
                  Start a cluster of VMs, and each of them can log into each other.
                  CAUTION: you should specify defaults before using this command:
                  1. select cloud to work on, e.g. cloud select kilo
                       default cloud=kilo
                  2. test if you can create a single VM on the cloud to see if
                     everything is set up
                  3. set the default key to start VMs, e.g. key default [USERNAME-key]
                  5. set image of VMs, e.g. default image
                  6. set flavor of VMs, e.g. default flavor
                  7. Make sure to use a new unused group name

          Arguments:
              NAME              cluster name or group name

          Options:
              --count=COUNT     give the number of VMs to add into the cluster
              --login=USERNAME  give a login name for the VMs, e.g. ubuntu
              --cloud=CLOUD     give a cloud to work on
              --flavor=FLAVOR   give the name of the flavor or flavor id
              --image=IMAGE     give the name of the image or image id
              --add             if a group exists and there are VMs in it
                                additional vms will be added to this cluster and the
                                keys will be added to each other so one can login between
                                them
              FORMAT            output format: table, json, csv
              COLUMN            customize what information to display, for example:
                                --column=status,addresses prints the columns status
                                and addresses
              --detail          for table print format, a brief version
                                is used as default, use this flag to print
                                detailed table

        """

        def get_vms(group_name):
            groups = Vm.get_vms_by_group(group_name)
            vms = []
            for group in groups:
                name = group["member"]
                print(name)
                vm = Vm.get_vm(name)
                vm['cluster'] = group_name
                vms.append(vm)
            return vms

        def _print(f):
                print (f)

        def write(filename, msg):
            with open(path_expand(filename), 'w') as f:
                output = f.write(msg)

        arg = dotdict(arguments)

        arg.format = arguments["--format"] or "table"
        arg.count = int(arguments["--count"] or 1)
        arg.username = arguments["--login"]
        arg.cloud = arguments["--cloud"] or Default.cloud
        arg.image = arguments["--image"] or Default.get(name="image", category=arg.cloud)
        arg.flavor = arguments["--flavor"] or Default.get(name="flavor", category=arg.cloud)
        arg.add = arguments["--add"]
        arg.group = arg.NAME
        arg.name = None
        arg.key = Default.key
        arg.secgroup = Default.secgroup
        arg.group = arg.NAME
        arg.short = arguments["--short"]

        if arg.create:

            boot_from_args(arg)

        elif arg.inventory:

            group = Vm.get_vms_by_group(arg.group)

            result = ""
            if arg.format is "table":
                result = "[servers]\n"

            for element in group:
                name = element["member"]
                vm = Vm.get_vm(name)[0]
                vm['cluster'] = arg.group
                result += "{floating_ip}\n".format(**vm)

            Console.ok("Writing ips to inventory.txt")
            print(result)

            write("inventory.txt", result)

            Console.ok(".ok")
            return ""


        elif arg.list and arg.NAME is not None:

            if arg.short:

                vms = Vm.get_vms_by_group(arg.group)

                if vms is None:
                    Console.error("no vms found for {}".format(arg.group))
                else:

                    print(Printer.list(vms,
                               header=['Group', 'Vm'],
                               order=['name', 'member'],
                               output=arg.format))

            else:

                groups = Vm.get_vms_by_group(arg.group)

                pprint(groups)

                vms = []
                for group in groups:
                    name = group["member"]
                    vm = Vm.get_vm(name)[0]
                    vm['cluster'] = arg.group
                    if vm is not None:
                        vms.append(vm)

                pprint(vms)


                if vms is None:
                    Console.error("no vms found for {}".format(arg.group))
                else:

                    print(Printer.list(vms,
                                   order=['name', 'cluster', 'flavor', 'image', 'status', 'user_id', 'floating_ip'],
                                   output=arg.format))
            return ""

        elif arg.setup:

            def push(from_path, vm):
                vm.ip = vm.floating_ip
                if vm.ip is not None:
                    if arg.verbose:
                        Console.info("Connecting to Instance at IP:" + format(vm.ip))

                    sshcommand = "scp"
                    sshcommand += " -o StrictHostKeyChecking=no"
                    sshcommand += " {:}".format(from_path)
                    sshcommand += " {username}@{ip}:.ssh/authorized_keys".format(**vm)

                    print(sshcommand)
                    os.system(sshcommand)
                else:
                    Console.error("No Public IPs found for the instance", traceflag=False)


            groups = Vm.get_vms_by_group(arg.group)

            pprint (groups)

            vms = []
            for group in groups:
                name = group["member"]
                vm = Vm.get_vm(name)[0]
                vm['cluster'] = arg.group
                if vm is not None:
                    vms.append(vm)

            pprint(vms)

            if vms is None:
                Console.error("no vms found for {}".format(arg.group))
            else:

                print(Printer.list(vms,
                           order=['name', 'cluster', 'flavor', 'image', 'status', 'user_id', 'floating_ip'],
                           output=arg.format))

                keys = ""
                for vm in vms:
                    vm = dotdict(vm)
                    cloud = vm.category

                    if vm.username is None:
                        vm.username = arguments["--username"] or Image.guess_username(arg.image)



                    chameleon = "chameleon" in ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["clouds"][cloud][
                        "cm_host"]


                    print ("C", chameleon)

                    if chameleon:
                        vm.username = "cc"
                    elif vm.category == "azure":
                        vm.username = ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["clouds"]["azure"]["default"][
                        "username"]
                    else:
                        if vm.username is None:
                            Console.error("Could not guess the username of the vm", traceflag=False)
                            return


                    Vm.set_login_user(name=vm.name, cloud=vm.category, username=vm.username)
                    vm.ip = vm.floating_ip


                    def execute(commands):
                        if vm.ip is not None:
                            if arg.verbose:
                                Console.info("Connecting to Instance at IP:" + format(vm.ip))

                            sshcommand = "ssh"
                            if arg.key is not None:
                                sshcommand += " -i {:}".format(arg.key)
                            sshcommand += " -o StrictHostKeyChecking=no"
                            sshcommand += " {username}@{ip}".format(**vm)
                            sshcommand += " \'{:}\'".format(commands)

                            print(sshcommand)
                            os.system(sshcommand)
                        else:
                            Console.error("No Public IPs found for the instance", traceflag=False)

                    def copy(commands):
                        if vm.ip is not None:
                            if arg.verbose:
                                Console.info("Connecting to Instance at IP:" + format(vm.ip))

                            sshcommand = "scp"
                            sshcommand += " -o StrictHostKeyChecking=no"
                            sshcommand += " {username}@{ip}".format(**vm)
                            sshcommand += ":{:}".format(commands)

                            print(sshcommand)
                            os.system(sshcommand)
                        else:
                            Console.error("No Public IPs found for the instance", traceflag=False)


                    def cat(filename):
                        with open(path_expand(filename), 'r') as f:
                            output = f.read()
                        return output



                    execute('cat /dev/zero | ssh-keygen -q -N ""')
                    copy(".ssh/id_rsa.pub ~/.ssh/id_rsa_{name}.pub".format(**vm))

                    output = "~/.ssh/id_rsa_{name}.pub".format(**vm)

                    keys = keys + cat(output)

                print ("WRITE KEYS")
                keys = keys + cat("~/.ssh/id_rsa.pub")
                output = "~/.ssh/id_rsa_{group}.pub".format(**arg)
                write(output, keys)

                print("PUSH KEYS")
                for vm in vms:
                    vm = dotdict(vm)
                    push("~/.ssh/id_rsa_{group}.pub".format(**arg), vm)

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

            Usage:
                vm default [--cloud=CLOUD][--format=FORMAT]
                vm refresh [all][--cloud=CLOUD]
                vm boot [--name=NAME]
                        [--cloud=CLOUD]
                        [--username=USERNAME]
                        [--image=IMAGE]
                        [--flavor=FLAVOR]
                        [--group=GROUP]
                        [--public]
                        [--secgroup=SECGROUP]
                        [--key=KEY]
                        [--dryrun]
                vm boot [--n=COUNT]
                        [--cloud=CLOUD]
                        [--username=USERNAME]
                        [--image=IMAGE]
                        [--flavor=FLAVOR]
                        [--group=GROUP]
                        [--public]
                        [--secgroup=SECGROUP]
                        [--key=KEY]
                        [--dryrun]
                vm ping [NAME] [N]
                vm console [NAME]
                         [--group=GROUP]
                         [--cloud=CLOUD]
                         [--force]
                vm start [NAMES]
                         [--group=GROUP]
                         [--cloud=CLOUD]
                         [--force]
                vm stop [NAMES]
                        [--group=GROUP]
                        [--cloud=CLOUD]
                        [--force]
                vm terminate [NAMES]
                          [--group=GROUP]
                          [--cloud=CLOUD]
                          [--force]
                vm delete [NAMES]
                          [--group=GROUP]
                          [--cloud=CLOUD]
                          [--keep]
                          [--dryrun]
                vm ip assign [NAMES]
                          [--cloud=CLOUD]
                vm ip show [NAMES]
                           [--group=GROUP]
                           [--cloud=CLOUD]
                           [--format=FORMAT]
                           [--refresh]
                vm ip inventory [NAMES]
                                [--header=HEADER]
                                [--file=FILE]
                vm ssh [NAME] [--username=USER]
                         [--quiet]
                         [--ip=IP]
                         [--cloud=CLOUD]
                         [--key=KEY]
                         [--command=COMMAND]
                vm rename [OLDNAMES] [NEWNAMES] [--force] [--dryrun]
                vm list [NAMES]
                        [--cloud=CLOUDS|--active]
                        [--group=GROUP]
                        [--format=FORMAT]
                        [--refresh]
                vm status [NAMES]
                vm wait [--cloud=CLOUD] [--interval=SECONDS]
                vm info [--cloud=CLOUD]
                        [--format=FORMAT]
                vm check NAME
                vm username USERNAME [NAMES] [--cloud=CLOUD]

            Arguments:
                COMMAND        positional arguments, the commands you want to
                               execute on the server(e.g. ls -a) separated by ';',
                               you will get a return of executing result instead of login to
                               the server, note that type in -- is suggested before
                               you input the commands
                NAME           server name. By default it is set to the name of last vm from database.
                NAMES          server name. By default it is set to the name of last vm from database.
                KEYPAIR_NAME   Name of the openstack keypair to be used to create VM. Note this is
                               not a path to key.
                NEWNAMES       New names of the VM while renaming.
                OLDNAMES       Old names of the VM while renaming.

            Options:
                --username=USERNAME  the username to login into the vm. If not specified it will be guessed
                                     from the image name and the cloud
                --ip=IP          give the public ip of the server
                --cloud=CLOUD    give a cloud to work on, if not given, selected
                                 or default cloud will be used
                --count=COUNT    give the number of servers to start
                --detail         for table print format, a brief version
                                 is used as default, use this flag to print
                                 detailed table
                --flavor=FLAVOR  give the name or id of the flavor
                --group=GROUP          give the group name of server
                --secgroup=SECGROUP    security group name for the server
                --image=IMAGE    give the name or id of the image
                --key=KEY        specify a key to use, input a string which
                                 is the full path to the private key file
                --keypair_name=KEYPAIR_NAME   Name of the openstack keypair to be used to create VM.
                                              Note this is not a path to key.
                --user=USER      give the user name of the server that you want
                                 to use to login
                --name=NAME      give the name of the virtual machine
                --force          rename/ delete vms without user's confirmation
                --command=COMMAND
                                 specify the commands to be executed


            Description:
                commands used to boot, start or delete servers of a cloud

                vm default [options...]
                    Displays default parameters that are set for vm boot either on the
                    default cloud or the specified cloud.

                vm boot [options...]
                    Boots servers on a cloud, user may specify flavor, image .etc, otherwise default values
                    will be used, see how to set default values of a cloud: cloud help

                vm start [options...]
                    Starts a suspended or stopped vm instance.

                vm stop [options...]
                    Stops a vm instance .

                vm delete [options...]
                    Delete servers of a cloud, user may delete a server by its name or id, delete servers
                    of a group or servers of a cloud, give prefix and/or range to find servers by their names.
                    Or user may specify more options to narrow the search

                vm floating_ip_assign [options...]
                    assign a public ip to a VM of a cloud

                vm ip show [options...]
                    show the ips of VMs

                vm ssh [options...]
                    login to a server or execute commands on it

                vm list [options...]
                    same as command "list vm", please refer to it

                vm status [options...]
                    Retrieves status of last VM booted on cloud and displays it.

            Tip:
                give the VM name, but in a hostlist style, which is very
                convenient when you need a range of VMs e.g. sample[1-3]
                => ['sample1', 'sample2', 'sample3']
                sample[1-3,18] => ['sample1', 'sample2', 'sample3', 'sample18']

            Quoting commands:
                cm vm login gvonlasz-004 --command=\"uname -a\"
        """

        """

        # terminate
        #  issues a termination to the cloud, keeps vm in database

        # delete
        #   issues a terminate if not already done
        #      (remember you do not have to go to cloud if state is already terminated)
        #   deletes the vm from database
        #


        # bulk rename

        rename abc[0-1] def[3-4]       renames the abc0,abc1 -> def3,def4

        if arguments["rename"]:
            oldnames = Parameter.expand(arguments["OLDNAME"])
            newnames = Parameter.expand(arguments["NEWNAME"])

            # check if new names ar not already taken
            # to be implemented

            if len(oldnames) == len(newnames):
                for i in range(0, len(oldnames)):
                    oldname = oldnames[i]
                    newname = newnames[i]
                if newname is None or newname == '':
                    print("New node name cannot be empty")
                else:
                    print(Cluster.rename_node(clusterid, oldname, newname))
        """

        cm = CloudmeshDatabase()

        def _print_dict(d, header=None, output='table'):
            return Printer.write(d, order=["id", "name", "status"], output=output, sort_keys=True)

        def _print_dict_ip(d, header=None, output='table'):
            return Printer.write(d, order=["network", "version", "addr"], output=output, sort_keys=True)

        def get_vm_name(name=None, offset=0, fill=3):

            if name is None:
                count = Default.get_counter(name='name') + offset
                prefix = Default.user
                if prefix is None or count is None:
                    Console.error("Prefix and Count could not be retrieved correctly.", traceflag=False)
                    return
                name = prefix + "-" + str(count).zfill(fill)
            return name

        def _refresh_cloud(cloud):
            try:
                msg = "Refresh VMs for cloud {:}.".format(cloud)
                if Vm.refresh(cloud=cloud):
                    Console.ok("{:} OK.".format(msg))
                else:
                    Console.error("{:} failed".format(msg), traceflag=False)
            except Exception as e:
                Console.error("Problem running VM refresh", traceflag=False)

        def _get_vm_names():

            vm_list  = cm.find(kind="vm")

            vms = [vm["name"] for vm in vm_list]

            names = pattern = arguments["NAMES"]
            if pattern is not None:
                if "*" in pattern:
                    names = search(vms, pattern)
                else:
                    names = Parameter.expand(names)

            if names == ['last'] or names is None:
                names == [Default.vm]

            return vm_list, names

        cloud = arguments["--cloud"] or Default.cloud

        config = ConfigDict("cloudmesh.yaml")
        active_clouds = config["cloudmesh"]["active"]

        def _refresh(cloud):
            all = arguments["all"] or None

            if all is None:

                _refresh_cloud(cloud)
            else:
                for cloud in active_clouds:
                    _refresh_cloud(cloud)

        arg = dotdict(arguments)

        arg.cloud = arguments["--cloud"] or Default.cloud
        arg.image = arguments["--image"] or Default.get(name="image", category=arg.cloud)
        arg.flavor = arguments["--flavor"] or Default.get(name="flavor", category=arg.cloud)
        arg.group = arguments["--group"] or Default.group
        arg.secgroup = arguments["--secgroup"] or Default.secgroup
        arg.key = arguments["--key"] or Default.key
        arg.dryrun = arguments["--dryrun"]
        arg.name = arguments["--name"]
        arg.format = arguments["--format"] or 'table'
        arg.refresh = Default.refresh or arguments["--refresh"]
        arg.count = int(arguments["--n"] or 1)
        arg.dryrun = arguments["--dryrun"]
        arg.verbose = not arguments["--quiet"]

        #
        # in many cases use NAMES
        # if arg.NAMES is not None:
        #   arg.names = Parameter.expand(arg.NAMES)   #  gvonlasz[001-002]  gives ["gvonlasz-001", "gvonlasz-002"]
        # else:
        #    arg.names = None
        #

        if arguments["boot"]:

            arg.username = arguments["--username"] or Image.guess_username(arg.image)
            is_name_provided = arg.name is not None

            arg.user = Default.user

            for index in range(0, arg.count):
                vm_details = dotdict({
                    "cloud": arg.cloud,
                    "name": get_vm_name(arg.name, index),
                    "image": arg.image,
                    "flavor": arg.flavor,
                    "key": arg.key,
                    "secgroup": arg.secgroup,
                    "group": arg.group,
                    "username": arg.username,
                    "user": arg.user
                })
                # correct the username
                vm_details.username = Image.guess_username_from_category(
                    vm_details.cloud,
                    vm_details.image,
                    username=arg.username)
                try:

                    if arg.dryrun:
                        print(Printer.attribute(vm_details, output=arg.format))
                        msg = "dryrun info. OK."
                        Console.ok(msg)
                    else:
                        vm_id = Vm.boot(**vm_details)

                        if vm_id is None:
                            msg = "info. failed."
                            Console.error(msg, traceflag=False)
                            return ""

                        # set name and counter in defaults
                        Default.set_vm(value=vm_details.name)
                        if is_name_provided is False:
                            Default.incr_counter("name")

                        # Add to group
                        if vm_id is not None:
                            Group.add(name=vm_details.group,
                                      species="vm",
                                      member=vm_details.name,
                                      category=vm_details.cloud)

                        msg = "info. OK."
                        Console.ok(msg)

                except Exception as e:
                    Console.error("Problem booting instance {name}".format(**vm_details), traceflag=False)

        elif arguments["username"]:

            arg.username = arguments["--username"] or Image.guess_username(arg.image)

            cloud = arg.cloud
            username = arg.USERNAME
            if arg.NAMES is None:
                names = [Default.vm]
            else:
                names = Parameter.expand(arg.NAMES)

            if len(names) == 0:
                return

            for name in names:
                arg.name = name
                Console.ok("Set username for {cloud}:{name} to {USERNAME}".format(**arg))
                Vm.set_login_user(name=name, cloud=cloud, username=username)

        elif arguments["default"]:
            try:
                count = Default.get_counter()
                prefix = Username()

                if prefix is None or count is None:
                    Console.error("Prefix and Count could not be retrieved correctly.", traceflag=False)
                    return

                vm_name = prefix + "-" + str(count).zfill(3)
                arg = {
                    "name": vm_name,
                    "cloud": arguments["--cloud"] or Default.cloud
                }
                for attribute in ["image", "flavor"]:
                    arg[attribute] = Default.get(name=attribute, category=cloud)
                for attribute in ["key", "group", "secgroup"]:
                    arg[attribute] = Default.get(name=attribute, category='general')

                output = arguments["--format"] or "table"
                print(Printer.attribute(arg, output=output))
                msg = "info. OK."
                Console.ok(msg)
                ValueError("default command not implemented properly. Upon "
                           "first install the defaults should be read from yaml.")
            except Exception as e:
                # Error.traceback(e)
                Console.error("Problem listing defaults", traceflag=False)

        elif arguments["ping"]:
            try:
                if arguments["NAME"] is None and arguments["N"] is None:
                    name = arguments["NAME"] or Default.vm
                    n = arguments["N"] or 1
                elif arguments["NAME"].isdigit():
                    n = arguments["NAME"]
                    name = Default.vm
                else:
                    name = arguments["NAME"] or Default.vm
                    n = arguments["N"] or 1

                print("Ping:", name, str(n))

                vm = dotdict(Vm.list(name=name, category=cloud, output="dict")["dict"])

                ip = vm.floating_ip

                result = Shell.ping(host=ip, count=n)
                print(result)

            except Exception as e:
                Console.error(e.message, traceflag=False)

        elif arguments["console"]:
            try:
                name = arguments["NAME"] or Default.vm

                vm = dotdict(Vm.list(name=name, category=cloud, output="dict")["dict"])

                cloud_provider = CloudProvider(cloud).provider
                vm_list = cloud_provider.list_console(vm.uuid)
                print(vm_list)
                msg = "info. OK."
                Console.ok(msg)
            except Exception as e:
                # Error.traceback(e)
                Console.error("Problem retrieving status of the VM", traceflag=False)

        elif arguments["status"]:
            try:
                cloud_provider = CloudProvider(cloud).provider
                vm_list = cloud_provider.list_vm(cloud)

                vms = [vm_list[i]["name"] for i in vm_list ]
                print ("V", vms)

                pattern = arguments["NAMES"]
                if pattern is not None:
                    if "*" in pattern:
                        print ("serach")
                        names  = search(vms, pattern)
                    else:
                        names = Parameter.expand()
                    for i in vm_list:
                        if vm_list[i]["name"] in names:
                            print("{} {}".format(vm_list[i]["status"], vm_list[i]["name"]))
                else:
                    print("{} {}".format(vm_list[0]["status"], vm_list[0]["name"]))
            except Exception as e:
                # Error.traceback(e)
                Console.error("Problem retrieving status of the VM", traceflag=True)
        elif arguments["wait"]:
            interval = arguments["--interval"] or 5
            try:
                cloud_provider = CloudProvider(cloud).provider
                for i in range(1,10):
                    vm_list = cloud_provider.list_vm(cloud)
                    time.sleep(float(1))
                    d = {}
                    for id in vm_list:
                        vm = vm_list[id]
                        d[vm["name"]] = vm["status"]
                    print (d)
                    print("{} {}".format(vm_list[0]["status"], vm_list[0]["name"]))
                    if vm_list[0]["status"] in ['ACTIVE']:
                        return
            except Exception as e:
                # Error.traceback(e)
                Console.error("Problem retrieving status of the VM", traceflag=True)

        elif arguments["info"]:
            try:
                cloud_provider = CloudProvider(cloud).provider
                vms = cloud_provider.list_vm(cloud)
                vm = vms[0]
                output_format = arguments["--format"] or "table"
                print(Printer.attribute(vm, output=output_format))
                msg = "info. OK."
                Console.ok(msg)
            except Exception as e:
                # Error.traceback(e)
                Console.error("Problem retrieving status of the VM", traceflag=False)

        elif arguments["check"]:

            test = {}
            try:

                names = Parameter.expand(arguments["NAME"])
                id = 0
                for name in names:
                    print("Not implemented: {}".format(name))
                    # TODO: check the status of the vms
                    status = "active"
                    # TODO: check if they have a floating ip
                    # TODO: get ip
                    floating_ip = "127.0.0.1"
                    ip = True
                    # ping
                    # TODO: ping the machine with the shell command
                    ping = True
                    # check if one can login and run a command
                    check = False
                    try:
                        r = Shell.execute("uname", "-a")
                        # do a real check
                        check = True
                    except:
                        check = False
                    test[name] = {
                        "id": id,
                        "name": name,
                        "status": status,
                        "ip": ip,
                        "ping": ping,
                        "login": check
                    }
                    id += 1

                pprint(test)

                print(Printer.write(test,
                                    order=["id",
                                           "name",
                                           "status",
                                           "ip",
                                           "ping",
                                           "login"],
                                    output="table",
                                    sort_keys=True))

                msg = "not yet implemented. failed."
                Console.error(msg, traceflag=False)
            except Exception as e:
                # Error.traceback(e)
                Console.error("Problem retrieving status of the VM", traceflag=False)

        elif arguments["start"]:
            try:
                servers = Parameter.expand(arguments["NAMES"])

                # If names not provided, take the last vm from DB.
                if len(servers) == 0:
                    last_vm = Default.vm
                    if last_vm is None:
                        Console.error("No VM records in database. Please run vm refresh.", traceflag=False)
                        return ""
                    name = last_vm["name"]
                    # print(name)
                    servers = list()
                    servers.append(name)

                group = arguments["--group"]
                force = arguments["--force"]

                # if default cloud not set, return error
                if not cloud:
                    Console.error("Default cloud not set.", traceflag=False)
                    return ""

                Vm.start(cloud=cloud, servers=servers)

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

        elif arguments["stop"]:
            try:
                servers = Parameter.expand(arguments["NAMES"])

                # If names not provided, take the last vm from DB.
                if servers is None or len(servers) == 0:
                    last_vm = Default.vm
                    if last_vm is None:
                        Console.error("No VM records in database. Please run vm refresh.", traceflag=False)
                        return ""
                    name = last_vm["name"]
                    # print(name)
                    servers = list()
                    servers.append(name)

                group = arguments["--group"]
                force = arguments["--force"]

                # if default cloud not set, return error
                if not cloud:
                    Console.error("Default cloud not set.", traceflag=False)
                    return ""

                Vm.stop(cloud=cloud, servers=servers)

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

        elif arguments["refresh"]:

            _refresh(cloud)

        elif arguments["delete"]:

            dryrun = arguments["--dryrun"]
            group = arguments["--group"]
            force = not arguments["--keep"]
            cloud = arguments["--cloud"]
            vms, servers = _get_vm_names()

            if servers in [None, []]:
                Console.error("No vms found.", traceflag=False)
                return ""

            for server in servers:
                if dryrun:
                    Console.ok("Dryrun: delete {}".format(server))
                else:
                   Vm.delete(servers=[server], force=force)

            return ""

        elif arguments["ip"] and arguments["assign"]:
            if arguments["NAMES"] is None:
                names = [Default.vm]
            else:
                names = Parameter.expand(arguments["NAMES"])

            for name in names:

                # ip = Network.get_floatingip(....)

                vm = dotdict(Vm.list(name=name, category=cloud, output="dict")["dict"])

                if vm.floating_ip is None:

                    Console.ok("Assign IP to {}".format(name))

                    try:
                        floating_ip = Network.find_assign_floating_ip(cloudname=cloud,
                                                                      instance_id=name)

                        Vm.refresh(cloud=cloud)

                        if floating_ip is not None:
                            print(
                                "Floating IP assigned to {:} is {:}".format(
                                    name, floating_ip))
                            msg = "info. OK."
                            Console.ok(msg)
                    except Exception as e:

                        Console.error("Problem assigning floating ips.", traceflag=False)

                else:
                    Console.error("VM {} already has a floating ip: {}".format(name, vm.floating_ip), traceflag=False)


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

            vms, names = _get_vm_names()

            if names in [None, []]:
                if str(Default.vm) in ['None', None]:
                    Console.error("The default vm is not set.", traceflag=False)
                    return ""
                else:
                    names = [Default.vm]

            header = arguments["--header"] or "[servers]"
            filename = arguments["--file"] or "inventory.txt"

            try:
                vm_ips = []
                for vm in vms:
                    if  vm["name"] in names:
                        print (vm["name"])
                        vm_ips.append(vm["floating_ip"])

                result = header + "\n"

                result += '\n'.join(vm_ips)
                Console.ok("Creating inventory file: {}".format(filename))

                Console.ok(result)

                with open(filename, 'w') as f:
                    f.write(result)



            except Exception as e:
                Console.error("Problem getting ip addresses for instance", traceflag=True)

        elif arguments["ip"] and arguments["show"]:
            if arguments["NAMES"] is None:
                if str(Default.vm) in ['None', None]:
                    Console.error("The default vm is not set.", traceflag=False)
                    return ""
                else:
                    names = [Default.vm]
            else:
                names = Parameter.expand(arguments["NAMES"])

            group = arguments["--group"]
            output_format = arguments["--format"] or "table"
            refresh = arguments["--refresh"]

            try:

                ips = Ip.list(cloud=arg.cloud, output=output_format, names=names)
                print(ips)
            except Exception as e:
                Console.error("Problem getting ip addresses for instance", traceflag=False)

        elif arguments["ssh"]:

            def _print(msg):
                if arg.verbose:
                    Console.msg(msg)

            chameleon = "chameleon" in ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["clouds"][arg.cloud][
                "cm_host"]

            if chameleon:
                arg.username = "cc"
            elif arg.cloud == "azure":
                arg.username = ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["clouds"]["azure"]["default"]["username"]
            else:
                if arg.username is None:
                    Console.error("Could not guess the username of the vm", traceflag=False)
                    return
                arg.username = arguments["--username"] or Image.guess_username(arg.image)
            arg.command = arguments["--command"]

            data = dotdict({
                'name': arguments["NAME"] or Default.vm,
                'username': arg.username,
                'cloud': arg.cloud,
                'command': arg.command
            })

            _print("login {cloud}:{username}@{name}".format(**data))

            vm = Vm.get(data.name, category=data.cloud)


            Vm.set_login_user(name=data.name, cloud=data.cloud, username=data.username)

            data.floating_ip = vm.floating_ip
            data.key = arguments["--key"] or Default.key

            _print(Printer.attribute(data))

            '''
            if vm.username is None:
                user_from_db = Vm.get_login_user(vm.name, vm.cloud)

                user_suggest = user_from_db or Default.user
                username = input("Username (Default: {}):".format(user_suggest)) or user_suggest

            Vm.set_login_user(name=data.name, cloud=cloud, username=data.username)
            '''

            ip = arguments["--ip"]
            commands = arguments["--command"]

            ip_addresses = []

            cloud_provider = CloudProvider(cloud).provider
            ip_addr = cloud_provider.get_ips(vm.name)

            ipaddr_dict = Vm.construct_ip_dict(ip_addr, cloud)
            for entry in ipaddr_dict:
                ip_addresses.append(ipaddr_dict[entry]["addr"])

            if len(ip_addresses) > 0:
                if ip is not None:
                    if ip not in ip_addresses:
                        Console.error("IP Address specified does not match with the host.", traceflag=False)
                        return ""
                else:
                    _print("Determining IP Address to use with a ping test.")
                    # This part assumes that the ping is allowed to the machine.
                    for ipadd in ip_addresses:
                        _print("Checking {:}...".format(ipadd))
                        try:
                            # Evading ping test, as ping is not enabled for VMs on Azure cloud
                            # socket.gethostbyaddr(ipadd)
                            # ip will be set if above command is successful.
                            ip = ipadd
                        except socket.herror:
                            _print("Cannot reach {:}.".format(ipadd))

                if ip is None:
                    _print("Unable to connect to the machine")
                    return ""
                else:
                    _print("IP to be used is: {:}".format(ip))

                #
                # TODO: is this correctly implemented
                #
                if not cloud == 'azure':
                    SecGroup.enable_ssh(cloud=cloud)

                if arg.verbose:
                    Console.info("Connecting to Instance at IP:" + format(ip))
                # Constructing the ssh command to connect to the machine.
                sshcommand = "ssh"
                if arg.key is not None:
                    sshcommand += " -i {:}".format(arg.key)
                sshcommand += " -o StrictHostKeyChecking=no"
                sshcommand += " {:}@{:}".format(data.username, ip)
                if commands is not None:
                    sshcommand += " \"{:}\"".format(commands)

                # print(sshcommand)
                os.system(sshcommand)
            else:
                Console.error("No Public IPs found for the instance", traceflag=False)

        elif arguments["list"]:

            # groups = Group.list(output="dict")

            arg = dotdict(arguments)
            arg.names = arguments["NAMES"]

            arg.group = arguments["--group"]
            if arg.group is None:
                arg.group = []
            else:
                arg.group = Parameter.expand(arguments["--group"])

            arg.refresh = arguments["--refresh"] or Default.refresh

            if arg.NAMES is not None:
                arg.names = Parameter.expand(arguments["NAMES"])
            else:
                arg.names = ["all"]

            _format = arguments["--format"] or "table"

            if arguments["--active"]:
                clouds = active_clouds
            else:
                if arguments["--cloud"]:
                    clouds = Parameter.expand(arguments["--cloud"])
                else:
                    clouds = [Default.cloud]

            try:

                d = ConfigDict("cloudmesh.yaml")
                for cloud in clouds:

                    if arg.refresh:
                        _refresh(cloud)

                    Console.ok("Listing VMs on Cloud: {:}".format(cloud))

                    vms = Vm.list(category=cloud, output="raw")

                    # print ("XXX", type(vms), vms)

                    if vms is None:
                        break

                    result = []
                    if "all" in arg.names:
                        if result is None:
                            result = []
                        else:
                            result = vms
                    elif arg.group is not None and len(arg.group) > 0:
                        for vm in vms:
                            if vm["group"] in arg.group:
                                result.append(vm)
                    elif arg.names is not None and len(arg.names) > 0:
                        for vm in vms:
                            if vm["name"] in arg.names:
                                result.append(vm)

                    if len(result) > 0:
                        # print(result)
                        (order, header) = CloudProvider(cloud).get_attributes("vm")
                        print(Printer.write(result,
                                            order=order,
                                            output=_format)
                              )
                    else:
                        Console.error("No data found with requested parameters.", traceflag=False)
            except Exception as e:
                # Error.traceback(e)
                Console.error("Problem listing all instances", traceflag=False)


        elif arguments["rename"]:
            try:
                oldnames = Parameter.expand(arguments["OLDNAMES"])
                newnames = Parameter.expand(arguments["NEWNAMES"])
                force = arguments["--force"]

                if oldnames is None or newnames is None:
                    Console.error("Wrong VMs specified for rename", traceflag=False)
                elif len(oldnames) != len(newnames):
                    Console.error("The number of VMs to be renamed is wrong",
                                  traceflat=False)
                else:
                    for i in range(0, len(oldnames)):
                        oldname = oldnames[i]
                        newname = newnames[i]
                        if arguments["--dryrun"]:
                            Console.ok("Rename {} to {}".format(oldname, newname))
                        else:
                            Vm.rename(cloud=cloud,
                                      oldname=oldname,
                                      newname=newname,
                                      force=force
                                      )
                    msg = "info. OK."
                    Console.ok(msg)
            except Exception as e:
                # Error.traceback(e)
                Console.error("Problem deleting instances", traceflag=False)

        return ""
Example #10
0
    def boot(self, **kwargs):
        """Boot a single VM

        :param kwargs: parameters to :meth:`Vm.boot`
        :return: the vm details
        :rtype: :class:`Node`
        """

        cloud = kwargs.get('cloud', Default.cloud)
        name = kwargs.get('name', Vm.generate_vm_name())
        image = kwargs.get('image', Default.image)
        flavor = kwargs.get('flavor', Default.flavor)
        key = kwargs.get('key', Default.key)
        secgroup = kwargs.get('secgroup', Default.secgroup)
        group = kwargs.get('group', Default.group)
        username = kwargs.get('username', Image.guess_username(image))
        cluster = kwargs.get('cluster', None)

        # shorthand for getting a dict of all the vm details
        #
        # IMPORTANT: anything declared prior to the call to `locals()`
        # may be passed to `Vm.boot`, so make sure that only parameters are
        # defined above this comment.
        details = locals()
        details.pop('kwargs')

        # currently, Vm.boot returns the instance UUID from the provider for openstack images
        # 2016/12/12
        uuid = Vm.boot(**details)


        # helper function: the Vm.boot only returns a UUID, but we
        # need to use the VM model instead. Additionally, we'll need
        # to poll the VM to wait until it is active.
        #
        # The kwargs are used to select the item from the DB:
        # eg: uuid=???, cm_id=???, etc
        def get_vm(**kwargs):
            """Selects the VM based on the given properties"""
            model = self.db.vm_table_from_provider('openstack')
            vm = self.db.select(model, **kwargs).all()
            assert len(vm) == 1, vm
            vm = vm[0]
            return vm

        # get the VM from the UUID
        vm = get_vm(uuid=uuid)
        cm_id = vm.cm_id

        def is_active():
            Vm.refresh(cloud=cloud)
            vm = get_vm(cm_id=cm_id)
            return vm.status == 'ACTIVE'

        if not exponential_backoff(is_active):
            Console.error('Failed to get ACTIVE vm within timeframe')
            raise ValueError

        assert is_active()
        vm = get_vm(cm_id=cm_id)
        assert isinstance(vm, VM_OPENSTACK), vm.__class__

        return OpenstackNode(model=vm, provider=self)
Example #11
0
    def do_select(self, args, arguments):
        """
        ::

          Usage:
              select image [CLOUD]
              select flavor [CLOUD]
              select cloud [CLOUD]
              select key [CLOUD]

          selects interactively the default values

          Arguments:

            CLOUD    the name of the cloud

          Options:

        """
        # pprint(arguments)
        cloud = arguments["CLOUD"] or Default.get_cloud()
        if arguments["image"]:
            try:
                image_dict = Image.list(cloud, format="dict")

                image_names = list()
                for image in image_dict.values():
                    image_names.append(image["name"])

                number = menu_return_num(title="Select an Image",
                                         menu_list=image_names,
                                         tries=10,
                                         with_display=True)

                if number == "q":
                    pass
                else:
                    image = image_names[number]
                    print("Selected image " + image)
                    Default.set("image", image, cloud=cloud)
            except:
                print("ERROR: could not set image.")

        elif arguments["flavor"]:
            try:
                flavor_dict = Flavor.list(cloud, format="dict")

                flavor_names = list()
                for flavor in flavor_dict.values():
                    flavor_names.append(flavor["name"])

                number = menu_return_num(title="Select a Flavor",
                                         menu_list=flavor_names,
                                         tries=10,
                                         with_display=True)

                if number == "q":
                    pass
                else:
                    flavor = flavor_names[number]
                    print("Selected flavor " + flavor)
                    Default.set("flavor", flavor, cloud=cloud)
            except:
                print("ERROR: could not set flavor.")

        elif arguments["cloud"]:
            try:
                config = ConfigDict("cloudmesh.yaml")
                clouds = config["cloudmesh"]["clouds"]

                for key in clouds.keys():
                    Console.ok("  " + key)

                number = menu_return_num(title="Select a cloud",
                                         menu_list=clouds.keys(),
                                         tries=10,
                                         with_display=True)
                if number == "q":
                    pass
                else:
                    cloud = clouds.keys()[number]
                    print("Selected cloud " + cloud)
                    Default.set("cloud", cloud, "general")
            except:
                print("ERROR: could not set cloud.")

        elif arguments["key"]:
            try:
                db = SSHKeyDBManager()

                key_dict = db.table_dict()

                key_names = list()
                for key in key_dict.values():
                    key_names.append(key["name"])

                number = menu_return_num(title="Select a Key",
                                         menu_list=key_names,
                                         tries=10,
                                         with_display=True)

                if number == "q":
                    pass
                else:
                    key = key_names[number]
                    print("Selected key " + key)

                    # TODO Fix default key setting in key DB
                    # db.set_default(key)

                    Default.set("key", key, cloud=cloud)
            except:
                print("ERROR: could not set key")

        return ""