Commit e3ed5316 authored by Balazs Lecz's avatar Balazs Lecz
Browse files

LXC: Add cpu_mask hypervisor parameter



Also implement syntax checking.
Signed-off-by: default avatarBalazs Lecz <leczb@google.com>
Reviewed-by: default avatarIustin Pop <iustin@google.com>
parent 31155d60
......@@ -545,6 +545,7 @@ HV_SECURITY_DOMAIN = "security_domain"
HV_KVM_FLAG = "kvm_flag"
HV_VHOST_NET = "vhost_net"
HV_KVM_USE_CHROOT = "use_chroot"
HV_CPU_MASK = "cpu_mask"
HVS_PARAMETER_TYPES = {
HV_BOOT_ORDER: VTYPE_STRING,
......@@ -580,6 +581,7 @@ HVS_PARAMETER_TYPES = {
HV_KVM_FLAG: VTYPE_STRING,
HV_VHOST_NET: VTYPE_BOOL,
HV_KVM_USE_CHROOT: VTYPE_BOOL,
HV_CPU_MASK: VTYPE_STRING,
}
HVS_PARAMETERS = frozenset(HVS_PARAMETER_TYPES.keys())
......@@ -918,6 +920,7 @@ HVC_DEFAULTS = {
HV_INIT_SCRIPT: "/ganeti-chroot",
},
HT_LXC: {
HV_CPU_MASK: "",
},
}
......
......@@ -47,6 +47,14 @@ from ganeti import utils
from ganeti import constants
def _IsCpuMaskWellFormed(cpu_mask):
try:
cpu_list = utils.ParseCpuMask(cpu_mask)
except errors.ParseError, _:
return False
return isinstance(cpu_list, list) and len(cpu_list) > 0
# Read the BaseHypervisor.PARAMETERS docstring for the syntax of the
# _CHECK values
......@@ -58,6 +66,12 @@ _FILE_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
_DIR_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
os.path.isdir, "not found or not a directory")
# CPU mask must be well-formed
# TODO: implement node level check for the CPU mask
_CPU_MASK_CHECK = (_IsCpuMaskWellFormed,
"CPU mask definition is not well-formed",
None, None)
# nice wrappers for users
REQ_FILE_CHECK = (True, ) + _FILE_CHECK
OPT_FILE_CHECK = (False, ) + _FILE_CHECK
......@@ -65,6 +79,8 @@ REQ_DIR_CHECK = (True, ) + _DIR_CHECK
OPT_DIR_CHECK = (False, ) + _DIR_CHECK
NET_PORT_CHECK = (True, lambda x: x > 0 and x < 65535, "invalid port number",
None, None)
OPT_CPU_MASK_CHECK = (False, ) + _CPU_MASK_CHECK
REQ_CPU_MASK_CHECK = (True, ) + _CPU_MASK_CHECK
# no checks at all
NO_CHECK = (False, None, None, None, None)
......
......@@ -88,6 +88,7 @@ class LXCHypervisor(hv_base.BaseHypervisor):
_DIR_MODE = 0755
PARAMETERS = {
constants.HV_CPU_MASK: hv_base.OPT_CPU_MASK_CHECK,
}
def __init__(self):
......@@ -149,17 +150,8 @@ class LXCHypervisor(hv_base.BaseHypervisor):
except EnvironmentError, err:
raise errors.HypervisorError("Getting CPU list for instance"
" %s failed: %s" % (instance_name, err))
# cpuset.cpus format: comma-separated list of CPU ids
# or dash-separated id ranges
# Example: "0-1,3"
cpu_list = []
for range_def in cpus.split(","):
boundaries = range_def.split("-")
n_elements = len(boundaries)
lower = int(boundaries[0])
higher = int(boundaries[n_elements - 1])
cpu_list.extend(range(lower, higher + 1))
return cpu_list
return utils.ParseCpuMask(cpus)
def ListInstances(self):
"""Get the list of running instances.
......@@ -207,7 +199,9 @@ class LXCHypervisor(hv_base.BaseHypervisor):
return data
def _CreateConfigFile(self, instance, root_dir):
"""Create an lxc.conf file for an instance"""
"""Create an lxc.conf file for an instance.
"""
out = []
# hostname
out.append("lxc.utsname = %s" % instance.name)
......@@ -231,6 +225,19 @@ class LXCHypervisor(hv_base.BaseHypervisor):
# TODO: additional mounts, if we disable CAP_SYS_ADMIN
# CPUs
if instance.hvparams[constants.HV_CPU_MASK]:
cpu_list = utils.ParseCpuMask(instance.hvparams[constants.HV_CPU_MASK])
cpus_in_mask = len(cpu_list)
if cpus_in_mask != instance.beparams["vcpus"]:
raise errors.HypervisorError("Number of VCPUs (%d) doesn't match"
" the number of CPUs in the"
" cpu_mask (%d)" %
(instance.beparams["vcpus"],
cpus_in_mask))
out.append("lxc.cgroup.cpuset.cpus = %s" %
instance.hvparams[constants.HV_CPU_MASK])
# Device control
# deny direct device access
out.append("lxc.cgroup.devices.deny = a")
......@@ -261,8 +268,8 @@ class LXCHypervisor(hv_base.BaseHypervisor):
def StartInstance(self, instance, block_devices):
"""Start an instance.
For LCX, we try to mount the block device and execute 'lxc-start
start' (we use volatile containers).
For LCX, we try to mount the block device and execute 'lxc-start'.
We use volatile containers.
"""
root_dir = self._InstanceDir(instance.name)
......
......@@ -711,6 +711,24 @@
</listitem>
</varlistentry>
<varlistentry>
<term>cpu_mask</term>
<listitem>
<simpara>Valid for the LXC hypervisor.</simpara>
<simpara>The processes belonging to the given instance are
only scheduled on the specified CPUs.
</simpara>
<simpara>
The parameter format is a comma-separated list of CPU IDs or
CPU ID ranges. The ranges are defined by a lower and higher
boundary, separated by a dash. The boundaries are inclusive.
</simpara>
</listitem>
</varlistentry>
</variablelist>
</para>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment