Ejemplo n.º 1
0
    def __init__(self, cloudname, user=None, flat=True):
        super(CloudProvider, self).__init__(cloudname, user=user)

        try:
            d = ConfigDict("cloudmesh.yaml")
            if not cloudname in d["cloudmesh"]["clouds"]:
                raise ValueError("the cloud {} is not defined in the yaml file. failed."
                                 .format(cloudname))

            cloud_details = d["cloudmesh"]["clouds"][cloudname]

            if cloud_details["cm_type"] == "openstack":
                provider = CloudProviderOpenstackAPI(
                    cloudname,
                    cloud_details,
                    flat=flat)
                self.provider = provider
                self.provider_class = CloudProviderOpenstackAPI

            if cloud_details["cm_type"] == "ec2":
                provider = CloudProviderLibcloudEC2(
                    cloudname,
                    cloud_details,
                    flat=flat)
                self.provider = provider
                self.provider_class = CloudProviderLibcloudEC2

            if cloud_details["cm_type"] == "azure":
                raise ValueError("azure cloud provider yet implemented. failed.")
                TODO.implement()

        except Exception as e:
            Error.traceback(e)
Ejemplo n.º 2
0
    def construct_ip_dict(cls, ip_addr, name="kilo"):
        try:
            d = ConfigDict("cloudmesh.yaml")
            cloud_details = d["cloudmesh"]["clouds"][name]

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

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

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

        except Exception as e:
            Error.error("error in vm construct dict", traceback=True)
Ejemplo n.º 3
0
    def __init__(self, cloudname, user=None, flat=True):
        super(CloudProvider, self).__init__(cloudname, user=user)


        try:
            d = ConfigDict("cloudmesh.yaml")
            if not cloudname in d["cloudmesh"]["clouds"]:
                raise ValueError("the cloud {} is not defined in the yaml file"
                                 .format(cloudname))

            cloud_details = d["cloudmesh"]["clouds"][cloudname]

            if cloud_details["cm_type"] == "openstack":
                provider = CloudProviderOpenstackAPI(
                    cloudname,
                    cloud_details,
                    flat=flat)
                self.provider = provider
                self.provider_class = CloudProviderOpenstackAPI

            if cloud_details["cm_type"] == "ec2":
                print("ec2 cloud provider yet to be implemented")
                TODO.implement()

            if cloud_details["cm_type"] == "azure":
                print("azure cloud provider yet to be implemented")
                TODO.implement()

        except Exception, e:
            Error.traceback(e)
Ejemplo n.º 4
0
    def __init__(self, cloudname, user=None, flat=True):
        super(CloudProvider, self).__init__(cloudname, user=user)

        try:
            d = ConfigDict("cloudmesh.yaml")

            if cloudname not in d["cloudmesh"]["clouds"]:
                Console.error("the cloud {} is not defined in the yaml file. failed."
                                 .format(cloudname), traceflag=False)
                return

            cloud_details = d["cloudmesh"]["clouds"][cloudname]

            if cloud_details["cm_type"] == "openstack":
                provider = CloudProviderOpenstackAPI(
                    cloudname,
                    cloud_details,
                    flat=flat)
                self.provider = provider
                self.provider_class = CloudProviderOpenstackAPI

            if cloud_details["cm_type"] == "ec2":
                provider = CloudProviderLibcloudEC2(
                    cloudname,
                    cloud_details,
                    flat=flat)
                self.provider = provider
                self.provider_class = CloudProviderLibcloudEC2

            if cloud_details["cm_type"] == "azure":
                raise ValueError("azure cloud provider yet implemented. failed.")
                Console.TODO("Azure provider to be implemented")

        except Exception as e:
            Error.traceback(e)
Ejemplo n.º 5
0
    def construct_ip_dict(cls, ip_addr, name="kilo"):
        try:
            d = ConfigDict("cloudmesh.yaml")
            cloud_details = d["cloudmesh"]["clouds"][name]

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

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

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

        except Exception, e:
            Error.traceback(e)
Ejemplo n.º 6
0
 def _refresh():
     try:
         msg = "Refresh VMs for cloud {:}.".format(cloud)
         if Vm.refresh(cloud=cloud):
             Console.ok("{:} OK.".format(msg))
         else:
             Console.error("{:} failed".format(msg))
     except Exception as e:
         Error.traceback(e)
         Console.error("Problem running VM refresh")
Ejemplo n.º 7
0
 def _refresh():
     try:
         msg = "Refresh VMs for cloud {:}.".format(cloud)
         if Vm.refresh(cloud=cloud):
             Console.ok("{:} OK.".format(msg))
         else:
             Console.error("{:} failed".format(msg))
     except Exception as e:
         Error.traceback(e)
         Console.error("Problem running VM refresh")
Ejemplo n.º 8
0
def read_yaml_config(filename, check=True, osreplace=True, exit=True):
    """
    reads in a yaml file from the specified filename. If check is set to true
    the code will fail if the file does not exist. However if it is set to
    false and the file does not exist, None is returned.

    :param filename: the file name
    :param check: if True fails if the file does not exist,
                  if False and the file does not exist return will be None
    """
    location = filename
    if location is not None:
        location = path_expand(location)

    if not os.path.exists(location) and not check:
        return None

    if check and os.path.exists(location):

        # test for tab in yaml file
        if check_file_for_tabs(location):
            log.error("The file {0} contains tabs. yaml "
                      "Files are not allowed to contain tabs".format(location))
            sys.exit()
        result = None
        try:

            if osreplace:
                result = open(location, 'r').read()
                t = Template(result)
                result = t.substitute(os.environ)

                # data = yaml.safe_load(result)
                data = ordered_load(result, yaml.SafeLoader)
            else:
                f = open(location, "r")

                # data = yaml.safe_load(f)

                data = ordered_load(result, yaml.SafeLoader)
                f.close()

            return data
        except Exception as e:
            log.error(
                "The file {0} fails with a yaml read error".format(filename))
            Error.traceback(e)
            sys.exit()

    else:
        log.error("The file {0} does not exist.".format(filename))
        if exit:
            sys.exit()

    return None
Ejemplo n.º 9
0
def read_yaml_config(filename, check=True, osreplace=True, exit=True):
    """
    reads in a yaml file from the specified filename. If check is set to true
    the code will fail if the file does not exist. However if it is set to
    false and the file does not exist, None is returned.

    :param filename: the file name
    :param check: if True fails if the file does not exist,
                  if False and the file does not exist return will be None
    """
    location = filename
    if location is not None:
        location = path_expand(location)

    if not os.path.exists(location) and not check:
        return None

    if check and os.path.exists(location):

        # test for tab in yaml file
        if check_file_for_tabs(location):
            log.error("The file {0} contains tabs. yaml "
                      "Files are not allowed to contain tabs".format(location))
            sys.exit()
        result = None
        try:

            if osreplace:
                result = open(location, 'r').read()
                t = Template(result)
                result = t.substitute(os.environ)

                # data = yaml.safe_load(result)
                data = ordered_load(result, yaml.SafeLoader)
            else:
                f = open(location, "r")

                # data = yaml.safe_load(f)

                data = ordered_load(result, yaml.SafeLoader)
                f.close()

            return data
        except Exception as e:
            log.error(
                "The file {0} fails with a yaml read error".format(filename))
            Error.traceback(e)
            sys.exit()

    else:
        log.error("The file {0} does not exist.".format(filename))
        if exit:
            sys.exit()

    return None
Ejemplo n.º 10
0
def BatchProvider(name, user=None):
    """
    Returns a provider for a given batch system that is defined
    in the cloudmesh.yaml file. Here you find a section such as::

        hpc:
            active:
            - india
            clusters:
              india:
                cm_heading: India HPC CLuster
                cm_host: india
                cm_label: indiahpc
                cm_type: slurm
                cm_type_version: 14.11.9
                credentials:
                  username: TBD
                  project: None
                default:
                  queue: delta
                  experiment_dir: /N/u/{username}/experiment
                  prefix:
                    username: null

    You can define a new resource by copying this section under india and
    give it a name according to your cluster. Fill out the username,
    and if appropirate define a project, which is the
    account this queue is charged under

    Ussage::

      provider = BatchProvider("india")

    Additional functions are defined as it inherits from BatchProviderBase
    and the provider type which is in the above example slurm

    :param name: name of the cluster in the cloudmesh yaml file
    :param user: cloudmesh user name associated with this queue.
    :return: the provider
    """
    try:
        d = ConfigDict("cloudmesh.yaml")
        details = d["cloudmesh"]["hpc"]["clusters"][name]

        if details["cm_type"].lower() in ["slurm"]:
            return BatchProviderSLURM()
        else:
            ValueError("batch  provider not supported.")

    except Exception as e:
        Error.traceback(e)
Ejemplo n.º 11
0
    def queue(cls, cluster, format='json', job=None):
        try:
            args = 'squeue '
            if job is not None:
                if job.isdigit():
                    args += ' -j {} '.format(str(job))  # search by job id
                else:
                    args += ' -n {} '.format(job)  # search by job name
            f = '--format=%all'
            args += f
            result = Shell.ssh(cluster, args)

            # TODO: process till header is found...(Need a better way)
            l = result.splitlines()
            for i, res in enumerate(l):
                if 'ACCOUNT|GRES|' in res:
                    result = "\n".join(str(x) for x in l[i:])
                    break

            parser = TableParser(strip=True)
            d = parser.to_dict(result)

            # add cluster and updated to each entry
            for key in list(d.keys()):
                d[key]['cluster'] = cluster
                d[key]['updated'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

            if format == 'json':
                return json.dumps(d, indent=4, separators=(',', ': '))

            else:
                return (Printer.write(d,
                                      order=['cluster',
                                             'jobid',
                                             'partition',
                                             'name',
                                             'user',
                                             'st',
                                             'time',
                                             'nodes',
                                             'nodelist',
                                             'updated'],
                                      output=format))
        except Exception as e:
            Error.traceback(e)
            return e
Ejemplo n.º 12
0
    def construct_ip_dict(cls, ip_addr, name=None):
        # TODO kilo cloud as defualt should be avoided
        if name is None:
            Console.error("cloud name not set")
            return None
        try:
            d = ConfigDict("cloudmesh.yaml")
            cloud_details = d["cloudmesh"]["clouds"][name]

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

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

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

        except Exception as e:
            Error.error("error in vm construct dict", traceback=True)
Ejemplo n.º 13
0
    def construct_ip_dict(cls, ip_addr, name=None):
        # TODO kilo cloud as defualt should be avoided
        if name is None:
            Console.error("cloud name not set")
            return None
        try:
            d = ConfigDict("cloudmesh.yaml")
            cloud_details = d["cloudmesh"]["clouds"][name]

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

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

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

        except Exception as e:
            Error.error("error in vm construct dict", traceback=True)
Ejemplo n.º 14
0
    def __init__(self, cloudname, user=None, flat=True):
        super(CloudProvider, self).__init__(cloudname, user=user)

        try:
            d = ConfigDict("cloudmesh.yaml")

            if cloudname not in d["cloudmesh"]["clouds"]:
                Console.error(
                    "the cloud {} is not defined in the yaml file. failed.".
                    format(cloudname),
                    traceflag=False)
                return

            cloud_details = d["cloudmesh"]["clouds"][cloudname]

            if cloud_details["cm_type"] == "openstack":
                provider = CloudProviderOpenstackAPI(cloudname,
                                                     cloud_details,
                                                     flat=flat)
                self.provider = provider
                self.provider_class = CloudProviderOpenstackAPI

            if cloud_details["cm_type"] == "ec2":
                provider = CloudProviderLibcloudEC2(cloudname,
                                                    cloud_details,
                                                    flat=flat)
                self.provider = provider
                self.provider_class = CloudProviderLibcloudEC2

            if cloud_details["cm_type"] == "azure":
                # raise ValueError("azure cloud provider yet implemented. failed.")
                # Console.TODO("Azure provider to be implemented")
                provider = CloudProviderAzureAPI(cloudname, cloud_details)
                self.provider = provider
                self.provider_class = CloudProviderAzureAPI

        except Exception as e:
            Error.traceback(e)
Ejemplo n.º 15
0
    def do_key(self, args, arguments):
        """
        ::

           Usage:
             key  -h | --help
             key list [--source=db] [--format=FORMAT]
             key list --source=cloudmesh [--format=FORMAT]
             key list --source=ssh [--dir=DIR] [--format=FORMAT]
             key load [--format=FORMAT]
             key list --source=git [--format=FORMAT] [--username=USERNAME]
             key add --git [--name=KEYNAME] FILENAME
             key add --ssh [--name=KEYNAME]
             key add [--name=KEYNAME] FILENAME
             key get NAME
             key default [KEYNAME | --select]
             key delete (KEYNAME | --select | --all) [--force]
             key upload [KEYNAME] [--cloud=CLOUD]
             key map [--cloud=CLOUD]

           Manages the keys

           Arguments:

             SOURCE         db, ssh, all
             KEYNAME        The name of a key. For key upload it defaults to the default key name.
             FORMAT         The format of the output (table, json, yaml)
             FILENAME       The filename with full path in which the key
                            is located
             NAME_ON_CLOUD  Typically the name of the keypair on the cloud.

           Options:

              --dir=DIR                     the directory with keys [default: ~/.ssh]
              --format=FORMAT               the format of the output [default: table]
              --source=SOURCE               the source for the keys [default: db]
              --username=USERNAME           the source for the keys [default: none]
              --name=KEYNAME                The name of a key
              --all                         delete all keys
              --force                       delete the key form the cloud
              --name_on_cloud=NAME_ON_CLOUD Typically the name of the keypair on the cloud.

           Description:

           key list --source=git  [--username=USERNAME]

              lists all keys in git for the specified user. If the
              name is not specified it is read from cloudmesh.yaml

           key list --source=ssh  [--dir=DIR] [--format=FORMAT]

              lists all keys in the directory. If the directory is not
              specified the default will be ~/.ssh

           key list --source=cloudmesh  [--dir=DIR] [--format=FORMAT]

              lists all keys in cloudmesh.yaml file in the specified directory.
               dir is by default ~/.cloudmesh

           key list [--format=FORMAT]

               list the keys in teh giiven format: json, yaml,
               table. table is default

           key list

                Prints list of keys. NAME of the key can be specified

               
           key add [--name=keyname] FILENAME

               adds the key specifid by the filename to the key
               database

           key get NAME

               Retrieves the key indicated by the NAME parameter from database
               and prints its fingerprint.

           key default [NAME]

                Used to set a key from the key-list as the default key
                if NAME is given. Otherwise print the current default
                key

           key delete NAME

                deletes a key. In yaml mode it can delete only key that
                are not saved in the database

           key rename NAME NEW

                renames the key from NAME to NEW.
                
        """
        # pprint(arguments)

        def _print_dict(d, header=None, format='table'):
            if format == "json":
                return json.dumps(d, indent=4)
            elif format == "yaml":
                return yaml.dump(d, default_flow_style=False)
            elif format == "table":
                return dict_printer(d,
                                    order=["name",
                                           "comment",
                                           "uri",
                                           "fingerprint",
                                           "source"],
                                    output="table",
                                    sort_keys=True)
            else:
                return d
                # return dict_printer(d,order=['cm_id, name, fingerprint'])

        directory = Config.path_expand(arguments["--dir"])

        if arguments['list']:
            _format = arguments['--format']
            _source = arguments['--source']
            _dir = arguments['--dir']

            if arguments['--source'] == 'ssh':

                try:
                    sshm = SSHKeyManager()
                    sshm.get_from_dir(directory)
                    d = dict(sshm.__keys__)
                    print(_print_dict(d, format=_format))
                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing keys from ssh")

            elif arguments['--source'] in ['cm', 'cloudmesh']:

                try:
                    sshm = SSHKeyManager()
                    m = sshm.get_from_yaml(load_order=directory)
                    d = dict(m.__keys__)
                    print(_print_dict(d, format=_format))
                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing keys from `{:}`".format(arguments['--source']))

            elif arguments['--source'] in ['git']:

                username = arguments["--username"]
                # print(username)
                if username == 'none':
                    conf = ConfigDict("cloudmesh.yaml")
                    username = conf["cloudmesh.github.username"]

                sshm = SSHKeyManager()
                try:
                    sshm.get_from_git(username)
                    d = dict(sshm.__keys__)
                    print(_print_dict(d, format=_format))
                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing git keys from database")
                    return ""

            elif arguments['--source'] == 'db':

                try:
                    sshdb = SSHKeyDBManager()
                    d = sshdb.table_dict()
                    if d != {}:
                        print(_print_dict(d, format=arguments['--format']))
                        msg = "info. OK."
                        Console.ok(msg)
                    else:
                        Console.error("No keys in the database")
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing keys from database")

        elif arguments['load']:
            _format = arguments['--format']
            _dir = arguments['--dir']

            try:
                sshm = SSHKeyManager()
                m = sshm.get_from_yaml(load_order=directory)
                d = dict(m.__keys__)

                sshdb = SSHKeyDBManager()

                for keyname in m.__keys__:
                    filename = m[keyname]["path"]
                    try:
                        sshdb.add(filename,
                                  keyname,
                                  source="yaml",
                                  uri="file://" + filename)
                    except Exception as e:
                        Console.error("problem adding key {}:{}".format(
                            keyname, filename))

                print(_print_dict(d, format=_format))
                msg = "info. OK."
                Console.ok(msg)
            except Exception as e:
                Console.error("Problem adding keys from yaml file")

        elif arguments['get']:

            try:
                name = arguments['NAME']
                sshdb = SSHKeyDBManager()
                d = sshdb.table_dict()

                for i in d:
                    if d[i]["name"] == name:
                        key = d[i]
                        print("{:}: {:}".format(key['name'], key['fingerprint']))
                        msg = "info. OK."
                        Console.ok(msg)
                        return ""
                    else:
                        pass
                Console.error("The key is not in the database")
            except Exception as e:
                Error.traceback(e)
                Console.error("The key is not in the database")

        # key add --git KEYNAME
        #      key add --ssh KEYNAME
        #      key add [--path=PATH]  KEYNAME

        elif arguments['add'] and arguments["--git"]:

            print('git add')
            sshdb = SSHKeyDBManager()
            keyname = arguments['--name']
            gitkeyname = arguments['NAME']
            filename = arguments['FILENAME']

            # Are we adding to the database as well?
            # sshdb.add(filename, keyname, source="ssh", uri="file://"+filename)

            username = arguments["--username"]

            if username == 'none':
                conf = ConfigDict("cloudmesh.yaml")
                username = conf["cloudmesh.github.username"]
            print(username)

            sshm = SSHKeyManager()
            try:
                sshm.get_from_git(username)
                d = dict(sshm.__keys__)
                print(d)
            except Exception as e:
                Error.traceback(e)
                Console.error("Problem adding keys to git for user: "******""

            try:
                # FIXME: correct code to add to git
                d[gitkeyname]['keyname'] = keyname
                d[gitkeyname]['user'] = None
                d[gitkeyname]['source'] = 'git'
                # sshdb.add_from_dict(d[gitkeyname])
            except Exception as e:
                Console.error("The key already exists")

        elif arguments['add'] and arguments["--ssh"]:

            # print('ssh add')
            sshdb = SSHKeyDBManager()
            keyname = arguments['--name']
            filename = Config.path_expand("~/.ssh/id_rsa.pub")
            try:
                sshdb.add(filename, keyname, source="ssh", uri="file://" + filename)
                print("Key {:} successfully added to the database".format(keyname or ""))
                msg = "info. OK."
                Console.ok(msg)
            except Exception as e:
                """
                Error.traceback(e)
                print (keyname)
                print (filename)
                """
                Console.error("Problem adding the key `{}` from file `{}`".format(keyname, filename))

        elif arguments['add'] and not arguments["--git"]:

            # print('ssh add')
            sshdb = SSHKeyDBManager()
            keyname = arguments['--name']
            filename = arguments['FILENAME']
            try:
                sshdb.add(filename, keyname, source="ssh", uri="file://" + filename)
                print("Key {:} successfully added to the database".format(keyname or ""))
                msg = "info. OK."
                Console.ok(msg)

            except ValueError as e:
                Console.error("The key `{}` already exists".format(keyname), traceflag=False)
            """
            except Exception as e:
                Error.traceback(e)
                print (keyname)
                print (filename)
                Console.error("Problem adding the key `{}` from file `{}`".format(keyname, filename))
            """
            return ""

        elif arguments['default']:

            # print("default")

            if arguments['KEYNAME']:
                keyname = None
                try:
                    keyname = arguments['KEYNAME']
                    sshdb = SSHKeyDBManager()
                    sshdb.set_default(keyname)
                    Default.set_key(keyname)
                    print("Key {:} set as default".format(keyname))
                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Setting default for key {:} failed.".format(keyname))

            elif arguments['--select']:
                keyname = None
                try:
                    sshdb = SSHKeyDBManager()
                    select = sshdb.select()
                    if select != 'q':
                        keyname = select.split(':')[0]
                        print("Setting key: {:} as default.".format(keyname))
                        sshdb.set_default(keyname)
                        msg = "info. OK."
                        Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Setting default for selected key {:} failed.".format(keyname))

            else:
                try:
                    sshdb = SSHKeyDBManager()
                    d = sshdb.table_dict()

                    for i in d:
                        if d[i]["is_default"] == "True":
                            key = d[i]
                            print("{:}: {:}".format(key['name'], key['fingerprint']))
                            msg = "info. OK."
                            Console.ok(msg)
                            return ""
                        else:
                            pass
                    Console.error("The key is not in the database")
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem retrieving default key.")

        elif arguments['delete']:

            delete_on_cloud = arguments["--force"] or False
            # print ("DDD", delete_on_cloud)
            if arguments['--all']:
                try:
                    sshm = SSHKeyManager(delete_on_cloud=delete_on_cloud)
                    sshm.delete_all_keys()
                    print("All keys from the database deleted successfully.")
                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem deleting keys")
            elif arguments['--select']:
                keyname = None
                sshdb = SSHKeyDBManager()
                select = sshdb.select()
                if select != 'q':
                    try:
                        keyname = select.split(':')[0]
                        print("Deleting key: {:}...".format(keyname))
                        sshm = SSHKeyManager(delete_on_cloud=delete_on_cloud)
                        sshm.delete_key(keyname)
                        msg = "info. OK."
                        Console.ok(msg)
                    except Exception as e:
                        Error.traceback(e)
                        Console.error("Problem deleting the key `{:}`".format(keyname))
            else:
                keyname = None
                try:
                    keyname = arguments['KEYNAME']
                    sshm = SSHKeyManager(delete_on_cloud=delete_on_cloud)
                    sshm.delete_key(keyname)
                    print("Key {:} deleted successfully from database.".format(keyname))
                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem deleting the key `{:}`".format(keyname))

        elif arguments['upload']:

            try:
                #
                # get username
                #
                conf = ConfigDict("cloudmesh.yaml")
                username = conf["cloudmesh"]["profile"]["username"]
                if username in ['None', 'TBD']:
                    username = None

                #
                # get cloudnames
                #
                clouds = []
                cloud = arguments["--cloud"] or Default.get_cloud()
                if cloud == "all":
                    config = ConfigDict("cloudmesh.yaml")
                    clouds = config["cloudmesh"]["clouds"]
                else:
                    clouds.append(cloud)

                #
                # get keyname
                #

                for cloud in clouds:
                    status = 0
                    sshdb = SSHKeyDBManager()
                    sshm = SSHKeyManager()
                    keys = sshdb.find_all()
                    for keyid in keys:
                        key = keys[keyid]

                        print ("upload key {} -> {}".format(key["name"],
                                                            cloud))

                        try:
                            status = sshm.add_key_to_cloud(
                                username,
                                key["name"],
                                cloud,
                                key["name"])

                        except Exception as e:
                            print (e)
                            if "already exists" in str(e):
                                print ("key already exists. Skipping "
                                       "upload. ok.")
                        if status == 1:
                            print("Problem uploading key. failed.")
                msg = "info. OK."
                Console.ok(msg)

            except Exception as e:
                Error.traceback(e)
                Console.error("Problem adding key to cloud")

        elif arguments['map']:
            try:
                cloud = arguments["--cloud"] or Default.get_cloud()
                sshm = SSHKeyManager()
                map_dict = sshm.get_key_cloud_maps(cloud)
                print(dict_printer(map_dict,
                                   order=["user", "key_name", "cloud_name", "key_name_on_cloud"]))

            except Exception as e:
                Error.traceback(e)
                Console.error("Problem adding key to cloud")
Ejemplo n.º 16
0
def main():
    """cm.

    Usage:
      cm --help
      cm [--debug] [--nosplash] [--file=SCRIPT] [-i] [COMMAND ...]

    Arguments:
      COMMAND                  A command to be executed

    Options:
      --file=SCRIPT  -f  SCRIPT  Executes the script
      -i                 After start keep the shell interactive,
                         otherwise quit [default: False]
      --nosplash    do not show the banner [default: False]
    """

    try:
        arg = docopt(main.__doc__, help=True)
        if arg['--help']:
            print(main.__doc__)
            sys.exit()

        # fixing the help parameter parsing

        #   arguments['COMMAND'] = ['help']
        #   arguments['help'] = 'False'

        script_file = arg['--file']

    except:
        script_file = None
        interactive = False

        arguments = sys.argv[1:]
        arg = {
            '--debug': '--debug' in arguments,
            '--nosplash': '--nosplash' in arguments,
            '-i': '-i' in arguments}

        for a in arg:
            if arg[a]:
                arguments.remove(a)

        arg['COMMAND'] = [' '.join(arguments)]

    splash = not arg['--nosplash']
    debug = arg['--debug']
    interactive = arg['-i']

    context = CloudmeshContext(debug=debug,
                               splash=splash)
    cmd = CloudmeshConsole(context)

    # TODO: check if cludmesh_yaml exists and if not create it
    # also creat .cloudmesh dir if it not exists
    """
    from cloudmesh_client.common import cloudmesh_yaml

    create_cmd3_yaml_file(force=False, verbose=False)

    filename = cloudmesh_yaml
    try:
        module_config = ConfigDict(filename=filename)
        modules = module_config["cmd3"]["modules"]
        properties = module_config["cmd3"]["properties"]
    except:
        modules = ['cloudmesh_cmd3.plugins']
    for module_name in modules:
        #print ("INSTALL", module_name)
        try:
            plugins.append(dict(get_plugins_from_module(module_name)))
        except:
            # print "WARNING: could not find", module_name
            pass

    """

    # if script_file is not None:
    #     cmd.do_exec(script_file)

    if len(arg['COMMAND']) > 0:
        user_cmd = None
        try:
            user_cmd = " ".join(arg['COMMAND'])
            if debug:
                print(">", user_cmd)
            cmd.onecmd(user_cmd)
        except Exception as e:
            print("ERROR: executing command '{0}'".format(user_cmd))
            print(70 * "=")
            print(e)
            print(70 * "=")
            Error.traceback()

        if interactive:
            cmd.cmdloop()

    elif not script_file or interactive:
        cmd.cmdloop()
Ejemplo n.º 17
0
    def do_register(self, args, arguments):
        """
        ::

          Usage:
              register info
              register backup
              register new [--force] [--dryrun]
              register clean [--force]
              register list ssh [--format=FORMAT]
              register list [--yaml=FILENAME][--info][--format=FORMAT]
              register cat [--yaml=FILENAME]
              register edit [--yaml=FILENAME]
              register user [USERNAME]
              register cloud [CLOUD] [--force]
              register remote [CLOUD] [--force]
              register export HOST [--password] [--format=FORMAT]
              register source HOST
              register merge FILEPATH
              register form [--yaml=FILENAME]
              register check [--yaml=FILENAME]
              register test [--yaml=FILENAME]
              register json HOST
              register env [--provider=PROVIDER]
              register ec2 CLOUD EC2ZIP
              register ENTRY

          managing the registered clouds in the cloudmesh.yaml file.
          It looks for it in the current directory, and than in
          ~/.cloudmesh.  If the file with the cloudmesh.yaml name is
          there it will use it.  If neither location has one a new
          file will be created in ~/.cloudmesh/cloudmesh.yaml. Some
          defaults will be provided.  However you will still need to
          fill it out with valid entries.

          Arguments:

            HOST   the host name
            USER   the user name
            FILEPATH the path of the file
            CLOUD the cloud name
            PROVIDER the provider or type of cloud [Default: openstack]
            USERNAME  Username that would be registered in yaml. Defaults to OS username.

          Options:

            --provider=PROVIDER     Provider to be used for cloud. Values are:
                                    openstack, azure, ec2.
            --version=VERSION       Version of the openstack cloud.
            --openrc=OPENRC         The location of the openrc file
            --password              Prints the password
            --force                 ignore interactive questions and execute
                                    the action

          Description:

              register info
                  lists the clouds specified in the cloudmesh.yaml
                  file in the current directory, and then in ~/.cloudmesh

              register list [--yaml=FILENAME] [--name] [--info]
                  lists the clouds specified in the cloudmesh.yaml file. If
                  info is specified it also prints the location of the yaml
                  file.

              register list ssh
                  lists hosts from ~/.ssh/config

              register cat [--yaml=FILENAME]
                  outputs the cloudmesh.yaml file

              register edit [--yaml=FILENAME]
                  edits the cloudmesh.yaml file

              register export HOST [--format=FORMAT]

                    prints the contents of an openrc.sh file based on the
                    information found in the cloudmesh.yaml file.

              register remote CLOUD [--force]

                    reads the Openstack OPENRC file from a remote host that
                    is described in cloudmesh.yaml file. We assume that
                    the file has already a template for this host. If
                    not it can be created from other examples before
                    you run this command.

                    It uses the OS_OPENRC variable to locate the file and
                    copy it onto your computer.

              register merge FILENAME
                  Replaces the TBD in cloudmesh.yaml with the contents
                  present in the named file

              register form [--yaml=FILENAME]
                  interactively fills out the form wherever we find TBD.

              register check [--yaml=FILENAME]
                  checks the yaml file for completness

              register test [--yaml=FILENAME]
                  checks the yaml file and executes tests to check if
                  we can use the cloud. TODO: maybe this should be in
                  a test command

              register json host
                  displays the host details in json format

              register remote CLOUD
                  registers a remote cloud and copies the openrc file
                  specified in the credentials of the cloudmesh.yaml

              register CLOUD --dir
                  Copies the entire directory from the cloud and puts it in
                  ~/.cloudmesh/clouds/host
                  For kilo, The directory would be copied to
                  ~/.cloudmesh/clouds/kilo

              register env [--provider=PROVIDER] [HOSTNAME]
                  Reads env OS_* variables and registers a new cloud in yaml,
                  interactively. Default PROVIDER is openstack and HOSTNAME
                  is localhost.

              register user [USERNAME]
                  Sets the user in yaml with the value provided.
         """

        # from pprint import pprint
        # pprint(arguments)

        def _get_config_yaml_file(arguments):
            filename = arguments["--yaml"] or "cloudmesh.yaml"
            filename = Config.find_file(filename)
            return filename

        def exists(filename):
            return os.path.isfile(filename)

        def export(host, output):
            config = ConfigDict("cloudmesh.yaml")
            credentials = dict(
                config["cloudmesh"]["clouds"][host]["credentials"])

            if not arguments["--password"]:
                credentials["OS_PASSWORD"] = "******"

            if output is None:
                for attribute, value in credentials.items():
                    print("export {}={}".format(attribute, value))
            elif output == "table":
                print(Printer.attribute(credentials))
            else:
                print(Printer.write(credentials, output=output))
                # TODO: bug csv does not work

        if arguments["info"]:

            filename = _get_config_yaml_file(arguments)

            if os.path.isfile(filename):
                Console.ok("File '{}' exists. ok.".format(filename))

                Console.ok("The yaml file contains the following templates:")

                d = CloudRegister.list(filename,
                                       Default.cloud,
                                       info=False,
                                       output="table")
                print(d)

            else:
                Console.error("File {} does not exist".format(filename))

            return ""

        elif arguments["backup"]:

            name = backup_name("~/.cloudmesh/cloudmesh.yaml")
            configfile = path_expand("~/.cloudmesh/cloudmesh.yaml")
            print (name)
            try:
                copy(configfile, name)
                Console.ok("Bakup copy created: {}. ok.".format(name))
            except:
                Console.error("Could not create a backup copy from {}".format(configfile))

            return ""

        elif arguments["new"]:

            import shutil
            import cloudmesh_client.etc

            config = ConfigDict("cloudmesh.yaml")
            data = dotdict({
                'dir': cloudmesh_client.etc.__file__,
                'filename': os.path.join(
                    os.path.dirname(cloudmesh_client.etc.__file__),
                    "cloudmesh.yaml"),
                'yamlfile': path_expand("~/.cloudmesh/cloudmesh.yaml"),
                'dryrun': arguments['--dryrun']
            })
            Console.ok(data.filename)
            force = arguments["--force"]
            if not force:
                force = yn_choice("Would you like create a new configuration file at {}".format(data.yamlfile))
            if force:
                if not data.dryrun:
                    config.make_a_copy(location=data.yamlfile)
                    shutil.copyfile(data.filename, data.yamlfile)
                print("copy ")
                print("From: ", data.filename)
                print("To:   ", data.yamlfile)

            # filename = _get_config_yaml_file(arguments)
            # if _exists(filename):
            #    Console.ok("File '{}' exists. ok.".format(filename))
            # else:
            #    Console.error("File {} does not exist".format(filename))
            return ""

        elif arguments["clean"]:

            filename = _get_config_yaml_file(arguments)
            force = arguments["--force"] or False
            if filename is not None:
                print(filename, force)
                if exists(filename):
                    print("Delete cloudmesh.yaml file:", filename)
                    if not force:
                        force = yn_choice("Would you like to delete the "
                                          "cloudmesh.yaml file")
                        print(force)
                    if force:
                        os.remove(filename)
                        Console.ok("Deleted the file " + filename + ". ok.")
                    else:
                        Console.ok("Please use Y to delete the file.")
                    pass
                else:
                    Console.error("File {} does not exist".format(filename))
            else:
                Console.error("No cloudmesh.yaml file found.")
            return ""

        elif arguments["cat"]:

            filename = _get_config_yaml_file(arguments)
            if exists(filename):
                with open(filename, 'r') as f:
                    lines = f.read().split("\n")
                print('\n'.join(lines))
            else:
                Console.error("File {} does not exist".format(filename))
            return ""

        elif arguments["edit"]:

            filename = _get_config_yaml_file(arguments)
            if exists(filename):
                try:
                    data = {"editor": os.environ["EDITOR"],
                            "filename": filename}
                    Console.ok("editing file " + filename)
                    os.system("{editor} {filename}".format(**data))
                except:
                    Console.error("No operating system environment variable EDITOR set.", traceflag=False)
            else:
                Console.error("File {} does not exist".format(filename), traceflag=False)
            return ""

        elif arguments['list'] and arguments['ssh']:
            output = arguments['--format'] or 'table'
            hosts = CloudRegister.list_ssh()
            print(Printer.list(hosts, output=output))
            return ""

        elif arguments['list']:

            filename = _get_config_yaml_file(arguments)
            info = arguments["--info"] or False
            output = arguments["--format"] or "table"

            if not filename:
                Console.error("File {} doesn't exist".format(filename))
            else:
                d = CloudRegister.list(filename,
                                       Default.cloud,
                                       info=info,
                                       output=output)
                print(d)
            return ""

        elif arguments['check']:
            filename = _get_config_yaml_file(arguments)
            if not filename:
                Console.error("File {} doesn't exist".format(
                    arguments["--yaml"] or 'cloudmesh.yaml'))
            else:
                CloudRegister.check_yaml_for_completeness(filename)
            return ""

        elif arguments['merge']:
            filename = arguments['FILENAME']
            CloudRegister.from_file(filename)
            return ""

        elif arguments['test']:
            filename = _get_config_yaml_file(arguments)
            CloudRegister.test(filename)
            return ""

        elif arguments['form']:
            filename = _get_config_yaml_file(arguments)
            if not filename:
                Console.error("File {} doesn't exist".format(
                    arguments["--yaml"] or 'cloudmesh.yaml'))
            else:
                CloudRegister.fill_out_form(filename)
            return ""

        elif arguments['source']:

            host = arguments['HOST']
            config = ConfigDict("cloudmesh.yaml")
            credentials = dict(
                config["cloudmesh"]["clouds"][host]["credentials"])

            # unset

            variables = list(os.environ)
            for attribute in variables:
                if attribute.startswith("OS_"):
                    print("x ", attribute)
                    del os.environ[attribute]

            # set
            for attribute, value in credentials.items():
                os.putenv(attribute, value)
                print("+ ", attribute)
            export(host, "table")

            return ""

        elif arguments['export']:

            output = arguments['--format']
            host = arguments['HOST']
            try:
                variables = list(os.environ)
                for attribute in variables:
                    if attribute.startswith("OS_"):
                        print("unset ", attribute)
                        del os.environ[attribute]
                export(host, output)
            except:
                Console.error ("The export may not include all values", traceflag=False)
            return ""

        elif arguments['json']:
            host = arguments['HOST']
            result = CloudRegister.get(host)
            if result:
                print(json.dumps(result, indent=4))
            else:
                print("Cloud {:} is not described in cloudmesh.yaml".format(
                    host))
            return ""

        elif arguments['remote']:

            force = arguments['--force']
            cloud = arguments['CLOUD']

            if cloud is None:
                # clouds =  [ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["active"][0]]
                clouds = ["kilo"]  # hardcode to kilo for now

            else:
                clouds = [cloud]

            for cloud in clouds:
                CloudRegister.remote(cloud, force)
                export(cloud, "table")

            config = ConfigDict("cloudmesh.yaml")
            if config["cloudmesh.profile.user"] == "TBD":
                name = config["cloudmesh.clouds.kilo.credentials.OS_USERNAME"]
                config["cloudmesh"]["profile"]["user"] = name
                config.save()
            return ""

        elif arguments['ec2']:

            cloud = arguments['CLOUD']
            zipfile = arguments['EC2ZIP']

            if cloud is None:
                clouds = [ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["active"][0]]
            else:
                clouds = [cloud]

            for cloud in clouds:
                CloudRegister.ec2(cloud, zipfile)
                export(cloud, "table")

            return ""

        elif arguments['env']:
            try:
                CloudRegister.from_environ(arguments['--provider'])
            except Exception as e:
                Error.traceback(e)
            return ""

        elif arguments['cloud']:
            """
            if arguments['--dir']:
                cloud = arguments['--name']
                directory = arguments['--dir']
                Console.ok(directory)
                CloudRegister.directory(cloud, directory)

            else:
            """

            values_to_replace = ['tbd', 'null', 'tbd_not_used']

            cloud = arguments['CLOUD']
            if cloud is None:
                clouds = [ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["active"][0]]
            else:
                clouds = [cloud]

            for cloud in clouds:

                config = ConfigDict("cloudmesh.yaml")

                cloud_config = config["cloudmesh.clouds"][cloud]

                # Checking credentials
                print("Checking cloud credentials...")
                for prop in cloud_config["credentials"]:
                    if cloud_config["credentials"][prop].lower() in values_to_replace:
                        value = input(prop + "(" + cloud_config["credentials"][prop] + "): ")
                        cloud_config["credentials"][prop] = value
                # Checking defaults
                print("Checking cloud defaults...")
                for prop in cloud_config["default"]:
                    if cloud_config["default"][prop].lower() in values_to_replace:
                        value = input(prop + "(" + cloud_config["default"][prop] + "): ")
                        cloud_config["default"][prop] = value
                config.save()
                export(cloud, "table")
            return ""

        elif arguments['user']:
            username = arguments["USERNAME"] or getpass.getuser()
            CloudRegister.set_username(username)

            Console.ok("Setting profile user to {} in the yaml file.".format(username))

            hosts = ssh_config()

            hosts.generate(key="india", username=username, verbose=True)

            return ""

        elif arguments['ENTRY'].lower() in ['chameleon']:


            config = ConfigDict("cloudmesh.yaml")
            credentials = dotdict(config["cloudmesh.clouds.chameleon.credentials"])

            default = credentials.OS_USERNAME
            username = input("Please enter the username for {:} [{}]: ".format("chameleon",
                                                                               default))
            username = username or default

            while True:
                default = credentials.OS_PROJECT_NAME
                project = input("Please enter the project id for {:} [{}]: ".format("chameleon",
                                                                                   default))
                project = project or default

                if project.isdigit():
                    project = "CH-{}".format(project)
                    break
                else:
                    try:
                        prefix, number = project.split("-")
                        if not (prefix in ["CH"] and number.isdigit()):
                            Console.error("This is not a valid Chameleon.org cloud project", traceflag=False)
                        else:
                            break
                    except:
                        Console.error("This is not a valid Chameleon.org cloud project", traceflag=False)

            password = getpass.getpass("Please enter the password for {:}: ".format("chameleon", credentials.OS_PASSWORD))

            credentials.OS_TENENT_ID = credentials.OS_PROJECT_NAME
            credentials.OS_TENENT_NAME = credentials.OS_PROJECT_NAME
            credentials.OS_USERNAME = username
            credentials.OS_PASSWORD = password

            config.save()
            return ""

        elif arguments['ENTRY'] is not None:
            name = arguments['ENTRY']
            Register.entry(name)
            return ""
        # if all fails do a simple list

        filename = _get_config_yaml_file(arguments)
        CloudRegister.list(filename)

        pass
Ejemplo n.º 18
0
def main():
    """cm.

    Usage:
      cm --help
      cm [--echo] [--debug] [--nosplash] [-i] [COMMAND ...]

    Arguments:
      COMMAND                  A command to be executed

    Options:
      --file=SCRIPT  -f  SCRIPT  Executes the script
      -i                 After start keep the shell interactive,
                         otherwise quit [default: False]
      --nosplash    do not show the banner [default: False]
    """
    def manual():
        print(main.__doc__)

    args = sys.argv[1:]

    arguments = {
        '--echo': '--echo' in args,
        '--help': '--help' in args,
        '--debug': '--debug' in args,
        '--nosplash': '--nosplash' in args,
        '-i': '-i' in args
    }

    echo = arguments["--echo"]
    if arguments['--help']:
        manual()
        sys.exit()

    for a in args:
        if a in arguments:
            args.remove(a)

    arguments['COMMAND'] = [' '.join(args)]

    commands = arguments["COMMAND"]
    if len(commands) > 0:
        if ".cm" in commands[0]:
            arguments["SCRIPT"] = commands[0]
            commands = commands[1:]
        else:
            arguments["SCRIPT"] = None

        arguments["COMMAND"] = ' '.join(commands)
        if arguments["COMMAND"] == '':
            arguments["COMMAND"] = None

    # noinspection PySimplifyBooleanCheck
    if arguments['COMMAND'] == []:
        arguments['COMMAND'] = None

    splash = not arguments['--nosplash']
    debug = arguments['--debug']
    interactive = arguments['-i']
    script = arguments["SCRIPT"]
    command = arguments["COMMAND"]

    context = CloudmeshContext(interactive=interactive,
                               debug=debug,
                               echo=echo,
                               splash=splash)
    cmd = CloudmeshConsole(context)

    if script is not None:
        cmd.do_exec(script)

    try:
        if echo:
            print("cm>", command)
        if command is not None:
            cmd.precmd(command)
            stop = cmd.onecmd(command)
            cmd.postcmd(stop, command)
    except Exception as e:
        print("ERROR: executing command '{0}'".format(command))
        print(70 * "=")
        print(e)
        print(70 * "=")
        Error.traceback()

    if interactive or (command is None and script is None):
        cmd.cmdloop()
Ejemplo n.º 19
0
    def do_reservation(self, args, arguments):
        """
        ::

            Usage:
                reservation info --user=USER --project=PROJECT
                reservation list [--name=NAME]
                                 [--user=USER]
                                 [--project=PROJECT]
                                 [--hosts=HOSTS]
                                 [--start=TIME_START]
                                 [--end=TIME_END]
                                 [--format=FORMAT]
                reservation delete [all]
                                   [--user=USER]
                                   [--project=PROJECT]
                                   [--name=NAME]
                                   [--start=TIME_START]
                                   [--end=TIME_END]
                                   [--hosts=HOSTS]
                reservation delete --file=FILE
                reservation update --name=NAME
                                  [--start=TIME_START]
                                  [--end=TIME_END]
                                  [--user=USER]
                                  [--project=PROJECT]
                                  [--hosts=HOSTS]
                                  [--description=DESCRIPTION]
                reservation add --name=NAME
                                [--start=TIME_START]
                                [--end=TIME_END]
                                [--user=USER]
                                [--project=PROJECT]
                                [--hosts=HOSTS]
                                [--description=DESCRIPTION]
                reservation add --file=FILE

            Arguments:

                NAME            Name of the reservation
                USER            Registration will be done for this user
                PROJECT         Project to be used
                HOSTS           Hosts to reserve
                TIME_START      Start time of reservation
                TIME_END        End time of reservation
                FORMAT          Format of output
                DESCRIPTION     Description for reservation
                FILE            File that contains reservation data to be added/ deleted

            Options:

                --name=NAME           Names of the reservation
                --user=USER           user name
                --project=PROJECT     project id
                --start=TIME_START    Start time of the reservation, in
                                      MM/DD/YYYY at hh:mm aa format. (default value: 01/01/1901 at 12:00 am])
                --end=TIME_END        End time of the reservation, in
                                      MM/DD/YYYY at hh:mm aa format. (default value: 12/31/2100 at 11:59 pm])
                --host=HOSTS          host name
                --description=DESCRIPTION  description summary of the reservation
                --file=FILE           Adding multiple reservations from one file
                --format=FORMAT       Format is either table, json, yaml or csv
                                      [default: table]

            Description:

                reservation info
                    lists the resources that support reservation for
                    a given user or project.
        """

        # print (arguments)
        def _print_dict(d, header=None, format='table'):
            if format == "json":
                return json.dumps(d, indent=4)
            elif format == "yaml":
                return pyaml.dump(d)
            elif format == "table":
                return dict_printer(d,
                                    order=["id",
                                           "name",
                                           "start_time",
                                           "end_time",
                                           "user",
                                           "project",
                                           "hosts",
                                           "description",
                                           "cloud"],
                                    output="table",
                                    sort_keys=True)
            elif format == "csv":
                TODO.implement()
            else:
                return d
                # return dict_printer(d,order=['cm_id, name, fingerprint'])

        def _get_db_date_format(date):
            """
            Utility Function that accepts instance of Date object and returns a string with Datetime for DB.
            :param date: Date object
            :return: Date as string with format expected in DB.
            """
            db_date = "{:}-{:}-{:} {:}:{:}".format(str(date.month).zfill(2),
                                                   str(date.day).zfill(2),
                                                   str(date.year).zfill(4),
                                                   str(date.hour).zfill(2),
                                                   str(date.minute).zfill(2))
            return db_date

        if arguments["info"]:

            TODO.implement()

        elif arguments["list"]:

            try:
                _name = arguments['--name']
                _user = arguments['--user']
                _project = arguments['--project']
                _format = arguments['--format']
                _hosts = arguments['--hosts']
                _start = arguments['--start']
                _end = arguments['--end']
                _format = arguments['--format']

                reserve = Reservation()
                dictionary = reserve.list(_name, _start, _end, _user, _project,
                                          _hosts)
                print(_print_dict(dictionary, format=_format))
                msg = "info. OK."
                Console.ok(msg)

            except Exception as e:
                Error.traceback(e)
                Console.error("Problem listing reservations")

        elif arguments["delete"]:
            if arguments["all"]:

                try:
                    reserve = Reservation()
                    reserve.delete()
                    msg = "info. OK."
                    Console.ok(msg)

                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem deleting all reservations")

            else:
                try:
                    _name = arguments['--name']
                    _user = arguments['--user']
                    _project = arguments['--project']
                    _format = arguments['--format']
                    _hosts = arguments['--hosts']
                    _start = arguments['--start']
                    _end = arguments['--end']
                    _format = arguments['--format']

                    reserve = Reservation()
                    reserve.delete(_name, _start, _end, _user, _project,
                                   _hosts)
                    msg = "info. OK."
                    Console.ok(msg)

                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem deleting reservations")

        elif arguments["add"]:

            if arguments["--file"] is None:
                name = None
                try:
                    name = arguments["--name"]
                    hosts = arguments["--hosts"]
                    user = arguments["--user"]
                    project = arguments["--project"]
                    description = arguments["--description"]

                    start_time = arguments["--start"] or "01/01/1901 at 07:30 pm"
                    end_time = arguments["--end"] or "12/31/2100 at 11:59 pm"

                    stime = Date(start_time)
                    etime = Date(end_time)

                    reserve = Reservation()
                    reserve.add(name, _get_db_date_format(stime),
                                _get_db_date_format(etime), hosts=hosts,
                                user=user,
                                project=project, description=description)

                    print("Reservation {:} added successfully".format(name))
                    msg = "info. OK."
                    Console.ok(msg)

                except Exception as e:
                    Error.traceback(e)
                    Console.error(
                        "Problem adding reservation {:}".format(name))

            else:
                try:
                    TODO.implement()
                    """
                    with open(os.path.join(sys.path[0], arguments["--file"])) as file:
                        reader = csv.reader(file)
                        for row in reader:
                            reservations = Reservation(cm_id=row[0],
                                                    label=row[1],
                                                    user=row[2],
                                                    project=row[3],
                                                    start_time=row[4],
                                                    end_time=row[5],
                                                    host=row[6],
                                                    summary=row[7])
                            db.add()
                    """
                except Exception as e:
                    print("Error in adding from file. ", e)

        elif arguments["update"]:
            name = None
            try:
                name = arguments["--name"]
                hosts = arguments["--hosts"]
                user = arguments["--user"]
                project = arguments["--project"]
                description = arguments["--description"]

                start_time = arguments["--start"] or "01/01/1901 at 07:30 pm"
                end_time = arguments["--end"] or "12/31/2100 at 11:59 pm"

                stime = Date(start_time)
                etime = Date(end_time)

                reserve = Reservation()
                reserve.update(name,
                               _get_db_date_format(stime),
                               _get_db_date_format(etime),
                               hosts=hosts,
                               user=user,
                               project=project,
                               description=description)

                print("Reservation {:} updated successfully".format(name))
                msg = "info. OK."
                Console.ok(msg)

            except Exception as e:
                Error.traceback(e)
                Console.error("Problem updating reservation {:}".format(name))

        return ""
Ejemplo n.º 20
0
    def do_vm(self, args, arguments):
        """
        ::

            Usage:
                vm default [--cloud=CLOUD][--format=FORMAT]
                vm refresh [--cloud=CLOUD]
                vm boot [--name=NAME]
                        [--cloud=CLOUD]
                        [--image=IMAGE_OR_ID]
                        [--flavor=FLAVOR_OR_ID]
                        [--group=GROUP]
                        [--secgroup=SECGROUP]
                        [--key=KEY]
                        [--dryrun]
                vm start [NAME]...
                         [--group=GROUP]
                         [--cloud=CLOUD]
                         [--force]
                vm stop [NAME]...
                        [--group=GROUP]
                        [--cloud=CLOUD]
                        [--force]
                vm delete [NAME]...
                          [--group=GROUP]
                          [--cloud=CLOUD]
                          [--force]
                vm ip assign [NAME]...
                          [--cloud=CLOUD]
                vm ip show [NAME]...
                           [--group=GROUP]
                           [--cloud=CLOUD]
                           [--format=FORMAT]
                           [--refresh]
                vm login [NAME] [--user=USER]
                         [--ip=IP]
                         [--cloud=CLOUD]
                         [--key=KEY]
                         [--command=COMMAND]
                vm rename [NAME]...
                          [--new=NEWNAME]
                          [--cloud=CLOUD]
                vm list [NAME_OR_ID]
                        [--cloud=CLOUD|--all]
                        [--group=GROUP]
                        [--format=FORMAT]
                        [--refresh]
                vm status [--cloud=CLOUD]
                vm info [--cloud=CLOUD]
                        [--format=FORMAT]

            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.
                NAME_OR_ID     server name or ID
                KEYPAIR_NAME   Name of the openstack keypair to be used to create VM. Note this is not a path to key.
                NEWNAME        New name of the VM while renaming.

            Options:
                --ip=IP          give the public ip of the server
                --cloud=CLOUD    give a cloud to work on, if not given, selected
                                 or default cloud will be used
                --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_OR_ID  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_OR_ID    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          delete vms without user's confirmation
                --command=COMMAND
                                 specify the commands to be executed
                --new=NEWNAME    Specify the new name for a VM while renaming.
                                 By default, this will be set to <username>-<count> format.



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

                vm default [options...]     Displays default parameters that are set for VM boot.
                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 login [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']

        """

        def _print_dict(d, header=None, format='table'):
            if format == "json":
                return json.dumps(d, indent=4)
            elif format == "yaml":
                return pyaml.dump(d)
            elif format == "table":
                return dict_printer(d,
                                    order=["id",
                                           "name",
                                           "status"],
                                    output="table",
                                    sort_keys=True)
            else:
                return d

        def _print_dict_ip(d, header=None, format='table'):
            if format == "json":
                return json.dumps(d, indent=4)
            elif format == "yaml":
                return pyaml.dump(d)
            elif format == "table":
                return dict_printer(d,
                                    order=["network",
                                           "version",
                                           "addr"],
                                    output="table",
                                    sort_keys=True)
            else:
                return d

        """
        def list_vms_on_cloud(cloud="kilo", group=None, format="table"):

            Utility reusable function to list vms on the cloud.
            :param cloud:
            :param group:
            :param format:
            :return:

            _cloud = cloud
            _group = group
            _format = format

            cloud_provider = CloudProvider(_cloud).provider
            servers = cloud_provider.list_vm(_cloud)


            server_list = {}
            index = 0
            # TODO: Improve the implementation to display more fields if required.
            for server in servers:
                server_list[index] = {}
                server_list[index]["name"] = server.name
                server_list[index]["id"] = server.id
                server_list[index]["status"] = server.status
                index += 1


            # TODO: Get this printed in a table
            print("Print table")
            dict_printer(servers, output=_format)
        """

        # pprint(arguments)

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

        cloud = arguments["--cloud"] or Default.get_cloud()

        if arguments["boot"]:
            name = None
            try:
                name = arguments["--name"]
                is_name_provided = True

                if name is None:
                    is_name_provided = False

                    count = Counter.get()
                    prefix = Username()

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

                    # BUG THE Z FILL SHOULD BE detected from yaml file
                    name = prefix + "-" + str(count).zfill(3)

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

                image = arguments["--image"] or Default.get("image",
                                                            category=cloud)
                # if default image not set, return error
                if not image:
                    Console.error("Default image not set.")
                    return ""

                flavor = arguments["--flavor"] or Default.get("flavor",
                                                              category=cloud)
                # if default flavor not set, return error
                if not flavor:
                    Console.error("Default flavor not set.")
                    return ""

                group = arguments["--group"] or Default.get_group()

                # if default group not set, return error
                if not group:
                    group = "default"
                    Default.set_group(group)

                secgroup = arguments["--secgroup"] or Default.get(
                    "secgroup", category=cloud)
                # print("SecurityGrp : {:}".format(secgroup))
                secgroup_list = ["default"]
                if secgroup is not None:
                    secgroup_list.append(secgroup)

                key_name = arguments["--key"] or Default.get_key()
                # if default keypair not set, return error
                if not key_name:
                    Console.error("Default key not set.")
                    return ""

                if arguments["--dryrun"]:

                    data = {
                        "cloud": cloud,
                        "name": name,
                        "image": image,
                        "flavor": flavor,
                        "key_name": key_name,
                        "secgroup_list": secgroup_list,
                        "group": group
                    }
                    print (attribute_printer(data, output="table"))
                    msg = "dryrun info. OK."
                    Console.ok(msg)
                else:
                    vm_id = Vm.boot(cloud=cloud,
                                    name=name,
                                    image=image,
                                    flavor=flavor,
                                    key_name=key_name,
                                    secgroup_list=secgroup_list)
                    Default.set("last_vm_id", vm_id)
                    Default.set("last_vm_name", name)

                    # SHOULD WE NOT DO THIS BY DEFAULT EVEN IF WE SPECIFY THE NAME?
                    if is_name_provided is False:
                        # Incrementing count
                        Counter.incr()

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

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

            except Exception as e:
                Error.traceback(e)
                Console.error("Problem booting instance {:}".format(name))

        elif arguments["default"]:
            try:
                count = Counter.get()
                prefix = Username()

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

                vm_name = prefix + "-" + str(count).zfill(3)
                data = {"name": vm_name,
                        "cloud": arguments["--cloud"] or Default.get_cloud()}
                for attribute in ["image", "flavor", "key", "login_key", "group", "secgroup"]:
                    data[attribute] = Default.get(attribute, category=cloud)
                output_format = arguments["--format"] or "table"
                print (attribute_printer(data, output=output_format))
                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")

        elif arguments["status"]:
            try:
                cloud_provider = CloudProvider(cloud).provider
                vm_list = cloud_provider.list_vm(cloud)
                print("Status of VM {} is {}".format(vm_list[0]["name"], vm_list[0]["status"]))
                msg = "info. OK."
                Console.ok(msg)
            except Exception as e:
                Error.traceback(e)
                Console.error("Problem retrieving status of the VM")

        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 (attribute_printer(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")

        elif arguments["start"]:
            try:
                servers = arguments["NAME"]

                # If names not provided, take the last vm from DB.
                if servers is None or len(servers) == 0:
                    last_vm = Vm.get_last_vm(cloud=cloud)
                    if last_vm is None:
                        Console.error("No VM records in database. Please run vm refresh.")
                        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.")
                    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")

        elif arguments["stop"]:
            try:
                servers = arguments["NAME"]

                # If names not provided, take the last vm from DB.
                if servers is None or len(servers) == 0:
                    last_vm = Vm.get_last_vm(cloud=cloud)
                    if last_vm is None:
                        Console.error("No VM records in database. Please run vm refresh.")
                        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.")
                    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")

        elif arguments["refresh"]:

            _refresh()

        elif arguments["delete"]:
            try:
                servers = arguments["NAME"]

                # If names not provided, take the last vm from DB.
                if servers is None or len(servers) == 0:
                    last_vm = Vm.get_last_vm(cloud=cloud)
                    if last_vm is None:
                        Console.error("No VM records in database. Please run vm refresh.")
                        return ""
                    name = last_vm["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.")
                    return ""

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

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

        elif arguments["ip"] and arguments["assign"]:
            vmids = arguments["NAME"]

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

            # if default cloud not set, return error
            if not cloud:
                Console.error("Default cloud not set.")
                return ""
            try:
                cloud_provider = CloudProvider(cloud).provider
                for sname in vmids:
                    floating_ip = cloud_provider.create_assign_floating_ip(
                        sname)
                    if floating_ip is not None:
                        print(
                            "Floating IP assigned to {:} successfully and it is: {:}".format(
                                sname, floating_ip))
                msg = "info. OK."
                Console.ok(msg)
            except Exception as e:
                Error.traceback(e)
                Console.error("Problem assigning floating ips.")

        elif arguments["ip"] and arguments["show"]:
            vmids = arguments["NAME"]

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

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

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

            try:
                cloud_provider = CloudProvider(cloud).provider
                for server in vmids:
                    ip_addr = cloud_provider.get_ips(server)

                    ipaddr_dict = Vm.construct_ip_dict(ip_addr, cloud)

                    print(
                        "IP Addresses of instance {:} are as follows:-".format(
                            server))
                    print(_print_dict_ip(ipaddr_dict, format=output_format))
                msg = "info. OK."
                Console.ok(msg)
            except Exception as e:
                Error.traceback(e)
                Console.error(
                    "Problem getting ip addresses for instance {:}".format(id))

        elif arguments["login"]:
            vm_names = arguments["NAME"]

            # If names not provided, take the last vm from DB.
            if vm_names is None or len(vm_names) == 0:
                last_vm = Vm.get_last_vm(cloud=cloud)
                if last_vm is None:
                    Console.error("No VM records in database. Please run vm refresh.")
                    return ""
                name = last_vm["name"]
            else:
                name = vm_names[0]

            print("Logging in into {:} machine...".format(name))

            user = arguments["--user"]

            # Get user if user argument not specified.
            if user is None:
                user_from_db = Vm.get_vm_login_user(name, cloud)
                user_suggest = user_from_db or getpass.getuser()
                user = input("Enter the user to login (Default: {}):".format(user_suggest)) or user_suggest
                Vm.set_vm_login_user(name, cloud, user)

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

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

            key = arguments["--key"] or Default.get("login_key",
                                                    category=cloud)
            if not key:
                Console.error("Default login_key not set.")
                return ""

            cloud_provider = CloudProvider(cloud).provider
            # print("Name : {:}".format(name))
            ip_addr = cloud_provider.get_ips(name)

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

            if ip is not None:
                if ip not in ip_addresses:
                    print(
                        "ERROR: IP Address specified does not match with the host.")
                    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:
                        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("SORRY. Unable to connect to the machine")
                return ""
            else:
                print("IP to be used is: {:}".format(ip))

            SecGroup.enable_ssh(cloud=cloud)
            # print("COMMANDS : {:}".format(commands))

            # Constructing the ssh command to connect to the machine.
            sshcommand = "ssh"
            if key is not None:
                sshcommand += " -i {:}".format(key)
            sshcommand += " -o StrictHostKeyChecking=no"
            sshcommand += " {:}@{:}".format(user, ip)
            if commands is not None:
                sshcommand += " \"{:}\"".format(commands)

            # print(sshcommand)
            os.system(sshcommand)

        elif arguments["list"]:

            if arguments["--all"]:
                try:
                    _format = arguments["--format"] or "table"
                    d = ConfigDict("cloudmesh.yaml")
                    for cloud in d["cloudmesh"]["clouds"]:

                        if arguments["--refresh"] or Default.refresh():
                            _refresh()

                        print("Listing VMs on Cloud: {:}".format(cloud))
                        result = Vm.list(cloud=cloud, output_format=_format)
                        if result is not None:
                            print(result)
                        else:
                            print("Sorry. No data found with requested parameters in DB.")
                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing all instances")
            else:

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

                try:
                    name_or_id = arguments["NAME_OR_ID"]
                    group = arguments["--group"]
                    _format = arguments["--format"] or "table"

                    # list_vms_on_cloud(cloud, group, _format)
                    if arguments["--refresh"] or Default.refresh():
                        _refresh()

                    result = Vm.list(name_or_id=name_or_id, cloud=cloud, output_format=_format)

                    if result is not None:
                        print(result)
                    else:
                        print("No data found with the requested parameters.")

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

                except Exception as e:
                    Error.traceback(e)
                    Console.error(
                        "Problem listing instances on cloud {:}".format(cloud))

        elif arguments["rename"]:
            try:
                servers = arguments["NAME"]

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

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

                new_name = arguments["--new"]
                is_name_provided = True

                # If the new name is not provided, make the new new name in format username-count.
                if new_name is None or len(new_name) == 0:

                    is_name_provided = False

                    count = Counter.get()
                    prefix = Username()

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

                    # BUG THE Z FILL SHOULD BE detected from yaml file
                    new_name = prefix + "-" + str(count).zfill(3)

                Vm.rename(cloud=cloud, servers=servers, new_name=new_name)

                if is_name_provided is False:
                    # Incrementing count
                    Counter.incr()

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

        return ""
Ejemplo n.º 21
0
    def do_key(self, args, arguments):
        """
        ::

           Usage:
             key  -h | --help
             key list --cloud=CLOUD
             key list --source=db [--format=FORMAT]
             key list --source=yaml [--format=FORMAT]
             key list --source=ssh [--dir=DIR] [--format=FORMAT]
             key list --source=git [--format=FORMAT] [--username=USERNAME]
             key list
             key load [--format=FORMAT]
             key add [NAME] [--source=FILENAME]
             key add [NAME] [--git]
             key add [NAME] [--ssh]
             key get NAME
             key default --select
             key delete (NAME | --select | --all)
             key delete NAME --cloud=CLOUD
             key upload [NAME] [--cloud=CLOUD]
             key upload [NAME] --active

           Manages the keys

           Arguments:

             CLOUD          The cloud
             NAME           The name of the key.
             SOURCE         db, ssh, all
             KEYNAME        The name of a key. For key upload it defaults to the default key name.
             FORMAT         The format of the output (table, json, yaml)
             FILENAME       The filename with full path in which the key
                            is located
             NAME_ON_CLOUD  Typically the name of the keypair on the cloud.

           Options:

              --dir=DIR                     the directory with keys [default: ~/.ssh]
              --format=FORMAT               the format of the output [default: table]
              --source=SOURCE               the source for the keys [default: db]
              --username=USERNAME           the source for the keys [default: none]
              --name=KEYNAME                The name of a key
              --all                         delete all keys
              --force                       delete the key form the cloud
              --name_on_cloud=NAME_ON_CLOUD Typically the name of the keypair on the cloud.

           Description:

           key list --source=git  [--username=USERNAME]

              lists all keys in git for the specified user. If the
              name is not specified it is read from cloudmesh.yaml

           key list --source=ssh  [--dir=DIR] [--format=FORMAT]

              lists all keys in the directory. If the directory is not
              specified the default will be ~/.ssh

           key list --source=yaml  [--dir=DIR] [--format=FORMAT]

              lists all keys in cloudmesh.yaml file in the specified directory.
               dir is by default ~/.cloudmesh

           key list [--format=FORMAT]

               list the keys in the giiven format: json, yaml,
               table. table is default

           key list

                Prints list of keys. NAME of the key can be specified

               
           key add [--name=keyname] FILENAME

               adds the key specifid by the filename to the key
               database

           key get NAME

               Retrieves the key indicated by the NAME parameter from database
               and prints its fingerprint.

           key default --select

                Select the default key interactively

           key delete NAME

                deletes a key. In yaml mode it can delete only key that
                are not saved in the database

           key rename NAME NEW

                renames the key from NAME to NEW.
                
        """
        # pprint(arguments)

        invalid_names = ['tbd', 'none', "", 'id_rsa']

        def _print_dict(d, header=None, format='table'):
            msg = Printer.write(d,
                                 order=["name",
                                        "comment",
                                        "uri",
                                        "fingerprint",
                                        "source"],
                                 output=format,
                                 sort_keys=True)
            if msg is None:
                Console.error("No keys found.", traceflag=False)
                return None
            else:
                return msg

        directory = Config.path_expand(arguments["--dir"])

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

        if arguments['list']:
            _format = arguments['--format']
            _source = arguments['--source']
            _dir = arguments['--dir']

            if "--source" not in arguments and "--cloud" not in arguments:
                arguments["--source"] = 'db'


            if arguments['--cloud']:

                    #
                    # get key list from openstack cloud
                    #
                    #keys = Key.list(cloud, output=_format)

                    #keys = Key.list_on_cloud(cloud, live=True, format=_format)
                    keys = Key.get_from_cloud(cloud, live=True, format=_format)
                    if keys is None:
                        Console.ok("The Key list is empty")
                    else:
                        print(Printer.write(keys,
                            order=["name",
                                "fingerprint"],
                            output=_format or "table"))
                    return ""

            elif arguments['--source'] == 'ssh':

                try:
                    #sshm = SSHKeyManager()
                    d = Key.get_from_dir(directory, store=False)

                    #print("SSS", type(Key.__keys__))
                    #d = dict(Key.all())
                    #print(d)
                    print(Printer.write(d,
                                        order=["name",
                                               "comment",
                                               "uri",
                                               "fingerprint",
                                               "source"],
                                        output="table"))

                    # d = dict(sshm.__keys__)

                    # print(_print_dict(d, format=_format))
                    msg = "info. OK."
                    Console.ok(msg)
                    return ""
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing keys from ssh")

            elif arguments['--source'] in ['cm', 'cloudmesh', 'yaml']:

                try:
                    #sshm = SSHKeyManager()
                    d = Key.get_from_yaml(load_order=directory, store=False)

                    print(Printer.write(d,
                                        order=["name",
                                               "comment",
                                               "uri",
                                               "fingerprint",
                                               "source"],
                                        output=_format))
                    return ""
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing keys from `{:}`".format(arguments['--source']))

            elif arguments['--source'] in ['git']:

                username = arguments["--username"]
                # print(username)
                if username == 'none':
                    conf = ConfigDict("cloudmesh.yaml")
                    username = conf["cloudmesh.github.username"]

                #sshm = SSHKeyManager()
                try:

                    d = Key.get_from_git(username, store=False)

                    print(Printer.write(d,
                                        order=["name",
                                               "comment",
                                               "uri",
                                               "fingerprint",
                                               "source"],
                                        output=_format))

                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing git keys from database")
                    return ""

            elif arguments['--source'] == 'db':

                try:
                    #sshdb = SSHKeyDBManager()
                    d = Key.all(output='dict')

                    if d is not None or d != []:

                        print(Printer.write(d,
                                            order=["name",
                                                   "comment",
                                                   "uri",
                                                   "fingerprint",
                                                   "source"],
                                            output=_format))

                        # print(_print_dict(d, output=arguments['--format']))
                        msg = "info. OK."
                        Console.ok(msg)
                    else:
                        Console.error("No keys in the database")
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing keys from database")



        elif arguments['get']:

            try:
                name = arguments['NAME']
                #sshdb = SSHKeyDBManager()
                d = Key.all(output="dict")

                for key in d:
                    if key["name"] == name:
                        print("{:}: {:}".format(key['name'], key['fingerprint']))
                        msg = "info. OK."
                        Console.ok(msg)
                        return ""
                    else:
                        pass
                Console.error("The key is not in the database")
            except Exception as e:
                Error.traceback(e)
                Console.error("The key is not in the database")

        # key add [NAME] [--source=FILENAME]
        #     key add [NAME] [--git]

        elif arguments['add'] and arguments["--git"]:

            # Console.error("This feature is not yet implemented", traceflag=False)
            # return ""

            print('git add')
            #sshdb = SSHKeyDBManager()

            data = dotdict(arguments)

            keyname = data.NAME

            #
            # get name
            #
            conf = ConfigDict("cloudmesh.yaml")
            data.username = conf["cloudmesh.github.username"]
            data.name = arguments['NAME'] or data.username

            #
            # get git username
            #
            data.username = ConfigDict("cloudmesh.yaml")["cloudmesh.github.username"]

            if str(data.name).lower() in invalid_names:
                Console.error("The github user name is not set in the yaml file", traceflag=False)
                return ""

            try:
                Console.msg("Retrieving github ssh keys for user {username}".format(**data))
                #sshm = SSHKeyManager()
                Key.get_from_git(data.username)
                d = Key.all()
                # pprint(d)
            except Exception as e:
                Console.error("Problem adding keys to git for user: {username}".format(**data))
                return ""

            for key in d:
                if key is not None:
                    key["name"] = key["name"].replace("-", "_")
                    key["source"] = "git"
                    key["user"] = data.name
                    try:
                        o = dict(key)
                        o['value'] = key["string"]
                        Key.add_from_dict(key)
                    except Exception as e:
                        Console.error("The key {name} with that finger print already exists".format(**key),
                                      traceflag=False)

        elif arguments['add'] and not arguments["--git"]:

            #     key add [NAME] [--source=FILENAME]
            #     key add [NAME] [--git]

            #sshdb = SSHKeyDBManager()

            data = dotdict()

            #
            # get name
            #
            conf = ConfigDict("cloudmesh.yaml")
            data.username = conf["cloudmesh.profile.user"]
            data.name = arguments['NAME'] or data.username

            data.filename = arguments['--source']
            if data.filename == "db" or data.filename is None:
                data.filename = Config.path_expand("~/.ssh/id_rsa.pub")

            if str(data.name).lower() in invalid_names:
                msg = ("Your choice of keyname {name} is insufficient. \n"
                       "You must be chosing a keyname that is distingct on all clouds. \n"
                       "Possible choices are your gmail name, your XSEDE name, or \n"
                       "some name that is uniqe. "
                       "Best is also to set this name in \n"
                       "cloudmesh.profile.user as "
                       "part of your \n~/cloudmesh/cloudmesh.yaml file.")
                Console.error(msg.format(**data), traceflag=False)
                return ""

            try:
                Key.add_from_path(data.filename,
                                    data.name,
                                    source="ssh",
                                    uri="file://" + data.filename)
                print("Key {name} successfully added to the database".format(**data))
                msg = "info. OK."
                Console.ok(msg)

            except ValueError as e:
                Console.error("A key with this fingerprint already exists".format(**data), traceflag=False)
                Console.msg("Please use check with: key list")

            return ""

        elif arguments['default']:

            # print("default")

            if arguments['--select']:
                keyname = None
                try:
                    #sshdb = SSHKeyDBManager()
                    select = Key.select()
                    if select != 'q':
                        keyname = select.split(':')[0]
                        print("Setting key: {:} as default.".format(keyname))
                        Default.key = keyname
                        msg = "info. OK."
                        Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Setting default for selected key {:} failed.".format(keyname))

            else:
                try:
                    #sshdb = SSHKeyDBManager()
                    d = Key.table_dict()

                    for i in d:
                        if d[i]["is_default"] == "True":
                            key = d[i]
                            print("{:}: {:}".format(key['name'], key['fingerprint']))
                            msg = "info. OK."
                            Console.ok(msg)
                            return ""
                        else:
                            pass
                    Console.error("The key is not in the database")
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem retrieving default key.")

        elif arguments['delete'] and arguments["--cloud"]:

            key = dotdict({
                'cloud': arguments["--cloud"],
                'name': arguments["NAME"]
            })
            try:
                Key.delete(key.name, key.cloud)
                msg = "info. OK."
                Console.ok(msg)
            except:
                Console.error("Problem deleting the key {name} on the cloud {cloud}".format(**key))

        elif arguments['delete']:

            # key delete (NAME | --select| --all)

            data = dotdict({
                'all': arguments['--all'] or False,
                'select': arguments['--select'] or False,
                'name': arguments['NAME'] or False,
            })


            pprint(data)
            # BUG delete all is not properly implemented

            if data.all:
                Console.TODO("Delete --all is not yet implemented.")
                # Key.delete()
            elif data.select:
                key = Key.select()
                print (key)

            else: # name
                Key.delete(data.name)


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

        elif arguments['upload']:

            # pprint(arguments)

            try:
                #
                # get username
                #
                conf = ConfigDict("cloudmesh.yaml")
                username = conf["cloudmesh"]["profile"]["user"]
                if username in ['None', 'TBD']:
                    username = None

                #
                # get cloudnames
                #
                clouds = []

                if arguments["--active"]:
                    cloud = 'active'
                else:
                    cloud = arguments["--cloud"] or Default.cloud

                if cloud == "all":
                    config = ConfigDict("cloudmesh.yaml")
                    clouds = config["cloudmesh"]["clouds"]
                elif cloud == 'active':
                    config = ConfigDict("cloudmesh.yaml")
                    clouds = config["cloudmesh"]["active"]
                else:
                    clouds.append(cloud)

                #
                # get keyname
                #

                for cloud in clouds:
                    status = 0
                    #sshdb = SSHKeyDBManager()
                    #sshm = SSHKeyManager()
                    keys = Key.all()
                    for key in keys:

                        print("upload key {} -> {}".format(key["name"],
                                                           cloud))

                        try:
                            status = Key.add_key_to_cloud(
                                username,
                                key["name"],
                                cloud)

                        except Exception as e:
                            Console.error("problem")
                            if "already exists" in str(e):
                                print("key already exists. Skipping upload. OK.")
                        if status == 1:
                            print("Problem uploading key {} to {}. failed.".format(key["name"],
                                                                                   cloud))

            except Exception as e:
                Console.error("Problem adding key to cloud")
Ejemplo n.º 22
0
    def do_register(self, args, arguments):
        """
        ::

          Usage:
              register info
              register new
              register clean [--force]
              register list ssh [--format=FORMAT]
              register list [--yaml=FILENAME][--info][--format=FORMAT]
              register cat [--yaml=FILENAME]
              register edit [--yaml=FILENAME]
              register export HOST [--password] [--format=FORMAT]
              register source HOST
              register merge FILEPATH
              register form [--yaml=FILENAME]
              register check [--yaml=FILENAME]
              register test [--yaml=FILENAME]
              register json HOST
              register remote [CLOUD] [--force]
              register env [--provider=PROVIDER]
              register profile --username=[USERNAME]
              register yaml ENTRY
              register CLOUD [--force]
              register CLOUD [--dir=DIR]
              register ec2 CLOUD EC2ZIP

          managing the registered clouds in the cloudmesh.yaml file.
          It looks for it in the current directory, and than in
          ~/.cloudmesh.  If the file with the cloudmesh.yaml name is
          there it will use it.  If neither location has one a new
          file will be created in ~/.cloudmesh/cloudmesh.yaml. Some
          defaults will be provided.  However you will still need to
          fill it out with valid entries.

          Arguments:

            HOST   the host name
            USER   the user name
            FILEPATH the path of the file
            CLOUD the cloud name
            PROVIDER the provider or type of cloud [Default: openstack]
            USERNAME  Username that would be registered in yaml. Defaults to OS username.

          Options:

            --provider=PROVIDER     Provider to be used for cloud. Values are:
                                    openstack, azure, ec2.
            --version=VERSION       Version of the openstack cloud.
            --openrc=OPENRC         The location of the openrc file
            --password              Prints the password
            --force                 ignore interactive questions and execute
                                    the action

          Description:

              register info
                  It looks out for the cloudmesh.yaml file in the current
                  directory, and then in ~/.cloudmesh

              register list [--yaml=FILENAME] [--name] [--info]
                  lists the clouds specified in the cloudmesh.yaml file. If
                  info is specified it also prints the location of the yaml
                  file.

              register list ssh
                  lists hosts from ~/.ssh/config

              register cat [--yaml=FILENAME]
                  outputs the cloudmesh.yaml file

              register edit [--yaml=FILENAME]
                  edits the cloudmesh.yaml file

              register export HOST [--format=FORMAT]

                    prints the contents of an openrc.sh file based on the
                    information found in the cloudmesh.yaml file.

              register remote CLOUD [--force]

                    reads the Openstack OPENRC file from a remote host that
                    is described in cloudmesh.yaml file. We assume that
                    the file has already a template for this host. If
                    not it can be created from other examples before
                    you run this command.

                    It uses the OS_OPENRC variable to locate the file and
                    copy it onto your computer.

              register merge FILENAME
                  Replaces the TBD in cloudmesh.yaml with the contents
                  present in the named file

              register form [--yaml=FILENAME]
                  interactively fills out the form wherever we find TBD.

              register check [--yaml=FILENAME]
                  checks the yaml file for completness

              register test [--yaml=FILENAME]
                  checks the yaml file and executes tests to check if
                  we can use the cloud. TODO: maybe this should be in
                  a test command

              register json host
                  displays the host details in json format

              register remote CLOUD
                  registers a remote cloud and copies the openrc file
                  specified in the credentials of the cloudmesh.yaml

              register CLOUD --dir
                  Copies the entire directory from the cloud and puts it in
                  ~/.cloudmesh/clouds/host
                  For kilo, The directory would be copied to
                  ~/.cloudmesh/clouds/kilo

              register env [--provider=PROVIDER] [HOSTNAME]
                  Reads env OS_* variables and registers a new cloud in yaml,
                  interactively. Default PROVIDER is openstack and HOSTNAME
                  is localhost.

              register username [USERNAME]
                  Sets the username in yaml with the value provided.
         """
        # from pprint import pprint
        # pprint(arguments)

        def _get_config_yaml_file(arguments):
            filename = arguments["--yaml"] or "cloudmesh.yaml"
            filename = Config.find_file(filename)
            return filename

        def exists(filename):
            return os.path.isfile(filename)

        def export(host, output):
            config = ConfigDict("cloudmesh.yaml")
            credentials = dict(
                config["cloudmesh"]["clouds"][host]["credentials"])

            if not arguments["--password"]:
                credentials["OS_PASSWORD"] = "******"

            if output is None:
                for attribute, value in credentials.items():
                    print("export {}={}".format(attribute, value))
            elif output == "table":
                print(attribute_printer(credentials))
            else:
                print(dict_printer(credentials, output=output))
                # TODO: bug csv does not work
            return ""

        if arguments["info"]:

            filename = _get_config_yaml_file(arguments)

            if os.path.isfile(filename):
                Console.ok("File '{}' exists. ok.".format(filename))

                Console.ok("The yaml file contains the following templates:")

                d = CloudRegister.list(filename,
                                       info=False,
                                       output="table")
                print(d)

            else:
                Console.error("File {} does not exist".format(filename))

            return ""

        elif arguments["new"]:

            import shutil
            import cloudmesh_client.etc
            print(cloudmesh_client.etc.__file__)
            filename = os.path.join(
                os.path.dirname(cloudmesh_client.etc.__file__),
                "cloudmesh.yaml")
            Console.ok(filename)
            yamlfile = path_expand("~/.cloudmesh/cloudmesh.yaml")
            shutil.copyfile(filename, yamlfile)
            print("copy ")
            print("From: ", filename)
            print("To:   ", yamlfile)

            # filename = _get_config_yaml_file(arguments)
            # if _exists(filename):
            #    Console.ok("File '{}' exists. ok.".format(filename))
            # else:
            #    Console.error("File {} does not exist".format(filename))
            return ""

        elif arguments["clean"]:

            filename = _get_config_yaml_file(arguments)
            force = arguments["--force"] or False
            if filename is not None:
                print(filename, force)
                if exists(filename):
                    print("Delete cloudmesh.yaml file:", filename)
                    if not force:
                        force = yn_choice("Would you like to delete the "
                                          "cloudmesh.yaml file")
                        print(force)
                    if force:
                        os.remove(filename)
                        Console.ok("Deleted the file " + filename + ". ok.")
                    else:
                        Console.ok("Please use Y to delete the file.")
                    pass
                else:
                    Console.error("File {} does not exist".format(filename))
            else:
                Console.error("No cloudmesh.yaml file found.")
            return ""

        elif arguments["cat"]:

            filename = _get_config_yaml_file(arguments)
            if exists(filename):
                with open(filename, 'r') as f:
                    lines = f.read().split("\n")
                print('\n'.join(lines))
            else:
                Console.error("File {} does not exist".format(filename))
            return ""

        elif arguments["edit"]:

            filename = _get_config_yaml_file(arguments)
            if exists(filename):
                try:
                    data = {"editor": os.environ["EDITOR"],
                            "filename": filename}
                    Console.ok("editing file " + filename)
                    os.system("{editor} {filename}".format(**data))
                except:
                    Console.error("No EDITOR variable set in shell.")
            else:
                Console.error("File {} does not exist".format(filename))
            return ""

        elif arguments['list'] and arguments['ssh']:
            output = arguments['--format'] or 'table'
            hosts = CloudRegister.list_ssh()
            print(print_list(hosts, output=output))
            return ""

        elif arguments['list']:

            filename = _get_config_yaml_file(arguments)
            info = arguments["--info"] or False
            output = arguments["--format"] or "table"

            if not filename:
                Console.error("File {} doesn't exist".format(filename))
            else:
                d = CloudRegister.list(filename,
                                       info=info,
                                       output=output)
                print(d)
            return ""

        elif arguments['check']:
            filename = _get_config_yaml_file(arguments)
            if not filename:
                Console.error("File {} doesn't exist".format(
                    arguments["--yaml"] or 'cloudmesh.yaml'))
            else:
                CloudRegister.check_yaml_for_completeness(filename)
            return ""

        elif arguments['merge']:
            filename = arguments['FILENAME']
            CloudRegister.from_file(filename)
            return

        elif arguments['test']:
            filename = _get_config_yaml_file(arguments)
            CloudRegister.test(filename)
            return ""

        elif arguments['form']:
            filename = _get_config_yaml_file(arguments)
            if not filename:
                Console.error("File {} doesn't exist".format(
                    arguments["--yaml"] or 'cloudmesh.yaml'))
            else:
                CloudRegister.fill_out_form(filename)
            return ""

        elif arguments['source']:

            host = arguments['HOST']
            config = ConfigDict("cloudmesh.yaml")
            credentials = dict(
                config["cloudmesh"]["clouds"][host]["credentials"])

            # unset

            variables = list(os.environ)
            for attribute in variables:
                if attribute.startswith("OS_"):
                    print("x ", attribute)
                    del os.environ[attribute]

            # set
            for attribute, value in credentials.items():
                os.putenv(attribute, value)
                print("+ ", attribute)
            export(host, "table")

            return ""

        elif arguments['export']:

            output = arguments['--format']
            host = arguments['HOST']

            variables = list(os.environ)
            for attribute in variables:
                if attribute.startswith("OS_"):
                    print("unset ", attribute)
                    del os.environ[attribute]
            export(host, output)

        elif arguments['json']:
            host = arguments['HOST']
            result = CloudRegister.get(host)
            if result:
                print(json.dumps(result, indent=4))
            else:
                print("Cloud {:} is not described in cloudmesh.yaml".format(
                    host))
            return ""

        elif arguments['remote']:

            force = arguments['--force']
            cloud = arguments['CLOUD']

            if cloud is None:
                clouds = ["kilo"]
            else:
                clouds = [cloud]

            for cloud in clouds:
                CloudRegister.remote(cloud, force)
                export(cloud, "table")

            config = ConfigDict("cloudmesh.yaml")
            if config["cloudmesh.profile.username"] == "TBD":
                name = config["cloudmesh.clouds.kilo.credentials.OS_USERNAME"]
                config["cloudmesh"]["profile"]["username"] = name
                config.save()
            else:
                print("KKK")
            return ""

        elif arguments['ec2']:

            cloud = arguments['CLOUD']
            zipfile = arguments['EC2ZIP']

            if cloud is None:
                clouds = ["kilo"]
            else:
                clouds = [cloud]

            for cloud in clouds:
                CloudRegister.ec2(cloud, zipfile)
                export(cloud, "table")

        elif arguments['env']:
            try:
                CloudRegister.from_environ(arguments['--provider'])
            except Exception as e:
                Error.traceback(e)
            return ""

        elif arguments['CLOUD']:
            if arguments['--dir']:
                cloud = arguments['CLOUD']
                directory = arguments['--dir']
                Console.ok(directory)
                CloudRegister.directory(cloud, directory)
            else:
                cloud = arguments['CLOUD']

                if cloud is None:
                    clouds = ["kilo"]
                else:
                    clouds = [cloud]

                for cloud in clouds:
                    CloudRegister.remote(cloud, True)
                    export(cloud, "table")
            return ""

        elif arguments['profile']:
            username = arguments["--username"] or getpass.getuser()
            CloudRegister.set_username(username)
            Console.ok("Username {} set successfully in the yaml settings.".format(username))
            return ""

        elif arguments['yaml']:
            name = arguments['ENTRY']
            Register.entry(name)
            return ""
        # if all fails do a simple list

        filename = _get_config_yaml_file(arguments)
        CloudRegister.list(filename)

        pass
Ejemplo n.º 23
0
    def do_register(self, args, arguments):
        """
        ::

          Usage:
              register info
              register backup
              register new [--force] [--dryrun]
              register clean [--force]
              register list ssh [--format=FORMAT]
              register list [--yaml=FILENAME][--info][--format=FORMAT]
              register cat [--yaml=FILENAME]
              register edit [--yaml=FILENAME]
              register user [USERNAME]
              register cloud [CLOUD] [--force]
              register remote [CLOUD] [--force]
              register export HOST [--password] [--format=FORMAT]
              register source HOST
              register merge FILEPATH
              register form [--yaml=FILENAME]
              register check [--yaml=FILENAME]
              register test [--yaml=FILENAME]
              register json HOST
              register env [--provider=PROVIDER]
              register ec2 CLOUD EC2ZIP
              register ENTRY

          managing the registered clouds in the cloudmesh.yaml file.
          It looks for it in the current directory, and than in
          ~/.cloudmesh.  If the file with the cloudmesh.yaml name is
          there it will use it.  If neither location has one a new
          file will be created in ~/.cloudmesh/cloudmesh.yaml. Some
          defaults will be provided.  However you will still need to
          fill it out with valid entries.

          Arguments:

            HOST   the host name
            USER   the user name
            FILEPATH the path of the file
            CLOUD the cloud name
            PROVIDER the provider or type of cloud [Default: openstack]
            USERNAME  Username that would be registered in yaml. Defaults to OS username.

          Options:

            --provider=PROVIDER     Provider to be used for cloud. Values are:
                                    openstack, azure, ec2.
            --version=VERSION       Version of the openstack cloud.
            --openrc=OPENRC         The location of the openrc file
            --password              Prints the password
            --force                 ignore interactive questions and execute
                                    the action

          Description:

              register info
                  lists the clouds specified in the cloudmesh.yaml
                  file in the current directory, and then in ~/.cloudmesh

              register list [--yaml=FILENAME] [--name] [--info]
                  lists the clouds specified in the cloudmesh.yaml file. If
                  info is specified it also prints the location of the yaml
                  file.

              register list ssh
                  lists hosts from ~/.ssh/config

              register cat [--yaml=FILENAME]
                  outputs the cloudmesh.yaml file

              register edit [--yaml=FILENAME]
                  edits the cloudmesh.yaml file

              register export HOST [--format=FORMAT]

                    prints the contents of an openrc.sh file based on the
                    information found in the cloudmesh.yaml file.

              register remote CLOUD [--force]

                    reads the Openstack OPENRC file from a remote host that
                    is described in cloudmesh.yaml file. We assume that
                    the file has already a template for this host. If
                    not it can be created from other examples before
                    you run this command.

                    It uses the OS_OPENRC variable to locate the file and
                    copy it onto your computer.

              register merge FILENAME
                  Replaces the TBD in cloudmesh.yaml with the contents
                  present in the named file

              register form [--yaml=FILENAME]
                  interactively fills out the form wherever we find TBD.

              register check [--yaml=FILENAME]
                  checks the yaml file for completness

              register test [--yaml=FILENAME]
                  checks the yaml file and executes tests to check if
                  we can use the cloud. TODO: maybe this should be in
                  a test command

              register json host
                  displays the host details in json format

              register remote CLOUD
                  registers a remote cloud and copies the openrc file
                  specified in the credentials of the cloudmesh.yaml

              register CLOUD --dir
                  Copies the entire directory from the cloud and puts it in
                  ~/.cloudmesh/clouds/host
                  For kilo, The directory would be copied to
                  ~/.cloudmesh/clouds/kilo

              register env [--provider=PROVIDER] [HOSTNAME]
                  Reads env OS_* variables and registers a new cloud in yaml,
                  interactively. Default PROVIDER is openstack and HOSTNAME
                  is localhost.

              register user [USERNAME]
                  Sets the user in yaml with the value provided.
         """

        # from pprint import pprint
        # pprint(arguments)

        def _get_config_yaml_file(arguments):
            filename = arguments["--yaml"] or "cloudmesh.yaml"
            filename = Config.find_file(filename)
            return filename

        def exists(filename):
            return os.path.isfile(filename)

        def export(host, output):
            config = ConfigDict("cloudmesh.yaml")
            credentials = dict(
                config["cloudmesh"]["clouds"][host]["credentials"])

            if not arguments["--password"]:
                credentials["OS_PASSWORD"] = "******"

            if output is None:
                for attribute, value in credentials.items():
                    print("export {}={}".format(attribute, value))
            elif output == "table":
                print(Printer.attribute(credentials))
            else:
                print(Printer.write(credentials, output=output))
                # TODO: bug csv does not work

        if arguments["info"]:

            filename = _get_config_yaml_file(arguments)

            if os.path.isfile(filename):
                Console.ok("File '{}' exists. ok.".format(filename))

                Console.ok("The yaml file contains the following templates:")

                d = CloudRegister.list(filename,
                                       Default.cloud,
                                       info=False,
                                       output="table")
                print(d)

            else:
                Console.error("File {} does not exist".format(filename))

            return ""

        elif arguments["backup"]:

            name = backup_name("~/.cloudmesh/cloudmesh.yaml")
            configfile = path_expand("~/.cloudmesh/cloudmesh.yaml")
            print(name)
            try:
                copy(configfile, name)
                Console.ok("Bakup copy created: {}. ok.".format(name))
            except:
                Console.error("Could not create a backup copy from {}".format(
                    configfile))

            return ""

        elif arguments["new"]:

            import shutil
            import cloudmesh_client.etc

            config = ConfigDict("cloudmesh.yaml")
            data = dotdict({
                'dir':
                cloudmesh_client.etc.__file__,
                'filename':
                os.path.join(os.path.dirname(cloudmesh_client.etc.__file__),
                             "cloudmesh.yaml"),
                'yamlfile':
                path_expand("~/.cloudmesh/cloudmesh.yaml"),
                'dryrun':
                arguments['--dryrun']
            })
            Console.ok(data.filename)
            force = arguments["--force"]
            if not force:
                force = yn_choice(
                    "Would you like create a new configuration file at {}".
                    format(data.yamlfile))
            if force:
                if not data.dryrun:
                    config.make_a_copy(location=data.yamlfile)
                    shutil.copyfile(data.filename, data.yamlfile)
                print("copy ")
                print("From: ", data.filename)
                print("To:   ", data.yamlfile)

            # filename = _get_config_yaml_file(arguments)
            # if _exists(filename):
            #    Console.ok("File '{}' exists. ok.".format(filename))
            # else:
            #    Console.error("File {} does not exist".format(filename))
            return ""

        elif arguments["clean"]:

            filename = _get_config_yaml_file(arguments)
            force = arguments["--force"] or False
            if filename is not None:
                print(filename, force)
                if exists(filename):
                    print("Delete cloudmesh.yaml file:", filename)
                    if not force:
                        force = yn_choice("Would you like to delete the "
                                          "cloudmesh.yaml file")
                        print(force)
                    if force:
                        os.remove(filename)
                        Console.ok("Deleted the file " + filename + ". ok.")
                    else:
                        Console.ok("Please use Y to delete the file.")
                    pass
                else:
                    Console.error("File {} does not exist".format(filename))
            else:
                Console.error("No cloudmesh.yaml file found.")
            return ""

        elif arguments["cat"]:

            filename = _get_config_yaml_file(arguments)
            if exists(filename):
                with open(filename, 'r') as f:
                    lines = f.read().split("\n")
                print('\n'.join(lines))
            else:
                Console.error("File {} does not exist".format(filename))
            return ""

        elif arguments["edit"]:

            filename = _get_config_yaml_file(arguments)
            if exists(filename):
                try:
                    data = {
                        "editor": os.environ["EDITOR"],
                        "filename": filename
                    }
                    Console.ok("editing file " + filename)
                    os.system("{editor} {filename}".format(**data))
                except:
                    Console.error(
                        "No operating system environment variable EDITOR set.",
                        traceflag=False)
            else:
                Console.error("File {} does not exist".format(filename),
                              traceflag=False)
            return ""

        elif arguments['list'] and arguments['ssh']:
            output = arguments['--format'] or 'table'
            hosts = CloudRegister.list_ssh()
            print(Printer.list(hosts, output=output))
            return ""

        elif arguments['list']:

            filename = _get_config_yaml_file(arguments)
            info = arguments["--info"] or False
            output = arguments["--format"] or "table"

            if not filename:
                Console.error("File {} doesn't exist".format(filename))
            else:
                d = CloudRegister.list(filename,
                                       Default.cloud,
                                       info=info,
                                       output=output)
                print(d)
            return ""

        elif arguments['check']:
            filename = _get_config_yaml_file(arguments)
            if not filename:
                Console.error("File {} doesn't exist".format(
                    arguments["--yaml"] or 'cloudmesh.yaml'))
            else:
                CloudRegister.check_yaml_for_completeness(filename)
            return ""

        elif arguments['merge']:
            filename = arguments['FILENAME']
            CloudRegister.from_file(filename)
            return ""

        elif arguments['test']:
            filename = _get_config_yaml_file(arguments)
            CloudRegister.test(filename)
            return ""

        elif arguments['form']:
            filename = _get_config_yaml_file(arguments)
            if not filename:
                Console.error("File {} doesn't exist".format(
                    arguments["--yaml"] or 'cloudmesh.yaml'))
            else:
                CloudRegister.fill_out_form(filename)
            return ""

        elif arguments['source']:

            host = arguments['HOST']
            config = ConfigDict("cloudmesh.yaml")
            credentials = dict(
                config["cloudmesh"]["clouds"][host]["credentials"])

            # unset

            variables = list(os.environ)
            for attribute in variables:
                if attribute.startswith("OS_"):
                    print("x ", attribute)
                    del os.environ[attribute]

            # set
            for attribute, value in credentials.items():
                os.putenv(attribute, value)
                print("+ ", attribute)
            export(host, "table")

            return ""

        elif arguments['export']:

            output = arguments['--format']
            host = arguments['HOST']
            try:
                variables = list(os.environ)
                for attribute in variables:
                    if attribute.startswith("OS_"):
                        print("unset ", attribute)
                        del os.environ[attribute]
                export(host, output)
            except:
                Console.error("The export may not include all values",
                              traceflag=False)
            return ""

        elif arguments['json']:
            host = arguments['HOST']
            result = CloudRegister.get(host)
            if result:
                print(json.dumps(result, indent=4))
            else:
                print("Cloud {:} is not described in cloudmesh.yaml".format(
                    host))
            return ""

        elif arguments['remote']:

            force = arguments['--force']
            cloud = arguments['CLOUD']

            if cloud is None:
                # clouds =  [ConfigDict(filename="cloudmesh.yaml")["cloudmesh"]["active"][0]]
                clouds = ["kilo"]  # hardcode to kilo for now

            else:
                clouds = [cloud]

            for cloud in clouds:
                CloudRegister.remote(cloud, force)
                export(cloud, "table")

            config = ConfigDict("cloudmesh.yaml")
            if config["cloudmesh.profile.user"] == "TBD":
                name = config["cloudmesh.clouds.kilo.credentials.OS_USERNAME"]
                config["cloudmesh"]["profile"]["user"] = name
                config.save()
            return ""

        elif arguments['ec2']:

            cloud = arguments['CLOUD']
            zipfile = arguments['EC2ZIP']

            if cloud is None:
                clouds = [
                    ConfigDict(
                        filename="cloudmesh.yaml")["cloudmesh"]["active"][0]
                ]
            else:
                clouds = [cloud]

            for cloud in clouds:
                CloudRegister.ec2(cloud, zipfile)
                export(cloud, "table")

            return ""

        elif arguments['env']:
            try:
                CloudRegister.from_environ(arguments['--provider'])
            except Exception as e:
                Error.traceback(e)
            return ""

        elif arguments['cloud']:
            """
            if arguments['--dir']:
                cloud = arguments['--name']
                directory = arguments['--dir']
                Console.ok(directory)
                CloudRegister.directory(cloud, directory)

            else:
            """

            values_to_replace = ['tbd', 'null', 'tbd_not_used']

            cloud = arguments['CLOUD']
            if cloud is None:
                clouds = [
                    ConfigDict(
                        filename="cloudmesh.yaml")["cloudmesh"]["active"][0]
                ]
            else:
                clouds = [cloud]

            for cloud in clouds:

                config = ConfigDict("cloudmesh.yaml")

                cloud_config = config["cloudmesh.clouds"][cloud]

                # Checking credentials
                print("Checking cloud credentials...")
                for prop in cloud_config["credentials"]:
                    if cloud_config["credentials"][prop].lower(
                    ) in values_to_replace:
                        value = input(prop + "(" +
                                      cloud_config["credentials"][prop] +
                                      "): ")
                        cloud_config["credentials"][prop] = value
                # Checking defaults
                print("Checking cloud defaults...")
                for prop in cloud_config["default"]:
                    if cloud_config["default"][prop].lower(
                    ) in values_to_replace:
                        value = input(prop + "(" +
                                      cloud_config["default"][prop] + "): ")
                        cloud_config["default"][prop] = value
                config.save()
                export(cloud, "table")
            return ""

        elif arguments['user']:
            username = arguments["USERNAME"] or getpass.getuser()
            CloudRegister.set_username(username)

            Console.ok("Setting profile user to {} in the yaml file.".format(
                username))

            hosts = ssh_config()

            hosts.generate(key="india", username=username, verbose=True)

            return ""

        elif arguments['ENTRY'] is not None:
            name = arguments['ENTRY']
            Register.entry(name)
            return ""
        # if all fails do a simple list

        filename = _get_config_yaml_file(arguments)
        CloudRegister.list(filename)

        pass
Ejemplo n.º 24
0
    def do_vm(self, args, arguments):
        """
        ::

            Usage:
                vm default [--cloud=CLOUD][--format=FORMAT]
                vm refresh [--cloud=CLOUD]
                vm boot [--name=NAME]
                        [--cloud=CLOUD]
                        [--image=IMAGE_OR_ID]
                        [--flavor=FLAVOR_OR_ID]
                        [--group=GROUP]
                        [--secgroup=SECGROUP]
                        [--key=KEY]
                        [--dryrun]
                vm start [NAME]...
                         [--group=GROUP]
                         [--cloud=CLOUD]
                         [--force]
                vm stop [NAME]...
                        [--group=GROUP]
                        [--cloud=CLOUD]
                        [--force]
                vm delete [NAME]...
                          [--group=GROUP]
                          [--cloud=CLOUD]
                          [--force]
                vm ip assign [NAME]...
                          [--cloud=CLOUD]
                vm ip show [NAME]...
                           [--group=GROUP]
                           [--cloud=CLOUD]
                           [--format=FORMAT]
                           [--refresh]
                vm login [NAME] [--user=USER]
                         [--ip=IP]
                         [--cloud=CLOUD]
                         [--key=KEY]
                         [--command=COMMAND]
                vm rename [NAME]...
                          [--new=NEWNAME]
                          [--cloud=CLOUD]
                vm list [NAME_OR_ID]
                        [--cloud=CLOUD|--all]
                        [--group=GROUP]
                        [--format=FORMAT]
                        [--refresh]
                vm status [--cloud=CLOUD]
                vm info [--cloud=CLOUD]
                        [--format=FORMAT]

            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.
                NAME_OR_ID     server name or ID
                KEYPAIR_NAME   Name of the openstack keypair to be used to create VM. Note this is not a path to key.
                NEWNAME        New name of the VM while renaming.

            Options:
                --ip=IP          give the public ip of the server
                --cloud=CLOUD    give a cloud to work on, if not given, selected
                                 or default cloud will be used
                --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_OR_ID  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_OR_ID    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          delete vms without user's confirmation
                --command=COMMAND
                                 specify the commands to be executed
                --new=NEWNAME    Specify the new name for a VM while renaming.
                                 By default, this will be set to <username>-<count> format.



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

                vm default [options...]     Displays default parameters that are set for VM boot.
                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 login [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']

        """
        def _print_dict(d, header=None, format='table'):
            if format == "json":
                return json.dumps(d, indent=4)
            elif format == "yaml":
                return pyaml.dump(d)
            elif format == "table":
                return dict_printer(d,
                                    order=["id", "name", "status"],
                                    output="table",
                                    sort_keys=True)
            else:
                return d

        def _print_dict_ip(d, header=None, format='table'):
            if format == "json":
                return json.dumps(d, indent=4)
            elif format == "yaml":
                return pyaml.dump(d)
            elif format == "table":
                return dict_printer(d,
                                    order=["network", "version", "addr"],
                                    output="table",
                                    sort_keys=True)
            else:
                return d

        """
        def list_vms_on_cloud(cloud="kilo", group=None, format="table"):

            Utility reusable function to list vms on the cloud.
            :param cloud:
            :param group:
            :param format:
            :return:

            _cloud = cloud
            _group = group
            _format = format

            cloud_provider = CloudProvider(_cloud).provider
            servers = cloud_provider.list_vm(_cloud)


            server_list = {}
            index = 0
            # TODO: Improve the implementation to display more fields if required.
            for server in servers:
                server_list[index] = {}
                server_list[index]["name"] = server.name
                server_list[index]["id"] = server.id
                server_list[index]["status"] = server.status
                index += 1


            # TODO: Get this printed in a table
            print("Print table")
            dict_printer(servers, output=_format)
        """

        # pprint(arguments)

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

        cloud = arguments["--cloud"] or Default.get_cloud()

        if arguments["boot"]:
            name = None
            try:
                name = arguments["--name"]
                is_name_provided = True

                if name is None:
                    is_name_provided = False

                    count = Counter.get()
                    prefix = Username()

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

                    # BUG THE Z FILL SHOULD BE detected from yaml file
                    name = prefix + "-" + str(count).zfill(3)

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

                image = arguments["--image"] or Default.get("image",
                                                            category=cloud)
                # if default image not set, return error
                if not image:
                    Console.error("Default image not set.")
                    return ""

                flavor = arguments["--flavor"] or Default.get("flavor",
                                                              category=cloud)
                # if default flavor not set, return error
                if not flavor:
                    Console.error("Default flavor not set.")
                    return ""

                group = arguments["--group"] or Default.get_group()

                # if default group not set, return error
                if not group:
                    group = "default"
                    Default.set_group(group)

                secgroup = arguments["--secgroup"] or Default.get(
                    "secgroup", category=cloud)
                # print("SecurityGrp : {:}".format(secgroup))
                secgroup_list = ["default"]
                if secgroup is not None:
                    secgroup_list.append(secgroup)

                key_name = arguments["--key"] or Default.get_key()
                # if default keypair not set, return error
                if not key_name:
                    Console.error("Default key not set.")
                    return ""

                if arguments["--dryrun"]:

                    data = {
                        "cloud": cloud,
                        "name": name,
                        "image": image,
                        "flavor": flavor,
                        "key_name": key_name,
                        "secgroup_list": secgroup_list,
                        "group": group
                    }
                    print(attribute_printer(data, output="table"))
                    msg = "dryrun info. OK."
                    Console.ok(msg)
                else:
                    vm_id = Vm.boot(cloud=cloud,
                                    name=name,
                                    image=image,
                                    flavor=flavor,
                                    key_name=key_name,
                                    secgroup_list=secgroup_list)
                    Default.set("last_vm_id", vm_id)
                    Default.set("last_vm_name", name)

                    # SHOULD WE NOT DO THIS BY DEFAULT EVEN IF WE SPECIFY THE NAME?
                    if is_name_provided is False:
                        # Incrementing count
                        Counter.incr()

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

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

            except Exception as e:
                Error.traceback(e)
                Console.error("Problem booting instance {:}".format(name))

        elif arguments["default"]:
            try:
                count = Counter.get()
                prefix = Username()

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

                vm_name = prefix + "-" + str(count).zfill(3)
                data = {
                    "name": vm_name,
                    "cloud": arguments["--cloud"] or Default.get_cloud()
                }
                for attribute in [
                        "image", "flavor", "key", "login_key", "group",
                        "secgroup"
                ]:
                    data[attribute] = Default.get(attribute, category=cloud)
                output_format = arguments["--format"] or "table"
                print(attribute_printer(data, output=output_format))
                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")

        elif arguments["status"]:
            try:
                cloud_provider = CloudProvider(cloud).provider
                vm_list = cloud_provider.list_vm(cloud)
                print("Status of VM {} is {}".format(vm_list[0]["name"],
                                                     vm_list[0]["status"]))
                msg = "info. OK."
                Console.ok(msg)
            except Exception as e:
                Error.traceback(e)
                Console.error("Problem retrieving status of the VM")

        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(attribute_printer(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")

        elif arguments["start"]:
            try:
                servers = arguments["NAME"]

                # If names not provided, take the last vm from DB.
                if servers is None or len(servers) == 0:
                    last_vm = Vm.get_last_vm(cloud=cloud)
                    if last_vm is None:
                        Console.error(
                            "No VM records in database. Please run vm refresh."
                        )
                        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.")
                    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")

        elif arguments["stop"]:
            try:
                servers = arguments["NAME"]

                # If names not provided, take the last vm from DB.
                if servers is None or len(servers) == 0:
                    last_vm = Vm.get_last_vm(cloud=cloud)
                    if last_vm is None:
                        Console.error(
                            "No VM records in database. Please run vm refresh."
                        )
                        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.")
                    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")

        elif arguments["refresh"]:

            _refresh()

        elif arguments["delete"]:
            try:
                servers = arguments["NAME"]

                # If names not provided, take the last vm from DB.
                if servers is None or len(servers) == 0:
                    last_vm = Vm.get_last_vm(cloud=cloud)
                    if last_vm is None:
                        Console.error(
                            "No VM records in database. Please run vm refresh."
                        )
                        return ""
                    name = last_vm["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.")
                    return ""

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

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

        elif arguments["ip"] and arguments["assign"]:
            vmids = arguments["NAME"]

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

            # if default cloud not set, return error
            if not cloud:
                Console.error("Default cloud not set.")
                return ""
            try:
                cloud_provider = CloudProvider(cloud).provider
                for sname in vmids:
                    floating_ip = cloud_provider.create_assign_floating_ip(
                        sname)
                    if floating_ip is not None:
                        print(
                            "Floating IP assigned to {:} successfully and it is: {:}"
                            .format(sname, floating_ip))
                msg = "info. OK."
                Console.ok(msg)
            except Exception as e:
                Error.traceback(e)
                Console.error("Problem assigning floating ips.")

        elif arguments["ip"] and arguments["show"]:
            vmids = arguments["NAME"]

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

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

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

            try:
                cloud_provider = CloudProvider(cloud).provider
                for server in vmids:
                    ip_addr = cloud_provider.get_ips(server)

                    ipaddr_dict = Vm.construct_ip_dict(ip_addr, cloud)

                    print(
                        "IP Addresses of instance {:} are as follows:-".format(
                            server))
                    print(_print_dict_ip(ipaddr_dict, format=output_format))
                msg = "info. OK."
                Console.ok(msg)
            except Exception as e:
                Error.traceback(e)
                Console.error(
                    "Problem getting ip addresses for instance {:}".format(id))

        elif arguments["login"]:
            vm_names = arguments["NAME"]

            # If names not provided, take the last vm from DB.
            if vm_names is None or len(vm_names) == 0:
                last_vm = Vm.get_last_vm(cloud=cloud)
                if last_vm is None:
                    Console.error(
                        "No VM records in database. Please run vm refresh.")
                    return ""
                name = last_vm["name"]
            else:
                name = vm_names[0]

            print("Logging in into {:} machine...".format(name))

            user = arguments["--user"]

            # Get user if user argument not specified.
            if user is None:
                user_from_db = Vm.get_vm_login_user(name, cloud)
                user_suggest = user_from_db or getpass.getuser()
                user = input("Enter the user to login (Default: {}):".format(
                    user_suggest)) or user_suggest
                Vm.set_vm_login_user(name, cloud, user)

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

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

            key = arguments["--key"] or Default.get("login_key",
                                                    category=cloud)
            if not key:
                Console.error("Default login_key not set.")
                return ""

            cloud_provider = CloudProvider(cloud).provider
            # print("Name : {:}".format(name))
            ip_addr = cloud_provider.get_ips(name)

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

            if ip is not None:
                if ip not in ip_addresses:
                    print(
                        "ERROR: IP Address specified does not match with the host."
                    )
                    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:
                        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("SORRY. Unable to connect to the machine")
                return ""
            else:
                print("IP to be used is: {:}".format(ip))

            SecGroup.enable_ssh(cloud=cloud)
            # print("COMMANDS : {:}".format(commands))

            # Constructing the ssh command to connect to the machine.
            sshcommand = "ssh"
            if key is not None:
                sshcommand += " -i {:}".format(key)
            sshcommand += " -o StrictHostKeyChecking=no"
            sshcommand += " {:}@{:}".format(user, ip)
            if commands is not None:
                sshcommand += " \"{:}\"".format(commands)

            # print(sshcommand)
            os.system(sshcommand)

        elif arguments["list"]:

            if arguments["--all"]:
                try:
                    _format = arguments["--format"] or "table"
                    d = ConfigDict("cloudmesh.yaml")
                    for cloud in d["cloudmesh"]["clouds"]:

                        if arguments["--refresh"] or Default.refresh():
                            _refresh()

                        print("Listing VMs on Cloud: {:}".format(cloud))
                        result = Vm.list(cloud=cloud, output_format=_format)
                        if result is not None:
                            print(result)
                        else:
                            print(
                                "Sorry. No data found with requested parameters in DB."
                            )
                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing all instances")
            else:

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

                try:
                    name_or_id = arguments["NAME_OR_ID"]
                    group = arguments["--group"]
                    _format = arguments["--format"] or "table"

                    # list_vms_on_cloud(cloud, group, _format)
                    if arguments["--refresh"] or Default.refresh():
                        _refresh()

                    result = Vm.list(name_or_id=name_or_id,
                                     cloud=cloud,
                                     output_format=_format)

                    if result is not None:
                        print(result)
                    else:
                        print("No data found with the requested parameters.")

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

                except Exception as e:
                    Error.traceback(e)
                    Console.error(
                        "Problem listing instances on cloud {:}".format(cloud))

        elif arguments["rename"]:
            try:
                servers = arguments["NAME"]

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

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

                new_name = arguments["--new"]
                is_name_provided = True

                # If the new name is not provided, make the new new name in format username-count.
                if new_name is None or len(new_name) == 0:

                    is_name_provided = False

                    count = Counter.get()
                    prefix = Username()

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

                    # BUG THE Z FILL SHOULD BE detected from yaml file
                    new_name = prefix + "-" + str(count).zfill(3)

                Vm.rename(cloud=cloud, servers=servers, new_name=new_name)

                if is_name_provided is False:
                    # Incrementing count
                    Counter.incr()

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

        return ""
Ejemplo n.º 25
0
def main():
    """cm.

    Usage:
      cm --help
      cm [--echo] [--debug] [--nosplash] [-i] [COMMAND ...]

    Arguments:
      COMMAND                  A command to be executed

    Options:
      --file=SCRIPT  -f  SCRIPT  Executes the script
      -i                 After start keep the shell interactive,
                         otherwise quit [default: False]
      --nosplash    do not show the banner [default: False]
    """

    def manual():
        print(main.__doc__)

    args = sys.argv[1:]

    arguments = {
        '--echo': '--echo' in args,
        '--help': '--help' in args,
        '--debug': '--debug' in args,
        '--nosplash': '--nosplash' in args,
        '-i': '-i' in args}

    echo = arguments["--echo"]
    if arguments['--help']:
        manual()
        sys.exit()

    for a in args:
        if a in arguments:
            args.remove(a)

    arguments['COMMAND'] = [' '.join(args)]

    commands = arguments["COMMAND"]
    if len(commands) > 0:
        if ".cm" in commands[0]:
            arguments["SCRIPT"] = commands[0]
            commands = commands[1:]
        else:
            arguments["SCRIPT"] = None

        arguments["COMMAND"] = ' '.join(commands)
        if arguments["COMMAND"] == '':
            arguments["COMMAND"] = None

    # noinspection PySimplifyBooleanCheck
    if arguments['COMMAND'] == []:
        arguments['COMMAND'] = None

    splash = not arguments['--nosplash']
    debug = arguments['--debug']
    interactive = arguments['-i']
    script = arguments["SCRIPT"]
    command = arguments["COMMAND"]

    context = CloudmeshContext(
        interactive=interactive,
        debug=debug,
        echo=echo,
        splash=splash)
    cmd = CloudmeshConsole(context)

    if script is not None:
        cmd.do_exec(script)

    try:
        if echo:
            print("cm>", command)
        if command is not None:
            cmd.precmd(command)
            stop = cmd.onecmd(command)
            cmd.postcmd(stop, command)
    except Exception as e:
        print("ERROR: executing command '{0}'".format(command))
        print(70 * "=")
        print(e)
        print(70 * "=")
        Error.traceback()

    if interactive or (command is None and script is None):
        cmd.cmdloop()
Ejemplo n.º 26
0
    def do_key(self, args, arguments):
        """
        ::

           Usage:
             key  -h | --help
             key list [--source=db] [--format=FORMAT]
             key list --source=cloudmesh [--format=FORMAT]
             key list --source=ssh [--dir=DIR] [--format=FORMAT]
             key load [--format=FORMAT]
             key list --source=git [--format=FORMAT] [--username=USERNAME]
             key add --git [--name=KEYNAME] FILENAME
             key add --ssh [--name=KEYNAME]
             key add [--name=KEYNAME] FILENAME
             key get NAME
             key default [KEYNAME | --select]
             key delete (KEYNAME | --select | --all) [--force]
             key upload [KEYNAME] [--cloud=CLOUD]
             key map [--cloud=CLOUD]

           Manages the keys

           Arguments:

             SOURCE         db, ssh, all
             KEYNAME        The name of a key. For key upload it defaults to the default key name.
             FORMAT         The format of the output (table, json, yaml)
             FILENAME       The filename with full path in which the key
                            is located
             NAME_ON_CLOUD  Typically the name of the keypair on the cloud.

           Options:

              --dir=DIR                     the directory with keys [default: ~/.ssh]
              --format=FORMAT               the format of the output [default: table]
              --source=SOURCE               the source for the keys [default: db]
              --username=USERNAME           the source for the keys [default: none]
              --name=KEYNAME                The name of a key
              --all                         delete all keys
              --force                       delete the key form the cloud
              --name_on_cloud=NAME_ON_CLOUD Typically the name of the keypair on the cloud.

           Description:

           key list --source=git  [--username=USERNAME]

              lists all keys in git for the specified user. If the
              name is not specified it is read from cloudmesh.yaml

           key list --source=ssh  [--dir=DIR] [--format=FORMAT]

              lists all keys in the directory. If the directory is not
              specified the default will be ~/.ssh

           key list --source=cloudmesh  [--dir=DIR] [--format=FORMAT]

              lists all keys in cloudmesh.yaml file in the specified directory.
               dir is by default ~/.cloudmesh

           key list [--format=FORMAT]

               list the keys in teh giiven format: json, yaml,
               table. table is default

           key list

                Prints list of keys. NAME of the key can be specified

               
           key add [--name=keyname] FILENAME

               adds the key specifid by the filename to the key
               database

           key get NAME

               Retrieves the key indicated by the NAME parameter from database
               and prints its fingerprint.

           key default [NAME]

                Used to set a key from the key-list as the default key
                if NAME is given. Otherwise print the current default
                key

           key delete NAME

                deletes a key. In yaml mode it can delete only key that
                are not saved in the database

           key rename NAME NEW

                renames the key from NAME to NEW.
                
        """

        # pprint(arguments)

        def _print_dict(d, header=None, format='table'):
            if format == "json":
                return json.dumps(d, indent=4)
            elif format == "yaml":
                return yaml.dump(d, default_flow_style=False)
            elif format == "table":
                return dict_printer(
                    d,
                    order=["name", "comment", "uri", "fingerprint", "source"],
                    output="table",
                    sort_keys=True)
            else:
                return d
                # return dict_printer(d,order=['cm_id, name, fingerprint'])

        directory = Config.path_expand(arguments["--dir"])

        if arguments['list']:
            _format = arguments['--format']
            _source = arguments['--source']
            _dir = arguments['--dir']

            if arguments['--source'] == 'ssh':

                try:
                    sshm = SSHKeyManager()
                    sshm.get_from_dir(directory)
                    d = dict(sshm.__keys__)
                    print(_print_dict(d, format=_format))
                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing keys from ssh")

            elif arguments['--source'] in ['cm', 'cloudmesh']:

                try:
                    sshm = SSHKeyManager()
                    m = sshm.get_from_yaml(load_order=directory)
                    d = dict(m.__keys__)
                    print(_print_dict(d, format=_format))
                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing keys from `{:}`".format(
                        arguments['--source']))

            elif arguments['--source'] in ['git']:

                username = arguments["--username"]
                # print(username)
                if username == 'none':
                    conf = ConfigDict("cloudmesh.yaml")
                    username = conf["cloudmesh.github.username"]

                sshm = SSHKeyManager()
                try:
                    sshm.get_from_git(username)
                    d = dict(sshm.__keys__)
                    print(_print_dict(d, format=_format))
                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing git keys from database")
                    return ""

            elif arguments['--source'] == 'db':

                try:
                    sshdb = SSHKeyDBManager()
                    d = sshdb.table_dict()
                    if d != {}:
                        print(_print_dict(d, format=arguments['--format']))
                        msg = "info. OK."
                        Console.ok(msg)
                    else:
                        Console.error("No keys in the database")
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing keys from database")

        elif arguments['load']:
            _format = arguments['--format']
            _dir = arguments['--dir']

            try:
                sshm = SSHKeyManager()
                m = sshm.get_from_yaml(load_order=directory)
                d = dict(m.__keys__)

                sshdb = SSHKeyDBManager()

                for keyname in m.__keys__:
                    filename = m[keyname]["path"]
                    try:
                        sshdb.add(filename,
                                  keyname,
                                  source="yaml",
                                  uri="file://" + filename)
                    except Exception as e:
                        Console.error("problem adding key {}:{}".format(
                            keyname, filename))

                print(_print_dict(d, format=_format))
                msg = "info. OK."
                Console.ok(msg)
            except Exception as e:
                Console.error("Problem adding keys from yaml file")

        elif arguments['get']:

            try:
                name = arguments['NAME']
                sshdb = SSHKeyDBManager()
                d = sshdb.table_dict()

                for i in d:
                    if d[i]["name"] == name:
                        key = d[i]
                        print("{:}: {:}".format(key['name'],
                                                key['fingerprint']))
                        msg = "info. OK."
                        Console.ok(msg)
                        return ""
                    else:
                        pass
                Console.error("The key is not in the database")
            except Exception as e:
                Error.traceback(e)
                Console.error("The key is not in the database")

        # key add --git KEYNAME
        #      key add --ssh KEYNAME
        #      key add [--path=PATH]  KEYNAME

        elif arguments['add'] and arguments["--git"]:

            print('git add')
            sshdb = SSHKeyDBManager()
            keyname = arguments['--name']
            gitkeyname = arguments['NAME']
            filename = arguments['FILENAME']

            # Are we adding to the database as well?
            # sshdb.add(filename, keyname, source="ssh", uri="file://"+filename)

            username = arguments["--username"]

            if username == 'none':
                conf = ConfigDict("cloudmesh.yaml")
                username = conf["cloudmesh.github.username"]
            print(username)

            sshm = SSHKeyManager()
            try:
                sshm.get_from_git(username)
                d = dict(sshm.__keys__)
                print(d)
            except Exception as e:
                Error.traceback(e)
                Console.error("Problem adding keys to git for user: "******""

            try:
                # FIXME: correct code to add to git
                d[gitkeyname]['keyname'] = keyname
                d[gitkeyname]['user'] = None
                d[gitkeyname]['source'] = 'git'
                # sshdb.add_from_dict(d[gitkeyname])
            except Exception as e:
                Console.error("The key already exists")

        elif arguments['add'] and arguments["--ssh"]:

            # print('ssh add')
            sshdb = SSHKeyDBManager()
            keyname = arguments['--name']
            filename = Config.path_expand("~/.ssh/id_rsa.pub")
            try:
                sshdb.add(filename,
                          keyname,
                          source="ssh",
                          uri="file://" + filename)
                print("Key {:} successfully added to the database".format(
                    keyname or ""))
                msg = "info. OK."
                Console.ok(msg)
            except Exception as e:
                """
                Error.traceback(e)
                print (keyname)
                print (filename)
                """
                Console.error(
                    "Problem adding the key `{}` from file `{}`".format(
                        keyname, filename))

        elif arguments['add'] and not arguments["--git"]:

            # print('ssh add')
            sshdb = SSHKeyDBManager()
            keyname = arguments['--name']
            filename = arguments['FILENAME']
            try:
                sshdb.add(filename,
                          keyname,
                          source="ssh",
                          uri="file://" + filename)
                print("Key {:} successfully added to the database".format(
                    keyname or ""))
                msg = "info. OK."
                Console.ok(msg)

            except ValueError as e:
                Console.error("The key `{}` already exists".format(keyname),
                              traceflag=False)
            """
            except Exception as e:
                Error.traceback(e)
                print (keyname)
                print (filename)
                Console.error("Problem adding the key `{}` from file `{}`".format(keyname, filename))
            """
            return ""

        elif arguments['default']:

            # print("default")

            if arguments['KEYNAME']:
                keyname = None
                try:
                    keyname = arguments['KEYNAME']
                    sshdb = SSHKeyDBManager()
                    sshdb.set_default(keyname)
                    Default.set_key(keyname)
                    print("Key {:} set as default".format(keyname))
                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error(
                        "Setting default for key {:} failed.".format(keyname))

            elif arguments['--select']:
                keyname = None
                try:
                    sshdb = SSHKeyDBManager()
                    select = sshdb.select()
                    if select != 'q':
                        keyname = select.split(':')[0]
                        print("Setting key: {:} as default.".format(keyname))
                        sshdb.set_default(keyname)
                        msg = "info. OK."
                        Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error(
                        "Setting default for selected key {:} failed.".format(
                            keyname))

            else:
                try:
                    sshdb = SSHKeyDBManager()
                    d = sshdb.table_dict()

                    for i in d:
                        if d[i]["is_default"] == "True":
                            key = d[i]
                            print("{:}: {:}".format(key['name'],
                                                    key['fingerprint']))
                            msg = "info. OK."
                            Console.ok(msg)
                            return ""
                        else:
                            pass
                    Console.error("The key is not in the database")
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem retrieving default key.")

        elif arguments['delete']:

            delete_on_cloud = arguments["--force"] or False
            # print ("DDD", delete_on_cloud)
            if arguments['--all']:
                try:
                    sshm = SSHKeyManager(delete_on_cloud=delete_on_cloud)
                    sshm.delete_all_keys()
                    print("All keys from the database deleted successfully.")
                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem deleting keys")
            elif arguments['--select']:
                keyname = None
                sshdb = SSHKeyDBManager()
                select = sshdb.select()
                if select != 'q':
                    try:
                        keyname = select.split(':')[0]
                        print("Deleting key: {:}...".format(keyname))
                        sshm = SSHKeyManager(delete_on_cloud=delete_on_cloud)
                        sshm.delete_key(keyname)
                        msg = "info. OK."
                        Console.ok(msg)
                    except Exception as e:
                        Error.traceback(e)
                        Console.error(
                            "Problem deleting the key `{:}`".format(keyname))
            else:
                keyname = None
                try:
                    keyname = arguments['KEYNAME']
                    sshm = SSHKeyManager(delete_on_cloud=delete_on_cloud)
                    sshm.delete_key(keyname)
                    print("Key {:} deleted successfully from database.".format(
                        keyname))
                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error(
                        "Problem deleting the key `{:}`".format(keyname))

        elif arguments['upload']:

            try:
                #
                # get username
                #
                conf = ConfigDict("cloudmesh.yaml")
                username = conf["cloudmesh"]["profile"]["username"]
                if username in ['None', 'TBD']:
                    username = None

                #
                # get cloudnames
                #
                clouds = []
                cloud = arguments["--cloud"] or Default.get_cloud()
                if cloud == "all":
                    config = ConfigDict("cloudmesh.yaml")
                    clouds = config["cloudmesh"]["clouds"]
                else:
                    clouds.append(cloud)

                #
                # get keyname
                #

                for cloud in clouds:
                    status = 0
                    sshdb = SSHKeyDBManager()
                    sshm = SSHKeyManager()
                    keys = sshdb.find_all()
                    for keyid in keys:
                        key = keys[keyid]

                        print("upload key {} -> {}".format(key["name"], cloud))

                        try:
                            status = sshm.add_key_to_cloud(
                                username, key["name"], cloud, key["name"])

                        except Exception as e:
                            print(e)
                            if "already exists" in str(e):
                                print("key already exists. Skipping "
                                      "upload. ok.")
                        if status == 1:
                            print("Problem uploading key. failed.")
                msg = "info. OK."
                Console.ok(msg)

            except Exception as e:
                Error.traceback(e)
                Console.error("Problem adding key to cloud")

        elif arguments['map']:
            try:
                cloud = arguments["--cloud"] or Default.get_cloud()
                sshm = SSHKeyManager()
                map_dict = sshm.get_key_cloud_maps(cloud)
                print(
                    dict_printer(map_dict,
                                 order=[
                                     "user", "key_name", "cloud_name",
                                     "key_name_on_cloud"
                                 ]))

            except Exception as e:
                Error.traceback(e)
                Console.error("Problem adding key to cloud")
Ejemplo n.º 27
0
    def do_key(self, args, arguments):
        """
        ::

           Usage:
             key  -h | --help
             key list --cloud=CLOUD
             key list --source=db [--format=FORMAT]
             key list --source=yaml [--format=FORMAT]
             key list --source=ssh [--dir=DIR] [--format=FORMAT]
             key list --source=git [--format=FORMAT] [--username=USERNAME]
             key list
             key load [--format=FORMAT]
             key add [NAME] [--source=FILENAME]
             key add [NAME] [--git]
             key add [NAME] [--ssh]
             key get NAME
             key default --select
             key delete (NAME | --select | --all)
             key delete NAME --cloud=CLOUD
             key upload [NAME] [--cloud=CLOUD]
             key upload [NAME] --active

           Manages the keys

           Arguments:

             CLOUD          The cloud
             NAME           The name of the key.
             SOURCE         db, ssh, all
             KEYNAME        The name of a key. For key upload it defaults to the default key name.
             FORMAT         The format of the output (table, json, yaml)
             FILENAME       The filename with full path in which the key
                            is located
             NAME_ON_CLOUD  Typically the name of the keypair on the cloud.

           Options:

              --dir=DIR                     the directory with keys [default: ~/.ssh]
              --format=FORMAT               the format of the output [default: table]
              --source=SOURCE               the source for the keys [default: db]
              --username=USERNAME           the source for the keys [default: none]
              --name=KEYNAME                The name of a key
              --all                         delete all keys
              --force                       delete the key form the cloud
              --name_on_cloud=NAME_ON_CLOUD Typically the name of the keypair on the cloud.

           Description:

           key list --source=git  [--username=USERNAME]

              lists all keys in git for the specified user. If the
              name is not specified it is read from cloudmesh.yaml

           key list --source=ssh  [--dir=DIR] [--format=FORMAT]

              lists all keys in the directory. If the directory is not
              specified the default will be ~/.ssh

           key list --source=yaml  [--dir=DIR] [--format=FORMAT]

              lists all keys in cloudmesh.yaml file in the specified directory.
               dir is by default ~/.cloudmesh

           key list [--format=FORMAT]

               list the keys in the giiven format: json, yaml,
               table. table is default

           key list

                Prints list of keys. NAME of the key can be specified

               
           key add [--name=keyname] FILENAME

               adds the key specifid by the filename to the key
               database

           key get NAME

               Retrieves the key indicated by the NAME parameter from database
               and prints its fingerprint.

           key default --select

                Select the default key interactively

           key delete NAME

                deletes a key. In yaml mode it can delete only key that
                are not saved in the database

           key rename NAME NEW

                renames the key from NAME to NEW.
                
        """
        # pprint(arguments)

        invalid_names = ['tbd', 'none', "", 'id_rsa']

        def _print_dict(d, header=None, format='table'):
            msg = Printer.write(
                d,
                order=["name", "comment", "uri", "fingerprint", "source"],
                output=format,
                sort_keys=True)
            if msg is None:
                Console.error("No keys found.", traceflag=False)
                return None
            else:
                return msg

        directory = Config.path_expand(arguments["--dir"])

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

        if arguments['list']:
            _format = arguments['--format']
            _source = arguments['--source']
            _dir = arguments['--dir']

            if "--source" not in arguments and "--cloud" not in arguments:
                arguments["--source"] = 'db'

            if arguments['--cloud']:

                #
                # get key list from openstack cloud
                #
                #keys = Key.list(cloud, output=_format)

                keys = Key.list_on_cloud(cloud, live=True, format=_format)
                if keys is None:
                    Console.ok("The Key list is empty")
                else:
                    print(keys)
                return ""

            elif arguments['--source'] == 'ssh':

                try:
                    #sshm = SSHKeyManager()
                    d = Key.get_from_dir(directory, store=False)

                    #print("SSS", type(Key.__keys__))
                    #d = dict(Key.all())
                    #print(d)
                    print(
                        Printer.write(d,
                                      order=[
                                          "name", "comment", "uri",
                                          "fingerprint", "source"
                                      ],
                                      output="table"))

                    # d = dict(sshm.__keys__)

                    # print(_print_dict(d, format=_format))
                    msg = "info. OK."
                    Console.ok(msg)
                    return ""
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing keys from ssh")

            elif arguments['--source'] in ['cm', 'cloudmesh', 'yaml']:

                try:
                    #sshm = SSHKeyManager()
                    d = Key.get_from_yaml(load_order=directory, store=False)

                    print(
                        Printer.write(d,
                                      order=[
                                          "name", "comment", "uri",
                                          "fingerprint", "source"
                                      ],
                                      output=_format))
                    return ""
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing keys from `{:}`".format(
                        arguments['--source']))

            elif arguments['--source'] in ['git']:

                username = arguments["--username"]
                # print(username)
                if username == 'none':
                    conf = ConfigDict("cloudmesh.yaml")
                    username = conf["cloudmesh.github.username"]

                #sshm = SSHKeyManager()
                try:

                    d = Key.get_from_git(username, store=False)

                    print(
                        Printer.write(d,
                                      order=[
                                          "name", "comment", "uri",
                                          "fingerprint", "source"
                                      ],
                                      output=_format))

                    msg = "info. OK."
                    Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing git keys from database")
                    return ""

            elif arguments['--source'] == 'db':

                try:
                    #sshdb = SSHKeyDBManager()
                    d = Key.all(output='dict')

                    if d is not None or d != []:

                        print(
                            Printer.write(d,
                                          order=[
                                              "name", "comment", "uri",
                                              "fingerprint", "source"
                                          ],
                                          output=_format))

                        # print(_print_dict(d, output=arguments['--format']))
                        msg = "info. OK."
                        Console.ok(msg)
                    else:
                        Console.error("No keys in the database")
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem listing keys from database")

        elif arguments['get']:

            try:
                name = arguments['NAME']
                #sshdb = SSHKeyDBManager()
                d = Key.all(output="dict")

                for key in d:
                    if key["name"] == name:
                        print("{:}: {:}".format(key['name'],
                                                key['fingerprint']))
                        msg = "info. OK."
                        Console.ok(msg)
                        return ""
                    else:
                        pass
                Console.error("The key is not in the database")
            except Exception as e:
                Error.traceback(e)
                Console.error("The key is not in the database")

        # key add [NAME] [--source=FILENAME]
        #     key add [NAME] [--git]

        elif arguments['add'] and arguments["--git"]:

            # Console.error("This feature is not yet implemented", traceflag=False)
            # return ""

            print('git add')
            #sshdb = SSHKeyDBManager()

            data = dotdict(arguments)

            keyname = data.NAME

            #
            # get name
            #
            conf = ConfigDict("cloudmesh.yaml")
            data.username = conf["cloudmesh.github.username"]
            data.name = arguments['NAME'] or data.username

            #
            # get git username
            #
            data.username = ConfigDict(
                "cloudmesh.yaml")["cloudmesh.github.username"]

            if str(data.name).lower() in invalid_names:
                Console.error(
                    "The github user name is not set in the yaml file",
                    traceflag=False)
                return ""

            try:
                Console.msg(
                    "Retrieving github ssh keys for user {username}".format(
                        **data))
                #sshm = SSHKeyManager()
                Key.get_from_git(data.username)
                d = Key.all()
                # pprint(d)
            except Exception as e:
                Console.error(
                    "Problem adding keys to git for user: {username}".format(
                        **data))
                return ""

            for key in d:
                if key is not None:
                    key["name"] = key["name"].replace("-", "_")
                    key["source"] = "git"
                    key["user"] = data.name
                    try:
                        o = dict(key)
                        o['value'] = key["string"]
                        Key.add_from_dict(key)
                    except Exception as e:
                        Console.error(
                            "The key {name} with that finger print already exists"
                            .format(**key),
                            traceflag=False)

        elif arguments['add'] and not arguments["--git"]:

            #     key add [NAME] [--source=FILENAME]
            #     key add [NAME] [--git]

            #sshdb = SSHKeyDBManager()

            data = dotdict()

            #
            # get name
            #
            conf = ConfigDict("cloudmesh.yaml")
            data.username = conf["cloudmesh.profile.user"]
            data.name = arguments['NAME'] or data.username

            data.filename = arguments['--source']
            if data.filename == "db" or data.filename is None:
                data.filename = Config.path_expand("~/.ssh/id_rsa.pub")

            if str(data.name).lower() in invalid_names:
                msg = (
                    "Your choice of keyname {name} is insufficient. \n"
                    "You must be chosing a keyname that is distingct on all clouds. \n"
                    "Possible choices are your gmail name, your XSEDE name, or \n"
                    "some name that is uniqe. "
                    "Best is also to set this name in \n"
                    "cloudmesh.profile.user as "
                    "part of your \n~/cloudmesh/cloudmesh.yaml file.")
                Console.error(msg.format(**data), traceflag=False)
                return ""

            try:
                Key.add_from_path(data.filename,
                                  data.name,
                                  source="ssh",
                                  uri="file://" + data.filename)
                print("Key {name} successfully added to the database".format(
                    **data))
                msg = "info. OK."
                Console.ok(msg)

            except ValueError as e:
                Console.error(
                    "A key with this fingerprint already exists".format(
                        **data),
                    traceflag=False)
                Console.msg("Please use check with: key list")

            return ""

        elif arguments['default']:

            # print("default")

            if arguments['--select']:
                keyname = None
                try:
                    #sshdb = SSHKeyDBManager()
                    select = Key.select()
                    if select != 'q':
                        keyname = select.split(':')[0]
                        print("Setting key: {:} as default.".format(keyname))
                        Default.key = keyname
                        msg = "info. OK."
                        Console.ok(msg)
                except Exception as e:
                    Error.traceback(e)
                    Console.error(
                        "Setting default for selected key {:} failed.".format(
                            keyname))

            else:
                try:
                    #sshdb = SSHKeyDBManager()
                    d = Key.table_dict()

                    for i in d:
                        if d[i]["is_default"] == "True":
                            key = d[i]
                            print("{:}: {:}".format(key['name'],
                                                    key['fingerprint']))
                            msg = "info. OK."
                            Console.ok(msg)
                            return ""
                        else:
                            pass
                    Console.error("The key is not in the database")
                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem retrieving default key.")

        elif arguments['delete'] and arguments["--cloud"]:

            key = dotdict({
                'cloud': arguments["--cloud"],
                'name': arguments["NAME"]
            })
            try:
                Key.delete(key.name, key.cloud)
                msg = "info. OK."
                Console.ok(msg)
            except:
                Console.error(
                    "Problem deleting the key {name} on the cloud {cloud}".
                    format(**key))

        elif arguments['delete']:

            # key delete (NAME | --select| --all)

            data = dotdict({
                'all': arguments['--all'] or False,
                'select': arguments['--select'] or False,
                'name': arguments['NAME'] or False,
            })

            pprint(data)
            # BUG delete all is not properly implemented

            if data.all:
                Console.TODO("Delete --all is not yet implemented.")
                # Key.delete()
            elif data.select:
                key = Key.select()
                print(key)

            else:  # name
                Key.delete(data.name)

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

        elif arguments['upload']:

            # pprint(arguments)

            try:
                #
                # get username
                #
                conf = ConfigDict("cloudmesh.yaml")
                username = conf["cloudmesh"]["profile"]["user"]
                if username in ['None', 'TBD']:
                    username = None

                #
                # get cloudnames
                #
                clouds = []

                if arguments["--active"]:
                    cloud = 'active'
                else:
                    cloud = arguments["--cloud"] or Default.cloud

                if cloud == "all":
                    config = ConfigDict("cloudmesh.yaml")
                    clouds = config["cloudmesh"]["clouds"]
                elif cloud == 'active':
                    config = ConfigDict("cloudmesh.yaml")
                    clouds = config["cloudmesh"]["active"]
                else:
                    clouds.append(cloud)

                #
                # get keyname
                #

                for cloud in clouds:
                    status = 0
                    #sshdb = SSHKeyDBManager()
                    #sshm = SSHKeyManager()
                    keys = Key.all()
                    for key in keys:

                        print("upload key {} -> {}".format(key["name"], cloud))

                        try:
                            status = Key.add_key_to_cloud(
                                username, key["name"], cloud)

                        except Exception as e:
                            Console.error("problem")
                            if "already exists" in str(e):
                                print(
                                    "key already exists. Skipping upload. OK.")
                        if status == 1:
                            print("Problem uploading key {} to {}. failed.".
                                  format(key["name"], cloud))

            except Exception as e:
                Console.error("Problem adding key to cloud")
Ejemplo n.º 28
0
    def do_reservation(self, args, arguments):
        """
        ::

            Usage:
                reservation info --user=USER --project=PROJECT
                reservation list [--name=NAME]
                                 [--user=USER]
                                 [--project=PROJECT]
                                 [--hosts=HOSTS]
                                 [--start=TIME_START]
                                 [--end=TIME_END]
                                 [--format=FORMAT]
                reservation delete [all]
                                   [--user=USER]
                                   [--project=PROJECT]
                                   [--name=NAME]
                                   [--start=TIME_START]
                                   [--end=TIME_END]
                                   [--hosts=HOSTS]
                reservation delete --file=FILE
                reservation update --name=NAME
                                  [--start=TIME_START]
                                  [--end=TIME_END]
                                  [--user=USER]
                                  [--project=PROJECT]
                                  [--hosts=HOSTS]
                                  [--description=DESCRIPTION]
                reservation add --name=NAME
                                [--start=TIME_START]
                                [--end=TIME_END]
                                [--user=USER]
                                [--project=PROJECT]
                                [--hosts=HOSTS]
                                [--description=DESCRIPTION]
                reservation add --file=FILE

            Arguments:

                NAME            Name of the reservation
                USER            Registration will be done for this user
                PROJECT         Project to be used
                HOSTS           Hosts to reserve
                TIME_START      Start time of reservation
                TIME_END        End time of reservation
                FORMAT          Format of output
                DESCRIPTION     Description for reservation
                FILE            File that contains reservation data to be added/ deleted

            Options:

                --name=NAME           Names of the reservation
                --user=USER           user name
                --project=PROJECT     project id
                --start=TIME_START    Start time of the reservation, in
                                      MM/DD/YYYY at hh:mm aa format. (default value: 01/01/1901 at 12:00 am])
                --end=TIME_END        End time of the reservation, in
                                      MM/DD/YYYY at hh:mm aa format. (default value: 12/31/2100 at 11:59 pm])
                --host=HOSTS          host name
                --description=DESCRIPTION  description summary of the reservation
                --file=FILE           Adding multiple reservations from one file
                --format=FORMAT       Format is either table, json, yaml or csv
                                      [default: table]

            Description:

                reservation info
                    lists the resources that support reservation for
                    a given user or project.
        """

        # print (arguments)
        def _print_dict(d, header=None, format='table'):
            if format == "json":
                return json.dumps(d, indent=4)
            elif format == "yaml":
                return pyaml.dump(d)
            elif format == "table":
                return Printer.write(d,
                                     order=[
                                         "id", "name", "start_time",
                                         "end_time", "user", "project",
                                         "hosts", "description", "cloud"
                                     ],
                                     output="table",
                                     sort_keys=True)
            elif format == "csv":
                TODO.implement()
            else:
                return d
                # return Printer.write(d,order=['cm_id, name, fingerprint'])

        def _get_db_date_format(date):
            """
            Utility Function that accepts instance of Date object and returns a string with Datetime for DB.
            :param date: Date object
            :return: Date as string with format expected in DB.
            """
            db_date = "{:}-{:}-{:} {:}:{:}".format(
                str(date.month).zfill(2),
                str(date.day).zfill(2),
                str(date.year).zfill(4),
                str(date.hour).zfill(2),
                str(date.minute).zfill(2))
            return db_date

        if arguments["info"]:

            TODO.implement()

        elif arguments["list"]:

            try:
                _name = arguments['--name']
                _user = arguments['--user']
                _project = arguments['--project']
                _format = arguments['--format']
                _hosts = arguments['--hosts']
                _start = arguments['--start']
                _end = arguments['--end']
                _format = arguments['--format']

                reserve = Reservation()
                dictionary = reserve.list(_name, _start, _end, _user, _project,
                                          _hosts)
                print(_print_dict(dictionary, format=_format))
                msg = "info. OK."
                Console.ok(msg)

            except Exception as e:
                Error.traceback(e)
                Console.error("Problem listing reservations")

        elif arguments["delete"]:
            if arguments["all"]:

                try:
                    reserve = Reservation()
                    reserve.delete()
                    msg = "info. OK."
                    Console.ok(msg)

                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem deleting all reservations")

            else:
                try:
                    _name = arguments['--name']
                    _user = arguments['--user']
                    _project = arguments['--project']
                    _format = arguments['--format']
                    _hosts = arguments['--hosts']
                    _start = arguments['--start']
                    _end = arguments['--end']
                    _format = arguments['--format']

                    reserve = Reservation()
                    reserve.delete(_name, _start, _end, _user, _project,
                                   _hosts)
                    msg = "info. OK."
                    Console.ok(msg)

                except Exception as e:
                    Error.traceback(e)
                    Console.error("Problem deleting reservations")

        elif arguments["add"]:

            if arguments["--file"] is None:
                name = None
                try:
                    name = arguments["--name"]
                    hosts = arguments["--hosts"]
                    user = arguments["--user"]
                    project = arguments["--project"]
                    description = arguments["--description"]

                    start_time = arguments[
                        "--start"] or "01/01/1901 at 07:30 pm"
                    end_time = arguments["--end"] or "12/31/2100 at 11:59 pm"

                    stime = Date(start_time)
                    etime = Date(end_time)

                    reserve = Reservation()
                    reserve.add(name,
                                _get_db_date_format(stime),
                                _get_db_date_format(etime),
                                hosts=hosts,
                                user=user,
                                project=project,
                                description=description)

                    print("Reservation {:} added successfully".format(name))
                    msg = "info. OK."
                    Console.ok(msg)

                except Exception as e:
                    Error.traceback(e)
                    Console.error(
                        "Problem adding reservation {:}".format(name))

            else:
                try:
                    TODO.implement()
                    """
                    with open(os.path.join(sys.path[0], arguments["--file"])) as file:
                        reader = csv.reader(file)
                        for row in reader:
                            reservations = Reservation(cm_id=row[0],
                                                    label=row[1],
                                                    user=row[2],
                                                    project=row[3],
                                                    start_time=row[4],
                                                    end_time=row[5],
                                                    host=row[6],
                                                    summary=row[7])
                            db.add()
                    """
                except Exception as e:
                    print("Error in adding from file. ", e)

        elif arguments["update"]:
            name = None
            try:
                name = arguments["--name"]
                hosts = arguments["--hosts"]
                user = arguments["--user"]
                project = arguments["--project"]
                description = arguments["--description"]

                start_time = arguments["--start"] or "01/01/1901 at 07:30 pm"
                end_time = arguments["--end"] or "12/31/2100 at 11:59 pm"

                stime = Date(start_time)
                etime = Date(end_time)

                reserve = Reservation()
                reserve.update(name,
                               _get_db_date_format(stime),
                               _get_db_date_format(etime),
                               hosts=hosts,
                               user=user,
                               project=project,
                               description=description)

                print("Reservation {:} updated successfully".format(name))
                msg = "info. OK."
                Console.ok(msg)

            except Exception as e:
                Error.traceback(e)
                Console.error("Problem updating reservation {:}".format(name))

        return ""
Ejemplo n.º 29
0
def main():
    """cm.

    Usage:
      cm --help
      cm [--debug] [--nosplash] [-i] [COMMAND ...]

    Arguments:
      COMMAND                  A command to be executed

    Options:
      --file=SCRIPT  -f  SCRIPT  Executes the script
      -i                 After start keep the shell interactive,
                         otherwise quit [default: False]
      --nosplash    do not show the banner [default: False]
    """

    def manual():
        print(main.__doc__)

    args = sys.argv[1:]

    arguments = {
        '--debug': '--debug' in args,
        '--nosplash': '--nosplash' in args,
        '-i': '-i' in args}

    for a in args:
        if a in arguments:
            args.remove(a)

    arguments['COMMAND'] = [' '.join(args)]

    commands = arguments["COMMAND"]
    if len(commands) > 0:
        if ".cm" in commands[0]:
            arguments["SCRIPT"] = commands[0]
            commands = commands[1:]
        else:
            arguments["SCRIPT"] = None

        arguments["COMMAND"] = ' '.join(commands)
        if arguments["COMMAND"] == '':
            arguments["COMMAND"] = None


    if arguments['COMMAND'] == []:
        arguments['COMMAND'] = None

    splash = not arguments['--nosplash']
    debug = arguments['--debug']
    interactive = arguments['-i']
    script = arguments["SCRIPT"]
    command = arguments["COMMAND"]



    context = CloudmeshContext(debug=debug,
                               splash=splash)
    cmd = CloudmeshConsole(context)


    if script is not None:
        cmd.do_exec(script)

    try:
        if debug:
            print(">", command)
        if command is not None:
            cmd.onecmd(command)
    except Exception, e:
        print("ERROR: executing command '{0}'".format(command))
        print(70 * "=")
        print(e)
        print(70 * "=")
        Error.traceback()