summaryrefslogtreecommitdiff
path: root/google_compute_engine
diff options
context:
space:
mode:
authorHelen Koike <helen.koike@collabora.com>2018-05-15 16:44:00 -0300
committerMax Illfelder <illfelder@users.noreply.github.com>2018-05-15 12:44:00 -0700
commit561679146849864f4cae14b19c3f61ef9b8b2970 (patch)
treeb47990594dcdba6108dfd820a97f0f832fb0f3b1 /google_compute_engine
parent4287b8a29c06a1dd916ea906c4a2fa7c13b35861 (diff)
downloadgoogle-compute-image-packages-561679146849864f4cae14b19c3f61ef9b8b2970.tar.gz
Add HandleClockSync in distro/utils.py for FreeBSD (#592)
* Add HandleClockSync in distro/utils.py for FreeBSD - There is no hwclock for FreeBSD, use ntpdate instead. - Check in compat.py if the system is FreeBSD and don't call distro.linux_distribution() if true - Migrate distro specific logic for clock sync to distro/utils. - Add the following functions to distro/helpers: def CallHwclock(logger): # Logic used by Linux systems def CallNtpdate(logger): # Logic used by FreeBSD - Add mock tests accordingly
Diffstat (limited to 'google_compute_engine')
-rwxr-xr-xgoogle_compute_engine/clock_skew/clock_skew_daemon.py11
-rw-r--r--google_compute_engine/clock_skew/tests/clock_skew_daemon_test.py32
-rw-r--r--google_compute_engine/compat.py7
-rw-r--r--google_compute_engine/distro/debian_8/tests/utils_test.py9
-rw-r--r--google_compute_engine/distro/debian_8/utils.py8
-rw-r--r--google_compute_engine/distro/debian_9/tests/utils_test.py9
-rw-r--r--google_compute_engine/distro/debian_9/utils.py8
-rw-r--r--google_compute_engine/distro/el_6/tests/utils_test.py9
-rw-r--r--google_compute_engine/distro/el_6/utils.py8
-rw-r--r--google_compute_engine/distro/el_7/tests/utils_test.py9
-rw-r--r--google_compute_engine/distro/el_7/utils.py8
-rw-r--r--google_compute_engine/distro/freebsd_11/__init__.py0
-rw-r--r--google_compute_engine/distro/freebsd_11/tests/__init__.py0
-rw-r--r--google_compute_engine/distro/freebsd_11/tests/utils_test.py46
-rw-r--r--google_compute_engine/distro/freebsd_11/utils.py42
-rw-r--r--google_compute_engine/distro/helpers.py35
-rw-r--r--google_compute_engine/distro/sles_11/tests/utils_test.py9
-rw-r--r--google_compute_engine/distro/sles_11/utils.py9
-rw-r--r--google_compute_engine/distro/sles_12/tests/utils_test.py9
-rw-r--r--google_compute_engine/distro/sles_12/utils.py9
-rw-r--r--google_compute_engine/distro/tests/helpers_test.py71
-rw-r--r--google_compute_engine/distro/utils.py8
-rw-r--r--google_compute_engine/tests/compat_test.py11
23 files changed, 331 insertions, 36 deletions
diff --git a/google_compute_engine/clock_skew/clock_skew_daemon.py b/google_compute_engine/clock_skew/clock_skew_daemon.py
index 881b729..3ae5978 100755
--- a/google_compute_engine/clock_skew/clock_skew_daemon.py
+++ b/google_compute_engine/clock_skew/clock_skew_daemon.py
@@ -17,13 +17,13 @@
import logging.handlers
import optparse
-import subprocess
from google_compute_engine import config_manager
from google_compute_engine import constants
from google_compute_engine import file_utils
from google_compute_engine import logger
from google_compute_engine import metadata_watcher
+from google_compute_engine.compat import distro_utils
LOCKFILE = constants.LOCALSTATEDIR + '/lock/google_clock_skew.lock'
@@ -42,6 +42,7 @@ class ClockSkewDaemon(object):
facility = logging.handlers.SysLogHandler.LOG_DAEMON
self.logger = logger.Logger(
name='google-clock-skew', debug=debug, facility=facility)
+ self.distro_utils = distro_utils.Utils(debug=debug)
self.watcher = metadata_watcher.MetadataWatcher(logger=self.logger)
try:
with file_utils.LockFile(LOCKFILE):
@@ -59,13 +60,7 @@ class ClockSkewDaemon(object):
response: string, the metadata response with the new drift token value.
"""
self.logger.info('Clock drift token has changed: %s.', response)
- command = ['/sbin/hwclock', '--hctosys']
- try:
- subprocess.check_call(command)
- except subprocess.CalledProcessError:
- self.logger.warning('Failed to sync system time with hardware clock.')
- else:
- self.logger.info('Synced system time with hardware clock.')
+ self.distro_utils.HandleClockSync(self.logger)
def main():
diff --git a/google_compute_engine/clock_skew/tests/clock_skew_daemon_test.py b/google_compute_engine/clock_skew/tests/clock_skew_daemon_test.py
index ad18d54..db1596c 100644
--- a/google_compute_engine/clock_skew/tests/clock_skew_daemon_test.py
+++ b/google_compute_engine/clock_skew/tests/clock_skew_daemon_test.py
@@ -15,8 +15,6 @@
"""Unittest for clock_skew_daemon.py module."""
-import subprocess
-
from google_compute_engine.clock_skew import clock_skew_daemon
from google_compute_engine.test_compat import mock
from google_compute_engine.test_compat import unittest
@@ -71,36 +69,18 @@ class ClockSkewDaemonTest(unittest.TestCase):
]
self.assertEqual(mocks.mock_calls, expected_calls)
- @mock.patch('google_compute_engine.clock_skew.clock_skew_daemon.subprocess.check_call')
- def testHandleClockSync(self, mock_call):
- command = ['/sbin/hwclock', '--hctosys']
- mock_sync = mock.create_autospec(clock_skew_daemon.ClockSkewDaemon)
- mock_logger = mock.Mock()
- mock_sync.logger = mock_logger
-
- clock_skew_daemon.ClockSkewDaemon.HandleClockSync(mock_sync, 'Response')
- mock_call.assert_called_once_with(command)
- expected_calls = [
- mock.call.info(mock.ANY, 'Response'),
- mock.call.info(mock.ANY),
- ]
- self.assertEqual(mock_logger.mock_calls, expected_calls)
-
- @mock.patch('google_compute_engine.clock_skew.clock_skew_daemon.subprocess.check_call')
- def testHandleClockSyncError(self, mock_call):
- command = ['/sbin/hwclock', '--hctosys']
+ @mock.patch('google_compute_engine.clock_skew.clock_skew_daemon.distro_utils')
+ def testHandleClockSync(self, mock_distro_utils):
mock_sync = mock.create_autospec(clock_skew_daemon.ClockSkewDaemon)
mock_logger = mock.Mock()
mock_sync.logger = mock_logger
- mock_call.side_effect = subprocess.CalledProcessError(1, 'Test')
+ mock_sync.distro_utils = mock_distro_utils
clock_skew_daemon.ClockSkewDaemon.HandleClockSync(mock_sync, 'Response')
- mock_call.assert_called_once_with(command)
- expected_calls = [
- mock.call.info(mock.ANY, 'Response'),
- mock.call.warning(mock.ANY),
- ]
+ expected_calls = [mock.call.info(mock.ANY, 'Response')]
self.assertEqual(mock_logger.mock_calls, expected_calls)
+ expected_calls = [mock.call.HandleClockSync(mock_logger)]
+ self.assertEqual(mock_distro_utils.mock_calls, expected_calls)
if __name__ == '__main__':
diff --git a/google_compute_engine/compat.py b/google_compute_engine/compat.py
index 3550458..9b2bcd4 100644
--- a/google_compute_engine/compat.py
+++ b/google_compute_engine/compat.py
@@ -24,7 +24,10 @@ if sys.version_info >= (3, 6):
else:
import platform as distro
-distribution = distro.linux_distribution()
+if 'freebsd' in sys.platform:
+ distribution = distro.version().split()
+else:
+ distribution = distro.linux_distribution()
distro_name = distribution[0].lower()
distro_version = distribution[1].split('.')[0]
distro_utils = None
@@ -45,6 +48,8 @@ elif 'suse' in distro_name and distro_version == '11':
import google_compute_engine.distro.sles_11.utils as distro_utils
elif 'suse' in distro_name:
import google_compute_engine.distro.sles_12.utils as distro_utils
+elif 'freebsd' in distro_name:
+ import google_compute_engine.distro.freebsd_11.utils as distro_utils
else:
# Default to Debian 9.
import google_compute_engine.distro.debian_9.utils as distro_utils
diff --git a/google_compute_engine/distro/debian_8/tests/utils_test.py b/google_compute_engine/distro/debian_8/tests/utils_test.py
index 0bb6d39..a58dbc6 100644
--- a/google_compute_engine/distro/debian_8/tests/utils_test.py
+++ b/google_compute_engine/distro/debian_8/tests/utils_test.py
@@ -35,3 +35,12 @@ class UtilsTest(unittest.TestCase):
self.mock_setup, ['A', 'B'], self.mock_logger)
expected_calls = [mock.call.call(['A', 'B'], mock.ANY)]
self.assertEqual(mocks.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro.helpers.CallHwclock')
+ def testHandleClockSync(self, mock_call):
+ mocks = mock.Mock()
+ mocks.attach_mock(mock_call, 'call')
+
+ utils.Utils.HandleClockSync(self.mock_setup, self.mock_logger)
+ expected_calls = [mock.call.call(mock.ANY)]
+ self.assertEqual(mocks.mock_calls, expected_calls)
diff --git a/google_compute_engine/distro/debian_8/utils.py b/google_compute_engine/distro/debian_8/utils.py
index b4aade5..e2b75e0 100644
--- a/google_compute_engine/distro/debian_8/utils.py
+++ b/google_compute_engine/distro/debian_8/utils.py
@@ -32,3 +32,11 @@ class Utils(utils.Utils):
dhclient_script: string, the path to a dhclient script used by dhclient.
"""
helpers.CallDhclient(interfaces, logger)
+
+ def HandleClockSync(self, logger):
+ """Sync the software clock with the hypervisor clock.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ helpers.CallHwclock(logger)
diff --git a/google_compute_engine/distro/debian_9/tests/utils_test.py b/google_compute_engine/distro/debian_9/tests/utils_test.py
index 633ba9b..efb5cc8 100644
--- a/google_compute_engine/distro/debian_9/tests/utils_test.py
+++ b/google_compute_engine/distro/debian_9/tests/utils_test.py
@@ -35,3 +35,12 @@ class UtilsTest(unittest.TestCase):
self.mock_setup, ['A', 'B'], self.mock_logger)
expected_calls = [mock.call.call(['A', 'B'], mock.ANY)]
self.assertEqual(mocks.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro.helpers.CallHwclock')
+ def testHandleClockSync(self, mock_call):
+ mocks = mock.Mock()
+ mocks.attach_mock(mock_call, 'call')
+
+ utils.Utils.HandleClockSync(self.mock_setup, self.mock_logger)
+ expected_calls = [mock.call.call(mock.ANY)]
+ self.assertEqual(mocks.mock_calls, expected_calls)
diff --git a/google_compute_engine/distro/debian_9/utils.py b/google_compute_engine/distro/debian_9/utils.py
index f235723..d1b8f00 100644
--- a/google_compute_engine/distro/debian_9/utils.py
+++ b/google_compute_engine/distro/debian_9/utils.py
@@ -32,3 +32,11 @@ class Utils(utils.Utils):
dhclient_script: string, the path to a dhclient script used by dhclient.
"""
helpers.CallDhclient(interfaces, logger)
+
+ def HandleClockSync(self, logger):
+ """Sync the software clock with the hypervisor clock.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ helpers.CallHwclock(logger)
diff --git a/google_compute_engine/distro/el_6/tests/utils_test.py b/google_compute_engine/distro/el_6/tests/utils_test.py
index 363046c..dcd5045 100644
--- a/google_compute_engine/distro/el_6/tests/utils_test.py
+++ b/google_compute_engine/distro/el_6/tests/utils_test.py
@@ -41,3 +41,12 @@ class UtilsTest(unittest.TestCase):
mock.call.call(['A', 'B'], mock.ANY, dhclient_script='test_script'),
]
self.assertEqual(mocks.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro.helpers.CallHwclock')
+ def testHandleClockSync(self, mock_call):
+ mocks = mock.Mock()
+ mocks.attach_mock(mock_call, 'call')
+
+ utils.Utils.HandleClockSync(self.mock_setup, self.mock_logger)
+ expected_calls = [mock.call.call(mock.ANY)]
+ self.assertEqual(mocks.mock_calls, expected_calls)
diff --git a/google_compute_engine/distro/el_6/utils.py b/google_compute_engine/distro/el_6/utils.py
index fc70541..b5922cc 100644
--- a/google_compute_engine/distro/el_6/utils.py
+++ b/google_compute_engine/distro/el_6/utils.py
@@ -32,3 +32,11 @@ class Utils(utils.Utils):
dhclient_script: string, the path to a dhclient script used by dhclient.
"""
helpers.CallDhclient(interfaces, logger, dhclient_script=dhclient_script)
+
+ def HandleClockSync(self, logger):
+ """Sync the software clock with the hypervisor clock.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ helpers.CallHwclock(logger)
diff --git a/google_compute_engine/distro/el_7/tests/utils_test.py b/google_compute_engine/distro/el_7/tests/utils_test.py
index 95ef298..09414bd 100644
--- a/google_compute_engine/distro/el_7/tests/utils_test.py
+++ b/google_compute_engine/distro/el_7/tests/utils_test.py
@@ -120,3 +120,12 @@ class UtilsTest(unittest.TestCase):
mock.call.call_dhclient(['C', 'D'], mock.ANY),
]
self.assertEqual(mocks.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro.helpers.CallHwclock')
+ def testHandleClockSync(self, mock_call):
+ mocks = mock.Mock()
+ mocks.attach_mock(mock_call, 'call')
+
+ utils.Utils.HandleClockSync(self.mock_setup, self.mock_logger)
+ expected_calls = [mock.call.call(mock.ANY)]
+ self.assertEqual(mocks.mock_calls, expected_calls)
diff --git a/google_compute_engine/distro/el_7/utils.py b/google_compute_engine/distro/el_7/utils.py
index a17cf56..866ab68 100644
--- a/google_compute_engine/distro/el_7/utils.py
+++ b/google_compute_engine/distro/el_7/utils.py
@@ -89,3 +89,11 @@ class Utils(utils.Utils):
elif replace:
for line in fileinput.input(interface_config, inplace=True):
print(re.sub(r'%s=.*' % config_key, config_entry, line.rstrip()))
+
+ def HandleClockSync(self, logger):
+ """Sync the software clock with the hypervisor clock.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ helpers.CallHwclock(logger)
diff --git a/google_compute_engine/distro/freebsd_11/__init__.py b/google_compute_engine/distro/freebsd_11/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/google_compute_engine/distro/freebsd_11/__init__.py
diff --git a/google_compute_engine/distro/freebsd_11/tests/__init__.py b/google_compute_engine/distro/freebsd_11/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/google_compute_engine/distro/freebsd_11/tests/__init__.py
diff --git a/google_compute_engine/distro/freebsd_11/tests/utils_test.py b/google_compute_engine/distro/freebsd_11/tests/utils_test.py
new file mode 100644
index 0000000..7bcc85e
--- /dev/null
+++ b/google_compute_engine/distro/freebsd_11/tests/utils_test.py
@@ -0,0 +1,46 @@
+#!/usr/bin/python
+# Copyright 2018 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Unittest for utils.py module."""
+
+from google_compute_engine.distro.freebsd_11 import utils
+from google_compute_engine.test_compat import mock
+from google_compute_engine.test_compat import unittest
+
+
+class UtilsTest(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_logger = mock.Mock()
+ self.mock_setup = mock.create_autospec(utils.Utils)
+
+ @mock.patch('google_compute_engine.distro.helpers.CallDhclient')
+ def testEnableNetworkInterfaces(self, mock_call):
+ mocks = mock.Mock()
+ mocks.attach_mock(mock_call, 'call')
+
+ utils.Utils.EnableNetworkInterfaces(
+ self.mock_setup, ['A', 'B'], self.mock_logger)
+ expected_calls = [mock.call.call(['A', 'B'], mock.ANY)]
+ self.assertEqual(mocks.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro.helpers.CallNtpdate')
+ def testHandleClockSync(self, mock_call):
+ mocks = mock.Mock()
+ mocks.attach_mock(mock_call, 'call')
+
+ utils.Utils.HandleClockSync(self.mock_setup, self.mock_logger)
+ expected_calls = [mock.call.call(mock.ANY)]
+ self.assertEqual(mocks.mock_calls, expected_calls)
diff --git a/google_compute_engine/distro/freebsd_11/utils.py b/google_compute_engine/distro/freebsd_11/utils.py
new file mode 100644
index 0000000..638c2d3
--- /dev/null
+++ b/google_compute_engine/distro/freebsd_11/utils.py
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+# Copyright 2018 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Utilities that are distro specific for use on FreeBSD 11."""
+
+from google_compute_engine.distro import helpers
+from google_compute_engine.distro import utils
+
+
+class Utils(utils.Utils):
+ """Utilities used by Linux guest services on FreeBSD 11."""
+
+ def EnableNetworkInterfaces(
+ self, interfaces, logger, dhclient_script=None):
+ """Enable the list of network interfaces.
+
+ Args:
+ interfaces: list of string, the output device names to enable.
+ logger: logger object, used to write to SysLog and serial port.
+ dhclient_script: string, the path to a dhclient script used by dhclient.
+ """
+ helpers.CallDhclient(interfaces, logger)
+
+ def HandleClockSync(self, logger):
+ """Sync the software clock with the hypervisor clock.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ helpers.CallNtpdate(logger)
diff --git a/google_compute_engine/distro/helpers.py b/google_compute_engine/distro/helpers.py
index 7e7272c..93902b3 100644
--- a/google_compute_engine/distro/helpers.py
+++ b/google_compute_engine/distro/helpers.py
@@ -40,3 +40,38 @@ def CallDhclient(
subprocess.check_call(dhclient_command + interfaces)
except subprocess.CalledProcessError:
logger.warning('Could not enable interfaces %s.', interfaces)
+
+
+def CallHwclock(logger):
+ """Sync clock using hwclock.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ command = ['/sbin/hwclock', '--hctosys']
+ try:
+ subprocess.check_call(command)
+ except subprocess.CalledProcessError:
+ logger.warning('Failed to sync system time with hardware clock.')
+ else:
+ logger.info('Synced system time with hardware clock.')
+
+
+def CallNtpdate(logger):
+ """Sync clock using ntpdate.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ ntpd_inactive = subprocess.call(['service', 'ntpd', 'status'])
+ try:
+ if not ntpd_inactive:
+ subprocess.check_call(['service', 'ntpd', 'stop'])
+ subprocess.check_call(
+ 'ntpdate `awk \'$1=="server" {print $2}\' /etc/ntp.conf`', shell=True)
+ if not ntpd_inactive:
+ subprocess.check_call(['service', 'ntpd', 'start'])
+ except subprocess.CalledProcessError:
+ logger.warning('Failed to sync system time with ntp server.')
+ else:
+ logger.info('Synced system time with ntp server.')
diff --git a/google_compute_engine/distro/sles_11/tests/utils_test.py b/google_compute_engine/distro/sles_11/tests/utils_test.py
index d18cc0c..735d5f7 100644
--- a/google_compute_engine/distro/sles_11/tests/utils_test.py
+++ b/google_compute_engine/distro/sles_11/tests/utils_test.py
@@ -71,3 +71,12 @@ class UtilsTest(unittest.TestCase):
mock.call.logger.warning(mock.ANY, 'eth3'),
]
self.assertEqual(mocks.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro.helpers.CallHwclock')
+ def testHandleClockSync(self, mock_call):
+ mocks = mock.Mock()
+ mocks.attach_mock(mock_call, 'call')
+
+ utils.Utils.HandleClockSync(self.mock_setup, self.mock_logger)
+ expected_calls = [mock.call.call(mock.ANY)]
+ self.assertEqual(mocks.mock_calls, expected_calls)
diff --git a/google_compute_engine/distro/sles_11/utils.py b/google_compute_engine/distro/sles_11/utils.py
index 795b02b..cd05f76 100644
--- a/google_compute_engine/distro/sles_11/utils.py
+++ b/google_compute_engine/distro/sles_11/utils.py
@@ -19,6 +19,7 @@ import os
import subprocess
from google_compute_engine import constants
+from google_compute_engine.distro import helpers
from google_compute_engine.distro import utils
@@ -58,3 +59,11 @@ class Utils(utils.Utils):
except subprocess.CalledProcessError:
# The interface is already active.
logger.warning('Could not activate interface %s.', interface)
+
+ def HandleClockSync(self, logger):
+ """Sync the software clock with the hypervisor clock.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ helpers.CallHwclock(logger)
diff --git a/google_compute_engine/distro/sles_12/tests/utils_test.py b/google_compute_engine/distro/sles_12/tests/utils_test.py
index ba849a4..9f042af 100644
--- a/google_compute_engine/distro/sles_12/tests/utils_test.py
+++ b/google_compute_engine/distro/sles_12/tests/utils_test.py
@@ -91,3 +91,12 @@ class UtilsTest(unittest.TestCase):
mock.call.logger.warning(mock.ANY, ['eth1', 'eth2']),
]
self.assertEqual(mocks.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro.helpers.CallHwclock')
+ def testHandleClockSync(self, mock_call):
+ mocks = mock.Mock()
+ mocks.attach_mock(mock_call, 'call')
+
+ utils.Utils.HandleClockSync(self.mock_setup, self.mock_logger)
+ expected_calls = [mock.call.call(mock.ANY)]
+ self.assertEqual(mocks.mock_calls, expected_calls)
diff --git a/google_compute_engine/distro/sles_12/utils.py b/google_compute_engine/distro/sles_12/utils.py
index 19fe3e0..60ecb2a 100644
--- a/google_compute_engine/distro/sles_12/utils.py
+++ b/google_compute_engine/distro/sles_12/utils.py
@@ -19,6 +19,7 @@ import os
import subprocess
from google_compute_engine import constants
+from google_compute_engine.distro import helpers
from google_compute_engine.distro import utils
@@ -80,3 +81,11 @@ class Utils(utils.Utils):
subprocess.check_call(ifup + interfaces)
except subprocess.CalledProcessError:
logger.warning('Could not activate interfaces %s.', interfaces)
+
+ def HandleClockSync(self, logger):
+ """Sync the software clock with the hypervisor clock.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ helpers.CallHwclock(logger)
diff --git a/google_compute_engine/distro/tests/helpers_test.py b/google_compute_engine/distro/tests/helpers_test.py
index 75a366d..a4b6863 100644
--- a/google_compute_engine/distro/tests/helpers_test.py
+++ b/google_compute_engine/distro/tests/helpers_test.py
@@ -64,3 +64,74 @@ class HelpersTest(unittest.TestCase):
]
self.assertEqual(mocks.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro.helpers.subprocess.check_call')
+ def testCallHwclock(self, mock_call):
+ command = ['/sbin/hwclock', '--hctosys']
+ mock_logger = mock.Mock()
+
+ helpers.CallHwclock(mock_logger)
+ mock_call.assert_called_once_with(command)
+ expected_calls = [mock.call.info(mock.ANY)]
+ self.assertEqual(mock_logger.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro.helpers.subprocess.check_call')
+ def testCallHwclockError(self, mock_call):
+ command = ['/sbin/hwclock', '--hctosys']
+ mock_logger = mock.Mock()
+ mock_call.side_effect = subprocess.CalledProcessError(1, 'Test')
+
+ helpers.CallHwclock(mock_logger)
+ mock_call.assert_called_once_with(command)
+ expected_calls = [mock.call.warning(mock.ANY)]
+ self.assertEqual(mock_logger.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro.helpers.subprocess.check_call')
+ @mock.patch('google_compute_engine.distro.helpers.subprocess.call')
+ def testCallNtpdateActive(self, mock_call, mock_check_call):
+ command_status = ['service', 'ntpd', 'status']
+ command_stop = ['service', 'ntpd', 'stop']
+ command_start = ['service', 'ntpd', 'start']
+ command_ntpdate = 'ntpdate `awk \'$1=="server" {print $2}\' /etc/ntp.conf`'
+ mock_logger = mock.Mock()
+ mock_call.return_value = 0
+ mock_check_call.return_value = True
+
+ helpers.CallNtpdate(mock_logger)
+ mock_call.assert_called_once_with(command_status)
+ expected_calls = [
+ mock.call(command_stop),
+ mock.call(command_ntpdate, shell=True),
+ mock.call(command_start),
+ ]
+ self.assertEqual(mock_check_call.mock_calls, expected_calls)
+ expected_calls = [mock.call.info(mock.ANY)]
+ self.assertEqual(mock_logger.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro.helpers.subprocess.check_call')
+ @mock.patch('google_compute_engine.distro.helpers.subprocess.call')
+ def testCallNtpdateInactive(self, mock_call, mock_check_call):
+ command_status = ['service', 'ntpd', 'status']
+ command_ntpdate = 'ntpdate `awk \'$1=="server" {print $2}\' /etc/ntp.conf`'
+ mock_logger = mock.Mock()
+ mock_call.return_value = 1
+
+ helpers.CallNtpdate(mock_logger)
+ mock_call.assert_called_once_with(command_status)
+ mock_check_call.assert_called_once_with(command_ntpdate, shell=True)
+ expected_calls = [mock.call.info(mock.ANY)]
+ self.assertEqual(mock_logger.mock_calls, expected_calls)
+
+ @mock.patch('google_compute_engine.distro.helpers.subprocess.check_call')
+ @mock.patch('google_compute_engine.distro.helpers.subprocess.call')
+ def testCallNtpdateError(self, mock_call, mock_check_call):
+ command_status = ['service', 'ntpd', 'status']
+ command_ntpdate = 'ntpdate `awk \'$1=="server" {print $2}\' /etc/ntp.conf`'
+ mock_logger = mock.Mock()
+ mock_check_call.side_effect = subprocess.CalledProcessError(1, 'Test')
+
+ helpers.CallNtpdate(mock_logger)
+ mock_call.assert_called_once_with(command_status)
+ mock_check_call.assert_called_once_with(command_ntpdate, shell=True)
+ expected_calls = [mock.call.warning(mock.ANY)]
+ self.assertEqual(mock_logger.mock_calls, expected_calls)
diff --git a/google_compute_engine/distro/utils.py b/google_compute_engine/distro/utils.py
index d2d9f97..bb26390 100644
--- a/google_compute_engine/distro/utils.py
+++ b/google_compute_engine/distro/utils.py
@@ -37,3 +37,11 @@ class Utils(object):
dhclient_script: string, the path to a dhclient script used by dhclient.
"""
pass
+
+ def HandleClockSync(self, logger):
+ """Sync the software clock with the hypervisor clock.
+
+ Args:
+ logger: logger object, used to write to SysLog and serial port.
+ """
+ pass
diff --git a/google_compute_engine/tests/compat_test.py b/google_compute_engine/tests/compat_test.py
index da0ceaf..189c795 100644
--- a/google_compute_engine/tests/compat_test.py
+++ b/google_compute_engine/tests/compat_test.py
@@ -69,7 +69,7 @@ class CompatTest(unittest.TestCase):
pass
@mock.patch('google_compute_engine.compat.distro.linux_distribution')
- def testDistroCompat(self, mock_call):
+ def testDistroCompatLinux(self, mock_call):
test_cases = {
('debian', '8.10', ''):
google_compute_engine.distro.debian_8.utils,
@@ -107,6 +107,15 @@ class CompatTest(unittest.TestCase):
self.assertEqual(
test_cases[distro], google_compute_engine.compat.distro_utils)
+ @mock.patch('google_compute_engine.compat.sys.platform', 'freebsd')
+ @mock.patch('google_compute_engine.compat.distro.version')
+ def testDistroCompatFreeBSD(self, mock_call):
+ mock_call.return_value = 'FreeBSD 11.1-RELEASE-p4 #0: Tue Nov 14 06:12:40'
+ reload_import(google_compute_engine.compat)
+ self.assertEqual(
+ google_compute_engine.distro.freebsd_11.utils,
+ google_compute_engine.compat.distro_utils)
+
if __name__ == '__main__':
unittest.main()