4 # Copyright (C) 2013 Google Inc.
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.
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.
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
21 """Utility functions for storage.
27 from ganeti import constants
28 from ganeti import pathutils
31 def GetDiskTemplatesOfStorageType(storage_type):
32 """Given the storage type, returns a list of disk templates based on that
34 return [dt for dt in constants.DISK_TEMPLATES
35 if constants.DISK_TEMPLATES_STORAGE_TYPE[dt] == storage_type]
38 def GetLvmDiskTemplates():
39 """Returns all disk templates that use LVM."""
40 return GetDiskTemplatesOfStorageType(constants.ST_LVM_VG)
43 def IsLvmEnabled(enabled_disk_templates):
44 """Check whether or not any lvm-based disk templates are enabled."""
45 return len(set(GetLvmDiskTemplates())
46 .intersection(set(enabled_disk_templates))) != 0
49 def LvmGetsEnabled(enabled_disk_templates, new_enabled_disk_templates):
50 """Checks whether lvm was not enabled before, but will be enabled after
54 if IsLvmEnabled(enabled_disk_templates):
56 return set(GetLvmDiskTemplates()).intersection(
57 set(new_enabled_disk_templates))
60 def _GetDefaultStorageUnitForDiskTemplate(cfg, disk_template):
61 """Retrieves the identifier of the default storage entity for the given
64 @type disk_template: string
65 @param disk_template: a disk template, for example 'drbd'
67 @return: identifier for a storage unit, for example the vg_name for lvm
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)
81 return (storage_type, None)
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.
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
93 return (constants.ST_LVM_PV, cfg.GetVGName())
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
99 _DISK_TEMPLATES_SPACE_QUERYABLE = GetLvmDiskTemplates() \
100 + GetDiskTemplatesOfStorageType(constants.ST_FILE)
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
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
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.
121 cluster_config = cfg.GetClusterInfo()
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))
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))
136 def LookupSpaceInfoByStorageType(storage_space_info, storage_type):
137 """Looks up the storage space info for a given storage type.
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.
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
149 @return: returns the element of storage_space_info that matches the given
154 for unit_info in storage_space_info:
155 if unit_info["type"] == storage_type:
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)