mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
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@us.ibm.com>
This commit is contained in:
1 parent
834e828123
commit
db79ac4259
4 files changed
+84
-29
No files matched your search
@@ -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)
|
||||
|
||||
@@ -838,13 +838,28 @@ def set_resource_label_xapi(resource, reslabel_xapi, oldlabel_xapi):
|
||||
|
||||
|
||||
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(xspol, dominfo, vmlabel):
|
||||
|
||||
|
||||
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(xspol, dominfo, 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, chg_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, chg_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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||