diff options
| -rw-r--r-- | cloudinit/sources/DataSourceConfigDrive.py | 58 | ||||
| -rw-r--r-- | cloudinit/sources/DataSourceEc2.py | 16 | ||||
| -rw-r--r-- | cloudinit/sources/__init__.py | 17 | 
3 files changed, 75 insertions, 16 deletions
| diff --git a/cloudinit/sources/DataSourceConfigDrive.py b/cloudinit/sources/DataSourceConfigDrive.py index b1cf942e..495eee82 100644 --- a/cloudinit/sources/DataSourceConfigDrive.py +++ b/cloudinit/sources/DataSourceConfigDrive.py @@ -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'] diff --git a/cloudinit/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py index c7ad6d54..3686fa10 100644 --- a/cloudinit/sources/DataSourceEc2.py +++ b/cloudinit/sources/DataSourceEc2.py @@ -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 diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py index 04083d0c..b22369a8 100644 --- a/cloudinit/sources/__init__.py +++ b/cloudinit/sources/__init__.py @@ -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 | 
