def configure_etc_hosts(self): """Sets the /etc/hosts file on both the controllers and compute2 nodes It copies the /etc/hosts file locally, edits it, then copies the edited file back. The function will also run the hostname command remotely in order to get the hostname from the nodes. It compares this with the cdomain name from the nfs_idmapd section. If there is a discrepancy or it can't retrieve the hostname, it will raise an error Returns a tuple of the short hostname and the full hostname """ banner(self.logger, ["Setting /etc/hosts"]) tmp_path = self.make_tmp_path("/tmp/etc_hosts") configure_hosts = self.make_conf_fn(tmp_path) # Helper to retrieve the short and long names. def get_host_names(hst, domain): res = Command("hostname", host=hst)() out = res.output try: hostname = out.split('\n')[0].strip() except Exception as e: self.logger.error("Unable to get the hostname from {0}".format(hst)) raise e ind = hostname.find(domain) if ind == -1: msg = "host {0}: discrepancy between found domain name: {1} "\ "and domain in config file: {2}".format(hst, hostname, domain) self.logger.error(msg) raise Exception(msg) short = hostname[:ind] if any(map(short.endswith, [".", "-", "_"])): short = short[:-1] # remove the .,- or _ return short, hostname # Get the domain from the share_storage config file domain_name = self.share_storage_cfg["nfs"]["nfs_idmapd"]["Domain"] # Get the /etc/hosts file from all the remote machines entries = {} for comp in self.computes: compute_entry = "{0} {1}".format(*get_host_names(comp, domain_name)) entries.update({comp: compute_entry}) for comp in self.computes: configure_hosts(comp, entries, "/etc/hosts", not_found="append", delim=" ") return True
def nova_setup(self): """ Nova setup will configure all necessary files for nova to enable live migration. """ banner(self.logger, ["Doing nova.conf configuration"]) tmp_path = self.make_tmp_path("/tmp/nova_conf") configure_nova = self.make_conf_fn(tmp_path, key_excludes=["filepath"]) _nova_conf = self.nova_cfg['nova_conf'] for comp in self.computes: cmd = "mkdir -p {0}".format(_nova_conf['state_path']) Command(cmd, host=comp)() def nova_adjust(nova_configs_list): head, tail = nova_configs_list[0], nova_configs_list[1:] def conf_adjust(conf_list, targets): for _conf in conf_list: fpath = _conf["filepath"] msg = "Copying {0} to {1}".format(fpath, tmp_path) self.logger.debug(msg) # Create the state_path directory and configure nova for target in targets: configure_nova(target, _conf, fpath) # For the computes, we only need to adjust the nova.conf (which is head) conf_adjust([head], self.computes) # For controllers we need to adjust the openstack service files conf_adjust(tail, self.controllers) main_compute = self.controllers[0] info = self.comp_info[main_compute] _nova_configs_list = [_nova_conf] if info.family in ["RHEL", "CentOS", "Fedora"] and \ info.version >= 7: msg = "Doing nova setup for {0} {1} on {2}" msg = msg.format(info.family, info.version, main_compute) self.logger.info(msg) _nova_api_service = self.nova_cfg['nova_api_service'] _nova_cert_service = self.nova_cfg['nova_cert_service'] _nova_comp_service = self.nova_cfg['nova_compute_service'] _nova_configs_list = [_nova_conf, _nova_api_service, _nova_cert_service, _nova_comp_service] else: self.logger.info("Doing nova setup for RHEL 6") # Now we know which files to adjust nova_adjust(_nova_configs_list)
def finalize_services(self): """Looks at the [services] section of system_info, and performs any necessary operations""" banner(self.logger, ["Finalizing services"]) svcs = self.system_info_cfg["system_services"] for info in self.comp_info.values(): for svc, cmds in svcs.items(): for cmd in cmds.split(","): self.logger.info("Calling {} on {}".format(cmd, svc)) info.service_control(svc, cmd) self.selinux() self.mount_fstab()
def nfs_client_setup(self): """NFS client function will append mount option for live migration to the compute nodes fstab file. """ banner(self.logger, ["Doing NFS client setup"]) fstab = self.system_info_cfg["fstab"] _fstab_filename = fstab['filepath'] _nfs_server = fstab["nfs_server"] _nfs_mount_pt = fstab['nfs_client_mount'] _nfs_fstype = fstab['fstype'] _mnt_opts = fstab['attribute'] _fsck_opt = fstab['fsck'] # Build up the command to be run on each compute node fstab_entry = [_nfs_server, _nfs_mount_pt, _nfs_fstype, _mnt_opts, _fsck_opt] fstab_entry = " ".join(fstab_entry) system_util = 'echo ' system_util_operator = ' >> ' cmd = [system_util, fstab_entry, system_util_operator, _fstab_filename] rmt_cmd = " ".join(cmd) tmp_path = self.make_tmp_path("/tmp/fstab") # Before we execute the command, let's make sure we don't have this # entry in /etc/fstab already def check_fstab(host, entry): self.scp("root@{}:{}".format(host, _fstab_filename), tmp_path) base_name = os.path.basename(_fstab_filename) fstab_path = os.path.join(tmp_path, base_name) found = False with open(fstab_path, "r") as fstab: for line in fstab: items = set(line.split()) s_entry = set(entry.split()) if s_entry == items: found = True os.unlink(fstab_path) return found for host in self.computes: if check_fstab(host, fstab_entry): continue ret = Command(rmt_cmd, host=host)() if ret != 0: err = 'The remote command failed {0}'.format(ret.output) raise EnvironmentError(err)
def libvirtd_setup(self): """ libvirtd setup will configure libvirtd to listen on the external network interface. :return: upon success zero is returned if not an exception is raised. """ tmp_path = self.make_tmp_path("/tmp/libvirtd_conf") _libvirtd_cfg = self.libvirtd_cfg['libvirtd_conf'] _libvirtd_syscfg = self.libvirtd_cfg['libvirtd_sysconfig'] libvirtd_path = _libvirtd_cfg["filepath"] libvirtd_syscfg_path = _libvirtd_syscfg['filepath'] banner(self.logger, ["_libvirtd_conf: {0}".format(_libvirtd_cfg), "_libvirtd_sysconf: {0}".format(_libvirtd_syscfg)]) configure_file = self.make_conf_fn(tmp_path, key_excludes=["filepath"]) # Copy the remote libvirtd from each compute node for cmpt in self.computes: configure_file(cmpt, _libvirtd_cfg, libvirtd_path) configure_file(cmpt, _libvirtd_syscfg, libvirtd_syscfg_path)
def nfs_server_setup(self): """ NFS_Server setup will create an export file and copy this file to the nfs server, it will also determine the release of RHEL and configure version 3 or 4 nfs service. """ banner(self.logger, ["Doing NFS server setup"]) tmp_path = self.make_tmp_path("/tmp/nfs_conf") nfs = self.share_storage_cfg["nfs"] nfs_server = nfs["nfs_export"]["nfs_server"] # Configure nfs port settings fpath = nfs["nfs_ports"]["filepath"] configure_port = self.make_conf_fn(tmp_path, key_excludes=["filepath"]) configure_port(nfs_server, nfs["nfs_ports"], fpath, not_found="append") # configure /etc/idmapd.conf if self.nfssrv_info.family in ["RHEL", "CentOS"] and \ self.nfssrv_info.version >= 7: rules = nfs['nfs_idmapd'] fpath = nfs["nfs_idmapd"]["filepath"] configure_idmapd = self.make_conf_fn(tmp_path, key_excludes=["filepath"]) configure_idmapd(nfs_server, rules, fpath) # configure nfs_exports file nfs_export = nfs['nfs_export']['export'] nfs_export_attribute = nfs['nfs_export']['attribute'] nfs_export_net = nfs['nfs_export']['network'] nfs_exports_info = [nfs_export, nfs_export_net + nfs_export_attribute] basename = os.path.join(tmp_path, os.path.basename(fpath)) self.gen_file(basename, nfs_exports_info) self.scp(basename, "root@{}:/etc/exports".format(nfs_server)) return True