做个一个没怎么学过python的菜鸟。看源代码是最好的学习方式了,如今就从nova入手,主要凝视一下 nova/compute/api.py 中的 create_instance函数

  1. def _create_instance(self, context, instance_type,
  2. image_href, kernel_id, ramdisk_id,
  3. min_count, max_count,
  4. display_name, display_description,
  5. key_name, key_data, security_group,
  6. availability_zone, user_data, metadata,
  7. injected_files, admin_password,
  8. access_ip_v4, access_ip_v6,
  9. requested_networks, config_drive,
  10. block_device_mapping, auto_disk_config,
  11. reservation_id=None, create_instance_here=False,
  12. scheduler_hints=None):
  13. """Verify all the input parameters regardless of the provisioning
  14. strategy being performed and schedule the instance(s) for
  15. creation."""
  16.  
  17. if not metadata:
  18. metadata = {}
  19. if not display_description:
  20. display_description = ''
  21. if not security_group:
  22. security_group = 'default'
  23.  
  24. if not instance_type:
  25. instance_type = instance_types.get_default_instance_type()
  26. if not min_count:
  27. min_count = 1
  28. if not max_count:
  29. max_count = min_count
  30. if not metadata:
  31. metadata = {}
  32.  
  33. block_device_mapping = block_device_mapping or []
  34.  
  35. #从quota得到详细的实例限制
  36. num_instances = quota.allowed_instances(context, max_count,
  37. instance_type)
  38. if num_instances < min_count:
  39. pid = context.project_id
  40. if num_instances <= 0:
  41. msg = _("Cannot run any more instances of this type.")
  42. else:
  43. msg = (_("Can only run %s more instances of this type.") %
  44. num_instances)
  45. LOG.warn(_("Quota exceeded for %(pid)s,"
  46. " tried to run %(min_count)s instances. " + msg) % locals())
  47. raise exception.QuotaError(code="InstanceLimitExceeded")
  48.  
  49. #检查元数据、注入文件、网络
  50. self._check_metadata_properties_quota(context, metadata)
  51. self._check_injected_file_quota(context, injected_files)
  52. self._check_requested_networks(context, requested_networks)
  53.  
  54. (image_service, image_id) = nova.image.get_image_service(context,
  55. image_href)
  56. #通过镜像id。訪问镜像的详细服务。
  57.  
  58. 得到一个image字典。
  59. image = image_service.show(context, image_id)
  60.  
  61. #iamge 是一个字典。返回key='min_ram'相应的值, get是字典的一个方法。
  62. #memory_mb:是虚拟机所属内存。
  63. if instance_type['memory_mb'] < int(image.get('min_ram') or 0):
  64. raise exception.InstanceTypeMemoryTooSmall()
  65. #root_gb :虚拟机根硬盘大小。instance_type代表了创建虚拟机的需求或者说配置。image则是实际上存在镜像的一个东西。
  66. if instance_type['root_gb'] < int(image.get('min_disk') or 0):
  67. raise exception.InstanceTypeDiskTooSmall()
  68.  
  69. config_drive_id = None
  70. if config_drive and config_drive is not True:
  71. # config_drive is volume id
  72. config_drive, config_drive_id = None, config_drive
  73.  
  74. os_type = None
  75. #properties是字典image的一个属性,image[properties]又是一个字典。
  76. if 'properties' in image and 'os_type' in image['properties']:
  77. os_type = image['properties']['os_type']
  78. architecture = None
  79. if 'properties' in image and 'arch' in image['properties']:
  80. architecture = image['properties']['arch']
  81. vm_mode = None
  82. if 'properties' in image and 'vm_mode' in image['properties']:
  83. vm_mode = image['properties']['vm_mode']
  84.  
  85. # If instance doesn't have auto_disk_config overridden by request, use
  86. # whatever the image indicates
  87. if auto_disk_config is None:
  88. if ('properties' in image and
  89. 'auto_disk_config' in image['properties']):
  90. #bool_from_str:将字符串转化为数组
  91. auto_disk_config = utils.bool_from_str(
  92. image['properties']['auto_disk_config'])
  93.  
  94. if kernel_id is None:
  95. kernel_id = image['properties'].get('kernel_id', None)
  96. if ramdisk_id is None:
  97. ramdisk_id = image['properties'].get('ramdisk_id', None)
  98. # FIXME(sirp): is there a way we can remove null_kernel?
  99. # No kernel and ramdisk for raw images
  100. if kernel_id == str(FLAGS.null_kernel):
  101. kernel_id = None
  102. ramdisk_id = None
  103. LOG.debug(_("Creating a raw instance"))
  104. # Make sure we have access to kernel and ramdisk (if not raw)
  105. #locals() 返回一个名字/值对的字典
  106. LOG.debug(_("Using Kernel=%(kernel_id)s, Ramdisk=%(ramdisk_id)s")
  107. % locals())
  108.  
  109. #show详细是干嘛的????
  110. if kernel_id:
  111. image_service.show(context, kernel_id)
  112. if ramdisk_id:
  113. image_service.show(context, ramdisk_id)
  114. if config_drive_id:
  115. image_service.show(context, config_drive_id)
  116.  
  117. #检查是否具有安全防火墙。假设不具有就创建一个默认的安全组。
  118. self.ensure_default_security_group(context)
  119.  
  120. #ssh 密钥文件名称存在。可是数据不存在。
  121.  
  122. if key_data is None and key_name:
  123. key_pair = self.db.key_pair_get(context, context.user_id, key_name)
  124. key_data = key_pair['public_key']
  125.  
  126. if reservation_id is None:
  127. reservation_id = utils.generate_uid('r')
  128.  
  129. #根设备名
  130. root_device_name = block_device.properties_root_device_name(
  131. image['properties'])
  132.  
  133. # NOTE(vish): We have a legacy hack to allow admins to specify hosts
  134. # via az using az:host. It might be nice to expose an
  135. # api to specify specific hosts to force onto, but for
  136. # now it just supports this legacy hack.
  137. host = None
  138. #parition 函数进行切割字符串,假设切割成功。返回tuple,中间的为分隔符;假设找不到。返回1个实用字符串
  139. #剩余两个元素为空。
  140. #下边主要功能是设置调度集群。
  141. if availability_zone:
  142. availability_zone, _x, host = availability_zone.partition(':')
  143. if not availability_zone:
  144. availability_zone = FLAGS.default_schedule_zone
  145. if context.is_admin and host:
  146. filter_properties = {'force_hosts': [host]}
  147. else:
  148. filter_properties = {}
  149.  
  150. filter_properties['scheduler_hints'] = scheduler_hints
  151.  
  152. base_options = {
  153. 'reservation_id': reservation_id,
  154. 'image_ref': image_href,
  155. 'kernel_id': kernel_id or '',
  156. 'ramdisk_id': ramdisk_id or '',
  157. 'power_state': power_state.NOSTATE,
  158. 'vm_state': vm_states.BUILDING, #注意刚開始是创建中状态。
  159. 'config_drive_id': config_drive_id or '',
  160. 'config_drive': config_drive or '',
  161. 'user_id': context.user_id,
  162. 'project_id': context.project_id,
  163. 'launch_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()),#格式化一个时间字符串。
  164. 'instance_type_id': instance_type['id'],#虚拟机的套餐类型。
  165.  
  166. 'memory_mb': instance_type['memory_mb'],#虚拟机的内存
  167. 'vcpus': instance_type['vcpus'],#虚拟机的cpu核数。
  168. 'root_gb': instance_type['root_gb'],#虚机根硬盘大小
  169. 'ephemeral_gb': instance_type['ephemeral_gb'],
  170. 'display_name': display_name,
  171. 'display_description': display_description,
  172. 'user_data': user_data or '',
  173. 'key_name': key_name,#密钥文件名称
  174. 'key_data': key_data,#密钥数据
  175. 'locked': False,
  176. 'metadata': metadata,
  177. 'access_ip_v4': access_ip_v4,
  178. 'access_ip_v6': access_ip_v6,
  179. 'availability_zone': availability_zone,
  180. 'os_type': os_type,#操作系统类型。
  181. 'architecture': architecture,
  182. 'vm_mode': vm_mode,#虚机状态。
  183. 'root_device_name': root_device_name,#根设备名称。
  184. 'progress': 0,
  185. 'auto_disk_config': auto_disk_config}
  186.  
  187. LOG.debug(_("Going to run %s instances...") % num_instances)
  188.  
  189. if create_instance_here:
  190. instance = self.create_db_entry_for_new_instance(
  191. context, instance_type, image, base_options,
  192. security_group, block_device_mapping)
  193. # Tells scheduler we created the instance already.
  194. base_options['uuid'] = instance['uuid']
  195. #cast是单向的不须要等待对方回复就可以返回。
  196. rpc_method = rpc.cast
  197. else:
  198. # We need to wait for the scheduler to create the instance
  199. # DB entries, because the instance *could* be # created in
  200. # a child zone.
  201. #我的理解:该实例不一定在这个集群创建。可能去子集群。由于可能有非常多个吧
  202. #因此须要等待他的创建完毕。
  203.  
  204. rpc_method = rpc.call
  205.  
  206. # TODO(comstud): We should use rpc.multicall when we can
  207. # retrieve the full instance dictionary from the scheduler.
  208. # Otherwise, we could exceed the AMQP max message size limit.
  209. # This would require the schedulers' schedule_run_instances
  210. # methods to return an iterator vs a list.
  211. #这里应该是调度器发消息了,让调度器去通知详细节点的nova-compute进程去创建虚机。
  212. instances = self._schedule_run_instance(
  213. rpc_method,
  214. context, base_options,
  215. instance_type,
  216. availability_zone, injected_files,
  217. admin_password, image,
  218. num_instances, requested_networks,
  219. block_device_mapping, security_group,
  220. filter_properties)
  221. #这里创建完毕。返回instance实例。
  222. if create_instance_here:
  223. return ([instance], reservation_id)
  224. return (instances, reservation_id)

下边这个是给调度器发送instance创建消息的函数:_schedule_run_instance

  1. #create_instance 调用,发送消息给调度器
  2. def _schedule_run_instance(self,
  3. rpc_method,
  4. context, base_options,
  5. instance_type,
  6. availability_zone, injected_files,
  7. admin_password, image,
  8. num_instances,
  9. requested_networks,
  10. block_device_mapping,
  11. security_group,
  12. filter_properties):
  13. """Send a run_instance request to the schedulers for processing."""
  14.  
  15. #pid不是进程id,是项目id.....
  16. pid = context.project_id
  17. uid = context.user_id
  18.  
  19. LOG.debug(_("Sending create to scheduler for %(pid)s/%(uid)s's") %
  20. locals())
  21.  
  22. request_spec = {
  23. 'image': utils.to_primitive(image),
  24. 'instance_properties': base_options,
  25. 'instance_type': instance_type,
  26. 'num_instances': num_instances,
  27. 'block_device_mapping': block_device_mapping,
  28. 'security_group': security_group,
  29. }
  30.  
  31. return rpc_method(context,
  32. FLAGS.scheduler_topic,
  33. {"method": "run_instance",
  34. "args": {"topic": FLAGS.compute_topic,
  35. "request_spec": request_spec,
  36. "admin_password": admin_password,
  37. "injected_files": injected_files,
  38. "requested_networks": requested_networks,
  39. "is_first_time": True,
  40. "filter_properties": filter_properties}})

这个代码是我个人的理解。最进学习openstack感觉一头雾水。边看《云计算与openstack》边写一些东西出来,也是一种体验吧。

加油!!。!

Openstack nova代码部分凝视一的更多相关文章

  1. eclipse调试openstack的nova代码

    前段时间一直在研究openstack的nova部分的代码.特别想知道,怎样用eclipse来调试代码.也在论坛上问了别人.无果.最后还是自己摸索出了出路. 以下写出自己探索之路.我是用devstack ...

  2. OpenStack Nova 高性能虚拟机之 CPU 绑定

    目录 文章目录 目录 前文列表 KVM KVM 的功能列表 KVM 工具集 KVM 虚拟机的本质是什么 vCPU 的调度与性能问题 Nova 支持的 vCPU 绑定 vcpu\_pin\_set 配置 ...

  3. Openstack Nova 源码分析 — 使用 VCDriver 创建 VMware Instance

    目录 目录 前言 流程图 nova-compute vCenter 前言 在上一篇Openstack Nova 源码分析 - Create instances (nova-conductor阶段)中, ...

  4. Openstack Nova 源码分析 — Create instances (nova-conductor阶段)

    目录 目录 前言 Instance Flavor Instance Status Virt Driver Resource Tracker nova-conductor Create Instance ...

  5. OpenStack Nova启动实例流程

    1.概述 启动一个新的实例,会涉及到OpenStack Nova中的多个组件: API服务器,接收用户端的请求,并且将其传递给云控制器. 云控制器,处理计算节点.网络控制器.API服务器和调度器之前的 ...

  6. OpenStack nova VM migration (live and cold) call flow

    OpenStack nova compute supports two flavors of Virtual Machine (VM) migration: Cold migration -- mig ...

  7. 如何删除 OpenStack Nova 僵尸实例

    转自:http://www.vpsee.com/2011/11/how-to-delete-a-openstack-nova-zombie-instance/ 前天强制重启一台 OpenStack N ...

  8. OpenStack Nova 制作 Windows 镜像

    OpenStack Nova 制作 Windows 镜像   windows虚拟机ubuntuimage防火墙云计算 本贴转自http://www.vpsee.com 上次 VPSee 给 OpenS ...

  9. OpenStack提交代码的review流程

    本文整理向openstack社区提交代码的基本流程,以及社区一些介绍资料.如有转载,请注明出处! 先放张图说明一下OpenStack的code review的大体流程: 对OpenStack提交代码更 ...

随机推荐

  1. post方式的数据抓取

    public static String sendPost(String url, String param) {        PrintWriter out = null;        Buff ...

  2. 学习RMQ-ST表

    RMQ一般是一个二维数组,用$dp[i][j]$表示起点为i开始连续数$2^j$个元素其中的最值,由于对于一个闭区间有:$R-L+1=len$因此也可以用另外一种记法:闭区间为$[i,i+2^j-1] ...

  3. 洛谷P3832 [NOI2017]蚯蚓排队 【链表 + 字符串hash】

    题目链接 洛谷P3832 题解 字符串哈希然后丢到hash表里边查询即可 因为\(k \le 50\),1.2操作就暴力维护一下 经复杂度分析会发现直接这样暴力维护是对的 一开始自然溢出WA了,还以为 ...

  4. 刷题总结—— Scout YYF I(poj3744 矩阵快速幂+概率dp)

    题目: Description YYF is a couragous scout. Now he is on a dangerous mission which is to penetrate int ...

  5. ANT总结

    1 Ant是什么? Apache Ant 是一个基于 Java的生成工具.生成工具在软件开发中用来将源代码和其他输入文件转换为可执行文件的形式(也有可能转换为可安装的产品映像形式).随着应用程序的生成 ...

  6. linux之stat

    stat指令:文件/文件系统的详细信息显示: 使用格式:stat 文件名 stat命令主要用于显示文件或文件系统的详细信息,该命令的语法格式如下: -f 不显示文件本身的信息,显示文件所在文件系统的信 ...

  7. (三)Spring 依赖注入

    一.Spring框架本身有四大原则: 使用POJO进行轻量级和最小侵入式开发. 通过依赖注入和接口变成实现松耦合. 通过AOP和默认习惯进行声明式变成. 使用AOP和模板减少模式化代码. Spring ...

  8. 【Hihocoder1634】Puzzle Game(DP)

    题意:有一个n*m的矩阵,每个矩阵里有一个数字a[i][j].现在要求将其中一个格子的值改为p,使得修改后矩阵的最大子矩阵和最小,求这个最小值 n,m<=150,abs(a[i][j])< ...

  9. 用来武装Firebug的十四款Firefox插件

    原文发布时间为:2010-04-24 -- 来源于本人的百度文章 [由搬家工具导入] 如果你是一名Web设计师,Firebug想必不会陌生,作为一款Firefox插件,它可能是网站前端开发最有用的工具 ...

  10. 将一个二叉树左右翻转(Java 版)

    public class Solution { public TreeNode invertTree(TreeNode root) { if (root == null) { return null; ...