diff --git a/PKG-INFO b/PKG-INFO index 7a86a86a..9555acf8 100644 --- a/PKG-INFO +++ b/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: oci-utils -Version: 0.12.7 +Version: 0.14.1 Summary: Oracle Cloud Infrastructure utilities Home-page: http://github.com/oracle/oci-utils/ Author: Laszlo Peter diff --git a/buildrpm/oci-utils.spec b/buildrpm/oci-utils.spec index f25e4f4e..0362496d 100644 --- a/buildrpm/oci-utils.spec +++ b/buildrpm/oci-utils.spec @@ -1,6 +1,6 @@ Name: oci-utils Version: 0.14.0 -Release: 0%{?dist} +Release: 1%{?dist} Url: http://cloud.oracle.com/iaas Summary: Oracle Cloud Infrastructure utilities License: UPL @@ -206,6 +206,9 @@ rm -rf %{buildroot} /opt/oci-utils/tests/__init__* %changelog +* Thu Aug 11 2022 Guido Tijskens -- 0.14.0-1 +- LINUX-12027: oci-image-migrate on ol7 unable to mount ol9 xfs filesystem + * Mon Jul 25 2022 Guido Tijskens -- 0.14.0-0 - support for ipv6: - LINUX-9259 add ipv6 support in oci-metadata diff --git a/lib/oci_utils/impl/migrate/oci_image_migrate_import_main.py b/lib/oci_utils/impl/migrate/oci_image_migrate_import_main.py index 1dcc03af..2efa96e7 100644 --- a/lib/oci_utils/impl/migrate/oci_image_migrate_import_main.py +++ b/lib/oci_utils/impl/migrate/oci_image_migrate_import_main.py @@ -51,6 +51,7 @@ def parse_args(): The command line namespace. """ parser = argparse.ArgumentParser( + prog='oci-image-migrate-import', description='Utility to import a (verified and modified) on-premise ' 'legacy image which was uploaded to object storage in ' 'the custom images folder of the Oracle Cloud ' diff --git a/lib/oci_utils/impl/migrate/oci_image_migrate_main.py b/lib/oci_utils/impl/migrate/oci_image_migrate_main.py index f574615a..110b0899 100644 --- a/lib/oci_utils/impl/migrate/oci_image_migrate_main.py +++ b/lib/oci_utils/impl/migrate/oci_image_migrate_main.py @@ -63,6 +63,7 @@ def parse_args(): The command line namespace. """ parser = argparse.ArgumentParser( + prog='oci-image-migrate', description='Utility to support preparation of on-premise legacy ' 'images for importing in the Oracle Cloud Infrastructure.') # @@ -260,7 +261,7 @@ def verify_support(): if ostype not in ['ol', 'redhat', 'centos']: _logger.info('OS type %s is not supported.', ostype) return False - if majorrelease not in ['7', '8']: + if majorrelease not in ['7', '8', '9']: _logger.info('OS %s %s is not supported', ostype, majorrelease) return False return True @@ -487,8 +488,7 @@ def main(): prereq_msg += msg # if imgres: - prereq_msg += '\n\n %s data collection and processing succeeded.' \ - % image_path + prereq_msg += '\n\n %s data collection and processing succeeded.' % image_path else: prereq_passed = False # @@ -501,12 +501,10 @@ def main(): result_msg(msg='\n Boot type is UEFI, use launch_mode NATIVE (or EMULATED) at import.', result=True) else: - raise OciMigrateException('Something wrong checking ' - 'the boot type') + raise OciMigrateException('Checking the boot type failed.') else: - prereq_msg += '\n\n %s processing failed, check the logfile ' \ - 'and/or set environment variable _OCI_UTILS_DEBUG.' \ - % image_path + prereq_msg += '\n\n %s processing failed, check the logfile and/or set environment variable ' \ + '_OCI_UTILS_DEBUG.' % image_path raise OciMigrateException(prereq_msg) except Exception as e: exit_with_msg('*** ERROR *** %s' % str(e)) diff --git a/lib/oci_utils/impl/migrate/oci_image_migrate_upload_main.py b/lib/oci_utils/impl/migrate/oci_image_migrate_upload_main.py index 5bc39ed0..581bc0be 100644 --- a/lib/oci_utils/impl/migrate/oci_image_migrate_upload_main.py +++ b/lib/oci_utils/impl/migrate/oci_image_migrate_upload_main.py @@ -45,6 +45,7 @@ def parse_args(): The command line namespace. """ parser = argparse.ArgumentParser( + prog='oci-image-migrate-upload', description='Utility to upload on-premise legacy images to object ' 'storage of the Oracle Cloud Infrastructure.') # diff --git a/lib/oci_utils/migrate/imgdevice.py b/lib/oci_utils/migrate/imgdevice.py index 56054ff3..2d2c2028 100644 --- a/lib/oci_utils/migrate/imgdevice.py +++ b/lib/oci_utils/migrate/imgdevice.py @@ -1,6 +1,6 @@ # oci-utils # -# Copyright (c) 2019, 2020 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved. # Licensed under the Universal Permissive License v 1.0 as shown # at http://oss.oracle.com/licenses/upl. @@ -30,6 +30,7 @@ from oci_utils.migrate import terminal_dimension from oci_utils.migrate.exception import OciMigrateException from oci_utils.migrate.migrate_tools import get_config_data +from pprint import pformat _logger = logging.getLogger('oci-utils.imgdevice') @@ -433,7 +434,8 @@ def handle_image(self): self.update_image() return True except Exception as e: - _logger.critical(' Image %s handling failed: %s', self.image_info['img_name'], str(e), exc_info=True) + _logger.debug(' Image %s handling failed: %s', self.image_info['img_name'], str(e), exc_info=True) + _logger.critical('\n Image %s handling failed: %s', self.image_info['img_name'], str(e)) return False finally: _, nbcols = terminal_dimension() @@ -958,8 +960,7 @@ def find_uuid_partition(uuid_part): """ part_p = 'na' mount_p = 'na' - for partition, partdata in list( - self.image_info['partitions'].items()): + for partition, partdata in list(self.image_info['partitions'].items()): if self.skip_partition(partdata): _logger.debug('Skipping %s', partition) elif 'ID_FS_UUID' in list(partdata.keys()): @@ -1072,6 +1073,7 @@ def find_mapper_partition(mapper_part): def get_grub_data(self, loopdir): """ Collect data related to boot and grub. + Parameters: ---------- loopdir: str @@ -1107,9 +1109,39 @@ def find_grub_config_file(): _logger.debug('No grub config file in %s', grubroot) return grub_path + def find_boot_loader_entries_dir(): + """ + Verify if the directory /boot/loader/entries exists and contains files. + + Returns + ------- + str: the path of the boot loader entries. + """ + _logger.debug('__ Looking for /boot/loader/entries') + boot_loader_entries = os.path.join(loopdir, 'boot/loader/entries') + if os.path.exists(boot_loader_entries): + if os.listdir(boot_loader_entries): + return boot_loader_entries + return None + + def find_grubenv_dir(): + """ + Verify if the grubenv file exists. + + Returns + ------- + str: the path of the grubenv file. + """ + _logger.debug('__ Looking for /boot/grub2/grubenv') + grubenvpath = os.path.join(loopdir, 'boot/grub2/grubenv') + if os.path.exists(grubenvpath): + return grubenvpath + return None + def find_efi_boot_config(): """ Find out if the image is using BIOS or UEFI boot. + Returns ------- str: [BIOS|UEFI] @@ -1146,6 +1178,10 @@ def find_efi_boot_config(): raise OciMigrateException('No grub config file found in %s' % self._fn) result_msg(msg='Grub config file: %s' % grub_cfg_path, result=False) # + # verify if a boot loader entries is present + boot_loader_entries_path = find_boot_loader_entries_dir() + grub_env_path = find_grubenv_dir() + # # investigate boot type self.image_info['boot_type'] = find_efi_boot_config() result_msg(msg='Image boot type: %s' % self.image_info['boot_type']) @@ -1153,50 +1189,102 @@ def find_efi_boot_config(): # get grub config contents grubdata = list() grub2 = False + grubby = True if boot_loader_entries_path else False grubentry = dict() grubefi = dict() kernelversion = '0' kernellist = list() _logger.debug('Initialised grub structure') - try: - # - # check for grub2 data - mentry = False - with open(grub_cfg_path, 'r') as f: - for ffsline in f: - fsline = ffsline.strip() - fsline_split = re.split('[ "]', fsline) - if bool(fsline.split()): - _logger.debug('%s', fsline) - if fsline_split[0] == 'menuentry': - mentry = True - grub2 = True - if grubentry: - grubdata.append(grubentry) - grubentry = {'menuentry': [fsline]} - _logger.debug('grub line: %s', fsline) - elif fsline_split[0] == 'search': - if mentry: - grubentry['menuentry'].append(fsline) - _logger.debug('Grub line: %s', grubentry['menuentry']) + + if not grubby: + try: + # + # check for grub2 data + mentry = False + with open(grub_cfg_path, 'r') as f: + for ffsline in f: + fsline = ffsline.strip() + fsline_split = re.split('[ "]', fsline) + if bool(fsline.split()): + _logger.debug('%s', fsline) + if fsline_split[0] == 'menuentry': + mentry = True + grub2 = True + if grubentry: + grubdata.append(grubentry) + grubentry = {'menuentry': [fsline]} + _logger.debug('grub line: %s', fsline) + elif fsline_split[0] == 'search': + if mentry: + grubentry['menuentry'].append(fsline) + _logger.debug('Grub line: %s', grubentry['menuentry']) + else: + _logger.debug('Not a menuentry, skipping %s', fsline) + elif fsline_split[0] == 'set': + if 'default_kernelopts' in fsline_split[1]: + grubefi = {'grubefi': [fsline]} + _logger.debug('efi line: %s', fsline) else: - _logger.debug('Not a menuentry, skipping %s', fsline) - elif fsline_split[0] == 'set': - if 'default_kernelopts' in fsline_split[1]: - grubefi = {'grubefi': [fsline]} - _logger.debug('efi line: %s', fsline) - else: - _logger.debug('Skipping %s', fsline) - if bool(grubentry): - grubdata.append(grubentry) - if bool(grubefi): - grubdata.append(grubefi) - except Exception as e: - _logger.error(' Errors during reading %s: %s', grub_cfg_path, str(e)) - raise OciMigrateException('Errors during reading %s:' % grub_cfg_path) from e - if grub2: + _logger.debug('Skipping %s', fsline) + if bool(grubentry): + grubdata.append(grubentry) + if bool(grubefi): + grubdata.append(grubefi) + except Exception as e: + _logger.error(' Errors during reading %s: %s', grub_cfg_path, str(e)) + raise OciMigrateException('Errors during reading %s:' % grub_cfg_path) from e + + if grubby: + _logger.debug('Found /boot/loader/entries') + result_msg(msg='Found /boot/loader/entries directory.', result=False) + # + # find all kernels defined in loader entries directory. + kernellist = system_tools.get_grubby_kernels(boot_loader_entries_path) + _logger.debug('Kernels defined in boot laoder entries: %s', kernellist) + if grub_env_path: + kernelversion = system_tools.get_grubby_default_kernel(grub_env_path) + _logger.debug('Default kernel: %s', kernelversion) + kernelopts = '' + try: + # find kernel options + with open(grub_cfg_path, 'r') as f: + for ffsline in f: + fsline = ffsline.strip() + fsline_split = re.split('[ "]', fsline) + if bool(fsline.split()): + if fsline_split[0] == 'set': + if 'kernelopts' in fsline_split[1]: + kernelopts = ' '.join(fsline_split[1:]) + break + for _, _, files in os.walk(boot_loader_entries_path): + for name in files: + with open(os.path.join(boot_loader_entries_path, name), 'r') as f: + for ffsline in f: + fsline = ffsline.strip() + if len(fsline) > 0: + _logger.debug('%s', fsline) + if fsline.split()[0] == 'title': + if grubentry: + grubdata.append(grubentry) + grubentry = {'title': [fsline]} + _logger.debug('grub line: %s', fsline) + elif fsline.split()[0] == 'linux': + grubentry['title'].append(fsline) + _logger.debug('grub line: %s', grubentry['title']) + else: + _logger.debug('skipping %s', fsline) + if grubentry: + if kernelopts: + grubentry['title'].append(kernelopts) + grubdata.append(grubentry) + + except Exception as e: + _logger.error(' Errors during reading %s: %s', boot_loader_entries_path, str(e)) + raise OciMigrateException('Errors during reading %s:' % boot_loader_entries_path) from e + + elif grub2: _logger.debug('Found grub2 configuration file.') - result_msg(msg='Found grub2 configuration file', result=False) + result_msg(msg='Found grub2 configuration file.', result=False) # # find all kernels defined in grub(1) config file. kernellist = system_tools.get_grub2_kernels(grub_cfg_path) @@ -1237,6 +1325,9 @@ def find_efi_boot_config(): _logger.error(' Errors during reading %s: %s', grub_cfg_path, str(e)) raise OciMigrateException('Errors during reading %s:' % grub_cfg_path) from e + _logger.debug('grubdata:\n %s', pformat(grubdata, indent=4)) + _logger.debug('kernellist\n %s', pformat(kernellist, indent=4)) + _logger.debug('kernelversion\n %s', kernelversion) return grubdata, kernelversion, kernellist def get_os_release(self): @@ -1459,23 +1550,25 @@ def generic_prereq_check(self): msg='grub2 line ->%s<- specifies boot partition via UUID.' % le) elif l_split[0] == 'kernel': grub_l += 1 - if len([a for a in l_split - if any(b in a for b in ['root=UUID=', 'root=/dev/mapper/'])]) == 0: - _logger.debug('grub line ->%s<- does not specify boot partition via ' - 'UUID nor LVM2.', le) + if len([a for a in l_split if any(b in a for b in ['root=UUID=', 'root=/dev/mapper/'])]) == 0: + _logger.debug('grub line ->%s<- does not specify boot partition via UUID nor LVM2.', le) grub_fail += 1 else: - result_msg(msg='grub line ->%s<- specifies boot partition via UUID or LVM2.' - % le, result=True) + result_msg(msg='grub line ->%s<- specifies boot partition via UUID or LVM2.' % le,) elif 'default_kernelopts' in l_split[1]: grub_l += 1 - if len([a for a in l_split - if any(b in a for b in ['root=UUID=', 'root=/dev/mapper/'])]) == 0: + if len([a for a in l_split if any(b in a for b in ['root=UUID=', 'root=/dev/mapper/'])]) == 0: + _logger.debug('grub line ->%s<- does not specify boot partition via UUID nor LVM2.', le) + grub_fail += 1 + else: + result_msg(msg='grub line ->%s<- specifies boot partition via UUID or LVM2.' % le) + elif l_split[0] == 'kernelopts=': + grub_l += 1 + if len([a for a in l_split if any(b in a for b in ['root=UUID=', 'root=/dev/mapper/'])]) == 0: _logger.debug('grub line ->%s<- does not specify boot partition via UUID nor LVM2.', le) grub_fail += 1 else: - result_msg(msg='grub line ->%s<- specifies boot partition via UUID or LVM2.' - % le, result=True) + result_msg(msg='grub line ->%s<- specifies boot partition via UUID or LVM2.' % le) else: _logger.debug('skipping %s', l_split) if grub_l == 0: @@ -1486,6 +1579,7 @@ def generic_prereq_check(self): failmsg += '\n - grub config file does not guarantee booting using UUID or LVM2.' else: _logger.debug('Grub config file ok.') + result_msg(msg='Grub config file ok.', result=True) else: passed_requirement = False failmsg += '\n - Grub config file not found.' diff --git a/lib/oci_utils/migrate/migrate_tools.py b/lib/oci_utils/migrate/migrate_tools.py index dfa1d99d..84b37157 100644 --- a/lib/oci_utils/migrate/migrate_tools.py +++ b/lib/oci_utils/migrate/migrate_tools.py @@ -568,6 +568,8 @@ def mount_partition(devname, mountpoint=None): # # mount failed, need to remove mountpoint. _logger.critical(' Failed to mount %s, missing driver, filesystem corruption...: %s', devname, str(e)) + _logger.critical(' Check file system driver and kernel version compatibility. ' + 'Check Known Issues in the man page and manual.') if mountpoint is None: if system_tools.exec_rmdir(mntpoint): _logger.debug('%s removed', mntpoint) diff --git a/lib/oci_utils/migrate/system_tools.py b/lib/oci_utils/migrate/system_tools.py index f3c7f774..f5f79485 100644 --- a/lib/oci_utils/migrate/system_tools.py +++ b/lib/oci_utils/migrate/system_tools.py @@ -1,6 +1,6 @@ # oci-utils # -# Copyright (c) 2019, 2021 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved. # Licensed under the Universal Permissive License v 1.0 as shown # at http://oss.oracle.com/licenses/upl. @@ -777,6 +777,53 @@ def get_free_nbd(): raise OciMigrateException('\nFailed to screen nbd devices:') from e +def get_grubby_kernels(boot_loader_entries): + """ + Get the version of the kernels defined in the boot loader entries directory. + + Parameters + ---------- + boot_loader_entries: str + The boot loader entries directory. + + Returns + ------- + list: list of kernels. + """ + _logger.debug('__ Get the kernel versions from %s', boot_loader_entries) + kernels_list = list() + for _, _, files in os.walk(boot_loader_entries): + for name in files: + with open(os.path.join(boot_loader_entries, name)) as bootloaderentry: + bl_lines = bootloaderentry.readlines() + for bline in bl_lines: + if 'vmlinuz' in bline: + kernels_list.append(bline.split('-', 1)[1].strip()) + break + return kernels_list + +def get_grubby_default_kernel(grubenv_path): + """ + Get the kernel booted by default in a loader entries env. + + Parameters + ---------- + grubenv_path: str + The full path of the grubenv file. + + Returns + ------- + str: the kernel version. + """ + _logger.debug('__ Get the default kernel from %s', grubenv_path) + with open(grubenv_path, 'r') as gf: + gf_lines = gf.readlines() + for gf_line in gf_lines: + if 'saved_entry' in gf_line: + return(gf_line.split('-', 1)[1].strip()) + return None + + def get_grub2_kernels(grub_config_file): """ Get the versions of the kernels defined in the grub2 config file. diff --git a/man/man1/oci-image-migrate.1 b/man/man1/oci-image-migrate.1 index 5a2fc848..b4018db8 100644 --- a/man/man1/oci-image-migrate.1 +++ b/man/man1/oci-image-migrate.1 @@ -88,14 +88,16 @@ sets a default cloud user. .SH KNOWN ISSUES -.IP \[bu] 2 "The cloud-init service does not start at first boot in OCI." +IP "The cloud-init service does not start at first boot in OCI." 0.4i + The cloud-init service, although enabled does not start at first boot in OCI. This was noticed on ubuntu18 server and is probably related to the situation described in https://bugs.launchpad.net/bugs/1669675. + The workaround: .nr step 1 1 .RS -.IP \n[step] +.IP \n[step] 5 connect to the instance using vnc or serial console. .IP \n+[step] delete the contents of /var/lib/cloud. @@ -109,24 +111,55 @@ reboot the instance. or run the script .B /usr/local/bin/reinitialise_cloud_init.sh and reboot. .RE -.IP \[bu] "/dev/disk/by-id entries in /etc/fstab are not supported." +.IP "/dev/disk/by-id entries in /etc/fstab are not supported." Entries in /etc/fstab as /dev/disk/by-id are not supported yet. + The workaround: .RS .IP \[bu] update the /etc/fstab file so it refers to partitions via label, uuid, logical volume. .RE -.IP \[bu] "The instance fails to find boot disk." +.IP "The instance fails to find boot disk." The instance created from a migrated image does not boot, is unable to find boot disk because .B initramfs does not include the correct kernel module to recognise the bootable partition. The issue is being worked on. + The workaround: .RS .IP \[bu] Rebuild initramfs before migration so it includes all modules and -rebuilding again after first boot with the necessary ones. +rebuilding again after first boot with the necessary ones only. .RE +.IP "Images with an xfs version 5.15.0 or higher fail to convert from an instance with xfs 5.4.0 (or lower)" +.B oci-image-migrate +fails with + +.B Failed to mount /dev/nbd[npm], missing driver, filesystem corruption...: Mount /dev/nbd3p3 failed: 32 + +Boot and/or root partition of an image created with +.B xfs-progs 5.15.0 +or higher fails to mount on an instance with +.B xfs-progs 5.4.0 +installed. +.B xfs-progs 5.15.0 +comes with the +.B UEK7 kernel +which is the default on +.B Oracle Linux 9 +and optional on +.B Oracle Linux 8 +but not available on +.B Oracle Linux 7. + +The workaround: +.RS +.IP \[bu] +Install +.B oci-utils-migrate +on a system with +.B UEK7 +kernel installed and run the migrate from there. .SH SEE ALSO .BR oci-image-migrate-upload(1) diff --git a/tools/provisioning/gen_instance/bin/create_instance.py b/tools/provisioning/gen_instance/bin/create_instance.py index c0ad9501..5f6a3c1c 100755 --- a/tools/provisioning/gen_instance/bin/create_instance.py +++ b/tools/provisioning/gen_instance/bin/create_instance.py @@ -101,7 +101,8 @@ def parse_args(): ------- The command line namespace. """ - parser = argparse.ArgumentParser(description='Configure oci utils auto test.') + parser = argparse.ArgumentParser(prog='create_instance', + description='Configure oci utils auto test.') parser.add_argument('-n', '--name', action='store', dest='display_name', diff --git a/tools/provisioning/gen_instance/bin/modify_instance.py b/tools/provisioning/gen_instance/bin/modify_instance.py index 9b57551b..91c53f43 100755 --- a/tools/provisioning/gen_instance/bin/modify_instance.py +++ b/tools/provisioning/gen_instance/bin/modify_instance.py @@ -21,6 +21,7 @@ import tty from datetime import datetime from subprocess import call +from pprint import pformat import oci @@ -69,6 +70,15 @@ # "http_no_proxy": "169.254.169.254,.oraclecloud.com,.oraclecorp.com,.us.oracle.com" } +updatable_parameters = {'availability domain': 'availability_domain', + 'boot volume size': 'boot_volume_size_in_gbs', + 'memory': 'instance_flex_memory_in_gbs', + 'nb cpus': 'instance_flex_ocpus', + 'subnet': 'subnet_ocid', + 'shape': 'shape', + 'image': 'source_ocid'} + + _logger = logging.getLogger(__name__) @@ -92,6 +102,28 @@ def print_g(msg, term=True): _logger.debug(msg) +def print_g_left(head, headlen, msg, term=True): + """ + Write message with header of a defined size. + + Parameters + ---------- + head: str + The header + headlen: int + The length of the header. + msg: str + The message. + term: bool + If True, write to stdout. + + Returns + ------- + No return value. + """ + print_g(f'{head:{headlen}s}: {msg}', term=term) + + def parse_args(): """ Parse the command line arguments. @@ -101,7 +133,8 @@ def parse_args(): ------- The command line namespace. """ - parser = argparse.ArgumentParser(description='Configure oci utils auto test.') + parser = argparse.ArgumentParser(prog='modify_instance', + description='Configure oci utils auto test.') parser.add_argument('-n', '--name', action='store', dest='display_name', @@ -302,23 +335,280 @@ def get_configdata(profile, configfile='~/.oci/config'): return config -class autotesttfvars: +class InstanceData: + def __init__(self, instance_name, args): + self.instance_name = instance_name + self.args = args + # + # initialise config structure + self.data = self.init_config() + self.compartments = self.get_compartments() + self.subnets = self.get_subnet_details() + self.availability_domains = list() + self.image_list = list() + self.shape_list = list() + + def init_config(self): + """ + Initialise config struct. + + Parameters + ---------- + instance_name: str + The instance display name. + + Returns + ------- + dict: the config structure. + """ + data = dict() + exec_dir = inspect.getfile(inspect.currentframe()) + data['instance_display_name'] = self.instance_name + data['exec_dir'] = os.path.dirname(exec_dir) + data['base_exec_dir'] = os.path.dirname(exec_dir) + data['operator'] = _get_current_user() + data['operator_home'] = _get_current_user_home() + def_base_dir = data['operator_home'] + '/' + default_instance_dir + instance_display_name = data['instance_display_name'] + data['def_instance_dir'] = def_base_dir + '/' + instance_display_name + data['def_data_dir'] = def_base_dir + '/' + instance_display_name + '/data' + data['base_instance_dir'] = def_base_dir + '/' + instance_display_name + '/base_instance' + data['def_tf_scripts_dir'] = def_base_dir + '/' + instance_display_name + '/tf_scripts' + data['def_sh_scripts_dir'] = def_base_dir + '/' + instance_display_name + '/sh_scripts' + data['tfvarsfile'] = data['def_data_dir'] + '/' + self.args.varfilename + '.tfvars.json' + if self.args.datadir != '_DDDD_': + data['def_data_dir'] = self.args.datadir + '/data' + data['def_tf_scripts_dir'] = self.args.datadir + '/tf_scripts' + data['def_sh_scripts_dir'] = self.args.datadir + '/sh_scripts' + data['base_instance_dir'] = self.args.datadir + '/base_instance' + data['oci_config'] = self.get_configdata() + return data + + def get_configdata(self): + """ + Read the oci sdk/cli config file. + + Parameters + ---------- + profile: str + the config profile. + configfile: str + the path of the configfile. + Returns + ------- + dict: the config data. + """ + sdkconfigfile = self.args.configfile + if self.args.configfile.startswith('~/'): + sdkconfigfile = os.path.expanduser('~') + self.args.configfile[1:] + return oci.config.from_file(file_location=sdkconfigfile, profile_name=self.args.profile) + + def get_compartments(self): + """ + Get the list of compartments in this tenancy. + + Parameters + ---------- + config_dict: dict + The oci configuration file data. + + Returns + ------- + list: list of compartment objects. + """ + try: + oci_identity = oci.identity.IdentityClient(self.data['oci_config']) + oci_compartments = oci_identity.list_compartments(self.data['oci_config']['tenancy']) + except oci.exceptions.ServiceError as e: + print_g('*** AUTHORISATION ERROR ***') + sys.exit(1) + except Exception as e: + print_g('*** ERROR *** %s' % str(e)) + _logger.error('ERROR %s', str(e), exc_info=True) + sys.exit(1) + return oci_compartments.data + + def set_compartment_name(self): + """ + Get the compartment name based on the ocid + + Parameters + ---------- + compartments: list + List of compartment objects. + compartment_id: str + The compartment ocid. + + Returns + ------- + str: the compartment name. + """ + for compartment in self.compartments: + if compartment.id == self.data['compartment_ocid']: + return compartment.name + return None + + def set_compartment_id(self, ocid): + """ + Set the current compartment id and name. + + Parameters + ---------- + ocid: str + The compartment ocid. + + Returns + ------- + No return value. + """ + self.data['compartment_ocid'] = ocid + self.data['compartment_name'] = self.set_compartment_name() + + def get_compartment_name(self): + """ + Return the compartent name. + + Returns + ------- + str: the compartment name. + """ + return self.data['compartment_name'] + + def get_subnet_details(self): + """ + Get all subnets in all accessible compartments. + + Parameters + ---------- + compartments: list + list of compartment objects. + config_dict: dict + The oci configuration file data. + + Returns + ------- + list: the list of subnets. + """ + oci_subnet_list = list() + oci_subnetclient = oci.core.VirtualNetworkClient(self.data['oci_config']) + oci_vcn_client = oci.core.VirtualNetworkClient(self.data['oci_config']) + for compartment in self.compartments: + try: + oci_vcns = oci_vcn_client.list_vcns(compartment.id).data + for vcn in oci_vcns: + oci_subnet_list.extend(oci_subnetclient.list_subnets(compartment.id, vcn_id=vcn.id).data) + except oci.exceptions.ServiceError as e: + # + # we skip an authorisation error here, as one cannot expect to have access to all compartments. + if e.status == 404: + pass + else: + print_g('*** ERROR *** %s' % str(e)) + _logger.error('ERROR %s', str(e), exc_info=True) + sys.exit(1) + return oci_subnet_list + + def get_subnet_name(self, ocid): + for subn in self.subnets: + if subn.id == ocid: + return subn.display_name() + return None + + def set_availability_domains(self, compartment_id): + """ + Set the list of availability domains. + + Parameters + ---------- + compartment_id: str + The compartment ocid. + + Returns + ------- + No return value. + """ + try: + oci_identity = oci.identity.IdentityClient(self.data['oci_config']) + oci_availability_domains = oci_identity.list_availability_domains(compartment_id) + except oci.exceptions.ServiceError as e: + print_g('*** AUTHORISATION ERROR ***') + _logger.error('Authorisation error', exc_info=True) + sys.exit(1) + except Exception as e: + print_g('*** ERROR *** %s' % str(e)) + _logger.error('ERROR %s', str(e), exc_info=True) + sys.exit(1) + self.availability_domains = oci_availability_domains.data + + def set_image_list(self, compartment_id): + """ + Get a list of availabel images in this compartment. + + Parameters + ---------- + config_dict: dict + The oci configuration file data. + compartment_id: str + The compartment ocid. + + Returns + ------- + list: the list of the image objects. + """ + try: + oci_imageclient = oci.core.ComputeClient(self.data['oci_config']) + oci_images_data_all = oci.pagination.list_call_get_all_results(oci_imageclient.list_images, compartment_id) + except oci.exceptions.ServiceError as e: + print_g('*** AUTHORISATION ERROR ***') + _logger.error('Authorisation error', exc_info=True) + sys.exit(1) + except Exception as e: + print_g('*** ERROR *** %s' % str(e)) + _logger.error('ERROR %s', str(e), exc_info=True) + sys.exit(1) + # + # remove windows from the list. + oci_images_list = list() + for image in oci_images_data_all.data: + if 'Windows' not in image.operating_system: + oci_images_list.append(image) + self.image_list = oci_images_list + + def get_image_name(self, image_id): + for img in self.image_list: + if img.id == image_id: + return img.display_name + return None + + def set_shape_list(self, image_ocid): + try: + oci_imageclient = oci.core.ComputeClient(self.data['oci_config']) + oci_shapes = oci_imageclient.list_image_shape_compatibility_entries(image_ocid) + except oci.exceptions.ServiceError as e: + print_g('*** AUTHORISATION ERROR ***') + _logger.error('Authorisation error', exc_info=True) + sys.exit(1) + except Exception as e: + print_g('*** ERROR *** %s' % str(e)) + _logger.error('ERROR %s', str(e), exc_info=True) + sys.exit(1) + self.shape_list = oci_shapes.data + + +class TerraformData: """ Manipulate the tfvar.json file. """ def __init__(self, tfvars_file): """ - Initialise. + Initialise, read the terraform variables values if they exist. Parameters ---------- tfvars_file: str Full path of the tfvar.json file. - # sdkconfig: dict - # Contents of the sdk config file. """ self.json_file = tfvars_file - # self.sdkconfig = sdkconfig try: with open(self.json_file, 'rb') as tfvj: self.jsondata = json.load(tfvj) @@ -556,20 +846,18 @@ def _select_from(some_list, prompt, default_val=0): return some_list[select_index] -def select_compartment(config_dict, prompt): +def get_compartments(config_dict): """ - Select a compartment in the tenancy. + Get the list of compartments in this tenancy. Parameters ---------- config_dict: dict The oci configuration file data. - prompt: str - The prompt Returns ------- - dict: the data of the compartment. + list: list of compartment objects. """ try: oci_identity = oci.identity.IdentityClient(config_dict) @@ -581,29 +869,113 @@ def select_compartment(config_dict, prompt): print_g('*** ERROR *** %s' % str(e)) _logger.error('ERROR %s', str(e), exc_info=True) sys.exit(1) - for comp in oci_compartments.data: - print_g('%4d %-30s %s' % (oci_compartments.data.index(comp), comp.name, comp.id)) - return _select_from(oci_compartments.data, prompt) + return oci_compartments.data -def select_vcn(config_dict, compartment_id): +def get_compartment_name(compartments, compartment_id): """ - Select a VCN. + Get the compartment name based on the ocid + + Parameters + ---------- + compartments: list + List of compartment objects. + compartment_id: str + The compartment ocid. + + Returns + ------- + str: the compartment name. + """ + for compartment in compartments: + if compartment.id == compartment_id: + return compartment.name + return None + + +def get_subnet_name(subnets, subnet_id): + """ + Get the subnet name based on the ocid. + + Parameters + ---------- + subnets: list + List of subnet objects. + subnet_id: str + The subnet ocid. + + Returns + ------- + str: the subnet name. + """ + for subnet in subnets: + if subnet.id == subnet_id: + return subnet.display_name + return None + + +def get_image_name(images, image_id): + """ + Get the image name based on the ocid. + + Parameters + ---------- + images: list + List of image objects. + image_id: str + The image ocid. + + Returns + ------- + str: the image name. + """ + print(dir(images[0])) + for image in images: + if image.id == image_id: + return image.display_name + return None + + +def select_compartment(config_dict, prompt): + """ + Select a compartment in the tenancy. Parameters ---------- config_dict: dict The oci configuration file data. + + prompt: str + The prompt + Returns + ------- + dict: the data of the compartment. + """ + oci_compartments = get_compartments(config_dict['tenancy']) + + for comp in oci_compartments: + print_g('%4d %-30s %s' % (oci_compartments.index(comp), comp.name, comp.id)) + return _select_from(oci_compartments.data, prompt) + + +def get_vcns(config_dict, compartment_id): + """ + Get the list of vcns in this compartment. + + Parameters + ---------- + config_dict: dict + The oci configuration data. compartment_id: str - The compartment ocid + The compartment ocid. Returns ------- - dict: the VCN + list: the list of vcn objects. """ try: - oci_vncclient = oci.core.VirtualNetworkClient(config_dict) - oci_vcns = oci_vncclient.list_vcns(compartment_id) + oci_vcnclient = oci.core.VirtualNetworkClient(config_dict) + oci_vcns = oci_vcnclient.list_vcns(compartment_id).data except oci.exceptions.ServiceError as e: print_g('*** AUTHORISATION ERROR ***') _logger.error('Authorisation error', exc_info=True) @@ -612,8 +984,28 @@ def select_vcn(config_dict, compartment_id): print_g('*** ERROR *** %s' % str(e)) _logger.error('ERROR %s', str(e), exc_info=True) sys.exit(1) - for vcn in oci_vcns.data: - print_g('%4d %-30s %s' % (oci_vcns.data.index(vcn), vcn.display_name, vcn.id)) + return oci_vcns + + +def select_vcn(config_dict, compartment_id): + """ + Select a VCN. + + Parameters + ---------- + config_dict: dict + The oci configuration file data. + compartment_id: str + The compartment ocid + + Returns + ------- + dict: the VCN + """ + oci_vcns = get_vcns(config_dict['tenancy'], compartment_id) + + for vcn in oci_vcns : + print_g('%4d %-30s %s' % (oci_vcns.index(vcn), vcn.display_name, vcn.id)) return _select_from(oci_vcns.data, 'Select VCN for instance.') @@ -648,39 +1040,59 @@ def select_subnet(config_dict, compartment_id, vcn_id): return _select_from(oci_subnets.data, 'Select subnet instance.') -def select_image(config_dict, compartment_id): +def get_subnet_details(compartments,config_dict): """ - Select an image. + Get all subnets in all accessible compartments. + + Parameters + ---------- + compartments: list + list of compartment objects. + config_dict: dict + The oci configuration file data. + + Returns + ------- + list: the list of subnets. + """ + oci_subnet_list = list() + oci_subnetclient = oci.core.VirtualNetworkClient(config_dict) + oci_vcn_client = oci.core.VirtualNetworkClient(config_dict) + for compartment in compartments: + try: + oci_vcns = oci_vcn_client.list_vcns(compartment.id).data + for vcn in oci_vcns: + oci_subnet_list.extend(oci_subnetclient.list_subnets(compartment.id, vcn_id=vcn.id).data) + except oci.exceptions.ServiceError as e: + # + # we skip an authorisation error here, as one cannot expect to have access to all compartments. + if e.status == 404: + pass + else: + print_g('*** ERROR *** %s' % str(e)) + _logger.error('ERROR %s', str(e), exc_info=True) + sys.exit(1) + return oci_subnet_list + + +def get_images(config_dict, compartment_id): + """ + Get a list of availabel images in this compartment. Parameters ---------- config_dict: dict The oci configuration file data. compartment_id: str - The compartment ocid + The compartment ocid. Returns ------- - dict: the image + list: the list of the image objects. """ try: oci_imageclient = oci.core.ComputeClient(config_dict) - oci_images_data_all = oci.pagination.list_call_get_all_results(oci_imageclient.list_images, - compartment_id).data - - # oci_images_data = oci.pagination.list_call_get_all_results(oci_imageclient.list_images, - # compartment_id, - # operating_system='Zero').data - # oci_images_data += oci.pagination.list_call_get_all_results(oci_imageclient.list_images, - # compartment_id, - # operating_system='Custom').data - # oci_images_data += oci.pagination.list_call_get_all_results(oci_imageclient.list_images, - # compartment_id, - # operating_system='Oracle Linux').data - # oci_images_data += oci.pagination.list_call_get_all_results(oci_imageclient.list_images, - # compartment_id, - # operating_system='Oracle Autonomous Linux').data - + oci_images_data_all = oci.pagination.list_call_get_all_results(oci_imageclient.list_images, compartment_id).data except oci.exceptions.ServiceError as e: print_g('*** AUTHORISATION ERROR ***') _logger.error('Authorisation error', exc_info=True) @@ -689,10 +1101,31 @@ def select_image(config_dict, compartment_id): print_g('*** ERROR *** %s' % str(e)) _logger.error('ERROR %s', str(e), exc_info=True) sys.exit(1) - oci_images_data = list() - for img in oci_images_data_all: - if 'Windows' not in img.operating_system: - oci_images_data.append(img) + # + # remove windows from the list. + oci_images_list = list() + for image in oci_images_data_all: + if 'Windows' not in image.operating_system: + oci_images_list.append(image) + return oci_images_list + + +def select_image(config_dict, compartment_id): + """ + Select an image. + + Parameters + ---------- + config_dict: dict + The oci configuration file data. + compartment_id: str + The compartment ocid + + Returns + ------- + dict: the image + """ + oci_images_data = get_images(config_dict, compartment_id) for image in oci_images_data: # print_g('%4d %-40s %s' % (oci_images_data.index(image), image.display_name, image.id)) print_g('%4d %-40s %s' % (oci_images_data.index(image), image.display_name, image.operating_system)) @@ -701,20 +1134,44 @@ def select_image(config_dict, compartment_id): return image_data -def select_availability_domain(config_dict, compartment_id): +def get_availability_domain(data): """ - Select an availability domain. + Get the availablility domain data. + + Parameters + ---------- + data: dict + The configuration data. + + Returns + ------- + dict: the configuration data. + """ + _ = _clear() + print_g('Availability domain.\n', term=True) + availability_domain = select_availability_domain(data['oci_config'], data['compartment'].id) + print_g(availability_domain, term=False) + print_g('Selected availability domain: %s\n' % availability_domain.name) + data['availability_domain'] = availability_domain.name + if not _read_yn('Continue?', default_yn=True): + sys.exit(1) + return data + + +def get_availability_domains(config_dict, compartment_id): + """ + Get the list of availbility domains. Parameters ---------- config_dict: dict - The oci configuration file data. + The oci configuration data. compartment_id: str - The compartment ocid + The compartment ocid. Returns ------- - dict: the availability domain. + list of availability domains. """ try: oci_identity = oci.identity.IdentityClient(config_dict) @@ -727,7 +1184,26 @@ def select_availability_domain(config_dict, compartment_id): print_g('*** ERROR *** %s' % str(e)) _logger.error('ERROR %s', str(e), exc_info=True) sys.exit(1) - for domain in oci_availability_domains.data: + return oci_availability_domains.data + + +def select_availability_domain(config_dict, compartment_id): + """ + Select an availability domain. + + Parameters + ---------- + config_dict: dict + The oci configuration file data. + compartment_id: str + The compartment ocid + + Returns + ------- + dict: the availability domain. + """ + oci_availability_domains = get_availability_domains(config_dict, compartment_id) + for domain in oci_availability_domains: print_g('%4d %-30s %s' % (oci_availability_domains.data.index(domain), domain.name, domain.id)) return _select_from(oci_availability_domains.data, 'Select availability domain.') @@ -1005,6 +1481,32 @@ def copy_dir(src, dest): return True +def backup_file(tfvars): + """ + Backup a file. + + Parameters + ---------- + tfvars: str + File name. + + Returns + ------- + bool: True on success, False otherwise. + """ + try: + if os.path.exists(tfvars): + tfvars_bck = tfvars + '_%s' % datetime.now().strftime('%Y%m%d_%H%M') + shutil.copy(tfvars, tfvars_bck) + print_g('Copied %s to %s' % (tfvars, tfvars_bck)) + else: + print_g('File %s does not exist.', tfvars) + except ValueError as e: + _logger.error('Failed to backup %s to %s: %s', tfvars, tfvars_bck, str(e)) + return False + return True + + def write_bash(fn, cmd): """ Write a command to the script file fn. @@ -1084,8 +1586,8 @@ def get_user_data(data): """ data['operator'] = _get_current_user() data['operator_home'] = _get_current_user_home() - print_g('Username: %s' % data['operator']) - print_g('Home: %s' % data['operator_home']) + print_g_left('Username', 30, data['operator']) + print_g_left('Home', 30, data['operator_home']) return data @@ -1116,11 +1618,11 @@ def create_directories(data, args): data['def_tf_scripts_dir'] = args.datadir + '/tf_scripts' data['def_sh_scripts_dir'] = args.datadir + '/sh_scripts' data['base_instance_dir'] = args.datadir + '/base_instance' - print_g('Default instance dir %s' % data['def_instance_dir']) - print_g('Default data dir %s' % data['def_data_dir']) - print_g('Base instance dir %s' % data['base_instance_dir']) - print_g('Default tf_scripts dir %s' % data['def_tf_scripts_dir']) - print_g('Default sh_scripts dir %s' % data['def_sh_scripts_dir']) + print_g_left('Default instance dir', 30, data['def_instance_dir']) + print_g_left('Default data dir', 30,data['def_data_dir']) + print_g_left('Base instance dir', 30, data['base_instance_dir']) + print_g_left('Default tf_scripts dir', 30, data['def_tf_scripts_dir']) + print_g_left('Default sh_scripts dir', 30, data['def_sh_scripts_dir']) return data if not create_dir(data['def_instance_dir']): @@ -1318,9 +1820,9 @@ def get_oci_config(data, args): dict: the configuration data. """ cfg_dict = get_configdata(args.profile, args.configfile) - print_g('Configuration') + print_g('\nConfiguration:\n-------------') for k, v in cfg_dict.items(): - print_g('%40s: %s' % (k, v)) + print_g_left(k, 30, v) data['oci_config'] = cfg_dict return data @@ -1619,6 +2121,19 @@ def write_scripts(data): print_g('\nor\n%s\n%s' % (create_script, destroy_script)) +def current_data(tfvars, instance): + head = 'Compartment: %s' % instance.get_compartment_name() + # print('%s\n%s' % (head, '-' * len(head))) + selection = ['availability domain: ' + tfvars['availability_domain'], + 'subnet: ' + instance.get_subnet_name(tfvars['subnet_ocid']), + 'image: ' + instance.get_image_name(tfvars['source_ocid']), + 'shape: ' + tfvars['shape'], + 'boot volume size: ' + tfvars['boot_volume_size_in_gbs']] + if 'instance_flex_memory_in_gbs' in tfvars: + selection.extend(['flex number of cpus: ' + tfvars['instance_flex_ocpus'], + 'flex memory in gbs: ' + tfvars['instance_flex_memory_in_gbs']]) + return head, selection + def main(): """ Configure auto tests. @@ -1640,52 +2155,107 @@ def main(): # instance name to create instance_display_name = args.display_name if args.display_name is not None else _get_display_name() # - # exec dir - config_data = init_struct(instance_display_name) - # # initialise logging logging.basicConfig(filename=default_log + instance_display_name + '.log', level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s (%(module)s:%(lineno)s) - %(message)s') # + # init + print_g('Collecting instance data.....\n') + config_data = InstanceData(instance_display_name, args) + # + # current user data + #config_data = get_user_data(config_data) + # # show initial data - print_g('Display name: %s' % instance_display_name) - print_g('exec dir: %s' % config_data['exec_dir'], term=False) - print_g('base exec dir: %s' % config_data['base_exec_dir'], term=False) + print_g_left('Display name', 30, config_data.data['instance_display_name']) + print_g_left('exec dir', 30, config_data.data['exec_dir'], term=False) + print_g_left('base exec dir', 30, config_data.data['base_exec_dir'], term=False) + print_g_left('Username', 30, config_data.data['operator']) + print_g_left('Home dir', 30, config_data.data['operator_home']) + print_g_left('Default instance dir', 30, config_data.data['def_instance_dir']) + print_g_left('Default data dir', 30,config_data.data['def_data_dir']) + print_g_left('Base instance dir', 30, config_data.data['base_instance_dir']) + print_g_left('Default tf_scripts dir', 30, config_data.data['def_tf_scripts_dir']) + print_g_left('Default sh_scripts dir', 30, config_data.data['def_sh_scripts_dir']) + print_g('\nConfiguration:\n-------------') + for k, v in config_data.data['oci_config'].items(): + print_g_left(k, 30, v) + print_g_left('tfvars file', 30, config_data.data['tfvarsfile']) + # + # Get configuration data from config file. + # config_data = get_oci_config(config_data, args) + if not _read_yn('Continue?', default_yn=True): + sys.exit(1) # - # current user - config_data = get_user_data(config_data) + # Get the current instance var file data + try: + with TerraformData(config_data.data['tfvarsfile']) as atfv: + tfvars_data = atfv.jsondata + except Exception as e: + print_g('***ERROR*** %s' % str(e), term=True) + sys.exit(1) # - # initialise data structure - image_data = dict() + # compartment ocid + config_data.set_compartment_id(tfvars_data['compartment_ocid']) # - # __GT__ - print(config_data) - print(image_data) + # availability_domains + config_data.set_availability_domains(config_data.data['compartment_ocid']) # - # __GT__ - # create directories - config_data = create_directories(config_data, args) + # images + config_data.set_image_list(config_data.data['compartment_ocid']) # # __GT__ - # copy the scripts in place. - # _ = copy_scripts(config_data) + print(pformat(config_data.data, indent=4)) + print(pformat(tfvars_data, indent=4)) + # print(pformat(config_data.compartments, indent=4)) + # print(pformat(config_data.subnets, indent=4)) + # print(pformat(config_data.availability_domains, indent=4)) + # print(pformat(config_data.image_list, indent=4)) + # print(pformat(config_data.shape_list, indent=4)) # - # tf variable file path - config_data['tfvarsfile'] = config_data['def_data_dir'] + '/' + args.varfilename + '.tfvars.json' - print_g('tfvars file: %s' % config_data['tfvarsfile']) + sys.exit(1) # - # Get configuration data from config file. - config_data = get_oci_config(config_data, args) - if not _read_yn('Continue?', default_yn=True): - sys.exit(1) - print(config_data) - sys.exit(0) - # _ = _clear() + # images + # image_list = get_images(config_data['oci_config'], tfvars_data['compartment_ocid']) + # + # current data + # compartment_name = get_compartment_name(compartment_list, tfvars_data['compartment_ocid']) + # + # subnet + # subnet_name = get_subnet_name(subnet_list, tfvars_data['subnet_ocid']) + # + # image + # image_name = get_image_name(image_list, tfvars_data['source_ocid']) + # + print_g_left('Instance name', 30, config_data.data['instance_display_name']) + print_g_left('Compartment', 30, config_data.data) + instance_data = {'compartment': {'name': compartment_name, 'ocid': tfvars_data['compartment_ocid']}} + instance_data['availability_domain'] = tfvars_data['availability_domain'] + instance_data['subnet'] = {'name': subnet_name, 'ocid': tfvars_data['subnet_ocid']} + instance_data['image'] = {'name': image_name, 'ocid': tfvars_data['source_ocid']} + instance_data['shape'] = {'name': tfvars_data['shape']} + instance_data['boot_volume_size_in_gbs'] = {'name': tfvars_data['boot_volume_size_in_gbs']} + if 'instance_flex_memory_in_gbs' in tfvars_data: + instance_data['instance_flex_memory_in_gbs'] = {'name': tfvars_data['instance_flex_memory_in_gbs']} + instance_data['instance_flex_ocpus'] = {'name': tfvars_data['instance_flex_ocpus']} + # + print_g_left('compartment', 30, '%-40s %s' % (instance_data['compartment']['name'], instance_data['compartment']['ocid'])) + print_g_left('availability domain', 30, instance_data['availability_domain']) + print_g_left('subnet', 30, '%-40s %s' % (instance_data['subnet']['name'], instance_data['subnet']['ocid'])) + print_g_left('image', 30, '%-40s %s' % (instance_data['image']['name'], instance_data['image']['ocid'])) + print_g_left('shape', 30, instance_data['shape']['name']) + print_g_left('boot volume size', 30, instance_data['boot_volume_size_in_gbs']['name']) + if 'instance_flex_memory_in_gbs' in instance_data: + print_g_left('memory in gbs', 30, str(instance_data['instance_flex_memory_in_gbs']['name'])) + print_g_left('number of cpus', 30, str(instance_data['instance_flex_ocpus']['name'])) + + # + sys.exit(1) # # compose var file. try: - with autotesttfvars(config_data['tfvarsfile']) as atfv: + with TerraformData(config_data['tfvarsfile']) as atfv: _ = atfv.update_json_with_config(config_data['oci_config']) print_g('Updated variables with config data', term=True) _ = atfv.update_user(instance_display_name) @@ -1748,7 +2318,7 @@ def main(): # various data varia_data = {'vnic_display_name': instance_display_name} try: - with autotesttfvars(config_data['tfvarsfile']) as atfv: + with TerraformData(config_data['tfvarsfile']) as atfv: _ = atfv.update_varia(varia_data) print_g('Updated various data.') except Exception as e: @@ -1756,7 +2326,7 @@ def main(): # # update tfvars file try: - with autotesttfvars(config_data['tfvarsfile']) as atfv: + with TerraformData(config_data['tfvarsfile']) as atfv: _ = atfv.update_image(image_data) print_g('Updated variables with image data.') _ = atfv.update_gen_data(gen_data)