summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/examples/cloud-config.txt27
-rwxr-xr-xec2-init.py10
-rw-r--r--ec2init/CloudConfig.py114
-rw-r--r--ec2init/DataSource.py9
-rw-r--r--ec2init/DataSourceEc2.py28
-rw-r--r--ec2init/__init__.py42
6 files changed, 165 insertions, 65 deletions
diff --git a/doc/examples/cloud-config.txt b/doc/examples/cloud-config.txt
index b808f99a..f4de88e8 100644
--- a/doc/examples/cloud-config.txt
+++ b/doc/examples/cloud-config.txt
@@ -81,6 +81,33 @@ packages:
- pwgen
- pastebinit
+# set up mount points
+# 'mounts' contains a list of lists
+# the inner list are entries for an /etc/fstab line
+# ie : [ fs_spec, fs_file, fs_vfstype, fs_mntops, fs-freq, fs_passno ]
+#
+# default:
+# mounts:
+# - [ ephemeral0, /mnt ]
+# - [ swap, none, swap, sw, 0, 0 ]
+#
+# in order to remove a previously listed mount (ie, one from defaults)
+# list only the fs_spec. For example, to override the default, of
+# mounting swap:
+# - [ swap ]
+# or
+# - [ swap, null ]
+#
+# - if a device does not exist at the time, an entry will still be
+# written to /etc/fstab.
+# - '/dev' can be ommitted for device names that begin with: xvd, sd, hd, vd
+# - if an entry does not have all 6 fields, they will be filled in
+# from the following: [ None, None, "auto", "defaults", "0", "0" ]
+#
+mounts:
+ - [ ephemeral0, /mnt, auto, "defaults,noexec" ]
+ - [ sdc, /opt/data ]
+ - [ dd, /dev/zero ]
# add each entry to ~/.ssh/authorized_keys for the configured user
ssh_authorized_keys:
diff --git a/ec2-init.py b/ec2-init.py
index 7597e9c6..06662f7b 100755
--- a/ec2-init.py
+++ b/ec2-init.py
@@ -41,16 +41,6 @@ def main():
except:
warn("failed to set defaults\n")
- # enable swap
- try:
- cloud.sem_and_run("enable_swap", "once-per-instance",
- cloud.enable_swap,[],False)
- except:
- import traceback
- traceback.print_exc(file=sys.stderr)
- warn("enabling swap failed!\n")
-
-
# finish, send the cloud-config event
cloud.initctl_emit()
diff --git a/ec2init/CloudConfig.py b/ec2init/CloudConfig.py
index 51618943..4875e999 100644
--- a/ec2init/CloudConfig.py
+++ b/ec2init/CloudConfig.py
@@ -39,6 +39,7 @@ class CloudConfig():
self.add_handler('apt-update-upgrade', self.h_apt_update_upgrade)
self.add_handler('config-ssh')
self.add_handler('disable-ec2-metadata')
+ self.add_handler('config-mounts')
def get_config_obj(self,cfgfile):
f=file(cfgfile)
@@ -189,7 +190,118 @@ class CloudConfig():
def h_config_runurl(self,name,args):
print "Warning, not doing anything for config %s" % name
-
+ def h_config_mounts(self,name,args):
+ # handle 'mounts'
+
+ # these are our default set of mounts
+ defmnts = [ [ "ephemeral0", "/mnt", "auto", "defaults", "0", "0" ],
+ [ "swap", "none", "swap", "sw", "0", "0" ] ]
+
+ # fs_spec, fs_file, fs_vfstype, fs_mntops, fs-freq, fs_passno
+ defvals = [ None, None, "auto", "defaults", "0", "0" ]
+
+ cfgmnt = [ ]
+ if self.cfg.has_key("mounts"):
+ cfgmnt = self.cfg["mounts"]
+
+ for i in range(len(cfgmnt)):
+ # skip something that wasn't a list
+ if not isinstance(cfgmnt[i],list): continue
+
+ # workaround, allow user to specify 'ephemeral'
+ # rather than more ec2 correct 'ephemeral0'
+ if cfgmnt[i] == "ephemeral":
+ cfgmnt[i] = "ephemeral0"
+
+ newname = cfgmnt[i][0]
+ if not newname.startswith("/"):
+ newname = self.cloud.device_name_to_device(cfgmnt[i][0])
+ if newname is not None:
+ cfgmnt[i][0] = newname
+ else:
+ # there is no good way of differenciating between
+ # a name that *couldn't* exist in the md service and
+ # one that merely didnt
+ # in order to allow user to specify 'sda3' rather
+ # than '/dev/sda3', go through some hoops
+ ok = False
+ for f in [ "/", "sd", "hd", "vd", "xvd" ]:
+ if cfgmnt[i][0].startswith(f):
+ ok = True
+ break
+ if not ok:
+ cfgmnt[i][1] = None
+
+ for i in range(len(cfgmnt)):
+ # fill in values with
+ for j in range(len(defvals)):
+ if len(cfgmnt[i]) <= j:
+ cfgmnt[i].append(defvals[j])
+ elif cfgmnt[i][j] is None:
+ cfgmnt[i][j] = defvals[j]
+
+ if not cfgmnt[i][0].startswith("/"):
+ cfgmnt[i][0]="/dev/%s" % cfgmnt[i][0]
+
+ # if the second entry in the list is 'None' this
+ # clears all previous entries of that same 'fs_spec'
+ # (fs_spec is the first field in /etc/fstab, ie, that device)
+ if cfgmnt[i][1] is None:
+ for j in range(i):
+ if cfgmnt[j][0] == cfgmnt[i][0]:
+ cfgmnt[j][1] = None
+
+
+ # for each of the "default" mounts, add them only if no other
+ # entry has the same device name
+ for defmnt in defmnts:
+ devname = self.cloud.device_name_to_device(defmnt[0])
+ if devname is None: continue
+ if not devname.startswith("/"):
+ defmnt[0] = "/dev/%s" % devname
+
+ cfgmnt_has = False
+ for cfgm in cfgmnt:
+ if cfgm[0] == defmnt[0]:
+ cfgmnt_has = True
+ break
+
+ if cfgmnt_has: continue
+ cfgmnt.append(defmnt)
+
+
+ # now, each entry in the cfgmnt list has all fstab values
+ # if the second field is None (not the string, the value) we skip it
+ actlist = filter(lambda x: x[1] is not None, cfgmnt)
+
+ if len(actlist) == 0: return
+
+ needswap = False
+ dirs = [ ]
+
+ fstab=file("/etc/fstab","ab")
+ fstab.write("# cloud-config mounts\n")
+ for line in actlist:
+ fstab.write('\t'.join(line) + "\n")
+ if line[2] == "swap": needswap = True
+ if line[1].startswith("/"): dirs.append(line[1])
+ fstab.close()
+
+ if needswap:
+ try: util.subp(("swapon", "-a"))
+ except: warn("Failed to enable swap")
+
+ for d in dirs:
+ if os.path.exists(d): continue
+ try: os.makedirs(d)
+ except: warn("Failed to make '%s' config-mount\n",d)
+
+ try: util.subp(("mount","-a"))
+ except: pass
+
+
+
+
def apply_credentials(keys, user, disable_root):
keys = set(keys)
if user:
diff --git a/ec2init/DataSource.py b/ec2init/DataSource.py
index c761ae3e..9fe38b17 100644
--- a/ec2init/DataSource.py
+++ b/ec2init/DataSource.py
@@ -21,5 +21,10 @@ class DataSource:
def get_public_ssh_keys(self):
return([])
- def getswap_devs(self):
- raise Exception("do not know how to generate swap list")
+ def device_name_to_device(self, name):
+ # translate a 'name' to a device
+ # the primary function at this point is on ec2
+ # to consult metadata service, that has
+ # ephemeral0: sdb
+ # and return 'sdb' for input 'ephemeral0'
+ return(None)
diff --git a/ec2init/DataSourceEc2.py b/ec2init/DataSourceEc2.py
index 123ede67..1e81fddb 100644
--- a/ec2init/DataSourceEc2.py
+++ b/ec2init/DataSourceEc2.py
@@ -4,7 +4,6 @@ import ec2init
import socket
import urllib2
import time
-import cPickle
import boto_utils
class DataSourceEc2(DataSource.DataSource):
@@ -26,8 +25,9 @@ class DataSourceEc2(DataSource.DataSource):
self.userdata_raw = udf.read()
udf.close()
- mdf = open(self.cachedir + "/meta-data.pkl")
- self.metadata = cPickle.load(mdf)
+ mdf = open(self.cachedir + "/meta-data.raw")
+ data = mdf.read()
+ self.metadata = eval(data)
mdf.close()
return True
@@ -109,13 +109,17 @@ class DataSourceEc2(DataSource.DataSource):
return(keys)
- def getswap_devs(self):
+ def device_name_to_device(self, name):
+ # consult metadata service, that has
+ # ephemeral0: sdb
+ # and return 'sdb' for input 'ephemeral0'
if not self.metadata.has_key('block-device-mapping'):
- raise Exception("no block-device-mapping")
- list = []
- for use_t, device in self.metadata['block-device-mapping'].items():
- if not device.startswith("/dev"):
- device="/dev/%s" % device
- if use_t == "swap":
- list.append(device)
- return(list)
+ return(None)
+
+ for entname, device in self.metadata['block-device-mapping'].items():
+ if entname == name:
+ return(device)
+ # LP: #513842 mapping in Euca has 'ephemeral' not 'ephemeral0'
+ if entname == "ephemeral" and name == "ephemeral0":
+ return(device)
+ return None
diff --git a/ec2init/__init__.py b/ec2init/__init__.py
index c4923f1b..5405b5e4 100644
--- a/ec2init/__init__.py
+++ b/ec2init/__init__.py
@@ -285,43 +285,5 @@ class EC2Init:
def get_hostname(self):
return(self.datasource.get_hostname())
- def enable_swap(self):
- swaps=[]
- try:
- swaps=self.datasource.getswap_devs()
- except:
- process = subprocess.Popen(
- ['blkid', '-t', 'TYPE=swap', '-o', 'device'],
- stdout=subprocess.PIPE)
- (out,err)=process.communicate()
- swaps=out.strip().split('\n')
-
- if len(swaps) == 0: return
-
- fstab="/etc/fstab"
- f=file(fstab,"rb")
- lines=f.read().split('\n')
- f.close()
- existing=[]
- for line in lines:
- try:
- (dev,mp,type,opts,dump,pss)=line.split()
- if dev.startswith("#"): continue
- except:
- continue
- existing.append(dev)
-
- to_add=[]
- for dev in swaps:
- if not dev in existing:
- to_add.append(dev)
-
- if len(to_add) == 0 : return
-
- f=file(fstab,"ab")
- for dev in to_add:
- f.write("%s\tnone\tswap\tsw\t0\t0\n" % dev)
- f.close()
-
- subprocess.Popen(['swapon', '-a']).communicate()
-
+ def device_name_to_device(self,name):
+ return(self.datasource.device_name_to_device(name))