rebuild 重建:
虚拟重置为初始状态, 或者更换镜像等
一.API
API入口在nova/api/openstack/compute/servers.py
@wsgi.action('rebuild')
@validation.schema(schema_server_rebuild_v20, '2.0', '2.0')
@validation.schema(schema_server_rebuild, '2.1', '2.18')
@validation.schema(schema_server_rebuild_v219, '2.19')
def _action_rebuild(self, req, id, body):
"""Rebuild an instance with the given attributes."""
rebuild_dict = body['rebuild']
// 重建的镜像参数
image_href = rebuild_dict["imageRef"]
// 重建指定密码
password = self._get_server_admin_password(rebuild_dict)
// 校验instance 以及 校验是否允许rebuild权限
context = req.environ['nova.context']
instance = self._get_server(context, req, id)
context.can(server_policies.SERVERS % 'rebuild',
target={'user_id': instance.user_id,
'project_id': instance.project_id})
attr_map = {
'name': 'display_name',
'description': 'display_description',
'metadata': 'metadata',
}
kwargs = {}
helpers.translate_attributes(helpers.REBUILD, rebuild_dict, kwargs)
for request_attribute, instance_attribute in attr_map.items():
try:
if request_attribute == 'name':
kwargs[instance_attribute] = common.normalize_name(
rebuild_dict[request_attribute])
else:
kwargs[instance_attribute] = rebuild_dict[
request_attribute]
except (KeyError, TypeError):
pass
try:
// 重建
self.compute_api.rebuild(context,
instance,
image_href,
password,
**kwargs)
except exception.InstanceIsLocked as e:
raise exc.HTTPConflict(explanation=e.format_message())
except exception.InstanceInvalidState as state_error:
common.raise_http_conflict_for_instance_invalid_state(state_error,
'rebuild', id)
......
instance = self._get_server(context, req, id, is_detail=True)
view = self._view_builder.show(req, instance, extend_address=False)
# Add on the admin_password attribute since the view doesn't do it
# unless instance passwords are disabled
if CONF.api.enable_instance_password:
view['server']['adminPass'] = password
robj = wsgi.ResponseObject(view)
return self._add_location(robj)
二. compute rebuild
compute_api.rebuild 定义在nova/compute/api.py
该函数为一个长函数, 这里进行拆分查看
@check_instance_lock
@check_instance_cell
// 校验虚拟机状态, 只允许在指定状态下进行
@check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED,
vm_states.ERROR])
def rebuild(self, context, instance, image_href, admin_password,
files_to_inject=None, **kwargs):
// 获取参数, 并进行参数校验
files_to_inject = files_to_inject or []
metadata = kwargs.get('metadata', {})
preserve_ephemeral = kwargs.get('preserve_ephemeral', False)
auto_disk_config = kwargs.get('auto_disk_config')
image_id, image = self._get_image(context, image_href)
self._check_auto_disk_config(image=image, **kwargs)
flavor = instance.get_flavor()
获取磁盘的mapping信息
bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
context, instance.uuid)
root_bdm = compute_utils.get_root_bdm(context, instance, bdms)
# Check to see if the image is changing and we have a volume-backed
# server.
is_volume_backed = compute_utils.is_volume_backed_instance(
context, instance, bdms)
if is_volume_backed:
# For boot from volume, instance.image_ref is empty, so we need to
# query the image from the volume.
if root_bdm is None:
# This shouldn't happen and is an error, we need to fail. This
# is not the users fault, it's an internal error. Without a
# root BDM we have no way of knowing the backing volume (or
# image in that volume) for this instance.
raise exception.NovaException(
_('Unable to find root block device mapping for '
'volume-backed instance.'))
volume = self.volume_api.get(context, root_bdm.volume_id)