Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_base.py @ 17c61836

History | View | Annotate | Download (11 kB)

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

24 205ab586 Iustin Pop
The syntax for the _CHECK variables and the contents of the PARAMETERS
25 205ab586 Iustin Pop
dict is the same, see the docstring for L{BaseHypervisor.PARAMETERS}.
26 205ab586 Iustin Pop

27 205ab586 Iustin Pop
@var _FILE_CHECK: stub for file checks, without the required flag
28 205ab586 Iustin Pop
@var _DIR_CHECK: stub for directory checks, without the required flag
29 205ab586 Iustin Pop
@var REQ_FILE_CHECK: mandatory file parameter
30 205ab586 Iustin Pop
@var OPT_FILE_CHECK: optional file parameter
31 205ab586 Iustin Pop
@var REQ_DIR_CHECK: mandatory directory parametr
32 205ab586 Iustin Pop
@var OPT_DIR_CHECK: optional directory parameter
33 205ab586 Iustin Pop
@var NO_CHECK: parameter without any checks at all
34 205ab586 Iustin Pop
@var REQUIRED_CHECK: parameter required to exist (and non-false), but
35 205ab586 Iustin Pop
    without other checks; beware that this can't be used for boolean
36 205ab586 Iustin Pop
    parameters, where you should use NO_CHECK or a custom checker
37 205ab586 Iustin Pop

38 65a6f9b7 Michael Hanselmann
"""
39 65a6f9b7 Michael Hanselmann
40 205ab586 Iustin Pop
import os
41 572e52bf Iustin Pop
import re
42 572e52bf Iustin Pop
43 572e52bf Iustin Pop
44 f48148c3 Iustin Pop
from ganeti import errors
45 205ab586 Iustin Pop
from ganeti import utils
46 205ab586 Iustin Pop
47 205ab586 Iustin Pop
48 205ab586 Iustin Pop
# Read the BaseHypervisor.PARAMETERS docstring for the syntax of the
49 205ab586 Iustin Pop
# _CHECK values
50 205ab586 Iustin Pop
51 205ab586 Iustin Pop
# must be afile
52 17c61836 Guido Trotter
_FILE_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
53 205ab586 Iustin Pop
              os.path.isfile, "not found or not a file")
54 205ab586 Iustin Pop
55 205ab586 Iustin Pop
# must be a directory
56 17c61836 Guido Trotter
_DIR_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
57 205ab586 Iustin Pop
             os.path.isdir, "not found or not a directory")
58 205ab586 Iustin Pop
59 205ab586 Iustin Pop
# nice wrappers for users
60 205ab586 Iustin Pop
REQ_FILE_CHECK = (True, ) + _FILE_CHECK
61 205ab586 Iustin Pop
OPT_FILE_CHECK = (False, ) + _FILE_CHECK
62 205ab586 Iustin Pop
REQ_DIR_CHECK = (True, ) + _DIR_CHECK
63 205ab586 Iustin Pop
OPT_DIR_CHECK = (False, ) + _DIR_CHECK
64 205ab586 Iustin Pop
65 205ab586 Iustin Pop
# no checks at all
66 205ab586 Iustin Pop
NO_CHECK = (False, None, None, None, None)
67 205ab586 Iustin Pop
68 205ab586 Iustin Pop
# required, but no other checks
69 205ab586 Iustin Pop
REQUIRED_CHECK = (True, None, None, None, None)
70 205ab586 Iustin Pop
71 205ab586 Iustin Pop
def ParamInSet(required, my_set):
72 205ab586 Iustin Pop
  """Builds parameter checker for set membership.
73 205ab586 Iustin Pop

74 205ab586 Iustin Pop
  @type required: boolean
75 205ab586 Iustin Pop
  @param required: whether this is a required parameter
76 205ab586 Iustin Pop
  @type my_set: tuple, list or set
77 205ab586 Iustin Pop
  @param my_set: allowed values set
78 205ab586 Iustin Pop

79 205ab586 Iustin Pop
  """
80 205ab586 Iustin Pop
  fn = lambda x: x in my_set
81 205ab586 Iustin Pop
  err = ("The value must be one of: %s" % utils.CommaJoin(my_set))
82 205ab586 Iustin Pop
  return (required, fn, err, None, None)
83 f48148c3 Iustin Pop
84 f48148c3 Iustin Pop
85 65a6f9b7 Michael Hanselmann
class BaseHypervisor(object):
86 65a6f9b7 Michael Hanselmann
  """Abstract virtualisation technology interface
87 65a6f9b7 Michael Hanselmann

88 f48148c3 Iustin Pop
  The goal is that all aspects of the virtualisation technology are
89 f48148c3 Iustin Pop
  abstracted away from the rest of code.
90 65a6f9b7 Michael Hanselmann

91 205ab586 Iustin Pop
  @cvar PARAMETERS: a dict of parameter name: check type; the check type is
92 205ab586 Iustin Pop
      a five-tuple containing:
93 205ab586 Iustin Pop
          - the required flag (boolean)
94 205ab586 Iustin Pop
          - a function to check for syntax, that will be used in
95 205ab586 Iustin Pop
            L{CheckParameterSyntax}, in the master daemon process
96 205ab586 Iustin Pop
          - an error message for the above function
97 205ab586 Iustin Pop
          - a function to check for parameter validity on the remote node,
98 205ab586 Iustin Pop
            in the L{ValidateParameters} function
99 205ab586 Iustin Pop
          - an error message for the above function
100 205ab586 Iustin Pop

101 65a6f9b7 Michael Hanselmann
  """
102 205ab586 Iustin Pop
  PARAMETERS = {}
103 e1b8653f Guido Trotter
  ANCILLARY_FILES = []
104 f48148c3 Iustin Pop
105 65a6f9b7 Michael Hanselmann
  def __init__(self):
106 65a6f9b7 Michael Hanselmann
    pass
107 65a6f9b7 Michael Hanselmann
108 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
109 65a6f9b7 Michael Hanselmann
    """Start an instance."""
110 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
111 65a6f9b7 Michael Hanselmann
112 65a6f9b7 Michael Hanselmann
  def StopInstance(self, instance, force=False):
113 65a6f9b7 Michael Hanselmann
    """Stop an instance."""
114 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
115 65a6f9b7 Michael Hanselmann
116 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
117 65a6f9b7 Michael Hanselmann
    """Reboot an instance."""
118 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
119 65a6f9b7 Michael Hanselmann
120 65a6f9b7 Michael Hanselmann
  def ListInstances(self):
121 65a6f9b7 Michael Hanselmann
    """Get the list of running instances."""
122 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
123 65a6f9b7 Michael Hanselmann
124 65a6f9b7 Michael Hanselmann
  def GetInstanceInfo(self, instance_name):
125 65a6f9b7 Michael Hanselmann
    """Get instance properties.
126 65a6f9b7 Michael Hanselmann

127 cd42d0ad Guido Trotter
    @type instance_name: string
128 c41eea6e Iustin Pop
    @param instance_name: the instance name
129 65a6f9b7 Michael Hanselmann

130 c41eea6e Iustin Pop
    @return: tuple (name, id, memory, vcpus, state, times)
131 65a6f9b7 Michael Hanselmann

132 65a6f9b7 Michael Hanselmann
    """
133 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
134 65a6f9b7 Michael Hanselmann
135 65a6f9b7 Michael Hanselmann
  def GetAllInstancesInfo(self):
136 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
137 65a6f9b7 Michael Hanselmann

138 c41eea6e Iustin Pop
    @return: list of tuples (name, id, memory, vcpus, stat, times)
139 c41eea6e Iustin Pop

140 65a6f9b7 Michael Hanselmann
    """
141 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
142 65a6f9b7 Michael Hanselmann
143 65a6f9b7 Michael Hanselmann
  def GetNodeInfo(self):
144 65a6f9b7 Michael Hanselmann
    """Return information about the node.
145 65a6f9b7 Michael Hanselmann

146 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
147 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
148 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
149 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
150 65a6f9b7 Michael Hanselmann

151 65a6f9b7 Michael Hanselmann
    """
152 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
153 65a6f9b7 Michael Hanselmann
154 637ce7f9 Guido Trotter
  @classmethod
155 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
156 65a6f9b7 Michael Hanselmann
    """Return a command for connecting to the console of an instance.
157 65a6f9b7 Michael Hanselmann

158 65a6f9b7 Michael Hanselmann
    """
159 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
160 65a6f9b7 Michael Hanselmann
161 e1b8653f Guido Trotter
  @classmethod
162 e1b8653f Guido Trotter
  def GetAncillaryFiles(cls):
163 e1b8653f Guido Trotter
    """Return a list of ancillary files to be copied to all nodes as ancillary
164 e1b8653f Guido Trotter
    configuration files.
165 e1b8653f Guido Trotter

166 e1b8653f Guido Trotter
    @rtype: list of strings
167 e1b8653f Guido Trotter
    @return: list of absolute paths of files to ship cluster-wide
168 e1b8653f Guido Trotter

169 e1b8653f Guido Trotter
    """
170 e1b8653f Guido Trotter
    # By default we return a member variable, so that if an hypervisor has just
171 e1b8653f Guido Trotter
    # a static list of files it doesn't have to override this function.
172 e1b8653f Guido Trotter
    return cls.ANCILLARY_FILES
173 e1b8653f Guido Trotter
174 65a6f9b7 Michael Hanselmann
  def Verify(self):
175 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
176 65a6f9b7 Michael Hanselmann

177 65a6f9b7 Michael Hanselmann
    """
178 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
179 6e7275c0 Iustin Pop
180 cd42d0ad Guido Trotter
  def MigrationInfo(self, instance):
181 cd42d0ad Guido Trotter
    """Get instance information to perform a migration.
182 cd42d0ad Guido Trotter

183 cd42d0ad Guido Trotter
    By default assume no information is needed.
184 cd42d0ad Guido Trotter

185 cd42d0ad Guido Trotter
    @type instance: L{objects.Instance}
186 cd42d0ad Guido Trotter
    @param instance: instance to be migrated
187 cd42d0ad Guido Trotter
    @rtype: string/data (opaque)
188 cd42d0ad Guido Trotter
    @return: instance migration information - serialized form
189 cd42d0ad Guido Trotter

190 cd42d0ad Guido Trotter
    """
191 cd42d0ad Guido Trotter
    return ''
192 cd42d0ad Guido Trotter
193 cd42d0ad Guido Trotter
  def AcceptInstance(self, instance, info, target):
194 cd42d0ad Guido Trotter
    """Prepare to accept an instance.
195 cd42d0ad Guido Trotter

196 cd42d0ad Guido Trotter
    By default assume no preparation is needed.
197 cd42d0ad Guido Trotter

198 cd42d0ad Guido Trotter
    @type instance: L{objects.Instance}
199 cd42d0ad Guido Trotter
    @param instance: instance to be accepted
200 cd42d0ad Guido Trotter
    @type info: string/data (opaque)
201 cd42d0ad Guido Trotter
    @param info: migration information, from the source node
202 cd42d0ad Guido Trotter
    @type target: string
203 cd42d0ad Guido Trotter
    @param target: target host (usually ip), on this node
204 cd42d0ad Guido Trotter

205 cd42d0ad Guido Trotter
    """
206 cd42d0ad Guido Trotter
    pass
207 cd42d0ad Guido Trotter
208 cd42d0ad Guido Trotter
  def FinalizeMigration(self, instance, info, success):
209 cd42d0ad Guido Trotter
    """Finalized an instance migration.
210 cd42d0ad Guido Trotter

211 cd42d0ad Guido Trotter
    Should finalize or revert any preparation done to accept the instance.
212 cd42d0ad Guido Trotter
    Since by default we do no preparation, we also don't have anything to do
213 cd42d0ad Guido Trotter

214 cd42d0ad Guido Trotter
    @type instance: L{objects.Instance}
215 cd42d0ad Guido Trotter
    @param instance: instance whose migration is being aborted
216 cd42d0ad Guido Trotter
    @type info: string/data (opaque)
217 cd42d0ad Guido Trotter
    @param info: migration information, from the source node
218 cd42d0ad Guido Trotter
    @type success: boolean
219 cd42d0ad Guido Trotter
    @param success: whether the migration was a success or a failure
220 cd42d0ad Guido Trotter

221 cd42d0ad Guido Trotter
    """
222 cd42d0ad Guido Trotter
    pass
223 cd42d0ad Guido Trotter
224 6e7275c0 Iustin Pop
  def MigrateInstance(self, name, target, live):
225 6e7275c0 Iustin Pop
    """Migrate an instance.
226 6e7275c0 Iustin Pop

227 cd42d0ad Guido Trotter
    @type name: string
228 cd42d0ad Guido Trotter
    @param name: name of the instance to be migrated
229 cd42d0ad Guido Trotter
    @type target: string
230 cd42d0ad Guido Trotter
    @param target: hostname (usually ip) of the target node
231 cd42d0ad Guido Trotter
    @type live: boolean
232 cd42d0ad Guido Trotter
    @param live: whether to do a live or non-live migration
233 6e7275c0 Iustin Pop

234 6e7275c0 Iustin Pop
    """
235 6e7275c0 Iustin Pop
    raise NotImplementedError
236 f48148c3 Iustin Pop
237 f48148c3 Iustin Pop
  @classmethod
238 f48148c3 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
239 f48148c3 Iustin Pop
    """Check the given parameters for validity.
240 f48148c3 Iustin Pop

241 f48148c3 Iustin Pop
    This should check the passed set of parameters for
242 f48148c3 Iustin Pop
    validity. Classes should extend, not replace, this function.
243 f48148c3 Iustin Pop

244 f48148c3 Iustin Pop
    @type hvparams:  dict
245 f48148c3 Iustin Pop
    @param hvparams: dictionary with parameter names/value
246 f48148c3 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
247 f48148c3 Iustin Pop

248 f48148c3 Iustin Pop
    """
249 f48148c3 Iustin Pop
    for key in hvparams:
250 f48148c3 Iustin Pop
      if key not in cls.PARAMETERS:
251 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' is not supported" % key)
252 205ab586 Iustin Pop
253 205ab586 Iustin Pop
    # cheap tests that run on the master, should not access the world
254 205ab586 Iustin Pop
    for name, (required, check_fn, errstr, _, _) in cls.PARAMETERS.items():
255 205ab586 Iustin Pop
      if name not in hvparams:
256 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' is missing" % name)
257 205ab586 Iustin Pop
      value = hvparams[name]
258 205ab586 Iustin Pop
      if not required and not value:
259 205ab586 Iustin Pop
        continue
260 205ab586 Iustin Pop
      if not value:
261 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' is required but"
262 205ab586 Iustin Pop
                                     " is currently not defined" % (name, ))
263 205ab586 Iustin Pop
      if check_fn is not None and not check_fn(value):
264 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' fails syntax"
265 205ab586 Iustin Pop
                                     " check: %s (current value: '%s')" %
266 205ab586 Iustin Pop
                                     (name, errstr, value))
267 205ab586 Iustin Pop
268 205ab586 Iustin Pop
  @classmethod
269 205ab586 Iustin Pop
  def ValidateParameters(cls, hvparams):
270 f48148c3 Iustin Pop
    """Check the given parameters for validity.
271 f48148c3 Iustin Pop

272 f48148c3 Iustin Pop
    This should check the passed set of parameters for
273 f48148c3 Iustin Pop
    validity. Classes should extend, not replace, this function.
274 f48148c3 Iustin Pop

275 f48148c3 Iustin Pop
    @type hvparams:  dict
276 f48148c3 Iustin Pop
    @param hvparams: dictionary with parameter names/value
277 f48148c3 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
278 f48148c3 Iustin Pop

279 f48148c3 Iustin Pop
    """
280 205ab586 Iustin Pop
    for name, (required, _, _, check_fn, errstr) in cls.PARAMETERS.items():
281 205ab586 Iustin Pop
      value = hvparams[name]
282 205ab586 Iustin Pop
      if not required and not value:
283 205ab586 Iustin Pop
        continue
284 205ab586 Iustin Pop
      if check_fn is not None and not check_fn(value):
285 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' fails"
286 205ab586 Iustin Pop
                                     " validation: %s (current value: '%s')" %
287 205ab586 Iustin Pop
                                     (name, errstr, value))
288 572e52bf Iustin Pop
289 572e52bf Iustin Pop
  def GetLinuxNodeInfo(self):
290 572e52bf Iustin Pop
    """For linux systems, return actual OS information.
291 572e52bf Iustin Pop

292 572e52bf Iustin Pop
    This is an abstraction for all non-hypervisor-based classes, where
293 572e52bf Iustin Pop
    the node actually sees all the memory and CPUs via the /proc
294 572e52bf Iustin Pop
    interface and standard commands. The other case if for example
295 572e52bf Iustin Pop
    xen, where you only see the hardware resources via xen-specific
296 572e52bf Iustin Pop
    tools.
297 572e52bf Iustin Pop

298 572e52bf Iustin Pop
    @return: a dict with the following keys (values in MiB):
299 572e52bf Iustin Pop
          - memory_total: the total memory size on the node
300 572e52bf Iustin Pop
          - memory_free: the available memory on the node for instances
301 572e52bf Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
302 572e52bf Iustin Pop

303 572e52bf Iustin Pop
    """
304 572e52bf Iustin Pop
    try:
305 572e52bf Iustin Pop
      fh = file("/proc/meminfo")
306 572e52bf Iustin Pop
      try:
307 572e52bf Iustin Pop
        data = fh.readlines()
308 572e52bf Iustin Pop
      finally:
309 572e52bf Iustin Pop
        fh.close()
310 572e52bf Iustin Pop
    except EnvironmentError, err:
311 572e52bf Iustin Pop
      raise errors.HypervisorError("Failed to list node info: %s" % (err,))
312 572e52bf Iustin Pop
313 572e52bf Iustin Pop
    result = {}
314 572e52bf Iustin Pop
    sum_free = 0
315 572e52bf Iustin Pop
    try:
316 572e52bf Iustin Pop
      for line in data:
317 572e52bf Iustin Pop
        splitfields = line.split(":", 1)
318 572e52bf Iustin Pop
319 572e52bf Iustin Pop
        if len(splitfields) > 1:
320 572e52bf Iustin Pop
          key = splitfields[0].strip()
321 572e52bf Iustin Pop
          val = splitfields[1].strip()
322 572e52bf Iustin Pop
          if key == 'MemTotal':
323 572e52bf Iustin Pop
            result['memory_total'] = int(val.split()[0])/1024
324 572e52bf Iustin Pop
          elif key in ('MemFree', 'Buffers', 'Cached'):
325 572e52bf Iustin Pop
            sum_free += int(val.split()[0])/1024
326 572e52bf Iustin Pop
          elif key == 'Active':
327 572e52bf Iustin Pop
            result['memory_dom0'] = int(val.split()[0])/1024
328 572e52bf Iustin Pop
    except (ValueError, TypeError), err:
329 572e52bf Iustin Pop
      raise errors.HypervisorError("Failed to compute memory usage: %s" %
330 572e52bf Iustin Pop
                                   (err,))
331 572e52bf Iustin Pop
    result['memory_free'] = sum_free
332 572e52bf Iustin Pop
333 572e52bf Iustin Pop
    cpu_total = 0
334 572e52bf Iustin Pop
    try:
335 572e52bf Iustin Pop
      fh = open("/proc/cpuinfo")
336 572e52bf Iustin Pop
      try:
337 572e52bf Iustin Pop
        cpu_total = len(re.findall("(?m)^processor\s*:\s*[0-9]+\s*$",
338 572e52bf Iustin Pop
                                   fh.read()))
339 572e52bf Iustin Pop
      finally:
340 572e52bf Iustin Pop
        fh.close()
341 572e52bf Iustin Pop
    except EnvironmentError, err:
342 572e52bf Iustin Pop
      raise errors.HypervisorError("Failed to list node info: %s" % (err,))
343 572e52bf Iustin Pop
    result['cpu_total'] = cpu_total
344 572e52bf Iustin Pop
    # FIXME: export correct data here
345 572e52bf Iustin Pop
    result['cpu_nodes'] = 1
346 572e52bf Iustin Pop
    result['cpu_sockets'] = 1
347 572e52bf Iustin Pop
348 572e52bf Iustin Pop
    return result