From 4c359db1b01d6b1be90dc872f7e1620b077ac918 Mon Sep 17 00:00:00 2001 From: Steven Dake Date: Thu, 7 Jun 2012 07:47:47 -0700 Subject: [PATCH] Remove cfntools and jeos These files are now available in the heat-jeos repository. Change-Id: I392e7443348a31e8454ae14d957b0b54560c2ec3 Signed-off-by: Steven Dake --- MANIFEST.in | 14 - bin/heat | 25 +- docs/GettingStarted.rst | 30 +- heat/cfntools/README | 13 - heat/cfntools/__init__.py | 0 heat/cfntools/cfn-get-metadata | 91 --- heat/cfntools/cfn-hup | 114 ---- heat/cfntools/cfn-init | 74 -- heat/cfntools/cfn-push-stats | 169 ----- heat/cfntools/cfn-signal | 91 --- heat/cfntools/cfn_helper.py | 893 ------------------------- heat/jeos/F16-i386-cfntools-jeos.tdl | 28 - heat/jeos/F16-i386-gold-jeos.tdl | 60 -- heat/jeos/F16-x86_64-cfntools-jeos.tdl | 28 - heat/jeos/F16-x86_64-gold-jeos.tdl | 60 -- heat/jeos/F17-i386-cfntools-jeos.tdl | 28 - heat/jeos/F17-i386-gold-jeos.tdl | 60 -- heat/jeos/F17-x86_64-cfntools-jeos.tdl | 28 - heat/jeos/F17-x86_64-gold-jeos.tdl | 60 -- heat/jeos/U10-amd64-cfntools-jeos.tdl | 25 - heat/utils.py | 214 ------ 21 files changed, 15 insertions(+), 2090 deletions(-) delete mode 100644 heat/cfntools/README delete mode 100644 heat/cfntools/__init__.py delete mode 100755 heat/cfntools/cfn-get-metadata delete mode 100755 heat/cfntools/cfn-hup delete mode 100755 heat/cfntools/cfn-init delete mode 100755 heat/cfntools/cfn-push-stats delete mode 100755 heat/cfntools/cfn-signal delete mode 100644 heat/cfntools/cfn_helper.py delete mode 100644 heat/jeos/F16-i386-cfntools-jeos.tdl delete mode 100644 heat/jeos/F16-i386-gold-jeos.tdl delete mode 100644 heat/jeos/F16-x86_64-cfntools-jeos.tdl delete mode 100644 heat/jeos/F16-x86_64-gold-jeos.tdl delete mode 100644 heat/jeos/F17-i386-cfntools-jeos.tdl delete mode 100644 heat/jeos/F17-i386-gold-jeos.tdl delete mode 100644 heat/jeos/F17-x86_64-cfntools-jeos.tdl delete mode 100644 heat/jeos/F17-x86_64-gold-jeos.tdl delete mode 100644 heat/jeos/U10-amd64-cfntools-jeos.tdl diff --git a/MANIFEST.in b/MANIFEST.in index c6886005d..f5ee34852 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -7,20 +7,6 @@ include MANIFEST.in pylintrc include openstack-common.conf include babel.cfg graft templates -include heat/jeos/F16-i386-gold-jeos.tdl -include heat/jeos/F17-i386-gold-jeos.tdl -include heat/jeos/F16-i386-cfntools-jeos.tdl -include heat/jeos/F17-i386-cfntools-jeos.tdl -include heat/jeos/F16-x86_64-gold-jeos.tdl -include heat/jeos/F17-x86_64-gold-jeos.tdl -include heat/jeos/F16-x86_64-cfntools-jeos.tdl -include heat/jeos/F17-x86_64-cfntools-jeos.tdl -include heat/jeos/U10-amd64-cfntools-jeos.tdl -include heat/cfntools/cfn-init -include heat/cfntools/cfn-hup -include heat/cfntools/cfn-signal -include heat/cfntools/cfn-get-metadata -include heat/cfntools/cfn-push-stats include heat/cloudinit/config include heat/cloudinit/part-handler.py include heat/db/sqlalchemy/migrate_repo/migrate.cfg diff --git a/bin/heat b/bin/heat index 5442f8a44..daad9c795 100755 --- a/bin/heat +++ b/bin/heat @@ -270,25 +270,6 @@ def stack_list(options, arguments): print json.dumps(result, indent=2) -@utils.catch_error('jeos-create') -def jeos_create(options, arguments): - ''' - Create a new JEOS (Just Enough Operating System) image. - - Usage: heat jeos-create - - Distribution: Distribution such as 'F16', 'F17', 'U10', 'D6'. - Architecture: Architecture such as 'i386' 'i686' or 'x86_64'. - Image Type: Image type such as 'gold' or 'cfntools'. - 'gold' is a basic gold JEOS. - 'cfntools' contains the cfntools helper scripts. - - The command must be run as root in order for libvirt to have permissions - to create virtual machines and read the raw DVDs. - ''' - utils.jeos_create(options, arguments, jeos_path, cfntools_path) - - def get_client(options): """ Returns a new client object to a heat server @@ -466,9 +447,7 @@ def lookup_command(parser, command_name): 'event-list': stack_events_list, 'validate': template_validate, 'gettemplate': get_template, - 'describe': stack_describe, - 'jeos_create': jeos_create, # DEPRECATED - 'jeos-create': jeos_create} + 'describe': stack_describe} commands = {} for command_set in (base_commands, stack_commands): @@ -507,8 +486,6 @@ Commands: validate Validate a template - jeos-create Create a JEOS image - event-list List events for a stack """ diff --git a/docs/GettingStarted.rst b/docs/GettingStarted.rst index 4fedabd60..591321487 100644 --- a/docs/GettingStarted.rst +++ b/docs/GettingStarted.rst @@ -121,29 +121,27 @@ This is for Heat to associate with the virtual machines. nova keypair-add --pub_key ~/.ssh/id_rsa.pub ${USER}_key -Install Oz ----------- -Verify that Oz_ is installed :: - - sudo yum -y install oz - -Oz is used below to create the JEOS. - -.. _Oz: http://aeolusproject.org/oz.html - -Create a JEOS -------------- +Download and install heat_jeos via git +-------------------------------------- +Download heat_jeos via git :: + git clone git://github.com/heat-api/heat-jeos.git + cd heat-jeos + setup.py install - sudo -E heat -y jeos-create F16 x86_64 cfntools +Create a JEOS with heat_jeos tools +---------------------------------- +:: -Note: The ``-E`` option to ``sudo`` preserves the environment, specifically the keystone credentials, when ``jeos-create`` is run as root. + sudo -E heat-jeos -y create F16 x86_64 cfntools -Note: ``jeos-create`` must be run as root in order to create the cfntools disk image. +Note: The ``-E`` option to ``sudo`` preserves the environment, specifically the keystone credentials, when ``heat-jeos`` is run as root. -Note: If you want to enable debugging output from Oz, add '``-d``' (debugging) to the ``jeos-create`` command. +Note: ``heat-jeos`` must be run as root in order to create the cfntools disk image. + +Note: If you want to enable debugging output from Oz, add '``-d``' (debugging) to the ``heat-jeos`` command. Verify JEOS registration ~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/heat/cfntools/README b/heat/cfntools/README deleted file mode 100644 index 49e6f9bc6..000000000 --- a/heat/cfntools/README +++ /dev/null @@ -1,13 +0,0 @@ -There are several bootstrap methods for cloudformations: -1. Create image with application ready to go -2. Use cloud-init to run a startup script passed as userdata to the nova - server create -3. Use the CloudFormation instance helper scripts - -This directory contains files required for choice #3. - -cfn-init - Reads the AWS::CloudFormation::Init for the instance resource, - installs packages, and starts services -cfn-signal - Waits for an application to be ready before continuing, ie: - supporting the WaitCondition feature -cfn-hup - Handle updates from the UpdateStack CloudFormation API call diff --git a/heat/cfntools/__init__.py b/heat/cfntools/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/heat/cfntools/cfn-get-metadata b/heat/cfntools/cfn-get-metadata deleted file mode 100755 index 61a078ccd..000000000 --- a/heat/cfntools/cfn-get-metadata +++ /dev/null @@ -1,91 +0,0 @@ -#!/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. - -""" -Implements cfn-get-metadata CloudFormation functionality -""" -import argparse -import io -import logging -import os -import os.path -import sys - - -if os.path.exists('/opt/aws/bin'): - sys.path.insert(0, '/opt/aws/bin') - from cfn_helper import * -else: - from heat.cfntools.cfn_helper import * - -description = " " -parser = argparse.ArgumentParser(description=description) -parser.add_argument('-s', '--stack', - dest="stack_name", - help="A Heat stack name", - required=True) -parser.add_argument('-r', '--resource', - dest="logical_resource_id", - help="A Heat logical resource ID", - required=True) -parser.add_argument('--access-key', - dest="access_key", - help="A Keystone access key", - required=False) -parser.add_argument('--secret-key', - dest="secret_key", - help="A Keystone secret key", - required=False) -parser.add_argument('--region', - dest="region", - help="Openstack region", - required=False) -parser.add_argument('--credential-file', - dest="credential_file", - help="credential-file", - required=False) -parser.add_argument('-u', '--url', - dest="url", - help="service url", - required=False) -parser.add_argument('-k', '--key', - dest="key", - help="key", - required=False) -args = parser.parse_args() - -if not args.stack_name: - print 'The Stack name must not be empty.' - exit(1) - -if not args.logical_resource_id: - print 'The Resource ID must not be empty' - exit(1) - -log_format = '%(levelname)s [%(asctime)s] %(message)s' -logging.basicConfig(format=log_format, level=logging.DEBUG) - -logger = logging.getLogger('cfn-get-metadata') -log_file_name = "/var/log/cfn-get-metadata.log" -file_handler = logging.FileHandler(log_file_name) -file_handler.setFormatter(logging.Formatter(log_format)) -logger.addHandler(file_handler) - -metadata = Metadata(args.stack_name, - args.logical_resource_id, - access_key=args.access_key, - secret_key=args.secret_key, - region=args.region) -metadata.retrieve() -print str(metadata) diff --git a/heat/cfntools/cfn-hup b/heat/cfntools/cfn-hup deleted file mode 100755 index 9aa261398..000000000 --- a/heat/cfntools/cfn-hup +++ /dev/null @@ -1,114 +0,0 @@ -#!/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. - -""" -Implements cfn-hup CloudFormation functionality -""" -import argparse -import io -import logging -import os -import os.path -import sys - - -if os.path.exists('/opt/aws/bin'): - sys.path.insert(0, '/opt/aws/bin') - from cfn_helper import * -else: - from heat.cfntools.cfn_helper import * - -description = " " -parser = argparse.ArgumentParser(description=description) -parser.add_argument('-c', '--config', - dest="config_dir", - help="Hook Config Directory", - required=False, - default='/etc/cfn/hooks.d') -parser.add_argument('-f', '--no-daemon', - dest="no_deamon", - action="store_true", - help="Do not run as a deamon", - required=False) -parser.add_argument('-v', '--verbose', - action="store_true", - dest="verbose", - help="Verbose logging", - required=False) -args = parser.parse_args() - -log_format = '%(levelname)s [%(asctime)s] %(message)s' -if args.verbose: - logging.basicConfig(format=log_format, level=logging.DEBUG) -else: - logging.basicConfig(format=log_format, level=logging.INFO) - -logger = logging.getLogger('cfntools') -log_file_name = "/var/log/cfn-hup.log" -file_handler = logging.FileHandler(log_file_name) -file_handler.setFormatter(logging.Formatter(log_format)) -logger.addHandler(file_handler) - -main_conf_path = '/etc/cfn/cfn-hup.conf' -try: - main_config_file = open(main_conf_path) -except IOError as exc: - logger.error('Could not open main configuration at %s' % main_conf_path) - exit(1) - -config_files = [] -hooks_conf_path = '/etc/cfn/hooks.conf' -if os.path.exists(hooks_conf_path): - try: - config_files.append(open(hooks_conf_path)) - except IOError as exc: - logger.exception(exc) - -if args.config_dir and os.path.exists(args.config_dir): - try: - for f in os.listdir(args.config_dir): - config_files.append(open(os.path.join(args.config_dir, f))) - - except OSError as exc: - logger.exception(exc) - -if not config_files: - logger.error('No hook files found at %s or %s' % (hooks_conf_path, - args.config_dir)) - exit(1) - -try: - mainconfig = HupConfig([main_config_file] + config_files) -except Exception as ex: - logger.error('Cannot load configuration: %s' % str(ex)) - exit(1) - -if not mainconfig.unique_resources_get(): - logger.error('No hooks were found. Add some to %s or %s' % (hooks_conf_path, - args.config_dir)) - exit(1) - - -for r in mainconfig.unique_resources_get(): - print r - metadata = Metadata(mainconfig.stack, - r, - credentials_file=mainconfig.credential_file, - region=mainconfig.region) - metadata.retrieve() - try: - metadata.cfn_hup(mainconfig.hooks) - except Exception as e: - logger.exception("Error processing metadata") - exit(1) diff --git a/heat/cfntools/cfn-init b/heat/cfntools/cfn-init deleted file mode 100755 index 9008170ac..000000000 --- a/heat/cfntools/cfn-init +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/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. - -""" -Implements cfn-init CloudFormation functionality -""" - -import argparse -import logging -import os -import sys - - -if os.path.exists('/opt/aws/bin'): - sys.path.insert(0, '/opt/aws/bin') - from cfn_helper import * -else: - from heat.cfntools.cfn_helper import * - -description = " " -parser = argparse.ArgumentParser(description=description) -parser.add_argument('-s', '--stack', - dest="stack_name", - help="A Heat stack name", - required=False) -parser.add_argument('-r', '--resource', - dest="logical_resource_id", - help="A Heat logical resource ID", - required=False) -parser.add_argument('--access-key', - dest="access_key", - help="A Keystone access key", - required=False) -parser.add_argument('--secret-key', - dest="secret_key", - help="A Keystone secret key", - required=False) -parser.add_argument('--region', - dest="region", - help="Openstack region", - required=False) -args = parser.parse_args() - -log_format = '%(levelname)s [%(asctime)s] %(message)s' -logging.basicConfig(format=log_format, level=logging.DEBUG) - -logger = logging.getLogger('cfn-init') -log_file_name = "/var/log/cfn-init.log" -file_handler = logging.FileHandler(log_file_name) -file_handler.setFormatter(logging.Formatter(log_format)) -logger.addHandler(file_handler) - -metadata = Metadata(args.stack_name, - args.logical_resource_id, - access_key=args.access_key, - secret_key=args.secret_key, - region=args.region) -metadata.retrieve() -try: - metadata.cfn_init() -except Exception as e: - logger.exception("Error processing metadata") - exit(1) diff --git a/heat/cfntools/cfn-push-stats b/heat/cfntools/cfn-push-stats deleted file mode 100755 index 148f41ac2..000000000 --- a/heat/cfntools/cfn-push-stats +++ /dev/null @@ -1,169 +0,0 @@ -#!/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. - -""" -Implements cfn-signal CloudFormation functionality -""" -import argparse -import logging -import os -import random -import sys - - -log_format = '%(levelname)s [%(asctime)s] %(message)s' -logging.basicConfig(format=log_format, level=logging.DEBUG) -logger = logging.getLogger('cfn-push-stats') - -try: - import psutil -except ImportError: - logger.warn("psutil not available. If you want process and memory " - "statistics, you need to install it.") -# -# --aws-credential-file=PATH Specifies the location of the file with AWS -# credentials. -# --aws-access-key-id=VALUE Specifies the AWS access key ID to use to -# identify the caller. -# --aws-secret-key=VALUE Specifies the AWS secret key to use to sign -# the request. -# --from-cron Specifies that this script is running from cron. -# -# Examples -# -# To perform a simple test run without posting data to Amazon CloudWatch -# -# ./mon-put-instance-data.pl --mem-util --verify --verbose -# -# To set a five-minute cron schedule to report memory and disk space utilization to CloudWatch -# -# */5 * * * * ~/aws-scripts-mon/mon-put-instance-data.pl --mem-util --disk-space-util --disk-path=/ --from-cron -# - -if os.path.exists('/opt/aws/bin'): - sys.path.insert(0, '/opt/aws/bin') - from cfn_helper import * -else: - from heat.cfntools.cfn_helper import * - -KILO = 1024 -MEGA = 1048576 -GIGA = 1073741824 -unit_map = {'bytes': 1, - 'kilobytes': KILO, - 'megabytes': MEGA, - 'gigabytes': GIGA} - -description = " " -parser = argparse.ArgumentParser(description=description) -parser.add_argument('-v', '--verbose', action="store_true", - help="Verbose logging", required=False) -parser.add_argument('--service-failure', required=False, action="store_true", - help='Reports a service falure.') -parser.add_argument('--mem-util', required=False, action="store_true", - help='Reports memory utilization in percentages.') -parser.add_argument('--mem-used', required=False, action="store_true", - help='Reports memory used (excluding cache and buffers) in megabytes.') -parser.add_argument('--mem-avail', required=False, action="store_true", - help='Reports available memory (including cache and buffers) in megabytes.') -parser.add_argument('--swap-util', required=False, action="store_true", - help='Reports swap utilization in percentages.') -parser.add_argument('--swap-used', required=False, action="store_true", - help='Reports allocated swap space in megabytes.') -parser.add_argument('--disk-space-util', required=False, action="store_true", - help='Reports disk space utilization in percentages.') -parser.add_argument('--disk-space-used', required=False, action="store_true", - help='Reports allocated disk space in gigabytes.') -parser.add_argument('--disk-space-avail',required=False, action="store_true", - help='Reports available disk space in gigabytes.') -parser.add_argument('--memory-units', required=False, default='megabytes', - help='Specifies units for memory metrics.') -parser.add_argument('--disk-units', required=False, default='megabytes', - help='Specifies units for disk metrics.') -parser.add_argument('--disk-path', required=False, default='/', - help='Selects the disk by the path on which to report.') -parser.add_argument('--watch', required=True, - help='the name of the watch to post to.') -args = parser.parse_args() - -data = {'Namespace': 'system/linux'} - -# service failure -# =============== -if args.service_failure: - data['ServiceFailure'] = { - 'Value': 1, - 'Units': 'Counter'} - -# memory space -# ========== -if args.mem_util or args.mem_used or args.mem_avail: - mem = psutil.phymem_usage() -if args.mem_util: - data['MemoryUtilization'] = { - 'Value': mem.percent, - 'Units': 'Percent'} -if args.mem_used: - data['MemoryUsed'] = { - 'Value': mem.used / unit_map[args.memory_units], - 'Units': args.memory_units} -if args.mem_avail: - data['MemoryAvailable'] = { - 'Value': mem.free / unit_map[args.memory_units], - 'Units': args.memory_units} - -# swap space -# ========== -if args.swap_util or args.swap_used: - swap = psutil.virtmem_usage() -if args.swap_util: - data['SwapUtilization'] = { - 'Value': swap.percent, - 'Units': 'Percent'} -if args.swap_used: - data['SwapUsed'] = { - 'Value': swap.used / unit_map[args.memory_units], - 'Units': args.memory_units} - -# disk space -# ========== -if args.disk_space_util or args.disk_space_used or args.disk_space_avail: - disk = psutil.disk_usage(args.disk_path) -if args.disk_space_util: - data['DiskSpaceUtilization'] = { - 'Value': disk.percent, - 'Units': 'Percent'} -if args.disk_space_used: - data['DiskSpaceUsed'] = { - 'Value': disk.used / unit_map[args.disk_units], - 'Units': args.disk_units} -if args.disk_space_avail: - data['DiskSpaceAvailable'] = { - 'Value': disk.free / unit_map[args.disk_units], - 'Units': args.disk_units} - -logger.info(str(data)) - -server_url = metadata_server_url() -if not server_url: - logger.error('can not get the metadata_server_url') - exit(1) -url = '%sstats/%s/data/' % (server_url, args.watch) - -cmd_str = "curl -X POST -H \'Content-Type:\' --data-binary \'%s\' %s" % \ - (json.dumps(data), url) - -cmd = CommandRunner(cmd_str) -cmd.run() -logger.info(cmd.stdout) diff --git a/heat/cfntools/cfn-signal b/heat/cfntools/cfn-signal deleted file mode 100755 index aa68ac1ea..000000000 --- a/heat/cfntools/cfn-signal +++ /dev/null @@ -1,91 +0,0 @@ -#!/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. - -""" -Implements cfn-signal CloudFormation functionality -""" -import argparse -import logging -import os -import sys - - -if os.path.exists('/opt/aws/bin'): - sys.path.insert(0, '/opt/aws/bin') - from cfn_helper import * -else: - from heat.cfntools.cfn_helper import * - - -description = " " -parser = argparse.ArgumentParser(description=description) -parser.add_argument('-s', '--success', - dest="success", - help="signal status to report", - default='true', - required=False) -parser.add_argument('-r', '--reason', - dest="reason", - help="The reason for the failure", - default="Configuration Complete", - required=False) -parser.add_argument('--data', - dest="data", - default="Application has completed configuration.", - help="The data to send", - required=False) -parser.add_argument('-i', '--id', - dest="unique_id", - help="the unique id to send back to the WaitCondition", - default='00000', - required=False) -parser.add_argument('-e', '--exit', - dest="exit_code", - help="The exit code from a procecc to interpret", - default=None, - required=False) -parser.add_argument('url', - help='the url to post to') -args = parser.parse_args() - -log_format = '%(levelname)s [%(asctime)s] %(message)s' -logging.basicConfig(format=log_format, level=logging.DEBUG) - -logger = logging.getLogger('cfn-init') -log_file_name = "/var/log/cfn-signal.log" -file_handler = logging.FileHandler(log_file_name) -file_handler.setFormatter(logging.Formatter(log_format)) -logger.addHandler(file_handler) - -logger.debug('cfn-signal called %s ' % (str(args))) - -status = 'FAILURE' -if args.exit_code: - # "exit_code" takes presedence over "success". - if args.exit_code == '0': - status = 'SUCCESS' -else: - if args.success == 'true': - status = 'SUCCESS' - -body = { - "Status" : status, - "Reason" : args.reason, - "UniqueId" : args.unique_id, - "Data" : args.data -} - -cmd_str = "curl -X PUT -H \'Content-Type:\' --data-binary \'%s\' %s" % \ - (json.dumps(body), args.url) -CommandRunner(cmd_str).run() diff --git a/heat/cfntools/cfn_helper.py b/heat/cfntools/cfn_helper.py deleted file mode 100644 index a30f49f89..000000000 --- a/heat/cfntools/cfn_helper.py +++ /dev/null @@ -1,893 +0,0 @@ -# -# 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. - -""" -Implements cfn metadata handling - -Resource metadata currently implemented: - * config/packages - * config/services - -Not implemented yet: - * config sets - * config/sources - * config/commands - * config/files - * config/users - * config/groups - * command line args - - placeholders are ignored -""" - -import ConfigParser -import errno -import grp -import json -import logging -import os -import os.path -import pwd -try: - import rpmUtils.updates as rpmupdates - import rpmUtils.miscutils as rpmutils - rpmutils_present = True -except: - rpmutils_present = False -import subprocess -import sys -from urllib2 import urlopen, Request -from urlparse import urlparse, urlunparse - - -logger = logging.getLogger('cfntools') - - -def to_boolean(b): - val = b.lower().strip() if isinstance(b, basestring) else b - return val in [True, 'true', 'yes', '1', 1] - - -class HupConfig(object): - def __init__(self, fp_list): - self.config = ConfigParser.SafeConfigParser() - for fp in fp_list: - self.config.readfp(fp) - - self.load_main_section() - - self.hooks = {} - for s in self.config.sections(): - if s != 'main': - self.hooks[s] = Hook(s, - self.config.get(s, 'triggers'), - self.config.get(s, 'path'), - self.config.get(s, 'runas'), - self.config.get(s, 'action')) - - def load_main_section(self): - # required values - self.stack = self.config.get('main', 'stack') - self.credential_file = self.config.get('main', 'credential-file') - try: - with open(self.credential_file) as f: - self.credentials = f.read() - except: - raise Exception("invalid credentials file %s" % - self.credential_file) - - # optional values - try: - self.region = self.config.get('main', 'region') - except ConfigParser.NoOptionError: - self.region = 'nova' - - try: - self.interval = self.config.getint('main', 'interval') - except ConfigParser.NoOptionError: - self.interval = 10 - - def __str__(self): - return '{stack: %s, credential_file: %s, region: %s, interval:%d}' % \ - (self.stack, self.credential_file, self.region, self.interval) - - def unique_resources_get(self): - resources = [] - for h in self.hooks: - r = self.hooks[h].resource_name_get() - if not r in resources: - resources.append(self.hooks[h].resource_name_get()) - return resources - - -class Hook(object): - def __init__(self, name, triggers, path, runas, action): - self.name = name - self.triggers = triggers - self.path = path - self.runas = runas - self.action = action - - def resource_name_get(self): - sp = self.path.split('.') - return sp[1] - - def event(self, ev_name, ev_object, ev_resource): - if self.resource_name_get() == ev_resource and \ - ev_name in self.triggers: - CommandRunner(self.action).run(user=self.runas) - else: - logger.debug('event: {%s, %s, %s} did not match %s' % - (ev_name, ev_object, ev_resource, self.__str__())) - - def __str__(self): - return '{%s, %s, %s, %s, %s}' % \ - (self.name, - self.triggers, - self.path, - self.runas, - self.action) - - -class CommandRunner(object): - """ - Helper class to run a command and store the output. - """ - - def __init__(self, command, nextcommand=None): - self._command = command - self._next = nextcommand - self._stdout = None - self._stderr = None - self._status = None - - def __str__(self): - s = "CommandRunner:" - s += "\n\tcommand: %s" % self._command - if self._status: - s += "\n\tstatus: %s" % self._status - if self._stdout: - s += "\n\tstdout: %s" % self._stdout - if self._stderr: - s += "\n\tstderr: %s" % self._stderr - return s - - def run(self, user='root'): - """ - Run the Command and return the output. - - Returns: - self - """ - logger.debug("Running command: %s" % self._command) - cmd = ['su', user, '-c', self._command] - subproc = subprocess.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - output = subproc.communicate() - - self._status = subproc.returncode - self._stdout = output[0] - self._stderr = output[1] - if self._next: - self._next.run() - return self - - @property - def stdout(self): - return self._stdout - - @property - def stderr(self): - return self._stderr - - @property - def status(self): - return self._status - - -class RpmHelper(object): - - if rpmutils_present: - _rpm_util = rpmupdates.Updates([], []) - - @classmethod - def prepcache(cls): - """ - Prepare the yum cache - """ - CommandRunner("yum -y makecache").run() - - @classmethod - def compare_rpm_versions(cls, v1, v2): - """ - Compare two RPM version strings. - - Arguments: - v1 -- a version string - v2 -- a version string - - Returns: - 0 -- the versions are equal - 1 -- v1 is greater - -1 -- v2 is greater - """ - if v1 and v2: - return rpmutils.compareVerOnly(v1, v2) - elif v1: - return 1 - elif v2: - return -1 - else: - return 0 - - @classmethod - def newest_rpm_version(cls, versions): - """ - Returns the highest (newest) version from a list of versions. - - Arguments: - versions -- A list of version strings - e.g., ['2.0', '2.2', '2.2-1.fc16', '2.2.22-1.fc16'] - """ - if versions: - if isinstance(versions, basestring): - return versions - versions = sorted(versions, rpmutils.compareVerOnly, - reverse=True) - return versions[0] - else: - return None - - @classmethod - def rpm_package_version(cls, pkg): - """ - Returns the version of an installed RPM. - - Arguments: - pkg -- A package name - """ - cmd = "rpm -q --queryformat '%{VERSION}-%{RELEASE}' %s" % pkg - command = CommandRunner(cmd).run() - return command.stdout - - @classmethod - def rpm_package_installed(cls, pkg): - """ - Indicates whether pkg is in rpm database. - - Arguments: - pkg -- A package name (with optional version and release spec). - e.g., httpd - e.g., httpd-2.2.22 - e.g., httpd-2.2.22-1.fc16 - """ - command = CommandRunner("rpm -q %s" % pkg).run() - return command.status == 0 - - @classmethod - def yum_package_available(cls, pkg): - """ - Indicates whether pkg is available via yum - - Arguments: - pkg -- A package name (with optional version and release spec). - e.g., httpd - e.g., httpd-2.2.22 - e.g., httpd-2.2.22-1.fc16 - """ - cmd_str = "yum -C -y --showduplicates list available %s" % pkg - command = CommandRunner(cmd_str).run() - return command.status == 0 - - @classmethod - def install(cls, packages, rpms=True): - """ - Installs (or upgrades) a set of packages via RPM or via Yum. - - Arguments: - packages -- a list of packages to install - rpms -- if True: - * use RPM to install the packages - * packages must be a list of URLs to retrieve RPMs - if False: - * use Yum to install packages - * packages is a list of: - - pkg name (httpd), or - - pkg name with version spec (httpd-2.2.22), or - - pkg name with version-release spec - (httpd-2.2.22-1.fc16) - """ - if rpms: - cmd = "rpm -U --force --nosignature " - cmd += " ".join(packages) - logger.info("Installing packages: %s" % cmd) - else: - cmd = "yum -y install " - cmd += " ".join(packages) - logger.info("Installing packages: %s" % cmd) - command = CommandRunner(cmd).run() - if command.status: - logger.warn("Failed to install packages: %s" % cmd) - - @classmethod - def downgrade(cls, packages, rpms=True): - """ - Downgrades a set of packages via RPM or via Yum. - - Arguments: - packages -- a list of packages to downgrade - rpms -- if True: - * use RPM to downgrade (replace) the packages - * packages must be a list of URLs to retrieve the RPMs - if False: - * use Yum to downgrade packages - * packages is a list of: - - pkg name with version spec (httpd-2.2.22), or - - pkg name with version-release spec - (httpd-2.2.22-1.fc16) - """ - if rpms: - cls.install(packages) - else: - cmd = "yum -y downgrade " - cmd += " ".join(packages) - logger.info("Downgrading packages: %s" % cmd) - command = Command(cmd).run() - if command.status: - logger.warn("Failed to downgrade packages: %s" % cmd) - - -class PackagesHandler(object): - _packages = {} - - _package_order = ["dpkg", "rpm", "apt", "yum"] - - @staticmethod - def _pkgsort(pkg1, pkg2): - order = PackagesHandler._package_order - p1_name = pkg1[0] - p2_name = pkg2[0] - if p1_name in order and p2_name in order: - return cmp(order.index(p1_name), order.index(p2_name)) - elif p1_name in order: - return -1 - elif p2_name in order: - return 1 - else: - return cmp(p1_name.lower(), p2_name.lower()) - - def __init__(self, packages): - self._packages = packages - - def _handle_gem_packages(self, packages): - """ - very basic support for gems - """ - # TODO(asalkeld) support versions - # -b == local & remote install - # -y == install deps - opts = '-b -y' - for pkg_name, versions in packages.iteritems(): - if len(versions) > 0: - cmd_str = 'gem install %s --version %s %s' % (opts, - versions[0], - pkg_name) - CommandRunner(cmd_str).run() - else: - CommandRunner('gem install %s %s' % (opts, pkg_name)).run() - - def _handle_python_packages(self, packages): - """ - very basic support for easy_install - """ - # TODO(asalkeld) support versions - for pkg_name, versions in packages.iteritems(): - cmd_str = 'easy_install %s' % (pkg_name) - CommandRunner(cmd_str).run() - - def _handle_yum_packages(self, packages): - """ - Handle installation, upgrade, or downgrade of a set of - packages via yum. - - Arguments: - packages -- a package entries map of the form: - "pkg_name" : "version", - "pkg_name" : ["v1", "v2"], - "pkg_name" : [] - - For each package entry: - * if no version is supplied and the package is already installed, do - nothing - * if no version is supplied and the package is _not_ already - installed, install it - * if a version string is supplied, and the package is already - installed, determine whether to downgrade or upgrade (or do nothing - if version matches installed package) - * if a version array is supplied, choose the highest version from the - array and follow same logic for version string above - """ - # collect pkgs for batch processing at end - installs = [] - downgrades = [] - # update yum cache - RpmHelper.prepcache() - for pkg_name, versions in packages.iteritems(): - ver = RpmHelper.newest_rpm_version(versions) - pkg = "%s-%s" % (pkg_name, ver) if ver else pkg_name - if RpmHelper.rpm_package_installed(pkg): - # FIXME:print non-error, but skipping pkg - pass - elif not RpmHelper.yum_package_available(pkg): - logger.warn("Skipping package '%s'. Not available via yum" % - pkg) - elif not ver: - installs.append(pkg) - else: - current_ver = RpmHelper.rpm_package_version(pkg) - rc = RpmHelper.compare_rpm_versions(current_ver, ver) - if rc < 0: - installs.append(pkg) - elif rc > 0: - downgrades.append(pkg) - if installs: - RpmHelper.install(installs, rpms=False) - if downgrades: - RpmHelper.downgrade(downgrades) - - def _handle_rpm_packages(sef, packages): - """ - Handle installation, upgrade, or downgrade of a set of - packages via rpm. - - Arguments: - packages -- a package entries map of the form: - "pkg_name" : "url" - - For each package entry: - * if the EXACT package is already installed, skip it - * if a different version of the package is installed, overwrite it - * if the package isn't installed, install it - """ - #FIXME: handle rpm installs - pass - - def _handle_apt_packages(self, packages): - """ - very basic support for apt - """ - # TODO(asalkeld) support versions - pkg_list = ' '.join([p for p in packages]) - - cmd_str = 'apt-get -y install %s' % pkg_list - CommandRunner(cmd_str).run() - - # map of function pionters to handle different package managers - _package_handlers = { - "yum": _handle_yum_packages, - "rpm": _handle_rpm_packages, - "apt": _handle_apt_packages, - "rubygems": _handle_gem_packages, - "python": _handle_python_packages - } - - def _package_handler(self, manager_name): - handler = None - if manager_name in self._package_handlers: - handler = self._package_handlers[manager_name] - return handler - - def apply_packages(self): - """ - Install, upgrade, or downgrade packages listed - Each package is a dict containing package name and a list of versions - Install order: - * dpkg - * rpm - * apt - * yum - """ - if not self._packages: - return - packages = sorted(self._packages.iteritems(), PackagesHandler._pkgsort) - - for manager, package_entries in packages: - handler = self._package_handler(manager) - if not handler: - logger.warn("Skipping invalid package type: %s" % manager) - else: - handler(self, package_entries) - - -class FilesHandler(object): - def __init__(self, files): - self._files = files - - def apply_files(self): - if not self._files: - return - for fdest, meta in self._files.iteritems(): - dest = fdest.encode() - try: - os.makedirs(os.path.dirname(dest)) - except OSError as e: - if e.errno == errno.EEXIST: - logger.debug(str(e)) - else: - logger.exception(e) - - if 'content' in meta: - if isinstance(meta['content'], basestring): - f = open(dest, 'w') - f.write(meta['content']) - f.close() - else: - f = open(dest, 'w') - f.write(json.dumps(meta['content'], indent=4)) - f.close() - elif 'source' in meta: - CommandRunner('wget -O %s %s' % (dest, meta['source'])).run() - else: - logger.error('%s %s' % (dest, str(meta))) - continue - - uid = -1 - gid = -1 - if 'owner' in meta: - try: - user_info = pwd.getpwnam(meta['owner']) - uid = user_info[2] - except KeyError as ex: - pass - - if 'group' in meta: - try: - group_info = grp.getgrnam(meta['group']) - gid = group_info[2] - except KeyError as ex: - pass - - os.chown(dest, uid, gid) - if 'mode' in meta: - os.chmod(dest, int(meta['mode'], 8)) - - -class SourcesHandler(object): - ''' - tar, tar+gzip,tar+bz2 and zip - ''' - _sources = {} - - def __init__(self, sources): - self._sources = sources - - def _url_to_tmp_filename(self, url): - sp = url.split('/') - if 'https://github.com' in url: - if 'zipball' == sp[-2]: - return '/tmp/%s-%s.zip' % (sp[-3], sp[-1]) - elif 'tarball' == sp[-2]: - return '/tmp/%s-%s.tar.gz' % (sp[-3], sp[-1]) - else: - pass - - return '/tmp/%s' % (sp[-1]) - - def _decompress(self, archive, dest_dir): - cmd_str = '' - logger.debug("Decompressing") - (r, ext) = os.path.splitext(archive) - if ext == '.tgz': - cmd_str = 'tar -C %s -xzf %s' % (dest_dir, archive) - elif ext == '.tbz2': - cmd_str = 'tar -C %s -xjf %s' % (dest_dir, archive) - elif ext == '.zip': - cmd_str = 'unzip -d %s %s' % (dest_dir, archive) - elif ext == '.tar': - cmd_str = 'tar -C %s -xf %s' % (dest_dir, archive) - elif ext == '.gz': - (r, ext) = os.path.splitext(r) - if ext: - cmd_str = 'tar -C %s -xzf %s' % (dest_dir, archive) - else: - cmd_str = 'gunzip -c %s > %s' % (archive, dest_dir) - elif ext == 'bz2': - (r, ext) = os.path.splitext(r) - if ext: - cmd_str = 'tar -C %s -xjf %s' % (dest_dir, archive) - else: - cmd_str = 'bunzip2 -c %s > %s' % (archive, dest_dir) - else: - pass - return CommandRunner(cmd_str) - - def apply_sources(self): - if not self._sources: - return - for dest, url in self._sources.iteritems(): - tmp_name = self._url_to_tmp_filename(url) - cmd_str = 'wget -O %s %s' % (tmp_name, url) - decompress_command = self._decompress(tmp_name, dest) - CommandRunner(cmd_str, decompress_command).run() - try: - os.makedirs(dest) - except OSError as e: - if e.errno == errno.EEXIST: - logger.debug(str(e)) - else: - logger.exception(e) - - -class ServicesHandler(object): - _services = {} - - def __init__(self, services, resource=None, hooks=None): - self._services = services - self.resource = resource - self.hooks = hooks - - def _handle_sysv_command(self, service, command): - service_exe = "/sbin/service" - enable_exe = "/sbin/chkconfig" - cmd = "" - if "enable" == command: - cmd = "%s %s on" % (enable_exe, service) - elif "disable" == command: - cmd = "%s %s off" % (enable_exe, service) - elif "start" == command: - cmd = "%s %s start" % (service_exe, service) - elif "stop" == command: - cmd = "%s %s stop" % (service_exe, service) - elif "status" == command: - cmd = "%s %s status" % (service_exe, service) - command = CommandRunner(cmd) - command.run() - return command - - def _handle_systemd_command(self, service, command): - exe = "/bin/systemctl" - cmd = "" - service = '%s.service' % service - if "enable" == command: - cmd = "%s enable %s" % (exe, service) - elif "disable" == command: - cmd = "%s disable %s" % (exe, service) - elif "start" == command: - cmd = "%s start %s" % (exe, service) - elif "stop" == command: - cmd = "%s stop %s" % (exe, service) - elif "status" == command: - cmd = "%s status %s" % (exe, service) - command = CommandRunner(cmd) - command.run() - return command - - def _initialize_service(self, handler, service, properties): - if "enabled" in properties: - enable = to_boolean(properties["enabled"]) - if enable: - logger.info("Enabling service %s" % service) - handler(self, service, "enable") - else: - logger.info("Disabling service %s" % service) - handler(self, service, "disable") - - if "ensureRunning" in properties: - ensure_running = to_boolean(properties["ensureRunning"]) - command = handler(self, service, "status") - running = command.status == 0 - if ensure_running and not running: - logger.info("Starting service %s" % service) - handler(self, service, "start") - elif not ensure_running and running: - logger.info("Stopping service %s" % service) - handler(self, service, "stop") - - def _monitor_service(self, handler, service, properties): - if "ensureRunning" in properties: - ensure_running = to_boolean(properties["ensureRunning"]) - command = handler(self, service, "status") - running = command.status == 0 - if ensure_running and not running: - logger.warn("Restarting service %s" % service) - start_cmd = handler(self, service, "start") - if start_cmd.status != 0: - logger.warning('Service %s did not start. STDERR: %s' % - (service, start_cmd.stderr)) - return - for h in self.hooks: - self.hooks[h].event('service.restarted', - service, self.resource) - - def _monitor_services(self, handler, services): - for service, properties in services.iteritems(): - self._monitor_service(handler, service, properties) - - def _initialize_services(self, handler, services): - for service, properties in services.iteritems(): - self._initialize_service(handler, service, properties) - - # map of function pointers to various service handlers - _service_handlers = { - "sysvinit": _handle_sysv_command, - "systemd": _handle_systemd_command - } - - def _service_handler(self, manager_name): - handler = None - if manager_name in self._service_handlers: - handler = self._service_handlers[manager_name] - return handler - - def apply_services(self): - """ - Starts, stops, enables, disables services - """ - if not self._services: - return - for manager, service_entries in self._services.iteritems(): - handler = self._service_handler(manager) - if not handler: - logger.warn("Skipping invalid service type: %s" % manager) - else: - self._initialize_services(handler, service_entries) - - def monitor_services(self): - """ - Restarts failed services, and runs hooks. - """ - if not self._services: - return - for manager, service_entries in self._services.iteritems(): - handler = self._service_handler(manager) - if not handler: - logger.warn("Skipping invalid service type: %s" % manager) - else: - self._monitor_services(handler, service_entries) - - -def metadata_server_url(): - """ - Return the url to the metadata server. - """ - try: - f = open("/var/lib/cloud/data/cfn-metadata-server") - server_url = f.read().strip() - f.close() - if not server_url[-1] == '/': - server_url += '/' - return server_url - except IOError: - return None - - -class MetadataServerConnectionError(Exception): - pass - - -class Metadata(object): - _metadata = None - _init_key = "AWS::CloudFormation::Init" - - def __init__(self, stack, resource, access_key=None, - secret_key=None, credentials_file=None, region=None): - - self.stack = stack - self.resource = resource - self.access_key = access_key - self.secret_key = secret_key - self.credentials_file = credentials_file - self.region = region - - # TODO(asalkeld) is this metadata for the local resource? - self._is_local_metadata = True - self._metadata = None - - def metadata_resource_url(self): - server_url = metadata_server_url() - if not server_url: - return - return server_url + 'stacks/%s/resources/%s' % (self.stack, - self.resource) - - def remote_metadata(self): - """ - Connect to the metadata server and retreive the metadata from there. - """ - url = self.metadata_resource_url() - if not url: - raise MetadataServerConnectionError() - - try: - return urlopen(url).read() - except: - raise MetadataServerConnectionError() - - def retrieve(self, meta_str=None): - """ - Read the metadata from the given filename - """ - if meta_str: - self._data = meta_str - else: - try: - self._data = self.remote_metadata() - except MetadataServerConnectionError: - f = open("/var/lib/cloud/data/cfn-init-data") - self._data = f.read() - f.close() - - if isinstance(self._data, str): - self._metadata = json.loads(self._data) - else: - self._metadata = self._data - - def __str__(self): - return json.dumps(self._metadata) - - def _is_valid_metadata(self): - """ - Should find the AWS::CloudFormation::Init json key - """ - is_valid = self._metadata and \ - self._init_key in self._metadata and \ - self._metadata[self._init_key] - if is_valid: - self._metadata = self._metadata[self._init_key] - return is_valid - - def _process_config(self): - """ - Parse and process a config section - * packages - * sources - * users (not yet) - * groups (not yet) - * files - * commands (not yet) - * services - """ - - self._config = self._metadata["config"] - PackagesHandler(self._config.get("packages")).apply_packages() - #FIXME: handle sources - SourcesHandler(self._config.get("sources")).apply_sources() - #FIXME: handle users - #FIXME: handle groups - FilesHandler(self._config.get("files")).apply_files() - #FIXME: handle commands - ServicesHandler(self._config.get("services")).apply_services() - - def cfn_init(self): - """ - Process the resource metadata - """ - # FIXME: when config sets are implemented, this should select the - # correct config set from the metadata, and send each config in the - # config set to process_config - if not self._is_valid_metadata(): - raise Exception("invalid metadata") - else: - self._process_config() - - def cfn_hup(self, hooks): - """ - Process the resource metadata - """ - if not self._is_valid_metadata(): - raise Exception("invalid metadata") - else: - if self._is_local_metadata: - self._config = self._metadata["config"] - s = self._config.get("services") - sh = ServicesHandler(s, resource=self.resource, hooks=hooks) - sh.monitor_services() diff --git a/heat/jeos/F16-i386-cfntools-jeos.tdl b/heat/jeos/F16-i386-cfntools-jeos.tdl deleted file mode 100644 index 0d1102183..000000000 --- a/heat/jeos/F16-i386-cfntools-jeos.tdl +++ /dev/null @@ -1,28 +0,0 @@ - diff --git a/heat/jeos/F16-i386-gold-jeos.tdl b/heat/jeos/F16-i386-gold-jeos.tdl deleted file mode 100644 index d1a232310..000000000 --- a/heat/jeos/F16-i386-gold-jeos.tdl +++ /dev/null @@ -1,60 +0,0 @@ - diff --git a/heat/jeos/F16-x86_64-cfntools-jeos.tdl b/heat/jeos/F16-x86_64-cfntools-jeos.tdl deleted file mode 100644 index dc135adfb..000000000 --- a/heat/jeos/F16-x86_64-cfntools-jeos.tdl +++ /dev/null @@ -1,28 +0,0 @@ - diff --git a/heat/jeos/F16-x86_64-gold-jeos.tdl b/heat/jeos/F16-x86_64-gold-jeos.tdl deleted file mode 100644 index f18f045d6..000000000 --- a/heat/jeos/F16-x86_64-gold-jeos.tdl +++ /dev/null @@ -1,60 +0,0 @@ - diff --git a/heat/jeos/F17-i386-cfntools-jeos.tdl b/heat/jeos/F17-i386-cfntools-jeos.tdl deleted file mode 100644 index aff94e9f1..000000000 --- a/heat/jeos/F17-i386-cfntools-jeos.tdl +++ /dev/null @@ -1,28 +0,0 @@ - diff --git a/heat/jeos/F17-i386-gold-jeos.tdl b/heat/jeos/F17-i386-gold-jeos.tdl deleted file mode 100644 index 31ba4202e..000000000 --- a/heat/jeos/F17-i386-gold-jeos.tdl +++ /dev/null @@ -1,60 +0,0 @@ - diff --git a/heat/jeos/F17-x86_64-cfntools-jeos.tdl b/heat/jeos/F17-x86_64-cfntools-jeos.tdl deleted file mode 100644 index 583bf9de4..000000000 --- a/heat/jeos/F17-x86_64-cfntools-jeos.tdl +++ /dev/null @@ -1,28 +0,0 @@ - diff --git a/heat/jeos/F17-x86_64-gold-jeos.tdl b/heat/jeos/F17-x86_64-gold-jeos.tdl deleted file mode 100644 index c21b2db74..000000000 --- a/heat/jeos/F17-x86_64-gold-jeos.tdl +++ /dev/null @@ -1,60 +0,0 @@ - diff --git a/heat/jeos/U10-amd64-cfntools-jeos.tdl b/heat/jeos/U10-amd64-cfntools-jeos.tdl deleted file mode 100644 index 36516ba4f..000000000 --- a/heat/jeos/U10-amd64-cfntools-jeos.tdl +++ /dev/null @@ -1,25 +0,0 @@ - diff --git a/heat/utils.py b/heat/utils.py index 750b49a05..482862e03 100644 --- a/heat/utils.py +++ b/heat/utils.py @@ -59,220 +59,6 @@ def catch_error(action): return wrap -@catch_error('jeos-create') -def jeos_create(options, arguments, jeos_path, cfntools_path): - ''' - Create a new JEOS (Just Enough Operating System) image. - - Usage: heat jeos-create - - Distribution: Distribution such as 'F16', 'F17', 'U10', 'D6'. - Architecture: Architecture such as 'i386' 'i686' or 'x86_64'. - Image Type: Image type such as 'gold' or 'cfntools'. - 'gold' is a basic gold JEOS. - 'cfntools' contains the cfntools helper scripts. - - The command must be run as root in order for libvirt to have permissions - to create virtual machines and read the raw DVDs. - ''' - - # if not running as root, return EPERM to command line - if os.geteuid() != 0: - logging.error("jeos-create must be run as root") - sys.exit(1) - if len(arguments) < 3: - print '\n Please provide the distro, arch, and instance type.' - print ' Usage:' - print ' heat jeos-create ' - print ' instance type can be:' - print ' gold builds a base image where userdata is used to' \ - ' initialize the instance' - print ' cfntools builds a base image where AWS CloudFormation' \ - ' tools are present' - sys.exit(1) - - distro = arguments.pop(0) - arch = arguments.pop(0) - instance_type = arguments.pop(0) - images_dir = '/var/lib/libvirt/images' - - arches = ('x86_64', 'i386', 'amd64') - arches_str = " | ".join(arches) - instance_types = ('gold', 'cfntools') - instances_str = " | ".join(instance_types) - - if not arch in arches: - logging.error('arch %s not supported' % arch) - logging.error('try: heat jeos-create %s [ %s ]' % (distro, arches_str)) - sys.exit(1) - - if not instance_type in instance_types: - logging.error('A JEOS instance type of %s not supported' % - instance_type) - logging.error('try: heat jeos-create %s %s [ %s ]' % - (distro, arch, instances_str)) - sys.exit(1) - - src_arch = 'i386' - fedora_match = re.match('F(1[6-7])', distro) - if fedora_match: - if arch == 'x86_64': - src_arch = 'x86_64' - version = fedora_match.group(1) - iso = '%s/Fedora-%s-%s-DVD.iso' % (images_dir, version, arch) - elif distro == 'U10': - if arch == 'amd64': - src_arch = 'x86_64' - iso = '%s/ubuntu-10.04.3-server-%s.iso' % (images_dir, arch) - else: - logging.error('distro %s not supported' % distro) - logging.error('try: F16, F17 or U10') - sys.exit(1) - - if not os.access(iso, os.R_OK): - logging.error('*** %s does not exist.' % (iso)) - sys.exit(1) - - tdl_file = '%s-%s-%s-jeos.tdl' % (distro, arch, instance_type) - tdl_path = os.path.join(jeos_path, tdl_file) - if options.debug: - print "Using tdl: %s" % tdl_path - - # Load the cfntools into the cfntool image by encoding them in base64 - # and injecting them into the TDL at the appropriate place - if instance_type == 'cfntools': - tdl_xml = etree.parse(tdl_path) - cfn_tools = ['cfn-init', 'cfn-hup', 'cfn-signal', - 'cfn-get-metadata', 'cfn_helper.py', 'cfn-push-stats'] - for cfnname in cfn_tools: - f = open('%s/%s' % (cfntools_path, cfnname), 'r') - cfscript_e64 = base64.b64encode(f.read()) - f.close() - cfnpath = "/template/files/file[@name='/opt/aws/bin/%s']" % cfnname - tdl_xml.xpath(cfnpath)[0].text = cfscript_e64 - - # TODO(sdake) INSECURE - tdl_xml.write('/tmp/tdl', xml_declaration=True) - tdl_path = '/tmp/tdl' - - dsk_filename = '%s/%s-%s-%s-jeos.dsk' % (images_dir, distro, - src_arch, instance_type) - qcow2_filename = '%s/%s-%s-%s-jeos.qcow2' % (images_dir, distro, - arch, instance_type) - image_name = '%s-%s-%s' % (distro, arch, instance_type) - - if not os.access(tdl_path, os.R_OK): - logging.error('The tdl for that disto/arch is not available') - sys.exit(1) - - creds = dict(username=options.username, - password=options.password, - tenant=options.tenant, - auth_url=options.auth_url, - strategy=options.auth_strategy) - - client = glance_client.Client(host="0.0.0.0", port=9292, - use_ssl=False, auth_tok=None, creds=creds) - - parameters = { - "filters": {}, - "limit": 10, - } - images = client.get_images(**parameters) - - image_registered = False - for image in images: - if image['name'] == distro + '-' + arch + '-' + instance_type: - image_registered = True - - runoz = options.yes and 'y' or None - if os.access(qcow2_filename, os.R_OK): - while runoz not in ('y', 'n'): - runoz = raw_input('An existing JEOS was found on disk.' - ' Do you want to build a fresh JEOS?' - ' (y/n) ').lower() - if runoz == 'y': - os.remove(qcow2_filename) - os.remove(dsk_filename) - if image_registered: - client.delete_image(image['id']) - elif runoz == 'n': - answer = None - while answer not in ('y', 'n'): - answer = raw_input('Do you want to register your existing' - ' JEOS file with glance? (y/n) ').lower() - if answer == 'n': - logging.info('No action taken') - sys.exit(0) - elif answer == 'y' and image_registered: - answer = None - while answer not in ('y', 'n'): - answer = raw_input('Do you want to delete the ' - 'existing JEOS in glance?' - ' (y/n) ').lower() - if answer == 'n': - logging.info('No action taken') - sys.exit(0) - elif answer == 'y': - client.delete_image(image['id']) - - if runoz is None or runoz == 'y': - logging.info('Creating JEOS image (%s) - ' - 'this takes approximately 10 minutes.' % image_name) - extra_opts = ' ' - if options.debug: - extra_opts = ' -d 3 ' - - ozcmd = "oz-install %s -t 50000 -u %s -x /dev/null" % (extra_opts, - tdl_path) - logging.debug("Running : %s" % ozcmd) - res = os.system(ozcmd) - if res == 256: - sys.exit(1) - if not os.access(dsk_filename, os.R_OK): - logging.error('oz-install did not create the image,' - ' check your oz installation.') - sys.exit(1) - - logging.info('Converting raw disk image to a qcow2 image.') - os.system("qemu-img convert -c -O qcow2 %s %s" % (dsk_filename, - qcow2_filename)) - - logging.info('Registering JEOS image (%s) ' - 'with OpenStack Glance.' % image_name) - - image_meta = {'name': image_name, - 'is_public': True, - 'disk_format': 'qcow2', - 'min_disk': 0, - 'min_ram': 0, - 'owner': options.username, - 'container_format': 'bare'} - - try: - with open(qcow2_filename) as ifile: - image_meta = client.add_image(image_meta, ifile) - image_id = image_meta['id'] - logging.debug(" Added new image with ID: %s" % image_id) - logging.debug(" Returned the following metadata for the new image:") - for k, v in sorted(image_meta.items()): - logging.debug(" %(k)30s => %(v)s" % locals()) - except exception.ClientConnectionError, e: - logging.error((" Failed to connect to the Glance API server." + - " Is the server running?" % locals())) - pieces = unicode(e).split('\n') - for piece in pieces: - logging.error(piece) - sys.exit(1) - except Exception, e: - logging.error(" Failed to add image. Got error:") - pieces = unicode(e).split('\n') - for piece in pieces: - logging.error(piece) - logging.warning(" Note: Your image metadata may still be in the " + - "registry, but the image's status will likely be 'killed'.") - - class LazyPluggable(object): """A pluggable backend loaded lazily based on some value."""