Move 'DetermineImageSize' from 'ganeti.cmdlib.backup' to
'ganeti.cmdlib.common' so it can be used by disk zeroing and instance
installations.  This patch also transforms this method into a function
and generalizes the error messages.

Signed-off-by: Jose A. Lopes <[email protected]>
---
 lib/cmdlib/backup.py | 59 +++++++---------------------------------------------
 lib/cmdlib/common.py | 52 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 58 insertions(+), 53 deletions(-)

diff --git a/lib/cmdlib/backup.py b/lib/cmdlib/backup.py
index a83d2f0..5f340b3 100644
--- a/lib/cmdlib/backup.py
+++ b/lib/cmdlib/backup.py
@@ -21,10 +21,8 @@
 
 """Logical units dealing with backup operations."""
 
-import urllib2
 import OpenSSL
 import logging
-import math
 
 from ganeti import compat
 from ganeti import constants
@@ -36,7 +34,7 @@ from ganeti.utils import retry
 
 from ganeti.cmdlib.base import NoHooksLU, LogicalUnit
 from ganeti.cmdlib.common import CheckNodeOnline, ExpandNodeUuidAndName, \
-  IsInstanceRunning
+  IsInstanceRunning, DetermineImageSize
 from ganeti.cmdlib.instance_storage import StartInstanceDisks, \
   ShutdownInstanceDisks, TemporaryDisk, ImageDisks
 from ganeti.cmdlib.instance_utils import GetClusterDomainSecret, \
@@ -347,54 +345,6 @@ class LUBackupExport(LogicalUnit):
                             " on node %s: %s", iname,
                             self.cfg.GetNodeName(node_uuid), msg)
 
-  def _DetermineImageSize(self, image_path, node_uuid):
-    """ Determines the size of the specified image.
-
-    @type image_path: string
-    @param image_path: The disk path or a URL of an image.
-    @type node_uuid: string
-    @param node_uuid: If a file path is used,
-
-    @raise OpExecError: If the image does not exist.
-
-    @rtype: int
-    @return: The size in MB, rounded up.
-
-    """
-    # Check if we are dealing with a URL first
-    class _HeadRequest(urllib2.Request):
-      def get_method(self):
-        return "HEAD"
-
-    if utils.IsUrl(image_path):
-      try:
-        response = urllib2.urlopen(_HeadRequest(image_path))
-      except urllib2.URLError:
-        raise errors.OpExecError("Could not retrieve image from given url %s" %
-                                 image_path)
-
-      content_length_str = response.info().getheader('content-length')
-
-      if not content_length_str:
-        raise errors.OpExecError(
-          "Cannot create temporary disk: size of zeroing image at path %s "
-          "could not be retrieved through HEAD request" % image_path
-        )
-
-      byte_size = int(content_length_str)
-    else:
-      # We end up here if a file path is used
-      result = self.rpc.call_get_file_info(node_uuid, image_path)
-      result.Raise("Cannot determine the size of file %s" % image_path)
-
-      success, attributes = result.payload
-      if not success:
-        raise errors.OpExecError("Could not open file %s" % image_path)
-      byte_size = attributes[constants.STAT_SIZE]
-
-    # Finally, the conversion
-    return math.ceil(byte_size / 1024. / 1024.)
-
   def _InstanceDiskSizeSum(self):
     """Calculates the size of all the disks of the instance used in this LU.
 
@@ -417,7 +367,12 @@ class LUBackupExport(LogicalUnit):
 
     zeroing_image = self.cfg.GetZeroingImage()
     src_node_uuid = self.instance.primary_node
-    disk_size = self._DetermineImageSize(zeroing_image, src_node_uuid)
+
+    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()
diff --git a/lib/cmdlib/common.py b/lib/cmdlib/common.py
index 9889a67..5e6b670 100644
--- a/lib/cmdlib/common.py
+++ b/lib/cmdlib/common.py
@@ -22,7 +22,9 @@
 """Common functions used by multiple logical units."""
 
 import copy
+import math
 import os
+import urllib2
 
 from ganeti import compat
 from ganeti import constants
@@ -764,7 +766,7 @@ def AnnotateDiskParams(instance, devs, cfg):
   @param devs: The root devices (not any of its children!)
   @param cfg: The config object
   @returns The annotated disk copies
-  @see L{rpc.node.AnnotateDiskParams}
+  @see L{ganeti.rpc.node.AnnotateDiskParams}
 
   """
   return rpc.AnnotateDiskParams(devs, cfg.GetInstanceDiskParams(instance))
@@ -1414,3 +1416,51 @@ def ConnectInstanceCommunicationNetworkOp(group_uuid, 
network):
     network_mode=constants.INSTANCE_COMMUNICATION_NETWORK_MODE,
     network_link=constants.INSTANCE_COMMUNICATION_NETWORK_LINK,
     conflicts_check=True)
+
+
+def DetermineImageSize(lu, image, node_uuid):
+  """Determines the size of the specified image.
+
+  @type image: string
+  @param image: absolute filepath or URL of the image
+
+  @type node_uuid: string
+  @param node_uuid: if L{image} is a filepath, this is the UUID of the
+    node where the image is located
+
+  @rtype: int
+  @return: size of the image in MB, rounded up
+  @raise OpExecError: if the image does not exist
+
+  """
+  # Check if we are dealing with a URL first
+  class _HeadRequest(urllib2.Request):
+    def get_method(self):
+      return "HEAD"
+
+  if utils.IsUrl(image):
+    try:
+      response = urllib2.urlopen(_HeadRequest(image))
+    except urllib2.URLError:
+      raise errors.OpExecError("Could not retrieve image from given url '%s'" %
+                               image)
+
+    content_length_str = response.info().getheader('content-length')
+
+    if not content_length_str:
+      raise errors.OpExecError("Could not determine image size from given url"
+                               " '%s'" % image)
+
+    byte_size = int(content_length_str)
+  else:
+    # We end up here if a file path is used
+    result = lu.rpc.call_get_file_info(node_uuid, image)
+    result.Raise("Could not determine size of file '%s'" % image)
+
+    success, attributes = result.payload
+    if not success:
+      raise errors.OpExecError("Could not open file '%s'" % image)
+    byte_size = attributes[constants.STAT_SIZE]
+
+  # Finally, the conversion
+  return math.ceil(byte_size / 1024. / 1024.)
-- 
1.9.1.423.g4596e3a

Reply via email to