Skip to content

Instantly share code, notes, and snippets.

@viglesiasce
Last active August 29, 2015 13:57
Show Gist options
  • Select an option

  • Save viglesiasce/9766518 to your computer and use it in GitHub Desktop.

Select an option

Save viglesiasce/9766518 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
#
# Software License Agreement (BSD License)
#
# Copyright (c) 2013, Eucalyptus Systems, Inc.
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms, with or
# without modification, are permitted provided that the following conditions
# are met:
#
# Redistributions of source code must retain the above
# copyright notice, this list of conditions and the
# following disclaimer.
#
# Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the
# following disclaimer in the documentation and/or other
# materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import argparse
import logging
import os
import subprocess
import sys
import euca2ools
(major, minor, patch) = euca2ools.__version__.split('-')[0].split('.')
if int(major) < 3 or (int(major) >= 3 and int(minor) < 1):
print >> sys.stderr, "euca2ools version 3.1.0 or newer required."
sys.exit(1)
from requestbuilder.exceptions import ServiceInitError
class InstallImage(object):
@staticmethod
def _get_env():
return os.environ.copy()
def _check_dependency(self, path):
env = self._get_env()
cmd = [path]
try:
with open(os.devnull, 'w') as nullfile:
subprocess.call(cmd, env=env, stdout=nullfile, stderr=nullfile)
except OSError:
print >> sys.stderr, "Error cannot find: " + path
sys.exit(1)
def install_xz_archive(self, xz, bucket, name=None):
### Decompress image
self._check_dependency("xz")
decompress_cmd = "xz -d {0}".format(xz)
print "Decompressing xz archive: " + xz
decompress_output = subprocess.Popen(decompress_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
decompress_output.wait()
decompress_stdout = decompress_output.stdout.read()
decompress_stderr = decompress_output.stderr.read()
if decompress_output.returncode > 0:
print "Error: Imaging worker image unable to decompress.\n" + decompress_stdout + decompress_stderr
sys.exit(1)
image_file = xz.strip(".xz")
self.install_image(image_file, bucket, name)
def install_tarball(self, tarball, bucket, name=None):
### Decompress image
self._check_dependency("tar")
decompress_cmd = "tar xzfv {0}".format(tarball)
print "Decompressing tarball: " + tarball
decompress_output = subprocess.Popen(decompress_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
decompress_output.wait()
decompress_stdout = decompress_output.stdout.read()
decompress_stderr = decompress_output.stderr.read()
if decompress_output.returncode > 0:
print "Error: Imaging worker image unable to decompress.\n" + decompress_stdout + decompress_stderr
sys.exit(1)
image_file = decompress_stdout.strip()
self.install_image(image_file, bucket, name)
def install_image(self, image_file, bucket, name=None):
### Bundle and upload image
self._check_dependency("euca-bundle-and-upload-image")
self._check_dependency("euca-register")
install_cmd = "euca-bundle-and-upload-image -b {0} -i {1} -r x86_64".format(bucket, image_file)
print "Bundling and uploading image to bucket: " + bucket
bundle_output = subprocess.Popen(install_cmd, env=self._get_env(), stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
bundle_output.wait()
bundle_stdout = bundle_output.stdout.read()
bundle_stderr = bundle_output.stderr.read()
if bundle_output.returncode > 0:
print "Error: Imaging Worker unable to bundle and upload image.\n" + bundle_stdout + bundle_stderr
sys.exit(1)
try:
manifest = bundle_stdout.split()[1]
except IndexError:
print "Error: Imaging Worker unable to retrieve uploaded image manifest."
sys.exit(1)
register_cmd = "euca-register {0} --name {1} " \
"--virtualization-type hvm".format(manifest, name)
print "Registering image manifest: " + manifest
register_output = subprocess.Popen(register_cmd, env=self._get_env(), stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
register_output.wait()
register_stdout = register_output.stdout.read()
register_stderr = register_output.stderr.read()
if register_output.returncode > 0:
print "Error: Imaging Worker unable to register image.\n" + register_stdout + register_stderr
sys.exit(1)
emi_id = register_stdout.split()[1]
print "Registered image: " + emi_id
remove_tarball_cmd = "rm -f {0}".format(image_file)
remove_output = subprocess.Popen(remove_tarball_cmd, env=self._get_env(), stdout=subprocess.PIPE,
stderr=subprocess.PIPE, shell=True)
remove_output.wait()
remove_stdout = remove_output.stdout.read()
remove_stderr = remove_output.stderr.read()
if remove_output.returncode > 0:
print "Error: Unable delete {0}\n" + remove_stdout + remove_stderr
return emi_id
@classmethod
def create(cls):
#
# Quiet the attempts to get logger for Walrus
#
class NullHandler(logging.Handler):
def emit(self, record):
pass
logging.getLogger("Walrus").addHandler(NullHandler())
try:
return cls()
except ServiceInitError as err:
print >> sys.stderr, str(err)
sys.exit(1)
if __name__ == "__main__":
description = '''
Image Installation Tool:
This tool provides an easy way to install a Eucalyptus Image.
Images bundles can be downloaded from:
http://emis.eucalyptus.com/
'''
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
description=description)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-t', '--tarball', metavar='TARBALL',
help='Install a RAW image from inside a tarball')
group.add_argument('-i', '--image', metavar='IMAGE',
help='''This option must be supplied if you
would like to install a RAW image file''')
group.add_argument('-x', "--xz", metavar='XZ',
help='''This option must be supplied if you
would like to install an XZ archive containing an
RAW image file''')
parser.add_argument("-b", "--bucket", metavar='BUCKET', required=True)
parser.add_argument("-n", "--name", metavar='NAME', required=True)
args = parser.parse_args()
install_tool = InstallImage.create()
if args.tarball:
install_tool.install_tarball(args.tarball, args.bucket, args.name)
elif args.image:
install_tool.install_image(args.image, args.bucket, args.name)
elif args.xz:
install_tool.install_xz_archive(args.xz, args.bucket, args.name)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment