[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] acm: Some fixes to the Xend ACM management code



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1186672496 -3600
# Node ID f0298301ba8b34ac3e5470cf953a3591f7730d26
# Parent  3876b4e7cc0a4d0404ca01fce0879d85cb98d213
acm: Some fixes to the Xend ACM management code

- prevent vlans from being relabeled when they are in use by the
  current policy
- fix problems when doing an update of the policy and the name of the
policy changes while doing that
- refactor code that has to take into consideration that unlabeled
domains may be defined using the label __UNLABELED__
- make 'xm list --label' show the complete label of a domain

Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx>
---
 tools/python/xen/util/acmpolicy.py      |   21 +++++++---
 tools/python/xen/util/security.py       |   64 ++++++++++++++++++++++++--------
 tools/python/xen/xend/XendDomainInfo.py |   26 ++++++++++---
 tools/python/xen/xm/main.py             |    2 -
 4 files changed, 84 insertions(+), 29 deletions(-)

diff -r 3876b4e7cc0a -r f0298301ba8b tools/python/xen/util/acmpolicy.py
--- a/tools/python/xen/util/acmpolicy.py        Thu Aug 09 16:02:33 2007 +0100
+++ b/tools/python/xen/util/acmpolicy.py        Thu Aug 09 16:14:56 2007 +0100
@@ -191,20 +191,21 @@ class ACMPolicy(XSPolicy):
                  acmpol_old.policy_get_virtualmachinelabel_names_sorted()
             del_array = ""
             chg_array = ""
+
             for o in oldvmnames:
                 if o not in newvmnames:
-                    old_idx = oldvmnames.index(o) + 1 # for _NULL_LABEL_
+                    old_idx = oldvmnames.index(o)
                     if vmlabel_map.has_key(o):
                         #not a deletion, but a renaming
                         new = vmlabel_map[o]
-                        new_idx = newvmnames.index(new) + 1 # for _NULL_LABEL_
+                        new_idx = newvmnames.index(new)
                         chg_array += struct.pack("ii", old_idx, new_idx)
                     else:
                         del_array += struct.pack("i", old_idx)
             for v in newvmnames:
                 if v in oldvmnames:
-                    old_idx = oldvmnames.index(v) + 1 # for _NULL_LABEL_
-                    new_idx = newvmnames.index(v) + 1 # for _NULL_LABEL_
+                    old_idx = oldvmnames.index(v)
+                    new_idx = newvmnames.index(v)
                     if old_idx != new_idx:
                         chg_array += struct.pack("ii", old_idx, new_idx)
 
@@ -348,7 +349,7 @@ class ACMPolicy(XSPolicy):
         ssidref = xsconstants.INVALID_SSIDREF
         names = self.policy_get_virtualmachinelabel_names_sorted()
         try:
-            vmidx = names.index(vm_label) + 1 # for _NULL_LABEL_
+            vmidx = names.index(vm_label)
             ssidref = (vmidx << 16) | vmidx
         except:
             pass
@@ -618,6 +619,9 @@ class ACMPolicy(XSPolicy):
         vmnames.remove(bootstrap)
         vmnames.sort()
         vmnames.insert(0, bootstrap)
+        if ACM_LABEL_UNLABELED in vmnames:
+            vmnames.remove(ACM_LABEL_UNLABELED)
+            vmnames.insert(0, ACM_LABEL_UNLABELED)
         return vmnames
 
     def policy_get_virtualmachinelabel_names_sorted(self):
@@ -625,7 +629,10 @@ class ACMPolicy(XSPolicy):
             label will be the first one in that list, followed
             by an alphabetically sorted list of VM label names """
         vmnames = self.policy_get_virtualmachinelabel_names()
-        return self.policy_sort_virtualmachinelabel_names(vmnames)
+        res = self.policy_sort_virtualmachinelabel_names(vmnames)
+        if res[0] != ACM_LABEL_UNLABELED:
+            res.insert(0, ACM_LABEL_UNLABELED)
+        return res
 
     def policy_get_virtualmachinelabels(self):
         """ Get a list of all virtual machine labels in this policy """
@@ -906,7 +913,7 @@ class ACMPolicy(XSPolicy):
             allvmtypes = self.policy_get_virtualmachinelabel_names_sorted()
         except:
             return None
-        return allvmtypes[chwall_ref-1] # skip _NULL_LABEL_
+        return allvmtypes[chwall_ref]
 
     def policy_get_domain_label_formatted(self, domid):
         label = self.policy_get_domain_label(domid)
diff -r 3876b4e7cc0a -r f0298301ba8b tools/python/xen/util/security.py
--- a/tools/python/xen/util/security.py Thu Aug 09 16:02:33 2007 +0100
+++ b/tools/python/xen/util/security.py Thu Aug 09 16:14:56 2007 +0100
@@ -838,13 +838,28 @@ def set_resource_label_xapi(resource, re
 
 
 def is_resource_in_use(resource):
-    """ Investigate all running domains whether they use this device """
+    """
+       Domain-0 'owns' resources of type 'VLAN', the rest are owned by
+       the guests.
+    """
     from xen.xend import XendDomain
-    dominfos = XendDomain.instance().list('all')
     lst = []
-    for dominfo in dominfos:
-        if is_resource_in_use_by_dom(dominfo, resource):
-            lst.append(dominfo)
+    if resource.startswith('vlan'):
+        from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
+        curpol = XSPolicyAdminInstance().get_loaded_policy()
+        policytype, label, policy = get_res_label(resource)
+        if curpol and \
+           policytype == xsconstants.ACM_POLICY_ID and \
+           policy == curpol.get_name() and \
+           label in curpol.policy_get_resourcelabel_names():
+            # VLAN is in use.
+            lst.append(XendDomain.instance().
+                         get_vm_by_uuid(XendDomain.DOM0_UUID))
+    else:
+        dominfos = XendDomain.instance().list('all')
+        for dominfo in dominfos:
+            if is_resource_in_use_by_dom(dominfo, resource):
+                lst.append(dominfo)
     return lst
 
 def devices_equal(res1, res2, mustexist=True):
@@ -892,6 +907,10 @@ def get_domain_resources(dominfo):
             if sec_lab:
                 resources[typ].append(sec_lab)
             else:
+                # !!! This should really get the label of the domain
+                # or at least a resource label that has the same STE type
+                # as the domain has
+                from xen.util.acmpolicy import ACM_LABEL_UNLABELED
                 resources[typ].append("%s:%s:%s" %
                                       (xsconstants.ACM_POLICY_ID,
                                        active_policy,
@@ -924,7 +943,8 @@ def resources_compatible_with_vmlabel(xs
 
 
 def __resources_compatible_with_vmlabel(xspol, dominfo, vmlabel,
-                                        access_control):
+                                        access_control,
+                                        is_policy_update=False):
     """
         Check whether the resources' labels are compatible with the
         given VM label. The access_control parameter provides a
@@ -955,15 +975,23 @@ def __resources_compatible_with_vmlabel(
         elif key in [ 'vif' ]:
             for xapi_label in value:
                 label = xapi_label.split(":")
-                if not collect_labels(reslabels, label, polname):
-                    return False
+                from xen.util.acmpolicy import ACM_LABEL_UNLABELED
+                if not (is_policy_update and \
+                        label[2] == ACM_LABEL_UNLABELED):
+                    if not collect_labels(reslabels, label, polname):
+                        return False
         else:
             log.error("Unhandled device type: %s" % key)
             return False
 
     # Check that all resource labes have a common STE type with the
     # vmlabel
-    rc = xspol.policy_check_vmlabel_against_reslabels(vmlabel, reslabels)
+    if len(reslabels) > 0:
+        rc = xspol.policy_check_vmlabel_against_reslabels(vmlabel, reslabels)
+    else:
+        rc = True
+    log.info("vmlabel=%s, reslabels=%s, rc=%s" %
+             (vmlabel, reslabels, str(rc)))
     return rc;
 
 def set_resource_label(resource, policytype, policyref, reslabel, \
@@ -1234,11 +1262,12 @@ def change_acm_policy(bin_pol, del_array
                 compatible = __resources_compatible_with_vmlabel(new_acmpol,
                                                       dominfo,
                                                       new_vmlabel,
-                                                      access_control)
+                                                      access_control,
+                                                      is_policy_update=True)
                 log.info("Domain %s with new label '%s' can access its "
                          "resources? : %s" %
                          (name, new_vmlabel, str(compatible)))
-                log.info("VM labels in new domain: %s" %
+                log.info("VM labels in new policy: %s" %
                          new_acmpol.policy_get_virtualmachinelabel_names())
                 if not compatible:
                     return (-xsconstants.XSERR_RESOURCE_ACCESS, "")
@@ -1252,11 +1281,16 @@ def change_acm_policy(bin_pol, del_array
                 sec_lab, new_seclab = labels
                 if sec_lab != new_seclab:
                     log.info("Updating domain %s to new label '%s'." % \
-                             (sec_lab, new_seclab))
+                             (dominfo.getName(), new_seclab))
                     # This better be working!
-                    dominfo.set_security_label(new_seclab,
-                                               sec_lab,
-                                               new_acmpol)
+                    res = dominfo.set_security_label(new_seclab,
+                                                     sec_lab,
+                                                     new_acmpol,
+                                                     cur_acmpol)
+                    if res[0] != xsconstants.XSERR_SUCCESS:
+                        log.info("ERROR: Could not chg label on domain %s: %s" 
%
+                                 (dominfo.getName(),
+                                  xsconstants.xserr2string(-int(res[0]))))
     finally:
         log.info("----------------------------------------------")
         mapfile_unlock()
diff -r 3876b4e7cc0a -r f0298301ba8b tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Thu Aug 09 16:02:33 2007 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py   Thu Aug 09 16:14:56 2007 +0100
@@ -2187,11 +2187,18 @@ class XendDomainInfo:
         return self.metrics.get_uuid();
 
 
-    def get_security_label(self):
+    def get_security_label(self, xspol=None):
+        """
+           Get the security label of a domain
+           @param xspol   The policy to use when converting the ssid into
+                          a label; only to be passed during the updating
+                          of the policy
+        """
         domid = self.getDomid()
 
-        from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
-        xspol = XSPolicyAdminInstance().get_loaded_policy()
+        if not xspol:
+            from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
+            xspol = XSPolicyAdminInstance().get_loaded_policy()
 
         if domid == 0:
             if xspol:
@@ -2202,7 +2209,8 @@ class XendDomainInfo:
             label = self.info.get('security_label', '')
         return label
 
-    def set_security_label(self, seclab, old_seclab, xspol=None):
+    def set_security_label(self, seclab, old_seclab, xspol=None,
+                           xspol_old=None):
         """
            Set the security label of a domain from its old to
            a new value.
@@ -2213,6 +2221,8 @@ class XendDomainInfo:
            @param xspol   An optional policy under which this
                           update should be done. If not given,
                           then the current active policy is used.
+           @param xspol_old The old policy; only to be passed during
+                           the updating of a policy
            @return Returns return code, a string with errors from
                    the hypervisor's operation, old label of the
                    domain
@@ -2223,6 +2233,7 @@ class XendDomainInfo:
         new_ssidref = 0
         domid = self.getDomid()
         res_labels = None
+        is_policy_update = (xspol_old != None)
 
         from xen.xend.XendXSPolicyAdmin import XSPolicyAdminInstance
         from xen.util import xsconstants
@@ -2276,13 +2287,16 @@ class XendDomainInfo:
 
                 # Check that all used resources are accessible under the
                 # new label
-                if not security.resources_compatible_with_vmlabel(xspol,
+                if not is_policy_update and \
+                   not security.resources_compatible_with_vmlabel(xspol,
                           self, label):
                     return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
 
                 #Check label against expected one.
-                old_label = self.get_security_label()
+                old_label = self.get_security_label(xspol_old)
                 if old_label != old_seclab:
+                    log.info("old_label != old_seclab: %s != %s" %
+                             (old_label, old_seclab))
                     return (-xsconstants.XSERR_BAD_LABEL, "", "", 0)
 
                 # relabel domain in the hypervisor
diff -r 3876b4e7cc0a -r f0298301ba8b tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py       Thu Aug 09 16:02:33 2007 +0100
+++ b/tools/python/xen/xm/main.py       Thu Aug 09 16:14:56 2007 +0100
@@ -876,7 +876,7 @@ def parse_doms_info(info):
     if len(tmp) != 3:
         seclabel = ""
     else:
-        seclabel = tmp[2]
+        seclabel = security_label
     parsed_info['seclabel'] = seclabel
 
     if serverType == SERVER_XEN_API:

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.