聲明:
本博客歡迎轉載,但請保留原作者信息!
作者:姜飛
團隊:華爲杭州OpenStack團隊
前面講了nova-compute啓動的時候將ironic的node信息資源上報到compute-nodes,接下來講解下Juno版本在對物理機進行部署的流程。
這裏直接跳到nova-scheduler發rpc到nova-compute,nova-compute進行spawn操作說起,nova-compute的spawn操作,直接就是在compute-driver類的spawn方法:
def spawn(self, context, instance, image_meta, injected_files,
admin_password, network_info=None, block_device_info=None):
# The compute manager is meant to know the node uuid, so missing uuid
# is a significant issue. It may mean we've been passed the wrong data.
node_uuid = instance.get('node')
if not node_uuid:
raise ironic.exc.BadRequest(
_("Ironic node uuid not supplied to "
"driver for instance %s.") % instance['uuid'])
#調用ironic的node.get方法查詢node的詳細信息,獲取該物理機的套餐信息。
icli = client_wrapper.IronicClientWrapper()
node = icli.call("node.get", node_uuid)
flavor = objects.Flavor.get_by_id(context,
instance['instance_type_id'])
#會將套餐裏面的baremetal:deploy_kernel_id和baremetal:deploy_ramdisk_id信息更新到driver_info,將image_source、root_gb、swap_mb、ephemeral_gb、ephem #eral_format、preserve_ephemeral信息更新到instance_info中,然後將driver_info和instance_info更新到ironic的node節點對應的屬性上。
self._add_driver_fields(node, instance, image_meta, flavor)
# NOTE(Shrews): The default ephemeral device needs to be set for
# services (like cloud-init) that depend on it being returned by the
# metadata server. Addresses bug https://launchpad.net/bugs/1324286.
if flavor['ephemeral_gb']:
instance.default_ephemeral_device = '/dev/sda1'
instance.save()
# validate we are ready to do the deploy
#調用ironic的接口查看該節點是否存在,查看deploy和power這2個狀態是否爲True,只有這2個狀態都爲False的時候才允許部署。
validate_chk = icli.call("node.validate", node_uuid)
if not validate_chk.deploy or not validate_chk.power:
# something is wrong. undo what we have done
self._cleanup_deploy(context, node, instance, network_info)
raise exception.ValidationError(_(
"Ironic node: %(id)s failed to validate."
" (deploy: %(deploy)s, power: %(power)s)")
% {'id': node.uuid,
'deploy': validate_chk.deploy,
'power': validate_chk.power})
# prepare for the deploy
try:
#先將ironic port-list出來的port不需要的port從extra的'vif_port_id'屬性中刪#除,這裏要確保network-info的port信息要和ironic port-list的port信息 #一致,network_info的port數一定是小於等於ironic的port數,然後將port的uuid增加到該節點的node的port信息中extra的'vif_port_id'中。
self._plug_vifs(node, instance, network_info)
#當前ironic用的是nova.virt.firewall.NoopFirewallDriver,所以關於這個可以不看
self._start_firewall(instance, network_info)
except Exception:
with excutils.save_and_reraise_exception():
LOG.error(_LE("Error preparing deploy for instance "
"%(instance)s on baremetal node %(node)s."),
{'instance': instance['uuid'],
'node': node_uuid})
self._cleanup_deploy(context, node, instance, network_info)
# trigger the node deploy
#設置部署狀態爲ACTIVE,然後就在這裏等ironic node的provision_state爲ACTIVE
try:
icli.call("node.set_provision_state", node_uuid,
ironic_states.ACTIVE)
except Exception as e:
with excutils.save_and_reraise_exception():
msg = (_LE("Failed to request Ironic to provision instance "
"%(inst)s: %(reason)s"),
{'inst': instance['uuid'],
'reason': six.text_type(e)})
LOG.error(msg)
self._cleanup_deploy(context, node, instance, network_info)
timer = loopingcall.FixedIntervalLoopingCall(self._wait_for_active,
icli, instance)
try:
timer.start(interval=CONF.ironic.api_retry_interval).wait()
except Exception:
with excutils.save_and_reraise_exception():
LOG.error(_LE("Error deploying instance %(instance)s on "
"baremetal node %(node)s."),
{'instance': instance['uuid'],
'node': node_uuid})
self.destroy(context, instance, network_info)
nova-compute的spawn的步驟就是設置ironic的provision_state爲ACTIVE,然後等待ironic的node provision_state爲ACTIVE就結束了。