首页 > 代码库 > nova-api中ExtensionManager的构造

nova-api中ExtensionManager的构造

nova/api/openstack/__init__.py

APIRouter类:def __init__(self, ext_mgr=None, init_only=None):    if ext_mgr is None:        if self.ExtensionManager:            ext_mgr = self.ExtensionManager()        else:            raise Exception(_("Must specify an ExtensionManager class"))    ...

      其中的ExtensionManager由子类nova/api/openstack/computer/__init__.py中的APIRouter指定为nova/api/openstack/computer/extensions.py中的ExtensionManager类,下面看其构造函数:

class ExtensionManager(base_extensions.ExtensionManager):    def __init__(self):        LOG.audit(_(Initializing extension manager.))        self.cls_list = CONF.osapi_compute_extension        self.extensions = {}        self.sorted_ext_list = []        self._load_extensions()

     其中self.cls_list是扩展包的引导类列表,此处为[nova.api.openstack.compute.contrib.standard_extensions]。接着看self._load_extensions()的内容,由于ExtensionManager的类继承关系,该函数为nova.api.openstack. extensions ExtensionManager的函数,内容如下:

def _load_extensions(self):    extensions = list(self.cls_list)    for ext_factory in extensions:        try:            self.load_extension(ext_factory)        except Exception as exc:            LOG.warn(_(Failed to load extension %(ext_factory)s:                        %(exc)s),                     {ext_factory: ext_factory, exc: exc})

       其中self.load_extension函数内容如下:

def load_extension(self, ext_factory):    LOG.debug(_("Loading extension %s"), ext_factory)    if isinstance(ext_factory, basestring):        factory = importutils.import_class(ext_factory)    else:        factory = ext_factory    LOG.debug(_("Calling extension factory %s"), ext_factory)    factory(self)

      整个过程就是调用nova.api.openstack.compute.contrib.standard_extensions。接下来看standard_extensions函数,内容如下:

def standard_extensions(ext_mgr):    extensions.load_standard_extensions(ext_mgr, LOG, __path__, __package__)

     其中extensions为nova.api.openstack.extensions,看load_standard_extensions内容如下:

def load_standard_extensions(ext_mgr, logger, path, package, ext_list=None):    our_dir = path[0]    for dirpath, dirnames, filenames in os.walk(our_dir):        relpath = os.path.relpath(dirpath, our_dir)        if relpath == .:            relpkg = ‘‘        else:            relpkg = .%s % ..join(relpath.split(os.sep))        for fname in filenames:            root, ext = os.path.splitext(fname)            if ext != .py or root == __init__:                continue            classname = "%s%s" % (root[0].upper(), root[1:])            classpath = ("%s%s.%s.%s" %                         (package, relpkg, root, classname))            if ext_list is not None and classname not in ext_list:                logger.debug("Skipping extension: %s" % classpath)                continue            try:                ext_mgr.load_extension(classpath)            except Exception as exc:                logger.warn(_(Failed to load extension %(classpath)s:                               %(exc)s),                            {classpath: classpath, exc: exc})        ...

       实际上也就是调用之前ExtensionManager的 load_extension函数加载模块,并构造模块中与模块名对应的类,由于这些类都是nova.api.openstack.extensions.ExtensionDescriptor的子类,且看其__init__函数:

def __init__(self, ext_mgr):    ext_mgr.register(self)    self.ext_mgr = ext_mgr

  可知构造这些扩展类会在ExtensionManager中进行注册,注册过程就是在ExtensionManag中将扩展类的实例存入ExtensionManager的extensions列表中,对应的key为扩展类的alias。

  综上所述,ExtensionManager的构造就是对其中的self.cls_list进行加载调用,self.cls_list包含扩展包的引导类或引导函数,此处为nova.api.openstack.compute.contrib.standard_extensions,该引导函数负责加载扩展包中模块,并构造相应的类实例,这些类实例在构造时会向ExtensionManager进行注册。

nova-api中ExtensionManager的构造