Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_base.py @ 9b94905f

History | View | Annotate | Download (12 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 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 205ab586 Iustin Pop
48 205ab586 Iustin Pop
49 205ab586 Iustin Pop
# Read the BaseHypervisor.PARAMETERS docstring for the syntax of the
50 205ab586 Iustin Pop
# _CHECK values
51 205ab586 Iustin Pop
52 205ab586 Iustin Pop
# must be afile
53 17c61836 Guido Trotter
_FILE_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
54 205ab586 Iustin Pop
              os.path.isfile, "not found or not a file")
55 205ab586 Iustin Pop
56 205ab586 Iustin Pop
# must be a directory
57 17c61836 Guido Trotter
_DIR_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
58 205ab586 Iustin Pop
             os.path.isdir, "not found or not a directory")
59 205ab586 Iustin Pop
60 205ab586 Iustin Pop
# nice wrappers for users
61 205ab586 Iustin Pop
REQ_FILE_CHECK = (True, ) + _FILE_CHECK
62 205ab586 Iustin Pop
OPT_FILE_CHECK = (False, ) + _FILE_CHECK
63 205ab586 Iustin Pop
REQ_DIR_CHECK = (True, ) + _DIR_CHECK
64 205ab586 Iustin Pop
OPT_DIR_CHECK = (False, ) + _DIR_CHECK
65 205ab586 Iustin Pop
66 205ab586 Iustin Pop
# no checks at all
67 205ab586 Iustin Pop
NO_CHECK = (False, None, None, None, None)
68 205ab586 Iustin Pop
69 205ab586 Iustin Pop
# required, but no other checks
70 205ab586 Iustin Pop
REQUIRED_CHECK = (True, None, None, None, None)
71 205ab586 Iustin Pop
72 d73ef63f Michael Hanselmann
73 205ab586 Iustin Pop
def ParamInSet(required, my_set):
74 205ab586 Iustin Pop
  """Builds parameter checker for set membership.
75 205ab586 Iustin Pop

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

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

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

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

103 65a6f9b7 Michael Hanselmann
  """
104 205ab586 Iustin Pop
  PARAMETERS = {}
105 e1b8653f Guido Trotter
  ANCILLARY_FILES = []
106 f48148c3 Iustin Pop
107 65a6f9b7 Michael Hanselmann
  def __init__(self):
108 65a6f9b7 Michael Hanselmann
    pass
109 65a6f9b7 Michael Hanselmann
110 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
111 65a6f9b7 Michael Hanselmann
    """Start an instance."""
112 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
113 65a6f9b7 Michael Hanselmann
114 07b49e41 Guido Trotter
  def StopInstance(self, instance, force=False, retry=False):
115 07b49e41 Guido Trotter
    """Stop an instance
116 07b49e41 Guido Trotter

117 07b49e41 Guido Trotter
    @type instance: L{objects.Instance}
118 07b49e41 Guido Trotter
    @param instance: instance to stop
119 07b49e41 Guido Trotter
    @type force: boolean
120 07b49e41 Guido Trotter
    @param force: whether to do a "hard" stop (destroy)
121 07b49e41 Guido Trotter
    @type retry: boolean
122 07b49e41 Guido Trotter
    @param retry: whether this is just a retry call
123 07b49e41 Guido Trotter

124 07b49e41 Guido Trotter
    """
125 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
126 65a6f9b7 Michael Hanselmann
127 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
128 65a6f9b7 Michael Hanselmann
    """Reboot an instance."""
129 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
130 65a6f9b7 Michael Hanselmann
131 65a6f9b7 Michael Hanselmann
  def ListInstances(self):
132 65a6f9b7 Michael Hanselmann
    """Get the list of running instances."""
133 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
134 65a6f9b7 Michael Hanselmann
135 65a6f9b7 Michael Hanselmann
  def GetInstanceInfo(self, instance_name):
136 65a6f9b7 Michael Hanselmann
    """Get instance properties.
137 65a6f9b7 Michael Hanselmann

138 cd42d0ad Guido Trotter
    @type instance_name: string
139 c41eea6e Iustin Pop
    @param instance_name: the instance name
140 65a6f9b7 Michael Hanselmann

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

143 65a6f9b7 Michael Hanselmann
    """
144 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
145 65a6f9b7 Michael Hanselmann
146 65a6f9b7 Michael Hanselmann
  def GetAllInstancesInfo(self):
147 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
148 65a6f9b7 Michael Hanselmann

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

151 65a6f9b7 Michael Hanselmann
    """
152 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
153 65a6f9b7 Michael Hanselmann
154 65a6f9b7 Michael Hanselmann
  def GetNodeInfo(self):
155 65a6f9b7 Michael Hanselmann
    """Return information about the node.
156 65a6f9b7 Michael Hanselmann

157 c41eea6e Iustin Pop
    @return: a dict with the following keys (values in MiB):
158 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
159 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
160 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
161 65a6f9b7 Michael Hanselmann

162 65a6f9b7 Michael Hanselmann
    """
163 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
164 65a6f9b7 Michael Hanselmann
165 637ce7f9 Guido Trotter
  @classmethod
166 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
167 65a6f9b7 Michael Hanselmann
    """Return a command for connecting to the console of an instance.
168 65a6f9b7 Michael Hanselmann

169 65a6f9b7 Michael Hanselmann
    """
170 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
171 65a6f9b7 Michael Hanselmann
172 e1b8653f Guido Trotter
  @classmethod
173 e1b8653f Guido Trotter
  def GetAncillaryFiles(cls):
174 e1b8653f Guido Trotter
    """Return a list of ancillary files to be copied to all nodes as ancillary
175 e1b8653f Guido Trotter
    configuration files.
176 e1b8653f Guido Trotter

177 e1b8653f Guido Trotter
    @rtype: list of strings
178 e1b8653f Guido Trotter
    @return: list of absolute paths of files to ship cluster-wide
179 e1b8653f Guido Trotter

180 e1b8653f Guido Trotter
    """
181 e1b8653f Guido Trotter
    # By default we return a member variable, so that if an hypervisor has just
182 e1b8653f Guido Trotter
    # a static list of files it doesn't have to override this function.
183 e1b8653f Guido Trotter
    return cls.ANCILLARY_FILES
184 e1b8653f Guido Trotter
185 65a6f9b7 Michael Hanselmann
  def Verify(self):
186 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
187 65a6f9b7 Michael Hanselmann

188 65a6f9b7 Michael Hanselmann
    """
189 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
190 6e7275c0 Iustin Pop
191 cd42d0ad Guido Trotter
  def MigrationInfo(self, instance):
192 cd42d0ad Guido Trotter
    """Get instance information to perform a migration.
193 cd42d0ad Guido Trotter

194 cd42d0ad Guido Trotter
    By default assume no information is needed.
195 cd42d0ad Guido Trotter

196 cd42d0ad Guido Trotter
    @type instance: L{objects.Instance}
197 cd42d0ad Guido Trotter
    @param instance: instance to be migrated
198 cd42d0ad Guido Trotter
    @rtype: string/data (opaque)
199 cd42d0ad Guido Trotter
    @return: instance migration information - serialized form
200 cd42d0ad Guido Trotter

201 cd42d0ad Guido Trotter
    """
202 cd42d0ad Guido Trotter
    return ''
203 cd42d0ad Guido Trotter
204 cd42d0ad Guido Trotter
  def AcceptInstance(self, instance, info, target):
205 cd42d0ad Guido Trotter
    """Prepare to accept an instance.
206 cd42d0ad Guido Trotter

207 cd42d0ad Guido Trotter
    By default assume no preparation is needed.
208 cd42d0ad Guido Trotter

209 cd42d0ad Guido Trotter
    @type instance: L{objects.Instance}
210 cd42d0ad Guido Trotter
    @param instance: instance to be accepted
211 cd42d0ad Guido Trotter
    @type info: string/data (opaque)
212 cd42d0ad Guido Trotter
    @param info: migration information, from the source node
213 cd42d0ad Guido Trotter
    @type target: string
214 cd42d0ad Guido Trotter
    @param target: target host (usually ip), on this node
215 cd42d0ad Guido Trotter

216 cd42d0ad Guido Trotter
    """
217 cd42d0ad Guido Trotter
    pass
218 cd42d0ad Guido Trotter
219 cd42d0ad Guido Trotter
  def FinalizeMigration(self, instance, info, success):
220 cd42d0ad Guido Trotter
    """Finalized an instance migration.
221 cd42d0ad Guido Trotter

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

225 cd42d0ad Guido Trotter
    @type instance: L{objects.Instance}
226 cd42d0ad Guido Trotter
    @param instance: instance whose migration is being aborted
227 cd42d0ad Guido Trotter
    @type info: string/data (opaque)
228 cd42d0ad Guido Trotter
    @param info: migration information, from the source node
229 cd42d0ad Guido Trotter
    @type success: boolean
230 cd42d0ad Guido Trotter
    @param success: whether the migration was a success or a failure
231 cd42d0ad Guido Trotter

232 cd42d0ad Guido Trotter
    """
233 cd42d0ad Guido Trotter
    pass
234 cd42d0ad Guido Trotter
235 6e7275c0 Iustin Pop
  def MigrateInstance(self, name, target, live):
236 6e7275c0 Iustin Pop
    """Migrate an instance.
237 6e7275c0 Iustin Pop

238 cd42d0ad Guido Trotter
    @type name: string
239 cd42d0ad Guido Trotter
    @param name: name of the instance to be migrated
240 cd42d0ad Guido Trotter
    @type target: string
241 cd42d0ad Guido Trotter
    @param target: hostname (usually ip) of the target node
242 cd42d0ad Guido Trotter
    @type live: boolean
243 cd42d0ad Guido Trotter
    @param live: whether to do a live or non-live migration
244 6e7275c0 Iustin Pop

245 6e7275c0 Iustin Pop
    """
246 6e7275c0 Iustin Pop
    raise NotImplementedError
247 f48148c3 Iustin Pop
248 f48148c3 Iustin Pop
  @classmethod
249 f48148c3 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
250 f48148c3 Iustin Pop
    """Check the given parameters for validity.
251 f48148c3 Iustin Pop

252 f48148c3 Iustin Pop
    This should check the passed set of parameters for
253 f48148c3 Iustin Pop
    validity. Classes should extend, not replace, this function.
254 f48148c3 Iustin Pop

255 f48148c3 Iustin Pop
    @type hvparams:  dict
256 f48148c3 Iustin Pop
    @param hvparams: dictionary with parameter names/value
257 f48148c3 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
258 f48148c3 Iustin Pop

259 f48148c3 Iustin Pop
    """
260 f48148c3 Iustin Pop
    for key in hvparams:
261 f48148c3 Iustin Pop
      if key not in cls.PARAMETERS:
262 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' is not supported" % key)
263 205ab586 Iustin Pop
264 205ab586 Iustin Pop
    # cheap tests that run on the master, should not access the world
265 205ab586 Iustin Pop
    for name, (required, check_fn, errstr, _, _) in cls.PARAMETERS.items():
266 205ab586 Iustin Pop
      if name not in hvparams:
267 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' is missing" % name)
268 205ab586 Iustin Pop
      value = hvparams[name]
269 205ab586 Iustin Pop
      if not required and not value:
270 205ab586 Iustin Pop
        continue
271 205ab586 Iustin Pop
      if not value:
272 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' is required but"
273 205ab586 Iustin Pop
                                     " is currently not defined" % (name, ))
274 205ab586 Iustin Pop
      if check_fn is not None and not check_fn(value):
275 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' fails syntax"
276 205ab586 Iustin Pop
                                     " check: %s (current value: '%s')" %
277 205ab586 Iustin Pop
                                     (name, errstr, value))
278 205ab586 Iustin Pop
279 205ab586 Iustin Pop
  @classmethod
280 205ab586 Iustin Pop
  def ValidateParameters(cls, hvparams):
281 f48148c3 Iustin Pop
    """Check the given parameters for validity.
282 f48148c3 Iustin Pop

283 f48148c3 Iustin Pop
    This should check the passed set of parameters for
284 f48148c3 Iustin Pop
    validity. Classes should extend, not replace, this function.
285 f48148c3 Iustin Pop

286 f48148c3 Iustin Pop
    @type hvparams:  dict
287 f48148c3 Iustin Pop
    @param hvparams: dictionary with parameter names/value
288 f48148c3 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
289 f48148c3 Iustin Pop

290 f48148c3 Iustin Pop
    """
291 205ab586 Iustin Pop
    for name, (required, _, _, check_fn, errstr) in cls.PARAMETERS.items():
292 205ab586 Iustin Pop
      value = hvparams[name]
293 205ab586 Iustin Pop
      if not required and not value:
294 205ab586 Iustin Pop
        continue
295 205ab586 Iustin Pop
      if check_fn is not None and not check_fn(value):
296 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' fails"
297 205ab586 Iustin Pop
                                     " validation: %s (current value: '%s')" %
298 205ab586 Iustin Pop
                                     (name, errstr, value))
299 572e52bf Iustin Pop
300 f5118ade Iustin Pop
  @classmethod
301 f5118ade Iustin Pop
  def PowercycleNode(cls):
302 f5118ade Iustin Pop
    """Hard powercycle a node using hypervisor specific methods.
303 f5118ade Iustin Pop

304 f5118ade Iustin Pop
    This method should hard powercycle the node, using whatever
305 f5118ade Iustin Pop
    methods the hypervisor provides. Note that this means that all
306 f5118ade Iustin Pop
    instances running on the node must be stopped too.
307 f5118ade Iustin Pop

308 f5118ade Iustin Pop
    """
309 f5118ade Iustin Pop
    raise NotImplementedError
310 f5118ade Iustin Pop
311 f5118ade Iustin Pop
312 572e52bf Iustin Pop
  def GetLinuxNodeInfo(self):
313 572e52bf Iustin Pop
    """For linux systems, return actual OS information.
314 572e52bf Iustin Pop

315 572e52bf Iustin Pop
    This is an abstraction for all non-hypervisor-based classes, where
316 572e52bf Iustin Pop
    the node actually sees all the memory and CPUs via the /proc
317 572e52bf Iustin Pop
    interface and standard commands. The other case if for example
318 572e52bf Iustin Pop
    xen, where you only see the hardware resources via xen-specific
319 572e52bf Iustin Pop
    tools.
320 572e52bf Iustin Pop

321 572e52bf Iustin Pop
    @return: a dict with the following keys (values in MiB):
322 572e52bf Iustin Pop
          - memory_total: the total memory size on the node
323 572e52bf Iustin Pop
          - memory_free: the available memory on the node for instances
324 572e52bf Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
325 572e52bf Iustin Pop

326 572e52bf Iustin Pop
    """
327 572e52bf Iustin Pop
    try:
328 3374afa9 Guido Trotter
      data = utils.ReadFile("/proc/meminfo").splitlines()
329 572e52bf Iustin Pop
    except EnvironmentError, err:
330 572e52bf Iustin Pop
      raise errors.HypervisorError("Failed to list node info: %s" % (err,))
331 572e52bf Iustin Pop
332 572e52bf Iustin Pop
    result = {}
333 572e52bf Iustin Pop
    sum_free = 0
334 572e52bf Iustin Pop
    try:
335 572e52bf Iustin Pop
      for line in data:
336 572e52bf Iustin Pop
        splitfields = line.split(":", 1)
337 572e52bf Iustin Pop
338 572e52bf Iustin Pop
        if len(splitfields) > 1:
339 572e52bf Iustin Pop
          key = splitfields[0].strip()
340 572e52bf Iustin Pop
          val = splitfields[1].strip()
341 572e52bf Iustin Pop
          if key == 'MemTotal':
342 572e52bf Iustin Pop
            result['memory_total'] = int(val.split()[0])/1024
343 572e52bf Iustin Pop
          elif key in ('MemFree', 'Buffers', 'Cached'):
344 572e52bf Iustin Pop
            sum_free += int(val.split()[0])/1024
345 572e52bf Iustin Pop
          elif key == 'Active':
346 572e52bf Iustin Pop
            result['memory_dom0'] = int(val.split()[0])/1024
347 572e52bf Iustin Pop
    except (ValueError, TypeError), err:
348 572e52bf Iustin Pop
      raise errors.HypervisorError("Failed to compute memory usage: %s" %
349 572e52bf Iustin Pop
                                   (err,))
350 572e52bf Iustin Pop
    result['memory_free'] = sum_free
351 572e52bf Iustin Pop
352 572e52bf Iustin Pop
    cpu_total = 0
353 572e52bf Iustin Pop
    try:
354 572e52bf Iustin Pop
      fh = open("/proc/cpuinfo")
355 572e52bf Iustin Pop
      try:
356 572e52bf Iustin Pop
        cpu_total = len(re.findall("(?m)^processor\s*:\s*[0-9]+\s*$",
357 572e52bf Iustin Pop
                                   fh.read()))
358 572e52bf Iustin Pop
      finally:
359 572e52bf Iustin Pop
        fh.close()
360 572e52bf Iustin Pop
    except EnvironmentError, err:
361 572e52bf Iustin Pop
      raise errors.HypervisorError("Failed to list node info: %s" % (err,))
362 572e52bf Iustin Pop
    result['cpu_total'] = cpu_total
363 572e52bf Iustin Pop
    # FIXME: export correct data here
364 572e52bf Iustin Pop
    result['cpu_nodes'] = 1
365 572e52bf Iustin Pop
    result['cpu_sockets'] = 1
366 572e52bf Iustin Pop
367 572e52bf Iustin Pop
    return result
368 f5118ade Iustin Pop
369 f5118ade Iustin Pop
  @classmethod
370 f5118ade Iustin Pop
  def LinuxPowercycle(cls):
371 f5118ade Iustin Pop
    """Linux-specific powercycle method.
372 f5118ade Iustin Pop

373 f5118ade Iustin Pop
    """
374 f5118ade Iustin Pop
    try:
375 f5118ade Iustin Pop
      fd = os.open("/proc/sysrq-trigger", os.O_WRONLY)
376 f5118ade Iustin Pop
      try:
377 f5118ade Iustin Pop
        os.write(fd, "b")
378 f5118ade Iustin Pop
      finally:
379 f5118ade Iustin Pop
        fd.close()
380 f5118ade Iustin Pop
    except OSError:
381 f5118ade Iustin Pop
      logging.exception("Can't open the sysrq-trigger file")
382 f5118ade Iustin Pop
      result = utils.RunCmd(["reboot", "-n", "-f"])
383 f5118ade Iustin Pop
      if not result:
384 f5118ade Iustin Pop
        logging.error("Can't run shutdown: %s", result.output)