Commit 38519f22 authored by Jose A. Lopes's avatar Jose A. Lopes
Browse files

Move 'DetermineImageSize' to 'ganeti.cmdlib.common'



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: default avatarJose A. Lopes <jabolopes@google.com>
Reviewed-by: default avatarHrvoje Ribicic <riba@google.com>
parent a44114c9
......@@ -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, \
......@@ -351,54 +349,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.
......@@ -421,7 +371,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()
......
......@@ -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.)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment