X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/30e4e7419ba8ad4178afdd4731658c154bc59e78..c90d8e610bcd21701bbdd03409bd3aee4916919f:/lib/hypervisor/hv_chroot.py?ds=sidebyside diff --git a/lib/hypervisor/hv_chroot.py b/lib/hypervisor/hv_chroot.py index 954c922..3830f5f 100644 --- a/lib/hypervisor/hv_chroot.py +++ b/lib/hypervisor/hv_chroot.py @@ -29,8 +29,9 @@ import time import logging from ganeti import constants -from ganeti import errors # pylint: disable-msg=W0611 +from ganeti import errors # pylint: disable=W0611 from ganeti import utils +from ganeti import objects from ganeti.hypervisor import hv_base from ganeti.errors import HypervisorError @@ -67,11 +68,7 @@ class ChrootManager(hv_base.BaseHypervisor): def __init__(self): hv_base.BaseHypervisor.__init__(self) - if not os.path.exists(self._ROOT_DIR): - os.mkdir(self._ROOT_DIR) - if not os.path.isdir(self._ROOT_DIR): - raise HypervisorError("Needed path %s is not a directory" % - self._ROOT_DIR) + utils.EnsureDirs([(self._ROOT_DIR, constants.RUN_DIRS_MODE)]) @staticmethod def _IsDirLive(path): @@ -87,30 +84,29 @@ class ChrootManager(hv_base.BaseHypervisor): def _GetMountSubdirs(path): """Return the list of mountpoints under a given path. - This function is Linux-specific. + """ + 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. """ - #TODO(iustin): investigate and document non-linux options - #(e.g. via mount output) - data = [] - fh = open("/proc/mounts", "r") - try: - for line in fh: - _, mountpoint, _ = line.split(" ", 2) - if (mountpoint.startswith(path) and - mountpoint != path): - data.append(mountpoint) - finally: - fh.close() - data.sort(key=lambda x: x.count("/"), reverse=True) - return data + return utils.PathJoin(cls._ROOT_DIR, instance_name) def ListInstances(self): """Get the list of running instances. """ return [name for name in os.listdir(self._ROOT_DIR) - if self._IsDirLive(os.path.join(self._ROOT_DIR, name))] + if self._IsDirLive(utils.PathJoin(self._ROOT_DIR, name))] def GetInstanceInfo(self, instance_name): """Get instance properties. @@ -121,7 +117,7 @@ class ChrootManager(hv_base.BaseHypervisor): @return: (name, id, memory, vcpus, stat, times) """ - dir_name = "%s/%s" % (self._ROOT_DIR, instance_name) + dir_name = self._InstanceDir(instance_name) if not self._IsDirLive(dir_name): raise HypervisorError("Instance %s is not running" % instance_name) return (instance_name, 0, 0, 0, 0, 0) @@ -134,19 +130,19 @@ class ChrootManager(hv_base.BaseHypervisor): """ data = [] for file_name in os.listdir(self._ROOT_DIR): - path = os.path.join(self._ROOT_DIR, file_name) + path = utils.PathJoin(self._ROOT_DIR, file_name) if self._IsDirLive(path): data.append((file_name, 0, 0, 0, 0, 0)) return data - def StartInstance(self, instance, block_devices): + def StartInstance(self, instance, block_devices, startup_paused): """Start an instance. For the chroot manager, we try to mount the block device and execute '/ganeti-chroot start'. """ - root_dir = "%s/%s" % (self._ROOT_DIR, instance.name) + root_dir = self._InstanceDir(instance.name) if not os.path.exists(root_dir): try: os.mkdir(root_dir) @@ -170,7 +166,7 @@ class ChrootManager(hv_base.BaseHypervisor): raise HypervisorError("Can't run the chroot start script: %s" % result.output) - def StopInstance(self, instance, force=False, retry=False): + def StopInstance(self, instance, force=False, retry=False, name=None): """Stop an instance. This method has complicated cleanup tests, as we must: @@ -179,7 +175,10 @@ class ChrootManager(hv_base.BaseHypervisor): - finally unmount the instance dir """ - root_dir = "%s/%s" % (self._ROOT_DIR, instance.name) + if name is None: + name = instance.name + + root_dir = self._InstanceDir(name) if not os.path.exists(root_dir) or not self._IsDirLive(root_dir): return @@ -202,11 +201,23 @@ class ChrootManager(hv_base.BaseHypervisor): raise HypervisorError("Can't stop the processes using the chroot") return + def CleanupInstance(self, instance_name): + """Cleanup after a stopped instance + + """ + root_dir = self._InstanceDir(instance_name) + + if not os.path.exists(root_dir): + return + + if self._IsDirLive(root_dir): + raise HypervisorError("Processes are still using the chroot") + for mpath in self._GetMountSubdirs(root_dir): utils.RunCmd(["umount", mpath]) result = utils.RunCmd(["umount", root_dir]) - if result.failed and force: + if result.failed: msg = ("Processes still alive in the chroot: %s" % utils.RunCmd("fuser -vm %s" % root_dir).output) logging.error(msg) @@ -222,6 +233,18 @@ class ChrootManager(hv_base.BaseHypervisor): raise HypervisorError("The chroot manager doesn't implement the" " reboot functionality") + def BalloonInstanceMemory(self, instance, mem): + """Balloon an instance memory to a certain value. + + @type instance: L{objects.Instance} + @param instance: instance to be accepted + @type mem: int + @param mem: actual memory size to use for instance runtime + + """ + # Currently chroots don't have memory limits + pass + def GetNodeInfo(self): """Return information about the node. @@ -236,15 +259,21 @@ class ChrootManager(hv_base.BaseHypervisor): return self.GetLinuxNodeInfo() @classmethod - def GetShellCommandForConsole(cls, instance, hvparams, beparams): - """Return a command for connecting to the console of an instance. + def GetInstanceConsole(cls, instance, # pylint: disable=W0221 + hvparams, beparams, root_dir=None): + """Return information for connecting to the console of an instance. """ - root_dir = "%s/%s" % (cls._ROOT_DIR, instance.name) - if not os.path.ismount(root_dir): - raise HypervisorError("Instance %s is not running" % instance.name) + if root_dir is None: + root_dir = cls._InstanceDir(instance.name) + if not os.path.ismount(root_dir): + raise HypervisorError("Instance %s is not running" % instance.name) - return "chroot %s" % root_dir + return objects.InstanceConsole(instance=instance.name, + kind=constants.CONS_SSH, + host=instance.primary_node, + user=constants.GANETI_RUNAS, + command=["chroot", root_dir]) def Verify(self): """Verify the hypervisor. @@ -265,7 +294,7 @@ class ChrootManager(hv_base.BaseHypervisor): def MigrateInstance(self, instance, target, live): """Migrate an instance. - @type instance: L{object.Instance} + @type instance: L{objects.Instance} @param instance: the instance to be migrated @type target: string @param target: hostname (usually ip) of the target node @@ -274,3 +303,16 @@ class ChrootManager(hv_base.BaseHypervisor): """ raise HypervisorError("Migration not supported by the chroot hypervisor") + + def GetMigrationStatus(self, instance): + """Get the migration status + + @type instance: L{objects.Instance} + @param instance: the instance that is being migrated + @rtype: L{objects.MigrationStatus} + @return: the status of the current migration (one of + L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional + progress info that can be retrieved from the hypervisor + + """ + raise HypervisorError("Migration not supported by the chroot hypervisor")