nova boot from volume在多主机zone下的坑
测试环境:3个计算节点,分别属于3个zone
[root@controller2 ~(keystone_admin)]# nova availability-zone-list
+-----------------------+----------------------------------------+
| Name | Status |
+-----------------------+----------------------------------------+
| internal | available |
| |- controller2 | |
| | |- nova-conductor | enabled :-) 2016-08-20T14:57:07.000000 |
| | |- nova-scheduler | enabled :-) 2016-08-20T14:57:06.000000 |
| | |- nova-consoleauth | enabled :-) 2016-08-20T14:57:08.000000 |
| | |- nova-cert | enabled :-) 2016-08-20T14:57:07.000000 |
| nova | available |
| |- controller3 | |
| | |- nova-compute | enabled :-) 2016-08-20T14:57:04.000000 |
| ag1 | available |
| |- controller1 | |
| | |- nova-compute | enabled :-)2016-08-19T23:41:45.000000 |
| ag2 | available |
| |- controller2 | |
| | |- nova-compute | enabled :-) 2016-08-20T14:57:06.000000 |
+-----------------------+----------------------------------------+
测试方式: 启动虚拟机的时候选择Booting from p_w_picpath(creates a new volume)测试
产生的原因: cinder无法识别nova的多zone,cinder能获取的zone信息有:
1、cinder-volume所在的zone
2、cinder.conf配置文件中的两个参数storage_availability_zone = nova和default_availability_zone = nova
大致过下代码调用过程:(从nova那边调用cinder那部分开始)
1、nova/virt/block_device.py->class DriverImageBlockDevicedef attachvol = volume_api.create
2、nova/volume/cinder.py-> class APIdef createitem = client.volumes.create
3、cinder/api/v2/volumes.py->class VolumeControllerdef createnew_volume = self.volume_api.create
4、cinder/volume/api.py->class APIdef createflow_engine = create_volume.get_flow
在create函数中cinder获取能获得到的zone的信息:
raw_zones = self.list_availability_zones(enable_cache=True)
availability_zones = set([az['name'] for az in raw_zones])
if CONF.storage_availability_zone:
availability_zones.add(CONF.storage_availability_zone)
deflist_availability_zones services = objects.ServiceList.get_all_by_topic ->
cinder/objects/service.py(defget_all_by_topic)db.service_get_all_by_topic ->
cinder/db/api.py(defservice_get_all_by_topic)IMPL.service_get_all_by_topic ->
cinder/db/sqlalchemy/api.py(def service_get_all_by_topic)
@require_admin_contextdefservice_get_all_by_topic(context,topic,disabled=None):query=model_query(context,models.Service,read_deleted="no").\#models在这里cinder/db/sqlalchemy/models.pyfilter_by(topic=topic)#topic默认传过来的是cinder-volumeifdisabledisnotNone:query=query.filter_by(disabled=disabled)returnquery.all()
查询数据库找出cinder-volume所在的zone
5、cinder/volume/flows/api/create_volume.py ->def get_flow
#这里是taskflow,只需关注add方法里面的东东defget_flow(db_api,p_w_picpath_service_api,availability_zones,create_what,scheduler_rpcapi=None,volume_rpcapi=None):"""Constructsandreturnstheapientrypointflow.Thisflowwilldothefollowing:1.Injectkeys&valuesfordependenttasks.2.Extractsandvalidatestheinputkeys&values.3.Reservesthequota(revertsquotaonanyfailures).4.Createsthedatabaseentry.5.Commitsthequota.6.Caststovolumemanagerorschedulerforfurtherprocessing."""flow_name=ACTION.replace(":","_")+"_api"api_flow=linear_flow.Flow(flow_name)api_flow.add(ExtractVolumeRequestTask(p_w_picpath_service_api,availability_zones,rebind={'size':'raw_size','availability_zone':'raw_availability_zone','volume_type':'raw_volume_type'}))api_flow.add(QuotaReserveTask(),EntryCreateTask(db_api),QuotaCommitTask())ifscheduler_rpcapiandvolume_rpcapi:#Thiswillcastitouttoeithertheschedulerorvolumemanagervia#therpcapisprovided.api_flow.add(VolumeCastTask(scheduler_rpcapi,volume_rpcapi,db_api))#Nowload(butdonotrun)theflowusingtheprovidedinitialdata.returntaskflow.engines.load(api_flow,store=create_what)
我们关心的在class ExtractVolumeRequestTask里
先看下入口execute方法,为什么看execute方法,你翻下taskflow怎么用的,就懂了
defexecute(self,context,size,snapshot,p_w_picpath_id,source_volume,availability_zone,volume_type,metadata,key_manager,source_replica,consistencygroup,cgsnapshot):utils.check_exclusive_options(snapshot=snapshot,p_w_picpathRef=p_w_picpath_id,source_volume=source_volume)policy.enforce_action(context,ACTION)#TODO(harlowja):whatguaranteeistherethatthesnapshotorsource#volumewillremainavailableafterwedothisinitialverification??snapshot_id=self._extract_snapshot(snapshot)source_volid=self._extract_source_volume(source_volume)source_replicaid=self._extract_source_replica(source_replica)size=self._extract_size(size,source_volume,snapshot)consistencygroup_id=self._extract_consistencygroup(consistencygroup)cgsnapshot_id=self._extract_cgsnapshot(cgsnapshot)self._check_p_w_picpath_metadata(context,p_w_picpath_id,size)availability_zone=self._extract_availability_zone(availability_zone,#关心的在这里snapshot,source_volume)#_extract_availability_zone函数def_extract_availability_zone(self,availability_zone,snapshot,source_volume):"""Extractsandreturnsavalidatedavailabilityzone.Thisfunctionwillextracttheavailabilityzone(ifnotprovided)fromthesnapshotorsource_volumeandthenperformsasetofvalidationchecksontheprovidedorextractedavailabilityzoneandthenreturnsthevalidatedavailabilityzone."""#Trytoextracttheavailabilityzonefromthecorrespondingsnapshot#orsourcevolumeifeitherisvalidsothatwecanbeinthesame#availabilityzoneasthesource.ifavailability_zoneisNone:ifsnapshot:try:availability_zone=snapshot['volume']['availability_zone']except(TypeError,KeyError):passifsource_volumeandavailability_zoneisNone:try:availability_zone=source_volume['availability_zone']except(TypeError,KeyError):passifavailability_zoneisNone:ifCONF.default_availability_zone:#default_availability_zone判断availability_zone=CONF.default_availability_zoneelse:#Forbackwardscompatibilityusethestorage_availability_zoneavailability_zone=CONF.storage_availability_zoneifavailability_zonenotinself.availability_zones:#self.availability_zones就是上述cinder-volume的zone外加cinder.conf中两个配置参数ifCONF.allow_availability_zone_fallback:#allow_availability_zone_fallback这个很关键original_az=availability_zoneavailability_zone=(CONF.default_availability_zoneorCONF.storage_availability_zone)LOG.warning(_LW("Availabilityzone'%(s_az)s'""notfound,fallingbackto""'%(s_fallback_az)s'."),{'s_az':original_az,'s_fallback_az':availability_zone})else:msg=_("Availabilityzone'%(s_az)s'isinvalid.")msg=msg%{'s_az':availability_zone}raiseexception.InvalidInput(reason=msg)#没启动allow_availability_zone_fallback的话,就抛异常了
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。