Revision 84c08e4e lib/hypervisor/hv_kvm.py
b/lib/hypervisor/hv_kvm.py | ||
---|---|---|
23 | 23 |
|
24 | 24 |
""" |
25 | 25 |
|
26 |
import errno |
|
26 | 27 |
import os |
27 | 28 |
import os.path |
28 | 29 |
import re |
... | ... | |
51 | 52 |
_UIDS_DIR = _ROOT_DIR + "/uid" # contains instances reserved uids |
52 | 53 |
_CTRL_DIR = _ROOT_DIR + "/ctrl" # contains instances control sockets |
53 | 54 |
_CONF_DIR = _ROOT_DIR + "/conf" # contains instances startup data |
54 |
_DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR] |
|
55 |
# KVM instances with chroot enabled are started in empty chroot directories. |
|
56 |
_CHROOT_DIR = _ROOT_DIR + "/chroot" # for empty chroot directories |
|
57 |
# After an instance is stopped, its chroot directory is removed. |
|
58 |
# If the chroot directory is not empty, it can't be removed. |
|
59 |
# A non-empty chroot directory indicates a possible security incident. |
|
60 |
# To support forensics, the non-empty chroot directory is quarantined in |
|
61 |
# a separate directory, called 'chroot-quarantine'. |
|
62 |
_CHROOT_QUARANTINE_DIR = _ROOT_DIR + "/chroot-quarantine" |
|
63 |
_DIRS = [_ROOT_DIR, _PIDS_DIR, _UIDS_DIR, _CTRL_DIR, _CONF_DIR, |
|
64 |
_CHROOT_DIR, _CHROOT_QUARANTINE_DIR] |
|
55 | 65 |
|
56 | 66 |
PARAMETERS = { |
57 | 67 |
constants.HV_KERNEL_PATH: hv_base.OPT_FILE_CHECK, |
... | ... | |
87 | 97 |
constants.HV_KVM_FLAG: |
88 | 98 |
hv_base.ParamInSet(False, constants.HT_KVM_FLAG_VALUES), |
89 | 99 |
constants.HV_VHOST_NET: hv_base.NO_CHECK, |
100 |
constants.HV_KVM_USE_CHROOT: hv_base.NO_CHECK, |
|
90 | 101 |
} |
91 | 102 |
|
92 | 103 |
_MIGRATION_STATUS_RE = re.compile('Migration\s+status:\s+(\w+)', |
... | ... | |
230 | 241 |
return utils.PathJoin(cls._CONF_DIR, "%s.runtime" % instance_name) |
231 | 242 |
|
232 | 243 |
@classmethod |
244 |
def _InstanceChrootDir(cls, instance_name): |
|
245 |
"""Returns the name of the KVM chroot dir of the instance |
|
246 |
|
|
247 |
""" |
|
248 |
return utils.PathJoin(cls._CHROOT_DIR, instance_name) |
|
249 |
|
|
250 |
@classmethod |
|
233 | 251 |
def _TryReadUidFile(cls, uid_file): |
234 | 252 |
"""Try to read a uid file |
235 | 253 |
|
... | ... | |
246 | 264 |
|
247 | 265 |
@classmethod |
248 | 266 |
def _RemoveInstanceRuntimeFiles(cls, pidfile, instance_name): |
249 |
"""Removes an instance's rutime sockets/files. |
|
267 |
"""Removes an instance's rutime sockets/files/dirs.
|
|
250 | 268 |
|
251 | 269 |
""" |
252 | 270 |
utils.RemoveFile(pidfile) |
... | ... | |
258 | 276 |
utils.RemoveFile(uid_file) |
259 | 277 |
if uid is not None: |
260 | 278 |
uidpool.ReleaseUid(uid) |
279 |
try: |
|
280 |
chroot_dir = cls._InstanceChrootDir(instance_name) |
|
281 |
utils.RemoveDir(chroot_dir) |
|
282 |
except OSError, err: |
|
283 |
if err.errno == errno.ENOTEMPTY: |
|
284 |
# The chroot directory is expected to be empty, but it isn't. |
|
285 |
new_chroot_dir = tempfile.mkdtemp(dir=cls._CHROOT_QUARANTINE_DIR, |
|
286 |
prefix="%s-%s-" % |
|
287 |
(instance_name, |
|
288 |
utils.TimestampForFilename())) |
|
289 |
logging.warning("The chroot directory of instance %s can not be" |
|
290 |
" removed as it is not empty. Moving it to the" |
|
291 |
" quarantine instead. Please investigate the" |
|
292 |
" contents (%s) and clean up manually", |
|
293 |
instance_name, new_chroot_dir) |
|
294 |
utils.RenameFile(chroot_dir, new_chroot_dir) |
|
295 |
else: |
|
296 |
raise |
|
261 | 297 |
|
262 | 298 |
def _WriteNetScript(self, instance, seq, nic): |
263 | 299 |
"""Write a script to connect a net interface to the proper bridge. |
... | ... | |
529 | 565 |
if hvp[constants.HV_USE_LOCALTIME]: |
530 | 566 |
kvm_cmd.extend(['-localtime']) |
531 | 567 |
|
568 |
if hvp[constants.HV_KVM_USE_CHROOT]: |
|
569 |
kvm_cmd.extend(['-chroot', self._InstanceChrootDir(instance.name)]) |
|
570 |
|
|
532 | 571 |
# Save the current instance nics, but defer their expansion as parameters, |
533 | 572 |
# as we'll need to generate executable temp files for them. |
534 | 573 |
kvm_nics = instance.nics |
... | ... | |
644 | 683 |
raise errors.HypervisorError("Failed to open VNC password file %s: %s" |
645 | 684 |
% (vnc_pwd_file, err)) |
646 | 685 |
|
686 |
if hvp[constants.HV_KVM_USE_CHROOT]: |
|
687 |
utils.EnsureDirs([(self._InstanceChrootDir(name), |
|
688 |
constants.SECURE_DIR_MODE)]) |
|
689 |
|
|
647 | 690 |
if security_model == constants.HT_SM_POOL: |
648 | 691 |
ss = ssconf.SimpleStore() |
649 | 692 |
uid_pool = uidpool.ParseUidPool(ss.GetUidPool(), separator="\n") |
Also available in: Unified diff