openstack创建instance的流程
http://ezzze.iteye.com/blog/1164920
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):
- returnfunctools.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(_("Castedto%(topic)s%(host)sfor%(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,v*n=is_v*n,
- requested_networks=requested_networks)
- defallocate_floating_ip(self,context):
- returnrpc.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)
- defcreate(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):
- ifpersistent:
- #Tocreateapersistentdomain,firstdefineit,thenlaunchit.
- domain=self._conn.defineXML(xml)
- domain.createWithFlags(launch_flags)
- else:
- #createXMLcallcreatesatransientdomain
- domain=self._conn.createXML(xml,launch_flags)
- returndomain
e call virt.libvirt.connetion.spwan 等待
- defspawn(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']
- exceptexception.NotFound:
- msg=_("Duringreboot,%sdisappeared.")%instance_name
- LOG.error(msg)
- raiseutils.LoopingCallDone
- ifstate==power_state.RUNNING:
- msg=_("Instance%sspawnedsuccessfully.")%instance_name
- LOG.info(msg)
- raiseutils.LoopingCallDone
- timer=utils.LoopingCall(_wait_for_boot)
- returntimer.start(interval=0.5,now=True)
5一旦instance的状态改变至running,他就会去通过networker获取网络信息, 这里有几种方式,取决于你的networkManager