Until now, virt-install supported only one seclabel and it was the first one libvirt reported in capabilities. This patch adds support for more of them and also adds a functionality to try to match the right one from the label given. This is done by checking how many colons the label has (precisely said, to how many parts it is split by the colons). --- v3: - Added support for testSecurity model in order to pass the test suite - Made some code more readable and wrapped under 80 columns v2: - Changed according to Cole's suggestions --- virtinst/CapabilitiesParser.py | 10 +++++--- virtinst/Seclabel.py | 52 ++++++++++++++++++++++++++++++++++++++---- virtinst/VirtualDisk.py | 11 ++++----- 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/virtinst/CapabilitiesParser.py b/virtinst/CapabilitiesParser.py index 4c1398c..6585a15 100644 --- a/virtinst/CapabilitiesParser.py +++ b/virtinst/CapabilitiesParser.py @@ -1,7 +1,7 @@ # # Some code for parsing libvirt's capabilities XML # -# Copyright 2007 Red Hat, Inc. +# Copyright 2007, 2012 Red Hat, Inc. # Mark McLoughlin <markmc@xxxxxxxxxx> # # This program is free software; you can redistribute it and/or modify @@ -260,11 +260,15 @@ class Host(object): def __init__(self, node=None): self.cpu = CPU() self.topology = None - self.secmodel = None + self.secmodels = [] if not node is None: self.parseXML(node) + def get_secmodel(self): + return self.secmodels and self.secmodels[0] or None + secmodel = property(get_secmodel) + # Back compat for CPU class def get_arch(self): return self.cpu.arch @@ -285,7 +289,7 @@ class Host(object): self.topology = Topology(child) if child.name == "secmodel": - self.secmodel = SecurityModel(child) + self.secmodels.append(SecurityModel(child)) if child.name == "cpu": self.cpu = CPU(child) diff --git a/virtinst/Seclabel.py b/virtinst/Seclabel.py index 7682664..5f69aa6 100644 --- a/virtinst/Seclabel.py +++ b/virtinst/Seclabel.py @@ -1,5 +1,5 @@ # -# Copyright 2010 Red Hat, Inc. +# Copyright 2010, 2012 Red Hat, Inc. # Cole Robinson <crobinso@xxxxxxxxxx> # # This program is free software; you can redistribute it and/or modify @@ -32,6 +32,14 @@ class Seclabel(XMLBuilderDomain.XMLBuilderDomain): MODEL_DEFAULT = "default" + SECLABEL_MODEL_TEST = "testSecurity" + SECLABEL_MODEL_SELINUX = "selinux" + SECLABEL_MODEL_DAC = "dac" + SECLABEL_MODEL_NONE = "none" + SECLABEL_MODELS = [ SECLABEL_MODEL_SELINUX, + SECLABEL_MODEL_DAC, + SECLABEL_MODEL_NONE ] + _dumpxml_xpath = "/domain/seclabel" def __init__(self, conn, parsexml=None, parsexmlnode=None, caps=None): XMLBuilderDomain.XMLBuilderDomain.__init__(self, conn, parsexml, @@ -50,7 +58,43 @@ class Seclabel(XMLBuilderDomain.XMLBuilderDomain): self.type = self.SECLABEL_TYPE_DEFAULT def _get_default_model(self): - return self._get_caps().host.secmodel.model + caps = self._get_caps() + if caps: + if (self.SECLABEL_MODEL_TEST in + [x.model for x in caps.host.secmodels]): + return self.SECLABEL_MODEL_TEST + + for model in self.SECLABEL_MODELS: + if model in [x.model for x in caps.host.secmodels]: + return model + raise RuntimeError("No supported model found in capabilities") + + def _guess_secmodel(self, label, imagelabel): + # We always want the testSecurity model when running tests + caps = self._get_caps() + if (caps and + self.SECLABEL_MODEL_TEST in + [x.model for x in caps.host.secmodels]): + return self.SECLABEL_MODEL_TEST + + if not label and not imagelabel: + return self._get_default_model() + + lab_len = imglab_len = None + if label: + lab_len = min(3, len(label.split(':'))) + if imagelabel: + imglab_len = min(3, len(imagelabel.split(':'))) + if lab_len and imglab_len and lab_len != imglab_len: + raise ValueError("Label and Imagelabel are incompatible") + + lab_len = lab_len or imglab_len + if lab_len == 3: + return self.SECLABEL_MODEL_SELINUX + elif lab_len == 2: + return self.SECLABEL_MODEL_DAC + else: + raise ValueError("Unknown model type for label '%s'" % self.label) def get_type(self): return self._type @@ -100,8 +144,6 @@ class Seclabel(XMLBuilderDomain.XMLBuilderDomain): typ = self.type relabel = self.relabel - if model == self.MODEL_DEFAULT: - model = self._get_default_model() if typ == self.SECLABEL_TYPE_DEFAULT: typ = self.SECLABEL_TYPE_DYNAMIC @@ -113,6 +155,8 @@ class Seclabel(XMLBuilderDomain.XMLBuilderDomain): raise RuntimeError("A label must be specified for static " "security type.") + if model == self.MODEL_DEFAULT: + model = self._guess_secmodel(self.label, self.imagelabel) label_xml = "" xml = " <seclabel type='%s' model='%s'" % (typ, model) diff --git a/virtinst/VirtualDisk.py b/virtinst/VirtualDisk.py index 2eeb43d..14986be 100644 --- a/virtinst/VirtualDisk.py +++ b/virtinst/VirtualDisk.py @@ -1,7 +1,7 @@ # # Classes for building disk device xml # -# Copyright 2006-2008 Red Hat, Inc. +# Copyright 2006-2008, 2012 Red Hat, Inc. # Jeremy Katz <katzj@xxxxxxxxxx> # # This program is free software; you can redistribute it and/or modify @@ -1620,11 +1620,10 @@ class VirtualDisk(VirtualDevice): for selinux commands """ caps = self._get_caps() - if (not caps and False): - #caps.host.secmodel is None or - #caps.host.secmodel.model != "selinux"): - # XXX: Libvirt support isn't strictly required, but all the - # our label guesses are built with svirt in mind + if not caps: + return False + + elif "selinux" not in [x.model for x in caps.host.secmodels]: return False elif self.is_remote(): -- 1.8.0 _______________________________________________ virt-tools-list mailing list virt-tools-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/virt-tools-list