前面几章中, 已经从需求,架构及Openstack官方的流程图, 讲述了Nova的基本知识。这一章开始到后面的几章,将从CLI入手, 结合代码, 来看看Instance的具体创建过程, 从而揭开Nova的神秘面纱。
代码版本: nova-2013.2.1
从前一章知道, Openstack创建一个Instance有两种方法, 一个是从Dashboard的HTML页面的launch命令 或是CLI的 nova-boot命令。事实上, 底层他们都是相同的实现, 使用REST 的请求完成。现在从CLI入手, 先看看Instance创建的命令:
nova boot --flavor m1.small --image ubuntu test
这是创建一个Instance的最简单的命令, 其中–flavor指定了要创建的Instance的一些基本配置, 如硬盘大小, CPU个数, 内存大小等。–image是启动所需的Image文件。后面的test是Instance的名字。
那么这个神奇的命令又干了什么事情呢?
使用which命令, 找出nova的命令, 结果如下
# which nova
/usr/bin/nova
然后使用命令cat /usr/bin/nova
再打开:
#!/usr/bin/python
# PBR Generated from u'console_scripts'
import sys
from novaclient.shell import main
if __name__ == "__main__":
sys.exit(main())
这段代码只是调用的novaclient.shell里的main函数。
def main():
try:
OpenStackComputeShell().main(map(strutils.safe_decode, sys.argv[1:]))
except Exception as e:
logger.debug(e, exc_info=1)
print("ERROR: %s" % strutils.safe_encode(six.text_type(e)),
file=sys.stderr)
sys.exit(1)
在main函数中,也只是简单的调用了OpenStackComputeShell里的main函数。然后在OpenStackComputeShell的main函数中, 就是一段很长的代码。有兴趣的话, 可以去看看这段代码。
总体来说, 它完成了下面的功能:
1. 取得命令解析器并解析命令
2. 找出对应的认证插件,默认为Keystone
3. 对help及bash_completion命令进行特殊处理
4. 对输入参数进行检查,并从参数或是环境变量中取出认证所需要的参数(username, password, project,token等),可以参考之前的Keystone系列博客
5. 创建Client对象, 它提供了一系列如相关服务的对象, 可以完成RESTful的请求
6. 使用现有的参数进行认证
7. 执行对应的命令
def main(self, argv):
# Parse args once to find version and debug settings
parser = self.get_base_parser()
(options, args) = parser.parse_known_args(argv)
self.setup_debugging(options.debug)
# Discover available auth plugins
novaclient.auth_plugin.discover_auth_systems()
# build available subcommands based on version
self.extensions = self._discover_extensions(
options.os_compute_api_version)
self._run_extension_hooks('__pre_parse_args__')
# NOTE(dtroyer): Hackery to handle --endpoint_type due to argparse
# thinking usage-list --end is ambiguous; but it
# works fine with only --endpoint-type present
# Go figure.
if '--endpoint_type' in argv:
spot = argv.index('--endpoint_type')
argv[spot] = '--endpoint-type'
subcommand_parser = self.get_subcommand_parser(
options.os_compute_api_version)
self.parser = subcommand_parser
if options.help or not argv:
subcommand_parser.print_help()
return 0
args = subcommand_parser.parse_args(argv)
self._run_extension_hooks('__post_parse_args__', args)
# Short-circuit and deal with help right away.
if args.func == self.do_help:
self.do_help(args)
return 0
elif args.func == self.do_bash_completion:
self.do_bash_completion(args)
return 0
(os_username, os_tenant_name, os_tenant_id, os_auth_url,
os_region_name, os_auth_system, endpoint_type, insecure,
service_type, service_name, volume_service_name,
bypass_url, os_cache, cacert, timeout) = (
args.os_username,
args.os_