diff options
author | Ben Howard <ben.howard@canonical.com> | 2014-03-18 15:57:30 -0600 |
---|---|---|
committer | Ben Howard <ben.howard@canonical.com> | 2014-03-18 15:57:30 -0600 |
commit | e91fd55890922d9054523afab4d7e4b268c1be64 (patch) | |
tree | 1d3d1ab71180314f590d2d76a82102e5d7e323a2 | |
parent | d9661a8ef4c6003ef48757715965ebb5c071c80b (diff) | |
download | vyos-cloud-init-e91fd55890922d9054523afab4d7e4b268c1be64.tar.gz vyos-cloud-init-e91fd55890922d9054523afab4d7e4b268c1be64.zip |
Windows Azure defines the ephemeral0 mount as being a per-boot instead of
per instance. Under a variety of circumstances, the ephemeral device may
be presented as a default device. This patch detects when that situation
happens and triggers CC modules disk-setup and mounts to run again.
Details of changes for cloudinit/sources/DataSourceAzure.py:
- auto-detect the location of ephemeral0
- check each boot if ephemeral0 is new
- done via NTFS w/ label of "Temporary Storage" w/ no files on it
- if device is mounted, datasource will unmount it
- if is new, change mounts and disk-setup to always for that boot only
-rw-r--r-- | cloudinit/sources/DataSourceAzure.py | 98 |
1 files changed, 94 insertions, 4 deletions
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py index c7331da5..256e0539 100644 --- a/cloudinit/sources/DataSourceAzure.py +++ b/cloudinit/sources/DataSourceAzure.py @@ -18,12 +18,14 @@ import base64 import crypt +import fnmatch import os import os.path import time from xml.dom import minidom from cloudinit import log as logging +from cloudinit.settings import PER_ALWAYS from cloudinit import sources from cloudinit import util @@ -53,14 +55,15 @@ BUILTIN_CLOUD_CONFIG = { 'disk_setup': { 'ephemeral0': {'table_type': 'mbr', 'layout': True, - 'overwrite': False} - }, + 'overwrite': False}, + }, 'fs_setup': [{'filesystem': 'ext4', 'device': 'ephemeral0.1', - 'replace_fs': 'ntfs'}] + 'replace_fs': 'ntfs'}], } DS_CFG_PATH = ['datasource', DS_NAME] +DEF_EPHEMERAL_LABEL = 'Temporary Storage' class DataSourceAzureNet(sources.DataSource): @@ -189,8 +192,17 @@ class DataSourceAzureNet(sources.DataSource): LOG.warn("failed to get instance id in %s: %s", shcfgxml, e) pubkeys = pubkeys_from_crt_files(fp_files) - self.metadata['public-keys'] = pubkeys + + found_ephemeral = find_ephemeral_disk() + if found_ephemeral: + self.ds_cfg['disk_aliases']['ephemeral0'] = found_ephemeral + LOG.debug("using detected ephemeral0 of %s" % found_ephemeral) + + cc_modules_override = support_new_ephemeral(self.sys_cfg) + if cc_modules_override: + self.cfg['cloud_config_modules'] = cc_modules_override + return True def device_name_to_device(self, name): @@ -200,6 +212,84 @@ class DataSourceAzureNet(sources.DataSource): return self.cfg +def count_files(mp): + return len(fnmatch.filter(os.listdir(mp), '*[!cdrom]*')) + + +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 find_ephemeral_disk(): + """ + Get the ephemeral disk. + """ + part_dev = find_ephemeral_part() + if part_dev and str(part_dev[-1]).isdigit(): + return part_dev[:-1] + elif part_dev: + return part_dev + return None + + +def support_new_ephemeral(cfg): + """ + Windows Azure makes ephemeral devices ephemeral to boot; a ephemeral device + may be presented as a fresh device, or not. + + Since the knowledge of when a disk is supposed to be plowed under is specific + to Windows Azure, the logic resides here in the datasource. When a new ephemeral + device is detected, cloud-init overrides the default frequency for both disk-setup + and mounts for the current boot only. + """ + device = find_ephemeral_part() + if not device: + LOG.debug("no default fabric formated ephemeral0.1 found") + return None + LOG.debug("fabric formated ephemeral0.1 device at %s" % device) + + file_count = 0 + try: + file_count = util.mount_cb(device, count_files) + except: + return None + LOG.debug("fabric prepared ephmeral0.1 has %s files on it" % file_count) + + if file_count >= 1: + LOG.debug("fabric prepared ephemeral0.1 will be preserved") + return None + else: + with util.unmounter(device): + LOG.debug("unmounted fabric prepared ephemeral0.1") + + LOG.debug("cloud-init will format ephemeral0.1 this boot.") + LOG.debug("setting disk_setup and mounts modules 'always' for this boot") + + cc_modules = cfg.get('cloud_config_modules') + if cc_modules: + mod_list = [] + for mod in cc_modules: + if mod in ("disk_setup", "mounts"): + mod_list.append([mod, PER_ALWAYS]) + LOG.debug("set module '%s' to 'always' for this boot" % mod) + else: + mod_list.append(mod) + return mod_list + + return None + + def handle_set_hostname(enabled, hostname, cfg): if not util.is_true(enabled): return |