Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_base.py @ 58e4df3c

History | View | Annotate | Download (23.6 kB)

1 65a6f9b7 Michael Hanselmann
#
2 65a6f9b7 Michael Hanselmann
#
3 65a6f9b7 Michael Hanselmann
4 53fde1ac Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2012, 2013 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 9e42978e Jose A. Lopes
from ganeti import constants
46 f48148c3 Iustin Pop
from ganeti import errors
47 9e42978e Jose A. Lopes
from ganeti import objects
48 205ab586 Iustin Pop
from ganeti import utils
49 205ab586 Iustin Pop
50 205ab586 Iustin Pop
51 e3ed5316 Balazs Lecz
def _IsCpuMaskWellFormed(cpu_mask):
52 b9511385 Tsachy Shacham
  """Verifies if the given single CPU mask is valid
53 b9511385 Tsachy Shacham

54 b9511385 Tsachy Shacham
  The single CPU mask should be in the form "a,b,c,d", where each
55 b9511385 Tsachy Shacham
  letter is a positive number or range.
56 b9511385 Tsachy Shacham

57 b9511385 Tsachy Shacham
  """
58 e3ed5316 Balazs Lecz
  try:
59 e3ed5316 Balazs Lecz
    cpu_list = utils.ParseCpuMask(cpu_mask)
60 e3ed5316 Balazs Lecz
  except errors.ParseError, _:
61 e3ed5316 Balazs Lecz
    return False
62 e3ed5316 Balazs Lecz
  return isinstance(cpu_list, list) and len(cpu_list) > 0
63 e3ed5316 Balazs Lecz
64 e3ed5316 Balazs Lecz
65 b9511385 Tsachy Shacham
def _IsMultiCpuMaskWellFormed(cpu_mask):
66 b9511385 Tsachy Shacham
  """Verifies if the given multiple CPU mask is valid
67 b9511385 Tsachy Shacham

68 b9511385 Tsachy Shacham
  A valid multiple CPU mask is in the form "a:b:c:d", where each
69 b9511385 Tsachy Shacham
  letter is a single CPU mask.
70 b9511385 Tsachy Shacham

71 b9511385 Tsachy Shacham
  """
72 b9511385 Tsachy Shacham
  try:
73 b9511385 Tsachy Shacham
    utils.ParseMultiCpuMask(cpu_mask)
74 b9511385 Tsachy Shacham
  except errors.ParseError, _:
75 b9511385 Tsachy Shacham
    return False
76 b9511385 Tsachy Shacham
77 b9511385 Tsachy Shacham
  return True
78 b9511385 Tsachy Shacham
79 b9511385 Tsachy Shacham
80 205ab586 Iustin Pop
# Read the BaseHypervisor.PARAMETERS docstring for the syntax of the
81 205ab586 Iustin Pop
# _CHECK values
82 205ab586 Iustin Pop
83 364e1664 Jose A. Lopes
# must be a file
84 17c61836 Guido Trotter
_FILE_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
85 5ae4945a Iustin Pop
               os.path.isfile, "not found or not a file")
86 205ab586 Iustin Pop
87 f15a6b03 Jose A. Lopes
# must be a file or a URL
88 364e1664 Jose A. Lopes
_FILE_OR_URL_CHECK = (lambda x: utils.IsNormAbsPath(x) or utils.IsUrl(x),
89 f15a6b03 Jose A. Lopes
                      "must be an absolute normalized path or a URL",
90 364e1664 Jose A. Lopes
                      lambda x: os.path.isfile(x) or utils.IsUrl(x),
91 f15a6b03 Jose A. Lopes
                      "not found or not a file or URL")
92 f15a6b03 Jose A. Lopes
93 205ab586 Iustin Pop
# must be a directory
94 17c61836 Guido Trotter
_DIR_CHECK = (utils.IsNormAbsPath, "must be an absolute normalized path",
95 5ae4945a Iustin Pop
              os.path.isdir, "not found or not a directory")
96 205ab586 Iustin Pop
97 e3ed5316 Balazs Lecz
# CPU mask must be well-formed
98 e3ed5316 Balazs Lecz
# TODO: implement node level check for the CPU mask
99 e3ed5316 Balazs Lecz
_CPU_MASK_CHECK = (_IsCpuMaskWellFormed,
100 e3ed5316 Balazs Lecz
                   "CPU mask definition is not well-formed",
101 e3ed5316 Balazs Lecz
                   None, None)
102 e3ed5316 Balazs Lecz
103 b9511385 Tsachy Shacham
# Multiple CPU mask must be well-formed
104 b9511385 Tsachy Shacham
_MULTI_CPU_MASK_CHECK = (_IsMultiCpuMaskWellFormed,
105 b9511385 Tsachy Shacham
                         "Multiple CPU mask definition is not well-formed",
106 b9511385 Tsachy Shacham
                         None, None)
107 b9511385 Tsachy Shacham
108 e2d14329 Andrea Spadaccini
# Check for validity of port number
109 e2d14329 Andrea Spadaccini
_NET_PORT_CHECK = (lambda x: 0 < x < 65535, "invalid port number",
110 e2d14329 Andrea Spadaccini
                   None, None)
111 e2d14329 Andrea Spadaccini
112 2c368f28 Guido Trotter
# Check that an integer is non negative
113 2c368f28 Guido Trotter
_NONNEGATIVE_INT_CHECK = (lambda x: x >= 0, "cannot be negative", None, None)
114 2c368f28 Guido Trotter
115 205ab586 Iustin Pop
# nice wrappers for users
116 205ab586 Iustin Pop
REQ_FILE_CHECK = (True, ) + _FILE_CHECK
117 205ab586 Iustin Pop
OPT_FILE_CHECK = (False, ) + _FILE_CHECK
118 f15a6b03 Jose A. Lopes
REQ_FILE_OR_URL_CHECK = (True, ) + _FILE_OR_URL_CHECK
119 f15a6b03 Jose A. Lopes
OPT_FILE_OR_URL_CHECK = (False, ) + _FILE_OR_URL_CHECK
120 205ab586 Iustin Pop
REQ_DIR_CHECK = (True, ) + _DIR_CHECK
121 205ab586 Iustin Pop
OPT_DIR_CHECK = (False, ) + _DIR_CHECK
122 e2d14329 Andrea Spadaccini
REQ_NET_PORT_CHECK = (True, ) + _NET_PORT_CHECK
123 e2d14329 Andrea Spadaccini
OPT_NET_PORT_CHECK = (False, ) + _NET_PORT_CHECK
124 e3ed5316 Balazs Lecz
REQ_CPU_MASK_CHECK = (True, ) + _CPU_MASK_CHECK
125 e2d14329 Andrea Spadaccini
OPT_CPU_MASK_CHECK = (False, ) + _CPU_MASK_CHECK
126 b9511385 Tsachy Shacham
REQ_MULTI_CPU_MASK_CHECK = (True, ) + _MULTI_CPU_MASK_CHECK
127 b9511385 Tsachy Shacham
OPT_MULTI_CPU_MASK_CHECK = (False, ) + _MULTI_CPU_MASK_CHECK
128 2c368f28 Guido Trotter
REQ_NONNEGATIVE_INT_CHECK = (True, ) + _NONNEGATIVE_INT_CHECK
129 2c368f28 Guido Trotter
OPT_NONNEGATIVE_INT_CHECK = (False, ) + _NONNEGATIVE_INT_CHECK
130 205ab586 Iustin Pop
131 205ab586 Iustin Pop
# no checks at all
132 205ab586 Iustin Pop
NO_CHECK = (False, None, None, None, None)
133 205ab586 Iustin Pop
134 205ab586 Iustin Pop
# required, but no other checks
135 205ab586 Iustin Pop
REQUIRED_CHECK = (True, None, None, None, None)
136 205ab586 Iustin Pop
137 e71b9ef4 Iustin Pop
# migration type
138 783a6c0b Iustin Pop
MIGRATION_MODE_CHECK = (True, lambda x: x in constants.HT_MIGRATION_MODES,
139 783a6c0b Iustin Pop
                        "invalid migration mode", None, None)
140 e71b9ef4 Iustin Pop
141 d73ef63f Michael Hanselmann
142 205ab586 Iustin Pop
def ParamInSet(required, my_set):
143 205ab586 Iustin Pop
  """Builds parameter checker for set membership.
144 205ab586 Iustin Pop

145 205ab586 Iustin Pop
  @type required: boolean
146 205ab586 Iustin Pop
  @param required: whether this is a required parameter
147 205ab586 Iustin Pop
  @type my_set: tuple, list or set
148 205ab586 Iustin Pop
  @param my_set: allowed values set
149 205ab586 Iustin Pop

150 205ab586 Iustin Pop
  """
151 205ab586 Iustin Pop
  fn = lambda x: x in my_set
152 ab3e6da8 Iustin Pop
  err = ("The value must be one of: %s" % utils.CommaJoin(my_set))
153 205ab586 Iustin Pop
  return (required, fn, err, None, None)
154 f48148c3 Iustin Pop
155 f48148c3 Iustin Pop
156 bc81cd54 Jose A. Lopes
def GenerateTapName():
157 bc81cd54 Jose A. Lopes
  """Generate a TAP network interface name for a NIC.
158 bc81cd54 Jose A. Lopes

159 bc81cd54 Jose A. Lopes
  This helper function generates a special TAP network interface
160 bc81cd54 Jose A. Lopes
  name for NICs that are meant to be used in instance communication.
161 bc81cd54 Jose A. Lopes
  This function checks the existing TAP interfaces in order to find
162 bc81cd54 Jose A. Lopes
  a unique name for the new TAP network interface.  The TAP network
163 bc81cd54 Jose A. Lopes
  interface names are of the form 'gnt.com.%d', where '%d' is a
164 bc81cd54 Jose A. Lopes
  unique number within the node.
165 bc81cd54 Jose A. Lopes

166 bc81cd54 Jose A. Lopes
  @rtype: string
167 bc81cd54 Jose A. Lopes
  @return: TAP network interface name, or the empty string if the
168 bc81cd54 Jose A. Lopes
           NIC is not used in instance communication
169 bc81cd54 Jose A. Lopes

170 bc81cd54 Jose A. Lopes
  """
171 bc81cd54 Jose A. Lopes
  result = utils.RunCmd(["ip", "tuntap", "list"])
172 bc81cd54 Jose A. Lopes
173 bc81cd54 Jose A. Lopes
  if result.failed:
174 bc81cd54 Jose A. Lopes
    raise errors.HypervisorError("Failed to list TUN/TAP interfaces")
175 bc81cd54 Jose A. Lopes
176 bc81cd54 Jose A. Lopes
  idxs = set()
177 bc81cd54 Jose A. Lopes
178 bc81cd54 Jose A. Lopes
  for line in result.output.splitlines():
179 bc81cd54 Jose A. Lopes
    parts = line.split(": ", 1)
180 bc81cd54 Jose A. Lopes
181 bc81cd54 Jose A. Lopes
    if len(parts) < 2:
182 bc81cd54 Jose A. Lopes
      raise errors.HypervisorError("Failed to parse TUN/TAP interfaces")
183 bc81cd54 Jose A. Lopes
184 bc81cd54 Jose A. Lopes
    r = re.match(r"gnt\.com\.([0-9]+)", parts[0])
185 bc81cd54 Jose A. Lopes
186 bc81cd54 Jose A. Lopes
    if r is not None:
187 bc81cd54 Jose A. Lopes
      idxs.add(int(r.group(1)))
188 bc81cd54 Jose A. Lopes
189 bc81cd54 Jose A. Lopes
  if idxs:
190 bc81cd54 Jose A. Lopes
    idx = max(idxs) + 1
191 bc81cd54 Jose A. Lopes
  else:
192 bc81cd54 Jose A. Lopes
    idx = 0
193 bc81cd54 Jose A. Lopes
194 bc81cd54 Jose A. Lopes
  return "gnt.com.%d" % idx
195 bc81cd54 Jose A. Lopes
196 bc81cd54 Jose A. Lopes
197 9e42978e Jose A. Lopes
def ConfigureNIC(cmd, instance, seq, nic, tap):
198 9e42978e Jose A. Lopes
  """Run the network configuration script for a specified NIC
199 9e42978e Jose A. Lopes

200 9e42978e Jose A. Lopes
  @type cmd: string
201 9e42978e Jose A. Lopes
  @param cmd: command to run
202 9e42978e Jose A. Lopes
  @type instance: instance object
203 9e42978e Jose A. Lopes
  @param instance: instance we're acting on
204 9e42978e Jose A. Lopes
  @type seq: int
205 9e42978e Jose A. Lopes
  @param seq: nic sequence number
206 9e42978e Jose A. Lopes
  @type nic: nic object
207 9e42978e Jose A. Lopes
  @param nic: nic we're acting on
208 9e42978e Jose A. Lopes
  @type tap: str
209 9e42978e Jose A. Lopes
  @param tap: the host's tap interface this NIC corresponds to
210 9e42978e Jose A. Lopes

211 9e42978e Jose A. Lopes
  """
212 9e42978e Jose A. Lopes
  env = {
213 9e42978e Jose A. Lopes
    "PATH": "%s:/sbin:/usr/sbin" % os.environ["PATH"],
214 9e42978e Jose A. Lopes
    "INSTANCE": instance.name,
215 9e42978e Jose A. Lopes
    "MAC": nic.mac,
216 9e42978e Jose A. Lopes
    "MODE": nic.nicparams[constants.NIC_MODE],
217 9e42978e Jose A. Lopes
    "INTERFACE": tap,
218 9e42978e Jose A. Lopes
    "INTERFACE_INDEX": str(seq),
219 9e42978e Jose A. Lopes
    "INTERFACE_UUID": nic.uuid,
220 9e42978e Jose A. Lopes
    "TAGS": " ".join(instance.GetTags()),
221 9e42978e Jose A. Lopes
  }
222 9e42978e Jose A. Lopes
223 9e42978e Jose A. Lopes
  if nic.ip:
224 9e42978e Jose A. Lopes
    env["IP"] = nic.ip
225 9e42978e Jose A. Lopes
226 9e42978e Jose A. Lopes
  if nic.name:
227 9e42978e Jose A. Lopes
    env["INTERFACE_NAME"] = nic.name
228 9e42978e Jose A. Lopes
229 9e42978e Jose A. Lopes
  if nic.nicparams[constants.NIC_LINK]:
230 9e42978e Jose A. Lopes
    env["LINK"] = nic.nicparams[constants.NIC_LINK]
231 9e42978e Jose A. Lopes
232 9e42978e Jose A. Lopes
  if nic.nicparams[constants.NIC_VLAN]:
233 9e42978e Jose A. Lopes
    env["VLAN"] = nic.nicparams[constants.NIC_VLAN]
234 9e42978e Jose A. Lopes
235 9e42978e Jose A. Lopes
  if nic.network:
236 9e42978e Jose A. Lopes
    n = objects.Network.FromDict(nic.netinfo)
237 9e42978e Jose A. Lopes
    env.update(n.HooksDict())
238 9e42978e Jose A. Lopes
239 9e42978e Jose A. Lopes
  if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
240 9e42978e Jose A. Lopes
    env["BRIDGE"] = nic.nicparams[constants.NIC_LINK]
241 9e42978e Jose A. Lopes
242 9e42978e Jose A. Lopes
  result = utils.RunCmd(cmd, env=env)
243 9e42978e Jose A. Lopes
  if result.failed:
244 9e42978e Jose A. Lopes
    raise errors.HypervisorError("Failed to configure interface %s: %s;"
245 9e42978e Jose A. Lopes
                                 " network configuration script output: %s" %
246 9e42978e Jose A. Lopes
                                 (tap, result.fail_reason, result.output))
247 9e42978e Jose A. Lopes
248 9e42978e Jose A. Lopes
249 a3f0f306 Jose A. Lopes
class HvInstanceState(object):
250 a3f0f306 Jose A. Lopes
  RUNNING = 0
251 a3f0f306 Jose A. Lopes
  SHUTDOWN = 1
252 a3f0f306 Jose A. Lopes
253 a3f0f306 Jose A. Lopes
  @staticmethod
254 a3f0f306 Jose A. Lopes
  def IsRunning(s):
255 a3f0f306 Jose A. Lopes
    return s == HvInstanceState.RUNNING
256 a3f0f306 Jose A. Lopes
257 a3f0f306 Jose A. Lopes
  @staticmethod
258 a3f0f306 Jose A. Lopes
  def IsShutdown(s):
259 a3f0f306 Jose A. Lopes
    return s == HvInstanceState.SHUTDOWN
260 a3f0f306 Jose A. Lopes
261 a3f0f306 Jose A. Lopes
262 65a6f9b7 Michael Hanselmann
class BaseHypervisor(object):
263 65a6f9b7 Michael Hanselmann
  """Abstract virtualisation technology interface
264 65a6f9b7 Michael Hanselmann

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

268 205ab586 Iustin Pop
  @cvar PARAMETERS: a dict of parameter name: check type; the check type is
269 205ab586 Iustin Pop
      a five-tuple containing:
270 205ab586 Iustin Pop
          - the required flag (boolean)
271 205ab586 Iustin Pop
          - a function to check for syntax, that will be used in
272 205ab586 Iustin Pop
            L{CheckParameterSyntax}, in the master daemon process
273 205ab586 Iustin Pop
          - an error message for the above function
274 205ab586 Iustin Pop
          - a function to check for parameter validity on the remote node,
275 205ab586 Iustin Pop
            in the L{ValidateParameters} function
276 205ab586 Iustin Pop
          - an error message for the above function
277 d271c6fd Iustin Pop
  @type CAN_MIGRATE: boolean
278 d271c6fd Iustin Pop
  @cvar CAN_MIGRATE: whether this hypervisor can do migration (either
279 d271c6fd Iustin Pop
      live or non-live)
280 205ab586 Iustin Pop

281 65a6f9b7 Michael Hanselmann
  """
282 205ab586 Iustin Pop
  PARAMETERS = {}
283 e1b8653f Guido Trotter
  ANCILLARY_FILES = []
284 69ab2e12 Guido Trotter
  ANCILLARY_FILES_OPT = []
285 d271c6fd Iustin Pop
  CAN_MIGRATE = False
286 f48148c3 Iustin Pop
287 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
288 65a6f9b7 Michael Hanselmann
    """Start an instance."""
289 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
290 65a6f9b7 Michael Hanselmann
291 874f6148 Michele Tartara
  def StopInstance(self, instance, force=False, retry=False, name=None,
292 874f6148 Michele Tartara
                   timeout=None):
293 07b49e41 Guido Trotter
    """Stop an instance
294 07b49e41 Guido Trotter

295 07b49e41 Guido Trotter
    @type instance: L{objects.Instance}
296 07b49e41 Guido Trotter
    @param instance: instance to stop
297 07b49e41 Guido Trotter
    @type force: boolean
298 07b49e41 Guido Trotter
    @param force: whether to do a "hard" stop (destroy)
299 07b49e41 Guido Trotter
    @type retry: boolean
300 07b49e41 Guido Trotter
    @param retry: whether this is just a retry call
301 bbcf7ad0 Iustin Pop
    @type name: string or None
302 bbcf7ad0 Iustin Pop
    @param name: if this parameter is passed, the the instance object
303 bbcf7ad0 Iustin Pop
        should not be used (will be passed as None), and the shutdown
304 bbcf7ad0 Iustin Pop
        must be done by name only
305 874f6148 Michele Tartara
    @type timeout: int or None
306 874f6148 Michele Tartara
    @param timeout: if the parameter is not None, a soft shutdown operation will
307 874f6148 Michele Tartara
        be killed after the specified number of seconds. A hard (forced)
308 874f6148 Michele Tartara
        shutdown cannot have a timeout
309 059ed766 Jose A. Lopes
    @raise errors.HypervisorError: when a parameter is not valid or
310 059ed766 Jose A. Lopes
        the instance failed to be stopped
311 07b49e41 Guido Trotter

312 07b49e41 Guido Trotter
    """
313 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
314 65a6f9b7 Michael Hanselmann
315 f28ec899 Guido Trotter
  def CleanupInstance(self, instance_name):
316 f28ec899 Guido Trotter
    """Cleanup after a stopped instance
317 f28ec899 Guido Trotter

318 f28ec899 Guido Trotter
    This is an optional method, used by hypervisors that need to cleanup after
319 f28ec899 Guido Trotter
    an instance has been stopped.
320 f28ec899 Guido Trotter

321 f28ec899 Guido Trotter
    @type instance_name: string
322 f28ec899 Guido Trotter
    @param instance_name: instance name to cleanup after
323 f28ec899 Guido Trotter

324 f28ec899 Guido Trotter
    """
325 f28ec899 Guido Trotter
    pass
326 f28ec899 Guido Trotter
327 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
328 65a6f9b7 Michael Hanselmann
    """Reboot an instance."""
329 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
330 65a6f9b7 Michael Hanselmann
331 58e356a9 Helga Velroyen
  def ListInstances(self, hvparams=None):
332 65a6f9b7 Michael Hanselmann
    """Get the list of running instances."""
333 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
334 65a6f9b7 Michael Hanselmann
335 0bbec3af Helga Velroyen
  def GetInstanceInfo(self, instance_name, hvparams=None):
336 65a6f9b7 Michael Hanselmann
    """Get instance properties.
337 65a6f9b7 Michael Hanselmann

338 cd42d0ad Guido Trotter
    @type instance_name: string
339 c41eea6e Iustin Pop
    @param instance_name: the instance name
340 0bbec3af Helga Velroyen
    @type hvparams: dict of strings
341 0bbec3af Helga Velroyen
    @param hvparams: hvparams to be used with this instance
342 65a6f9b7 Michael Hanselmann

343 9d22cc90 Jose A. Lopes
    @rtype: (string, string, int, int, HvInstanceState, int)
344 c41eea6e Iustin Pop
    @return: tuple (name, id, memory, vcpus, state, times)
345 65a6f9b7 Michael Hanselmann

346 65a6f9b7 Michael Hanselmann
    """
347 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
348 65a6f9b7 Michael Hanselmann
349 0200a1af Helga Velroyen
  def GetAllInstancesInfo(self, hvparams=None):
350 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
351 65a6f9b7 Michael Hanselmann

352 0200a1af Helga Velroyen
    @type hvparams: dict of strings
353 0200a1af Helga Velroyen
    @param hvparams: hypervisor parameter
354 9d22cc90 Jose A. Lopes

355 9d22cc90 Jose A. Lopes
    @rtype: (string, string, int, int, HvInstanceState, int)
356 9d22cc90 Jose A. Lopes
    @return: list of tuples (name, id, memory, vcpus, state, times)
357 c41eea6e Iustin Pop

358 65a6f9b7 Michael Hanselmann
    """
359 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
360 65a6f9b7 Michael Hanselmann
361 fac489a5 Helga Velroyen
  def GetNodeInfo(self, hvparams=None):
362 65a6f9b7 Michael Hanselmann
    """Return information about the node.
363 65a6f9b7 Michael Hanselmann

364 fac489a5 Helga Velroyen
    @type hvparams: dict of strings
365 fac489a5 Helga Velroyen
    @param hvparams: hypervisor parameters
366 fac489a5 Helga Velroyen

367 ef14e128 Bernardo Dal Seno
    @return: a dict with at least the following keys (memory values in MiB):
368 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
369 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
370 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
371 ef14e128 Bernardo Dal Seno
          - cpu_total: total number of CPUs
372 ff05ff94 Bernardo Dal Seno
          - cpu_dom0: number of CPUs used by the node OS
373 ef14e128 Bernardo Dal Seno
          - cpu_nodes: number of NUMA domains
374 ef14e128 Bernardo Dal Seno
          - cpu_sockets: number of physical CPU sockets
375 65a6f9b7 Michael Hanselmann

376 65a6f9b7 Michael Hanselmann
    """
377 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
378 65a6f9b7 Michael Hanselmann
379 637ce7f9 Guido Trotter
  @classmethod
380 c42be2c0 Petr Pudlak
  def GetInstanceConsole(cls, instance, primary_node, node_group,
381 c42be2c0 Petr Pudlak
                         hvparams, beparams):
382 55cc0a44 Michael Hanselmann
    """Return information for connecting to the console of an instance.
383 65a6f9b7 Michael Hanselmann

384 65a6f9b7 Michael Hanselmann
    """
385 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
386 65a6f9b7 Michael Hanselmann
387 e1b8653f Guido Trotter
  @classmethod
388 e1b8653f Guido Trotter
  def GetAncillaryFiles(cls):
389 e1b8653f Guido Trotter
    """Return a list of ancillary files to be copied to all nodes as ancillary
390 e1b8653f Guido Trotter
    configuration files.
391 e1b8653f Guido Trotter

392 69ab2e12 Guido Trotter
    @rtype: (list of absolute paths, list of absolute paths)
393 69ab2e12 Guido Trotter
    @return: (all files, optional files)
394 e1b8653f Guido Trotter

395 e1b8653f Guido Trotter
    """
396 e1b8653f Guido Trotter
    # By default we return a member variable, so that if an hypervisor has just
397 e1b8653f Guido Trotter
    # a static list of files it doesn't have to override this function.
398 69ab2e12 Guido Trotter
    assert set(cls.ANCILLARY_FILES).issuperset(cls.ANCILLARY_FILES_OPT), \
399 69ab2e12 Guido Trotter
      "Optional ancillary files must be a subset of ancillary files"
400 69ab2e12 Guido Trotter
401 69ab2e12 Guido Trotter
    return (cls.ANCILLARY_FILES, cls.ANCILLARY_FILES_OPT)
402 e1b8653f Guido Trotter
403 75bf3149 Helga Velroyen
  def Verify(self, hvparams=None):
404 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
405 65a6f9b7 Michael Hanselmann

406 75bf3149 Helga Velroyen
    @type hvparams: dict of strings
407 75bf3149 Helga Velroyen
    @param hvparams: hypervisor parameters to be verified against
408 75bf3149 Helga Velroyen

409 cd04dfd2 Michael Hanselmann
    @return: Problem description if something is wrong, C{None} otherwise
410 cd04dfd2 Michael Hanselmann

411 65a6f9b7 Michael Hanselmann
    """
412 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
413 6e7275c0 Iustin Pop
414 b459a848 Andrea Spadaccini
  def MigrationInfo(self, instance): # pylint: disable=R0201,W0613
415 cd42d0ad Guido Trotter
    """Get instance information to perform a migration.
416 cd42d0ad Guido Trotter

417 cd42d0ad Guido Trotter
    By default assume no information is needed.
418 cd42d0ad Guido Trotter

419 cd42d0ad Guido Trotter
    @type instance: L{objects.Instance}
420 cd42d0ad Guido Trotter
    @param instance: instance to be migrated
421 cd42d0ad Guido Trotter
    @rtype: string/data (opaque)
422 cd42d0ad Guido Trotter
    @return: instance migration information - serialized form
423 cd42d0ad Guido Trotter

424 cd42d0ad Guido Trotter
    """
425 d0c8c01d Iustin Pop
    return ""
426 cd42d0ad Guido Trotter
427 cd42d0ad Guido Trotter
  def AcceptInstance(self, instance, info, target):
428 cd42d0ad Guido Trotter
    """Prepare to accept an instance.
429 cd42d0ad Guido Trotter

430 cd42d0ad Guido Trotter
    By default assume no preparation is needed.
431 cd42d0ad Guido Trotter

432 cd42d0ad Guido Trotter
    @type instance: L{objects.Instance}
433 cd42d0ad Guido Trotter
    @param instance: instance to be accepted
434 cd42d0ad Guido Trotter
    @type info: string/data (opaque)
435 cd42d0ad Guido Trotter
    @param info: migration information, from the source node
436 cd42d0ad Guido Trotter
    @type target: string
437 cd42d0ad Guido Trotter
    @param target: target host (usually ip), on this node
438 cd42d0ad Guido Trotter

439 cd42d0ad Guido Trotter
    """
440 cd42d0ad Guido Trotter
    pass
441 cd42d0ad Guido Trotter
442 b990eedd Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
443 b990eedd Guido Trotter
    """Balloon an instance memory to a certain value.
444 b990eedd Guido Trotter

445 b990eedd Guido Trotter
    @type instance: L{objects.Instance}
446 b990eedd Guido Trotter
    @param instance: instance to be accepted
447 b990eedd Guido Trotter
    @type mem: int
448 b990eedd Guido Trotter
    @param mem: actual memory size to use for instance runtime
449 b990eedd Guido Trotter

450 b990eedd Guido Trotter
    """
451 b990eedd Guido Trotter
    raise NotImplementedError
452 b990eedd Guido Trotter
453 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
454 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the target node.
455 cd42d0ad Guido Trotter

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

459 cd42d0ad Guido Trotter
    @type instance: L{objects.Instance}
460 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
461 cd42d0ad Guido Trotter
    @type info: string/data (opaque)
462 cd42d0ad Guido Trotter
    @param info: migration information, from the source node
463 cd42d0ad Guido Trotter
    @type success: boolean
464 cd42d0ad Guido Trotter
    @param success: whether the migration was a success or a failure
465 cd42d0ad Guido Trotter

466 cd42d0ad Guido Trotter
    """
467 cd42d0ad Guido Trotter
    pass
468 cd42d0ad Guido Trotter
469 bc0a2284 Helga Velroyen
  def MigrateInstance(self, cluster_name, instance, target, live):
470 6e7275c0 Iustin Pop
    """Migrate an instance.
471 6e7275c0 Iustin Pop

472 bc0a2284 Helga Velroyen
    @type cluster_name: string
473 bc0a2284 Helga Velroyen
    @param cluster_name: name of the cluster
474 3a488770 Iustin Pop
    @type instance: L{objects.Instance}
475 9044275a Michael Hanselmann
    @param instance: the instance to be migrated
476 cd42d0ad Guido Trotter
    @type target: string
477 cd42d0ad Guido Trotter
    @param target: hostname (usually ip) of the target node
478 cd42d0ad Guido Trotter
    @type live: boolean
479 cd42d0ad Guido Trotter
    @param live: whether to do a live or non-live migration
480 6e7275c0 Iustin Pop

481 6e7275c0 Iustin Pop
    """
482 6e7275c0 Iustin Pop
    raise NotImplementedError
483 f48148c3 Iustin Pop
484 6a1434d7 Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
485 6a1434d7 Andrea Spadaccini
    """Finalize the instance migration on the source node.
486 6a1434d7 Andrea Spadaccini

487 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
488 6a1434d7 Andrea Spadaccini
    @param instance: the instance that was migrated
489 6a1434d7 Andrea Spadaccini
    @type success: bool
490 6a1434d7 Andrea Spadaccini
    @param success: whether the migration succeeded or not
491 6a1434d7 Andrea Spadaccini
    @type live: bool
492 6a1434d7 Andrea Spadaccini
    @param live: whether the user requested a live migration or not
493 6a1434d7 Andrea Spadaccini

494 6a1434d7 Andrea Spadaccini
    """
495 6a1434d7 Andrea Spadaccini
    pass
496 6a1434d7 Andrea Spadaccini
497 6a1434d7 Andrea Spadaccini
  def GetMigrationStatus(self, instance):
498 6a1434d7 Andrea Spadaccini
    """Get the migration status
499 6a1434d7 Andrea Spadaccini

500 6a1434d7 Andrea Spadaccini
    @type instance: L{objects.Instance}
501 6a1434d7 Andrea Spadaccini
    @param instance: the instance that is being migrated
502 6a1434d7 Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
503 6a1434d7 Andrea Spadaccini
    @return: the status of the current migration (one of
504 6a1434d7 Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
505 6a1434d7 Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
506 6a1434d7 Andrea Spadaccini

507 6a1434d7 Andrea Spadaccini
    """
508 6a1434d7 Andrea Spadaccini
    raise NotImplementedError
509 6a1434d7 Andrea Spadaccini
510 30b12688 Jose A. Lopes
  def _InstanceStartupMemory(self, instance):
511 61eb1a46 Guido Trotter
    """Get the correct startup memory for an instance
512 61eb1a46 Guido Trotter

513 61eb1a46 Guido Trotter
    This function calculates how much memory an instance should be started
514 61eb1a46 Guido Trotter
    with, making sure it's a value between the minimum and the maximum memory,
515 61eb1a46 Guido Trotter
    but also trying to use no more than the current free memory on the node.
516 61eb1a46 Guido Trotter

517 61eb1a46 Guido Trotter
    @type instance: L{objects.Instance}
518 61eb1a46 Guido Trotter
    @param instance: the instance that is being started
519 61eb1a46 Guido Trotter
    @rtype: integer
520 61eb1a46 Guido Trotter
    @return: memory the instance should be started with
521 61eb1a46 Guido Trotter

522 61eb1a46 Guido Trotter
    """
523 30b12688 Jose A. Lopes
    free_memory = self.GetNodeInfo(hvparams=instance.hvparams)["memory_free"]
524 61eb1a46 Guido Trotter
    max_start_mem = min(instance.beparams[constants.BE_MAXMEM], free_memory)
525 61eb1a46 Guido Trotter
    start_mem = max(instance.beparams[constants.BE_MINMEM], max_start_mem)
526 61eb1a46 Guido Trotter
    return start_mem
527 61eb1a46 Guido Trotter
528 f48148c3 Iustin Pop
  @classmethod
529 f48148c3 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
530 f48148c3 Iustin Pop
    """Check the given parameters for validity.
531 f48148c3 Iustin Pop

532 f48148c3 Iustin Pop
    This should check the passed set of parameters for
533 f48148c3 Iustin Pop
    validity. Classes should extend, not replace, this function.
534 f48148c3 Iustin Pop

535 f48148c3 Iustin Pop
    @type hvparams:  dict
536 f48148c3 Iustin Pop
    @param hvparams: dictionary with parameter names/value
537 f48148c3 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
538 f48148c3 Iustin Pop

539 f48148c3 Iustin Pop
    """
540 f48148c3 Iustin Pop
    for key in hvparams:
541 f48148c3 Iustin Pop
      if key not in cls.PARAMETERS:
542 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' is not supported" % key)
543 205ab586 Iustin Pop
544 205ab586 Iustin Pop
    # cheap tests that run on the master, should not access the world
545 205ab586 Iustin Pop
    for name, (required, check_fn, errstr, _, _) in cls.PARAMETERS.items():
546 205ab586 Iustin Pop
      if name not in hvparams:
547 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' is missing" % name)
548 205ab586 Iustin Pop
      value = hvparams[name]
549 205ab586 Iustin Pop
      if not required and not value:
550 205ab586 Iustin Pop
        continue
551 205ab586 Iustin Pop
      if not value:
552 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' is required but"
553 205ab586 Iustin Pop
                                     " is currently not defined" % (name, ))
554 205ab586 Iustin Pop
      if check_fn is not None and not check_fn(value):
555 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' fails syntax"
556 205ab586 Iustin Pop
                                     " check: %s (current value: '%s')" %
557 205ab586 Iustin Pop
                                     (name, errstr, value))
558 205ab586 Iustin Pop
559 205ab586 Iustin Pop
  @classmethod
560 205ab586 Iustin Pop
  def ValidateParameters(cls, hvparams):
561 f48148c3 Iustin Pop
    """Check the given parameters for validity.
562 f48148c3 Iustin Pop

563 f48148c3 Iustin Pop
    This should check the passed set of parameters for
564 f48148c3 Iustin Pop
    validity. Classes should extend, not replace, this function.
565 f48148c3 Iustin Pop

566 f48148c3 Iustin Pop
    @type hvparams:  dict
567 f48148c3 Iustin Pop
    @param hvparams: dictionary with parameter names/value
568 f48148c3 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
569 f48148c3 Iustin Pop

570 f48148c3 Iustin Pop
    """
571 205ab586 Iustin Pop
    for name, (required, _, _, check_fn, errstr) in cls.PARAMETERS.items():
572 205ab586 Iustin Pop
      value = hvparams[name]
573 205ab586 Iustin Pop
      if not required and not value:
574 205ab586 Iustin Pop
        continue
575 205ab586 Iustin Pop
      if check_fn is not None and not check_fn(value):
576 205ab586 Iustin Pop
        raise errors.HypervisorError("Parameter '%s' fails"
577 205ab586 Iustin Pop
                                     " validation: %s (current value: '%s')" %
578 205ab586 Iustin Pop
                                     (name, errstr, value))
579 572e52bf Iustin Pop
580 f5118ade Iustin Pop
  @classmethod
581 8ef418bb Helga Velroyen
  def PowercycleNode(cls, hvparams=None):
582 f5118ade Iustin Pop
    """Hard powercycle a node using hypervisor specific methods.
583 f5118ade Iustin Pop

584 f5118ade Iustin Pop
    This method should hard powercycle the node, using whatever
585 f5118ade Iustin Pop
    methods the hypervisor provides. Note that this means that all
586 f5118ade Iustin Pop
    instances running on the node must be stopped too.
587 f5118ade Iustin Pop

588 8ef418bb Helga Velroyen
    @type hvparams: dict of strings
589 8ef418bb Helga Velroyen
    @param hvparams: hypervisor params to be used on this node
590 8ef418bb Helga Velroyen

591 f5118ade Iustin Pop
    """
592 f5118ade Iustin Pop
    raise NotImplementedError
593 f5118ade Iustin Pop
594 94fed7da Iustin Pop
  @staticmethod
595 23cb5697 Michele Tartara
  def GetLinuxNodeInfo(meminfo="/proc/meminfo", cpuinfo="/proc/cpuinfo"):
596 572e52bf Iustin Pop
    """For linux systems, return actual OS information.
597 572e52bf Iustin Pop

598 572e52bf Iustin Pop
    This is an abstraction for all non-hypervisor-based classes, where
599 572e52bf Iustin Pop
    the node actually sees all the memory and CPUs via the /proc
600 572e52bf Iustin Pop
    interface and standard commands. The other case if for example
601 572e52bf Iustin Pop
    xen, where you only see the hardware resources via xen-specific
602 572e52bf Iustin Pop
    tools.
603 572e52bf Iustin Pop

604 23cb5697 Michele Tartara
    @param meminfo: name of the file containing meminfo
605 23cb5697 Michele Tartara
    @type meminfo: string
606 23cb5697 Michele Tartara
    @param cpuinfo: name of the file containing cpuinfo
607 23cb5697 Michele Tartara
    @type cpuinfo: string
608 572e52bf Iustin Pop
    @return: a dict with the following keys (values in MiB):
609 572e52bf Iustin Pop
          - memory_total: the total memory size on the node
610 572e52bf Iustin Pop
          - memory_free: the available memory on the node for instances
611 572e52bf Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
612 ef14e128 Bernardo Dal Seno
          - cpu_total: total number of CPUs
613 ff05ff94 Bernardo Dal Seno
          - cpu_dom0: number of CPUs used by the node OS
614 ef14e128 Bernardo Dal Seno
          - cpu_nodes: number of NUMA domains
615 ef14e128 Bernardo Dal Seno
          - cpu_sockets: number of physical CPU sockets
616 572e52bf Iustin Pop

617 572e52bf Iustin Pop
    """
618 572e52bf Iustin Pop
    try:
619 23cb5697 Michele Tartara
      data = utils.ReadFile(meminfo).splitlines()
620 572e52bf Iustin Pop
    except EnvironmentError, err:
621 572e52bf Iustin Pop
      raise errors.HypervisorError("Failed to list node info: %s" % (err,))
622 572e52bf Iustin Pop
623 572e52bf Iustin Pop
    result = {}
624 572e52bf Iustin Pop
    sum_free = 0
625 572e52bf Iustin Pop
    try:
626 572e52bf Iustin Pop
      for line in data:
627 572e52bf Iustin Pop
        splitfields = line.split(":", 1)
628 572e52bf Iustin Pop
629 572e52bf Iustin Pop
        if len(splitfields) > 1:
630 572e52bf Iustin Pop
          key = splitfields[0].strip()
631 572e52bf Iustin Pop
          val = splitfields[1].strip()
632 d0c8c01d Iustin Pop
          if key == "MemTotal":
633 e687ec01 Michael Hanselmann
            result["memory_total"] = int(val.split()[0]) / 1024
634 d0c8c01d Iustin Pop
          elif key in ("MemFree", "Buffers", "Cached"):
635 e687ec01 Michael Hanselmann
            sum_free += int(val.split()[0]) / 1024
636 d0c8c01d Iustin Pop
          elif key == "Active":
637 e687ec01 Michael Hanselmann
            result["memory_dom0"] = int(val.split()[0]) / 1024
638 572e52bf Iustin Pop
    except (ValueError, TypeError), err:
639 572e52bf Iustin Pop
      raise errors.HypervisorError("Failed to compute memory usage: %s" %
640 572e52bf Iustin Pop
                                   (err,))
641 d0c8c01d Iustin Pop
    result["memory_free"] = sum_free
642 572e52bf Iustin Pop
643 572e52bf Iustin Pop
    cpu_total = 0
644 572e52bf Iustin Pop
    try:
645 23cb5697 Michele Tartara
      fh = open(cpuinfo)
646 572e52bf Iustin Pop
      try:
647 78f99abb Michele Tartara
        cpu_total = len(re.findall(r"(?m)^processor\s*:\s*[0-9]+\s*$",
648 572e52bf Iustin Pop
                                   fh.read()))
649 572e52bf Iustin Pop
      finally:
650 572e52bf Iustin Pop
        fh.close()
651 572e52bf Iustin Pop
    except EnvironmentError, err:
652 572e52bf Iustin Pop
      raise errors.HypervisorError("Failed to list node info: %s" % (err,))
653 d0c8c01d Iustin Pop
    result["cpu_total"] = cpu_total
654 ff05ff94 Bernardo Dal Seno
    # We assume that the node OS can access all the CPUs
655 ff05ff94 Bernardo Dal Seno
    result["cpu_dom0"] = cpu_total
656 572e52bf Iustin Pop
    # FIXME: export correct data here
657 d0c8c01d Iustin Pop
    result["cpu_nodes"] = 1
658 d0c8c01d Iustin Pop
    result["cpu_sockets"] = 1
659 572e52bf Iustin Pop
660 572e52bf Iustin Pop
    return result
661 f5118ade Iustin Pop
662 f5118ade Iustin Pop
  @classmethod
663 f5118ade Iustin Pop
  def LinuxPowercycle(cls):
664 f5118ade Iustin Pop
    """Linux-specific powercycle method.
665 f5118ade Iustin Pop

666 f5118ade Iustin Pop
    """
667 f5118ade Iustin Pop
    try:
668 f5118ade Iustin Pop
      fd = os.open("/proc/sysrq-trigger", os.O_WRONLY)
669 f5118ade Iustin Pop
      try:
670 f5118ade Iustin Pop
        os.write(fd, "b")
671 f5118ade Iustin Pop
      finally:
672 f5118ade Iustin Pop
        fd.close()
673 f5118ade Iustin Pop
    except OSError:
674 f5118ade Iustin Pop
      logging.exception("Can't open the sysrq-trigger file")
675 f5118ade Iustin Pop
      result = utils.RunCmd(["reboot", "-n", "-f"])
676 f5118ade Iustin Pop
      if not result:
677 f5118ade Iustin Pop
        logging.error("Can't run shutdown: %s", result.output)
678 53fde1ac Iustin Pop
679 53fde1ac Iustin Pop
  @staticmethod
680 53fde1ac Iustin Pop
  def _FormatVerifyResults(msgs):
681 53fde1ac Iustin Pop
    """Formats the verification results, given a list of errors.
682 53fde1ac Iustin Pop

683 53fde1ac Iustin Pop
    @param msgs: list of errors, possibly empty
684 53fde1ac Iustin Pop
    @return: overall problem description if something is wrong,
685 53fde1ac Iustin Pop
        C{None} otherwise
686 53fde1ac Iustin Pop

687 53fde1ac Iustin Pop
    """
688 53fde1ac Iustin Pop
    if msgs:
689 53fde1ac Iustin Pop
      return "; ".join(msgs)
690 53fde1ac Iustin Pop
    else:
691 53fde1ac Iustin Pop
      return None
692 c5708931 Dimitris Aragiorgis
693 50e0f1d9 Dimitris Aragiorgis
  # pylint: disable=R0201,W0613
694 c5708931 Dimitris Aragiorgis
  def HotAddDevice(self, instance, dev_type, device, extra, seq):
695 c5708931 Dimitris Aragiorgis
    """Hot-add a device.
696 c5708931 Dimitris Aragiorgis

697 c5708931 Dimitris Aragiorgis
    """
698 50e0f1d9 Dimitris Aragiorgis
    raise errors.HotplugError("Hotplug is not supported by this hypervisor")
699 c5708931 Dimitris Aragiorgis
700 50e0f1d9 Dimitris Aragiorgis
  # pylint: disable=R0201,W0613
701 c5708931 Dimitris Aragiorgis
  def HotDelDevice(self, instance, dev_type, device, extra, seq):
702 c5708931 Dimitris Aragiorgis
    """Hot-del a device.
703 c5708931 Dimitris Aragiorgis

704 c5708931 Dimitris Aragiorgis
    """
705 50e0f1d9 Dimitris Aragiorgis
    raise errors.HotplugError("Hotplug is not supported by this hypervisor")
706 c5708931 Dimitris Aragiorgis
707 50e0f1d9 Dimitris Aragiorgis
  # pylint: disable=R0201,W0613
708 c5708931 Dimitris Aragiorgis
  def HotModDevice(self, instance, dev_type, device, extra, seq):
709 c5708931 Dimitris Aragiorgis
    """Hot-mod a device.
710 c5708931 Dimitris Aragiorgis

711 c5708931 Dimitris Aragiorgis
    """
712 50e0f1d9 Dimitris Aragiorgis
    raise errors.HotplugError("Hotplug is not supported by this hypervisor")
713 50e0f1d9 Dimitris Aragiorgis
714 50e0f1d9 Dimitris Aragiorgis
  # pylint: disable=R0201,W0613
715 50e0f1d9 Dimitris Aragiorgis
  def VerifyHotplugSupport(self, instance, action, dev_type):
716 50e0f1d9 Dimitris Aragiorgis
    """Verifies that hotplug is supported.
717 c5708931 Dimitris Aragiorgis

718 24711492 Dimitris Aragiorgis
    Given the target device and hotplug action checks if hotplug is
719 24711492 Dimitris Aragiorgis
    actually supported.
720 50e0f1d9 Dimitris Aragiorgis

721 50e0f1d9 Dimitris Aragiorgis
    @type instance: L{objects.Instance}
722 50e0f1d9 Dimitris Aragiorgis
    @param instance: the instance object
723 50e0f1d9 Dimitris Aragiorgis
    @type action: string
724 50e0f1d9 Dimitris Aragiorgis
    @param action: one of the supported hotplug commands
725 50e0f1d9 Dimitris Aragiorgis
    @type dev_type: string
726 50e0f1d9 Dimitris Aragiorgis
    @param dev_type: one of the supported device types to hotplug
727 50e0f1d9 Dimitris Aragiorgis
    @raise errors.HotplugError: if hotplugging is not supported
728 c5708931 Dimitris Aragiorgis

729 c5708931 Dimitris Aragiorgis
    """
730 24711492 Dimitris Aragiorgis
    raise errors.HotplugError("Hotplug is not supported.")
731 24711492 Dimitris Aragiorgis
732 24711492 Dimitris Aragiorgis
  def HotplugSupported(self, instance):
733 24711492 Dimitris Aragiorgis
    """Checks if hotplug is supported.
734 24711492 Dimitris Aragiorgis

735 24711492 Dimitris Aragiorgis
    By default is not. Currently only KVM hypervisor supports it.
736 24711492 Dimitris Aragiorgis

737 24711492 Dimitris Aragiorgis
    """
738 50e0f1d9 Dimitris Aragiorgis
    raise errors.HotplugError("Hotplug is not supported by this hypervisor")