分享

OpenStack建立实例完整过程源码详细分析(4)

xioaxu790 发表于 2014-6-11 10:51:06 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 1 22068
写在前面的话:

今天,继续接着昨天的内容,进行本文,若想参考之前的帖子,请参考下面内容:
1、OpenStack建立实例完整过程源码详细分析(1)

2、OpenStack建立实例完整过程源码详细分析(2)

3、OpenStack建立实例完整过程源码详细分析(3)




好了,咱们内容继续

再回到源码详细分析(1)中最开始的方法run_instances:
  1. def run_instances(self, context, **kwargs):   
  2.             """
  3.             准备实例,并且发送实例的信息和要运行实例的请求消息到远程调度器scheduler;  
  4.             实现实例的简历和运行,由调度器完成;  
  5.             """  
  6.                
  7.             # 设置最小建立实例的数目;   
  8.             min_count = int(kwargs.get('min_count', 1))   
  9.                
  10.             # 获取kwargs['kernel_id']指定的镜像image数据返回给kernel;   
  11.             # 获取更新的kwargs['kernel_id'];   
  12.             if kwargs.get('kernel_id'):     
  13.                 kernel = self._get_image(context, kwargs['kernel_id'])   
  14.                 # 根据kernel['id']查询数据库中匹配的S3镜像数据,获取它的uuid属性,并返回;   
  15.                 # 返回匹配的db.models.S3Image.uuid给kwargs['kernel_id'];   
  16.                 kwargs['kernel_id'] = ec2utils.id_to_glance_id(context, kernel['id'])   
  17.                     
  18.             # 获取kwargs['ramdisk_id']指定的镜像image数据返回给ramdisk;   
  19.             # 获取更新的kwargs['ramdisk_id'];   
  20.             if kwargs.get('ramdisk_id'):   
  21.                 ramdisk = self._get_image(context, kwargs['ramdisk_id'])               
  22.                 # 根据ramdisk['id']查询数据库中匹配的S3镜像数据,获取它的uuid属性,并返回;   
  23.                 # 返回匹配的db.models.S3Image.uuid给kwargs['ramdisk_id'];   
  24.                 kwargs['ramdisk_id'] = ec2utils.id_to_glance_id(context, ramdisk['id'])   
  25.                     
  26.             # 循环获取每一个块设备映射;   
  27.             # 解析块设备映射bdm;   
  28.             for bdm in kwargs.get('block_device_mapping', []):   
  29.                 _parse_block_device_mapping(bdm)   
  30.         
  31.             # 获取kwargs['image_id']指定的镜像image数据;   
  32.             image = self._get_image(context, kwargs['image_id'])   
  33.             # 根据image['id']查询数据库中匹配的S3镜像数据,获取它的uuid属性,并返回;   
  34.             # 返回匹配的db.models.S3Image.uuid给image_uuid;   
  35.             image_uuid = ec2utils.id_to_glance_id(context, image['id'])   
  36.         
  37.             # 获取镜像image的状态;   
  38.             if image:   
  39.                 image_state = self._get_image_state(image)   
  40.             else:   
  41.                 raise exception.ImageNotFoundEC2(image_id=kwargs['image_id'])   
  42.         
  43.             if image_state != 'available':   
  44.                 raise exception.EC2APIError(_('Image must be available'))   
  45.          
  46.             (instances, resv_id) = self.compute_api.create(context,     
  47.                 instance_type=instance_types.get_instance_type_by_name(kwargs.get('instance_type', None)),   
  48.                 image_href=image_uuid,   
  49.                 max_count=int(kwargs.get('max_count', min_count)),   
  50.                 min_count=min_count,   
  51.                 kernel_id=kwargs.get('kernel_id'),   
  52.                 ramdisk_id=kwargs.get('ramdisk_id'),   
  53.                 key_name=kwargs.get('key_name'),   
  54.                 user_data=kwargs.get('user_data'),   
  55.                 security_group=kwargs.get('security_group'),   
  56.                 availability_zone=kwargs.get('placement', {}).get('availability_zone'),   
  57.                 block_device_mapping=kwargs.get('block_device_mapping', {}))   
  58.             return self._format_run_instances(context, resv_id)  
复制代码

我们来解析第二个比较重要的语句_parse_block_device_mapping(bdm):
    我们先来看看kwargs中'block_device_mapping'所表示的数据形式:

  1. [
  2.            ({'device_name': '/dev/fake0',
  3.               'ebs': {'snapshot_id': 'snap-12345678',
  4.                       'volume_size': 1}},
  5.             {'device_name': '/dev/fake0',
  6.              'snapshot_id': '00000000-1111-2222-3333-444444444444',
  7.              'volume_size': 1,
  8.              'delete_on_termination': True}),
  9.             ({'device_name': '/dev/fake1',
  10.               'ebs': {'snapshot_id': 'snap-23456789',
  11.                       'delete_on_termination': False}},
  12.              {'device_name': '/dev/fake1',
  13.               'snapshot_id': '11111111-2222-3333-4444-555555555555',
  14.               'delete_on_termination': False}),
  15.             ({'device_name': '/dev/fake2',
  16.               'ebs': {'snapshot_id': 'vol-87654321',
  17.                       'volume_size': 2}},
  18.             {'device_name': '/dev/fake2',
  19.              'volume_id': '22222222-3333-4444-5555-666666666666',
  20.              'volume_size': 2,
  21.              'delete_on_termination': True}),
  22.             ({'device_name': '/dev/fake3',
  23.               'ebs': {'snapshot_id': 'vol-98765432',
  24.                       'delete_on_termination': False}},
  25.              {'device_name': '/dev/fake3',
  26.               'volume_id': '77777777-8888-9999-0000-aaaaaaaaaaaa',
  27.               'delete_on_termination': False}),
  28.             ({'device_name': '/dev/fake4',
  29.               'ebs': {'no_device': True}},
  30.              {'device_name': '/dev/fake4',
  31.               'no_device': True}),
  32.             ({'device_name': '/dev/fake5',
  33.              'virtual_name': 'ephemeral0'},
  34.             {'device_name': '/dev/fake5',
  35.              'virtual_name': 'ephemeral0'}),
  36.             ({'device_name': '/dev/fake6',
  37.              'virtual_name': 'swap'},
  38.             {'device_name': '/dev/fake6',
  39.              'virtual_name': 'swap'}),
  40.     ]
复制代码

2.方法_parse_block_device_mapping的源码分析:
  1. def _parse_block_device_mapping(bdm):  
  2.     """
  3.     解析块设备映射bdm;
  4.     """  
  5.     ebs = bdm.pop('ebs', None)  
  6.     if ebs:  
  7.         ec2_id = ebs.pop('snapshot_id', None)  
  8.         if ec2_id:  
  9.             # 判断如果是快照;  
  10.             # 则根据获取的ec2_id值,从匹配的数据库信息中获取uuid值赋值给bdm['snapshot_id'],更新bdm中的相应数据;  
  11.             if ec2_id.startswith('snap-'):  
  12.                 bdm['snapshot_id'] = ec2utils.ec2_snap_id_to_uuid(ec2_id)  
  13.             # 判断如果是volume;  
  14.             # 则根据获取的ec2_id值,从匹配的数据库信息中获取uuid值赋值给bdm['snapshot_id'],更新bdm中的相应数据;  
  15.             elif ec2_id.startswith('vol-'):  
  16.                 bdm['volume_id'] = ec2utils.ec2_vol_id_to_uuid(ec2_id)  
  17.                              
  18.             ebs.setdefault('delete_on_termination', True)  
  19.          
  20.         # 更新bdm;  
  21.         bdm.update(ebs)  
  22.       
  23.     # 返回更新后的bdm;  
  24.     return bdm  
复制代码

这个方法主要完成的就是读取数据库,获取相应数据更新上述实例数据中的'snapshot_id'和'volume_id'值;
     例如,针对bdm信息:
  1.     (          {'device_name': '/dev/fake0',
  2.                  'ebs': {'snapshot_id': 'snap-12345678',
  3.                             'volume_size': 1}},
  4.                {'device_name': '/dev/fake0',
  5.                  'snapshot_id': '00000000-1111-2222-3333-444444444444',
  6.                  'volume_size': 1,
  7.                  'delete_on_termination': True})
复制代码

    ec2_id的值即为'snap-12345678';

    再看方法ec2utils.ec2_snap_id_to_uuid(ec2_id):

  1. def ec2_snap_id_to_uuid(ec2_id):  
  2.     """
  3.     为给定的ec2-id获取相应快照的UUID值;
  4.     """  
  5.       
  6.     # 获取admin的上下文信息;  
  7.     ctxt = context.get_admin_context()  
  8.   
  9.     # 转换一个EC2的ID为一个实例的ID(INT格式);(主要是格式变换的问题)  
  10.     int_id = ec2_id_to_id(ec2_id)  
  11.       
  12.     # 根据给定的int_id获取相应快照的UUID值;  
  13.     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:

  1. def get_snapshot_uuid_by_ec2_id(context, ec2_id, session=None):  
  2.     """根据给定的ec2_id获取相应快照的UUID值;"""  
  3.     result = _ec2_snapshot_get_query(context, session=session).\  
  4.                     filter_by(id=ec2_id).\  
  5.                     first()  
  6.   
  7.     if not result:  
  8.         raise exception.SnapshotNotFound(snapshot_id=ec2_id)  
  9.   
  10.     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方法;



已有(1)人评论

跳转到指定楼层
junzi234 发表于 2014-6-11 12:43:20
昨天刚看了看python 今天貌似能看懂写了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条