deb-heat/heat/cloudinit/loguserdata.py
Zane Bitter 95ec13c572 Fix cloud-init Python syntax for Python < 2.6
The loguserdata.py file gets uploaded to the servers created by Heat to run
under cloud-init. Since the default versions of Python installed on the
user's server may be very old (e.g. RHEL 5 defaults to Python 2.4), avoid
using the octal syntax introduced for Python 3.0 and backported only as far
as Python 2.6. (Also avoid the old syntax, which will break on Python 3.x.)

Also remove use of the "with" statement from loguserdata.py and
part-handler.py. This statement is only available from Python 2.6 on (or in
Python 2.5 via "from __future__ import with_statement").

Finally, remove use of the "except ExceptionType as value" syntax for
catching exceptions. Again, this was only backported to Python 2.6.

Change-Id: I89e86d00993d51e2514b1e589503c6d966909403
Partial-Bug: #1375864
2014-10-01 15:16:45 -04:00

106 lines
2.9 KiB
Python
Executable File

#!/usr/bin/env python
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import datetime
from distutils.version import LooseVersion
import errno
import logging
import os
import pkg_resources
import subprocess
import sys
VAR_PATH = '/var/lib/heat-cfntools'
LOG = logging.getLogger('heat-provision')
def chk_ci_version():
v = LooseVersion(pkg_resources.get_distribution('cloud-init').version)
return v >= LooseVersion('0.6.0')
def init_logging():
LOG.setLevel(logging.INFO)
LOG.addHandler(logging.StreamHandler())
fh = logging.FileHandler("/var/log/heat-provision.log")
os.chmod(fh.baseFilename, int("600", 8))
LOG.addHandler(fh)
def call(args):
class LogStream(object):
def write(self, data):
LOG.info(data)
LOG.info('%s\n', ' '.join(args)) # noqa
try:
ls = LogStream()
p = subprocess.Popen(args, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
data = p.communicate()
if data:
for x in data:
ls.write(x)
except OSError:
ex_type, ex, tb = sys.exc_info()
if ex.errno == errno.ENOEXEC:
LOG.error('Userdata empty or not executable: %s', ex)
return os.EX_OK
else:
LOG.error('OS error running userdata: %s', ex)
return os.EX_OSERR
except Exception:
ex_type, ex, tb = sys.exc_info()
LOG.error('Unknown error running userdata: %s', ex)
return os.EX_SOFTWARE
return p.returncode
def main():
if not chk_ci_version():
# pre 0.6.0 - user data executed via cloudinit, not this helper
LOG.error('Unable to log provisioning, need a newer version of'
' cloud-init')
return -1
userdata_path = os.path.join(VAR_PATH, 'cfn-userdata')
os.chmod(userdata_path, int("700", 8))
LOG.info('Provision began: %s', datetime.datetime.now())
returncode = call([userdata_path])
LOG.info('Provision done: %s', datetime.datetime.now())
if returncode:
return returncode
if __name__ == '__main__':
init_logging()
code = main()
if code:
LOG.error('Provision failed with exit code %s', code)
sys.exit(code)
provision_log = os.path.join(VAR_PATH, 'provision-finished')
# touch the file so it is timestamped with when finished
pl = file(provision_log, 'a')
try:
os.utime(provision_log, None)
finally:
pl.close()