在上一章中, 通过跟踪nova boot
命令, 已经完成了Instance创建参数的解析及身份认证的过程。这一章中继续完成CLI部分的代码跟踪,看看RESTful的请求是如何发出去的。
如果阅读过上一章的内容,就可知道nova boot
所对应的最终的执行函数是do_boot
。这段代码不长,内容也很简单,具体看注释。
do_boot
def do_boot(cs, args):
"""Boot a new server."""
#从args中把参数解析出来,并进行必要的有效性检查
boot_args, boot_kwargs = _boot(cs, args)
#从args中取出一些对应的扩展参数
extra_boot_kwargs = utils.get_resource_manager_extra_kwargs(do_boot, args)
boot_kwargs.update(extra_boot_kwargs)
#使用servers对象创建Instance,并将结果返回
server = cs.servers.create(*boot_args, **boot_kwargs)
# Keep any information (like adminPass) returned by create
info = server._info
server = cs.servers.get(info['id'])
info.update(server._info)
#以下部分对返回的结果做进一步的处理,然后打印给用户,和流程没有关系
flavor = info.get('flavor', {})
flavor_id = flavor.get('id', '')
info['flavor'] = _find_flavor(cs, flavor_id).name
image = info.get('image', {})
if image:
image_id = image.get('id', '')
info['image'] = _find_image(cs, image_id).name
else: # Booting from volume
info['image'] = "Attempt to boot from volume - no image supplied"
info.pop('links', None)
info.pop('addresses', None)
utils.print_dict(info)
#如果设置了poll参数, 则一直轮询Instance的状态,一直到active结束
if args.poll:
_poll_for_status(cs.servers.get, info['id'], 'building', ['active'])
在这段代码中, 只有两个点需要进一步去跟踪
1. _boot中是怎么样去检查参数的?
2. servers是那个类的对象? 它又是如何去创建Instance的?
_boot
这是一段比较长的代码,但它完成的事情还是比较简单的, 对传入的各个参数进行合法性检查及一些冲突检测。因为参数比较多, 所以代码会比较长, 但每个参数几乎是独立的,所以到单个参数的时候都很好理解。
def _boot(cs, args, reservation_id=None, min_count=None, max_count=None):
"""Boot a new server."""
#对创建的实例个数进行检查, 没有设置,默认创建一个实例
if min_count is None:
min_count = 1
if max_count is None:
max_count = min_count
if min_count > max_count:
raise exceptions.CommandError("min_instances should be <= "
"max_instances")
if not min_count or not max_count:
raise exceptions.CommandError("min_instances nor max_instances should"
"be 0")
#取出image的信息
if args.image:
image = _find_image(cs, args.image)
else:
image = None
#如果没有设置image,则从image的metadata中查找image
if not image and args.image_with:
images = _match_image(cs, args.image_with)
if images:
# TODO(harlowja): log a warning that we
# are selecting the first of many?
image = images[0]
#对实例的flavor进行检查
if not args.flavor:
raise exceptions.CommandError("you need to specify a Flavor ID ")
if args.num_instances is not None:
if args.num_instances <= 1:
raise exceptions.CommandError("num_instances should be > 1")
max_count = args.num_instances
#取出flavor的信息
flavor = _find_flavor(cs, args.flavor)
#对meta 数据进行解析
meta = dict(v.split('=', 1) for v in args.meta)
#需要存入实例的文件,最多可以存入5个
files = {}
for f in args.files:
try:
dst, src = f.split('=', 1)
files[dst] = open(src)
except IOError as e:
raise exceptions.CommandError("Can't open '%s': %s" % (src, e))
except ValueError as e:
raise exceptions.CommandError("Invalid file argument '%s'. File "
"arguments must be of the form '--file <dst-path=src-path>'" % f)
# use the os-keypair extension
key_name = None
if args.key_name is not None:
key_name = args.key_name
#user数据的文件
if args.user_data:
try:
userdata = open(args.user_data)
except IOError as