写在前面的话:
今天,继续接着昨天的内容,进行本文,若想参考之前的帖子,请参考下面内容:
1、OpenStack建立实例完整过程源码详细分析(1)
2、OpenStack建立实例完整过程源码详细分析(2)
3、OpenStack建立实例完整过程源码详细分析(3)
好了,咱们内容继续
再回到源码详细分析(1)中最开始的方法run_instances:
- def run_instances(self, context, **kwargs):
- """
- 准备实例,并且发送实例的信息和要运行实例的请求消息到远程调度器scheduler;
- 实现实例的简历和运行,由调度器完成;
- """
-
- # 设置最小建立实例的数目;
- min_count = int(kwargs.get('min_count', 1))
-
- # 获取kwargs['kernel_id']指定的镜像image数据返回给kernel;
- # 获取更新的kwargs['kernel_id'];
- if kwargs.get('kernel_id'):
- kernel = self._get_image(context, kwargs['kernel_id'])
- # 根据kernel['id']查询数据库中匹配的S3镜像数据,获取它的uuid属性,并返回;
- # 返回匹配的db.models.S3Image.uuid给kwargs['kernel_id'];
- kwargs['kernel_id'] = ec2utils.id_to_glance_id(context, kernel['id'])
-
- # 获取kwargs['ramdisk_id']指定的镜像image数据返回给ramdisk;
- # 获取更新的kwargs['ramdisk_id'];
- if kwargs.get('ramdisk_id'):
- ramdisk = self._get_image(context, kwargs['ramdisk_id'])
- # 根据ramdisk['id']查询数据库中匹配的S3镜像数据,获取它的uuid属性,并返回;
- # 返回匹配的db.models.S3Image.uuid给kwargs['ramdisk_id'];
- kwargs['ramdisk_id'] = ec2utils.id_to_glance_id(context, ramdisk['id'])
-
- # 循环获取每一个块设备映射;
- # 解析块设备映射bdm;
- for bdm in kwargs.get('block_device_mapping', []):
- _parse_block_device_mapping(bdm)
-
- # 获取kwargs['image_id']指定的镜像image数据;
- image = self._get_image(context, kwargs['image_id'])
- # 根据image['id']查询数据库中匹配的S3镜像数据,获取它的uuid属性,并返回;
- # 返回匹配的db.models.S3Image.uuid给image_uuid;
- image_uuid = ec2utils.id_to_glance_id(context, image['id'])
-
- # 获取镜像image的状态;
- if image:
- image_state = self._get_image_state(image)
- else:
- raise exception.ImageNotFoundEC2(image_id=kwargs['image_id'])
-
- if image_state != 'available':
- raise exception.EC2APIError(_('Image must be available'))
-
- (instances, resv_id) = self.compute_api.create(context,
- instance_type=instance_types.get_instance_type_by_name(kwargs.get('instance_type', None)),
- image_href=image_uuid,
- max_count=int(kwargs.get('max_count', min_count)),
- min_count=min_count,
- kernel_id=kwargs.get('kernel_id'),
- ramdisk_id=kwargs.get('ramdisk_id'),
- key_name=kwargs.get('key_name'),
- user_data=kwargs.get('user_data'),
- security_group=kwargs.get('security_group'),
- availability_zone=kwargs.get('placement', {}).get('availability_zone'),
- block_device_mapping=kwargs.get('block_device_mapping', {}))
- return self._format_run_instances(context, resv_id)
复制代码
我们来解析第二个比较重要的语句_parse_block_device_mapping(bdm):
我们先来看看kwargs中'block_device_mapping'所表示的数据形式:
- [
- ({'device_name': '/dev/fake0',
- 'ebs': {'snapshot_id': 'snap-12345678',
- 'volume_size': 1}},
- {'device_name': '/dev/fake0',
- 'snapshot_id': '00000000-1111-2222-3333-444444444444',
- 'volume_size': 1,
- 'delete_on_termination': True}),
-
- ({'device_name': '/dev/fake1',
- 'ebs': {'snapshot_id': 'snap-23456789',
- 'delete_on_termination': False}},
- {'device_name': '/dev/fake1',
- 'snapshot_id': '11111111-2222-3333-4444-555555555555',
- 'delete_on_termination': False}),
-
- ({'device_name': '/dev/fake2',
- 'ebs': {'snapshot_id': 'vol-87654321',
- 'volume_size': 2}},
- {'device_name': '/dev/fake2',
- 'volume_id': '22222222-3333-4444-5555-666666666666',
- 'volume_size': 2,
- 'delete_on_termination': True}),
-
- ({'device_name': '/dev/fake3',
- 'ebs': {'snapshot_id': 'vol-98765432',
- 'delete_on_termination': False}},
- {'device_name': '/dev/fake3',
- 'volume_id': '77777777-8888-9999-0000-aaaaaaaaaaaa',
- 'delete_on_termination': False}),
-
- ({'device_name': '/dev/fake4',
- 'ebs': {'no_device': True}},
- {'device_name': '/dev/fake4',
- 'no_device': True}),
-
- ({'device_name': '/dev/fake5',
- 'virtual_name': 'ephemeral0'},
- {'device_name': '/dev/fake5',
- 'virtual_name': 'ephemeral0'}),
-
- ({'device_name': '/dev/fake6',
- 'virtual_name': 'swap'},
- {'device_name': '/dev/fake6',
- 'virtual_name': 'swap'}),
- ]
复制代码
2.方法_parse_block_device_mapping的源码分析:
- def _parse_block_device_mapping(bdm):
- """
- 解析块设备映射bdm;
- """
- ebs = bdm.pop('ebs', None)
- if ebs:
- ec2_id = ebs.pop('snapshot_id', None)
- if ec2_id:
- # 判断如果是快照;
- # 则根据获取的ec2_id值,从匹配的数据库信息中获取uuid值赋值给bdm['snapshot_id'],更新bdm中的相应数据;
- if ec2_id.startswith('snap-'):
- bdm['snapshot_id'] = ec2utils.ec2_snap_id_to_uuid(ec2_id)
- # 判断如果是volume;
- # 则根据获取的ec2_id值,从匹配的数据库信息中获取uuid值赋值给bdm['snapshot_id'],更新bdm中的相应数据;
- elif ec2_id.startswith('vol-'):
- bdm['volume_id'] = ec2utils.ec2_vol_id_to_uuid(ec2_id)
-
- ebs.setdefault('delete_on_termination', True)
-
- # 更新bdm;
- bdm.update(ebs)
-
- # 返回更新后的bdm;
- return bdm
复制代码
这个方法主要完成的就是读取数据库,获取相应数据更新上述实例数据中的'snapshot_id'和'volume_id'值;
例如,针对bdm信息:
- ( {'device_name': '/dev/fake0',
- 'ebs': {'snapshot_id': 'snap-12345678',
- 'volume_size': 1}},
- {'device_name': '/dev/fake0',
- 'snapshot_id': '00000000-1111-2222-3333-444444444444',
- 'volume_size': 1,
- 'delete_on_termination': True})
复制代码
ec2_id的值即为'snap-12345678';
再看方法ec2utils.ec2_snap_id_to_uuid(ec2_id):
- def ec2_snap_id_to_uuid(ec2_id):
- """
- 为给定的ec2-id获取相应快照的UUID值;
- """
-
- # 获取admin的上下文信息;
- ctxt = context.get_admin_context()
-
- # 转换一个EC2的ID为一个实例的ID(INT格式);(主要是格式变换的问题)
- int_id = ec2_id_to_id(ec2_id)
-
- # 根据给定的int_id获取相应快照的UUID值;
- return get_snapshot_uuid_from_int_id(ctxt, int_id)
复制代码
语句int_id = ec2_id_to_id(ec2_id)实际上就是获取整型数据12345678赋值给int_id;
进一步调用了方法get_snapshot_uuid_by_ec2_id:
- def get_snapshot_uuid_by_ec2_id(context, ec2_id, session=None):
- """根据给定的ec2_id获取相应快照的UUID值;"""
- result = _ec2_snapshot_get_query(context, session=session).\
- filter_by(id=ec2_id).\
- first()
-
- if not result:
- raise exception.SnapshotNotFound(snapshot_id=ec2_id)
-
- return result['uuid']
复制代码
可见根据传入的参数ec2_id=12345678,查询匹配的快照数据库信息,并且获取数据库内置的uuid值最终返回给方法_parse_block_device_mapping中的bdm['snapshot_id'];
获取bdm['volume_id']值的方法流程是一样的,只不过一个是针对快照类型的bdm['snapshot_id'],一个是针对卷类型的bdm['volume_id'];
设置'delete_on_termination'的值为true;
更新相关的bdm数据信息;
后面将会开始解析重要的creat方法;
|