tripleo-ansible/scripts/populate_image_vars
Julia Kreger 2c7ec6fd02 Fix populate_image_vars for bootstrap node
The bootstrap node requires special logic but the same disk image
variable as normal controller nodes.  Changed logic to create symlink if
the controller variable file is present and a symlink is not
already present.

Change-Id: I3388cf5070e7f0a747feadc860d444eda42c78fe
2015-01-13 16:25:00 -05:00

158 lines
6.4 KiB
Python
Executable File

#!/usr/bin/env python
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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 argparse
import json
import os
import subprocess
import sys
import tempfile
import yaml
# # Example
# +--------------------------------------+---------------------------+-------------+------------------+------------+--------+
# | ID | Name | Disk Format | Container Format | Size | Status |
# +--------------------------------------+---------------------------+-------------+------------------+------------+--------+
# | 2b98a88d-d79e-4a2f-87c1-c8c76c690092 | bm-deploy-kernel | aki | aki | 3170560 | active |
# | 3d2b01b0-bf7a-4000-8d56-cfd1131c32bc | bm-deploy-ramdisk | ari | ari | 22778117 | active |
# | 3dc11dba-f639-42f1-8d54-d8f08268bd25 | overcloud-compute | qcow2 | bare | 614817792 | active |
# | 3276eef3-d128-4ab6-899f-af9201145505 | overcloud-compute-initrd | ari | ari | 9963568 | active |
# | 7cfb3aa9-3f6c-4f20-80a4-9d4694641dec | overcloud-compute-vmlinuz | aki | aki | 3170560 | active |
# | cef3732c-1c6a-4182-8a6e-3960a1acf99e | overcloud-control | qcow2 | bare | 1062666240 | active |
# | a8126d25-305c-47d9-a27e-7fbc3d92bb7d | overcloud-control-initrd | ari | ari | 10726940 | active |
# | c1602866-0664-49f5-b3f8-97dc936dc198 | overcloud-control-vmlinuz | aki | aki | 3170560 | active |
# | 25a6637e-71b3-4bff-95ca-a1a08582c801 | overcloud-swift | qcow2 | bare | 387252224 | active |
# | 1932f035-725f-40b1-827d-20da22686df1 | overcloud-swift-initrd | ari | ari | 9963824 | active |
# | 40d536b3-a0f8-4d33-8077-521db986de5f | overcloud-swift-vmlinuz | aki | aki | 3170560 | active |
# +--------------------------------------+---------------------------+-------------+------------------+------------+--------+
def image_list():
# Using subprocess to avoid glanceclient dep for now
glance_list = subprocess.Popen(
['glance', 'image-list'],
stdout=subprocess.PIPE
)
for line in glance_list.stdout:
if line[0] != '|':
continue
if line[2:5] == 'ID ':
continue
(image_id, name, image_type) = [
x.strip() for x in line.split('|', 4)[1:4]
]
if image_type != 'qcow2':
continue
yield (image_id, name, image_type)
glance_list.wait()
def name_to_class(name):
(stack, bits) = name.split('-', 1)
bits = bits.split('-')
new_bits = []
buildnum = None
for bit in bits:
try:
buildnum = int(bit)
except ValueError:
new_bits.append(bit)
if new_bits == ['compute']:
return ('nova-compute', buildnum)
if new_bits == ['control']:
return ('controller', buildnum)
if new_bits == ['swift']:
return ('swift-storage', buildnum)
return ('-'.join(new_bits), buildnum)
def find_images(target_buildnum=None):
mapping = {}
for (image_id, name, image_type) in image_list():
(image_class, buildnum) = name_to_class(name)
if image_class in mapping:
if target_buildnum is None:
if mapping[image_class]['buildnum'] >= buildnum:
continue
else:
if buildnum != target_buildnum:
continue
mapping[image_class] = {'buildnum': buildnum, 'id': image_id}
return mapping
def keys_to_variables(k, v):
variable_name = '%s_rebuild_image_id' % k.replace('-', '_').lower()
value = v['id']
return {variable_name: value}
def parse_args(argv):
parser = argparse.ArgumentParser()
parser.add_argument('buildnum', type=int, nargs='?',
help='Build number, if left out will take highest. '
'If the build is not found, an existing '
'image that matches a class will be used.')
parser.add_argument('--output-dir', default='plugins/inventory/group_vars')
return parser.parse_args(argv[1:])
def main(argv):
args = parse_args(argv)
images = find_images(target_buildnum=args.buildnum)
if not images:
print('ERROR: no images found, aborting')
return 2
print(json.dumps(images, indent=4))
for k, v in iter(images.items()):
if k == 'all':
continue
the_vars = keys_to_variables(k, v)
output_path = os.path.join(args.output_dir, k)
if os.path.exists(output_path):
print('... Editting %s' % output_path)
with open(output_path, 'r') as input_file:
existing = yaml.load(input_file.read())
else:
print('... Creating %s' % output_path)
existing = {}
existing.update(the_vars)
prefix = '.%s' % k
with tempfile.NamedTemporaryFile(
prefix=prefix,
dir=args.output_dir,
delete=False
) as out:
out.write(yaml.dump(existing, default_flow_style=False))
os.rename(out.name, output_path)
# The conditionals and resulting symlink below is to support the
# execution of the playbook steps with-in the bootstrap node context
# when a user utilizes this script and does not define the controller
# disk image id as a global variable on the playbook command line.
if os.path.isfile(os.path.join(
args.output_dir,
'controller'
)) and not os.path.islink(os.path.join(
args.output_dir,
'controller-bootstrap')):
os.symlink(
'controller',
os.path.join(args.output_dir, 'controller-bootstrap')
)
if __name__ == '__main__':
sys.exit(main(sys.argv))