blob: 15346d940385f200b0e5de6ac66009ccdd4aa460 [file] [log] [blame]
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 OpenStack, LLC
# All Rights Reserved.
#
# 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.
"""
Simple script that analyzes a devstack environment and constructs
a Tempest configuration file for the devstack environment.
"""
import optparse
import os
import subprocess
import sys
SUCCESS = 0
FAILURE = 1
def execute(cmd, raise_error=True):
"""
Executes a command in a subprocess. Returns a tuple
of (exitcode, out, err), where out is the string output
from stdout and err is the string output from stderr when
executing the command.
:param cmd: Command string to execute
:param raise_error: If returncode is not 0 (success), then
raise a RuntimeError? Default: True)
"""
process = subprocess.Popen(cmd,
shell=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
result = process.communicate()
(out, err) = result
exitcode = process.returncode
if process.returncode != 0 and raise_error:
msg = "Command %(cmd)s did not succeed. Returned an exit "\
"code of %(exitcode)d."\
"\n\nSTDOUT: %(out)s"\
"\n\nSTDERR: %(err)s" % locals()
raise RuntimeError(msg)
return exitcode, out, err
def add_options(parser):
"""
Adds CLI options to a supplied option parser
:param parser: `optparse.OptionParser`
"""
parser.add_option('-o', '--outfile', metavar="PATH",
help=("File to save generated config to. Default: "
"prints config to stdout."))
parser.add_option('-v', '--verbose', default=False, action="store_true",
help="Print more verbose output")
parser.add_option('-D', '--devstack-dir', metavar="PATH",
default=os.getcwd(),
help="Directory to find devstack. Default: $PWD")
def get_devstack_localrc(options):
"""
Finds the localrc file in the devstack directory and returns a dict
representing the key/value pairs in the localrc file.
"""
localrc_path = os.path.join(os.path.abspath(options.devstack_dir), 'localrc')
if not os.path.exists(localrc_path):
raise RuntimeError("Failed to find localrc file in devstack dir %s" %
options.devstack_dir)
if options.verbose:
print "Reading localrc settings from %s" % localrc_path
try:
settings = dict([line.split('=') for line in
open(localrc_path, 'r').readlines()
if not line.startswith('#')])
return settings
except (TypeError, ValueError) as e:
raise RuntimeError("Failed to read settings from localrc file %s. "
"Got error: %s" % (localrc_path, e))
def main():
oparser = optparse.OptionParser()
add_options(oparser)
options, args = oparser.parse_args()
localrc = get_devstack_localrc(options)
conf_settings = {
'service_host': localrc.get('HOST_IP', '127.0.0.1'),
'service_port': 5000, # Make this configurable when devstack does
'identity_api_version': 'v2.0', # Ditto
'user': localrc.get('USERNAME', 'admin'),
'password': localrc.get('ADMIN_PASSWORD', 'password')
}
# We need to determine the UUID of the base image, so we
# query the Glance endpoint for a list of images...
cmd = "glance index -A %s" % localrc['SERVICE_TOKEN']
retcode, out, err = execute(cmd)
if retcode != 0:
raise RuntimeError("Unable to get list of images from Glance. "
"Got error: %s" % err)
image_lines = out.split('\n')[2:]
for line in image_lines:
if 'ami' in line:
conf_settings['base_image_uuid'] = line.split()[0]
break
if 'base_image_uuid' not in conf_settings:
raise RuntimeError("Unable to find any AMI images in glance index")
if options.verbose:
print "Found base image with UUID %s" % conf_settings['base_image_uuid']
tempest_conf = """[nova]
host=%(service_host)s
port=%(service_port)s
apiVer=%(identity_api_version)s
path=tokens
user=%(user)s
api_key=%(password)s
tenant_name=%(user)s
ssh_timeout=300
build_interval=10
build_timeout=600
[image]
host = %(service_host)s
port = 9292
username = %(user)s
password = %(password)s
tenant = %(user)s
auth_url = http://127.0.0.1:5000/v2.0/tokens/
strategy = keystone
service_token = servicetoken
[environment]
image_ref=%(base_image_uuid)s
image_ref_alt=4
flavor_ref=1
flavor_ref_alt=2
create_image_enabled=true
resize_available=true
authentication=keystone_v2""" % conf_settings
if options.outfile:
outfile_path = os.path.abspath(options.outfile)
if os.path.exists(outfile_path):
confirm = raw_input("Output file already exists. Overwrite? [y/N]")
if confirm != 'Y':
print "Exiting"
return SUCCESS
with open(outfile_path, 'wb') as outfile:
outfile.write(tempest_conf)
if options.verbose:
print "Wrote tempest config to %s" % outfile_path
else:
print tempest_conf
if __name__ == '__main__':
try:
sys.exit(main())
except RuntimeError, e:
sys.exit("ERROR: %s" % e)