Ejemplo n.º 1
0
    def list_nodes(self):
        nodes = []
        for n in self._provider.nodes():
            d = {}
            d['id'] = n.id
            d['key'] = n.key_name
            d['image_id'] = n.image_id
            d['private_ip'] = n.private_ip_address
            d['public_ip'] = n.public_ip_address
            d['state'] = n.state['Name']
            nodes.append(d)

        print(Printer.list(nodes))
Ejemplo n.º 2
0
    def do_openapi(self, args, arguments):
        """
        ::

          Usage:
              openapi generate [FUNCTION] --filename=FILENAME
                                         [--serverurl=SERVERURL]
                                         [--yamlfile=YAML]
                                         [--import_class]
                                         [--all_functions]
                                         [--enable_upload]
                                         [--verbose]
                                         [--basic_auth=CREDENTIALS]
              openapi server start YAML [NAME]
                              [--directory=DIRECTORY]
                              [--port=PORT]
                              [--server=SERVER]
                              [--host=HOST]
                              [--verbose]
                              [--debug]
                              [--fg]
                              [--os]
              openapi server stop NAME
              openapi server list [NAME] [--output=OUTPUT]
              openapi server ps [NAME] [--output=OUTPUT]
              openapi register add NAME ENDPOINT
              openapi register filename NAME
              openapi register delete NAME
              openapi register list [NAME] [--output=OUTPUT]
              openapi register protocol PROTOCOL
              openapi TODO merge [SERVICES...] [--dir=DIR] [--verbose]
              openapi TODO doc FILE --format=(txt|md)[--indent=INDENT]
              openapi TODO doc [SERVICES...] [--dir=DIR]
              openapi sklearn FUNCTION MODELTAG
              openapi sklearnreadfile FUNCTION MODELTAG
              openapi sklearn upload --filename=FILENAME

          Arguments:
              FUNCTION  The name for the function or class
              MODELTAG  The arbirtary name choosen by the user to store the Sklearn trained model as Pickle object
              FILENAME  Path to python file containing the function or class
              SERVERURL OpenAPI server URL Default: https://localhost:8080/cloudmesh
              YAML      Path to yaml file that will contain OpenAPI spec. Default: FILENAME with .py replaced by .yaml
              DIR       The directory of the specifications
              FILE      The specification

          Options:
              --import_class         FUNCTION is a required class name instead of an optional function name
              --all_functions        Generate OpenAPI spec for all functions in FILENAME
              --debug                Use the server in debug mode
              --verbose              Specifies to run in debug mode
                                     [default: False]
              --port=PORT            The port for the server [default: 8080]
              --directory=DIRECTORY  The directory in which the server is run
              --server=SERVER        The server [default: flask]
              --output=OUTPUT        The outputformat, table, csv, yaml, json
                                     [default: table]
              --srcdir=SRCDIR        The directory of the specifications
              --destdir=DESTDIR      The directory where the generated code
                                     is placed

          Description:
            This command does some useful things.

            openapi TODO doc FILE --format=(txt|md|rst) [--indent=INDENT]
                Sometimes it is useful to generate teh openaopi documentation
                in another format. We provide fucntionality to generate the
                documentation from the yaml file in a different formt.

            openapi TODO doc --format=(txt|md|rst) [SERVICES...]
                Creates a short documentation from services registered in the
                registry.

            openapi TODO merge [SERVICES...] [--dir=DIR] [--verbose]
                Merges tow service specifications into a single servoce
                TODO: do we have a prototype of this?


            openapi sklearn sklearn.linear_model.LogisticRegression
                Generates the .py file for the Model given for the generator

            openapi sklearnreadfile sklearn.linear_model.LogisticRegression
            Generates the .py file for the Model given for the generator which supports reading files

            openapi generate [FUNCTION] --filename=FILENAME
                                         [--serverurl=SERVERURL]
                                         [--yamlfile=YAML]
                                         [--import_class]
                                         [--all_functions]
                                         [--enable_upload]
                                         [--verbose]
                                         [--basic_auth=CREDENTIALS]
                Generates an OpenAPI specification for FUNCTION in FILENAME and
                writes the result to YAML. Use --import_class to import a class
                with its associated class methods, or use --all_functions to 
                import all functions in FILENAME. These options ignore functions
                whose names start with '_'. Use --enable_upload to add file
                upload functionality to a copy of your python file and the
                resulting yaml file.

                For optional basic authorization, we support (temporarily) a single user
                credential. CREDENTIALS should be formatted as follows:

                user:password

                Example: --basic_auth=admin:secret

            openapi server start YAML [NAME]
                              [--directory=DIRECTORY]
                              [--port=PORT]
                              [--server=SERVER]
                              [--host=HOST]
                              [--verbose]
                              [--debug]
                              [--fg]
                              [--os]
                starts an openapi web service using YAML as a specification
                TODO: directory is hard coded as None, and in server.py it
                  defaults to the directory where the yaml file lives. Can
                  we just remove this argument?

            openapi server stop NAME
                stops the openapi service with the given name
                TODO: where does this command has to be started from

            openapi server list [NAME] [--output=OUTPUT]
                Provides a list of all OpenAPI services in the registry

            openapi server ps [NAME] [--output=OUTPUT]
                list the running openapi service

            openapi register add NAME ENDPOINT
                Openapi comes with a service registry in which we can register
                openapi services.

            openapi register filename NAME
                In case you have a yaml file the openapi service can also be
                registerd from a yaml file

            openapi register delete NAME
                Deletes the names service from the registry

            openapi register list [NAME] [--output=OUTPUT]
                Provides a list of all registerd OpenAPI services


        """
        #print(arguments)
        map_parameters(arguments,
                       'fg',
                       'os',
                       'output',
                       'verbose',
                       'port',
                       'directory',
                       'yamlfile',
                       'serverurl',
                       'name',
                       'import_class',
                       'all_functions',
                       'enable_upload',
                       'host',
                       'basic_auth')
        arguments.debug = arguments.verbose

        #VERBOSE(arguments)

        if arguments.generate:
            if arguments.import_class and arguments.all_functions:
                Console.error('Cannot generate openapi with both --import_class and --all_functions')
            if arguments.import_class and not arguments.FUNCTION:
                Console.error('FUNCTION parameter (class name) is required when using --import_class')
            try:
                p = Parameter(arguments)
                p.Print()
                filename = p.filename # ./dir/myfile.py
                yamlfile = p.yamlfile # ./dir/myfile.yaml
                directory = p.yamldirectory # ./dir
                function = p.function # myfunction
                serverurl = p.serverurl # http://localhost:8080/cloudmesh/
                module_name = p.module_name # myfile
                basic_auth = p.basic_auth # user:password

                # If statement here for mode with basic_auth

                enable_upload = arguments.enable_upload
                # append the upload function to the end of a copy of the file if not already done
                if enable_upload:
                    uploadPython = textwrap.dedent("""
                        from cloudmesh.openapi.registry.fileoperation import FileOperation
                        
                        def upload() -> str:
                            filename=FileOperation().file_upload()
                            return filename
                        
                        #### upload functionality added
                        """)
                    upload_added = False
                    for line in open(filename):
                        if '#### upload functionality added' in line:
                            upload_added = True
                    if not upload_added:
                        filename_upload = filename.replace('.py', '_upload-enabled.py')
                        copyfile(filename, filename_upload)
                        Console.info(f'copied {filename} to {filename_upload}')
                        filename = filename_upload
                        module_name = module_name + '_upload-enabled'
                        with open(filename, 'a') as f:
                            f.write('\n')
                            f.write(uploadPython)
                        Console.info(f'added upload functionality to {filename}')

                if basic_auth:
                    user, password = basic_auth.split(':')
                    BasicAuth.reset_users()
                    BasicAuth.add_user(user, password)
                    module_name, filename = BasicAuth.write_basic_auth(
                        filename=filename,
                         module_name=module_name)

                # Parameter() takes care of putting the filename in the path
                imported_module = import_module(module_name)
                dataclass_list = []
                for attr_name in dir(imported_module):
                    attr = getattr(imported_module, attr_name)
                    if is_dataclass(attr):
                        dataclass_list.append(attr)
                # not currently supporting multiple functions or all functions
                # could do comma-separated function/class names

                if enable_upload:
                    upload_obj = getattr(imported_module, 'upload')
                    setattr(sys.modules[module_name], 'upload', upload_obj)

                if arguments.import_class:
                    class_obj = getattr(imported_module, function)
                    # do we maybe need to do this here?
                    # setattr(sys.modules[module_name], function, class_obj)
                    class_description = class_obj.__doc__.strip().split("\n")[0]
                    func_objects = {}
                    for attr_name in dir(class_obj):
                        attr = getattr(class_obj, attr_name)                        
                        if isinstance(attr, types.MethodType) and attr_name[0] != '_':
                            # are we sure this is right?
                            # would probably create a valid openapi yaml, but not technically accurate
                            # module.function may work but it should be module.Class.function
                            setattr(sys.modules[module_name], attr_name, attr)
                            func_objects[attr_name] = attr
                        elif is_dataclass(attr):
                            dataclass_list.append(attr)
                    openAPI = generator.Generator()
                    Console.info(
                        'Generating openapi for class: ' + class_obj.__name__)
                    openAPI.generate_openapi_class(class_name=class_obj.__name__,
                                                   class_description=class_description,
                                                   filename=filename,
                                                   func_objects=func_objects,
                                                   serverurl=serverurl,
                                                   outdir=directory,
                                                   yamlfile=yamlfile,
                                                   dataclass_list=dataclass_list,
                                                   all_function=False,
                                                   enable_upload=enable_upload,
                                                   basic_auth_enabled=basic_auth,
                                                   write=True)
                elif arguments.all_functions:
                    func_objects = {}
                    for attr_name in dir(imported_module):
                        if type(getattr(imported_module, attr_name)).__name__ == 'function' and attr_name[0] != '_':
                            func_obj = getattr(imported_module, attr_name)
                            setattr(sys.modules[module_name], attr_name, func_obj)
                            func_objects[attr_name] = func_obj
                    openAPI = generator.Generator()
                    Console.info(
                        'Generating openapi for all functions in file: ' + filename)
                    openAPI.generate_openapi_class(class_name=module_name,
                                                   class_description="No description provided",
                                                   filename=filename,
                                                   func_objects=func_objects,
                                                   serverurl=serverurl,
                                                   outdir=directory,
                                                   yamlfile=yamlfile,
                                                   dataclass_list=dataclass_list,
                                                   all_function=True,
                                                   enable_upload=enable_upload,
                                                   basic_auth_enabled=basic_auth,
                                                   write=True)

                else:
                    func_obj = getattr(imported_module, function)
                    setattr(sys.modules[module_name], function, func_obj)
                    openAPI = generator.Generator()
                    Console.info(
                        'Generating openapi for function: ' + func_obj.__name__)
                    openAPI.generate_openapi(f=func_obj,
                                             filename=filename,
                                             serverurl=serverurl,
                                             outdir=directory,
                                             yamlfile=yamlfile,
                                             dataclass_list=dataclass_list,
                                             enable_upload=enable_upload,
                                             basic_auth_enabled=basic_auth,
                                             write=True)

            except Exception as e:
                Console.error("Failed to generate openapi yaml")
                print(e)

        elif arguments.server and arguments.start and arguments.os:

            try:
                s = Server(
                    name=arguments.NAME,
                    spec=path_expand(arguments.YAML),
                    directory=path_expand(
                        arguments.directory) or arguments.directory,
                    port=arguments.port,
                    server=arguments.wsgi,
                    debug=arguments.debug
                )

                pid = s.run_os()

                VERBOSE(arguments, label="Server parameters")

                print(f"Run PID: {pid}")

            except FileNotFoundError:

                Console.error("specification file not found")

            except Exception as e:

                print(e)

        elif arguments.server and arguments.list:

            try:
                result = Server.list(name=arguments.NAME)

                # BUG: order= nt yet defined

                print(Printer.list(result))

            except ConnectionError:
                Console.error("Server not running")

        elif arguments.server and arguments.ps:

            try:
                print()
                Console.info("Running Cloudmesh OpenAPI Servers")
                print()
                result = Server.ps(name=arguments.NAME)
                print(Printer.list(result, order=["name", "pid", "spec"]))

                print()
            except ConnectionError:
                Console.error("Server not running")

        elif arguments.register and arguments.add:

            registry = Registry()
            result = registry.add(name=arguments.NAME, url=arguments.BASEURL,
                                  pid=arguments.PID)

            registry.Print(data=result, output=arguments.output)

        elif arguments.register and arguments.delete:

            registry = Registry()
            result = registry.delete(name=arguments.NAME)
            if result == 0:
                Console.error("Entry could not be found")
            elif result is not None:
                Console.ok("Ok. Entry deleted")
            else:
                Console.error("Could not delete entry")

        elif arguments.register and arguments.list:

            registry = Registry()
            result = registry.list(name=arguments.NAME)

            registry.Print(data=result, output=arguments.output)

        elif arguments.register and arguments.protocol:
            result = Registry.protocol(protocol=arguments.PROTOCOL)
            Console.ok(f"Using Registry Protocol: {result}")

        elif arguments.register and arguments['filename']:

            registry = Registry()
            result = [registry.add_form_file(arguments['filename'])]

            registry.Print(data=result, output=arguments.output)

        elif arguments.server and arguments.start:

            # VERBOSE(arguments)

            try:
                s = Server(
                    name=arguments.NAME,
                    spec=path_expand(arguments.YAML),
                    directory=None,
                    #directory=path_expand(
                    #    arguments.directory) or arguments.directory,
                    port=arguments.port,
                    host=arguments.host,
                    server=arguments.wsgi,
                    debug=arguments.debug)

                pid = s.start(name=arguments.NAME,
                              spec=path_expand(arguments.YAML),
                              foreground=arguments.fg)

                if pid is None:
                    pass
                else:
                    print(f"Run PID: {pid}")

            except FileNotFoundError:

                Console.error("specification file not found")

            except Exception as e:
                print(e)

        elif arguments.server and arguments.stop:

            try:
                print()
                Console.info("Stopping Cloudmesh OpenAPI Server")
                print()

                Server.stop(name=arguments.NAME)

                print()
            except ConnectionError:
                Console.error("Server not running")

        elif arguments.sklearn and not arguments.upload:

            try:
                Sklearngenerator(input_sklibrary=arguments.FUNCTION,
                                 model_tag=arguments.MODELTAG)
            except Exception as e:
                print(e)

        elif arguments.sklearnreadfile and not arguments.upload:

            try:
                SklearngeneratorFile(input_sklibrary=arguments.FUNCTION,
                                          model_tag=arguments.MODELTAG)
            except Exception as e:
                print(e)
        
        #TODO: implement this?
        elif arguments.sklearn and arguments.upload:

            try:
                openAPI = generator.Generator()
                openAPI.fileput()

            except Exception as e:
                print(e)

        '''
Ejemplo n.º 3
0
    def do_default(self, args, arguments):
        """
        ::

          Usage:
              default list [--context=CONTEXT] [--format=FORMAT]
              default delete --context=CONTEXT
              default delete KEY [--context=CONTEXT]
              default KEY [--context=CONTEXT]
              default KEY=VALUE [--CONTEXT=CONTEXT]

          Arguments:
            KEY    the name of the default
            VALUE  the value to set the key to

          Options:
             --context=CONTEXT    the name of the context
             --format=FORMAT  the output format. Values include
                              table, json, csv, yaml.

        Description:
            Cloudmesh has the ability to manage easily multiple
            clouds. One of the key concepts to manage multiple clouds
            is to use defaults for the cloud, the images, flavors,
            and other values. The default command is used to manage
            such default values. These defaults are used in other commands
            if they are not overwritten by a command parameter.

            The current default values can by listed with

                default list --all

            Via the default command you can list, set, get and delete
            default values. You can list the defaults with

               default list

            A default can be set with

                default KEY=VALUE

            To look up a default value you can say

                default KEY

            A default can be deleted with

                default delete KEY

            To be specific to a cloud you can specify the name of the
            cloud with the --cloud=CLOUD option. The list command can
            print the information in various formats iv specified.

        Examples:
            default list --all
                lists all default values

            default list --cloud=kilo
                lists the defaults for the cloud with the name kilo

            default image=xyz
                sets the default image for the default cloud to xyz

            default image=abc --cloud=kilo
                sets the default image for the cloud kilo to xyz

            default image
                list the default image of the default cloud

            default image --cloud=kilo
                list the default image of the cloud kilo

            default delete image
                deletes the value for the default image in the
                default cloud

            default delete image --cloud=kilo
                deletes the value for the default image in the
                cloud kilo

        """
        print(arguments)
        # print (">", args, "<")

        context = arguments["--context"] or "global"

        defaults = Default()

        if arguments["delete"]:

            key = arguments.KEY
            if key is None:
                del defaults[context]
            else:
                del defaults[context, key]
            # if not result :
            #    Console.error("default {} not present".format(key))
            # else:
            #    Console.ok("Deleted key {} for cloud {}. ok.".format(key,
            #                                                      cloud))
            return ""

        if arguments.KEY is not None:
            if "=" not in arguments.KEY:
                print(arguments.KEY,
                      "=",
                      defaults[context, arguments.KEY],
                      sep='')
            else:
                key, value = arguments["KEY"].split("=", 1)
                defaults[context, key] = value
            return ""

        if arguments["list"]:

            output_format = arguments["--format"] or defaults[
                "global", "output"] or 'table'

            if defaults is None:
                Console.error("No default values found")
            else:

                data = []
                d = defaults.__dict__()
                for context in d:
                    for key in d[context]:
                        data.append({
                            "context": context,
                            "key": key,
                            "value": d[context][key]
                        })
                print(Printer.list(data, output=output_format))
            return ""
Ejemplo n.º 4
0
 def list_flavors(self):
     flavors = self._provider.flavors()
     print(Printer.list(flavors))
Ejemplo n.º 5
0
    def do_openapi3(self, args, arguments):
        """
        ::

          Usage:
              openapi3 generate FUNCTION [YAML]
                                         --baseurl=BASEURL
                                         --filename=FILENAME
                                         --yamldirectory=DIRECTORY
                                         [--verbose]
              openapi3 server start YAML [NAME]
                              [--directory=DIRECTORY]
                              [--port=PORT]
                              [--server=SERVER]
                              [--verbose]
                              [--debug]
                              [--debug]
                              [--fg]
                              [--os]
              openapi3 server stop NAME
              openapi3 server list [NAME] [--output=OUTPUT]
              openapi3 server ps [NAME] [--output=OUTPUT]
              openapi3 register add NAME ENDPOINT
              openapi3 register filename NAME
              openapi3 register delete NAME
              openapi3 register list [NAME] [--output=OUTPUT]
              openapi3 tbd
              openapi3 tbd merge [SERVICES...] [--dir=DIR] [--verbose]
              openapi3 tdb list [--dir=DIR]
              openapi3 tbd description [SERVICES...] [--dir=DIR]
              openapi3 tbd md FILE [--indent=INDENT]
              openapi3 tbd codegen [SERVICES...] [--srcdir=SRCDIR]
                              [--destdir=DESTDIR]

          Arguments:
              DIR   The directory of the specifications
              FILE  The specification

          Options:
              --debug                use the server in debug mode
              --verbose              specifies to run in debug mode [default: False]
              --port=PORT            the port for the server [default: 8080]
              --directory=DIRECTORY  the directory in which the server is run
              --server=SERVER        the server [default: flask]
              --output=OUTPUT        the outputformat, table, csv, yaml, json [default: table]
              --srcdir=SRCDIR   The directory of the specifications
              --destdir=DESTDIR  The directory where the generated code should be put

          Description:
            This command does some useful things.


        """

        map_parameters(arguments, 'fg', 'os', 'output', 'verbose', 'port',
                       'directory', 'yamldirectory', 'baseurl', 'filename',
                       'name')
        arguments.debug = arguments.verbose

        # VERBOSE(arguments)

        if arguments.generate:

            try:
                function = arguments.FUNCTION
                yamlfile = arguments.YAML
                baseurl = path_expand(arguments.baseurl)
                filename = arguments.filename.strip().split(".")[0]
                yamldirectory = path_expand(arguments.yamldirectory)

                sys.path.append(baseurl)

                module_name = pathlib.Path(f"{filename}").stem

                imported_module = import_module(module_name)

                func_obj = getattr(imported_module, function)

                setattr(sys.modules[module_name], function, func_obj)

                # get dataclasses defined in module
                dataclass_list = []
                for attr_name in dir(imported_module):
                    #
                    # BUG: module is highloghted in pycharm
                    #
                    attr = getattr(imported_module, attr_name)
                    if is_dataclass(attr):
                        dataclass_list.append(attr)

                openAPI = generator.Generator()

                # BUG: this is windows specific and must be done differently
                # check if os.path.dirname, os.path.basename does this

                if sys.platform == 'win32':
                    baseurl_short = baseurl.split("\\")[-1]
                else:
                    baseurl_short = baseurl.split("/")[-1]
                openAPI.generate_openapi(func_obj, baseurl_short,
                                         yamldirectory, yamlfile,
                                         dataclass_list)
            except Exception as e:
                Console.error("Failed to generate openapi yaml")
                print(e)

        elif arguments.server and arguments.start and arguments.os:

            try:
                s = Server(spec=path_expand(arguments.YAML),
                           directory=path_expand(arguments.directory)
                           if arguments.directory else arguments.directory,
                           port=arguments.port,
                           server=arguments.wsgi,
                           debug=arguments.debug,
                           name=arguments.NAME)

                pid = s.run_os()

                VERBOSE(arguments, label="Server parameters")

                print(f"Run PID: {pid}")

            except FileNotFoundError:

                Console.error("specification file not found")

            except Exception as e:

                print(e)

        elif arguments.server and arguments.list:

            try:
                result = Server.list(self, name=arguments.NAME)

                # BUG: order= nt yet defined

                print(Printer.list(result))

            except ConnectionError:
                Console.error("Server not running")

        elif arguments.server and arguments.ps:

            try:
                print()
                Console.info("Running Cloudmesh OpenAPI Servers")
                print()
                result = Server.ps(name=arguments.NAME)

                print(Printer.list(result, order=["name", "pid", "spec"]))

                print()
            except ConnectionError:
                Console.error("Server not running")

        elif arguments.server and arguments.stop and arguments.os:

            try:
                Server.stop(self, name=arguments.NAME)
            except ConnectionError:
                Console.error("Server not running")

        elif arguments.register and arguments.add:

            registry = Registry()
            result = registry.add(name=arguments.NAME,
                                  url=arguments.BASEURL,
                                  pid=arguments.PID)

            registry.Print(data=result, output=arguments.output)

        elif arguments.register and arguments.delete:

            registry = Registry()
            result = registry.delete(name=arguments.NAME)
            if result == 0:
                Console.error("Entry could not be found")
            else:
                Console.ok("Ok. Entry deleted")

        elif arguments.register and arguments.list:

            registry = Registry()
            result = registry.list(name=arguments.NAME)

            registry.Print(data=result, output=arguments.output)

        elif arguments.register and arguments.filename:

            registry = Registry()
            result = [registry.add_form_file(arguments.filename)]

            registry.Print(data=result, output=arguments.output)

        elif arguments.server and arguments.start:

            # VERBOSE(arguments)

            try:
                s = Server(name=arguments.NAME,
                           spec=arguments.YAML,
                           directory=arguments.directory,
                           port=arguments.port,
                           server=arguments.wsgi,
                           debug=arguments.debug)

                print("spec: ", path_expand(arguments.YAML))
                pid = s.start(name=arguments.NAME,
                              spec=path_expand(arguments.YAML),
                              foreground=arguments.fg)

                print(f"Run PID: {pid}")

            except FileNotFoundError:

                Console.error("specification file not found")

            except Exception as e:
                print(e)

        elif arguments.server and arguments.stop:

            try:
                print()
                Console.info("Stopping Cloudmesh OpenAPI Server")
                print()

                Server.stop(name=arguments.NAME)

                print()
            except ConnectionError:
                Console.error("Server not running")
        '''