Revision d90f0cb4

b/lib/cmdlib/instance_storage.py
872 872
                         cleanup=new_disks)
873 873

  
874 874

  
875
def _PerformNodeInfoCall(lu, node_uuids, vg):
876
  """Prepares the input and performs a node info call.
877

  
878
  @type lu: C{LogicalUnit}
879
  @param lu: a logical unit from which we get configuration data
880
  @type node_uuids: list of string
881
  @param node_uuids: list of node UUIDs to perform the call for
882
  @type vg: string
883
  @param vg: the volume group's name
884

  
885
  """
886
  lvm_storage_units = [(constants.ST_LVM_VG, vg)]
887
  storage_units = rpc.PrepareStorageUnitsForNodes(lu.cfg, lvm_storage_units,
888
                                                  node_uuids)
889
  hvname = lu.cfg.GetHypervisorType()
890
  hvparams = lu.cfg.GetClusterInfo().hvparams
891
  nodeinfo = lu.rpc.call_node_info(node_uuids, storage_units,
892
                                   [(hvname, hvparams[hvname])])
893
  return nodeinfo
894

  
895

  
896
def _CheckVgCapacityForNode(node_name, node_info, vg, requested):
897
  """Checks the vg capacity for a given node.
898

  
899
  @type node_info: tuple (_, list of dicts, _)
900
  @param node_info: the result of the node info call for one node
901
  @type node_name: string
902
  @param node_name: the name of the node
903
  @type vg: string
904
  @param vg: volume group name
905
  @type requested: int
906
  @param requested: the amount of disk in MiB to check for
907
  @raise errors.OpPrereqError: if the node doesn't have enough disk,
908
      or we cannot check the node
909

  
910
  """
911
  (_, space_info, _) = node_info
912
  lvm_vg_info = utils.storage.LookupSpaceInfoByStorageType(
913
      space_info, constants.ST_LVM_VG)
914
  if not lvm_vg_info:
915
    raise errors.OpPrereqError("Can't retrieve storage information for LVM")
916
  vg_free = lvm_vg_info.get("storage_free", None)
917
  if not isinstance(vg_free, int):
918
    raise errors.OpPrereqError("Can't compute free disk space on node"
919
                               " %s for vg %s, result was '%s'" %
920
                               (node_name, vg, vg_free), errors.ECODE_ENVIRON)
921
  if requested > vg_free:
922
    raise errors.OpPrereqError("Not enough disk space on target node %s"
923
                               " vg %s: required %d MiB, available %d MiB" %
924
                               (node_name, vg, requested, vg_free),
925
                               errors.ECODE_NORES)
926

  
927

  
875 928
def _CheckNodesFreeDiskOnVG(lu, node_uuids, vg, requested):
876 929
  """Checks if nodes have enough free disk space in the specified VG.
877 930

  
......
892 945
      or we cannot check the node
893 946

  
894 947
  """
895
  lvm_storage_units = [(constants.ST_LVM_VG, vg)]
896
  storage_units = rpc.PrepareStorageUnitsForNodes(lu.cfg, lvm_storage_units,
897
                                                  node_uuids)
898
  hvname = lu.cfg.GetHypervisorType()
899
  hvparams = lu.cfg.GetClusterInfo().hvparams
900
  nodeinfo = lu.rpc.call_node_info(node_uuids, storage_units,
901
                                   [(hvname, hvparams[hvname])])
948
  nodeinfo = _PerformNodeInfoCall(lu, node_uuids, vg)
902 949
  for node in node_uuids:
903 950
    node_name = lu.cfg.GetNodeName(node)
904

  
905 951
    info = nodeinfo[node]
906 952
    info.Raise("Cannot get current information from node %s" % node_name,
907 953
               prereq=True, ecode=errors.ECODE_ENVIRON)
908
    (_, space_info, _) = info.payload
909
    lvm_vg_info = utils.storage.LookupSpaceInfoByStorageType(
910
        space_info, constants.ST_LVM_VG)
911
    if not lvm_vg_info:
912
      raise errors.OpPrereqError("Can't retrieve storage information for LVM")
913
    vg_free = lvm_vg_info.get("storage_free", None)
914
    if not isinstance(vg_free, int):
915
      raise errors.OpPrereqError("Can't compute free disk space on node"
916
                                 " %s for vg %s, result was '%s'" %
917
                                 (node_name, vg, vg_free), errors.ECODE_ENVIRON)
918
    if requested > vg_free:
919
      raise errors.OpPrereqError("Not enough disk space on target node %s"
920
                                 " vg %s: required %d MiB, available %d MiB" %
921
                                 (node_name, vg, requested, vg_free),
922
                                 errors.ECODE_NORES)
954
    _CheckVgCapacityForNode(node_name, info.payload, vg, requested)
923 955

  
924 956

  
925 957
def CheckNodesFreeDiskPerVG(lu, node_uuids, req_sizes):
b/test/py/ganeti.cmdlib.instance_storage_unittest.py
1
#!/usr/bin/python
2
#
3

  
4
# Copyright (C) 2013 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

  
21

  
22
"""Script for unittesting the cmdlib module 'instance_storage'"""
23

  
24

  
25
import unittest
26

  
27
from ganeti import constants
28
from ganeti.cmdlib import instance_storage
29
from ganeti import errors
30

  
31
import testutils
32
import mock
33

  
34

  
35
class TestCheckNodesFreeDiskOnVG(unittest.TestCase):
36

  
37
  def setUp(self):
38
    self.node_uuid = "12345"
39
    self.node_uuids = [self.node_uuid]
40

  
41
    self.node_info = mock.Mock()
42

  
43
    self.es = True
44
    self.ndparams = {constants.ND_EXCLUSIVE_STORAGE: self.es}
45

  
46
    mock_rpc = mock.Mock()
47
    mock_rpc.call_node_info = mock.Mock()
48

  
49
    mock_cfg = mock.Mock()
50
    mock_cfg.GetNodeInfo = mock.Mock(return_value=self.node_info)
51
    mock_cfg.GetNdParams = mock.Mock(return_value=self.ndparams)
52

  
53
    self.hvname = "myhv"
54
    self.hvparams = mock.Mock()
55
    self.clusterinfo = mock.Mock()
56
    self.clusterinfo.hvparams = {self.hvname: self.hvparams}
57

  
58
    mock_cfg.GetHypervisorType = mock.Mock(return_value=self.hvname)
59
    mock_cfg.GetClusterInfo = mock.Mock(return_value=self.clusterinfo)
60

  
61
    self.lu = mock.Mock()
62
    self.lu.rpc = mock_rpc
63
    self.lu.cfg = mock_cfg
64

  
65
    self.vg = "myvg"
66

  
67
    self.node_name = "mynode"
68
    self.space_info = [{"type": constants.ST_LVM_VG,
69
                        "name": self.vg,
70
                        "storage_free": 125,
71
                        "storage_size": 666}]
72

  
73
  def testPerformNodeInfoCall(self):
74
    expected_hv_arg = [(self.hvname, self.hvparams)]
75
    expected_storage_arg = {self.node_uuid:
76
        [(constants.ST_LVM_VG, self.vg, [self.es])]}
77
    instance_storage._PerformNodeInfoCall(self.lu, self.node_uuids, self.vg)
78
    self.lu.rpc.call_node_info.assert_called_with(
79
        self.node_uuids, expected_storage_arg, expected_hv_arg)
80

  
81
  def testCheckVgCapacityForNode(self):
82
    requested = 123
83
    node_info = (None, self.space_info, None)
84
    instance_storage._CheckVgCapacityForNode(self.node_name, node_info,
85
                                             self.vg, requested)
86

  
87
  def testCheckVgCapacityForNodeNotEnough(self):
88
    requested = 250
89
    node_info = (None, self.space_info, None)
90
    self.assertRaises(
91
        errors.OpPrereqError,
92
        instance_storage._CheckVgCapacityForNode,
93
        self.node_name, node_info, self.vg, requested)
94

  
95
  def testCheckVgCapacityForNodeNoStorageData(self):
96
    node_info = (None, [], None)
97
    self.assertRaises(
98
        errors.OpPrereqError,
99
        instance_storage._CheckVgCapacityForNode,
100
        self.node_name, node_info, self.vg, NotImplemented)
101

  
102
  def testCheckVgCapacityForNodeBogusSize(self):
103
    broken_space_info = [{"type": constants.ST_LVM_VG,
104
                        "name": self.vg,
105
                        "storage_free": "greenbunny",
106
                        "storage_size": "redbunny"}]
107
    node_info = (None, broken_space_info, None)
108
    self.assertRaises(
109
        errors.OpPrereqError,
110
        instance_storage._CheckVgCapacityForNode,
111
        self.node_name, node_info, self.vg, NotImplemented)
112

  
113

  
114
if __name__ == "__main__":
115
  testutils.GanetiTestProgram()

Also available in: Unified diff