diff options
Diffstat (limited to 'apex/undercloud/undercloud.py')
-rw-r--r-- | apex/undercloud/undercloud.py | 131 |
1 files changed, 110 insertions, 21 deletions
diff --git a/apex/undercloud/undercloud.py b/apex/undercloud/undercloud.py index 013570d3..5ee487c2 100644 --- a/apex/undercloud/undercloud.py +++ b/apex/undercloud/undercloud.py @@ -15,6 +15,7 @@ import shutil import subprocess import time +from apex.builders import undercloud_builder as uc_builder from apex.virtual import utils as virt_utils from apex.virtual import configure_vm as vm_lib from apex.common import constants @@ -31,8 +32,10 @@ class Undercloud: """ def __init__(self, image_path, template_path, root_pw=None, external_network=False, - image_name='undercloud.qcow2'): + image_name='undercloud.qcow2', + os_version=constants.DEFAULT_OS_VERSION): self.ip = None + self.os_version = os_version self.root_pw = root_pw self.external_net = external_network self.volume = os.path.join(constants.LIBVIRT_VOLUME_PATH, @@ -61,27 +64,40 @@ class Undercloud: if self.external_net: networks.append('external') console = 'ttyAMA0' if platform.machine() == 'aarch64' else 'ttyS0' + root = 'vda2' if platform.machine() == 'aarch64' else 'sda' self.vm = vm_lib.create_vm(name='undercloud', image=self.volume, baremetal_interfaces=networks, direct_boot='overcloud-full', kernel_args=['console={}'.format(console), - 'root=/dev/sda'], + 'root=/dev/{}'.format(root)], default_network=True, - template_dir=self.template_path) + template_dir=self.template_path, + memory=10240) self.setup_volumes() self.inject_auth() - def _set_ip(self): - ip_out = self.vm.interfaceAddresses( + @staticmethod + def _get_ip(vm): + ip_out = vm.interfaceAddresses( libvirt.VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE, 0) if ip_out: for (name, val) in ip_out.items(): for ipaddr in val['addrs']: if ipaddr['type'] == libvirt.VIR_IP_ADDR_TYPE_IPV4: - self.ip = ipaddr['addr'] - return True + return ipaddr['addr'] + + def _set_ip(self): + ip = self._get_ip(self.vm) + if ip: + self.ip = ip + return True + + @staticmethod + def get_ip(): + vm = Undercloud._get_vm() + return Undercloud._get_ip(vm) def start(self): """ @@ -96,7 +112,7 @@ class Undercloud: # give 10 seconds to come up time.sleep(10) # set IP - for x in range(5): + for x in range(10): if self._set_ip(): logging.info("Undercloud started. IP Address: {}".format( self.ip)) @@ -110,19 +126,37 @@ class Undercloud: "Unable to find IP for undercloud. Check if VM booted " "correctly") - def configure(self, net_settings, playbook, apex_temp_dir): + def detect_nat(self, net_settings): + if self.external_net: + net = net_settings['networks'][constants.EXTERNAL_NETWORK][0] + else: + net = net_settings['networks'][constants.ADMIN_NETWORK] + if net['gateway'] == net['installer_vm']['ip']: + return True + else: + return False + + def configure(self, net_settings, deploy_settings, + playbook, apex_temp_dir, virtual_oc=False): """ Configures undercloud VM - :param net_setings: Network settings for deployment + :param net_settings: Network settings for deployment + :param deploy_settings: Deployment settings for deployment :param playbook: playbook to use to configure undercloud :param apex_temp_dir: temporary apex directory to hold configs/logs + :param virtual_oc: Boolean to determine if overcloud is virt :return: None """ logging.info("Configuring Undercloud...") # run ansible - ansible_vars = Undercloud.generate_config(net_settings) + ansible_vars = Undercloud.generate_config(net_settings, + deploy_settings) ansible_vars['apex_temp_dir'] = apex_temp_dir + + ansible_vars['nat'] = self.detect_nat(net_settings) + ansible_vars['container_client'] = utils.find_container_client( + self.os_version) try: utils.run_ansible(ansible_vars, playbook, host=self.ip, user='stack') @@ -150,11 +184,19 @@ class Undercloud: if os.path.exists(dest_img): os.remove(dest_img) shutil.copyfile(src_img, dest_img) + if img_file == self.image_name and platform.machine() != 'aarch64': + uc_builder.expand_disk(dest_img) + self.expand_root_fs() + shutil.chown(dest_img, user='qemu', group='qemu') os.chmod(dest_img, 0o0744) - # TODO(trozet):check if resize needed right now size is 50gb + + def expand_root_fs(self): # there is a lib called vminspect which has some dependencies and is # not yet available in pip. Consider switching to this lib later. + logging.debug("Expanding root filesystem on /dev/sda partition") + virt_ops = [{constants.VIRT_RUN_CMD: 'xfs_growfs /dev/sda'}] + virt_utils.virt_customize(virt_ops, self.volume) def inject_auth(self): virt_ops = list() @@ -169,39 +211,59 @@ class Undercloud: '/root/.ssh/id_rsa.pub:/root/.ssh/authorized_keys'}) run_cmds = [ 'chmod 600 /root/.ssh/authorized_keys', - 'restorecon /root/.ssh/authorized_keys', + 'restorecon -R -v /root/.ssh', + 'id -u stack || useradd -m stack', + 'mkdir -p /home/stack/.ssh', + 'chown stack:stack /home/stack/.ssh', 'cp /root/.ssh/authorized_keys /home/stack/.ssh/', 'chown stack:stack /home/stack/.ssh/authorized_keys', - 'chmod 600 /home/stack/.ssh/authorized_keys' + 'chmod 600 /home/stack/.ssh/authorized_keys', + 'echo "stack ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers', + 'touch /etc/cloud/cloud-init.disabled' ] for cmd in run_cmds: virt_ops.append({constants.VIRT_RUN_CMD: cmd}) virt_utils.virt_customize(virt_ops, self.volume) @staticmethod - def generate_config(ns): + def generate_config(ns, ds): """ Generates a dictionary of settings for configuring undercloud :param ns: network settings to derive undercloud settings + :param ds: deploy settings to derive undercloud settings :return: dictionary of settings """ ns_admin = ns['networks']['admin'] intro_range = ns['apex']['networks']['admin']['introspection_range'] config = dict() + # Check if this is an ARM deployment + config['aarch64'] = platform.machine() == 'aarch64' + # Configuration for undercloud.conf config['undercloud_config'] = [ "enable_ui false", "undercloud_update_packages false", "undercloud_debug false", "inspection_extras false", + "ipxe_enabled {}".format( + str(ds['global_params'].get('ipxe', True) and + not config['aarch64'])), "undercloud_hostname undercloud.{}".format(ns['dns-domain']), "local_ip {}/{}".format(str(ns_admin['installer_vm']['ip']), str(ns_admin['cidr']).split('/')[1]), - "network_gateway {}".format(str(ns_admin['installer_vm']['ip'])), - "network_cidr {}".format(str(ns_admin['cidr'])), + "generate_service_certificate false", + "undercloud_ntp_servers {}".format(str(ns['ntp'][0])), + "container_images_file " + "/home/stack/containers-prepare-parameter.yaml", + "undercloud_enable_selinux false" + ] + + config['undercloud_network_config'] = [ + "gateway {}".format(str(ns_admin['installer_vm']['ip'])), + "cidr {}".format(str(ns_admin['cidr'])), "dhcp_start {}".format(str(ns_admin['dhcp_range'][0])), "dhcp_end {}".format(str(ns_admin['dhcp_range'][1])), - "inspection_iprange {}".format(','.join(intro_range)) + "inspection_iprange {}".format(','.join(intro_range)), ] config['ironic_config'] = [ @@ -225,8 +287,35 @@ class Undercloud: "prefix": str(ns_external['cidr']).split('/')[1], "enabled": ns_external['enabled'] } - - # Check if this is an ARM deployment - config['aarch64'] = platform.machine() == 'aarch64' + # We will NAT external network if it is enabled. If external network + # is IPv6, we will NAT admin network in case we need IPv4 connectivity + # for things like DNS server. + if 'external' in ns.enabled_network_list and \ + ns_external['cidr'].version == 4: + nat_cidr = ns_external['cidr'] + else: + nat_cidr = ns['networks']['admin']['cidr'] + config['nat_cidr'] = str(nat_cidr) + if nat_cidr.version == 6: + config['nat_network_ipv6'] = True + else: + config['nat_network_ipv6'] = False + config['http_proxy'] = ns.get('http_proxy', '') + config['https_proxy'] = ns.get('https_proxy', '') return config + + def _update_delorean_repo(self): + if utils.internet_connectivity(): + logging.info('Updating delorean repo on Undercloud') + delorean_repo = ( + "https://trunk.rdoproject.org/centos7-{}" + "/current-tripleo/delorean.repo".format(self.os_version)) + cmd = ("curl -L -f -o " + "/etc/yum.repos.d/deloran.repo {}".format(delorean_repo)) + try: + virt_utils.virt_customize([{constants.VIRT_RUN_CMD: cmd}], + self.volume) + except Exception: + logging.warning("Failed to download and update delorean repo " + "for Undercloud") |