Utility functions to check if a disk template is enabed
[ganeti-local] / lib / utils / storage.py
1 #
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 """Utility functions for storage.
22
23 """
24
25 import logging
26
27 from ganeti import constants
28 from ganeti import pathutils
29
30
31 def GetDiskTemplatesOfStorageType(storage_type):
32   """Given the storage type, returns a list of disk templates based on that
33      storage type."""
34   return [dt for dt in constants.DISK_TEMPLATES
35           if constants.DISK_TEMPLATES_STORAGE_TYPE[dt] == storage_type]
36
37
38 def GetLvmDiskTemplates():
39   """Returns all disk templates that use LVM."""
40   return GetDiskTemplatesOfStorageType(constants.ST_LVM_VG)
41
42
43 def IsDiskTemplateEnabled(disk_template, enabled_disk_templates):
44   """Checks if a particular disk template is enabled.
45
46   """
47   return disk_template in enabled_disk_templates
48
49
50 def IsFileStorageEnabled(enabled_disk_templates):
51   """Checks if file storage is enabled.
52
53   """
54   return IsDiskTemplateEnabled(constants.DT_FILE, enabled_disk_templates)
55
56
57 def IsSharedFileStorageEnabled(enabled_disk_templates):
58   """Checks if shared file storage is enabled.
59
60   """
61   return IsDiskTemplateEnabled(constants.DT_SHARED_FILE, enabled_disk_templates)
62
63
64 def IsLvmEnabled(enabled_disk_templates):
65   """Check whether or not any lvm-based disk templates are enabled."""
66   return len(set(GetLvmDiskTemplates())
67              .intersection(set(enabled_disk_templates))) != 0
68
69
70 def LvmGetsEnabled(enabled_disk_templates, new_enabled_disk_templates):
71   """Checks whether lvm was not enabled before, but will be enabled after
72      the operation.
73
74   """
75   if IsLvmEnabled(enabled_disk_templates):
76     return False
77   return set(GetLvmDiskTemplates()).intersection(
78       set(new_enabled_disk_templates))
79
80
81 def _GetDefaultStorageUnitForDiskTemplate(cfg, disk_template):
82   """Retrieves the identifier of the default storage entity for the given
83   storage type.
84
85   @type disk_template: string
86   @param disk_template: a disk template, for example 'drbd'
87   @rtype: string
88   @return: identifier for a storage unit, for example the vg_name for lvm
89      storage
90
91   """
92   storage_type = constants.DISK_TEMPLATES_STORAGE_TYPE[disk_template]
93   if disk_template in GetLvmDiskTemplates():
94     return (storage_type, cfg.GetVGName())
95   # FIXME: Adjust this, once FILE_STORAGE_DIR and SHARED_FILE_STORAGE_DIR
96   # are not in autoconf anymore.
97   elif disk_template == constants.DT_FILE:
98     return (storage_type, pathutils.DEFAULT_FILE_STORAGE_DIR)
99   elif disk_template == constants.DT_SHARED_FILE:
100     return (storage_type, pathutils.DEFAULT_SHARED_FILE_STORAGE_DIR)
101   else:
102     return (storage_type, None)
103
104
105 def _GetDefaultStorageUnitForSpindles(cfg):
106   """Creates a 'spindle' storage unit, by retrieving the volume group
107   name and associating it to the lvm-pv storage type.
108
109   @rtype: (string, string)
110   @return: tuple (storage_type, storage_key), where storage type is
111     'lvm-pv' and storage_key the name of the default volume group
112
113   """
114   return (constants.ST_LVM_PV, cfg.GetVGName())
115
116
117 # List of storage type for which space reporting is implemented.
118 # FIXME: Remove this, once the backend is capable to do this for all
119 # storage types.
120 _DISK_TEMPLATES_SPACE_QUERYABLE = GetLvmDiskTemplates() \
121     + GetDiskTemplatesOfStorageType(constants.ST_FILE)
122
123
124 def GetStorageUnitsOfCluster(cfg, include_spindles=False):
125   """Examines the cluster's configuration and returns a list of storage
126   units and their storage keys, ordered by the order in which they
127   are enabled.
128
129   @type cfg: L{config.ConfigWriter}
130   @param cfg: Cluster configuration
131   @type include_spindles: boolean
132   @param include_spindles: flag to include an extra storage unit for physical
133     volumes
134   @rtype: list of tuples (string, string)
135   @return: list of storage units, each storage unit being a tuple of
136     (storage_type, storage_key); storage_type is in
137     C{constants.VALID_STORAGE_TYPES} and the storage_key a string to
138     identify an entity of that storage type, for example a volume group
139     name for LVM storage or a file for file storage.
140
141   """
142   cluster_config = cfg.GetClusterInfo()
143   storage_units = []
144   for disk_template in cluster_config.enabled_disk_templates:
145     if disk_template in _DISK_TEMPLATES_SPACE_QUERYABLE:
146       storage_units.append(
147           _GetDefaultStorageUnitForDiskTemplate(cfg, disk_template))
148   if include_spindles:
149     included_storage_types = set([st for (st, _) in storage_units])
150     if not constants.ST_LVM_PV in included_storage_types:
151       storage_units.append(
152           _GetDefaultStorageUnitForSpindles(cfg))
153
154   return storage_units
155
156
157 def LookupSpaceInfoByStorageType(storage_space_info, storage_type):
158   """Looks up the storage space info for a given storage type.
159
160   Note that this lookup can be ambiguous if storage space reporting for several
161   units of the same storage type was requested. This function is only supposed
162   to be used for legacy code in situations where it actually is unambiguous.
163
164   @type storage_space_info: list of dicts
165   @param storage_space_info: result of C{GetNodeInfo}
166   @type storage_type: string
167   @param storage_type: a storage type, which is included in the storage_units
168     list
169   @rtype: tuple
170   @return: returns the element of storage_space_info that matches the given
171     storage type
172
173   """
174   result = None
175   for unit_info in storage_space_info:
176     if unit_info["type"] == storage_type:
177       if result is None:
178         result = unit_info
179       else:
180         # There is more than one storage type in the query, log a warning
181         logging.warning("Storage space information requested for"
182                         " ambiguous storage type '%s'.", storage_type)
183   return result