From 573ada525b8a7384398a8d7d5f094f343555df56 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Tue, 1 May 2012 17:09:32 +0100 Subject: Add support for configuring libvirt VM clock and timers There are a number of time sources made available to guests, each of which have a number of configurable policies. This introduces config APIs for the libvirt domain XML to configure the clock time sources Change-Id: Ic5047b02b4753f20bb9a63e85130d84258df7a28 Signed-off-by: Daniel P. Berrange --- nova/tests/test_libvirt_config.py | 92 +++++++++++++++++++++++++++++++++++++++ nova/virt/libvirt/config.py | 65 +++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) diff --git a/nova/tests/test_libvirt_config.py b/nova/tests/test_libvirt_config.py index df435690f..1e0818bd7 100644 --- a/nova/tests/test_libvirt_config.py +++ b/nova/tests/test_libvirt_config.py @@ -54,6 +54,98 @@ class LibvirtConfigTest(LibvirtConfigBaseTest): self.assertXmlEqual(xml, "bar") +class LibvirtConfigGuestTimerTest(LibvirtConfigBaseTest): + def test_config_platform(self): + obj = config.LibvirtConfigGuestTimer() + obj.track = "host" + + xml = obj.to_xml() + self.assertXmlEqual(xml, """ + + """) + + def test_config_pit(self): + obj = config.LibvirtConfigGuestTimer() + obj.name = "pit" + obj.tickpolicy = "discard" + + xml = obj.to_xml() + self.assertXmlEqual(xml, """ + + """) + + def test_config_hpet(self): + obj = config.LibvirtConfigGuestTimer() + obj.name = "hpet" + obj.present = False + + xml = obj.to_xml() + self.assertXmlEqual(xml, """ + + """) + + +class LibvirtConfigGuestClockTest(LibvirtConfigBaseTest): + def test_config_utc(self): + obj = config.LibvirtConfigGuestClock() + + xml = obj.to_xml() + self.assertXmlEqual(xml, """ + + """) + + def test_config_localtime(self): + obj = config.LibvirtConfigGuestClock() + obj.offset = "localtime" + + xml = obj.to_xml() + self.assertXmlEqual(xml, """ + + """) + + def test_config_timezone(self): + obj = config.LibvirtConfigGuestClock() + obj.offset = "timezone" + obj.timezone = "EDT" + + xml = obj.to_xml() + self.assertXmlEqual(xml, """ + + """) + + def test_config_variable(self): + obj = config.LibvirtConfigGuestClock() + obj.offset = "variable" + obj.adjustment = "123456" + + xml = obj.to_xml() + self.assertXmlEqual(xml, """ + + """) + + def test_config_timers(self): + obj = config.LibvirtConfigGuestClock() + + tmpit = config.LibvirtConfigGuestTimer() + tmpit.name = "pit" + tmpit.tickpolicy = "discard" + + tmrtc = config.LibvirtConfigGuestTimer() + tmrtc.name = "rtc" + tmrtc.tickpolicy = "merge" + + obj.add_timer(tmpit) + obj.add_timer(tmrtc) + + xml = obj.to_xml() + self.assertXmlEqual(xml, """ + + + + + """) + + class LibvirtConfigGuestDiskTest(LibvirtConfigBaseTest): def test_config_file(self): diff --git a/nova/virt/libvirt/config.py b/nova/virt/libvirt/config.py index 3f068fa05..3ebdf21f0 100644 --- a/nova/virt/libvirt/config.py +++ b/nova/virt/libvirt/config.py @@ -63,6 +63,63 @@ class LibvirtConfigObject(object): return xml_str +class LibvirtConfigGuestTimer(LibvirtConfigObject): + + def __init__(self, **kwargs): + super(LibvirtConfigGuestTimer, self).__init__(root_name="timer", + **kwargs) + + self.name = "platform" + self.track = None + self.tickpolicy = None + self.present = None + + def format_dom(self): + tm = super(LibvirtConfigGuestTimer, self).format_dom() + + tm.set("name", self.name) + if self.track is not None: + tm.set("track", self.track) + if self.tickpolicy is not None: + tm.set("tickpolicy", self.tickpolicy) + if self.present is not None: + if self.present: + tm.set("present", "yes") + else: + tm.set("present", "no") + + return tm + + +class LibvirtConfigGuestClock(LibvirtConfigObject): + + def __init__(self, **kwargs): + super(LibvirtConfigGuestClock, self).__init__(root_name="clock", + **kwargs) + + self.offset = "utc" + self.adjustment = None + self.timezone = None + self.timers = [] + + def format_dom(self): + clk = super(LibvirtConfigGuestClock, self).format_dom() + + clk.set("offset", self.offset) + if self.adjustment: + clk.set("adjustment", self.adjustment) + elif self.timezone: + clk.set("timezone", self.timezone) + + for tm in self.timers: + clk.append(tm.format_dom()) + + return clk + + def add_timer(self, tm): + self.timers.append(tm) + + class LibvirtConfigGuestDevice(LibvirtConfigObject): def __init__(self, **kwargs): @@ -306,6 +363,7 @@ class LibvirtConfigGuest(LibvirtConfigObject): self.memory = 1024 * 1024 * 500 self.vcpus = 1 self.acpi = False + self.clock = None self.os_type = None self.os_kernel = None self.os_initrd = None @@ -360,6 +418,10 @@ class LibvirtConfigGuest(LibvirtConfigObject): self._format_basic_props(root) self._format_os(root) self._format_features(root) + + if self.clock is not None: + root.append(self.clock.format_dom()) + self._format_devices(root) return root @@ -367,6 +429,9 @@ class LibvirtConfigGuest(LibvirtConfigObject): def add_device(self, dev): self.devices.append(dev) + def set_clock(self, clk): + self.clock = clk + class LibvirtConfigCPU(LibvirtConfigObject): -- cgit