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 84% rename from lago/providers/libvirt/templates/dom_template.xml rename to lago/providers/libvirt/templates/dom_template-base.xml.j2 index 27d16509..cc896f8d 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 }} @@ -27,7 +27,7 @@ - /dev/urandom + {{ '/dev/urandom' if libvirt_ver >= 2002001 else '/dev/random' }}
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/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) 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 %}