[Pkg-ganeti-devel] [ganeti] 71/165: Add a separate function for running helper VMs
Apollon Oikonomopoulos
apoikos at moszumanska.debian.org
Tue Aug 11 13:53:14 UTC 2015
This is an automated email from the git hooks/post-receive script.
apoikos pushed a commit to branch master
in repository ganeti.
commit e8c47afa161a0df3ddd57b291462b99a1bfe27d2
Author: Petr Pudlak <pudlak at google.com>
Date: Tue Nov 11 10:48:26 2014 +0100
Add a separate function for running helper VMs
The code for creating an instance and running a zeroing VM was almost
the same. The new generic function will be also used for other untrusted
operations such as export and import.
Signed-off-by: Petr Pudlak <pudlak at google.com>
Reviewed-by: Hrvoje Ribicic <riba at google.com>
---
Makefile.am | 1 +
lib/cmdlib/backup.py | 57 +++----------
lib/cmdlib/instance_create.py | 51 +++---------
lib/cmdlib/instance_helpervm.py | 172 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 191 insertions(+), 90 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 7c2d1a9..2be3981 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -489,6 +489,7 @@ cmdlib_PYTHON = \
lib/cmdlib/group.py \
lib/cmdlib/instance.py \
lib/cmdlib/instance_create.py \
+ lib/cmdlib/instance_helpervm.py \
lib/cmdlib/instance_migration.py \
lib/cmdlib/instance_operation.py \
lib/cmdlib/instance_query.py \
diff --git a/lib/cmdlib/backup.py b/lib/cmdlib/backup.py
index 3486291..84ceecf 100644
--- a/lib/cmdlib/backup.py
+++ b/lib/cmdlib/backup.py
@@ -39,13 +39,12 @@ from ganeti import errors
from ganeti import locking
from ganeti import masterd
from ganeti import utils
-from ganeti.utils import retry
from ganeti.cmdlib.base import NoHooksLU, LogicalUnit
-from ganeti.cmdlib.common import CheckNodeOnline, ExpandNodeUuidAndName, \
- IsInstanceRunning, DetermineImageSize
+from ganeti.cmdlib.common import CheckNodeOnline, ExpandNodeUuidAndName
+from ganeti.cmdlib.instance_helpervm import RunWithHelperVM
from ganeti.cmdlib.instance_storage import StartInstanceDisks, \
- ShutdownInstanceDisks, TemporaryDisk, ImageDisks
+ ShutdownInstanceDisks
from ganeti.cmdlib.instance_utils import GetClusterDomainSecret, \
BuildInstanceHookEnvByObject, CheckNodeNotDrained, RemoveInstance, \
CheckCompressionTool
@@ -374,54 +373,16 @@ class LUBackupExport(LogicalUnit):
assert self.op.zeroing_timeout_per_mib is not None
zeroing_image = self.cfg.GetZeroingImage()
- src_node_uuid = self.instance.primary_node
-
- try:
- disk_size = DetermineImageSize(self, zeroing_image, src_node_uuid)
- except errors.OpExecError, err:
- raise errors.OpExecError("Could not create temporary disk for zeroing:"
- " %s", err)
# Calculate the sum prior to adding the temporary disk
instance_disks_size_sum = self._InstanceDiskSizeSum()
+ timeout = self.op.zeroing_timeout_fixed + \
+ self.op.zeroing_timeout_per_mib * instance_disks_size_sum
- with TemporaryDisk(self,
- self.instance,
- [(constants.DT_PLAIN, constants.DISK_RDWR, disk_size)],
- feedback_fn):
- feedback_fn("Activating instance disks")
- StartInstanceDisks(self, self.instance, False)
-
- feedback_fn("Imaging disk with zeroing image")
- ImageDisks(self, self.instance, zeroing_image)
-
- feedback_fn("Starting instance with zeroing image")
- result = self.rpc.call_instance_start(src_node_uuid,
- (self.instance, [], []),
- False, self.op.reason)
- result.Raise("Could not start instance %s when using the zeroing image "
- "%s" % (self.instance.name, zeroing_image))
-
- # First wait for the instance to start up
- running_check = lambda: IsInstanceRunning(self, self.instance,
- prereq=False)
- instance_up = retry.SimpleRetry(True, running_check, 5.0,
- self.op.shutdown_timeout)
- if not instance_up:
- raise errors.OpExecError("Could not boot instance when using the "
- "zeroing image %s" % zeroing_image)
-
- feedback_fn("Instance is up, now awaiting shutdown")
-
- # Then for it to be finished, detected by its shutdown
- timeout = self.op.zeroing_timeout_fixed + \
- self.op.zeroing_timeout_per_mib * instance_disks_size_sum
- instance_up = retry.SimpleRetry(False, running_check, 20.0, timeout)
- if instance_up:
- self.LogWarning("Zeroing not completed prior to timeout; instance will"
- "be shut down forcibly")
-
- feedback_fn("Zeroing completed!")
+ RunWithHelperVM(self, self.instance, zeroing_image,
+ self.op.shutdown_timeout, timeout,
+ log_prefix="Zeroing free disk space",
+ feedback_fn=feedback_fn)
def StartInstance(self, feedback_fn, src_node_uuid):
"""Send the node instructions to start the instance.
diff --git a/lib/cmdlib/instance_create.py b/lib/cmdlib/instance_create.py
index 2178b4a..e13b06d 100644
--- a/lib/cmdlib/instance_create.py
+++ b/lib/cmdlib/instance_create.py
@@ -45,7 +45,6 @@ from ganeti import netutils
from ganeti import objects
from ganeti import pathutils
from ganeti import utils
-from ganeti.utils import retry
from ganeti import serializer
from ganeti.cmdlib.base import LogicalUnit
@@ -56,14 +55,14 @@ from ganeti.cmdlib.common import \
IsExclusiveStorageEnabledNode, CheckHVParams, CheckOSParams, \
ExpandNodeUuidAndName, \
IsValidDiskAccessModeCombination, \
- CheckDiskTemplateEnabled, CheckIAllocatorOrNode, CheckOSImage, \
- IsInstanceRunning, DetermineImageSize
+ CheckDiskTemplateEnabled, CheckIAllocatorOrNode, CheckOSImage
+from ganeti.cmdlib.instance_helpervm import RunWithHelperVM
from ganeti.cmdlib.instance_storage import CalculateFileStorageDir, \
CheckNodesFreeDiskPerVG, CheckRADOSFreeSpace, CheckSpindlesExclusiveStorage, \
ComputeDiskSizePerVG, CreateDisks, \
- GenerateDiskTemplate, CommitDisks, StartInstanceDisks, \
+ GenerateDiskTemplate, CommitDisks, \
WaitForSync, ComputeDisks, \
- TemporaryDisk, ImageDisks, WipeDisks
+ ImageDisks, WipeDisks
from ganeti.cmdlib.instance_utils import \
CheckNodeNotDrained, CopyLockList, \
ReleaseLocks, CheckNodeVmCapable, \
@@ -1395,8 +1394,6 @@ class LUInstanceCreate(LogicalUnit):
raise errors.OpExecError("Cannot create install instance because an"
" install image has not been specified")
- disk_size = DetermineImageSize(self, install_image, instance.primary_node)
-
env = self.GetOsInstallPackageEnvironment(
instance,
constants.OS_SCRIPT_CREATE_UNTRUSTED)
@@ -1405,41 +1402,11 @@ class LUInstanceCreate(LogicalUnit):
osparams_private=self.op.osparams_private,
osparams_secret=self.op.osparams_secret)
- with TemporaryDisk(self,
- instance,
- [(constants.DT_PLAIN, constants.DISK_RDWR, disk_size)],
- feedback_fn):
- feedback_fn("Activating instance disks")
- StartInstanceDisks(self, instance, False)
-
- feedback_fn("Imaging disk with install image")
- ImageDisks(self, instance, install_image)
-
- feedback_fn("Starting instance with install image")
- result = self.rpc.call_instance_start(instance.primary_node,
- (instance, [], []),
- False, self.op.reason)
- result.Raise("Could not start instance '%s' with the install image '%s'"
- % (instance.name, install_image))
-
- # First wait for the instance to start up
- running_check = lambda: IsInstanceRunning(self, instance, prereq=False)
- instance_up = retry.SimpleRetry(True, running_check, 5.0,
- self.op.helper_startup_timeout)
- if not instance_up:
- raise errors.OpExecError("Could not boot instance using install image"
- " '%s'" % install_image)
-
- feedback_fn("Instance is up, now awaiting shutdown")
-
- # Then for it to be finished, detected by its shutdown
- instance_up = retry.SimpleRetry(False, running_check, 20.0,
- self.op.helper_shutdown_timeout)
- if instance_up:
- self.LogWarning("Installation not completed prior to timeout, shutting"
- " down instance forcibly")
-
- feedback_fn("Installation complete")
+ RunWithHelperVM(self, instance, install_image,
+ self.op.helper_startup_timeout,
+ self.op.helper_shutdown_timeout,
+ log_prefix="Running OS create script",
+ feedback_fn=feedback_fn)
def Exec(self, feedback_fn):
"""Create and add the instance to the cluster.
diff --git a/lib/cmdlib/instance_helpervm.py b/lib/cmdlib/instance_helpervm.py
new file mode 100644
index 0000000..5fba97b
--- /dev/null
+++ b/lib/cmdlib/instance_helpervm.py
@@ -0,0 +1,172 @@
+#
+#
+
+# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+"""Functions for running helper virtual machines to perform tasks on instances.
+
+"""
+
+import contextlib
+
+from ganeti import constants
+from ganeti import errors
+from ganeti.utils import retry
+
+from ganeti.cmdlib.common import IsInstanceRunning, DetermineImageSize
+from ganeti.cmdlib.instance_storage import StartInstanceDisks, \
+ TemporaryDisk, ImageDisks
+
+
+ at contextlib.contextmanager
+def HelperVM(lu, instance, vm_image, startup_timeout, vm_timeout,
+ log_prefix=None, feedback_fn=None):
+ """Runs a given helper VM for a given instance.
+
+ @type lu: L{LogicalUnit}
+ @param lu: the lu on whose behalf we execute
+ @type instance: L{objects.Instance}
+ @param instance: the instance definition
+ @type vm_image: string
+ @param vm_image: the name of the helper VM image to dump on a temporary disk
+ @type startup_timeout: int
+ @param startup_timeout: how long to wait for the helper VM to start up
+ @type vm_timeout: int
+ @param vm_timeout: how long to wait for the helper VM to finish its work
+ @type log_prefix: string
+ @param log_prefix: a prefix for all log messages
+ @type feedback_fn: function
+ @param feedback_fn: Function used to log progress
+
+ """
+ if log_prefix:
+ add_prefix = lambda msg: "%s: %s" % (log_prefix, msg)
+ else:
+ add_prefix = lambda msg: msg
+
+ if feedback_fn is not None:
+ log_feedback = lambda msg: feedback_fn(add_prefix(msg))
+ else:
+ log_feedback = lambda _: None
+
+ try:
+ disk_size = DetermineImageSize(lu, vm_image, instance.primary_node)
+ except errors.OpExecError, err:
+ raise errors.OpExecError("Could not create temporary disk: %s", err)
+
+ with TemporaryDisk(lu,
+ instance,
+ [(constants.DT_PLAIN, constants.DISK_RDWR, disk_size)],
+ log_feedback):
+ log_feedback("Activating helper VM's temporary disks")
+ StartInstanceDisks(lu, instance, False)
+
+ log_feedback("Imaging temporary disks with image %s" % (vm_image, ))
+ ImageDisks(lu, instance, vm_image)
+
+ log_feedback("Starting helper VM")
+ result = lu.rpc.call_instance_start(instance.primary_node,
+ (instance, [], []),
+ False, lu.op.reason)
+ result.Raise(add_prefix("Could not start helper VM with image %s" %
+ (vm_image, )))
+
+ # First wait for the instance to start up
+ running_check = lambda: IsInstanceRunning(lu, instance, prereq=False)
+ instance_up = retry.SimpleRetry(True, running_check, 5.0,
+ startup_timeout)
+ if not instance_up:
+ raise errors.OpExecError(add_prefix("Could not boot instance using"
+ " image %s" % (vm_image, )))
+
+ log_feedback("Helper VM is up")
+
+ def cleanup():
+ log_feedback("Waiting for helper VM to finish")
+
+ # Then for it to be finished, detected by its shutdown
+ instance_up = retry.SimpleRetry(False, running_check, 20.0, vm_timeout)
+ if instance_up:
+ lu.LogWarning(add_prefix("Helper VM has not finished within the"
+ " timeout; shutting it down forcibly"))
+ return \
+ lu.rpc.call_instance_shutdown(instance.primary_node,
+ instance,
+ constants.DEFAULT_SHUTDOWN_TIMEOUT,
+ lu.op.reason)
+ else:
+ return None
+
+ # Run the inner block and handle possible errors
+ try:
+ yield
+ except Exception:
+ # if the cleanup failed for some reason, log it and just re-raise
+ result = cleanup()
+ if result:
+ result.Warn(add_prefix("Could not shut down helper VM with image"
+ " %s within timeout" % (vm_image, )))
+ log_feedback("Error running helper VM with image %s" %
+ (vm_image, ))
+ raise
+ else:
+ result = cleanup()
+ # if the cleanup failed for some reason, throw an exception
+ if result:
+ result.Raise(add_prefix("Could not shut down helper VM with image %s"
+ " within timeout" % (vm_image, )))
+ raise errors.OpExecError("Error running helper VM with image %s" %
+ (vm_image, ))
+
+ log_feedback("Helper VM execution completed")
+
+
+def RunWithHelperVM(lu, instance, vm_image, startup_timeout, vm_timeout,
+ log_prefix=None, feedback_fn=None):
+ """Runs a given helper VM for a given instance.
+
+ @type lu: L{LogicalUnit}
+ @param lu: the lu on whose behalf we execute
+ @type instance: L{objects.Instance}
+ @param instance: the instance definition
+ @type vm_image: string
+ @param vm_image: the name of the helper VM image to dump on a temporary disk
+ @type startup_timeout: int
+ @param startup_timeout: how long to wait for the helper VM to start up
+ @type vm_timeout: int
+ @param vm_timeout: how long to wait for the helper VM to finish its work
+ @type log_prefix: string
+ @param log_prefix: a prefix for all log messages
+ @type feedback_fn: function
+ @param feedback_fn: Function used to log progress
+
+
+ """
+ with HelperVM(lu, instance, vm_image, startup_timeout, vm_timeout,
+ log_prefix=log_prefix, feedback_fn=feedback_fn):
+ pass
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ganeti/ganeti.git
More information about the Pkg-ganeti-devel
mailing list