Merge ~rjschwei/cloud-init:suseIntegrate into cloud-init:master
- Git
- lp:~rjschwei/cloud-init
- suseIntegrate
- Merge into master
Status: | Merged |
---|---|
Approved by: | Scott Moser |
Approved revision: | 03953443306bccd173c3f06c6cf124f907396eee |
Merged at revision: | cbda576a7bbf846710ad55940bf8ca1f2d2194b9 |
Proposed branch: | ~rjschwei/cloud-init:suseIntegrate |
Merge into: | cloud-init:master |
Diff against target: |
643 lines (+369/-165) 11 files modified
cloudinit/config/cc_resolv_conf.py (+1/-1) cloudinit/distros/__init__.py (+1/-1) cloudinit/distros/opensuse.py (+210/-0) cloudinit/distros/sles.py (+5/-155) templates/hosts.suse.tmpl (+0/-3) templates/ntp.conf.opensuse.tmpl (+100/-0) tests/unittests/test_distros/test_opensuse.py (+12/-0) tests/unittests/test_distros/test_sles.py (+12/-0) tests/unittests/test_handler/test_handler_locale.py (+9/-3) tests/unittests/test_handler/test_handler_set_hostname.py (+3/-2) tox.ini (+16/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Server Team CI bot | continuous-integration | Approve | |
Review via email: mp+329616@code.launchpad.net |
Commit message
Description of the change
Integrate support for openSUSE, return SLES support to a working state.
Scott Moser (smoser) wrote : | # |
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:8fe1df5788a
https:/
Executed test runs:
FAILED: Checkout
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:8fe1df5788a
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
SUCCESS: Ubuntu LTS: Integration
SUCCESS: MAAS Compatability Testing
IN_PROGRESS: Declarative: Post Actions
Click here to trigger a rebuild:
https:/
- 583e3b4... by Robert Schweikert
-
- flake8 clean up for SUSE support
- 4ece32a... by Robert Schweikert
-
- Style conformance changes
Robert Schweikert (rjschwei) wrote : | # |
@smoser can you give this another look please?
Scott Moser (smoser) wrote : | # |
A few very small nits.
The rest looks good.
Please fix those and then I approve.
- 0395344... by Robert Schweikert
-
- SUSE integration
+ Remove openSUSE specific hosts template. The hosts file gets written
based on OS family and both SLES and openSUSE have "suse" as family
+ Add ntp config file template for openSUSE. The ntp configuration is written
based on distro name
+ Fix up comments in main integration implementation
Preview Diff
1 | diff --git a/cloudinit/config/cc_resolv_conf.py b/cloudinit/config/cc_resolv_conf.py |
2 | index 2548d1f..9812562 100644 |
3 | --- a/cloudinit/config/cc_resolv_conf.py |
4 | +++ b/cloudinit/config/cc_resolv_conf.py |
5 | @@ -55,7 +55,7 @@ LOG = logging.getLogger(__name__) |
6 | |
7 | frequency = PER_INSTANCE |
8 | |
9 | -distros = ['fedora', 'rhel', 'sles'] |
10 | +distros = ['fedora', 'opensuse', 'rhel', 'sles'] |
11 | |
12 | |
13 | def generate_resolv_conf(template_fn, params, target_fname="/etc/resolv.conf"): |
14 | diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py |
15 | index 1fd48a7..807b3ea 100755 |
16 | --- a/cloudinit/distros/__init__.py |
17 | +++ b/cloudinit/distros/__init__.py |
18 | @@ -35,7 +35,7 @@ OSFAMILIES = { |
19 | 'redhat': ['centos', 'fedora', 'rhel'], |
20 | 'gentoo': ['gentoo'], |
21 | 'freebsd': ['freebsd'], |
22 | - 'suse': ['sles'], |
23 | + 'suse': ['opensuse', 'sles'], |
24 | 'arch': ['arch'], |
25 | } |
26 | |
27 | diff --git a/cloudinit/distros/opensuse.py b/cloudinit/distros/opensuse.py |
28 | new file mode 100644 |
29 | index 0000000..b46007d |
30 | --- /dev/null |
31 | +++ b/cloudinit/distros/opensuse.py |
32 | @@ -0,0 +1,210 @@ |
33 | +# Copyright (C) 2017 SUSE LLC |
34 | +# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. |
35 | +# |
36 | +# Author: Robert Schweikert <rjschwei@suse.com> |
37 | +# Author: Juerg Haefliger <juerg.haefliger@hp.com> |
38 | +# |
39 | +# This file is part of cloud-init. See LICENSE file for license information. |
40 | + |
41 | +from cloudinit import distros |
42 | + |
43 | +from cloudinit.distros.parsers.hostname import HostnameConf |
44 | + |
45 | +from cloudinit import helpers |
46 | +from cloudinit import log as logging |
47 | +from cloudinit import util |
48 | + |
49 | +from cloudinit.distros import net_util |
50 | +from cloudinit.distros import rhel_util as rhutil |
51 | +from cloudinit.settings import PER_INSTANCE |
52 | + |
53 | +LOG = logging.getLogger(__name__) |
54 | + |
55 | + |
56 | +class Distro(distros.Distro): |
57 | + clock_conf_fn = '/etc/sysconfig/clock' |
58 | + hostname_conf_fn = '/etc/HOSTNAME' |
59 | + init_cmd = ['service'] |
60 | + locale_conf_fn = '/etc/sysconfig/language' |
61 | + network_conf_fn = '/etc/sysconfig/network' |
62 | + network_script_tpl = '/etc/sysconfig/network/ifcfg-%s' |
63 | + resolve_conf_fn = '/etc/resolv.conf' |
64 | + route_conf_tpl = '/etc/sysconfig/network/ifroute-%s' |
65 | + systemd_hostname_conf_fn = '/etc/hostname' |
66 | + systemd_locale_conf_fn = '/etc/locale.conf' |
67 | + tz_local_fn = '/etc/localtime' |
68 | + |
69 | + def __init__(self, name, cfg, paths): |
70 | + distros.Distro.__init__(self, name, cfg, paths) |
71 | + self._runner = helpers.Runners(paths) |
72 | + self.osfamily = 'suse' |
73 | + cfg['ssh_svcname'] = 'sshd' |
74 | + if self.uses_systemd(): |
75 | + self.init_cmd = ['systemctl'] |
76 | + cfg['ssh_svcname'] = 'sshd.service' |
77 | + |
78 | + def apply_locale(self, locale, out_fn=None): |
79 | + if self.uses_systemd(): |
80 | + if not out_fn: |
81 | + out_fn = self.systemd_locale_conf_fn |
82 | + locale_cfg = {'LANG': locale} |
83 | + else: |
84 | + if not out_fn: |
85 | + out_fn = self.locale_conf_fn |
86 | + locale_cfg = {'RC_LANG': locale} |
87 | + rhutil.update_sysconfig_file(out_fn, locale_cfg) |
88 | + |
89 | + def install_packages(self, pkglist): |
90 | + self.package_command( |
91 | + 'install', |
92 | + args='--auto-agree-with-licenses', |
93 | + pkgs=pkglist |
94 | + ) |
95 | + |
96 | + def package_command(self, command, args=None, pkgs=None): |
97 | + if pkgs is None: |
98 | + pkgs = [] |
99 | + |
100 | + cmd = ['zypper'] |
101 | + # No user interaction possible, enable non-interactive mode |
102 | + cmd.append('--non-interactive') |
103 | + |
104 | + # Command is the operation, such as install |
105 | + if command == 'upgrade': |
106 | + command = 'update' |
107 | + cmd.append(command) |
108 | + |
109 | + # args are the arguments to the command, not global options |
110 | + if args and isinstance(args, str): |
111 | + cmd.append(args) |
112 | + elif args and isinstance(args, list): |
113 | + cmd.extend(args) |
114 | + |
115 | + pkglist = util.expand_package_list('%s-%s', pkgs) |
116 | + cmd.extend(pkglist) |
117 | + |
118 | + # Allow the output of this to flow outwards (ie not be captured) |
119 | + util.subp(cmd, capture=False) |
120 | + |
121 | + def set_timezone(self, tz): |
122 | + tz_file = self._find_tz_file(tz) |
123 | + if self.uses_systemd(): |
124 | + # Currently, timedatectl complains if invoked during startup |
125 | + # so for compatibility, create the link manually. |
126 | + util.del_file(self.tz_local_fn) |
127 | + util.sym_link(tz_file, self.tz_local_fn) |
128 | + else: |
129 | + # Adjust the sysconfig clock zone setting |
130 | + clock_cfg = { |
131 | + 'TIMEZONE': str(tz), |
132 | + } |
133 | + rhutil.update_sysconfig_file(self.clock_conf_fn, clock_cfg) |
134 | + # This ensures that the correct tz will be used for the system |
135 | + util.copy(tz_file, self.tz_local_fn) |
136 | + |
137 | + def update_package_sources(self): |
138 | + self._runner.run("update-sources", self.package_command, |
139 | + ['refresh'], freq=PER_INSTANCE) |
140 | + |
141 | + def _bring_up_interfaces(self, device_names): |
142 | + if device_names and 'all' in device_names: |
143 | + raise RuntimeError(('Distro %s can not translate ' |
144 | + 'the device name "all"') % (self.name)) |
145 | + return distros.Distro._bring_up_interfaces(self, device_names) |
146 | + |
147 | + def _read_hostname(self, filename, default=None): |
148 | + if self.uses_systemd() and filename.endswith('/previous-hostname'): |
149 | + return util.load_file(filename).strip() |
150 | + elif self.uses_systemd(): |
151 | + (out, _err) = util.subp(['hostname']) |
152 | + if len(out): |
153 | + return out |
154 | + else: |
155 | + return default |
156 | + else: |
157 | + try: |
158 | + conf = self._read_hostname_conf(filename) |
159 | + hostname = conf.hostname |
160 | + except IOError: |
161 | + pass |
162 | + if not hostname: |
163 | + return default |
164 | + return hostname |
165 | + |
166 | + def _read_hostname_conf(self, filename): |
167 | + conf = HostnameConf(util.load_file(filename)) |
168 | + conf.parse() |
169 | + return conf |
170 | + |
171 | + def _read_system_hostname(self): |
172 | + if self.uses_systemd(): |
173 | + host_fn = self.systemd_hostname_conf_fn |
174 | + else: |
175 | + host_fn = self.hostname_conf_fn |
176 | + return (host_fn, self._read_hostname(host_fn)) |
177 | + |
178 | + def _write_hostname(self, hostname, out_fn): |
179 | + if self.uses_systemd() and out_fn.endswith('/previous-hostname'): |
180 | + util.write_file(out_fn, hostname) |
181 | + elif self.uses_systemd(): |
182 | + util.subp(['hostnamectl', 'set-hostname', str(hostname)]) |
183 | + else: |
184 | + conf = None |
185 | + try: |
186 | + # Try to update the previous one |
187 | + # so lets see if we can read it first. |
188 | + conf = self._read_hostname_conf(out_fn) |
189 | + except IOError: |
190 | + pass |
191 | + if not conf: |
192 | + conf = HostnameConf('') |
193 | + conf.set_hostname(hostname) |
194 | + util.write_file(out_fn, str(conf), 0o644) |
195 | + |
196 | + def _write_network(self, settings): |
197 | + # Convert debian settings to ifcfg format |
198 | + entries = net_util.translate_network(settings) |
199 | + LOG.debug("Translated ubuntu style network settings %s into %s", |
200 | + settings, entries) |
201 | + # Make the intermediate format as the suse format... |
202 | + nameservers = [] |
203 | + searchservers = [] |
204 | + dev_names = entries.keys() |
205 | + for (dev, info) in entries.items(): |
206 | + net_fn = self.network_script_tpl % (dev) |
207 | + route_fn = self.route_conf_tpl % (dev) |
208 | + mode = None |
209 | + if info.get('auto', None): |
210 | + mode = 'auto' |
211 | + else: |
212 | + mode = 'manual' |
213 | + bootproto = info.get('bootproto', None) |
214 | + gateway = info.get('gateway', None) |
215 | + net_cfg = { |
216 | + 'BOOTPROTO': bootproto, |
217 | + 'BROADCAST': info.get('broadcast'), |
218 | + 'GATEWAY': gateway, |
219 | + 'IPADDR': info.get('address'), |
220 | + 'LLADDR': info.get('hwaddress'), |
221 | + 'NETMASK': info.get('netmask'), |
222 | + 'STARTMODE': mode, |
223 | + 'USERCONTROL': 'no' |
224 | + } |
225 | + if dev != 'lo': |
226 | + net_cfg['ETHTOOL_OPTIONS'] = '' |
227 | + else: |
228 | + net_cfg['FIREWALL'] = 'no' |
229 | + rhutil.update_sysconfig_file(net_fn, net_cfg, True) |
230 | + if gateway and bootproto == 'static': |
231 | + default_route = 'default %s' % gateway |
232 | + util.write_file(route_fn, default_route, 0o644) |
233 | + if 'dns-nameservers' in info: |
234 | + nameservers.extend(info['dns-nameservers']) |
235 | + if 'dns-search' in info: |
236 | + searchservers.extend(info['dns-search']) |
237 | + if nameservers or searchservers: |
238 | + rhutil.update_resolve_conf_file(self.resolve_conf_fn, |
239 | + nameservers, searchservers) |
240 | + return dev_names |
241 | + |
242 | +# vi: ts=4 expandtab |
243 | diff --git a/cloudinit/distros/sles.py b/cloudinit/distros/sles.py |
244 | index dbec2ed..6e336cb 100644 |
245 | --- a/cloudinit/distros/sles.py |
246 | +++ b/cloudinit/distros/sles.py |
247 | @@ -1,167 +1,17 @@ |
248 | -# Copyright (C) 2013 Hewlett-Packard Development Company, L.P. |
249 | +# Copyright (C) 2017 SUSE LLC |
250 | # |
251 | -# Author: Juerg Haefliger <juerg.haefliger@hp.com> |
252 | +# Author: Robert Schweikert <rjschwei@suse.com> |
253 | # |
254 | # This file is part of cloud-init. See LICENSE file for license information. |
255 | |
256 | -from cloudinit import distros |
257 | +from cloudinit.distros import opensuse |
258 | |
259 | -from cloudinit.distros.parsers.hostname import HostnameConf |
260 | - |
261 | -from cloudinit import helpers |
262 | from cloudinit import log as logging |
263 | -from cloudinit import util |
264 | - |
265 | -from cloudinit.distros import net_util |
266 | -from cloudinit.distros import rhel_util |
267 | -from cloudinit.settings import PER_INSTANCE |
268 | |
269 | LOG = logging.getLogger(__name__) |
270 | |
271 | |
272 | -class Distro(distros.Distro): |
273 | - clock_conf_fn = '/etc/sysconfig/clock' |
274 | - locale_conf_fn = '/etc/sysconfig/language' |
275 | - network_conf_fn = '/etc/sysconfig/network' |
276 | - hostname_conf_fn = '/etc/HOSTNAME' |
277 | - network_script_tpl = '/etc/sysconfig/network/ifcfg-%s' |
278 | - resolve_conf_fn = '/etc/resolv.conf' |
279 | - tz_local_fn = '/etc/localtime' |
280 | - |
281 | - def __init__(self, name, cfg, paths): |
282 | - distros.Distro.__init__(self, name, cfg, paths) |
283 | - # This will be used to restrict certain |
284 | - # calls from repeatly happening (when they |
285 | - # should only happen say once per instance...) |
286 | - self._runner = helpers.Runners(paths) |
287 | - self.osfamily = 'suse' |
288 | - |
289 | - def install_packages(self, pkglist): |
290 | - self.package_command('install', args='-l', pkgs=pkglist) |
291 | - |
292 | - def _write_network(self, settings): |
293 | - # Convert debian settings to ifcfg format |
294 | - entries = net_util.translate_network(settings) |
295 | - LOG.debug("Translated ubuntu style network settings %s into %s", |
296 | - settings, entries) |
297 | - # Make the intermediate format as the suse format... |
298 | - nameservers = [] |
299 | - searchservers = [] |
300 | - dev_names = entries.keys() |
301 | - for (dev, info) in entries.items(): |
302 | - net_fn = self.network_script_tpl % (dev) |
303 | - mode = info.get('auto') |
304 | - if mode and mode.lower() == 'true': |
305 | - mode = 'auto' |
306 | - else: |
307 | - mode = 'manual' |
308 | - net_cfg = { |
309 | - 'BOOTPROTO': info.get('bootproto'), |
310 | - 'BROADCAST': info.get('broadcast'), |
311 | - 'GATEWAY': info.get('gateway'), |
312 | - 'IPADDR': info.get('address'), |
313 | - 'LLADDR': info.get('hwaddress'), |
314 | - 'NETMASK': info.get('netmask'), |
315 | - 'STARTMODE': mode, |
316 | - 'USERCONTROL': 'no' |
317 | - } |
318 | - if dev != 'lo': |
319 | - net_cfg['ETHERDEVICE'] = dev |
320 | - net_cfg['ETHTOOL_OPTIONS'] = '' |
321 | - else: |
322 | - net_cfg['FIREWALL'] = 'no' |
323 | - rhel_util.update_sysconfig_file(net_fn, net_cfg, True) |
324 | - if 'dns-nameservers' in info: |
325 | - nameservers.extend(info['dns-nameservers']) |
326 | - if 'dns-search' in info: |
327 | - searchservers.extend(info['dns-search']) |
328 | - if nameservers or searchservers: |
329 | - rhel_util.update_resolve_conf_file(self.resolve_conf_fn, |
330 | - nameservers, searchservers) |
331 | - return dev_names |
332 | - |
333 | - def apply_locale(self, locale, out_fn=None): |
334 | - if not out_fn: |
335 | - out_fn = self.locale_conf_fn |
336 | - locale_cfg = { |
337 | - 'RC_LANG': locale, |
338 | - } |
339 | - rhel_util.update_sysconfig_file(out_fn, locale_cfg) |
340 | - |
341 | - def _write_hostname(self, hostname, out_fn): |
342 | - conf = None |
343 | - try: |
344 | - # Try to update the previous one |
345 | - # so lets see if we can read it first. |
346 | - conf = self._read_hostname_conf(out_fn) |
347 | - except IOError: |
348 | - pass |
349 | - if not conf: |
350 | - conf = HostnameConf('') |
351 | - conf.set_hostname(hostname) |
352 | - util.write_file(out_fn, str(conf), 0o644) |
353 | - |
354 | - def _read_system_hostname(self): |
355 | - host_fn = self.hostname_conf_fn |
356 | - return (host_fn, self._read_hostname(host_fn)) |
357 | - |
358 | - def _read_hostname_conf(self, filename): |
359 | - conf = HostnameConf(util.load_file(filename)) |
360 | - conf.parse() |
361 | - return conf |
362 | - |
363 | - def _read_hostname(self, filename, default=None): |
364 | - hostname = None |
365 | - try: |
366 | - conf = self._read_hostname_conf(filename) |
367 | - hostname = conf.hostname |
368 | - except IOError: |
369 | - pass |
370 | - if not hostname: |
371 | - return default |
372 | - return hostname |
373 | - |
374 | - def _bring_up_interfaces(self, device_names): |
375 | - if device_names and 'all' in device_names: |
376 | - raise RuntimeError(('Distro %s can not translate ' |
377 | - 'the device name "all"') % (self.name)) |
378 | - return distros.Distro._bring_up_interfaces(self, device_names) |
379 | - |
380 | - def set_timezone(self, tz): |
381 | - tz_file = self._find_tz_file(tz) |
382 | - # Adjust the sysconfig clock zone setting |
383 | - clock_cfg = { |
384 | - 'TIMEZONE': str(tz), |
385 | - } |
386 | - rhel_util.update_sysconfig_file(self.clock_conf_fn, clock_cfg) |
387 | - # This ensures that the correct tz will be used for the system |
388 | - util.copy(tz_file, self.tz_local_fn) |
389 | - |
390 | - def package_command(self, command, args=None, pkgs=None): |
391 | - if pkgs is None: |
392 | - pkgs = [] |
393 | - |
394 | - cmd = ['zypper'] |
395 | - # No user interaction possible, enable non-interactive mode |
396 | - cmd.append('--non-interactive') |
397 | - |
398 | - # Comand is the operation, such as install |
399 | - cmd.append(command) |
400 | - |
401 | - # args are the arguments to the command, not global options |
402 | - if args and isinstance(args, str): |
403 | - cmd.append(args) |
404 | - elif args and isinstance(args, list): |
405 | - cmd.extend(args) |
406 | - |
407 | - pkglist = util.expand_package_list('%s-%s', pkgs) |
408 | - cmd.extend(pkglist) |
409 | - |
410 | - # Allow the output of this to flow outwards (ie not be captured) |
411 | - util.subp(cmd, capture=False) |
412 | - |
413 | - def update_package_sources(self): |
414 | - self._runner.run("update-sources", self.package_command, |
415 | - ['refresh'], freq=PER_INSTANCE) |
416 | +class Distro(opensuse.Distro): |
417 | + pass |
418 | |
419 | # vi: ts=4 expandtab |
420 | diff --git a/templates/hosts.suse.tmpl b/templates/hosts.suse.tmpl |
421 | index 399ec9b..b608269 100644 |
422 | --- a/templates/hosts.suse.tmpl |
423 | +++ b/templates/hosts.suse.tmpl |
424 | @@ -14,12 +14,9 @@ you need to add the following to config: |
425 | # |
426 | # The following lines are desirable for IPv4 capable hosts |
427 | 127.0.0.1 localhost |
428 | -127.0.0.1 {{fqdn}} {{hostname}} |
429 | - |
430 | |
431 | # The following lines are desirable for IPv6 capable hosts |
432 | ::1 localhost ipv6-localhost ipv6-loopback |
433 | -::1 {{fqdn}} {{hostname}} |
434 | fe00::0 ipv6-localnet |
435 | |
436 | ff00::0 ipv6-mcastprefix |
437 | diff --git a/templates/ntp.conf.opensuse.tmpl b/templates/ntp.conf.opensuse.tmpl |
438 | new file mode 100644 |
439 | index 0000000..5c5fc4d |
440 | --- /dev/null |
441 | +++ b/templates/ntp.conf.opensuse.tmpl |
442 | @@ -0,0 +1,100 @@ |
443 | +## template:jinja |
444 | + |
445 | +################################################################################ |
446 | +## /etc/ntp.conf |
447 | +## |
448 | +## Sample NTP configuration file. |
449 | +## See package 'ntp-doc' for documentation, Mini-HOWTO and FAQ. |
450 | +## Copyright (c) 1998 S.u.S.E. GmbH Fuerth, Germany. |
451 | +## |
452 | +## Author: Michael Andres, <ma@suse.de> |
453 | +## Michael Skibbe, <mskibbe@suse.de> |
454 | +## |
455 | +################################################################################ |
456 | + |
457 | +## |
458 | +## Radio and modem clocks by convention have addresses in the |
459 | +## form 127.127.t.u, where t is the clock type and u is a unit |
460 | +## number in the range 0-3. |
461 | +## |
462 | +## Most of these clocks require support in the form of a |
463 | +## serial port or special bus peripheral. The particular |
464 | +## device is normally specified by adding a soft link |
465 | +## /dev/device-u to the particular hardware device involved, |
466 | +## where u correspond to the unit number above. |
467 | +## |
468 | +## Generic DCF77 clock on serial port (Conrad DCF77) |
469 | +## Address: 127.127.8.u |
470 | +## Serial Port: /dev/refclock-u |
471 | +## |
472 | +## (create soft link /dev/refclock-0 to the particular ttyS?) |
473 | +## |
474 | +# server 127.127.8.0 mode 5 prefer |
475 | + |
476 | +## |
477 | +## Undisciplined Local Clock. This is a fake driver intended for backup |
478 | +## and when no outside source of synchronized time is available. |
479 | +## |
480 | +# server 127.127.1.0 # local clock (LCL) |
481 | +# fudge 127.127.1.0 stratum 10 # LCL is unsynchronized |
482 | + |
483 | +## |
484 | +## Add external Servers using |
485 | +## # rcntpd addserver <yourserver> |
486 | +## The servers will only be added to the currently running instance, not |
487 | +## to /etc/ntp.conf. |
488 | +## |
489 | +{% if pools %}# pools |
490 | +{% endif %} |
491 | +{% for pool in pools -%} |
492 | +pool {{pool}} iburst |
493 | +{% endfor %} |
494 | +{%- if servers %}# servers |
495 | +{% endif %} |
496 | +{% for server in servers -%} |
497 | +server {{server}} iburst |
498 | +{% endfor %} |
499 | + |
500 | +# Access control configuration; see /usr/share/doc/packages/ntp/html/accopt.html for |
501 | +# details. The web page <http://support.ntp.org/bin/view/Support/AccessRestrictions> |
502 | +# might also be helpful. |
503 | +# |
504 | +# Note that "restrict" applies to both servers and clients, so a configuration |
505 | +# that might be intended to block requests from certain clients could also end |
506 | +# up blocking replies from your own upstream servers. |
507 | + |
508 | +# By default, exchange time with everybody, but don't allow configuration. |
509 | +restrict -4 default notrap nomodify nopeer noquery |
510 | +restrict -6 default notrap nomodify nopeer noquery |
511 | + |
512 | +# Local users may interrogate the ntp server more closely. |
513 | +restrict 127.0.0.1 |
514 | +restrict ::1 |
515 | + |
516 | +# Clients from this (example!) subnet have unlimited access, but only if |
517 | +# cryptographically authenticated. |
518 | +#restrict 192.168.123.0 mask 255.255.255.0 notrust |
519 | + |
520 | +## |
521 | +## Miscellaneous stuff |
522 | +## |
523 | + |
524 | +driftfile /var/lib/ntp/drift/ntp.drift # path for drift file |
525 | + |
526 | +logfile /var/log/ntp # alternate log file |
527 | +# logconfig =syncstatus + sysevents |
528 | +# logconfig =all |
529 | + |
530 | +# statsdir /tmp/ # directory for statistics files |
531 | +# filegen peerstats file peerstats type day enable |
532 | +# filegen loopstats file loopstats type day enable |
533 | +# filegen clockstats file clockstats type day enable |
534 | + |
535 | +# |
536 | +# Authentication stuff |
537 | +# |
538 | +keys /etc/ntp.keys # path for keys file |
539 | +trustedkey 1 # define trusted keys |
540 | +requestkey 1 # key (7) for accessing server variables |
541 | +controlkey 1 # key (6) for accessing server variables |
542 | + |
543 | diff --git a/tests/unittests/test_distros/test_opensuse.py b/tests/unittests/test_distros/test_opensuse.py |
544 | new file mode 100644 |
545 | index 0000000..bdb1d63 |
546 | --- /dev/null |
547 | +++ b/tests/unittests/test_distros/test_opensuse.py |
548 | @@ -0,0 +1,12 @@ |
549 | +# This file is part of cloud-init. See LICENSE file for license information. |
550 | + |
551 | +from ..helpers import CiTestCase |
552 | + |
553 | +from . import _get_distro |
554 | + |
555 | + |
556 | +class TestopenSUSE(CiTestCase): |
557 | + |
558 | + def test_get_distro(self): |
559 | + distro = _get_distro("opensuse") |
560 | + self.assertEqual(distro.osfamily, 'suse') |
561 | diff --git a/tests/unittests/test_distros/test_sles.py b/tests/unittests/test_distros/test_sles.py |
562 | new file mode 100644 |
563 | index 0000000..c656aac |
564 | --- /dev/null |
565 | +++ b/tests/unittests/test_distros/test_sles.py |
566 | @@ -0,0 +1,12 @@ |
567 | +# This file is part of cloud-init. See LICENSE file for license information. |
568 | + |
569 | +from ..helpers import CiTestCase |
570 | + |
571 | +from . import _get_distro |
572 | + |
573 | + |
574 | +class TestSLES(CiTestCase): |
575 | + |
576 | + def test_get_distro(self): |
577 | + distro = _get_distro("sles") |
578 | + self.assertEqual(distro.osfamily, 'suse') |
579 | diff --git a/tests/unittests/test_handler/test_handler_locale.py b/tests/unittests/test_handler/test_handler_locale.py |
580 | index e9a810c..aaf6c76 100644 |
581 | --- a/tests/unittests/test_handler/test_handler_locale.py |
582 | +++ b/tests/unittests/test_handler/test_handler_locale.py |
583 | @@ -49,9 +49,15 @@ class TestLocale(t_help.FilesystemMockingTestCase): |
584 | } |
585 | cc = self._get_cloud('sles') |
586 | cc_locale.handle('cc_locale', cfg, cc, LOG, []) |
587 | - |
588 | - contents = util.load_file('/etc/sysconfig/language', decode=False) |
589 | + if cc.distro.uses_systemd: |
590 | + locale_conf = cc.distro.systemd_locale_conf_fn |
591 | + else: |
592 | + locale_conf = cc.distro.locale_conf_fn |
593 | + contents = util.load_file(locale_conf, decode=False) |
594 | n_cfg = ConfigObj(BytesIO(contents)) |
595 | - self.assertEqual({'RC_LANG': cfg['locale']}, dict(n_cfg)) |
596 | + if cc.distro.uses_systemd(): |
597 | + self.assertEqual({'LANG': cfg['locale']}, dict(n_cfg)) |
598 | + else: |
599 | + self.assertEqual({'RC_LANG': cfg['locale']}, dict(n_cfg)) |
600 | |
601 | # vi: ts=4 expandtab |
602 | diff --git a/tests/unittests/test_handler/test_handler_set_hostname.py b/tests/unittests/test_handler/test_handler_set_hostname.py |
603 | index 4b18de7..8165bf9 100644 |
604 | --- a/tests/unittests/test_handler/test_handler_set_hostname.py |
605 | +++ b/tests/unittests/test_handler/test_handler_set_hostname.py |
606 | @@ -70,7 +70,8 @@ class TestHostname(t_help.FilesystemMockingTestCase): |
607 | cc = cloud.Cloud(ds, paths, {}, distro, None) |
608 | self.patchUtils(self.tmp) |
609 | cc_set_hostname.handle('cc_set_hostname', cfg, cc, LOG, []) |
610 | - contents = util.load_file("/etc/HOSTNAME") |
611 | - self.assertEqual('blah', contents.strip()) |
612 | + if not distro.uses_systemd(): |
613 | + contents = util.load_file(distro.hostname_conf_fn) |
614 | + self.assertEqual('blah', contents.strip()) |
615 | |
616 | # vi: ts=4 expandtab |
617 | diff --git a/tox.ini b/tox.ini |
618 | index 1e7ca2d..a17156c 100644 |
619 | --- a/tox.ini |
620 | +++ b/tox.ini |
621 | @@ -92,6 +92,22 @@ deps = |
622 | six==1.9.0 |
623 | -r{toxinidir}/test-requirements.txt |
624 | |
625 | +[testenv:opensusel42] |
626 | +basepython = python2.7 |
627 | +commands = nosetests {posargs:tests/unittests} |
628 | +deps = |
629 | + # requirements |
630 | + argparse==1.3.0 |
631 | + jinja2==2.8 |
632 | + PyYAML==3.11 |
633 | + PrettyTable==0.7.2 |
634 | + oauthlib==0.7.2 |
635 | + configobj==5.0.6 |
636 | + requests==2.11.1 |
637 | + jsonpatch==1.11 |
638 | + six==1.9.0 |
639 | + -r{toxinidir}/test-requirements.txt |
640 | + |
641 | [testenv:tip-pycodestyle] |
642 | commands = {envpython} -m pycodestyle {posargs:cloudinit/ tests/ tools/} |
643 | deps = pycodestyle |
Some comments inline.