The entire Web services portal

CMD start cinder – volume – API/root/cinder cinder/CMD/API. Py

def main():
  .....
  server = service.WSGIService('osapi_volume')...Copy the code

Create a snippet of WsgiServer

The default CONF contains osAPI_volume_LISTEN and osAPI_volume_listen_port

# IP address on which OpenStack Volume API listens (string value)
# osapi_volume_listen = 0.0.0.0

# Port on which OpenStack Volume API listens (port value)
# Minimum value: 0
# Maximum value: 65535
#osapi_volume_listen_port = 8776
Copy the code
class WSGIService(service.ServiceBase):
    """Provides ability to launch API from a 'paste' configuration."""

    def __init__(self, name, loader=None):
        """Initialize, but do not start the WSGI server. :param name: The name of the WSGI server given to the loader. :param loader: Loads the WSGI application using the given name. :returns: None """
        self.name = name
        self.manager = self._get_manager()
        self.loader = loader or wsgi.Loader(CONF)
        self.app = self.loader.load_app(name)
        self.host = getattr(CONF, '%s_listen' % name, "0.0.0.0")
        self.port = getattr(CONF, '%s_listen_port' % name, 0)
        self.workers = (getattr(CONF, '%s_workers' % name, None) or
                        processutils.get_worker_count())
        if self.workers and self.workers < 1:
            worker_name = '%s_workers' % name
            msg = (_("%(worker_name)s value of %(workers)d is invalid, "
                     "must be greater than 0.") %
                   {'worker_name': worker_name,
                    'workers': self.workers})
            raise exception.InvalidInput(msg)
        setup_profiler(name, self.host)

        self.server = wsgi.Server(CONF,
                                  name,
                                  self.app,
                                  host=self.host,
                                  port=self.port)
Copy the code

Paste Configuration file

Run the following command to paste composite, filter, app, and pipeline../cinder /etc/cinder-api-paste


[composite:osapi_volume]
use = call:cinder.api:root_app_factory
/: apiversions

Copy the code
  1. Root_app_factory method in cinder/api.py

def root_app_factory(loader, global_conf, **local_conf):
    if CONF.enable_v1_api:
        LOG.warning(_LW('The v1 api is deprecated and is not under active '
                        'development. You should set enable_v1_api=false '
                        'and enable_v3_api=true in your cinder.conf file.'))
    return paste.urlmap.urlmap_factory(loader, global_conf, **local_conf)

Copy the code
  1. Continue looking for the ApiVersion

[pipeline:apiversions]
pipeline = cors http_proxy_to_wsgi faultwrap osvolumeversionapp

Copy the code
  1. Continue looking for osVolumeVersionApp

[app:osvolumeversionapp]
paste.app_factory = cinder.api.versions:Versions.factory

Copy the code
  1. Continue to find cinder. API. Versions: versions. The factory

The action parameter of mapper is responsible for calling the method of the same name in resource(a Controller class)


class Versions(openstack.APIRouter):
    """Route versions requests."""

    ExtensionManager = extensions.ExtensionManager

    def _setup_routes(self, mapper, ext_mgr):
        self.resources['versions'] = create_resource()
        mapper.connect('versions'.'/',
                       controller=self.resources['versions'],
                       action='all')
        mapper.redirect(' '.'/')

Copy the code
  1. But there is no factory method in the Versions class, so go ahead and look for its parent

class APIRouter(base_wsgi.Router):
    """Routes requests on the API to the appropriate controller and method."""
    ExtensionManager = None  # override in subclasses

    @classmethod
    def factory(cls, global_config, **local_config):
        """Simple paste factory, :class:`cinder.wsgi.Router` doesn't have."""
        returnCLS () omits some code.....Copy the code
  1. Having found the factory Factory method, we continue back to the Versions class returned by the factory

Action =’all’ is bound to the Controller class returned by create_resource()


def create_resource():
    return wsgi.Resource(VersionsController())

Copy the code

Go to see the definition of VersionController class. / cinder cinder/API/versions. Py

Class VersionsController(wsgi.controller): def __init__(self): super(VersionsController, self).__init__(None) omit some code... @wsgi.response(300) def all(self, req):"""Return all known versions."""
        builder = views_versions.get_view_builder(req)
        known_versions = copy.deepcopy(_KNOWN_VERSIONS)
        return builder.build_versions(known_versions)

Copy the code

So typing http://volume_api_ip:8776/ in the browser will lead to the versionapp all method, which is actually called

Build_versions (known_versions) returns a dictionary that can be json.

View the file. / cinder cinder/API/views/versions. Py

class ViewBuilder(object):
    def __init__(self, base_url):
        """Initialize ViewBuilder. :param base_url: url of the root wsgi application """
        self.base_url = base_url

    def build_versions(self, versions):
        views = [self._build_version(versions[key])
                 for key in sorted(list(versions.keys()))]
        return dict(versions=views)
Copy the code