Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_base.py @ e695efbf

History | View | Annotate | Download (13.5 kB)

1 65a6f9b7 Michael Hanselmann
#
2 65a6f9b7 Michael Hanselmann
#
3 65a6f9b7 Michael Hanselmann
4 783a6c0b Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010 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 29921401 Iustin Pop
import logging
43 572e52bf Iustin Pop
44 572e52bf Iustin Pop
45 f48148c3 Iustin Pop
from ganeti import errors
46 205ab586 Iustin Pop
from ganeti import utils
47 e71b9ef4 Iustin Pop
from ganeti import constants
48 205ab586 Iustin Pop
49 205ab586 Iustin Pop
50 e3ed5316 Balazs Lecz
def _IsCpuMaskWellFormed(cpu_mask):
51 e3ed5316 Balazs Lecz
  try:
52 e3ed5316 Balazs Lecz
    cpu_list = utils.ParseCpuMask(cpu_mask)
53 e3ed5316 Balazs Lecz
  except errors.ParseError, _:
54 e3ed5316 Balazs Lecz
    return False
55 e3ed5316 Balazs Lecz
  return isinstance(cpu_list, list) and len(cpu_list) > 0
56 e3ed5316 Balazs Lecz
57 e3ed5316 Balazs Lecz
58 205ab586 Iustin Pop
# Read the BaseHypervisor.PARAMETERS docstring for the syntax of the
59 205ab586 Iustin Pop
# _CHECK values
60 205ab586 Iustin Pop
61 205ab586 Iustin Pop
# must be afile
62 17c61836 Guido Trotter
_FILE_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
63 205ab586 Iustin Pop
              os.path.isfile, "not found or not a file")
64 205ab586 Iustin Pop
65 205ab586 Iustin Pop
# must be a directory
66 17c61836 Guido Trotter
_DIR_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
67 205ab586 Iustin Pop
             os.path.isdir, "not found or not a directory")
68 205ab586 Iustin Pop
69 e3ed5316 Balazs Lecz
# CPU mask must be well-formed
70 e3ed5316 Balazs Lecz
# TODO: implement node level check for the CPU mask
71 e3ed5316 Balazs Lecz
_CPU_MASK_CHECK = (_IsCpuMaskWellFormed,
72 e3ed5316 Balazs Lecz
                   "CPU mask definition is not well-formed",
73 e3ed5316 Balazs Lecz
                   None, None)
74 e3ed5316 Balazs Lecz
75 205ab586 Iustin Pop
# nice wrappers for users
76 205ab586 Iustin Pop
REQ_FILE_CHECK = (True, ) + _FILE_CHECK
77 205ab586 Iustin Pop
OPT_FILE_CHECK = (False, ) + _FILE_CHECK
78 205ab586 Iustin Pop
REQ_DIR_CHECK = (True, ) + _DIR_CHECK
79 205ab586 Iustin Pop
OPT_DIR_CHECK = (False, ) + _DIR_CHECK
80 78411c60 Iustin Pop
NET_PORT_CHECK = (True, lambda x: x > 0 and x < 65535, "invalid port number",
81 78411c60 Iustin Pop
                  None, None)
82 e3ed5316 Balazs Lecz
OPT_CPU_MASK_CHECK = (False, ) + _CPU_MASK_CHECK
83 e3ed5316 Balazs Lecz
REQ_CPU_MASK_CHECK = (True, ) + _CPU_MASK_CHECK
84 205ab586 Iustin Pop
85 205ab586 Iustin Pop
# no checks at all
86 205ab586 Iustin Pop
NO_CHECK = (False, None, None, None, None)
87 205ab586 Iustin Pop
88 205ab586 Iustin Pop
# required, but no other checks
89 205ab586 Iustin Pop
REQUIRED_CHECK = (True, None, None, None, None)
90 205ab586 Iustin Pop
91 e71b9ef4 Iustin Pop
# migration type
92 783a6c0b Iustin Pop
MIGRATION_MODE_CHECK = (True, lambda x: x in constants.HT_MIGRATION_MODES,
93 783a6c0b Iustin Pop
                        "invalid migration mode", None, None)
94 e71b9ef4 Iustin Pop
95 d73ef63f Michael Hanselmann
96 205ab586 Iustin Pop
def ParamInSet(required, my_set):
97 205ab586 Iustin Pop
  """Builds parameter checker for set membership.
98 205ab586 Iustin Pop

99 205ab586 Iustin Pop
  @type required: boolean
100 205ab586 Iustin Pop
  @param required: whether this is a required parameter
101 205ab586 Iustin Pop
  @type my_set: tuple, list or set
102 205ab586 Iustin Pop
  @param my_set: allowed values set
103 205ab586 Iustin Pop

104 205ab586 Iustin Pop
  """
105 205ab586 Iustin Pop
  fn = lambda x: x in my_set
106 ab3e6da8 Iustin Pop
  err = ("The value must be one of: %s" % utils.CommaJoin(my_set))
107 205ab586 Iustin Pop
  return (required, fn, err, None, None)
108 f48148c3 Iustin Pop
109 f48148c3 Iustin Pop
110 65a6f9b7 Michael Hanselmann
class BaseHypervisor(object):
111 65a6f9b7 Michael Hanselmann
  """Abstract virtualisation technology interface
112 65a6f9b7 Michael Hanselmann

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

116 205ab586 Iustin Pop
  @cvar PARAMETERS: a dict of parameter name: check type; the check type is
117 205ab586 Iustin Pop
      a five-tuple containing:
118 205ab586 Iustin Pop
          - the required flag (boolean)
119 205ab586 Iustin Pop
          - a function to check for syntax, that will be used in
120 205ab586 Iustin Pop
            L{CheckParameterSyntax}, in the master daemon process
121 205ab586 Iustin Pop
          - an error message for the above function
122 205ab586 Iustin Pop
          - a function to check for parameter validity on the remote node,
123 205ab586 Iustin Pop
            in the L{ValidateParameters} function
124 205ab586 Iustin Pop
          - an error message for the above function
125 d271c6fd Iustin Pop
  @type CAN_MIGRATE: boolean
126 d271c6fd Iustin Pop
  @cvar CAN_MIGRATE: whether this hypervisor can do migration (either
127 d271c6fd Iustin Pop
      live or non-live)
128 205ab586 Iustin Pop

129 65a6f9b7 Michael Hanselmann
  """
130 205ab586 Iustin Pop
  PARAMETERS = {}
131 e1b8653f Guido Trotter
  ANCILLARY_FILES = []
132 d271c6fd Iustin Pop
  CAN_MIGRATE = False
133 f48148c3 Iustin Pop
134 65a6f9b7 Michael Hanselmann
  def __init__(self):
135 65a6f9b7 Michael Hanselmann
    pass
136 65a6f9b7 Michael Hanselmann
137 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
138 65a6f9b7 Michael Hanselmann
    """Start an instance."""
139 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
140 65a6f9b7 Michael Hanselmann
141 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
142 07b49e41 Guido Trotter
    """Stop an instance
143 07b49e41 Guido Trotter

144 07b49e41 Guido Trotter
    @type instance: L{objects.Instance}
145 07b49e41 Guido Trotter
    @param instance: instance to stop
146 07b49e41 Guido Trotter
    @type force: boolean
147 07b49e41 Guido Trotter
    @param force: whether to do a "hard" stop (destroy)
148 07b49e41 Guido Trotter
    @type retry: boolean
149 07b49e41 Guido Trotter
    @param retry: whether this is just a retry call
150 bbcf7ad0 Iustin Pop
    @type name: string or None
151 bbcf7ad0 Iustin Pop
    @param name: if this parameter is passed, the the instance object
152 bbcf7ad0 Iustin Pop
        should not be used (will be passed as None), and the shutdown
153 bbcf7ad0 Iustin Pop
        must be done by name only
154 07b49e41 Guido Trotter

155 07b49e41 Guido Trotter
    """
156 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
157 65a6f9b7 Michael Hanselmann
158 f28ec899 Guido Trotter
  def CleanupInstance(self, instance_name):
159 f28ec899 Guido Trotter
    """Cleanup after a stopped instance
160 f28ec899 Guido Trotter

161 f28ec899 Guido Trotter
    This is an optional method, used by hypervisors that need to cleanup after
162 f28ec899 Guido Trotter
    an instance has been stopped.
163 f28ec899 Guido Trotter

164 f28ec899 Guido Trotter
    @type instance_name: string
165 f28ec899 Guido Trotter
    @param instance_name: instance name to cleanup after
166 f28ec899 Guido Trotter

167 f28ec899 Guido Trotter
    """
168 f28ec899 Guido Trotter
    pass
169 f28ec899 Guido Trotter
170 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
171 65a6f9b7 Michael Hanselmann
    """Reboot an instance."""
172 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
173 65a6f9b7 Michael Hanselmann
174 65a6f9b7 Michael Hanselmann
  def ListInstances(self):
175 65a6f9b7 Michael Hanselmann
    """Get the list of running instances."""
176 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
177 65a6f9b7 Michael Hanselmann
178 65a6f9b7 Michael Hanselmann
  def GetInstanceInfo(self, instance_name):
179 65a6f9b7 Michael Hanselmann
    """Get instance properties.
180 65a6f9b7 Michael Hanselmann

181 cd42d0ad Guido Trotter
    @type instance_name: string
182 c41eea6e Iustin Pop
    @param instance_name: the instance name
183 65a6f9b7 Michael Hanselmann

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

186 65a6f9b7 Michael Hanselmann
    """
187 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
188 65a6f9b7 Michael Hanselmann
189 65a6f9b7 Michael Hanselmann
  def GetAllInstancesInfo(self):
190 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
191 65a6f9b7 Michael Hanselmann

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

194 65a6f9b7 Michael Hanselmann
    """
195 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
196 65a6f9b7 Michael Hanselmann
197 65a6f9b7 Michael Hanselmann
  def GetNodeInfo(self):
198 65a6f9b7 Michael Hanselmann
    """Return information about the node.
199 65a6f9b7 Michael Hanselmann

200 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
201 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
202 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
203 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
204 65a6f9b7 Michael Hanselmann

205 65a6f9b7 Michael Hanselmann
    """
206 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
207 65a6f9b7 Michael Hanselmann
208 637ce7f9 Guido Trotter
  @classmethod
209 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
210 65a6f9b7 Michael Hanselmann
    """Return a command for connecting to the console of an instance.
211 65a6f9b7 Michael Hanselmann

212 65a6f9b7 Michael Hanselmann
    """
213 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
214 65a6f9b7 Michael Hanselmann
215 e1b8653f Guido Trotter
  @classmethod
216 e1b8653f Guido Trotter
  def GetAncillaryFiles(cls):
217 e1b8653f Guido Trotter
    """Return a list of ancillary files to be copied to all nodes as ancillary
218 e1b8653f Guido Trotter
    configuration files.
219 e1b8653f Guido Trotter

220 e1b8653f Guido Trotter
    @rtype: list of strings
221 e1b8653f Guido Trotter
    @return: list of absolute paths of files to ship cluster-wide
222 e1b8653f Guido Trotter

223 e1b8653f Guido Trotter
    """
224 e1b8653f Guido Trotter
    # By default we return a member variable, so that if an hypervisor has just
225 e1b8653f Guido Trotter
    # a static list of files it doesn't have to override this function.
226 e1b8653f Guido Trotter
    return cls.ANCILLARY_FILES
227 e1b8653f Guido Trotter
228 65a6f9b7 Michael Hanselmann
  def Verify(self):
229 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
230 65a6f9b7 Michael Hanselmann

231 65a6f9b7 Michael Hanselmann
    """
232 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
233 6e7275c0 Iustin Pop
234 7260cfbe Iustin Pop
  def MigrationInfo(self, instance): # pylint: disable-msg=R0201,W0613
235 cd42d0ad Guido Trotter
    """Get instance information to perform a migration.
236 cd42d0ad Guido Trotter

237 cd42d0ad Guido Trotter
    By default assume no information is needed.
238 cd42d0ad Guido Trotter

239 cd42d0ad Guido Trotter
    @type instance: L{objects.Instance}
240 cd42d0ad Guido Trotter
    @param instance: instance to be migrated
241 cd42d0ad Guido Trotter
    @rtype: string/data (opaque)
242 cd42d0ad Guido Trotter
    @return: instance migration information - serialized form
243 cd42d0ad Guido Trotter

244 cd42d0ad Guido Trotter
    """
245 cd42d0ad Guido Trotter
    return ''
246 cd42d0ad Guido Trotter
247 cd42d0ad Guido Trotter
  def AcceptInstance(self, instance, info, target):
248 cd42d0ad Guido Trotter
    """Prepare to accept an instance.
249 cd42d0ad Guido Trotter

250 cd42d0ad Guido Trotter
    By default assume no preparation is needed.
251 cd42d0ad Guido Trotter

252 cd42d0ad Guido Trotter
    @type instance: L{objects.Instance}
253 cd42d0ad Guido Trotter
    @param instance: instance to be accepted
254 cd42d0ad Guido Trotter
    @type info: string/data (opaque)
255 cd42d0ad Guido Trotter
    @param info: migration information, from the source node
256 cd42d0ad Guido Trotter
    @type target: string
257 cd42d0ad Guido Trotter
    @param target: target host (usually ip), on this node
258 cd42d0ad Guido Trotter

259 cd42d0ad Guido Trotter
    """
260 cd42d0ad Guido Trotter
    pass
261 cd42d0ad Guido Trotter
262 cd42d0ad Guido Trotter
  def FinalizeMigration(self, instance, info, success):
263 cd42d0ad Guido Trotter
    """Finalized an instance migration.
264 cd42d0ad Guido Trotter

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

268 cd42d0ad Guido Trotter
    @type instance: L{objects.Instance}
269 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
270 cd42d0ad Guido Trotter
    @type info: string/data (opaque)
271 cd42d0ad Guido Trotter
    @param info: migration information, from the source node
272 cd42d0ad Guido Trotter
    @type success: boolean
273 cd42d0ad Guido Trotter
    @param success: whether the migration was a success or a failure
274 cd42d0ad Guido Trotter

275 cd42d0ad Guido Trotter
    """
276 cd42d0ad Guido Trotter
    pass
277 cd42d0ad Guido Trotter
278 58d38b02 Iustin Pop
  def MigrateInstance(self, instance, target, live):
279 6e7275c0 Iustin Pop
    """Migrate an instance.
280 6e7275c0 Iustin Pop

281 3a488770 Iustin Pop
    @type instance: L{objects.Instance}
282 9044275a Michael Hanselmann
    @param instance: the instance to be migrated
283 cd42d0ad Guido Trotter
    @type target: string
284 cd42d0ad Guido Trotter
    @param target: hostname (usually ip) of the target node
285 cd42d0ad Guido Trotter
    @type live: boolean
286 cd42d0ad Guido Trotter
    @param live: whether to do a live or non-live migration
287 6e7275c0 Iustin Pop

288 6e7275c0 Iustin Pop
    """
289 6e7275c0 Iustin Pop
    raise NotImplementedError
290 f48148c3 Iustin Pop
291 f48148c3 Iustin Pop
  @classmethod
292 f48148c3 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
293 f48148c3 Iustin Pop
    """Check the given parameters for validity.
294 f48148c3 Iustin Pop

295 f48148c3 Iustin Pop
    This should check the passed set of parameters for
296 f48148c3 Iustin Pop
    validity. Classes should extend, not replace, this function.
297 f48148c3 Iustin Pop

298 f48148c3 Iustin Pop
    @type hvparams:  dict
299 f48148c3 Iustin Pop
    @param hvparams: dictionary with parameter names/value
300 f48148c3 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
301 f48148c3 Iustin Pop

302 f48148c3 Iustin Pop
    """
303 f48148c3 Iustin Pop
    for key in hvparams:
304 f48148c3 Iustin Pop
      if key not in cls.PARAMETERS:
305 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' is not supported" % key)
306 205ab586 Iustin Pop
307 205ab586 Iustin Pop
    # cheap tests that run on the master, should not access the world
308 205ab586 Iustin Pop
    for name, (required, check_fn, errstr, _, _) in cls.PARAMETERS.items():
309 205ab586 Iustin Pop
      if name not in hvparams:
310 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' is missing" % name)
311 205ab586 Iustin Pop
      value = hvparams[name]
312 205ab586 Iustin Pop
      if not required and not value:
313 205ab586 Iustin Pop
        continue
314 205ab586 Iustin Pop
      if not value:
315 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' is required but"
316 205ab586 Iustin Pop
                                     " is currently not defined" % (name, ))
317 205ab586 Iustin Pop
      if check_fn is not None and not check_fn(value):
318 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' fails syntax"
319 205ab586 Iustin Pop
                                     " check: %s (current value: '%s')" %
320 205ab586 Iustin Pop
                                     (name, errstr, value))
321 205ab586 Iustin Pop
322 205ab586 Iustin Pop
  @classmethod
323 205ab586 Iustin Pop
  def ValidateParameters(cls, hvparams):
324 f48148c3 Iustin Pop
    """Check the given parameters for validity.
325 f48148c3 Iustin Pop

326 f48148c3 Iustin Pop
    This should check the passed set of parameters for
327 f48148c3 Iustin Pop
    validity. Classes should extend, not replace, this function.
328 f48148c3 Iustin Pop

329 f48148c3 Iustin Pop
    @type hvparams:  dict
330 f48148c3 Iustin Pop
    @param hvparams: dictionary with parameter names/value
331 f48148c3 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
332 f48148c3 Iustin Pop

333 f48148c3 Iustin Pop
    """
334 205ab586 Iustin Pop
    for name, (required, _, _, check_fn, errstr) in cls.PARAMETERS.items():
335 205ab586 Iustin Pop
      value = hvparams[name]
336 205ab586 Iustin Pop
      if not required and not value:
337 205ab586 Iustin Pop
        continue
338 205ab586 Iustin Pop
      if check_fn is not None and not check_fn(value):
339 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' fails"
340 205ab586 Iustin Pop
                                     " validation: %s (current value: '%s')" %
341 205ab586 Iustin Pop
                                     (name, errstr, value))
342 572e52bf Iustin Pop
343 f5118ade Iustin Pop
  @classmethod
344 f5118ade Iustin Pop
  def PowercycleNode(cls):
345 f5118ade Iustin Pop
    """Hard powercycle a node using hypervisor specific methods.
346 f5118ade Iustin Pop

347 f5118ade Iustin Pop
    This method should hard powercycle the node, using whatever
348 f5118ade Iustin Pop
    methods the hypervisor provides. Note that this means that all
349 f5118ade Iustin Pop
    instances running on the node must be stopped too.
350 f5118ade Iustin Pop

351 f5118ade Iustin Pop
    """
352 f5118ade Iustin Pop
    raise NotImplementedError
353 f5118ade Iustin Pop
354 94fed7da Iustin Pop
  @staticmethod
355 94fed7da Iustin Pop
  def GetLinuxNodeInfo():
356 572e52bf Iustin Pop
    """For linux systems, return actual OS information.
357 572e52bf Iustin Pop

358 572e52bf Iustin Pop
    This is an abstraction for all non-hypervisor-based classes, where
359 572e52bf Iustin Pop
    the node actually sees all the memory and CPUs via the /proc
360 572e52bf Iustin Pop
    interface and standard commands. The other case if for example
361 572e52bf Iustin Pop
    xen, where you only see the hardware resources via xen-specific
362 572e52bf Iustin Pop
    tools.
363 572e52bf Iustin Pop

364 572e52bf Iustin Pop
    @return: a dict with the following keys (values in MiB):
365 572e52bf Iustin Pop
          - memory_total: the total memory size on the node
366 572e52bf Iustin Pop
          - memory_free: the available memory on the node for instances
367 572e52bf Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
368 572e52bf Iustin Pop

369 572e52bf Iustin Pop
    """
370 572e52bf Iustin Pop
    try:
371 3374afa9 Guido Trotter
      data = utils.ReadFile("/proc/meminfo").splitlines()
372 572e52bf Iustin Pop
    except EnvironmentError, err:
373 572e52bf Iustin Pop
      raise errors.HypervisorError("Failed to list node info: %s" % (err,))
374 572e52bf Iustin Pop
375 572e52bf Iustin Pop
    result = {}
376 572e52bf Iustin Pop
    sum_free = 0
377 572e52bf Iustin Pop
    try:
378 572e52bf Iustin Pop
      for line in data:
379 572e52bf Iustin Pop
        splitfields = line.split(":", 1)
380 572e52bf Iustin Pop
381 572e52bf Iustin Pop
        if len(splitfields) > 1:
382 572e52bf Iustin Pop
          key = splitfields[0].strip()
383 572e52bf Iustin Pop
          val = splitfields[1].strip()
384 572e52bf Iustin Pop
          if key == 'MemTotal':
385 572e52bf Iustin Pop
            result['memory_total'] = int(val.split()[0])/1024
386 572e52bf Iustin Pop
          elif key in ('MemFree', 'Buffers', 'Cached'):
387 572e52bf Iustin Pop
            sum_free += int(val.split()[0])/1024
388 572e52bf Iustin Pop
          elif key == 'Active':
389 572e52bf Iustin Pop
            result['memory_dom0'] = int(val.split()[0])/1024
390 572e52bf Iustin Pop
    except (ValueError, TypeError), err:
391 572e52bf Iustin Pop
      raise errors.HypervisorError("Failed to compute memory usage: %s" %
392 572e52bf Iustin Pop
                                   (err,))
393 572e52bf Iustin Pop
    result['memory_free'] = sum_free
394 572e52bf Iustin Pop
395 572e52bf Iustin Pop
    cpu_total = 0
396 572e52bf Iustin Pop
    try:
397 572e52bf Iustin Pop
      fh = open("/proc/cpuinfo")
398 572e52bf Iustin Pop
      try:
399 572e52bf Iustin Pop
        cpu_total = len(re.findall("(?m)^processor\s*:\s*[0-9]+\s*$",
400 572e52bf Iustin Pop
                                   fh.read()))
401 572e52bf Iustin Pop
      finally:
402 572e52bf Iustin Pop
        fh.close()
403 572e52bf Iustin Pop
    except EnvironmentError, err:
404 572e52bf Iustin Pop
      raise errors.HypervisorError("Failed to list node info: %s" % (err,))
405 572e52bf Iustin Pop
    result['cpu_total'] = cpu_total
406 572e52bf Iustin Pop
    # FIXME: export correct data here
407 572e52bf Iustin Pop
    result['cpu_nodes'] = 1
408 572e52bf Iustin Pop
    result['cpu_sockets'] = 1
409 572e52bf Iustin Pop
410 572e52bf Iustin Pop
    return result
411 f5118ade Iustin Pop
412 f5118ade Iustin Pop
  @classmethod
413 f5118ade Iustin Pop
  def LinuxPowercycle(cls):
414 f5118ade Iustin Pop
    """Linux-specific powercycle method.
415 f5118ade Iustin Pop

416 f5118ade Iustin Pop
    """
417 f5118ade Iustin Pop
    try:
418 f5118ade Iustin Pop
      fd = os.open("/proc/sysrq-trigger", os.O_WRONLY)
419 f5118ade Iustin Pop
      try:
420 f5118ade Iustin Pop
        os.write(fd, "b")
421 f5118ade Iustin Pop
      finally:
422 f5118ade Iustin Pop
        fd.close()
423 f5118ade Iustin Pop
    except OSError:
424 f5118ade Iustin Pop
      logging.exception("Can't open the sysrq-trigger file")
425 f5118ade Iustin Pop
      result = utils.RunCmd(["reboot", "-n", "-f"])
426 f5118ade Iustin Pop
      if not result:
427 f5118ade Iustin Pop
        logging.error("Can't run shutdown: %s", result.output)