def find_candidate_devs(probe_optical=True, dslist=None):
    """Return a list of devices that may contain the config drive.

    The returned list is sorted by search order where the first item has
    should be searched first (highest priority)

    config drive v1:
       Per documentation, this is "associated as the last available disk on the
       instance", and should be VFAT.
       Currently, we do not restrict search list to "last available disk"

    config drive v2:
       Disk should be:
        * either vfat or iso9660 formated
        * labeled with 'config-2' or 'CONFIG-2'
    """
    if dslist is None:
        dslist = []

    # query optical drive to get it in blkid cache for 2.6 kernels
    if probe_optical:
        for device in OPTICAL_DEVICES:
            try:
                util.find_devs_with(path=device)
            except util.ProcessExecutionError:
                pass

    by_fstype = []
    for fs_type in FS_TYPES:
        by_fstype.extend(util.find_devs_with("TYPE=%s" % (fs_type)))

    by_label = []
    for label in LABEL_TYPES:
        by_label.extend(util.find_devs_with("LABEL=%s" % (label)))

    # give preference to "last available disk" (vdb over vda)
    # note, this is not a perfect rendition of that.
    by_fstype.sort(reverse=True)
    by_label.sort(reverse=True)

    # combine list of items by putting by-label items first
    # followed by fstype items, but with dupes removed
    candidates = (by_label + [d for d in by_fstype if d not in by_label])

    # We are looking for a block device or partition with necessary label or
    # an unpartitioned block device (ex sda, not sda1)
    devices = [d for d in candidates
               if d in by_label or not util.is_partition(d)]

    LOG.debug("devices=%s dslist=%s", devices, dslist)
    if devices and "IBMCloud" in dslist:
        # IBMCloud uses config-2 label, but limited to a single UUID.
        ibm_platform, ibm_path = get_ibm_platform()
        if ibm_path in devices:
            devices.remove(ibm_path)
            LOG.debug("IBMCloud device '%s' (%s) removed from candidate list",
                      ibm_path, ibm_platform)

    return devices
def find_ephemeral_part():
    """
    Locate the default ephmeral0.1 device. This will be the first device
    that has a LABEL of DEF_EPHEMERAL_LABEL and is a NTFS device. If Azure
    gets more ephemeral devices, this logic will only identify the first
    such device.
    """
    c_label_devs = util.find_devs_with("LABEL=%s" % DEF_EPHEMERAL_LABEL)
    c_fstype_devs = util.find_devs_with("TYPE=ntfs")
    for dev in c_label_devs:
        if dev in c_fstype_devs:
            return dev
    return None
    def user_data_vsphere(self):
        '''
        vSphere specific userdata read

        If on vSphere the user data will be contained on the
        cdrom device in file <user_data_file>
        To access it:
           Leverage util.mount_cb to:
               mkdir <tmp mount dir>
               mount /dev/fd0 <tmp mount dir>
               The call back passed to util.mount_cb will do:
                   read <tmp mount dir>/<user_data_file>
        '''

        return_str = None
        cdrom_list = util.find_devs_with('LABEL=CDROM')
        for cdrom_dev in cdrom_list:
            try:
                return_str = util.mount_cb(cdrom_dev, read_user_data_callback)
                if return_str:
                    break
            except OSError as err:
                if err.errno != errno.ENOENT:
                    raise
            except util.MountFailedError:
                util.logexc(LOG, "Failed to mount %s when looking for user "
                            "data", cdrom_dev)

        self.userdata_raw = return_str
        self.metadata = META_DATA_NOT_SUPPORTED

        if return_str:
            return True
        else:
            return False
Example #4
0
def transport_iso9660(require_iso=True):

    # Go through mounts to see if it was already mounted
    mounts = util.mounts()
    for (dev, info) in mounts.items():
        fstype = info['fstype']
        if fstype != "iso9660" and require_iso:
            continue
        if not maybe_cdrom_device(dev):
            continue
        mp = info['mountpoint']
        (_fname, contents) = get_ovf_env(mp)
        if contents is not False:
            return contents

    if require_iso:
        mtype = "iso9660"
    else:
        mtype = None

    # generate a list of devices with mtype filesystem, filter by regex
    devs = [dev for dev in
            util.find_devs_with("TYPE=%s" % mtype if mtype else None)
            if maybe_cdrom_device(dev)]
    for dev in devs:
        try:
            (_fname, contents) = util.mount_cb(dev, get_ovf_env, mtype=mtype)
        except util.MountFailedError:
            LOG.debug("%s not mountable as iso9660", dev)
            continue

        if contents is not False:
            return contents

    return None
def cfg_drive_device():
    """ get the config drive device.  return a string like '/dev/vdb'
        or None (if there is no non-root device attached). This does not
        check the contents, only reports that if there *were* a config_drive
        attached, it would be this device.
        per config_drive documentation, this is
         "associated as the last available disk on the instance"
    """

    if 'CLOUD_INIT_CONFIG_DRIVE_DEVICE' in os.environ:
        return(os.environ['CLOUD_INIT_CONFIG_DRIVE_DEVICE'])

    # we are looking for a raw block device (sda, not sda1) with a vfat
    # filesystem on it.

    letters = "abcdefghijklmnopqrstuvwxyz"
    devs = util.find_devs_with("TYPE=vfat")

    # filter out anything not ending in a letter (ignore partitions)
    devs = [f for f in devs if f[-1] in letters]

    # sort them in reverse so "last" device is first
    devs.sort(reverse=True)

    if len(devs):
        return(devs[0])

    return(None)
Example #6
0
def list_possible_azure_ds_devs():
    # return a sorted list of devices that might have a azure datasource
    devlist = []
    for fstype in ("iso9660", "udf"):
        devlist.extend(util.find_devs_with("TYPE=%s" % fstype))

    devlist.sort(reverse=True)
    return devlist
Example #7
0
 def _os_name_to_device(self, name):
     device = None
     try:
         criteria = 'LABEL=%s' % (name)
         if name == 'swap':
             criteria = 'TYPE=%s' % (name)
         dev_entries = util.find_devs_with(criteria)
         if dev_entries:
             device = dev_entries[0]
     except util.ProcessExecutionError:
         pass
     return device
Example #8
0
def can_dev_be_reformatted(devpath):
    # determine if the ephemeral block device path devpath
    # is newly formatted after a resize.
    if not os.path.exists(devpath):
        return False, "device %s does not exist" % devpath

    realpath = os.path.realpath(devpath)
    LOG.debug("Resolving realpath of %s -> %s", devpath, realpath)

    # it is possible that the block device might exist, but the kernel
    # have not yet read the partition table and sent events.  we udevadm settle
    # to hope to resolve that.  Better here would probably be to test and see,
    # and then settle if we didn't find anything and try again.
    if util.which("udevadm"):
        util.subp(["udevadm", "settle"])

    # devpath of /dev/sd[a-z] or /dev/disk/cloud/azure_resource
    # where partitions are "<devpath>1" or "<devpath>-part1" or "<devpath>p1"
    part1path = None
    for suff in ("-part", "p", ""):
        cand = devpath + suff + "1"
        if os.path.exists(cand):
            if os.path.exists(devpath + suff + "2"):
                msg = ("device %s had more than 1 partition: %s, %s" % devpath, cand, devpath + suff + "2")
                return False, msg
            part1path = cand
            break

    if part1path is None:
        return False, "device %s was not partitioned" % devpath

    real_part1path = os.path.realpath(part1path)
    ntfs_devices = util.find_devs_with("TYPE=ntfs", no_cache=True)
    LOG.debug("ntfs_devices found = %s", ntfs_devices)
    if real_part1path not in ntfs_devices:
        msg = "partition 1 (%s -> %s) on device %s was not ntfs formatted" % (part1path, real_part1path, devpath)
        return False, msg

    def count_files(mp):
        ignored = set(["dataloss_warning_readme.txt"])
        return len([f for f in os.listdir(mp) if f.lower() not in ignored])

    bmsg = "partition 1 (%s -> %s) on device %s was ntfs formatted" % (part1path, real_part1path, devpath)
    try:
        file_count = util.mount_cb(part1path, count_files)
    except util.MountFailedError as e:
        return False, bmsg + " but mount of %s failed: %s" % (part1path, e)

    if file_count != 0:
        return False, bmsg + " but had %d files on it." % file_count

    return True, bmsg + " and had no important files. Safe for reformatting."
Example #9
0
def find_candidate_devs():
    """
    Return a list of devices that may contain the context disk.
    """
    combined = []
    for f in ('LABEL=CONTEXT', 'LABEL=CDROM', 'TYPE=iso9660'):
        devs = util.find_devs_with(f)
        devs.sort()
        for d in devs:
            if d not in combined:
                combined.append(d)

    return combined
Example #10
0
def find_fabric_formatted_ephemeral_part():
    """
    Locate the first fabric formatted ephemeral device.
    """
    potential_locations = ["/dev/disk/cloud/azure_resource-part1", "/dev/disk/azure/resource-part1"]
    device_location = None
    for potential_location in potential_locations:
        if os.path.exists(potential_location):
            device_location = potential_location
            break
    if device_location is None:
        return None
    ntfs_devices = util.find_devs_with("TYPE=ntfs")
    real_device = os.path.realpath(device_location)
    if real_device in ntfs_devices:
        return device_location
    return None
Example #11
0
def find_candidate_devs():
    """Return a list of devices that may contain the config drive.

    The returned list is sorted by search order where the first item has
    should be searched first (highest priority)

    config drive v1:
       Per documentation, this is "associated as the last available disk on the
       instance", and should be VFAT.
       Currently, we do not restrict search list to "last available disk"

    config drive v2:
       Disk should be:
        * either vfat or iso9660 formated
        * labeled with 'config-2'
    """

    # Query optical drive to get it in blkid cache for 2.6 kernels
    util.find_devs_with(path="/dev/sr0")
    util.find_devs_with(path="/dev/sr1")

    by_fstype = (util.find_devs_with("TYPE=vfat") +
                 util.find_devs_with("TYPE=iso9660"))
    by_label = util.find_devs_with("LABEL=config-2")

    # give preference to "last available disk" (vdb over vda)
    # note, this is not a perfect rendition of that.
    by_fstype.sort(reverse=True)
    by_label.sort(reverse=True)

    # combine list of items by putting by-label items first
    # followed by fstype items, but with dupes removed
    combined = (by_label + [d for d in by_fstype if d not in by_label])

    # We are looking for a block device or partition with necessary label or
    # an unpartitioned block device.
    combined = [d for d in combined
                    if d in by_label or not util.is_partition(d)]

    return combined
    def get_data(self):
        defaults = {
            "instance-id": "nocloud", "dsmode": self.dsmode
        }

        found = []
        md = {}
        ud = ""

        try:
            # parse the kernel command line, getting data passed in
            if parse_cmdline_data(self.cmdline_id, md):
                found.append("cmdline")
        except:
            util.logexc(log)
            return False

        # check to see if the seeddir has data.
        seedret = {}
        if util.read_optional_seed(seedret, base=self.seeddir + "/"):
            md = util.mergedict(md, seedret['meta-data'])
            ud = seedret['user-data']
            found.append(self.seeddir)
            log.debug("using seeded cache data in %s" % self.seeddir)

        # 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 medi
        if 'seedfrom' in self.ds_cfg and self.ds_cfg['seedfrom']:
            found.append("ds_config")
            md["seedfrom"] = self.ds_cfg['seedfrom']

        fslist = util.find_devs_with("TYPE=vfat")
        fslist.extend(util.find_devs_with("TYPE=iso9660"))

        label_list = util.find_devs_with("LABEL=cidata")
        devlist = list(set(fslist) & set(label_list))
        devlist.sort(reverse=True)

        for dev in devlist:
            try:
                (newmd, newud) = util.mount_callback_umount(dev,
                    util.read_seeded)
                md = util.mergedict(newmd, md)
                ud = newud

                # for seed from a device, the default mode is 'net'.
                # that is more likely to be what is desired.
                # If they want dsmode of local, then they must
                # specify that.
                if 'dsmode' not in md:
                    md['dsmode'] = "net"

                log.debug("using data from %s" % dev)
                found.append(dev)
                break
            except OSError, e:
                if e.errno != errno.ENOENT:
                    raise
            except util.mountFailedError:
                log.warn("Failed to mount %s when looking for seed" % dev)
Example #13
0
    def get_data(self):
        defaults = {
            "instance-id": "nocloud",
            "dsmode": self.dsmode,
        }

        found = []
        mydata = {
            'meta-data': {},
            'user-data': "",
            'vendor-data': "",
            'network-config': {}
        }

        try:
            # Parse the kernel command line, getting data passed in
            md = {}
            if parse_cmdline_data(self.cmdline_id, md):
                found.append("cmdline")
                mydata = _merge_new_seed(mydata, {'meta-data': md})
        except:
            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']
        }

        for path in self.seed_dirs:
            try:
                seeded = util.pathprefix2dict(path, **pp2d_kwargs)
                found.append(path)
                LOG.debug("Using seeded data from %s", path)
                mydata = _merge_new_seed(mydata, seeded)
                break
            except ValueError as e:
                pass

        # 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'):
            found.append("ds_config_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:
            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")
        if label is not None:
            # Query optical drive to get it in blkid cache for 2.6 kernels
            util.find_devs_with(path="/dev/sr0")
            util.find_devs_with(path="/dev/sr1")

            fslist = util.find_devs_with("TYPE=vfat")
            fslist.extend(util.find_devs_with("TYPE=iso9660"))

            label_list = util.find_devs_with("LABEL=%s" % label)
            devlist = list(set(fslist) & set(label_list))
            devlist.sort(reverse=True)

            for dev in devlist:
                try:
                    LOG.debug("Attempting to use data from %s", dev)

                    try:
                        seeded = util.mount_cb(dev, _pp2d_callback,
                                               pp2d_kwargs)
                    except ValueError as e:
                        if dev in label_list:
                            LOG.warn(
                                "device %s with label=%s not a"
                                "valid seed.", dev, label)
                        continue

                    mydata = _merge_new_seed(mydata, seeded)

                    # For seed from a device, the default mode is 'net'.
                    # that is more likely to be what is desired.  If they want
                    # dsmode of local, then they must specify that.
                    if 'dsmode' not in mydata['meta-data']:
                        mydata['meta-data']['dsmode'] = "net"

                    LOG.debug("Using data from %s", dev)
                    found.append(dev)
                    break
                except OSError as e:
                    if e.errno != errno.ENOENT:
                        raise
                except util.MountFailedError:
                    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.
        if len(found) == 0:
            return False

        seeded_network = None
        # The special argument "seedfrom" indicates we should
        # 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"]
            seedfound = False
            for proto in self.supported_seed_starts:
                if seedfrom.startswith(proto):
                    seedfound = proto
                    break
            if not seedfound:
                LOG.debug("Seed from %s not supported by %s", seedfrom, self)
                return False

            if (mydata['meta-data'].get('network-interfaces')
                    or mydata.get('network-config')):
                seeded_network = self.dsmode

            # This could throw errors, but the user told us to do it
            # so if errors are raised, let them raise
            (md_seed, ud) = util.read_seeded(seedfrom, timeout=None)
            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
            found.append(seedfrom)

        # Now that we have exhausted any other places merge in the defaults
        mydata['meta-data'] = util.mergemanydict(
            [mydata['meta-data'], defaults])

        netdata = {'format': None, 'data': None}
        if mydata['meta-data'].get('network-interfaces'):
            netdata['format'] = 'interfaces'
            netdata['data'] = mydata['meta-data']['network-interfaces']
        elif mydata.get('network-config'):
            netdata['format'] = 'network-config'
            netdata['data'] = mydata['network-config']

        # if this is the local datasource or 'seedfrom' was used
        # and the source of the seed was self.dsmode.
        # Then see if there is network config to apply.
        # note this is obsolete network-interfaces style seeding.
        if self.dsmode in ("local", seeded_network):
            if mydata['meta-data'].get('network-interfaces'):
                LOG.debug("Updating network interfaces from %s", self)
                self.distro.apply_network(
                    mydata['meta-data']['network-interfaces'])

        if mydata['meta-data']['dsmode'] == self.dsmode:
            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']
            return True

        LOG.debug("%s: not claiming datasource, dsmode=%s", self,
                  mydata['meta-data']['dsmode'])
        return False
    def _get_data(self):
        defaults = {
            "instance-id": "nocloud",
            "dsmode": self.dsmode,
        }

        found = []
        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 = util.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})
        except Exception:
            util.logexc(LOG, "Unable to parse dmi data")
            return False

        try:
            # Parse the kernel command line, getting data passed in
            md = {}
            if load_cmdline_data(md):
                found.append("cmdline")
                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']}

        for path in self.seed_dirs:
            try:
                seeded = util.pathprefix2dict(path, **pp2d_kwargs)
                found.append(path)
                LOG.debug("Using seeded data from %s", path)
                mydata = _merge_new_seed(mydata, seeded)
                break
            except ValueError:
                pass

        # 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'):
            found.append("ds_config_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:
            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")
        if label is not None:
            # Query optical drive to get it in blkid cache for 2.6 kernels
            util.find_devs_with(path="/dev/sr0")
            util.find_devs_with(path="/dev/sr1")

            fslist = util.find_devs_with("TYPE=vfat")
            fslist.extend(util.find_devs_with("TYPE=iso9660"))

            label_list = util.find_devs_with("LABEL=%s" % label.upper())
            label_list.extend(util.find_devs_with("LABEL=%s" % label.lower()))

            devlist = list(set(fslist) & set(label_list))
            devlist.sort(reverse=True)

            for dev in devlist:
                try:
                    LOG.debug("Attempting to use data from %s", dev)

                    try:
                        seeded = util.mount_cb(dev, _pp2d_callback,
                                               pp2d_kwargs)
                    except ValueError:
                        if dev in label_list:
                            LOG.warning("device %s with label=%s not a"
                                        "valid seed.", dev, label)
                        continue

                    mydata = _merge_new_seed(mydata, seeded)

                    LOG.debug("Using data from %s", dev)
                    found.append(dev)
                    break
                except OSError as e:
                    if e.errno != errno.ENOENT:
                        raise
                except util.MountFailedError:
                    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.
        if len(found) == 0:
            return False

        # The special argument "seedfrom" indicates we should
        # 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"]
            seedfound = False
            for proto in self.supported_seed_starts:
                if seedfrom.startswith(proto):
                    seedfound = proto
                    break
            if not seedfound:
                LOG.debug("Seed from %s not supported by %s", seedfrom, self)
                return False

            # This could throw errors, but the user told us to do it
            # so if errors are raised, let them raise
            (md_seed, ud) = util.read_seeded(seedfrom, timeout=None)
            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
            found.append(seedfrom)

        # Now that we have exhausted any other places merge in the defaults
        mydata['meta-data'] = util.mergemanydict([mydata['meta-data'],
                                                  defaults])

        self.dsmode = self._determine_dsmode(
            [mydata['meta-data'].get('dsmode')])

        if self.dsmode == sources.DSMODE_DISABLED:
            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')
        return True
    def get_data(self):
        defaults = {
            "instance-id": "nocloud",
            "dsmode": self.dsmode,
        }

        found = []
        md = {}
        ud = ""

        try:
            # Parse the kernel command line, getting data passed in
            if parse_cmdline_data(self.cmdline_id, md):
                found.append("cmdline")
        except:
            util.logexc(LOG, "Unable to parse command line data")
            return False

        # Check to see if the seed dir has data.
        seedret = {}
        if util.read_optional_seed(seedret, base=self.seed_dir + "/"):
            md = util.mergemanydict([md, seedret['meta-data']])
            ud = seedret['user-data']
            found.append(self.seed_dir)
            LOG.debug("Using seeded cache data from %s", self.seed_dir)

        # 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 'seedfrom' in self.ds_cfg and self.ds_cfg['seedfrom']:
            found.append("ds_config")
            md["seedfrom"] = self.ds_cfg['seedfrom']

        # if ds_cfg has 'user-data' and 'meta-data'
        if 'user-data' in self.ds_cfg and 'meta-data' in self.ds_cfg:
            if self.ds_cfg['user-data']:
                ud = self.ds_cfg['user-data']
            if self.ds_cfg['meta-data'] is not False:
                md = util.mergemanydict([md, self.ds_cfg['meta-data']])
            if 'ds_config' not in found:
                found.append("ds_config")

        label = self.ds_cfg.get('fs_label', "cidata")
        if label is not None:
            # Query optical drive to get it in blkid cache for 2.6 kernels
            util.find_devs_with(path="/dev/sr0")
            util.find_devs_with(path="/dev/sr1")

            fslist = util.find_devs_with("TYPE=vfat")
            fslist.extend(util.find_devs_with("TYPE=iso9660"))

            label_list = util.find_devs_with("LABEL=%s" % label)
            devlist = list(set(fslist) & set(label_list))
            devlist.sort(reverse=True)

            for dev in devlist:
                try:
                    LOG.debug("Attempting to use data from %s", dev)

                    (newmd, newud) = util.mount_cb(dev, util.read_seeded)
                    md = util.mergemanydict([newmd, md])
                    ud = newud

                    # For seed from a device, the default mode is 'net'.
                    # that is more likely to be what is desired.  If they want
                    # dsmode of local, then they must specify that.
                    if 'dsmode' not in md:
                        md['dsmode'] = "net"

                    LOG.debug("Using data from %s", dev)
                    found.append(dev)
                    break
                except OSError as e:
                    if e.errno != errno.ENOENT:
                        raise
                except util.MountFailedError:
                    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.
        if len(found) == 0:
            return False

        seeded_interfaces = None

        # The special argument "seedfrom" indicates we should
        # 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 md:
            seedfrom = md["seedfrom"]
            seedfound = False
            for proto in self.supported_seed_starts:
                if seedfrom.startswith(proto):
                    seedfound = proto
                    break
            if not seedfound:
                LOG.debug("Seed from %s not supported by %s", seedfrom, self)
                return False

            if 'network-interfaces' in md:
                seeded_interfaces = self.dsmode

            # This could throw errors, but the user told us to do it
            # so if errors are raised, let them raise
            (md_seed, ud) = util.read_seeded(seedfrom, timeout=None)
            LOG.debug("Using seeded cache data from %s", seedfrom)

            # Values in the command line override those from the seed
            md = util.mergemanydict([md, md_seed])
            found.append(seedfrom)

        # Now that we have exhausted any other places merge in the defaults
        md = util.mergemanydict([md, defaults])

        # Update the network-interfaces if metadata had 'network-interfaces'
        # entry and this is the local datasource, or 'seedfrom' was used
        # and the source of the seed was self.dsmode
        # ('local' for NoCloud, 'net' for NoCloudNet')
        if ('network-interfaces' in md and
            (self.dsmode in ("local", seeded_interfaces))):
            LOG.debug("Updating network interfaces from %s", self)
            self.distro.apply_network(md['network-interfaces'])

        if md['dsmode'] == self.dsmode:
            self.seed = ",".join(found)
            self.metadata = md
            self.userdata_raw = ud
            return True

        LOG.debug("%s: not claiming datasource, dsmode=%s", self, md['dsmode'])
        return False
Example #16
0
    def get_data(self):
        defaults = {
            "instance-id": "nocloud",
            "dsmode": self.dsmode,
        }

        found = []
        md = {}
        ud = ""

        try:
            # Parse the kernel command line, getting data passed in
            if parse_cmdline_data(self.cmdline_id, md):
                found.append("cmdline")
        except:
            util.logexc(LOG, "Unable to parse command line data")
            return False

        # Check to see if the seed dir has data.
        seedret = {}
        if util.read_optional_seed(seedret, base=self.seed_dir + "/"):
            md = util.mergemanydict([md, seedret['meta-data']])
            ud = seedret['user-data']
            found.append(self.seed_dir)
            LOG.debug("Using seeded cache data from %s", self.seed_dir)

        # 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 'seedfrom' in self.ds_cfg and self.ds_cfg['seedfrom']:
            found.append("ds_config")
            md["seedfrom"] = self.ds_cfg['seedfrom']

        # if ds_cfg has 'user-data' and 'meta-data'
        if 'user-data' in self.ds_cfg and 'meta-data' in self.ds_cfg:
            if self.ds_cfg['user-data']:
                ud = self.ds_cfg['user-data']
            if self.ds_cfg['meta-data'] is not False:
                md = util.mergemanydict([md, self.ds_cfg['meta-data']])
            if 'ds_config' not in found:
                found.append("ds_config")

        label = self.ds_cfg.get('fs_label', "cidata")
        if label is not None:
            # Query optical drive to get it in blkid cache for 2.6 kernels
            util.find_devs_with(path="/dev/sr0")
            util.find_devs_with(path="/dev/sr1")

            fslist = util.find_devs_with("TYPE=vfat")
            fslist.extend(util.find_devs_with("TYPE=iso9660"))

            label_list = util.find_devs_with("LABEL=%s" % label)
            devlist = list(set(fslist) & set(label_list))
            devlist.sort(reverse=True)

            for dev in devlist:
                try:
                    LOG.debug("Attempting to use data from %s", dev)

                    (newmd, newud) = util.mount_cb(dev, util.read_seeded)
                    md = util.mergemanydict([newmd, md])
                    ud = newud

                    # For seed from a device, the default mode is 'net'.
                    # that is more likely to be what is desired.  If they want
                    # dsmode of local, then they must specify that.
                    if 'dsmode' not in md:
                        md['dsmode'] = "net"

                    LOG.debug("Using data from %s", dev)
                    found.append(dev)
                    break
                except OSError as e:
                    if e.errno != errno.ENOENT:
                        raise
                except util.MountFailedError:
                    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.
        if len(found) == 0:
            return False

        seeded_interfaces = None

        # The special argument "seedfrom" indicates we should
        # 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 md:
            seedfrom = md["seedfrom"]
            seedfound = False
            for proto in self.supported_seed_starts:
                if seedfrom.startswith(proto):
                    seedfound = proto
                    break
            if not seedfound:
                LOG.debug("Seed from %s not supported by %s", seedfrom, self)
                return False

            if 'network-interfaces' in md:
                seeded_interfaces = self.dsmode

            # This could throw errors, but the user told us to do it
            # so if errors are raised, let them raise
            (md_seed, ud) = util.read_seeded(seedfrom, timeout=None)
            LOG.debug("Using seeded cache data from %s", seedfrom)

            # Values in the command line override those from the seed
            md = util.mergemanydict([md, md_seed])
            found.append(seedfrom)

        # Now that we have exhausted any other places merge in the defaults
        md = util.mergemanydict([md, defaults])

        # Update the network-interfaces if metadata had 'network-interfaces'
        # entry and this is the local datasource, or 'seedfrom' was used
        # and the source of the seed was self.dsmode
        # ('local' for NoCloud, 'net' for NoCloudNet')
        if ('network-interfaces' in md
                and (self.dsmode in ("local", seeded_interfaces))):
            LOG.debug("Updating network interfaces from %s", self)
            self.distro.apply_network(md['network-interfaces'])

        if md['dsmode'] == self.dsmode:
            self.seed = ",".join(found)
            self.metadata = md
            self.userdata_raw = ud
            return True

        LOG.debug("%s: not claiming datasource, dsmode=%s", self, md['dsmode'])
        return False
    def get_data(self):
        defaults = {
            "instance-id": "nocloud",
            "dsmode": self.dsmode,
        }

        found = []
        mydata = {'meta-data': {}, 'user-data': "", 'vendor-data': ""}

        try:
            # Parse the kernel command line, getting data passed in
            md = {}
            if parse_cmdline_data(self.cmdline_id, md):
                found.append("cmdline")
            mydata['meta-data'].update(md)
        except:
            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']}

        try:
            seeded = util.pathprefix2dict(self.seed_dir, **pp2d_kwargs)
            found.append(self.seed_dir)
            LOG.debug("Using seeded data from %s", self.seed_dir)
        except ValueError as e:
            pass

        if self.seed_dir in found:
            mydata = _merge_new_seed(mydata, seeded)

        # 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'):
            found.append("ds_config_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:
            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")
        if label is not None:
            # Query optical drive to get it in blkid cache for 2.6 kernels
            util.find_devs_with(path="/dev/sr0")
            util.find_devs_with(path="/dev/sr1")

            fslist = util.find_devs_with("TYPE=vfat")
            fslist.extend(util.find_devs_with("TYPE=iso9660"))

            label_list = util.find_devs_with("LABEL=%s" % label)
            devlist = list(set(fslist) & set(label_list))
            devlist.sort(reverse=True)

            for dev in devlist:
                try:
                    LOG.debug("Attempting to use data from %s", dev)

                    try:
                        seeded = util.mount_cb(dev, _pp2d_callback,
                                               pp2d_kwargs)
                    except ValueError as e:
                        if dev in label_list:
                            LOG.warn("device %s with label=%s not a"
                                     "valid seed.", dev, label)
                        continue

                    mydata = _merge_new_seed(mydata, seeded)

                    # For seed from a device, the default mode is 'net'.
                    # that is more likely to be what is desired.  If they want
                    # dsmode of local, then they must specify that.
                    if 'dsmode' not in mydata['meta-data']:
                        mydata['dsmode'] = "net"

                    LOG.debug("Using data from %s", dev)
                    found.append(dev)
                    break
                except OSError as e:
                    if e.errno != errno.ENOENT:
                        raise
                except util.MountFailedError:
                    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.
        if len(found) == 0:
            return False

        seeded_interfaces = None

        # The special argument "seedfrom" indicates we should
        # 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"]
            seedfound = False
            for proto in self.supported_seed_starts:
                if seedfrom.startswith(proto):
                    seedfound = proto
                    break
            if not seedfound:
                LOG.debug("Seed from %s not supported by %s", seedfrom, self)
                return False

            if 'network-interfaces' in mydata['meta-data']:
                seeded_interfaces = self.dsmode

            # This could throw errors, but the user told us to do it
            # so if errors are raised, let them raise
            (md_seed, ud) = util.read_seeded(seedfrom, timeout=None)
            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
            found.append(seedfrom)

        # Now that we have exhausted any other places merge in the defaults
        mydata['meta-data'] = util.mergemanydict([mydata['meta-data'],
                                                  defaults])

        # Update the network-interfaces if metadata had 'network-interfaces'
        # entry and this is the local datasource, or 'seedfrom' was used
        # and the source of the seed was self.dsmode
        # ('local' for NoCloud, 'net' for NoCloudNet')
        if ('network-interfaces' in mydata['meta-data'] and
                (self.dsmode in ("local", seeded_interfaces))):
            LOG.debug("Updating network interfaces from %s", self)
            self.distro.apply_network(
                mydata['meta-data']['network-interfaces'])

        if mydata['meta-data']['dsmode'] == self.dsmode:
            self.seed = ",".join(found)
            self.metadata = mydata['meta-data']
            self.userdata_raw = mydata['user-data']
            self.vendordata = mydata['vendor-data']
            return True

        LOG.debug("%s: not claiming datasource, dsmode=%s", self, md['dsmode'])
        return False
Example #18
0
def _has_ntfs_filesystem(devpath):
    ntfs_devices = util.find_devs_with("TYPE=ntfs", no_cache=True)
    LOG.debug('ntfs_devices found = %s', ntfs_devices)
    return os.path.realpath(devpath) in ntfs_devices