Ensure that config drive datasource attempts to

translate the device name to a actual device using
logic that will try the ec2 metadata (if avail) or
will try using 'blkid' to find a corresponding label.
This commit is contained in:
Joshua Harlow 2012-10-05 13:38:54 -07:00
parent 0001a0e2fa
commit 13aa637222
3 changed files with 75 additions and 16 deletions

View File

@ -48,6 +48,7 @@ class DataSourceConfigDrive(sources.DataSource):
self.dsmode = 'local'
self.seed_dir = os.path.join(paths.seed_dir, 'config_drive')
self.version = None
self.ec2_metadata = None
def __str__(self):
mstr = "%s [%s,ver=%s]" % (util.obj_name(self), self.dsmode,
@ -55,6 +56,62 @@ class DataSourceConfigDrive(sources.DataSource):
mstr += "[source=%s]" % (self.source)
return mstr
def _ec2_name_to_device(self, name):
if not self.ec2_metadata:
return None
bdm = self.ec2_metadata.get('block-device-mapping', {})
for (ent_name, device) in bdm.items():
if name == ent_name:
return device
return None
def _os_name_to_device(self, name):
device = None
try:
dev_entries = util.find_devs_with('LABEL=%s' % (name))
if dev_entries:
device = dev_entries[0]
except util.ProcessExecutionError:
pass
return device
def device_name_to_device(self, name):
# Translate a 'name' to a 'physical' device
if not name:
return None
# Try the ec2 mapping first
names = [name]
if name == 'root':
names.insert(0, 'ami')
if name == 'ami':
names.append('root')
device = None
for n in names:
device = self._ec2_name_to_device(n)
if device:
break
# Try the openstack way second
if not device:
for n in names:
device = self._os_name_to_device(n)
if device:
break
# Ok give up...
if not device:
return None
# Ensure translated ok
if not device.startswith("/"):
device = "/dev/%s" % device
if os.path.exists(device):
return device
# Durn, try adjusting the mapping
remapped = self._remap_device(os.path.basename(device))
if remapped:
LOG.debug("Remapped device name %s => %s", device, remapped)
return remapped
# Really give up now
return None
def get_data(self):
found = None
md = {}
@ -143,6 +200,7 @@ class DataSourceConfigDrive(sources.DataSource):
self.source = found
self.metadata = md
self.ec2_metadata = results.get('ec2-metadata')
self.userdata_raw = results.get('userdata')
self.version = results['cfgdrive_ver']

View File

@ -151,22 +151,6 @@ class DataSourceEc2(sources.DataSource):
self.metadata_address = url2base.get(url)
return bool(url)
def _remap_device(self, short_name):
# LP: #611137
# the metadata service may believe that devices are named 'sda'
# when the kernel named them 'vda' or 'xvda'
# we want to return the correct value for what will actually
# exist in this instance
mappings = {"sd": ("vd", "xvd")}
for (nfrom, tlist) in mappings.iteritems():
if not short_name.startswith(nfrom):
continue
for nto in tlist:
cand = "/dev/%s%s" % (nto, short_name[len(nfrom):])
if os.path.exists(cand):
return cand
return None
def device_name_to_device(self, name):
# Consult metadata service, that has
# ephemeral0: sdb

View File

@ -23,6 +23,7 @@
from email.mime.multipart import MIMEMultipart
import abc
import os
from cloudinit import importer
from cloudinit import log as logging
@ -128,6 +129,22 @@ class DataSource(object):
return keys
def _remap_device(self, short_name):
# LP: #611137
# the metadata service may believe that devices are named 'sda'
# when the kernel named them 'vda' or 'xvda'
# we want to return the correct value for what will actually
# exist in this instance
mappings = {"sd": ("vd", "xvd")}
for (nfrom, tlist) in mappings.iteritems():
if not short_name.startswith(nfrom):
continue
for nto in tlist:
cand = "/dev/%s%s" % (nto, short_name[len(nfrom):])
if os.path.exists(cand):
return cand
return None
def device_name_to_device(self, _name):
# translate a 'name' to a device
# the primary function at this point is on ec2