diff options
Diffstat (limited to 'cloudinit/sources/DataSourceNoCloud.py')
| -rw-r--r-- | cloudinit/sources/DataSourceNoCloud.py | 156 | 
1 files changed, 88 insertions, 68 deletions
| diff --git a/cloudinit/sources/DataSourceNoCloud.py b/cloudinit/sources/DataSourceNoCloud.py index a126aad3..56559630 100644 --- a/cloudinit/sources/DataSourceNoCloud.py +++ b/cloudinit/sources/DataSourceNoCloud.py @@ -13,9 +13,8 @@ import os  from cloudinit import dmi  from cloudinit import log as logging +from cloudinit import sources, util  from cloudinit.net import eni -from cloudinit import sources -from cloudinit import util  LOG = logging.getLogger(__name__) @@ -27,8 +26,10 @@ class DataSourceNoCloud(sources.DataSource):      def __init__(self, sys_cfg, distro, paths):          sources.DataSource.__init__(self, sys_cfg, distro, paths)          self.seed = None -        self.seed_dirs = [os.path.join(paths.seed_dir, 'nocloud'), -                          os.path.join(paths.seed_dir, 'nocloud-net')] +        self.seed_dirs = [ +            os.path.join(paths.seed_dir, "nocloud"), +            os.path.join(paths.seed_dir, "nocloud-net"), +        ]          self.seed_dir = None          self.supported_seed_starts = ("/", "file://") @@ -55,17 +56,21 @@ class DataSourceNoCloud(sources.DataSource):          }          found = [] -        mydata = {'meta-data': {}, 'user-data': "", 'vendor-data': "", -                  'network-config': None} +        mydata = { +            "meta-data": {}, +            "user-data": "", +            "vendor-data": "", +            "network-config": None, +        }          try:              # Parse the system serial label from dmi. If not empty, try parsing              # like the commandline              md = {} -            serial = dmi.read_dmi_data('system-serial-number') +            serial = dmi.read_dmi_data("system-serial-number")              if serial and load_cmdline_data(md, serial):                  found.append("dmi") -                mydata = _merge_new_seed(mydata, {'meta-data': md}) +                mydata = _merge_new_seed(mydata, {"meta-data": md})          except Exception:              util.logexc(LOG, "Unable to parse dmi data")              return False @@ -75,14 +80,16 @@ class DataSourceNoCloud(sources.DataSource):              md = {}              if load_cmdline_data(md):                  found.append("cmdline") -                mydata = _merge_new_seed(mydata, {'meta-data': md}) +                mydata = _merge_new_seed(mydata, {"meta-data": md})          except Exception:              util.logexc(LOG, "Unable to parse command line data")              return False          # Check to see if the seed dir has data. -        pp2d_kwargs = {'required': ['user-data', 'meta-data'], -                       'optional': ['vendor-data', 'network-config']} +        pp2d_kwargs = { +            "required": ["user-data", "meta-data"], +            "optional": ["vendor-data", "network-config"], +        }          for path in self.seed_dirs:              try: @@ -97,31 +104,35 @@ class DataSourceNoCloud(sources.DataSource):          # If the datasource config had a 'seedfrom' entry, then that takes          # precedence over a 'seedfrom' that was found in a filesystem          # but not over external media -        if self.ds_cfg.get('seedfrom'): +        if self.ds_cfg.get("seedfrom"):              found.append("ds_config_seedfrom") -            mydata['meta-data']["seedfrom"] = self.ds_cfg['seedfrom'] +            mydata["meta-data"]["seedfrom"] = self.ds_cfg["seedfrom"]          # fields appropriately named can also just come from the datasource          # config (ie, 'user-data', 'meta-data', 'vendor-data' there) -        if 'user-data' in self.ds_cfg and 'meta-data' in self.ds_cfg: +        if "user-data" in self.ds_cfg and "meta-data" in self.ds_cfg:              mydata = _merge_new_seed(mydata, self.ds_cfg)              found.append("ds_config")          def _pp2d_callback(mp, data):              return util.pathprefix2dict(mp, **data) -        label = self.ds_cfg.get('fs_label', "cidata") +        label = self.ds_cfg.get("fs_label", "cidata")          if label is not None:              for dev in self._get_devices(label):                  try:                      LOG.debug("Attempting to use data from %s", dev)                      try: -                        seeded = util.mount_cb(dev, _pp2d_callback, -                                               pp2d_kwargs) +                        seeded = util.mount_cb( +                            dev, _pp2d_callback, pp2d_kwargs +                        )                      except ValueError: -                        LOG.warning("device %s with label=%s not a " -                                    "valid seed.", dev, label) +                        LOG.warning( +                            "device %s with label=%s not a valid seed.", +                            dev, +                            label, +                        )                          continue                      mydata = _merge_new_seed(mydata, seeded) @@ -133,8 +144,9 @@ class DataSourceNoCloud(sources.DataSource):                      if e.errno != errno.ENOENT:                          raise                  except util.MountFailedError: -                    util.logexc(LOG, "Failed to mount %s when looking for " -                                "data", dev) +                    util.logexc( +                        LOG, "Failed to mount %s when looking for data", dev +                    )          # There was no indication on kernel cmdline or data          # in the seeddir suggesting this handler should be used. @@ -145,8 +157,8 @@ class DataSourceNoCloud(sources.DataSource):          # attempt to seed the userdata / metadata from its value          # its primarily value is in allowing the user to type less          # on the command line, ie: ds=nocloud;s=http://bit.ly/abcdefg -        if "seedfrom" in mydata['meta-data']: -            seedfrom = mydata['meta-data']["seedfrom"] +        if "seedfrom" in mydata["meta-data"]: +            seedfrom = mydata["meta-data"]["seedfrom"]              seedfound = False              for proto in self.supported_seed_starts:                  if seedfrom.startswith(proto): @@ -162,39 +174,43 @@ class DataSourceNoCloud(sources.DataSource):              LOG.debug("Using seeded cache data from %s", seedfrom)              # Values in the command line override those from the seed -            mydata['meta-data'] = util.mergemanydict([mydata['meta-data'], -                                                      md_seed]) -            mydata['user-data'] = ud -            mydata['vendor-data'] = vd +            mydata["meta-data"] = util.mergemanydict( +                [mydata["meta-data"], md_seed] +            ) +            mydata["user-data"] = ud +            mydata["vendor-data"] = vd              found.append(seedfrom)          # Now that we have exhausted any other places merge in the defaults -        mydata['meta-data'] = util.mergemanydict([mydata['meta-data'], -                                                  defaults]) +        mydata["meta-data"] = util.mergemanydict( +            [mydata["meta-data"], defaults] +        )          self.dsmode = self._determine_dsmode( -            [mydata['meta-data'].get('dsmode')]) +            [mydata["meta-data"].get("dsmode")] +        )          if self.dsmode == sources.DSMODE_DISABLED: -            LOG.debug("%s: not claiming datasource, dsmode=%s", self, -                      self.dsmode) +            LOG.debug( +                "%s: not claiming datasource, dsmode=%s", self, self.dsmode +            )              return False          self.seed = ",".join(found) -        self.metadata = mydata['meta-data'] -        self.userdata_raw = mydata['user-data'] -        self.vendordata_raw = mydata['vendor-data'] -        self._network_config = mydata['network-config'] -        self._network_eni = mydata['meta-data'].get('network-interfaces') +        self.metadata = mydata["meta-data"] +        self.userdata_raw = mydata["user-data"] +        self.vendordata_raw = mydata["vendor-data"] +        self._network_config = mydata["network-config"] +        self._network_eni = mydata["meta-data"].get("network-interfaces")          return True      @property      def platform_type(self):          # Handle upgrade path of pickled ds -        if not hasattr(self, '_platform_type'): +        if not hasattr(self, "_platform_type"):              self._platform_type = None          if not self._platform_type: -            self._platform_type = 'lxd' if util.is_lxd() else 'nocloud' +            self._platform_type = "lxd" if util.is_lxd() else "nocloud"          return self._platform_type      def _get_cloud_name(self): @@ -203,11 +219,11 @@ class DataSourceNoCloud(sources.DataSource):      def _get_subplatform(self):          """Return the subplatform metadata source details.""" -        if self.seed.startswith('/dev'): -            subplatform_type = 'config-disk' +        if self.seed.startswith("/dev"): +            subplatform_type = "config-disk"          else: -            subplatform_type = 'seed-dir' -        return '%s (%s)' % (subplatform_type, self.seed) +            subplatform_type = "seed-dir" +        return "%s (%s)" % (subplatform_type, self.seed)      def check_instance_id(self, sys_cfg):          # quickly (local check only) if self.instance_id is still valid @@ -218,7 +234,7 @@ class DataSourceNoCloud(sources.DataSource):          # LP: #1568150 need getattr in the case that an old class object          # has been loaded from a pickled file and now executing new source. -        dirs = getattr(self, 'seed_dirs', [self.seed_dir]) +        dirs = getattr(self, "seed_dirs", [self.seed_dir])          quick_id = _quick_read_instance_id(dirs=dirs)          if not quick_id:              return None @@ -236,7 +252,7 @@ def _quick_read_instance_id(dirs=None):      if dirs is None:          dirs = [] -    iid_key = 'instance-id' +    iid_key = "instance-id"      fill = {}      if load_cmdline_data(fill) and iid_key in fill:          return fill[iid_key] @@ -245,9 +261,9 @@ def _quick_read_instance_id(dirs=None):          if d is None:              continue          try: -            data = util.pathprefix2dict(d, required=['meta-data']) -            md = util.load_yaml(data['meta-data']) -            if iid_key in md: +            data = util.pathprefix2dict(d, required=["meta-data"]) +            md = util.load_yaml(data["meta-data"]) +            if md and iid_key in md:                  return md[iid_key]          except ValueError:              pass @@ -256,14 +272,16 @@ def _quick_read_instance_id(dirs=None):  def load_cmdline_data(fill, cmdline=None): -    pairs = [("ds=nocloud", sources.DSMODE_LOCAL), -             ("ds=nocloud-net", sources.DSMODE_NETWORK)] +    pairs = [ +        ("ds=nocloud", sources.DSMODE_LOCAL), +        ("ds=nocloud-net", sources.DSMODE_NETWORK), +    ]      for idstr, dsmode in pairs:          if parse_cmdline_data(idstr, fill, cmdline):              # if dsmode was explicitly in the command line, then              # prefer it to the dsmode based on the command line id -            if 'dsmode' not in fill: -                fill['dsmode'] = dsmode +            if "dsmode" not in fill: +                fill["dsmode"] = dsmode              return True      return False @@ -323,19 +341,19 @@ def _maybe_remove_top_network(cfg):      Return the original value if no change or the updated value if changed."""      nullval = object() -    network_val = cfg.get('network', nullval) +    network_val = cfg.get("network", nullval)      if network_val is nullval:          return cfg -    bmsg = 'Top level network key in network-config %s: %s' +    bmsg = "Top level network key in network-config %s: %s"      if not isinstance(network_val, dict):          LOG.debug(bmsg, "was not a dict", cfg)          return cfg      if len(list(cfg.keys())) != 1:          LOG.debug(bmsg, "had multiple top level keys", cfg)          return cfg -    if network_val.get('config') == "disabled": +    if network_val.get("config") == "disabled":          LOG.debug(bmsg, "was config/disabled", cfg) -    elif not all(('config' in network_val, 'version' in network_val)): +    elif not all(("config" in network_val, "version" in network_val)):          LOG.debug(bmsg, "but missing 'config' or 'version'", cfg)          return cfg      LOG.debug(bmsg, "fixed by removing shifting network.", cfg) @@ -345,19 +363,20 @@ def _maybe_remove_top_network(cfg):  def _merge_new_seed(cur, seeded):      ret = cur.copy() -    newmd = seeded.get('meta-data', {}) -    if not isinstance(seeded['meta-data'], dict): -        newmd = util.load_yaml(seeded['meta-data']) -    ret['meta-data'] = util.mergemanydict([cur['meta-data'], newmd]) +    newmd = seeded.get("meta-data", {}) +    if not isinstance(seeded["meta-data"], dict): +        newmd = util.load_yaml(seeded["meta-data"]) +    ret["meta-data"] = util.mergemanydict([cur["meta-data"], newmd]) -    if seeded.get('network-config'): -        ret['network-config'] = _maybe_remove_top_network( -            util.load_yaml(seeded.get('network-config'))) +    if seeded.get("network-config"): +        ret["network-config"] = _maybe_remove_top_network( +            util.load_yaml(seeded.get("network-config")) +        ) -    if 'user-data' in seeded: -        ret['user-data'] = seeded['user-data'] -    if 'vendor-data' in seeded: -        ret['vendor-data'] = seeded['vendor-data'] +    if "user-data" in seeded: +        ret["user-data"] = seeded["user-data"] +    if "vendor-data" in seeded: +        ret["vendor-data"] = seeded["vendor-data"]      return ret @@ -369,7 +388,7 @@ class DataSourceNoCloudNet(DataSourceNoCloud):  # Used to match classes to dependencies  datasources = [ -    (DataSourceNoCloud, (sources.DEP_FILESYSTEM, )), +    (DataSourceNoCloud, (sources.DEP_FILESYSTEM,)),      (DataSourceNoCloudNet, (sources.DEP_FILESYSTEM, sources.DEP_NETWORK)),  ] @@ -378,4 +397,5 @@ datasources = [  def get_datasource_list(depends):      return sources.list_from_depends(depends, datasources) +  # vi: ts=4 expandtab | 
