Skip to content

Commit

Permalink
Add support for VMware PhotonOS (#909)
Browse files Browse the repository at this point in the history
Also added a new (currently experimental) systemd-networkd renderer,
and includes a small refactor to cc_resolv_conf.py to support the
resolved.conf used by systemd-resolved.
  • Loading branch information
sshedi committed Jun 18, 2021
1 parent f5a2449 commit 35aa9db
Show file tree
Hide file tree
Showing 30 changed files with 1,256 additions and 59 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ get in contact with that distribution and send them our way!

| Supported OSes | Supported Public Clouds | Supported Private Clouds |
| --- | --- | --- |
| Alpine Linux<br />ArchLinux<br />Debian<br />DragonFlyBSD<br />Fedora<br />FreeBSD<br />Gentoo Linux<br />NetBSD<br />OpenBSD<br />RHEL/CentOS/AlmaLinux/Rocky<br />SLES/openSUSE<br />Ubuntu<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /> | Amazon Web Services<br />Microsoft Azure<br />Google Cloud Platform<br />Oracle Cloud Infrastructure<br />Softlayer<br />Rackspace Public Cloud<br />IBM Cloud<br />DigitalOcean<br />Bigstep<br />Hetzner<br />Joyent<br />CloudSigma<br />Alibaba Cloud<br />OVH<br />OpenNebula<br />Exoscale<br />Scaleway<br />CloudStack<br />AltCloud<br />SmartOS<br />HyperOne<br />Vultr<br />Rootbox<br /> | Bare metal installs<br />OpenStack<br />LXD<br />KVM<br />Metal-as-a-Service (MAAS)<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />|
| Alpine Linux<br />ArchLinux<br />Debian<br />DragonFlyBSD<br />Fedora<br />FreeBSD<br />Gentoo Linux<br />NetBSD<br />OpenBSD<br />RHEL/CentOS/AlmaLinux/Rocky/PhotonOS<br />SLES/openSUSE<br />Ubuntu<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /> | Amazon Web Services<br />Microsoft Azure<br />Google Cloud Platform<br />Oracle Cloud Infrastructure<br />Softlayer<br />Rackspace Public Cloud<br />IBM Cloud<br />DigitalOcean<br />Bigstep<br />Hetzner<br />Joyent<br />CloudSigma<br />Alibaba Cloud<br />OVH<br />OpenNebula<br />Exoscale<br />Scaleway<br />CloudStack<br />AltCloud<br />SmartOS<br />HyperOne<br />Vultr<br />Rootbox<br /> | Bare metal installs<br />OpenStack<br />LXD<br />KVM<br />Metal-as-a-Service (MAAS)<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />|

## To start developing cloud-init

Expand Down
11 changes: 8 additions & 3 deletions cloudinit/cmd/devel/net_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from cloudinit.sources import DataSourceOVF as ovf

from cloudinit import distros, safeyaml
from cloudinit.net import eni, netplan, network_state, sysconfig
from cloudinit.net import eni, netplan, networkd, network_state, sysconfig
from cloudinit import log

NAME = 'net-convert'
Expand Down Expand Up @@ -51,7 +51,7 @@ def get_parser(parser=None):
parser.add_argument("--debug", action='store_true',
help='enable debug logging to stderr.')
parser.add_argument("-O", "--output-kind",
choices=['eni', 'netplan', 'sysconfig'],
choices=['eni', 'netplan', 'networkd', 'sysconfig'],
required=True,
help="The network config format to emit")
return parser
Expand Down Expand Up @@ -118,9 +118,14 @@ def handle_args(name, args):
config['netplan_path'] = config['netplan_path'][1:]
# enable some netplan features
config['features'] = ['dhcp-use-domains', 'ipv6-mtu']
else:
elif args.output_kind == "networkd":
r_cls = networkd.Renderer
config = distro.renderer_configs.get('networkd')
elif args.output_kind == "sysconfig":
r_cls = sysconfig.Renderer
config = distro.renderer_configs.get('sysconfig')
else:
raise RuntimeError("Invalid output_kind")

r = r_cls(config=config)
sys.stderr.write(''.join([
Expand Down
26 changes: 19 additions & 7 deletions cloudinit/config/cc_ntp.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
NTP_CONF = '/etc/ntp.conf'
NR_POOL_SERVERS = 4
distros = ['almalinux', 'alpine', 'centos', 'debian', 'fedora', 'opensuse',
'rhel', 'rocky', 'sles', 'ubuntu']
'photon', 'rhel', 'rocky', 'sles', 'ubuntu']

NTP_CLIENT_CONFIG = {
'chrony': {
Expand Down Expand Up @@ -80,24 +80,37 @@
'confpath': '/etc/chrony/chrony.conf',
},
},
'rhel': {
'opensuse': {
'chrony': {
'service_name': 'chronyd',
},
'ntp': {
'confpath': '/etc/ntp.conf',
'service_name': 'ntpd',
},
'chrony': {
'service_name': 'chronyd',
'systemd-timesyncd': {
'check_exe': '/usr/lib/systemd/systemd-timesyncd',
},
},
'opensuse': {
'photon': {
'chrony': {
'service_name': 'chronyd',
},
'ntp': {
'confpath': '/etc/ntp.conf',
'service_name': 'ntpd',
'confpath': '/etc/ntp.conf'
},
'systemd-timesyncd': {
'check_exe': '/usr/lib/systemd/systemd-timesyncd',
'confpath': '/etc/systemd/timesyncd.conf',
},
},
'rhel': {
'ntp': {
'service_name': 'ntpd',
},
'chrony': {
'service_name': 'chronyd',
},
},
'sles': {
Expand Down Expand Up @@ -551,7 +564,6 @@ def handle(name, cfg, cloud, log, _args):
# Select which client is going to be used and get the configuration
ntp_client_config = select_ntp_client(ntp_cfg.get('ntp_client'),
cloud.distro)

# Allow user ntp config to override distro configurations
ntp_client_config = util.mergemanydict(
[ntp_client_config, ntp_cfg.get('config', {})], reverse=True)
Expand Down
25 changes: 18 additions & 7 deletions cloudinit/config/cc_resolv_conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
**Module frequency:** per instance
**Supported distros:** alpine, fedora, rhel, sles
**Supported distros:** alpine, fedora, photon, rhel, sles
**Config keys**::
Expand All @@ -47,18 +47,23 @@
"""

from cloudinit import log as logging
from cloudinit.settings import PER_INSTANCE
from cloudinit import templater
from cloudinit.settings import PER_INSTANCE
from cloudinit import util

LOG = logging.getLogger(__name__)

frequency = PER_INSTANCE

distros = ['alpine', 'fedora', 'opensuse', 'rhel', 'sles']
distros = ['alpine', 'fedora', 'opensuse', 'photon', 'rhel', 'sles']

RESOLVE_CONFIG_TEMPLATE_MAP = {
'/etc/resolv.conf': 'resolv.conf',
'/etc/systemd/resolved.conf': 'systemd.resolved.conf',
}


def generate_resolv_conf(template_fn, params, target_fname="/etc/resolv.conf"):
def generate_resolv_conf(template_fn, params, target_fname):
flags = []
false_flags = []

Expand Down Expand Up @@ -104,12 +109,18 @@ def handle(name, cfg, cloud, log, _args):
if "resolv_conf" not in cfg:
log.warning("manage_resolv_conf True but no parameters provided!")

template_fn = cloud.get_template_filename('resolv.conf')
if not template_fn:
try:
template_fn = cloud.get_template_filename(
RESOLVE_CONFIG_TEMPLATE_MAP[cloud.distro.resolv_conf_fn])
except KeyError:
log.warning("No template found, not rendering /etc/resolv.conf")
return

generate_resolv_conf(template_fn=template_fn, params=cfg["resolv_conf"])
generate_resolv_conf(
template_fn=template_fn,
params=cfg["resolv_conf"],
target_fname=cloud.disro.resolve_conf_fn
)
return

# vi: ts=4 expandtab
4 changes: 2 additions & 2 deletions cloudinit/config/cc_yum_add_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
**Module frequency:** per always
**Supported distros:** almalinux, centos, fedora, rhel, rocky
**Supported distros:** almalinux, centos, fedora, photon, rhel, rocky
**Config keys**::
Expand All @@ -36,7 +36,7 @@

from cloudinit import util

distros = ['almalinux', 'centos', 'fedora', 'rhel', 'rocky']
distros = ['almalinux', 'centos', 'fedora', 'photon', 'rhel', 'rocky']


def _canonicalize_id(repo_id):
Expand Down
28 changes: 17 additions & 11 deletions cloudinit/config/tests/test_resolv_conf.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from unittest import mock

import pytest

from unittest import mock
from cloudinit.config.cc_resolv_conf import generate_resolv_conf

from tests.unittests.test_distros.test_create_users import MyBaseDistro

EXPECTED_HEADER = """\
# Your system has been configured with 'manage-resolv-conf' set to true.
Expand All @@ -14,22 +13,28 @@


class TestGenerateResolvConf:

dist = MyBaseDistro()
tmpl_fn = "templates/resolv.conf.tmpl"

@mock.patch("cloudinit.config.cc_resolv_conf.templater.render_to_file")
def test_default_target_fname_is_etc_resolvconf(self, m_render_to_file):
generate_resolv_conf("templates/resolv.conf.tmpl", mock.MagicMock())
def test_dist_resolv_conf_fn(self, m_render_to_file):
self.dist.resolve_conf_fn = "/tmp/resolv-test.conf"
generate_resolv_conf(self.tmpl_fn,
mock.MagicMock(),
self.dist.resolve_conf_fn)

assert [
mock.call(mock.ANY, "/etc/resolv.conf", mock.ANY)
mock.call(mock.ANY, self.dist.resolve_conf_fn, mock.ANY)
] == m_render_to_file.call_args_list

@mock.patch("cloudinit.config.cc_resolv_conf.templater.render_to_file")
def test_target_fname_is_used_if_passed(self, m_render_to_file):
generate_resolv_conf(
"templates/resolv.conf.tmpl", mock.MagicMock(), "/use/this/path"
)
path = "/use/this/path"
generate_resolv_conf(self.tmpl_fn, mock.MagicMock(), path)

assert [
mock.call(mock.ANY, "/use/this/path", mock.ANY)
mock.call(mock.ANY, path, mock.ANY)
] == m_render_to_file.call_args_list

# Patch in templater so we can assert on the actual generated content
Expand Down Expand Up @@ -75,7 +80,8 @@ def test_target_fname_is_used_if_passed(self, m_render_to_file):
def test_flags_and_options(
self, m_write_file, params, expected_extra_line
):
generate_resolv_conf("templates/resolv.conf.tmpl", params)
target_fn = "/etc/resolv.conf"
generate_resolv_conf(self.tmpl_fn, params, target_fn)

expected_content = EXPECTED_HEADER
if expected_extra_line is not None:
Expand Down
4 changes: 3 additions & 1 deletion cloudinit/distros/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
'debian': ['debian', 'ubuntu'],
'freebsd': ['freebsd'],
'gentoo': ['gentoo'],
'redhat': ['almalinux', 'amazon', 'centos', 'fedora', 'rhel', 'rocky'],
'redhat': ['almalinux', 'amazon', 'centos', 'fedora', 'photon', 'rhel',
'rocky'],
'suse': ['opensuse', 'sles'],
}

Expand Down Expand Up @@ -80,6 +81,7 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta):

_ci_pkl_version = 1
prefer_fqdn = False
resolve_conf_fn = "/etc/resolv.conf"

def __init__(self, name, cfg, paths):
self._paths = paths
Expand Down
1 change: 0 additions & 1 deletion cloudinit/distros/arch.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
class Distro(distros.Distro):
locale_gen_fn = "/etc/locale.gen"
network_conf_dir = "/etc/netctl"
resolve_conf_fn = "/etc/resolv.conf"
init_cmd = ['systemctl'] # init scripts
renderer_configs = {
"netplan": {"netplan_path": "/etc/netplan/50-cloud-init.yaml",
Expand Down
1 change: 0 additions & 1 deletion cloudinit/distros/gentoo.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
class Distro(distros.Distro):
locale_conf_fn = '/etc/locale.gen'
network_conf_fn = '/etc/conf.d/net'
resolve_conf_fn = '/etc/resolv.conf'
hostname_conf_fn = '/etc/conf.d/hostname'
init_cmd = ['rc-service'] # init scripts

Expand Down
1 change: 0 additions & 1 deletion cloudinit/distros/opensuse.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class Distro(distros.Distro):
locale_conf_fn = '/etc/sysconfig/language'
network_conf_fn = '/etc/sysconfig/network/config'
network_script_tpl = '/etc/sysconfig/network/ifcfg-%s'
resolve_conf_fn = '/etc/resolv.conf'
route_conf_tpl = '/etc/sysconfig/network/ifroute-%s'
systemd_hostname_conf_fn = '/etc/hostname'
systemd_locale_conf_fn = '/etc/locale.conf'
Expand Down

0 comments on commit 35aa9db

Please sign in to comment.