http://ezzze.iteye.com/blog/1164920
http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango
workflow:
1. 用户向nova-api发送请求
用户发送请求到nova-api,这里有两种:
a.通过openstack api
从 server.py's controller.create():
- self.helper.create_instance(req, body, self.compute_api.create)
create_instance_helper.CreateInstanceHelper() 查表获取基本信息
b.通过ec2 api
从cloud.py.run_instances()
统一调 computer.api.create() 将新的数据插回去
- self._ask_scheduler_to_create_instance(context, base_options,
- instance_type, zone_blob,
- availability_zone, injected_files,
- admin_password, image,
- instance_id=instance_id,
- requested_networks=requested_networks)
2. API 将处理好的数据通过MQ 转发给scheduler .(code from Computer.api)
- rpc.cast(context,
- FLAGS.scheduler_topic,
- {"method": "run_instance",
- "args": {"topic": FLAGS.compute_topic,
- "instance_id": instance_id,
- "request_spec": request_spec,
- "availability_zone": availability_zone,
- "admin_password": admin_password,
- "injected_files": injected_files,
- "requested_networks": requested_networks}})
3. Scheduler 获取信息并作出决定 哪一个host 可以来run instance.
- def __getattr__(self, key):
- return functools.partial(self._schedule, key)
- def _schedule(self, method, context, topic, *args, **kwargs):
- .......
- rpc.cast(context,
- db.queue_get_for(context, topic, host),
- {"method": method,
- "args": kwargs})
- LOG.debug(_("Casted to %(topic)s %(host)s for %(method)s") % locals())
4. Computer 从池中获取信息 并让 Networker 去准备一个ip ,让volume 准备卷, 然后初始化相应的信息,例如创建image,映射device,创建domain,
并将domain 放入running pool中 然后就进入等待直到instance的状态变为running.
a. networker 分配ip
- network_info = self.network_api.allocate_for_instance(context,
- instance, vpn=is_vpn,
- requested_networks=requested_networks)
- def allocate_floating_ip(self, context):
- return rpc.call(context,
- FLAGS.network_topic,
- {'method': 'allocate_floating_ip',
- 'args': {'project_id': context.project_id}})
b 让 volume 准备卷
- bd_mapping = self._setup_block_device_mapping(context, instance_id)
- def create(self, context, size, snapshot_id, name, description,
- volume_type=None, metadata=None, availability_zone=None):
- rpc.cast(context,
- FLAGS.scheduler_topic,
- {"method": "create_volume",
- "args": {"topic": FLAGS.volume_topic,
- "volume_id": volume['id'],
- "snapshot_id": snapshot_id}})
c call nova.virt.libvirt.firewall.IptablesFirewallDriver 建立网络规则
这里是重头戏,单独开个贴记录下....
d call libvirt 创建domian 并launch
- domain = self._create_new_domain(xml)
- def _create_new_domain(self, xml, persistent=True, launch_flags=0):
- if persistent:
- # To create a persistent domain, first define it, then launch it.
- domain = self._conn.defineXML(xml)
- domain.createWithFlags(launch_flags)
- else:
- # createXML call creates a transient domain
- domain = self._conn.createXML(xml, launch_flags)
- return domain
e call virt.libvirt.connetion.spwan 等待
- def spawn(self, context, instance, network_info,
- block_device_info=None):
- ..........
- def _wait_for_boot():
- instance_name = instance['name']
- try:
- state = self.get_info(instance_name)['state']
- except exception.NotFound:
- msg = _("During reboot, %s disappeared.") % instance_name
- LOG.error(msg)
- raise utils.LoopingCallDone
- if state == power_state.RUNNING:
- msg = _("Instance %s spawned successfully.") % instance_name
- LOG.info(msg)
- raise utils.LoopingCallDone
- timer = utils.LoopingCall(_wait_for_boot)
- return timer.start(interval=0.5, now=True)
5 一旦instance的状态改变至running,他就会去通过networker获取网络信息, 这里有几种方式,取决于你的networkManager