设为首页 收藏本站
查看: 1886|回复: 0

[经验分享] Openstack(Ocata)镜像创建流程分析

[复制链接]
累计签到:2 天
连续签到:2 天
发表于 2017-12-5 10:57:53 | 显示全部楼层 |阅读模式
  O版中镜像RESFUL请求默认是v2,与v1相比更复杂了。这里主要分析镜像创建(glance image-create)流程。
  glanceclient的命令do_image_create(v2/shell.py)分别执行了image = gc.images.create(**fields)、do_image_upload(gc, args)两步,分别对应api中create、upload方法
  1、glance.api.v2.images:ImageController中包含了create、index、delete等基本方法。



@utils.mutating
     #创建镜像对象:这里主要分析image_factory和image_repo的获取;try内容是生成一个image对象,并存放到repo中。此时只是存储到数据库中,并没有生成相应的image文件,size大小为None
     def create(self, req, image, extra_properties, tags):
         image_factory = self.gateway.get_image_factory(req.context)
         image_repo = self.gateway.get_repo(req.context)
         try:
             image = image_factory.new_image(extra_properties=extra_properties,      
                                             tags=tags, **image)
             image_repo.add(image)
         except (exception.DuplicateLocation,
                 exception.Invalid) as e:
             raise webob.exc.HTTPBadRequest(explanation=e.msg)
         except (exception.ReservedProperty,
                 exception.ReadonlyProperty) as e:
             raise webob.exc.HTTPForbidden(explanation=e.msg)
         except exception.Forbidden as e:
             LOG.debug("User not permitted to create image")
             raise webob.exc.HTTPForbidden(explanation=e.msg)
         except exception.LimitExceeded as e:
             LOG.warn(encodeutils.exception_to_unicode(e))
             raise webob.exc.HTTPRequestEntityTooLarge(
                 explanation=e.msg, request=req, content_type='text/plain')
         except exception.Duplicate as e:
             raise webob.exc.HTTPConflict(explanation=e.msg)
         except exception.NotAuthenticated as e:
             raise webob.exc.HTTPUnauthorized(explanation=e.msg)
         except TypeError as e:
             LOG.debug(encodeutils.exception_to_unicode(e))
             raise webob.exc.HTTPBadRequest(explanation=e)

         return image


#依次将domain、location、quota、policy、notifier、authorization作为构造对
#像参数。返回一个FactoryProxy。
def get_image_factory(self, context):
         image_factory = glance.domain.ImageFactory()
         store_image_factory = glance.location.ImageFactoryProxy(
             image_factory, context, self.store_api, self.store_utils)
         quota_image_factory = glance.quota.ImageFactoryProxy(
             store_image_factory, context, self.db_api, self.store_utils)
         policy_image_factory = policy.ImageFactoryProxy(
             quota_image_factory, context, self.policy)
         notifier_image_factory = glance.notifier.ImageFactoryProxy(
             policy_image_factory, context, self.notifier)
         #api.conf中property_protection_file默认为None
         if property_utils.is_property_protection_enabled():
             property_rules = property_utils.PropertyRules(self.policy)
             pif = property_protections.ProtectedImageFactoryProxy(
                 notifier_image_factory, context, property_rules)
             authorized_image_factory = authorization.ImageFactoryProxy(
                 pif, context)
         else:
             #执行如下流程
             authorized_image_factory = authorization.ImageFactoryProxy(
                 notifier_image_factory, context)
         return authorized_image_factory


#获取仓库repo,用于存储image对象。
def get_repo(self, context):
         image_repo = glance.db.ImageRepo(context, self.db_api)
         store_image_repo = glance.location.ImageRepoProxy(
             image_repo, context, self.store_api, self.store_utils)
         quota_image_repo = glance.quota.ImageRepoProxy(
             store_image_repo, context, self.db_api, self.store_utils)
         policy_image_repo = policy.ImageRepoProxy(
             quota_image_repo, context, self.policy)
         notifier_image_repo = glance.notifier.ImageRepoProxy(
             policy_image_repo, context, self.notifier)
         if property_utils.is_property_protection_enabled():
             property_rules = property_utils.PropertyRules(self.policy)
             pir = property_protections.ProtectedImageRepoProxy(
                 notifier_image_repo, context, property_rules)
             authorized_image_repo = authorization.ImageRepoProxy(
                 pir, context)
         else:
             authorized_image_repo = authorization.ImageRepoProxy(
                 notifier_image_repo, context)

         return authorized_image_repo
  2、glance.api.v2.image_data:ImageDataController中upload方法主要包括以下几步:
  a、获取image_repo = self.gateway.get_repo(req.context)
  b、image = image_repo.get(image_id)
         image.status = 'saving'
  c、image_repo.save(image, from_state='queued')  save方法会将镜像image信息更新到db
         image.set_data(data, size)
  d、image_repo.save(image, from_state='saving')   这里data是一个eventlet.wsgi.Input对象
  3、重点分析set_data方法:其分别执行了glance.notifier和glance.location模块中set_data方法。其中glance.location.ImageProxy中set_data为镜像文件的实际上传过程。



def set_data(self, data, size=None):
         if size is None:
             size = 0  # NOTE(markwash): zero -> unknown size
         # Create the verifier for signature verification (if correct properties
         # are present)
         extra_props = self.image.extra_properties
         if (signature_utils.should_create_verifier(extra_props)):
             # NOTE(bpoulos): if creating verifier fails, exception will be
             # raised
             img_signature = extra_props[signature_utils.SIGNATURE]
             hash_method = extra_props[signature_utils.HASH_METHOD]
             key_type = extra_props[signature_utils.KEY_TYPE]
             cert_uuid = extra_props[signature_utils.CERT_UUID]
             verifier = signature_utils.get_verifier(
                 context=self.context,
                 img_signature_certificate_uuid=cert_uuid,
                 img_signature_hash_method=hash_method,
                 img_signature=img_signature,
                 img_signature_key_type=key_type
             )
         else:
             verifier = None
         #用glance_store模块完成文件上传到glance目录中,
         location, size, checksum, loc_meta = self.store_api.add_to_backend(
             CONF,
             self.image.image_id,
             utils.LimitingReader(utils.CooperativeReader(data),
                                  CONF.image_size_cap),
             size,
             context=self.context,
             verifier=verifier)

         # NOTE(bpoulos): if verification fails, exception will be raised
         if verifier:
             try:
                 verifier.verify()
                 LOG.info(_LI("Successfully verified signature for image %s"),
                          self.image.image_id)
             except crypto_exception.InvalidSignature:
                 raise cursive_exception.SignatureVerificationError(
                     _('Signature verification failed')
                 )
         #更新镜像相关属性
         self.image.locations = [{'url': location, 'metadata': loc_meta,
                                  'status': 'active'}]
         self.image.size = size
         self.image.checksum = checksum
         self.image.status = 'active'
  默认情况下,镜像的virtual_size值为None。这里如果需要该值,则需要调用qemu-img info image-file获取virtual-size和size大小。修改1:获取virtual-size大小;修改2:设置image的virtual-size。



#glance.common.utils.py增加get_virtual_size方法
def get_virtual_size(image_id):
     try:
         file_path = os.path.join(CONF.glance_store.filesystem_store_datadir, image_id)
         stdout, stderr = putils.trycmd('qemu-img', 'info',
                                            '--output=json', file_path,
                                            prlimit=utils.QEMU_IMG_PROC_LIMITS,
                                            log_errors=putils.LOG_ALL_ERRORS)
     except OSError as exc:
         if exc.errno != 2:
             with excutils.save_and_reraise_exception():
                 exc_message = encodeutils.exception_to_unicode(exc)
                 msg = _LE('Failed to execute introspection '
                               '%(task_id)s: %(exc)s')
                 LOG.error(msg, {'task_id': self.task_id,
                                     'exc': exc_message})
             return
         if stderr:
             raise RuntimeError(stderr)
     metadata = json.loads(stdout)
     virtual_size = metadata.get('virtual-size', 0)
     return virtual_size
  glance.location中set_data方法增加:self.image.virtual_size = utils.get_virtual_size(self.image.image_id)

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-420763-1-1.html 上篇帖子: openstack 之~keystone之网关协议 下篇帖子: 深度探索 OpenStack Neutron:BGP(1) 【转载】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表