diff --git a/hepix/commands/amiconfig.sh b/hepix/commands/amiconfig.sh index 940d853..4e096b0 100644 --- a/hepix/commands/amiconfig.sh +++ b/hepix/commands/amiconfig.sh @@ -4,6 +4,12 @@ AMICONFIG="/usr/sbin/amiconfig" AMILOCK="/var/lock/subsys/amiconfig" AMISETUP="/etc/sysconfig/amiconfig" +# Where to look for injected extra user-data +AMI_EXTRA_USER_DATA="/cernvm/extra-user-data" + +# A lock file to signal appended user-data +AMI_DONE_EXTRA_APPENDED='/var/lib/amiconfig/extra-appended.done' + # Maximum number of retries when attempting to retrieve user-data AMI_DOWNLOAD_RETRIES=2 @@ -28,6 +34,7 @@ fi RetrieveUserData() { if [ "$AMICONFIG_CONTEXT_URL" != '' ] ; then + # If context URL is found, it's from the environment. We must fill manually # the "local copy", where applicable $LOGGER "Won't check for new URLs: found from environment: $AMICONFIG_CONTEXT_URL" @@ -65,16 +72,12 @@ RetrieveUserData() { fi else + RetrieveUserDataCvmOnline || RetrieveUserDataEC2 || RetrieveUserDataCloudStack || RetrieveUserDataGCE - if [ $? == 1 ] ; then - if [ ! -f /cernvm/extra-user-data ]; then - $LOGGER "No user-data can be retrieved from any location" - return 1 - else - cat /cernvm/extra-user-data > "$AMICONFIG_LOCAL_USER_DATA" - chmod 600 "$AMICONFIG_LOCAL_USER_DATA" - fi + if [ $? != 0 ] ; then + $LOGGER "No standard user-data can be retrieved from any standard source: we are going to check for extra injected user data" fi + fi # At this point, user-data is available locally. Let's uncompress it if needed @@ -91,14 +94,67 @@ RetrieveUserData() { fi fi - if [ -f /cernvm/extra-user-data ]; then - cat /cernvm/extra-user-data >> "$AMICONFIG_LOCAL_USER_DATA" + # Now we retrieve the extra user data (which is never compressed) and append it, if it exists + if [ ! -e "$AMI_DONE_EXTRA_APPENDED" ] ; then + RetrieveUserDataInjected && touch "$AMI_DONE_EXTRA_APPENDED" + else + $LOGGER "Extra injected user-data already appended, skipping" + fi + + # Hard failure only if no user-data can be found either from standard location and extra injected path + if [ ! -r "$AMICONFIG_LOCAL_USER_DATA" ] ; then + return 1 fi return 0 } +# Retrieve injected user data. Injected user-data does not exclude other +# user-data sources, but it is always appended to existing user-data. In some +# cases the injected extra user-data can be the only source: this case is +# appropriately dealt with. Returns 1 on failure, 0 if found +RetrieveUserDataInjected() { + + # Fall back to this path if no existing user-data is there already + LOCAL_USER_DATA='/var/lib/amiconfig/2007-12-15' + + if [ -r "$AMI_EXTRA_USER_DATA" ] ; then + + $LOGGER "Extra injected configuration: additional user-data found at $AMI_EXTRA_USER_DATA" + + if [ "$AMICONFIG_CONTEXT_URL" == '' ] ; then + + $LOGGER "Extra injected configuration: this is the only user-data source available" + + # This is the only user-data! Set variables properly and save permanently + mkdir -p "$LOCAL_USER_DATA" + export AMICONFIG_CONTEXT_URL="file:$LOCAL_USER_DATA" + export AMICONFIG_LOCAL_USER_DATA="${LOCAL_USER_DATA}/user-data" + echo "export AMICONFIG_CONTEXT_URL=$AMICONFIG_CONTEXT_URL" > $AMISETUP + + # Add a newline at the end (might be missing) + echo '' > "$AMICONFIG_LOCAL_USER_DATA" + + else + + $LOGGER "Extra injected configuration: appending configuration to current user-data at $AMICONFIG_LOCAL_USER_DATA" + + fi + + # Append extra injected user-data + cat "$AMI_EXTRA_USER_DATA" >> "$AMICONFIG_LOCAL_USER_DATA" + chmod 0600 "$AMICONFIG_LOCAL_USER_DATA" + + return 0 # success (found) + + fi + + $LOGGER "Extra injected configuration: no injected user-data found at $AMI_EXTRA_USER_DATA" + return 1 # failure (not found) + +} + # Tries to check for the user-data file left there from CernVM Online. # Returns 0 on success, 1 on failure RetrieveUserDataCvmOnline() { @@ -482,8 +538,6 @@ Main() { case "$MODE" in user) RunUserDataScript before - # Hack: read meta-data from HTTP, user-data locally to include extra user data - export AMICONFIG_EC2_USER_DATA_URL="file:$(dirname ${AMICONFIG_LOCAL_USER_DATA})" $AMICONFIG 2>&1 #| $PIPELOGGER RunUserDataScript after mkdir -p `dirname "$AMI_DONE_USER"` diff --git a/hepix/extra/hepix_functions b/hepix/extra/hepix_functions index 548644d..2d2a61b 100644 --- a/hepix/extra/hepix_functions +++ b/hepix/extra/hepix_functions @@ -83,21 +83,29 @@ getResourcesFromCD() { context_disk_found="" mount_dir=$(mktemp -d) - for dev in /dev/sr{0,1} /dev/{xv,v,h,s}d{c,d,b}; do + for dev in /dev/sr{0,1} /dev/{xv,v,h,s}d{c,d,b}{,1}; do if [ -e "${dev}" ] ; then rdisk=$dev - logger -t $0 "Attempting to mount contextualization image from $rdisk" - mount -t iso9660 ${rdisk} $mount_dir > /dev/null 2>&1 - if [ 0 -eq $? ]; then - if [ -e "$mount_dir/prolog.sh" -o -e "$mount_dir/context.sh" ]; then - cp -r $mount_dir/* $CONTEXT_DIR/ - chmod 700 $CONTEXT_DIR - context_disk_found="indeed" - break - else - umount $mount_dir >/dev/null 2>&1 - fi - fi + + # Extract filesystem type of device + fstype=$( blkid $rdisk | sed -e 's/SEC_TYPE//' | grep -o -E 'TYPE="[0-9a-zA-Z]+' ) + fstype=${fstype:6} + + if [ "x$fstype" = "xiso9660" -o "x$fstype" = "xvfat" ]; then + logger -t $0 "Attempting to mount contextualization image from $rdisk" + + mount -o ro ${rdisk} $mount_dir > /dev/null 2>&1 + if [ 0 -eq $? ]; then + if [ -e "$mount_dir/prolog.sh" -o -e "$mount_dir/context.sh" ]; then + cp -r $mount_dir/* $CONTEXT_DIR/ + chmod 700 $CONTEXT_DIR + context_disk_found="indeed" + break + else + umount $mount_dir >/dev/null 2>&1 + fi + fi + fi fi done if [ -z "${rdisk}" ]; then diff --git a/rpath/amiconfig/instancedata.py b/rpath/amiconfig/instancedata.py index e307204..573ffd0 100644 --- a/rpath/amiconfig/instancedata.py +++ b/rpath/amiconfig/instancedata.py @@ -42,23 +42,19 @@ def open(self, path): return results def read(self, path): - ec2_user_data_url = os.getenv("AMICONFIG_EC2_USER_DATA_URL") - if ec2_user_data_url is not None: - try: - results = urllib.urlopen('%s/user-data' % (ec2_user_data_url)) - except Exception, e: - raise EC2DataRetrievalError, '[Errno %s] %s' % (e.errno, e.strerror) - if results.headers.gettype() == 'text/html': - # Eucalyptus returns text/html and no Server: header - # We want to protect ourselves from HTTP servers returning real - # HTML, so let's hope at least they're conformant and return a - # Server: header - if 'server' in results.headers: - raise EC2DataRetrievalError, '%s' % results.read() - return results.read() return self.open(path).read() def getUserData(self): + + # Read user-data from cache if possible + user_data_cache = os.getenv("AMICONFIG_LOCAL_USER_DATA") + if user_data_cache is not None and user_data_cache[0] == '/': + try: + return open(user_data_cache).read() + except IOError, e: + pass + + # Fall back to standard read return self.read('user-data') def getAMIId(self):