From 492b381c9dd92a20d994ac90e77aceb7d51cfb13 Mon Sep 17 00:00:00 2001 From: Nadav Goldin Date: Tue, 20 Jun 2017 20:21:57 +0300 Subject: [PATCH 1/3] Move domain templates to Jinja2 For now only for simple replacements, so there is not a big difference from what we had before. Signed-off-by: Nadav Goldin --- lago.spec.in | 1 + ..._template.xml => dom_template-base.xml.j2} | 6 +-- ...mplate-el6.xml => dom_template-el6.xml.j2} | 6 +-- lago/providers/libvirt/utils.py | 33 ++++++++++++++++- lago/providers/libvirt/vm.py | 37 ++++++++++--------- 5 files changed, 58 insertions(+), 25 deletions(-) rename lago/providers/libvirt/templates/{dom_template.xml => dom_template-base.xml.j2} (91%) rename lago/providers/libvirt/templates/{dom_template-el6.xml => dom_template-el6.xml.j2} (91%) diff --git a/lago.spec.in b/lago.spec.in index 510fe69b..ce6babad 100644 --- a/lago.spec.in +++ b/lago.spec.in @@ -128,6 +128,7 @@ Requires: sudo %{python2_sitelib}/%{name}/providers/*.py* %{python2_sitelib}/%{name}/providers/libvirt/*.py* %{python2_sitelib}/%{name}/providers/libvirt/templates/*.xml +%{python2_sitelib}/%{name}/providers/libvirt/templates/*.j2 %{python2_sitelib}/%{name}-%{version}-py*.egg-info %{_bindir}/lagocli diff --git a/lago/providers/libvirt/templates/dom_template.xml b/lago/providers/libvirt/templates/dom_template-base.xml.j2 similarity index 91% rename from lago/providers/libvirt/templates/dom_template.xml rename to lago/providers/libvirt/templates/dom_template-base.xml.j2 index 27d16509..860d2027 100644 --- a/lago/providers/libvirt/templates/dom_template.xml +++ b/lago/providers/libvirt/templates/dom_template-base.xml.j2 @@ -1,6 +1,6 @@ - @NAME@ - @MEM_SIZE@ + {{ name }} + {{ mem_size }} 1 hvm @@ -13,7 +13,7 @@ - @QEMU_KVM@ + {{ qemu_kvm }} diff --git a/lago/providers/libvirt/templates/dom_template-el6.xml b/lago/providers/libvirt/templates/dom_template-el6.xml.j2 similarity index 91% rename from lago/providers/libvirt/templates/dom_template-el6.xml rename to lago/providers/libvirt/templates/dom_template-el6.xml.j2 index 9a7b08c1..0ac67ef5 100644 --- a/lago/providers/libvirt/templates/dom_template-el6.xml +++ b/lago/providers/libvirt/templates/dom_template-el6.xml.j2 @@ -1,6 +1,6 @@ - @NAME@ - @MEM_SIZE@ + {{ name }} + {{ mem_size }} 1 hvm @@ -13,7 +13,7 @@ - @QEMU_KVM@ + {{ qemu_kvm }} diff --git a/lago/providers/libvirt/utils.py b/lago/providers/libvirt/utils.py index 4c50bcc6..66b8c9eb 100644 --- a/lago/providers/libvirt/utils.py +++ b/lago/providers/libvirt/utils.py @@ -21,11 +21,15 @@ Utilities to help deal with the libvirt python bindings """ import libvirt -import pkg_resources import xmltodict import lxml.etree +import logging +import pkg_resources +from jinja2 import Environment, PackageLoader, TemplateNotFound from lago.config import config +LOGGER = logging.getLogger(__name__) + #: Mapping of domain statuses values to human readable strings DOMAIN_STATES = { libvirt.VIR_DOMAIN_NOSTATE: 'no state', @@ -100,6 +104,33 @@ def get_template(basename): ) +def get_domain_template(distro, libvirt_ver, **kwargs): + """ + Get a rendered Jinja2 domain template + + Args: + distro(str): domain distro + libvirt_ver(int): libvirt version + kwargs(dict): args for template render + + Returns: + str: rendered template + """ + env = Environment( + loader=PackageLoader('lago', 'providers/libvirt/templates'), + trim_blocks=True, + lstrip_blocks=True, + ) + + template_name = 'dom_template-{0}.xml.j2'.format(distro) + try: + template = env.get_template(template_name) + except TemplateNotFound: + LOGGER.debug('could not find template %s using default', template_name) + template = env.get_template('dom_template-base.xml.j2') + return template.render(libvirt_ver=libvirt_ver, **kwargs) + + def dict_to_xml(spec, full_document=False): """ Convert dict to XML diff --git a/lago/providers/libvirt/vm.py b/lago/providers/libvirt/vm.py index 6a1286e1..e0d10c2e 100644 --- a/lago/providers/libvirt/vm.py +++ b/lago/providers/libvirt/vm.py @@ -51,6 +51,7 @@ def __init__(self, vm): name=self.vm.virt_env.uuid + libvirt_url, libvirt_url=libvirt_url, ) + self._libvirt_ver = self.libvirt_con.getVersion() caps_raw_xml = self.libvirt_con.getCapabilities() self._caps = ET.fromstring(caps_raw_xml) @@ -367,19 +368,10 @@ def cpu_vendor(self): """ return self._cpu.vendor - def _load_domain_xml(self): - if self.vm.distro() == 'el6': - dom_raw_xml = libvirt_utils.get_template('dom_template-el6.xml') - else: - dom_raw_xml = libvirt_utils.get_template('dom_template.xml') - return dom_raw_xml - def _libvirt_name(self): return self.vm.virt_env.prefixed_name(self.vm.name()) - def _libvirt_xml(self): - dom_raw_xml = self._load_domain_xml() - + def _get_qemu_kvm_path(self): qemu_kvm_path = self._caps.findtext( "guest[os_type='hvm']/arch[@name='x86_64']/domain[@type='kvm']" "/emulator" @@ -393,19 +385,28 @@ def _libvirt_xml(self): ) if not qemu_kvm_path: - raise Exception('kvm executable not found') + raise utils.LagoException('kvm executable not found') + + return qemu_kvm_path - replacements = { - '@NAME@': self._libvirt_name(), - '@MEM_SIZE@': self.vm._spec.get('memory', 16 * 1024), - '@QEMU_KVM@': qemu_kvm_path, + def _load_xml(self): + + args = { + 'distro': self.vm.distro(), + 'libvirt_ver': self._libvirt_ver, + 'name': self._libvirt_name(), + 'mem_size': self.vm.spec.get('memory', 16 * 1024), + 'qemu_kvm': self._get_qemu_kvm_path() } - for key, val in replacements.items(): - dom_raw_xml = dom_raw_xml.replace(key, str(val), 1) + dom_raw_xml = libvirt_utils.get_domain_template(**args) parser = ET.XMLParser(remove_blank_text=True) - dom_xml = ET.fromstring(dom_raw_xml, parser) + return ET.fromstring(dom_raw_xml, parser) + + def _libvirt_xml(self): + + dom_xml = self._load_xml() for child in self._cpu: dom_xml.append(child) From daab62bb3cb1ed538d41014526186475a22aefef Mon Sep 17 00:00:00 2001 From: Nadav Goldin Date: Tue, 20 Jun 2017 20:31:09 +0300 Subject: [PATCH 2/3] libvirt: use /dev/random on libvirt versions <= 2002001 It appears that on older libvirt versions(such as 1.3 on Ubuntu16.04), /dev/urandom backend model is not supported. I could not trace in libvirt's changelog when that was changed, and I hope this is not a different issue specific to Ubuntu16.04. However, we know for sure that /dev/urandom works on libvirt version greater than 2002001. So here we add a simple condition on that. Signed-off-by: Nadav Goldin --- lago/providers/libvirt/templates/dom_template-base.xml.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lago/providers/libvirt/templates/dom_template-base.xml.j2 b/lago/providers/libvirt/templates/dom_template-base.xml.j2 index 860d2027..cc896f8d 100644 --- a/lago/providers/libvirt/templates/dom_template-base.xml.j2 +++ b/lago/providers/libvirt/templates/dom_template-base.xml.j2 @@ -27,7 +27,7 @@ - /dev/urandom + {{ '/dev/urandom' if libvirt_ver >= 2002001 else '/dev/random' }}
From ef7a94901d03a82a4faec186fc47dca7044efeab Mon Sep 17 00:00:00 2001 From: Nadav Goldin Date: Thu, 22 Jun 2017 16:15:29 +0300 Subject: [PATCH 3/3] CirrOS 0.3.5 support 1. Ensure network scripts are working(on older cirros other interfaces were just not configured properly). 2. Use same domain template as el6 with the normal serial console. Signed-off-by: Nadav Goldin --- .../templates/dom_template-cirros0.3.5.xml.j2 | 1 + lago/templates/sysprep-cirros0.3.5.j2 | 5 +++++ lago/templates/sysprep-macros.j2 | 12 ++++++++++++ 3 files changed, 18 insertions(+) create mode 120000 lago/providers/libvirt/templates/dom_template-cirros0.3.5.xml.j2 create mode 100644 lago/templates/sysprep-cirros0.3.5.j2 diff --git a/lago/providers/libvirt/templates/dom_template-cirros0.3.5.xml.j2 b/lago/providers/libvirt/templates/dom_template-cirros0.3.5.xml.j2 new file mode 120000 index 00000000..9038d619 --- /dev/null +++ b/lago/providers/libvirt/templates/dom_template-cirros0.3.5.xml.j2 @@ -0,0 +1 @@ +dom_template-el6.xml.j2 \ No newline at end of file diff --git a/lago/templates/sysprep-cirros0.3.5.j2 b/lago/templates/sysprep-cirros0.3.5.j2 new file mode 100644 index 00000000..7cda7d93 --- /dev/null +++ b/lago/templates/sysprep-cirros0.3.5.j2 @@ -0,0 +1,5 @@ +{% import 'sysprep-macros.j2' as macros %} +{% include 'sysprep-base.j2' %} + +{{ macros.iscsi(name=iscsi_name, hostname=hostname) }} +{{ macros.network_devices_cirros(mappings=mappings) }} diff --git a/lago/templates/sysprep-macros.j2 b/lago/templates/sysprep-macros.j2 index 73b89fd6..797fe4e6 100644 --- a/lago/templates/sysprep-macros.j2 +++ b/lago/templates/sysprep-macros.j2 @@ -37,3 +37,15 @@ source /etc/network/interfaces.d/*.cfg \ {% endfor %} {% endfilter %} {% endmacro %} + + +{% macro network_devices_cirros(mappings) %} +write /etc/network/interfaces:auto lo \ +iface lo inet loopback \ +{% filter dedent %} +{%+ for iface, mac in mappings.viewitems() %} + auto {{ iface }} \ + iface {{ iface }} inet dhcp \ +{% endfor %} +{% endfilter %} +{% endmacro %}