sfPPP / openstack-note

note
5 stars 0 forks source link

Openstack nova client分析 #95

Open sfPPP opened 6 years ago

sfPPP commented 6 years ago

参考连接 目录结构:

├── api_versions.py
├── base.py       -------------提供基本的Manager基类
├── client.py      -------------主要提供HTTPClient类,也提供根据版本创建Client对象的函数
├── crypto.py
├── exceptions.py
├── extension.py
├── i18n.py
├── __init__.py
├── shell.py        -------------命令解析,创建相应版本的Client类对象,调用相应版本的shell.py中的函数
├── tests
├── utils.py
└── v2 
         ├── agents.py
         ├── aggregates.py
         ├── assisted_volume_snapshots.py
         ├── availability_zones.py
         ├── cells.py
         ├── certs.py
         ├── client.py
         ├── cloudpipe.py
         ├── contrib
         ├── flavor_access.py
         ├── flavors.py
         ├── hosts.py
         ├── hypervisors.py
         ├── images.py
         ├── __init__.py
         ├── instance_action.py
         ├── keypairs.py
         ├── limits.py
         ├── list_extensions.py
         ├── migrations.py
         ├── networks.py
         ├── quota_classes.py
         ├── quotas.py
         ├── server_external_events.py
         ├── server_groups.py
         ├── server_migrations.py
         ├── servers.py
         ├── services.py
         ├── shell.py     ---------提供每个Command对应的方法
         ├── usage.py
         ├── versions.py
         ├── virtual_interfaces.py
         ├── volumes.py

shell.py

def main():
    try:
        argv = [encodeutils.safe_decode(a) for a in sys.argv[1:]]
        OpenStackComputeShell().main(argv)

OpenStackComputeShell 类

class OpenStackComputeShell(object):
    times = []

    def __init__(self):
        self.client_logger = None

    def _append_global_identity_args(self, parser, argv):
        # Register the CLI arguments that have moved to the session object.
        loading.register_session_argparse_arguments(parser)
        # Peek into argv to see if os-auth-token or os-token were given,
        # in which case, the token auth plugin is what the user wants
        # else, we'll default to password
        default_auth_plugin = 'password'
        if 'os-token' in argv:
            default_auth_plugin = 'token'
        loading.register_auth_argparse_arguments(
            parser, argv, default=default_auth_plugin)

        parser.set_defaults(insecure=strutils.bool_from_string(
            utils.env('NOVACLIENT_INSECURE', default=False)))
        parser.set_defaults(os_auth_url=utils.env('OS_AUTH_URL', 'NOVA_URL'))

        parser.set_defaults(os_username=utils.env('OS_USERNAME',
                                                  'NOVA_USERNAME'))
        parser.set_defaults(os_password=utils.env('OS_PASSWORD',
                                                  'NOVA_PASSWORD'))
        parser.set_defaults(os_project_name=utils.env(
            'OS_PROJECT_NAME', 'OS_TENANT_NAME', 'NOVA_PROJECT_ID'))
        parser.set_defaults(os_project_id=utils.env(
            'OS_PROJECT_ID', 'OS_TENANT_ID'))

    def get_base_parser(self, argv):
        parser = NovaClientArgumentParser(
            prog='nova',
            description=__doc__.strip(),
            epilog='See "nova help COMMAND" '
                   'for help on a specific command.',
            add_help=False,
            formatter_class=OpenStackHelpFormatter,
        )

        # Global arguments
        parser.add_argument(
            '-h', '--help',
            action='store_true',
            help=argparse.SUPPRESS,
        )

base.py 定义了所有操作的Manager类

class Manager(HookableMixin):
    """Manager for API service.

    Managers interact with a particular type of API (servers, flavors, images,
    etc.) and provide CRUD operations for them.
    """
    resource_class = None
    cache_lock = threading.RLock()

    def __init__(self, api):
        self.api = api

    @property
    def client(self):
        return self.api.client

    @property
    def api_version(self):
        return self.api.api_version

    def _list(self, url, response_key, obj_class=None, body=None):
        if body:
            resp, body = self.api.client.post(url, body=body)
        else:
            resp, body = self.api.client.get(url)

        if obj_class is None:
            obj_class = self.resource_class

        data = body[response_key]
        # NOTE(ja): keystone returns values as list as {'values': [ ... ]}
        #           unlike other services which just return the list...
        if isinstance(data, dict):
            try:
                data = data['values']
            except KeyError:
                pass

        with self.completion_cache('human_id', obj_class, mode="w"):
 ....................................................................
    def write_to_completion_cache(self, cache_type, val):
        cache = getattr(self, "_%s_cache" % cache_type, None)
        if cache:
            cache.write("%s\n" % val)

    def _get(self, url, response_key):
        resp, body = self.api.client.get(url)
        if response_key is not None:
            content = body[response_key]
        else:
            content = body
        return self.resource_class(self, content, loaded=True,
                                   resp=resp)

    def _create(self, url, body, response_key, return_raw=False, **kwargs):
        self.run_hooks('modify_body_for_create', body, **kwargs)
        resp, body = self.api.client.post(url, body=body)
        if return_raw:
            return self.convert_into_with_meta(body[response_key], resp)

        with self.completion_cache('human_id', self.resource_class, mode="a"):
            with self.completion_cache('uuid', self.resource_class, mode="a"):
                return self.resource_class(self, body[response_key], resp=resp)

    def _delete(self, url):
        resp, body = self.api.client.delete(url)
        return self.convert_into_with_meta(body, resp)

    def _update(self, url, body, response_key=None, **kwargs):
        self.run_hooks('modify_body_for_update', body, **kwargs)
        resp, body = self.api.client.put(url, body=body)
        if body:
            if response_key:
                return self.resource_class(self, body[response_key], resp=resp)
            else:
                return self.resource_class(self, body, resp=resp)
        else:
            return StrWithMeta(body, resp)

    def convert_into_with_meta(self, item, resp):
        if isinstance(item, six.string_types):
            if six.PY2 and isinstance(item, six.text_type):
                return UnicodeWithMeta(item, resp)
            else:
                return StrWithMeta(item, resp)
        elif isinstance(item, six.binary_type):
            return BytesWithMeta(item, resp)
        elif isinstance(item, list):
            return ListWithMeta(item, resp)
        elif isinstance(item, tuple):
            return TupleWithMeta(item, resp)
        elif item is None:
            return TupleWithMeta((), resp)
        else:
            return DictWithMeta(item, resp)