NOTE: 现在有两种方式调用novaclient,一种是命令行'# nova ***',一种是horizon那边的调用
1. 现在进入文件'novaclient.v%s.shell',这里面是实际上的每个api---这里面的api都是以命令行的方式来调用的
1.1 例如我们使用命令'# nova cpu-hotplug ***',那么他调用的函数就是'def do_cpu_hotplug(cs, args):'
2. 现在我们分析horizon那边的调用过程--接下来以新建云主机这个动作来分析
2.1 首先查看horizon模块的代码:
# vim openstack_dashboard/api/nova.py
def server_create(request, name, image, flavor, key_name, user_data,
security_groups, block_device_mapping=None,
block_device_mapping_v2=None, nics=None,
availability_zone=None, instance_count=1, admin_pass=None,
disk_config=None, config_drive=None, meta=None):
return Server(novaclient(request).servers.create(
name, image, flavor, userdata=user_data,
security_groups=security_groups,
key_name=key_name, block_device_mapping=block_device_mapping,
block_device_mapping_v2=block_device_mapping_v2,
nics=nics, availability_zone=availability_zone,
min_count=instance_count, admin_pass=admin_pass,
disk_config=disk_config, config_drive=config_drive,
meta=meta), request)
2.2 根据代码可以很容易的发现,最后调用的是python-novaclient模块里面的文件‘novaclient/v2/servers.py’里面的函数
def create(self, name, image, flavor, meta=None, files=None,
reservation_id=None, min_count=None,
max_count=None, security_groups=None, userdata=None,
key_name=None, availability_zone=None,
block_device_mapping=None, block_device_mapping_v2=None,
nics=None, scheduler_hints=None,
config_drive=None, disk_config=None, admin_pass=None,
access_ip_v4=None, access_ip_v6=None, **kwargs):
# TODO(anthony): indicate in doc string if param is an extension
# and/or optional
"""
Create (boot) a new server.
:param name: Something to name the server.
:param image: The :class:`Image` to boot with.
:param flavor: The :class:`Flavor` to boot onto.
:param meta: A dict of arbitrary key/value metadata to store for this
server. Both keys and values must be <=255 characters.
:param files: A dict of files to overwrite on the server upon boot.
Keys are file names (i.e. ``/etc/passwd``) and values
are the file contents (either as a string or as a
file-like object). A maximum of five entries is allowed,
and each file must be 10k or less.
:param reservation_id: a UUID for the set of servers being requested.
:param min_count: (optional extension) The minimum number of
servers to launch.
:param max_count: (optional extension) The maximum number of
servers to launch.
:param security_groups: A list of security group names
:param userdata: user data to pass to be exposed by the metadata
server this can be a file type object as well or a
string.
:param key_name: (optional extension) name of previously created
keypair to inject into the instance.
:param availability_zone: Name of the availability zone for instance
placement.
:param block_device_mapping: (optional extension) A dict of block
device mappings for this server.
:param block_device_mapping_v2: (optional extension) A dict of block
device mappings for this server.
:param nics: (optional extension) an ordered list of nics to be
added to this server, with information about
connected networks, fixed IPs, port etc.
:param scheduler_hints: (optional extension) arbitrary key-value pairs
specified by the client to help boot an instance
:param config_drive: (optional extension) value for config drive
either boolean, or volume-id
:param disk_config: (optional extension) control how the disk is
partitioned when the server is created. possible
values are 'AUTO' or 'MANUAL'.
:param admin_pass: (optional extension) add a user supplied admin
password.
:param access_ip_v4: (optional extension) add alternative access ip v4
:param access_ip_v6: (optional extension) add alternative access ip v6
:param description: optional description of the server (allowed since
microversion 2.19)
"""
if not min_count:
min_count = 1
if not max_count:
max_count = min_count
if min_count > max_count:
min_count = max_count
boot_args = [name, image, flavor]
descr_microversion = api_versions.APIVersion("2.19")
if "description" in kwargs and self.api_version < descr_microversion:
raise exceptions.UnsupportedAttribute("description", "2.19")
boot_kwargs = dict(
meta=meta, files=files, userdata=userdata,
reservation_id=reservation_id, min_count=min_count,
max_count=max_count, security_groups=security_groups,
key_name=key_name, availability_zone=availability_zone,
scheduler_hints=scheduler_hints, config_drive=config_drive,
disk_config=disk_config, admin_pass=admin_pass,
access_ip_v4=access_ip_v4, access_ip_v6=access_ip_v6, **kwargs)
if block_device_mapping:
resource_url = "/os-volumes_boot"
boot_kwargs['block_device_mapping'] = block_device_mapping
elif block_device_mapping_v2:
resource_url = "/os-volumes_boot"
boot_kwargs['block_device_mapping_v2'] = block_device_mapping_v2
else:
resource_url = "/servers"
if nics:
boot_kwargs['nics'] = nics
response_key = "server"
return self._boot(resource_url, response_key, *boot_args,
**boot_kwargs)
2.3 然后调用函数def _boot(),它的主要功能就是将各个参数放到一个body的字典内
2.4 然后进入文件'novaclient/base.py'内的函数'def _create()',这个函数的作用就是生成一个http请求,基于restful标准协议,其实就是组装一个curl命令
resp, body = self.api.client.post(url, body=body)
例子:创建云主机:
REQ: curl -i 'http://192.168.1.9:8774/v2/14fd316568bc4f6992ba161fd4e23001/servers' -X POST -H "X-Auth-Project-Id: 14fd316568bc4f6992ba161fd4e23001"
-H "User-Agent: python-novaclient" -H "Content-Type: application/json" -H "Accept: application/json" -H "X-Auth-Token: 3b9da36bfcf4491f88994b25c3045f95"
-d '{"server": {"name": "createVm", "imageRef": "db281a42-df86-4a3d-a8df-1af7b2eb80bc", "availability_zone": "nova", "key_name": "keyName",
"flavorRef": "8", "max_count": 1, "min_count": 1, "networks": [{"port": "406b40b4-6b66-47d9-a943-9e341aeae6ef"}]}}'
2.5 接下来在nova模块已经基于wsgi初始化了一个api的route map,会解析上面的url来判断调用哪个api
### 接下来就是分析nova模块的代码