作为个人学习笔记分享,有任何问题欢迎交流!
(2013.7.5更新)
Nova中volume挂载流程分为两部分:挂载命令的发送和接收处理
1 挂载命令的发送
1.1提供API接口
代码来源:nova/api/openstack/contrib/volumes.py:VolumeAttachmentController.create():
@wsgi.serializers(xml=VolumeAttachmentTemplate)
def create(self, req, server_id, body):
"""Attach a volume to an instance."""
context = req.environ['nova.context']
authorize(context)
authorize_attach(context, action='create')
if not self.is_valid_body(body, 'volumeAttachment'):
raise exc.HTTPUnprocessableEntity()
#从请求中获取卷ID和设备名称
volume_id = body['volumeAttachment']['volumeId']
device = body['volumeAttachment'].get('device')
self._validate_volume_id(volume_id)
msg = _("Attach volume %(volume_id)s to instance %(server_id)s"
" at %(device)s") % locals()
LOG.audit(msg, context=context)
try:
instance = self.compute_api.get(context, server_id)#compute_api=compute.API(),compute.API()即为/nova/compute/__init__.py:API(*args,**kwargs),该函数导入了一个类,被导入的类是由_compute_opts中compute_api_class决定的,compute_api_class的默认值为:nova.compute.api.API,所以get()既是nova/compute/api.py:API.get(),根据实例ID获取一个实例。
device = self.compute_api.attach_volume(context, instance,
volume_id, device)#挂载一个存在的卷到一个存在的实例
except exception.NotFound:
raise exc.HTTPNotFound()
except exception.InstanceInvalidState as state_error:
common.raise_http_conflict_for_instance_invalid_state(state_error,
'attach_volume')
1.2发送RPCcast异步请求,给instance挂载上volume_id,挂载点在device.
代码来源:nova/compute/api.py:API.attach_volume(context, instance, volume_id,device)
#volume_api=nova/volume/cinder/api.py:API
try:
volume = self.volume_api.get(context, volume_id)通过cinderclient从cinder获取volume.
self.volume_api.check_attach(context, volume, instance=instance)#检查volume是否可用
self.volume_api.reserve_volume(context, volume)
self.compute_rpcapi.attach_volume(context, instance=instance,
volume_id=volume_id, mountpoint=device)#compute_rpcapi=nova/compute/rpcapi.py:ComputeAPI
except Exception:
with excutils.save_and_reraise_exception():
self.db.block_device_mapping_destroy_by_instance_and_device(
context, instance['uuid'], device)
#nova/compute/rpcapi.py:ComputeAPI.attach_volume():
def attach_volume(self, ctxt, instance, volume_id, mountpoint):
instance_p = jsonutils.to_primitive(instance)
self.cast(ctxt, self.make_msg('attach_volume',#cast调用
instance=instance_p, volume_id=volume_id,
mountpoint