
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
158 lines
6.4 KiB
Python
Executable File
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))
|