コード例 #1
0
def _IsCpuMaskWellFormed(cpu_mask):
  """Verifies if the given single CPU mask is valid

  The single CPU mask should be in the form "a,b,c,d", where each
  letter is a positive number or range.

  """
  try:
    cpu_list = utils.ParseCpuMask(cpu_mask)
  except errors.ParseError, _:
    return False
コード例 #2
0
    def _GetCgroupCpuList(cls, instance_name):
        """Return the list of CPU ids for an instance.

    """
        try:
            cpumask = cls._GetCgroupInstanceValue(instance_name, "cpuset.cpus")
        except EnvironmentError as err:
            raise errors.HypervisorError("Getting CPU list for instance"
                                         " %s failed: %s" %
                                         (instance_name, err))

        return utils.ParseCpuMask(cpumask)
コード例 #3
0
 def testWellFormed(self):
     self.assertEqual(utils.ParseCpuMask(""), [])
     self.assertEqual(utils.ParseCpuMask("1"), [1])
     self.assertEqual(utils.ParseCpuMask("0-2,4,5-5"), [0, 1, 2, 4, 5])
コード例 #4
0
    def _CreateConfigFile(self, instance, sda_dev_path):
        """Create an lxc.conf file for an instance.

    """
        out = []
        # hostname
        out.append("lxc.utsname = %s" % instance.name)

        # separate pseudo-TTY instances
        out.append("lxc.pts = 255")
        # standard TTYs
        num_ttys = instance.hvparams[constants.HV_LXC_NUM_TTYS]
        if num_ttys:  # if it is the number greater than 0
            out.append("lxc.tty = %s" % num_ttys)

        # console log file
        # After the following patch was applied, we lost the console log file output
        # until the lxc.console.logfile parameter was introduced in 1.0.6.
        # https://
        # lists.linuxcontainers.org/pipermail/lxc-devel/2014-March/008470.html
        lxc_version = self._GetLXCVersionFromCmd("lxc-start")
        if lxc_version >= LXCVersion("1.0.6"):
            console_log_path = self._InstanceConsoleLogFilePath(instance.name)
            _CreateBlankFile(console_log_path, constants.SECURE_FILE_MODE)
            out.append("lxc.console.logfile = %s" % console_log_path)
        else:
            logging.warn(
                "Console log file is not supported in LXC version %s,"
                " disabling.", lxc_version)

        # root FS
        out.append("lxc.rootfs = %s" % sda_dev_path)

        # Necessary file systems
        out.append("lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0")
        out.append("lxc.mount.entry = sysfs sys sysfs defaults 0 0")

        # 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])

        # Memory
        out.append("lxc.cgroup.memory.limit_in_bytes = %dM" %
                   instance.beparams[constants.BE_MAXMEM])
        if LXCHypervisor._IsCgroupParameterPresent(self._MEMORY_SWAP_PARAMETER,
                                                   instance.hvparams):
            out.append("lxc.cgroup.memory.memsw.limit_in_bytes = %dM" %
                       instance.beparams[constants.BE_MAXMEM])

        # Device control
        # deny direct device access
        out.append("lxc.cgroup.devices.deny = a")
        dev_specs = instance.hvparams[constants.HV_LXC_DEVICES]
        for dev_spec in dev_specs.split(","):
            out.append("lxc.cgroup.devices.allow = %s" % dev_spec)

        # Networking
        for idx, nic in enumerate(instance.nics):
            out.append("# NIC %d" % idx)
            mode = nic.nicparams[constants.NIC_MODE]
            link = nic.nicparams[constants.NIC_LINK]
            if mode == constants.NIC_MODE_BRIDGED:
                out.append("lxc.network.type = veth")
                out.append("lxc.network.link = %s" % link)
            else:
                raise errors.HypervisorError(
                    "LXC hypervisor only supports"
                    " bridged mode (NIC %d has mode %s)" % (idx, mode))
            out.append("lxc.network.hwaddr = %s" % nic.mac)
            out.append("lxc.network.flags = up")

        # Capabilities
        for cap in self._GetInstanceDropCapabilities(instance.hvparams):
            out.append("lxc.cap.drop = %s" % cap)

        # Extra config
        # TODO: Currently a configuration parameter that includes comma
        # in its value can't be added via this parameter.
        # Make this parameter able to read from a file once the
        # "parameter from a file" feature added.
        extra_configs = instance.hvparams[constants.HV_LXC_EXTRA_CONFIG]
        if extra_configs:
            out.append("# User defined configs")
            out.extend(extra_configs.split(","))

        return "\n".join(out) + "\n"
コード例 #5
0
class LXCHypervisor(hv_base.BaseHypervisor):
    """LXC-based virtualization.

  TODO:
    - move hardcoded parameters into hypervisor parameters, once we
      have the container-parameter support

  Problems/issues:
    - LXC is very temperamental; in daemon mode, it succeeds or fails
      in launching the instance silently, without any error
      indication, and when failing it can leave network interfaces
      around, and future successful startups will list the instance
      twice

  """
    _ROOT_DIR = pathutils.RUN_DIR + "/lxc"
    _DEVS = [
        "c 1:3",  # /dev/null
        "c 1:5",  # /dev/zero
        "c 1:7",  # /dev/full
        "c 1:8",  # /dev/random
        "c 1:9",  # /dev/urandom
        "c 1:10",  # /dev/aio
        "c 5:0",  # /dev/tty
        "c 5:1",  # /dev/console
        "c 5:2",  # /dev/ptmx
        "c 136:*",  # first block of Unix98 PTY slaves
    ]
    _DENIED_CAPABILITIES = [
        "mac_override",  # Allow MAC configuration or state changes
        # TODO: remove sys_admin too, for safety
        #"sys_admin",       # Perform  a range of system administration operations
        "sys_boot",  # Use reboot(2) and kexec_load(2)
        "sys_module",  # Load  and  unload kernel modules
        "sys_time",  # Set  system  clock, set real-time (hardware) clock
    ]
    _DIR_MODE = 0755

    PARAMETERS = {
        constants.HV_CPU_MASK: hv_base.OPT_CPU_MASK_CHECK,
    }

    def __init__(self):
        hv_base.BaseHypervisor.__init__(self)
        utils.EnsureDirs([(self._ROOT_DIR, self._DIR_MODE)])

    @staticmethod
    def _GetMountSubdirs(path):
        """Return the list of mountpoints under a given path.

    """
        result = []
        for _, mountpoint, _, _ in utils.GetMounts():
            if (mountpoint.startswith(path) and mountpoint != path):
                result.append(mountpoint)

        result.sort(key=lambda x: x.count("/"), reverse=True)
        return result

    @classmethod
    def _InstanceDir(cls, instance_name):
        """Return the root directory for an instance.

    """
        return utils.PathJoin(cls._ROOT_DIR, instance_name)

    @classmethod
    def _InstanceConfFile(cls, instance_name):
        """Return the configuration file for an instance.

    """
        return utils.PathJoin(cls._ROOT_DIR, instance_name + ".conf")

    @classmethod
    def _InstanceLogFile(cls, instance_name):
        """Return the log file for an instance.

    """
        return utils.PathJoin(cls._ROOT_DIR, instance_name + ".log")

    @classmethod
    def _GetCgroupMountPoint(cls):
        for _, mountpoint, fstype, _ in utils.GetMounts():
            if fstype == "cgroup":
                return mountpoint
        raise errors.HypervisorError("The cgroup filesystem is not mounted")

    @classmethod
    def _GetCgroupCpuList(cls, instance_name):
        """Return the list of CPU ids for an instance.

    """
        cgroup = cls._GetCgroupMountPoint()
        try:
            cpus = utils.ReadFile(
                utils.PathJoin(cgroup, 'lxc', instance_name, "cpuset.cpus"))
        except EnvironmentError, err:
            raise errors.HypervisorError("Getting CPU list for instance"
                                         " %s failed: %s" %
                                         (instance_name, err))

        return utils.ParseCpuMask(cpus)
コード例 #6
0
                            data="",
                            mode=constants.SECURE_FILE_MODE)
        except EnvironmentError, err:
            raise errors.HypervisorError("Creating console log file %s for"
                                         " instance %s failed: %s" %
                                         (console_log, instance.name, err))
        out.append("lxc.console = %s" % console_log)

        # root FS
        out.append("lxc.rootfs = %s" % root_dir)

        # 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])

        # Memory
        # Conditionally enable, memory resource controller might be disabled
        cgroup = self._GetCgroupMountPoint()
        if os.path.exists(utils.PathJoin(cgroup, 'memory.limit_in_bytes')):
            out.append("lxc.cgroup.memory.limit_in_bytes = %dM" %
コード例 #7
0
ファイル: hv_lxc.py プロジェクト: yiannist/ganeti
        return os.path.exists(param_path)

    @classmethod
    def _GetCgroupCpuList(cls, instance_name):
        """Return the list of CPU ids for an instance.

    """
        try:
            cpumask = cls._GetCgroupInstanceValue(instance_name, "cpuset.cpus")
        except EnvironmentError, err:
            raise errors.HypervisorError("Getting CPU list for instance"
                                         " %s failed: %s" %
                                         (instance_name, err))

        return utils.ParseCpuMask(cpumask)

    @classmethod
    def _GetCgroupCpuUsage(cls, instance_name):
        """Return the CPU usage of an instance.

    """
        try:
            cputime_ns = cls._GetCgroupInstanceValue(instance_name,
                                                     "cpuacct.usage")
        except EnvironmentError, err:
            raise HypervisorError("Failed to get the cpu usage of %s: %s" %
                                  (instance_name, err))

        return float(cputime_ns) / 10**9  # nano secs to float secs