Skip to content

Commit 35aa9db

Browse files
authored
Add support for VMware PhotonOS (canonical#909)
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.
1 parent f5a2449 commit 35aa9db

30 files changed

+1256
-59
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ get in contact with that distribution and send them our way!
3939

4040
| Supported OSes | Supported Public Clouds | Supported Private Clouds |
4141
| --- | --- | --- |
42-
| 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 />|
42+
| 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 />|
4343

4444
## To start developing cloud-init
4545

cloudinit/cmd/devel/net_convert.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from cloudinit.sources import DataSourceOVF as ovf
1212

1313
from cloudinit import distros, safeyaml
14-
from cloudinit.net import eni, netplan, network_state, sysconfig
14+
from cloudinit.net import eni, netplan, networkd, network_state, sysconfig
1515
from cloudinit import log
1616

1717
NAME = 'net-convert'
@@ -51,7 +51,7 @@ def get_parser(parser=None):
5151
parser.add_argument("--debug", action='store_true',
5252
help='enable debug logging to stderr.')
5353
parser.add_argument("-O", "--output-kind",
54-
choices=['eni', 'netplan', 'sysconfig'],
54+
choices=['eni', 'netplan', 'networkd', 'sysconfig'],
5555
required=True,
5656
help="The network config format to emit")
5757
return parser
@@ -118,9 +118,14 @@ def handle_args(name, args):
118118
config['netplan_path'] = config['netplan_path'][1:]
119119
# enable some netplan features
120120
config['features'] = ['dhcp-use-domains', 'ipv6-mtu']
121-
else:
121+
elif args.output_kind == "networkd":
122+
r_cls = networkd.Renderer
123+
config = distro.renderer_configs.get('networkd')
124+
elif args.output_kind == "sysconfig":
122125
r_cls = sysconfig.Renderer
123126
config = distro.renderer_configs.get('sysconfig')
127+
else:
128+
raise RuntimeError("Invalid output_kind")
124129

125130
r = r_cls(config=config)
126131
sys.stderr.write(''.join([

cloudinit/config/cc_ntp.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
NTP_CONF = '/etc/ntp.conf'
2626
NR_POOL_SERVERS = 4
2727
distros = ['almalinux', 'alpine', 'centos', 'debian', 'fedora', 'opensuse',
28-
'rhel', 'rocky', 'sles', 'ubuntu']
28+
'photon', 'rhel', 'rocky', 'sles', 'ubuntu']
2929

3030
NTP_CLIENT_CONFIG = {
3131
'chrony': {
@@ -80,24 +80,37 @@
8080
'confpath': '/etc/chrony/chrony.conf',
8181
},
8282
},
83-
'rhel': {
83+
'opensuse': {
84+
'chrony': {
85+
'service_name': 'chronyd',
86+
},
8487
'ntp': {
88+
'confpath': '/etc/ntp.conf',
8589
'service_name': 'ntpd',
8690
},
87-
'chrony': {
88-
'service_name': 'chronyd',
91+
'systemd-timesyncd': {
92+
'check_exe': '/usr/lib/systemd/systemd-timesyncd',
8993
},
9094
},
91-
'opensuse': {
95+
'photon': {
9296
'chrony': {
9397
'service_name': 'chronyd',
9498
},
9599
'ntp': {
96-
'confpath': '/etc/ntp.conf',
97100
'service_name': 'ntpd',
101+
'confpath': '/etc/ntp.conf'
98102
},
99103
'systemd-timesyncd': {
100104
'check_exe': '/usr/lib/systemd/systemd-timesyncd',
105+
'confpath': '/etc/systemd/timesyncd.conf',
106+
},
107+
},
108+
'rhel': {
109+
'ntp': {
110+
'service_name': 'ntpd',
111+
},
112+
'chrony': {
113+
'service_name': 'chronyd',
101114
},
102115
},
103116
'sles': {
@@ -551,7 +564,6 @@ def handle(name, cfg, cloud, log, _args):
551564
# Select which client is going to be used and get the configuration
552565
ntp_client_config = select_ntp_client(ntp_cfg.get('ntp_client'),
553566
cloud.distro)
554-
555567
# Allow user ntp config to override distro configurations
556568
ntp_client_config = util.mergemanydict(
557569
[ntp_client_config, ntp_cfg.get('config', {})], reverse=True)

cloudinit/config/cc_resolv_conf.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
3131
**Module frequency:** per instance
3232
33-
**Supported distros:** alpine, fedora, rhel, sles
33+
**Supported distros:** alpine, fedora, photon, rhel, sles
3434
3535
**Config keys**::
3636
@@ -47,18 +47,23 @@
4747
"""
4848

4949
from cloudinit import log as logging
50-
from cloudinit.settings import PER_INSTANCE
5150
from cloudinit import templater
51+
from cloudinit.settings import PER_INSTANCE
5252
from cloudinit import util
5353

5454
LOG = logging.getLogger(__name__)
5555

5656
frequency = PER_INSTANCE
5757

58-
distros = ['alpine', 'fedora', 'opensuse', 'rhel', 'sles']
58+
distros = ['alpine', 'fedora', 'opensuse', 'photon', 'rhel', 'sles']
59+
60+
RESOLVE_CONFIG_TEMPLATE_MAP = {
61+
'/etc/resolv.conf': 'resolv.conf',
62+
'/etc/systemd/resolved.conf': 'systemd.resolved.conf',
63+
}
5964

6065

61-
def generate_resolv_conf(template_fn, params, target_fname="/etc/resolv.conf"):
66+
def generate_resolv_conf(template_fn, params, target_fname):
6267
flags = []
6368
false_flags = []
6469

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

107-
template_fn = cloud.get_template_filename('resolv.conf')
108-
if not template_fn:
112+
try:
113+
template_fn = cloud.get_template_filename(
114+
RESOLVE_CONFIG_TEMPLATE_MAP[cloud.distro.resolv_conf_fn])
115+
except KeyError:
109116
log.warning("No template found, not rendering /etc/resolv.conf")
110117
return
111118

112-
generate_resolv_conf(template_fn=template_fn, params=cfg["resolv_conf"])
119+
generate_resolv_conf(
120+
template_fn=template_fn,
121+
params=cfg["resolv_conf"],
122+
target_fname=cloud.disro.resolve_conf_fn
123+
)
113124
return
114125

115126
# vi: ts=4 expandtab

cloudinit/config/cc_yum_add_repo.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
1919
**Module frequency:** per always
2020
21-
**Supported distros:** almalinux, centos, fedora, rhel, rocky
21+
**Supported distros:** almalinux, centos, fedora, photon, rhel, rocky
2222
2323
**Config keys**::
2424
@@ -36,7 +36,7 @@
3636

3737
from cloudinit import util
3838

39-
distros = ['almalinux', 'centos', 'fedora', 'rhel', 'rocky']
39+
distros = ['almalinux', 'centos', 'fedora', 'photon', 'rhel', 'rocky']
4040

4141

4242
def _canonicalize_id(repo_id):

cloudinit/config/tests/test_resolv_conf.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
from unittest import mock
2-
31
import pytest
42

3+
from unittest import mock
54
from cloudinit.config.cc_resolv_conf import generate_resolv_conf
6-
5+
from tests.unittests.test_distros.test_create_users import MyBaseDistro
76

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

1514

1615
class TestGenerateResolvConf:
16+
17+
dist = MyBaseDistro()
18+
tmpl_fn = "templates/resolv.conf.tmpl"
19+
1720
@mock.patch("cloudinit.config.cc_resolv_conf.templater.render_to_file")
18-
def test_default_target_fname_is_etc_resolvconf(self, m_render_to_file):
19-
generate_resolv_conf("templates/resolv.conf.tmpl", mock.MagicMock())
21+
def test_dist_resolv_conf_fn(self, m_render_to_file):
22+
self.dist.resolve_conf_fn = "/tmp/resolv-test.conf"
23+
generate_resolv_conf(self.tmpl_fn,
24+
mock.MagicMock(),
25+
self.dist.resolve_conf_fn)
2026

2127
assert [
22-
mock.call(mock.ANY, "/etc/resolv.conf", mock.ANY)
28+
mock.call(mock.ANY, self.dist.resolve_conf_fn, mock.ANY)
2329
] == m_render_to_file.call_args_list
2430

2531
@mock.patch("cloudinit.config.cc_resolv_conf.templater.render_to_file")
2632
def test_target_fname_is_used_if_passed(self, m_render_to_file):
27-
generate_resolv_conf(
28-
"templates/resolv.conf.tmpl", mock.MagicMock(), "/use/this/path"
29-
)
33+
path = "/use/this/path"
34+
generate_resolv_conf(self.tmpl_fn, mock.MagicMock(), path)
3035

3136
assert [
32-
mock.call(mock.ANY, "/use/this/path", mock.ANY)
37+
mock.call(mock.ANY, path, mock.ANY)
3338
] == m_render_to_file.call_args_list
3439

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

8086
expected_content = EXPECTED_HEADER
8187
if expected_extra_line is not None:

cloudinit/distros/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@
4646
'debian': ['debian', 'ubuntu'],
4747
'freebsd': ['freebsd'],
4848
'gentoo': ['gentoo'],
49-
'redhat': ['almalinux', 'amazon', 'centos', 'fedora', 'rhel', 'rocky'],
49+
'redhat': ['almalinux', 'amazon', 'centos', 'fedora', 'photon', 'rhel',
50+
'rocky'],
5051
'suse': ['opensuse', 'sles'],
5152
}
5253

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

8182
_ci_pkl_version = 1
8283
prefer_fqdn = False
84+
resolve_conf_fn = "/etc/resolv.conf"
8385

8486
def __init__(self, name, cfg, paths):
8587
self._paths = paths

cloudinit/distros/arch.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
class Distro(distros.Distro):
2626
locale_gen_fn = "/etc/locale.gen"
2727
network_conf_dir = "/etc/netctl"
28-
resolve_conf_fn = "/etc/resolv.conf"
2928
init_cmd = ['systemctl'] # init scripts
3029
renderer_configs = {
3130
"netplan": {"netplan_path": "/etc/netplan/50-cloud-init.yaml",

cloudinit/distros/gentoo.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
class Distro(distros.Distro):
2424
locale_conf_fn = '/etc/locale.gen'
2525
network_conf_fn = '/etc/conf.d/net'
26-
resolve_conf_fn = '/etc/resolv.conf'
2726
hostname_conf_fn = '/etc/conf.d/hostname'
2827
init_cmd = ['rc-service'] # init scripts
2928

cloudinit/distros/opensuse.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ class Distro(distros.Distro):
2727
locale_conf_fn = '/etc/sysconfig/language'
2828
network_conf_fn = '/etc/sysconfig/network/config'
2929
network_script_tpl = '/etc/sysconfig/network/ifcfg-%s'
30-
resolve_conf_fn = '/etc/resolv.conf'
3130
route_conf_tpl = '/etc/sysconfig/network/ifroute-%s'
3231
systemd_hostname_conf_fn = '/etc/hostname'
3332
systemd_locale_conf_fn = '/etc/locale.conf'

0 commit comments

Comments
 (0)