charm-ironic-conductor/lib/charm/openstack/ironic/controller_utils.py

176 lines
5.9 KiB
Python

import os
import shutil
from charmhelpers.core.templating import render
import charmhelpers.core.host as ch_host
import charmhelpers.fetch as fetch
import charmhelpers.core.hookenv as hookenv
_IRONIC_USER = "ironic"
_IRONIC_GROUP = "ironic"
class PXEBootBase(object):
TFTP_ROOT = "/tftpboot"
HTTP_ROOT = "/httpboot"
HTTP_SERVER_CONF = "/etc/nginx/nginx.conf"
GRUB_DIR = os.path.join(TFTP_ROOT, "grub")
GRUB_CFG = os.path.join(GRUB_DIR, "grub.cfg")
MAP_FILE = os.path.join(TFTP_ROOT, "map-file")
TFTP_CONFIG = "/etc/default/tftpd-hpa"
# This is a file map of source to destination. The destination is
# relative to self.TFTP_ROOT
FILE_MAP = {
"/usr/lib/PXELINUX/pxelinux.0": "pxelinux.0",
"/usr/lib/syslinux/modules/bios/chain.c32": "chain.c32",
"/usr/lib/syslinux/modules/bios/ldlinux.c32": "ldlinux.c32",
"/usr/lib/grub/x86_64-efi-signed/grubnetx64.efi.signed": "grubx64.efi",
"/usr/lib/shim/shim.efi.signed": "bootx64.efi",
"/usr/lib/ipxe/undionly.kpxe": "undionly.kpxe",
"/usr/lib/ipxe/ipxe.efi": "ipxe.efi",
}
TFTP_PACKAGES = ["tftpd-hpa"]
TFTPD_SERVICE = "tftpd-hpa"
PACKAGES = [
'syslinux-common',
'pxelinux',
'grub-efi-amd64-signed',
'shim-signed',
'ipxe',
]
HTTPD_PACKAGES = ["nginx"]
HTTPD_SERVICE_NAME = "nginx"
IRONIC_USER = _IRONIC_USER
IRONIC_GROUP = _IRONIC_GROUP
def __init__(self, charm_config):
self._config = charm_config
def get_restart_map(self):
return {
self.TFTP_CONFIG: [self.TFTPD_SERVICE,],
self.MAP_FILE: [self.TFTPD_SERVICE,],
self.GRUB_CFG: [self.TFTPD_SERVICE,],
}
def determine_packages(self):
default_packages = (
self.PACKAGES + self.TFTP_PACKAGES + self.HTTPD_PACKAGES)
return default_packages
def _copy_resources(self):
self._ensure_folders()
for f in self.FILE_MAP:
if os.path.isfile(f) is False:
raise ValueError(
"Missing required file %s. Package not installes?" % f)
shutil.copy(
f, os.path.join(self.TFTP_ROOT, self.FILE_MAP[f]),
follow_symlinks=True)
ch_host.chownr(
self.TFTP_ROOT, _IRONIC_USER, _IRONIC_GROUP, chowntopdir=True)
def _ensure_folders(self):
if os.path.isdir(self.TFTP_ROOT) is False:
os.makedirs(self.TFTP_ROOT)
if os.path.isdir(self.HTTP_ROOT) is False:
os.makedirs(self.HTTP_ROOT)
if os.path.isdir(self.GRUB_DIR) is False:
os.makedirs(self.GRUB_DIR)
ch_host.chownr(
self.TFTP_ROOT, _IRONIC_USER, _IRONIC_GROUP, chowntopdir=True)
ch_host.chownr(
self.HTTP_ROOT, _IRONIC_USER, _IRONIC_GROUP, chowntopdir=True)
# def _create_file_map(self):
# self._ensure_folders()
# render(source='tftp-file-map',
# target=self.MAP_FILE,
# owner=_IRONIC_USER,
# perms=0o664,
# context={})
# def _create_grub_cfg(self):
# self._ensure_folders()
# render(source='grub-efi',
# target=os.path.join(self.GRUB_DIR, "grub.cfg"),
# owner="root",
# perms=0o644,
# context={
# "tftpboot": self.TFTP_ROOT,
# })
# def _create_tftp_config(self):
# cfg_dir = os.path.dirname(self.TFTP_CONFIG)
# if os.path.isdir(cfg_dir) is False:
# raise Exception("Could not find %s" % cfg_dir)
# render(source='tftpd-hpa',
# target=self.TFTP_CONFIG,
# owner="root",
# perms=0o644,
# context={
# "tftpboot": self.TFTP_ROOT,
# "max_tftp_block_size": self._config.get(
# "max_tftp_block_size", 0)
# })
# def _enable_ipxe_webserver(self):
# if self._config.get("use_ipxe", False) is False:
# return
# fetch.apt_install(self.HTTPD_PACKAGES, fatal=True)
# render(source='nginx.conf',
# target=self.HTTP_SERVER_CONF,
# owner="root",
# perms=0o644,
# context={
# "ironic_user": _IRONIC_USER,
# "ipxe_http_port": self._config.get(
# "ipxe_http_port", 8080),
# "httpboot": self.HTTP_ROOT,
# })
# def configure_resources(self):
# # On Ubuntu 20.04, if IPv6 is not available on the system,
# # the tftp-hpa package fails to install properly. We create the
# # config beforehand, forcing IPv4.
# self._create_tftp_config()
# self._create_file_map()
# fetch.apt_install(self.TFTP_PACKAGES, fatal=True)
# fetch.apt_install(self.PACKAGES, fatal=True)
# self._copy_resources()
# self._create_grub_cfg()
class PXEBootBionic(PXEBootBase):
# This is a file map of source to destination. The destination is
# relative to self.TFTP_ROOT
FILE_MAP = {
"/usr/lib/PXELINUX/pxelinux.0": "pxelinux.0",
"/usr/lib/syslinux/modules/bios/chain.c32": "chain.c32",
"/usr/lib/syslinux/modules/bios/ldlinux.c32": "ldlinux.c32",
"/usr/lib/grub/x86_64-efi-signed/grubnetx64.efi.signed": "grubx64.efi",
"/usr/lib/shim/shimx64.efi.signed": "bootx64.efi",
"/usr/lib/ipxe/undionly.kpxe": "undionly.kpxe",
"/usr/lib/ipxe/ipxe.efi": "ipxe.efi",
}
def get_pxe_config_class(charm_config):
# In the future, we may need to make slight adjustments to package
# names and/or configuration files, based on the version of Ubuntu
# we are installing on. This function serves as a factory which will
# return an instance of the proper class to the charm. For now we only
# have one class.
series = ch_host.get_distrib_codename()
if series == "bionic":
return PXEBootBionic(charm_config)
return PXEBootBase(charm_config)