Revision 683335b3

b/Makefile.am
1251 1251
	test/py/ganeti.utils.nodesetup_unittest.py \
1252 1252
	test/py/ganeti.utils.process_unittest.py \
1253 1253
	test/py/ganeti.utils.retry_unittest.py \
1254
	test/py/ganeti.utils.storage_unittest.py \
1254 1255
	test/py/ganeti.utils.text_unittest.py \
1255 1256
	test/py/ganeti.utils.wrapper_unittest.py \
1256 1257
	test/py/ganeti.utils.x509_unittest.py \
b/lib/utils/storage.py
22 22

  
23 23
"""
24 24

  
25
import logging
26

  
25 27
from ganeti import constants
28
from ganeti import pathutils
26 29

  
27 30

  
28 31
def GetDiskTemplatesOfStorageType(storage_type):
......
52 55
    return False
53 56
  return set(GetLvmDiskTemplates()).intersection(
54 57
      set(new_enabled_disk_templates))
58

  
59

  
60
def _GetDefaultStorageUnitForDiskTemplate(cfg, disk_template):
61
  """Retrieves the identifier of the default storage entity for the given
62
  storage type.
63

  
64
  @type disk_template: string
65
  @param disk_template: a disk template, for example 'drbd'
66
  @rtype: string
67
  @return: identifier for a storage unit, for example the vg_name for lvm
68
     storage
69

  
70
  """
71
  storage_type = constants.DISK_TEMPLATES_STORAGE_TYPE[disk_template]
72
  if disk_template in GetLvmDiskTemplates():
73
    return (storage_type, cfg.GetVGName())
74
  # FIXME: Adjust this, once FILE_STORAGE_DIR and SHARED_FILE_STORAGE_DIR
75
  # are not in autoconf anymore.
76
  elif disk_template == constants.DT_FILE:
77
    return (storage_type, pathutils.DEFAULT_FILE_STORAGE_DIR)
78
  elif disk_template == constants.DT_SHARED_FILE:
79
    return (storage_type, pathutils.DEFAULT_SHARED_FILE_STORAGE_DIR)
80
  else:
81
    return (storage_type, None)
82

  
83

  
84
def _GetDefaultStorageUnitForSpindles(cfg):
85
  """Creates a 'spindle' storage unit, by retrieving the volume group
86
  name and associating it to the lvm-pv storage type.
87

  
88
  @rtype: (string, string)
89
  @return: tuple (storage_type, storage_key), where storage type is
90
    'lvm-pv' and storage_key the name of the default volume group
91

  
92
  """
93
  return (constants.ST_LVM_PV, cfg.GetVGName())
94

  
95

  
96
# List of storage type for which space reporting is implemented.
97
# FIXME: Remove this, once the backend is capable to do this for all
98
# storage types.
99
_DISK_TEMPLATES_SPACE_QUERYABLE = GetLvmDiskTemplates() \
100
    + GetDiskTemplatesOfStorageType(constants.ST_FILE)
101

  
102

  
103
def GetStorageUnitsOfCluster(cfg, include_spindles=False):
104
  """Examines the cluster's configuration and returns a list of storage
105
  units and their storage keys, ordered by the order in which they
106
  are enabled.
107

  
108
  @type cfg: L{config.ConfigWriter}
109
  @param cfg: Cluster configuration
110
  @type include_spindles: boolean
111
  @param include_spindles: flag to include an extra storage unit for physical
112
    volumes
113
  @rtype: list of tuples (string, string)
114
  @return: list of storage units, each storage unit being a tuple of
115
    (storage_type, storage_key); storage_type is in
116
    C{constants.VALID_STORAGE_TYPES} and the storage_key a string to
117
    identify an entity of that storage type, for example a volume group
118
    name for LVM storage or a file for file storage.
119

  
120
  """
121
  cluster_config = cfg.GetClusterInfo()
122
  storage_units = []
123
  for disk_template in cluster_config.enabled_disk_templates:
124
    if disk_template in _DISK_TEMPLATES_SPACE_QUERYABLE:
125
      storage_units.append(
126
          _GetDefaultStorageUnitForDiskTemplate(cfg, disk_template))
127
  if include_spindles:
128
    included_storage_types = set([st for (st, _) in storage_units])
129
    if not constants.ST_LVM_PV in included_storage_types:
130
      storage_units.append(
131
          _GetDefaultStorageUnitForSpindles(cfg))
132

  
133
  return storage_units
134

  
135

  
136
def LookupSpaceInfoByStorageType(storage_space_info, storage_type):
137
  """Looks up the storage space info for a given storage type.
138

  
139
  Note that this lookup can be ambiguous if storage space reporting for several
140
  units of the same storage type was requested. This function is only supposed
141
  to be used for legacy code in situations where it actually is unambiguous.
142

  
143
  @type storage_space_info: list of dicts
144
  @param storage_space_info: result of C{GetNodeInfo}
145
  @type storage_type: string
146
  @param storage_type: a storage type, which is included in the storage_units
147
    list
148
  @rtype: tuple
149
  @return: returns the element of storage_space_info that matches the given
150
    storage type
151

  
152
  """
153
  result = None
154
  for unit_info in storage_space_info:
155
    if unit_info["type"] == storage_type:
156
      if result is None:
157
        result = unit_info
158
      else:
159
        # There is more than one storage type in the query, log a warning
160
        logging.warning("Storage space information requested for"
161
                        " ambiguous storage type '%s'.", storage_type)
162
  return result
b/test/py/ganeti.utils.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 ganeti.utils.storage module"""
23

  
24
import mock
25

  
26
import unittest
27

  
28
from ganeti import constants
29
from ganeti import errors
30
from ganeti import objects
31
from ganeti import pathutils
32
from ganeti.utils import storage
33

  
34
import testutils
35

  
36

  
37
class TestGetStorageUnitForDiskTemplate(unittest.TestCase):
38

  
39
  def setUp(self):
40
    self._default_vg_name = "some_vg_name"
41
    self._cfg = mock.Mock()
42
    self._cfg.GetVGName = mock.Mock(return_value=self._default_vg_name)
43

  
44
  def testGetDefaultStorageUnitForDiskTemplateLvm(self):
45
    for disk_template in [constants.DT_DRBD8, constants.DT_PLAIN]:
46
      (storage_type, storage_key) = \
47
          storage._GetDefaultStorageUnitForDiskTemplate(self._cfg,
48
                                                        disk_template)
49
      self.assertEqual(storage_type, constants.ST_LVM_VG)
50
      self.assertEqual(storage_key, self._default_vg_name)
51

  
52
  def testGetDefaultStorageUnitForDiskTemplateFile(self):
53
    (storage_type, storage_key) = \
54
        storage._GetDefaultStorageUnitForDiskTemplate(self._cfg,
55
                                                      constants.DT_FILE)
56
    self.assertEqual(storage_type, constants.ST_FILE)
57
    self.assertEqual(storage_key, pathutils.DEFAULT_FILE_STORAGE_DIR)
58

  
59
  def testGetDefaultStorageUnitForDiskTemplateSharedFile(self):
60
    (storage_type, storage_key) = \
61
        storage._GetDefaultStorageUnitForDiskTemplate(self._cfg,
62
                                                      constants.DT_SHARED_FILE)
63
    self.assertEqual(storage_type, constants.ST_FILE)
64
    self.assertEqual(storage_key, pathutils.DEFAULT_SHARED_FILE_STORAGE_DIR)
65

  
66
  def testGetDefaultStorageUnitForDiskTemplateDiskless(self):
67
    (storage_type, storage_key) = \
68
        storage._GetDefaultStorageUnitForDiskTemplate(self._cfg,
69
                                                      constants.DT_DISKLESS)
70
    self.assertEqual(storage_type, constants.ST_DISKLESS)
71
    self.assertEqual(storage_key, None)
72

  
73
  def testGetDefaultStorageUnitForSpindles(self):
74
    (storage_type, storage_key) = \
75
        storage._GetDefaultStorageUnitForSpindles(self._cfg)
76
    self.assertEqual(storage_type, constants.ST_LVM_PV)
77
    self.assertEqual(storage_key, self._default_vg_name)
78

  
79

  
80
class TestGetStorageUnitsOfCluster(unittest.TestCase):
81

  
82
  def setUp(self):
83
    storage._GetDefaultStorageUnitForDiskTemplate = \
84
        mock.Mock(return_value=("foo", "bar"))
85

  
86
    self._cluster_cfg = objects.Cluster()
87
    self._enabled_disk_templates = \
88
        [constants.DT_DRBD8, constants.DT_PLAIN, constants.DT_FILE,
89
         constants.DT_SHARED_FILE]
90
    self._cluster_cfg.enabled_disk_templates = \
91
        self._enabled_disk_templates
92
    self._cfg = mock.Mock()
93
    self._cfg.GetClusterInfo = mock.Mock(return_value=self._cluster_cfg)
94
    self._cfg.GetVGName = mock.Mock(return_value="some_vg_name")
95

  
96
  def testGetStorageUnitsOfCluster(self):
97
    storage_units = storage.GetStorageUnitsOfCluster(self._cfg)
98
    self.assertEqual(len(storage_units), len(self._enabled_disk_templates))
99

  
100
  def testGetStorageUnitsOfClusterWithSpindles(self):
101
    storage_units = storage.GetStorageUnitsOfCluster(
102
        self._cfg, include_spindles=True)
103
    self.assertEqual(len(storage_units), len(self._enabled_disk_templates) + 1)
104
    self.assertTrue(constants.ST_LVM_PV in [st for (st, sk) in storage_units])
105

  
106

  
107
class TestLookupSpaceInfoByStorageType(unittest.TestCase):
108

  
109
  def setUp(self):
110
    self._space_info = [
111
        {"type": st, "name": st + "_key", "storage_size": 0, "storage_free": 0}
112
        for st in constants.VALID_STORAGE_TYPES]
113

  
114
  def testValidLookup(self):
115
    query_type = constants.ST_LVM_PV
116
    result = storage.LookupSpaceInfoByStorageType(self._space_info, query_type)
117
    self.assertEqual(query_type, result["type"])
118

  
119
  def testNotInList(self):
120
    result = storage.LookupSpaceInfoByStorageType(self._space_info,
121
                                                  "non_existing_type")
122
    self.assertEqual(None, result)
123

  
124

  
125
if __name__ == "__main__":
126
  testutils.GanetiTestProgram()

Also available in: Unified diff