Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ 428a794b

History | View | Annotate | Download (43.6 kB)

1 65a6f9b7 Michael Hanselmann
#
2 65a6f9b7 Michael Hanselmann
#
3 65a6f9b7 Michael Hanselmann
4 1a63f285 Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 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
"""Xen hypervisors
23 65a6f9b7 Michael Hanselmann

24 65a6f9b7 Michael Hanselmann
"""
25 65a6f9b7 Michael Hanselmann
26 b48909c8 Iustin Pop
import logging
27 397b7844 Dimitris Aragiorgis
import errno
28 d0bb3f24 Michael Hanselmann
import string # pylint: disable=W0402
29 397b7844 Dimitris Aragiorgis
import shutil
30 65a6f9b7 Michael Hanselmann
from cStringIO import StringIO
31 65a6f9b7 Michael Hanselmann
32 65a6f9b7 Michael Hanselmann
from ganeti import constants
33 65a6f9b7 Michael Hanselmann
from ganeti import errors
34 65a6f9b7 Michael Hanselmann
from ganeti import utils
35 a2d32034 Michael Hanselmann
from ganeti.hypervisor import hv_base
36 a744b676 Manuel Franceschini
from ganeti import netutils
37 55cc0a44 Michael Hanselmann
from ganeti import objects
38 9d9bded1 Michael Hanselmann
from ganeti import pathutils
39 65a6f9b7 Michael Hanselmann
40 65a6f9b7 Michael Hanselmann
41 a8e8c0c6 Michael Hanselmann
XEND_CONFIG_FILE = utils.PathJoin(pathutils.XEN_CONFIG_DIR, "xend-config.sxp")
42 a8e8c0c6 Michael Hanselmann
XL_CONFIG_FILE = utils.PathJoin(pathutils.XEN_CONFIG_DIR, "xen/xl.conf")
43 a8e8c0c6 Michael Hanselmann
VIF_BRIDGE_SCRIPT = utils.PathJoin(pathutils.XEN_CONFIG_DIR,
44 a8e8c0c6 Michael Hanselmann
                                   "scripts/vif-bridge")
45 18bf85b1 Michael Hanselmann
_DOM0_NAME = "Domain-0"
46 d0bb3f24 Michael Hanselmann
_DISK_LETTERS = string.ascii_lowercase
47 d0bb3f24 Michael Hanselmann
48 d0bb3f24 Michael Hanselmann
_FILE_DRIVER_MAP = {
49 d0bb3f24 Michael Hanselmann
  constants.FD_LOOP: "file",
50 d0bb3f24 Michael Hanselmann
  constants.FD_BLKTAP: "tap:aio",
51 7bc2c097 Michele Tartara
  constants.FD_BLKTAP2: "tap2:tapdisk:aio",
52 d0bb3f24 Michael Hanselmann
  }
53 22d568c2 Guido Trotter
54 22d568c2 Guido Trotter
55 347fa0f1 Michael Hanselmann
def _CreateConfigCpus(cpu_mask):
56 347fa0f1 Michael Hanselmann
  """Create a CPU config string for Xen's config file.
57 347fa0f1 Michael Hanselmann

58 347fa0f1 Michael Hanselmann
  """
59 347fa0f1 Michael Hanselmann
  # Convert the string CPU mask to a list of list of int's
60 347fa0f1 Michael Hanselmann
  cpu_list = utils.ParseMultiCpuMask(cpu_mask)
61 347fa0f1 Michael Hanselmann
62 347fa0f1 Michael Hanselmann
  if len(cpu_list) == 1:
63 347fa0f1 Michael Hanselmann
    all_cpu_mapping = cpu_list[0]
64 347fa0f1 Michael Hanselmann
    if all_cpu_mapping == constants.CPU_PINNING_OFF:
65 347fa0f1 Michael Hanselmann
      # If CPU pinning has 1 entry that's "all", then remove the
66 347fa0f1 Michael Hanselmann
      # parameter from the config file
67 347fa0f1 Michael Hanselmann
      return None
68 347fa0f1 Michael Hanselmann
    else:
69 347fa0f1 Michael Hanselmann
      # If CPU pinning has one non-all entry, mapping all vCPUS (the entire
70 347fa0f1 Michael Hanselmann
      # VM) to one physical CPU, using format 'cpu = "C"'
71 347fa0f1 Michael Hanselmann
      return "cpu = \"%s\"" % ",".join(map(str, all_cpu_mapping))
72 347fa0f1 Michael Hanselmann
  else:
73 347fa0f1 Michael Hanselmann
74 347fa0f1 Michael Hanselmann
    def _GetCPUMap(vcpu):
75 347fa0f1 Michael Hanselmann
      if vcpu[0] == constants.CPU_PINNING_ALL_VAL:
76 347fa0f1 Michael Hanselmann
        cpu_map = constants.CPU_PINNING_ALL_XEN
77 347fa0f1 Michael Hanselmann
      else:
78 347fa0f1 Michael Hanselmann
        cpu_map = ",".join(map(str, vcpu))
79 347fa0f1 Michael Hanselmann
      return "\"%s\"" % cpu_map
80 347fa0f1 Michael Hanselmann
81 347fa0f1 Michael Hanselmann
    # build the result string in format 'cpus = [ "c", "c", "c" ]',
82 347fa0f1 Michael Hanselmann
    # where each c is a physical CPU number, a range, a list, or any
83 347fa0f1 Michael Hanselmann
    # combination
84 347fa0f1 Michael Hanselmann
    return "cpus = [ %s ]" % ", ".join(map(_GetCPUMap, cpu_list))
85 347fa0f1 Michael Hanselmann
86 347fa0f1 Michael Hanselmann
87 ff19ac20 Helga Velroyen
def _RunInstanceList(fn, instance_list_errors):
88 ff19ac20 Helga Velroyen
  """Helper function for L{_GetInstanceList} to retrieve the list of instances
89 ff19ac20 Helga Velroyen
  from xen.
90 b255379d Michael Hanselmann

91 b255379d Michael Hanselmann
  @type fn: callable
92 ff19ac20 Helga Velroyen
  @param fn: Function to query xen for the list of instances
93 ff19ac20 Helga Velroyen
  @type instance_list_errors: list
94 ff19ac20 Helga Velroyen
  @param instance_list_errors: Error list
95 b255379d Michael Hanselmann
  @rtype: list
96 b255379d Michael Hanselmann

97 b255379d Michael Hanselmann
  """
98 b255379d Michael Hanselmann
  result = fn()
99 b255379d Michael Hanselmann
  if result.failed:
100 ff19ac20 Helga Velroyen
    logging.error("Retrieving the instance list from xen failed (%s): %s",
101 ff19ac20 Helga Velroyen
                  result.fail_reason, result.output)
102 ff19ac20 Helga Velroyen
    instance_list_errors.append(result)
103 b255379d Michael Hanselmann
    raise utils.RetryAgain()
104 b255379d Michael Hanselmann
105 b255379d Michael Hanselmann
  # skip over the heading
106 b255379d Michael Hanselmann
  return result.stdout.splitlines()
107 b255379d Michael Hanselmann
108 b255379d Michael Hanselmann
109 2609da63 Helga Velroyen
def _ParseInstanceList(lines, include_node):
110 2609da63 Helga Velroyen
  """Parses the output of listing instances by xen.
111 b255379d Michael Hanselmann

112 b255379d Michael Hanselmann
  @type lines: list
113 2609da63 Helga Velroyen
  @param lines: Result of retrieving the instance list from xen
114 b255379d Michael Hanselmann
  @type include_node: boolean
115 b255379d Michael Hanselmann
  @param include_node: If True, return information for Dom0
116 b255379d Michael Hanselmann
  @return: list of tuple containing (name, id, memory, vcpus, state, time
117 b255379d Michael Hanselmann
    spent)
118 b255379d Michael Hanselmann

119 b255379d Michael Hanselmann
  """
120 b255379d Michael Hanselmann
  result = []
121 b255379d Michael Hanselmann
122 b255379d Michael Hanselmann
  # Iterate through all lines while ignoring header
123 b255379d Michael Hanselmann
  for line in lines[1:]:
124 b255379d Michael Hanselmann
    # The format of lines is:
125 b255379d Michael Hanselmann
    # Name      ID Mem(MiB) VCPUs State  Time(s)
126 b255379d Michael Hanselmann
    # Domain-0   0  3418     4 r-----    266.2
127 b255379d Michael Hanselmann
    data = line.split()
128 b255379d Michael Hanselmann
    if len(data) != 6:
129 2609da63 Helga Velroyen
      raise errors.HypervisorError("Can't parse instance list,"
130 b255379d Michael Hanselmann
                                   " line: %s" % line)
131 b255379d Michael Hanselmann
    try:
132 b255379d Michael Hanselmann
      data[1] = int(data[1])
133 b255379d Michael Hanselmann
      data[2] = int(data[2])
134 b255379d Michael Hanselmann
      data[3] = int(data[3])
135 b255379d Michael Hanselmann
      data[5] = float(data[5])
136 b255379d Michael Hanselmann
    except (TypeError, ValueError), err:
137 2609da63 Helga Velroyen
      raise errors.HypervisorError("Can't parse instance list,"
138 b255379d Michael Hanselmann
                                   " line: %s, error: %s" % (line, err))
139 b255379d Michael Hanselmann
140 b255379d Michael Hanselmann
    # skip the Domain-0 (optional)
141 b255379d Michael Hanselmann
    if include_node or data[0] != _DOM0_NAME:
142 b255379d Michael Hanselmann
      result.append(data)
143 b255379d Michael Hanselmann
144 b255379d Michael Hanselmann
  return result
145 b255379d Michael Hanselmann
146 b255379d Michael Hanselmann
147 36bebc53 Helga Velroyen
def _GetInstanceList(fn, include_node, _timeout=5):
148 b255379d Michael Hanselmann
  """Return the list of running instances.
149 b255379d Michael Hanselmann

150 2609da63 Helga Velroyen
  See L{_RunInstanceList} and L{_ParseInstanceList} for parameter details.
151 b255379d Michael Hanselmann

152 b255379d Michael Hanselmann
  """
153 ff19ac20 Helga Velroyen
  instance_list_errors = []
154 b255379d Michael Hanselmann
  try:
155 ff19ac20 Helga Velroyen
    lines = utils.Retry(_RunInstanceList, (0.3, 1.5, 1.0), _timeout,
156 ff19ac20 Helga Velroyen
                        args=(fn, instance_list_errors))
157 b255379d Michael Hanselmann
  except utils.RetryTimeout:
158 ff19ac20 Helga Velroyen
    if instance_list_errors:
159 ff19ac20 Helga Velroyen
      instance_list_result = instance_list_errors.pop()
160 b255379d Michael Hanselmann
161 ff19ac20 Helga Velroyen
      errmsg = ("listing instances failed, timeout exceeded (%s): %s" %
162 ff19ac20 Helga Velroyen
                (instance_list_result.fail_reason, instance_list_result.output))
163 b255379d Michael Hanselmann
    else:
164 ff19ac20 Helga Velroyen
      errmsg = "listing instances failed"
165 b255379d Michael Hanselmann
166 b255379d Michael Hanselmann
    raise errors.HypervisorError(errmsg)
167 b255379d Michael Hanselmann
168 2609da63 Helga Velroyen
  return _ParseInstanceList(lines, include_node)
169 b255379d Michael Hanselmann
170 b255379d Michael Hanselmann
171 364c350f Jose A. Lopes
def _IsInstanceRunning(instance_info):
172 364c350f Jose A. Lopes
  return instance_info == "r-----" \
173 364c350f Jose A. Lopes
      or instance_info == "-b----"
174 364c350f Jose A. Lopes
175 364c350f Jose A. Lopes
176 364c350f Jose A. Lopes
def _IsInstanceShutdown(instance_info):
177 364c350f Jose A. Lopes
  return instance_info == "---s--"
178 364c350f Jose A. Lopes
179 364c350f Jose A. Lopes
180 06c9a520 Michael Hanselmann
def _ParseNodeInfo(info):
181 06c9a520 Michael Hanselmann
  """Return information about the node.
182 06c9a520 Michael Hanselmann

183 06c9a520 Michael Hanselmann
  @return: a dict with the following keys (memory values in MiB):
184 06c9a520 Michael Hanselmann
        - memory_total: the total memory size on the node
185 06c9a520 Michael Hanselmann
        - memory_free: the available memory on the node for instances
186 06c9a520 Michael Hanselmann
        - nr_cpus: total number of CPUs
187 06c9a520 Michael Hanselmann
        - nr_nodes: in a NUMA system, the number of domains
188 06c9a520 Michael Hanselmann
        - nr_sockets: the number of physical CPU sockets in the node
189 06c9a520 Michael Hanselmann
        - hv_version: the hypervisor version in the form (major, minor)
190 06c9a520 Michael Hanselmann

191 06c9a520 Michael Hanselmann
  """
192 06c9a520 Michael Hanselmann
  result = {}
193 06c9a520 Michael Hanselmann
  cores_per_socket = threads_per_core = nr_cpus = None
194 06c9a520 Michael Hanselmann
  xen_major, xen_minor = None, None
195 06c9a520 Michael Hanselmann
  memory_total = None
196 06c9a520 Michael Hanselmann
  memory_free = None
197 06c9a520 Michael Hanselmann
198 06c9a520 Michael Hanselmann
  for line in info.splitlines():
199 06c9a520 Michael Hanselmann
    fields = line.split(":", 1)
200 06c9a520 Michael Hanselmann
201 06c9a520 Michael Hanselmann
    if len(fields) < 2:
202 06c9a520 Michael Hanselmann
      continue
203 06c9a520 Michael Hanselmann
204 06c9a520 Michael Hanselmann
    (key, val) = map(lambda s: s.strip(), fields)
205 06c9a520 Michael Hanselmann
206 06c9a520 Michael Hanselmann
    # Note: in Xen 3, memory has changed to total_memory
207 06c9a520 Michael Hanselmann
    if key in ("memory", "total_memory"):
208 06c9a520 Michael Hanselmann
      memory_total = int(val)
209 06c9a520 Michael Hanselmann
    elif key == "free_memory":
210 06c9a520 Michael Hanselmann
      memory_free = int(val)
211 06c9a520 Michael Hanselmann
    elif key == "nr_cpus":
212 06c9a520 Michael Hanselmann
      nr_cpus = result["cpu_total"] = int(val)
213 06c9a520 Michael Hanselmann
    elif key == "nr_nodes":
214 06c9a520 Michael Hanselmann
      result["cpu_nodes"] = int(val)
215 06c9a520 Michael Hanselmann
    elif key == "cores_per_socket":
216 06c9a520 Michael Hanselmann
      cores_per_socket = int(val)
217 06c9a520 Michael Hanselmann
    elif key == "threads_per_core":
218 06c9a520 Michael Hanselmann
      threads_per_core = int(val)
219 06c9a520 Michael Hanselmann
    elif key == "xen_major":
220 06c9a520 Michael Hanselmann
      xen_major = int(val)
221 06c9a520 Michael Hanselmann
    elif key == "xen_minor":
222 06c9a520 Michael Hanselmann
      xen_minor = int(val)
223 06c9a520 Michael Hanselmann
224 06c9a520 Michael Hanselmann
  if None not in [cores_per_socket, threads_per_core, nr_cpus]:
225 06c9a520 Michael Hanselmann
    result["cpu_sockets"] = nr_cpus / (cores_per_socket * threads_per_core)
226 06c9a520 Michael Hanselmann
227 06c9a520 Michael Hanselmann
  if memory_free is not None:
228 06c9a520 Michael Hanselmann
    result["memory_free"] = memory_free
229 06c9a520 Michael Hanselmann
230 06c9a520 Michael Hanselmann
  if memory_total is not None:
231 06c9a520 Michael Hanselmann
    result["memory_total"] = memory_total
232 06c9a520 Michael Hanselmann
233 06c9a520 Michael Hanselmann
  if not (xen_major is None or xen_minor is None):
234 06c9a520 Michael Hanselmann
    result[constants.HV_NODEINFO_KEY_VERSION] = (xen_major, xen_minor)
235 06c9a520 Michael Hanselmann
236 06c9a520 Michael Hanselmann
  return result
237 06c9a520 Michael Hanselmann
238 06c9a520 Michael Hanselmann
239 fac489a5 Helga Velroyen
def _MergeInstanceInfo(info, instance_list):
240 06c9a520 Michael Hanselmann
  """Updates node information from L{_ParseNodeInfo} with instance info.
241 06c9a520 Michael Hanselmann

242 06c9a520 Michael Hanselmann
  @type info: dict
243 06c9a520 Michael Hanselmann
  @param info: Result from L{_ParseNodeInfo}
244 fac489a5 Helga Velroyen
  @type instance_list: list of tuples
245 fac489a5 Helga Velroyen
  @param instance_list: list of instance information; one tuple per instance
246 06c9a520 Michael Hanselmann
  @rtype: dict
247 06c9a520 Michael Hanselmann

248 06c9a520 Michael Hanselmann
  """
249 06c9a520 Michael Hanselmann
  total_instmem = 0
250 06c9a520 Michael Hanselmann
251 fac489a5 Helga Velroyen
  for (name, _, mem, vcpus, _, _) in instance_list:
252 06c9a520 Michael Hanselmann
    if name == _DOM0_NAME:
253 06c9a520 Michael Hanselmann
      info["memory_dom0"] = mem
254 ff05ff94 Bernardo Dal Seno
      info["cpu_dom0"] = vcpus
255 06c9a520 Michael Hanselmann
256 06c9a520 Michael Hanselmann
    # Include Dom0 in total memory usage
257 06c9a520 Michael Hanselmann
    total_instmem += mem
258 06c9a520 Michael Hanselmann
259 06c9a520 Michael Hanselmann
  memory_free = info.get("memory_free")
260 06c9a520 Michael Hanselmann
  memory_total = info.get("memory_total")
261 06c9a520 Michael Hanselmann
262 06c9a520 Michael Hanselmann
  # Calculate memory used by hypervisor
263 06c9a520 Michael Hanselmann
  if None not in [memory_total, memory_free, total_instmem]:
264 06c9a520 Michael Hanselmann
    info["memory_hv"] = memory_total - memory_free - total_instmem
265 06c9a520 Michael Hanselmann
266 06c9a520 Michael Hanselmann
  return info
267 06c9a520 Michael Hanselmann
268 06c9a520 Michael Hanselmann
269 fac489a5 Helga Velroyen
def _GetNodeInfo(info, instance_list):
270 06c9a520 Michael Hanselmann
  """Combines L{_MergeInstanceInfo} and L{_ParseNodeInfo}.
271 06c9a520 Michael Hanselmann

272 fac489a5 Helga Velroyen
  @type instance_list: list of tuples
273 fac489a5 Helga Velroyen
  @param instance_list: list of instance information; one tuple per instance
274 fac489a5 Helga Velroyen

275 06c9a520 Michael Hanselmann
  """
276 fac489a5 Helga Velroyen
  return _MergeInstanceInfo(_ParseNodeInfo(info), instance_list)
277 06c9a520 Michael Hanselmann
278 06c9a520 Michael Hanselmann
279 d0bb3f24 Michael Hanselmann
def _GetConfigFileDiskData(block_devices, blockdev_prefix,
280 d0bb3f24 Michael Hanselmann
                           _letters=_DISK_LETTERS):
281 d0bb3f24 Michael Hanselmann
  """Get disk directives for Xen config file.
282 d0bb3f24 Michael Hanselmann

283 d0bb3f24 Michael Hanselmann
  This method builds the xen config disk directive according to the
284 d0bb3f24 Michael Hanselmann
  given disk_template and block_devices.
285 d0bb3f24 Michael Hanselmann

286 d0bb3f24 Michael Hanselmann
  @param block_devices: list of tuples (cfdev, rldev):
287 d0bb3f24 Michael Hanselmann
      - cfdev: dict containing ganeti config disk part
288 ce9283c1 Thomas Thrainer
      - rldev: ganeti.block.bdev.BlockDev object
289 d0bb3f24 Michael Hanselmann
  @param blockdev_prefix: a string containing blockdevice prefix,
290 d0bb3f24 Michael Hanselmann
                          e.g. "sd" for /dev/sda
291 d0bb3f24 Michael Hanselmann

292 d0bb3f24 Michael Hanselmann
  @return: string containing disk directive for xen instance config file
293 d0bb3f24 Michael Hanselmann

294 d0bb3f24 Michael Hanselmann
  """
295 d0bb3f24 Michael Hanselmann
  if len(block_devices) > len(_letters):
296 d0bb3f24 Michael Hanselmann
    raise errors.HypervisorError("Too many disks")
297 d0bb3f24 Michael Hanselmann
298 d0bb3f24 Michael Hanselmann
  disk_data = []
299 d0bb3f24 Michael Hanselmann
300 117a85a0 Raffa Santi
  for sd_suffix, (cfdev, dev_path, _) in zip(_letters, block_devices):
301 d0bb3f24 Michael Hanselmann
    sd_name = blockdev_prefix + sd_suffix
302 d0bb3f24 Michael Hanselmann
303 d0bb3f24 Michael Hanselmann
    if cfdev.mode == constants.DISK_RDWR:
304 d0bb3f24 Michael Hanselmann
      mode = "w"
305 d0bb3f24 Michael Hanselmann
    else:
306 d0bb3f24 Michael Hanselmann
      mode = "r"
307 d0bb3f24 Michael Hanselmann
308 cd3b4ff4 Helga Velroyen
    if cfdev.dev_type in [constants.DT_FILE, constants.DT_SHARED_FILE]:
309 a57e502a Thomas Thrainer
      driver = _FILE_DRIVER_MAP[cfdev.logical_id[0]]
310 d0bb3f24 Michael Hanselmann
    else:
311 d0bb3f24 Michael Hanselmann
      driver = "phy"
312 d0bb3f24 Michael Hanselmann
313 d0bb3f24 Michael Hanselmann
    disk_data.append("'%s:%s,%s,%s'" % (driver, dev_path, sd_name, mode))
314 d0bb3f24 Michael Hanselmann
315 d0bb3f24 Michael Hanselmann
  return disk_data
316 d0bb3f24 Michael Hanselmann
317 d0bb3f24 Michael Hanselmann
318 295ed29b Santi Raffa
def _QuoteCpuidField(data):
319 295ed29b Santi Raffa
  """Add quotes around the CPUID field only if necessary.
320 295ed29b Santi Raffa

321 295ed29b Santi Raffa
  Xen CPUID fields come in two shapes: LIBXL strings, which need quotes around
322 295ed29b Santi Raffa
  them, and lists of XEND strings, which don't.
323 295ed29b Santi Raffa

324 295ed29b Santi Raffa
  @param data: Either type of parameter.
325 295ed29b Santi Raffa
  @return: The quoted version thereof.
326 295ed29b Santi Raffa

327 295ed29b Santi Raffa
  """
328 295ed29b Santi Raffa
  return "'%s'" % data if data.startswith("host") else data
329 295ed29b Santi Raffa
330 295ed29b Santi Raffa
331 a2d32034 Michael Hanselmann
class XenHypervisor(hv_base.BaseHypervisor):
332 65a6f9b7 Michael Hanselmann
  """Xen generic hypervisor interface
333 65a6f9b7 Michael Hanselmann

334 65a6f9b7 Michael Hanselmann
  This is the Xen base class used for both Xen PVM and HVM. It contains
335 65a6f9b7 Michael Hanselmann
  all the functionality that is identical for both.
336 65a6f9b7 Michael Hanselmann

337 65a6f9b7 Michael Hanselmann
  """
338 d271c6fd Iustin Pop
  CAN_MIGRATE = True
339 7dd106d3 Iustin Pop
  REBOOT_RETRY_COUNT = 60
340 7dd106d3 Iustin Pop
  REBOOT_RETRY_INTERVAL = 10
341 397b7844 Dimitris Aragiorgis
  _ROOT_DIR = pathutils.RUN_DIR + "/xen-hypervisor"
342 397b7844 Dimitris Aragiorgis
  _NICS_DIR = _ROOT_DIR + "/nic" # contains NICs' info
343 397b7844 Dimitris Aragiorgis
  _DIRS = [_ROOT_DIR, _NICS_DIR]
344 65a6f9b7 Michael Hanselmann
345 3680f662 Guido Trotter
  ANCILLARY_FILES = [
346 22d568c2 Guido Trotter
    XEND_CONFIG_FILE,
347 22d568c2 Guido Trotter
    XL_CONFIG_FILE,
348 22d568c2 Guido Trotter
    VIF_BRIDGE_SCRIPT,
349 3680f662 Guido Trotter
    ]
350 69ab2e12 Guido Trotter
  ANCILLARY_FILES_OPT = [
351 69ab2e12 Guido Trotter
    XL_CONFIG_FILE,
352 3680f662 Guido Trotter
    ]
353 3680f662 Guido Trotter
354 3d942d8b Michael Hanselmann
  def __init__(self, _cfgdir=None, _run_cmd_fn=None, _cmd=None):
355 0a903309 Michael Hanselmann
    hv_base.BaseHypervisor.__init__(self)
356 0a903309 Michael Hanselmann
357 0a903309 Michael Hanselmann
    if _cfgdir is None:
358 0a903309 Michael Hanselmann
      self._cfgdir = pathutils.XEN_CONFIG_DIR
359 0a903309 Michael Hanselmann
    else:
360 0a903309 Michael Hanselmann
      self._cfgdir = _cfgdir
361 0a903309 Michael Hanselmann
362 3d942d8b Michael Hanselmann
    if _run_cmd_fn is None:
363 3d942d8b Michael Hanselmann
      self._run_cmd_fn = utils.RunCmd
364 3d942d8b Michael Hanselmann
    else:
365 3d942d8b Michael Hanselmann
      self._run_cmd_fn = _run_cmd_fn
366 3d942d8b Michael Hanselmann
367 3d942d8b Michael Hanselmann
    self._cmd = _cmd
368 3d942d8b Michael Hanselmann
369 f92d9674 Helga Velroyen
  @staticmethod
370 f92d9674 Helga Velroyen
  def _GetCommandFromHvparams(hvparams):
371 f92d9674 Helga Velroyen
    """Returns the Xen command extracted from the given hvparams.
372 f92d9674 Helga Velroyen

373 f92d9674 Helga Velroyen
    @type hvparams: dict of strings
374 f92d9674 Helga Velroyen
    @param hvparams: hypervisor parameters
375 f92d9674 Helga Velroyen

376 f92d9674 Helga Velroyen
    """
377 f92d9674 Helga Velroyen
    if hvparams is None or constants.HV_XEN_CMD not in hvparams:
378 f92d9674 Helga Velroyen
      raise errors.HypervisorError("Cannot determine xen command.")
379 f92d9674 Helga Velroyen
    else:
380 f92d9674 Helga Velroyen
      return hvparams[constants.HV_XEN_CMD]
381 f92d9674 Helga Velroyen
382 398fd4f6 Helga Velroyen
  def _GetCommand(self, hvparams):
383 d8784f7d Michael Hanselmann
    """Returns Xen command to use.
384 d8784f7d Michael Hanselmann

385 51a95d00 Helga Velroyen
    @type hvparams: dict of strings
386 51a95d00 Helga Velroyen
    @param hvparams: hypervisor parameters
387 51a95d00 Helga Velroyen

388 d8784f7d Michael Hanselmann
    """
389 3d942d8b Michael Hanselmann
    if self._cmd is None:
390 f92d9674 Helga Velroyen
      cmd = XenHypervisor._GetCommandFromHvparams(hvparams)
391 3d942d8b Michael Hanselmann
    else:
392 3d942d8b Michael Hanselmann
      cmd = self._cmd
393 3d942d8b Michael Hanselmann
394 3d942d8b Michael Hanselmann
    if cmd not in constants.KNOWN_XEN_COMMANDS:
395 3d942d8b Michael Hanselmann
      raise errors.ProgrammerError("Unknown Xen command '%s'" % cmd)
396 3d942d8b Michael Hanselmann
397 3d942d8b Michael Hanselmann
    return cmd
398 3d942d8b Michael Hanselmann
399 85530402 Michele Tartara
  def _RunXen(self, args, hvparams, timeout=None):
400 81124130 Michael Hanselmann
    """Wrapper around L{utils.process.RunCmd} to run Xen command.
401 3d942d8b Michael Hanselmann

402 58e356a9 Helga Velroyen
    @type hvparams: dict of strings
403 58e356a9 Helga Velroyen
    @param hvparams: dictionary of hypervisor params
404 85530402 Michele Tartara
    @type timeout: int or None
405 85530402 Michele Tartara
    @param timeout: if a timeout (in seconds) is specified, the command will be
406 85530402 Michele Tartara
                    terminated after that number of seconds.
407 81124130 Michael Hanselmann
    @see: L{utils.process.RunCmd}
408 3d942d8b Michael Hanselmann

409 3d942d8b Michael Hanselmann
    """
410 7066724d Michele Tartara
    cmd = []
411 7066724d Michele Tartara
412 7066724d Michele Tartara
    if timeout is not None:
413 7066724d Michele Tartara
      cmd.extend(["timeout", str(timeout)])
414 7066724d Michele Tartara
415 85530402 Michele Tartara
    cmd.extend([self._GetCommand(hvparams)])
416 3d942d8b Michael Hanselmann
    cmd.extend(args)
417 3d942d8b Michael Hanselmann
418 3d942d8b Michael Hanselmann
    return self._run_cmd_fn(cmd)
419 3d942d8b Michael Hanselmann
420 0a903309 Michael Hanselmann
  def _ConfigFileName(self, instance_name):
421 c2be2532 Guido Trotter
    """Get the config file name for an instance.
422 c2be2532 Guido Trotter

423 c2be2532 Guido Trotter
    @param instance_name: instance name
424 c2be2532 Guido Trotter
    @type instance_name: str
425 c2be2532 Guido Trotter
    @return: fully qualified path to instance config file
426 c2be2532 Guido Trotter
    @rtype: str
427 c2be2532 Guido Trotter

428 c2be2532 Guido Trotter
    """
429 0a903309 Michael Hanselmann
    return utils.PathJoin(self._cfgdir, instance_name)
430 c2be2532 Guido Trotter
431 5661b908 Iustin Pop
  @classmethod
432 2a3bbbaa Dimitris Aragiorgis
  def _WriteNICInfoFile(cls, instance, idx, nic):
433 397b7844 Dimitris Aragiorgis
    """Write the Xen config file for the instance.
434 397b7844 Dimitris Aragiorgis

435 397b7844 Dimitris Aragiorgis
    This version of the function just writes the config file from static data.
436 397b7844 Dimitris Aragiorgis

437 397b7844 Dimitris Aragiorgis
    """
438 2a3bbbaa Dimitris Aragiorgis
    instance_name = instance.name
439 397b7844 Dimitris Aragiorgis
    dirs = [(dname, constants.RUN_DIRS_MODE)
440 397b7844 Dimitris Aragiorgis
            for dname in cls._DIRS + [cls._InstanceNICDir(instance_name)]]
441 397b7844 Dimitris Aragiorgis
    utils.EnsureDirs(dirs)
442 397b7844 Dimitris Aragiorgis
443 397b7844 Dimitris Aragiorgis
    cfg_file = cls._InstanceNICFile(instance_name, idx)
444 397b7844 Dimitris Aragiorgis
    data = StringIO()
445 397b7844 Dimitris Aragiorgis
446 4a65d4fd Thomas Thrainer
    data.write("TAGS=%s\n" % r"\ ".join(instance.GetTags()))
447 397b7844 Dimitris Aragiorgis
    if nic.netinfo:
448 397b7844 Dimitris Aragiorgis
      netinfo = objects.Network.FromDict(nic.netinfo)
449 884ec6d4 Dimitris Aragiorgis
      for k, v in netinfo.HooksDict().iteritems():
450 884ec6d4 Dimitris Aragiorgis
        data.write("%s=%s\n" % (k, v))
451 397b7844 Dimitris Aragiorgis
452 397b7844 Dimitris Aragiorgis
    data.write("MAC=%s\n" % nic.mac)
453 cc6fd3da Dimitris Aragiorgis
    if nic.ip:
454 cc6fd3da Dimitris Aragiorgis
      data.write("IP=%s\n" % nic.ip)
455 cc6fd3da Dimitris Aragiorgis
    data.write("INTERFACE_INDEX=%s\n" % str(idx))
456 cc6fd3da Dimitris Aragiorgis
    if nic.name:
457 cc6fd3da Dimitris Aragiorgis
      data.write("INTERFACE_NAME=%s\n" % nic.name)
458 cc6fd3da Dimitris Aragiorgis
    data.write("INTERFACE_UUID=%s\n" % nic.uuid)
459 397b7844 Dimitris Aragiorgis
    data.write("MODE=%s\n" % nic.nicparams[constants.NIC_MODE])
460 397b7844 Dimitris Aragiorgis
    data.write("LINK=%s\n" % nic.nicparams[constants.NIC_LINK])
461 397b7844 Dimitris Aragiorgis
462 397b7844 Dimitris Aragiorgis
    try:
463 397b7844 Dimitris Aragiorgis
      utils.WriteFile(cfg_file, data=data.getvalue())
464 397b7844 Dimitris Aragiorgis
    except EnvironmentError, err:
465 397b7844 Dimitris Aragiorgis
      raise errors.HypervisorError("Cannot write Xen instance configuration"
466 397b7844 Dimitris Aragiorgis
                                   " file %s: %s" % (cfg_file, err))
467 397b7844 Dimitris Aragiorgis
468 397b7844 Dimitris Aragiorgis
  @classmethod
469 397b7844 Dimitris Aragiorgis
  def _InstanceNICDir(cls, instance_name):
470 397b7844 Dimitris Aragiorgis
    """Returns the directory holding the tap device files for a given instance.
471 397b7844 Dimitris Aragiorgis

472 397b7844 Dimitris Aragiorgis
    """
473 397b7844 Dimitris Aragiorgis
    return utils.PathJoin(cls._NICS_DIR, instance_name)
474 397b7844 Dimitris Aragiorgis
475 397b7844 Dimitris Aragiorgis
  @classmethod
476 397b7844 Dimitris Aragiorgis
  def _InstanceNICFile(cls, instance_name, seq):
477 397b7844 Dimitris Aragiorgis
    """Returns the name of the file containing the tap device for a given NIC
478 397b7844 Dimitris Aragiorgis

479 397b7844 Dimitris Aragiorgis
    """
480 397b7844 Dimitris Aragiorgis
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
481 397b7844 Dimitris Aragiorgis
482 397b7844 Dimitris Aragiorgis
  @classmethod
483 c3d839f5 Michael Hanselmann
  def _GetConfig(cls, instance, startup_memory, block_devices):
484 c3d839f5 Michael Hanselmann
    """Build Xen configuration for an instance.
485 65a6f9b7 Michael Hanselmann

486 65a6f9b7 Michael Hanselmann
    """
487 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
488 65a6f9b7 Michael Hanselmann
489 c3d839f5 Michael Hanselmann
  def _WriteConfigFile(self, instance_name, data):
490 4390ccff Guido Trotter
    """Write the Xen config file for the instance.
491 4390ccff Guido Trotter

492 4390ccff Guido Trotter
    This version of the function just writes the config file from static data.
493 4390ccff Guido Trotter

494 4390ccff Guido Trotter
    """
495 1a63f285 Iustin Pop
    # just in case it exists
496 0a903309 Michael Hanselmann
    utils.RemoveFile(utils.PathJoin(self._cfgdir, "auto", instance_name))
497 a8e8c0c6 Michael Hanselmann
498 0a903309 Michael Hanselmann
    cfg_file = self._ConfigFileName(instance_name)
499 1a63f285 Iustin Pop
    try:
500 1a63f285 Iustin Pop
      utils.WriteFile(cfg_file, data=data)
501 1a63f285 Iustin Pop
    except EnvironmentError, err:
502 1a63f285 Iustin Pop
      raise errors.HypervisorError("Cannot write Xen instance configuration"
503 1a63f285 Iustin Pop
                                   " file %s: %s" % (cfg_file, err))
504 4390ccff Guido Trotter
505 0a903309 Michael Hanselmann
  def _ReadConfigFile(self, instance_name):
506 4390ccff Guido Trotter
    """Returns the contents of the instance config file.
507 4390ccff Guido Trotter

508 4390ccff Guido Trotter
    """
509 0a903309 Michael Hanselmann
    filename = self._ConfigFileName(instance_name)
510 76c364d9 Michael Hanselmann
511 4390ccff Guido Trotter
    try:
512 76c364d9 Michael Hanselmann
      file_content = utils.ReadFile(filename)
513 4390ccff Guido Trotter
    except EnvironmentError, err:
514 4390ccff Guido Trotter
      raise errors.HypervisorError("Failed to load Xen config file: %s" % err)
515 76c364d9 Michael Hanselmann
516 4390ccff Guido Trotter
    return file_content
517 4390ccff Guido Trotter
518 0a903309 Michael Hanselmann
  def _RemoveConfigFile(self, instance_name):
519 65a6f9b7 Michael Hanselmann
    """Remove the xen configuration file.
520 65a6f9b7 Michael Hanselmann

521 65a6f9b7 Michael Hanselmann
    """
522 0a903309 Michael Hanselmann
    utils.RemoveFile(self._ConfigFileName(instance_name))
523 397b7844 Dimitris Aragiorgis
    try:
524 397b7844 Dimitris Aragiorgis
      shutil.rmtree(self._InstanceNICDir(instance_name))
525 397b7844 Dimitris Aragiorgis
    except OSError, err:
526 397b7844 Dimitris Aragiorgis
      if err.errno != errno.ENOENT:
527 397b7844 Dimitris Aragiorgis
        raise
528 65a6f9b7 Michael Hanselmann
529 48bba9de Balazs Lecz
  def _StashConfigFile(self, instance_name):
530 48bba9de Balazs Lecz
    """Move the Xen config file to the log directory and return its new path.
531 48bba9de Balazs Lecz

532 48bba9de Balazs Lecz
    """
533 48bba9de Balazs Lecz
    old_filename = self._ConfigFileName(instance_name)
534 48bba9de Balazs Lecz
    base = ("%s-%s" %
535 48bba9de Balazs Lecz
            (instance_name, utils.TimestampForFilename()))
536 48bba9de Balazs Lecz
    new_filename = utils.PathJoin(pathutils.LOG_XEN_DIR, base)
537 48bba9de Balazs Lecz
    utils.RenameFile(old_filename, new_filename)
538 48bba9de Balazs Lecz
    return new_filename
539 48bba9de Balazs Lecz
540 398fd4f6 Helga Velroyen
  def _GetInstanceList(self, include_node, hvparams):
541 36bebc53 Helga Velroyen
    """Wrapper around module level L{_GetInstanceList}.
542 06b78e8b Michael Hanselmann

543 398fd4f6 Helga Velroyen
    @type hvparams: dict of strings
544 398fd4f6 Helga Velroyen
    @param hvparams: hypervisor parameters to be used on this node
545 398fd4f6 Helga Velroyen

546 06b78e8b Michael Hanselmann
    """
547 398fd4f6 Helga Velroyen
    return _GetInstanceList(lambda: self._RunXen(["list"], hvparams),
548 58e356a9 Helga Velroyen
                            include_node)
549 65a6f9b7 Michael Hanselmann
550 58e356a9 Helga Velroyen
  def ListInstances(self, hvparams=None):
551 65a6f9b7 Michael Hanselmann
    """Get the list of running instances.
552 65a6f9b7 Michael Hanselmann

553 65a6f9b7 Michael Hanselmann
    """
554 398fd4f6 Helga Velroyen
    instance_list = self._GetInstanceList(False, hvparams)
555 36bebc53 Helga Velroyen
    names = [info[0] for info in instance_list]
556 65a6f9b7 Michael Hanselmann
    return names
557 65a6f9b7 Michael Hanselmann
558 0bbec3af Helga Velroyen
  def GetInstanceInfo(self, instance_name, hvparams=None):
559 65a6f9b7 Michael Hanselmann
    """Get instance properties.
560 65a6f9b7 Michael Hanselmann

561 0bbec3af Helga Velroyen
    @type instance_name: string
562 c41eea6e Iustin Pop
    @param instance_name: the instance name
563 0bbec3af Helga Velroyen
    @type hvparams: dict of strings
564 0bbec3af Helga Velroyen
    @param hvparams: the instance's hypervisor params
565 c41eea6e Iustin Pop

566 c41eea6e Iustin Pop
    @return: tuple (name, id, memory, vcpus, stat, times)
567 65a6f9b7 Michael Hanselmann

568 65a6f9b7 Michael Hanselmann
    """
569 398fd4f6 Helga Velroyen
    instance_list = self._GetInstanceList(instance_name == _DOM0_NAME, hvparams)
570 65a6f9b7 Michael Hanselmann
    result = None
571 36bebc53 Helga Velroyen
    for data in instance_list:
572 65a6f9b7 Michael Hanselmann
      if data[0] == instance_name:
573 65a6f9b7 Michael Hanselmann
        result = data
574 65a6f9b7 Michael Hanselmann
        break
575 65a6f9b7 Michael Hanselmann
    return result
576 65a6f9b7 Michael Hanselmann
577 0200a1af Helga Velroyen
  def GetAllInstancesInfo(self, hvparams=None):
578 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
579 65a6f9b7 Michael Hanselmann

580 0200a1af Helga Velroyen
    @type hvparams: dict of strings
581 0200a1af Helga Velroyen
    @param hvparams: hypervisor parameters
582 c41eea6e Iustin Pop
    @return: list of tuples (name, id, memory, vcpus, stat, times)
583 c41eea6e Iustin Pop

584 65a6f9b7 Michael Hanselmann
    """
585 398fd4f6 Helga Velroyen
    return self._GetInstanceList(False, hvparams)
586 65a6f9b7 Michael Hanselmann
587 c3d839f5 Michael Hanselmann
  def _MakeConfigFile(self, instance, startup_memory, block_devices):
588 c3d839f5 Michael Hanselmann
    """Gather configuration details and write to disk.
589 c3d839f5 Michael Hanselmann

590 c3d839f5 Michael Hanselmann
    See L{_GetConfig} for arguments.
591 c3d839f5 Michael Hanselmann

592 c3d839f5 Michael Hanselmann
    """
593 c3d839f5 Michael Hanselmann
    buf = StringIO()
594 c3d839f5 Michael Hanselmann
    buf.write("# Automatically generated by Ganeti. Do not edit!\n")
595 c3d839f5 Michael Hanselmann
    buf.write("\n")
596 c3d839f5 Michael Hanselmann
    buf.write(self._GetConfig(instance, startup_memory, block_devices))
597 c3d839f5 Michael Hanselmann
    buf.write("\n")
598 c3d839f5 Michael Hanselmann
599 c3d839f5 Michael Hanselmann
    self._WriteConfigFile(instance.name, buf.getvalue())
600 c3d839f5 Michael Hanselmann
601 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
602 c41eea6e Iustin Pop
    """Start an instance.
603 c41eea6e Iustin Pop

604 c41eea6e Iustin Pop
    """
605 30b12688 Jose A. Lopes
    startup_memory = self._InstanceStartupMemory(instance)
606 c3d839f5 Michael Hanselmann
607 c3d839f5 Michael Hanselmann
    self._MakeConfigFile(instance, startup_memory, block_devices)
608 c3d839f5 Michael Hanselmann
609 3d942d8b Michael Hanselmann
    cmd = ["create"]
610 323f9095 Stephen Shirley
    if startup_paused:
611 3d942d8b Michael Hanselmann
      cmd.append("-p")
612 3d942d8b Michael Hanselmann
    cmd.append(self._ConfigFileName(instance.name))
613 65a6f9b7 Michael Hanselmann
614 398fd4f6 Helga Velroyen
    result = self._RunXen(cmd, instance.hvparams)
615 65a6f9b7 Michael Hanselmann
    if result.failed:
616 48bba9de Balazs Lecz
      # Move the Xen configuration file to the log directory to avoid
617 48bba9de Balazs Lecz
      # leaving a stale config file behind.
618 48bba9de Balazs Lecz
      stashed_config = self._StashConfigFile(instance.name)
619 48bba9de Balazs Lecz
      raise errors.HypervisorError("Failed to start instance %s: %s (%s). Moved"
620 48bba9de Balazs Lecz
                                   " config file to %s" %
621 65a6f9b7 Michael Hanselmann
                                   (instance.name, result.fail_reason,
622 48bba9de Balazs Lecz
                                    result.output, stashed_config))
623 65a6f9b7 Michael Hanselmann
624 874f6148 Michele Tartara
  def StopInstance(self, instance, force=False, retry=False, name=None,
625 874f6148 Michele Tartara
                   timeout=None):
626 c41eea6e Iustin Pop
    """Stop an instance.
627 c41eea6e Iustin Pop

628 874f6148 Michele Tartara
    A soft shutdown can be interrupted. A hard shutdown tries forever.
629 874f6148 Michele Tartara

630 c41eea6e Iustin Pop
    """
631 874f6148 Michele Tartara
    assert(timeout is None or force is not None)
632 874f6148 Michele Tartara
633 bbcf7ad0 Iustin Pop
    if name is None:
634 bbcf7ad0 Iustin Pop
      name = instance.name
635 4b8b172d Michael Hanselmann
636 85530402 Michele Tartara
    return self._StopInstance(name, force, instance.hvparams, timeout)
637 31da5ab5 Michael Hanselmann
638 ddc64582 Michele Tartara
  def _ShutdownInstance(self, name, hvparams, timeout):
639 364c350f Jose A. Lopes
    """Shutdown an instance if the instance is running.
640 364c350f Jose A. Lopes

641 364c350f Jose A. Lopes
    The '-w' flag waits for shutdown to complete which avoids the need
642 364c350f Jose A. Lopes
    to poll in the case where we want to destroy the domain
643 364c350f Jose A. Lopes
    immediately after shutdown.
644 364c350f Jose A. Lopes

645 364c350f Jose A. Lopes
    @type name: string
646 364c350f Jose A. Lopes
    @param name: name of the instance to stop
647 affe1792 Klaus Aehlig
    @type hvparams: dict of string
648 affe1792 Klaus Aehlig
    @param hvparams: hypervisor parameters of the instance
649 874f6148 Michele Tartara
    @type timeout: int or None
650 874f6148 Michele Tartara
    @param timeout: a timeout after which the shutdown command should be killed,
651 874f6148 Michele Tartara
                    or None for no timeout
652 364c350f Jose A. Lopes

653 364c350f Jose A. Lopes
    """
654 3d680d45 Klaus Aehlig
    instance_info = self.GetInstanceInfo(name, hvparams=hvparams)
655 364c350f Jose A. Lopes
656 364c350f Jose A. Lopes
    if instance_info is None or _IsInstanceShutdown(instance_info[4]):
657 364c350f Jose A. Lopes
      logging.info("Failed to shutdown instance %s, not running", name)
658 364c350f Jose A. Lopes
      return None
659 364c350f Jose A. Lopes
660 85530402 Michele Tartara
    return self._RunXen(["shutdown", "-w", name], hvparams, timeout)
661 364c350f Jose A. Lopes
662 affe1792 Klaus Aehlig
  def _DestroyInstance(self, name, hvparams):
663 364c350f Jose A. Lopes
    """Destroy an instance if the instance if the instance exists.
664 364c350f Jose A. Lopes

665 364c350f Jose A. Lopes
    @type name: string
666 364c350f Jose A. Lopes
    @param name: name of the instance to destroy
667 affe1792 Klaus Aehlig
    @type hvparams: dict of string
668 affe1792 Klaus Aehlig
    @param hvparams: hypervisor parameters of the instance
669 364c350f Jose A. Lopes

670 364c350f Jose A. Lopes
    """
671 3d680d45 Klaus Aehlig
    instance_info = self.GetInstanceInfo(name, hvparams=hvparams)
672 364c350f Jose A. Lopes
673 364c350f Jose A. Lopes
    if instance_info is None:
674 364c350f Jose A. Lopes
      logging.info("Failed to destroy instance %s, does not exist", name)
675 364c350f Jose A. Lopes
      return None
676 364c350f Jose A. Lopes
677 affe1792 Klaus Aehlig
    return self._RunXen(["destroy", name], hvparams)
678 364c350f Jose A. Lopes
679 85530402 Michele Tartara
  def _StopInstance(self, name, force, hvparams, timeout):
680 31da5ab5 Michael Hanselmann
    """Stop an instance.
681 31da5ab5 Michael Hanselmann

682 58e356a9 Helga Velroyen
    @type name: string
683 364c350f Jose A. Lopes
    @param name: name of the instance to destroy
684 364c350f Jose A. Lopes

685 58e356a9 Helga Velroyen
    @type force: boolean
686 364c350f Jose A. Lopes
    @param force: whether to do a "hard" stop (destroy)
687 364c350f Jose A. Lopes

688 58e356a9 Helga Velroyen
    @type hvparams: dict of string
689 58e356a9 Helga Velroyen
    @param hvparams: hypervisor parameters of the instance
690 58e356a9 Helga Velroyen

691 874f6148 Michele Tartara
    @type timeout: int or None
692 874f6148 Michele Tartara
    @param timeout: a timeout after which the shutdown command should be killed,
693 874f6148 Michele Tartara
                    or None for no timeout
694 874f6148 Michele Tartara

695 31da5ab5 Michael Hanselmann
    """
696 65a6f9b7 Michael Hanselmann
    if force:
697 affe1792 Klaus Aehlig
      result = self._DestroyInstance(name, hvparams)
698 65a6f9b7 Michael Hanselmann
    else:
699 85530402 Michele Tartara
      self._ShutdownInstance(name, hvparams, timeout)
700 affe1792 Klaus Aehlig
      result = self._DestroyInstance(name, hvparams)
701 65a6f9b7 Michael Hanselmann
702 364c350f Jose A. Lopes
    if result is not None and result.failed and \
703 3d680d45 Klaus Aehlig
          self.GetInstanceInfo(name, hvparams=hvparams) is not None:
704 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to stop instance %s: %s, %s" %
705 bbcf7ad0 Iustin Pop
                                   (name, result.fail_reason, result.output))
706 65a6f9b7 Michael Hanselmann
707 4b8b172d Michael Hanselmann
    # Remove configuration file if stopping/starting instance was successful
708 4b8b172d Michael Hanselmann
    self._RemoveConfigFile(name)
709 4b8b172d Michael Hanselmann
710 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
711 c41eea6e Iustin Pop
    """Reboot an instance.
712 c41eea6e Iustin Pop

713 c41eea6e Iustin Pop
    """
714 0bbec3af Helga Velroyen
    ini_info = self.GetInstanceInfo(instance.name, hvparams=instance.hvparams)
715 65a6f9b7 Michael Hanselmann
716 e0561198 Iustin Pop
    if ini_info is None:
717 e0561198 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s,"
718 e0561198 Iustin Pop
                                   " not running" % instance.name)
719 e0561198 Iustin Pop
720 398fd4f6 Helga Velroyen
    result = self._RunXen(["reboot", instance.name], instance.hvparams)
721 65a6f9b7 Michael Hanselmann
    if result.failed:
722 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s: %s, %s" %
723 3213d3c8 Iustin Pop
                                   (instance.name, result.fail_reason,
724 3213d3c8 Iustin Pop
                                    result.output))
725 06b78e8b Michael Hanselmann
726 06b78e8b Michael Hanselmann
    def _CheckInstance():
727 0bbec3af Helga Velroyen
      new_info = self.GetInstanceInfo(instance.name, hvparams=instance.hvparams)
728 06b78e8b Michael Hanselmann
729 06b78e8b Michael Hanselmann
      # check if the domain ID has changed or the run time has decreased
730 e0561198 Iustin Pop
      if (new_info is not None and
731 e0561198 Iustin Pop
          (new_info[1] != ini_info[1] or new_info[5] < ini_info[5])):
732 06b78e8b Michael Hanselmann
        return
733 7dd106d3 Iustin Pop
734 06b78e8b Michael Hanselmann
      raise utils.RetryAgain()
735 06b78e8b Michael Hanselmann
736 06b78e8b Michael Hanselmann
    try:
737 06b78e8b Michael Hanselmann
      utils.Retry(_CheckInstance, self.REBOOT_RETRY_INTERVAL,
738 06b78e8b Michael Hanselmann
                  self.REBOOT_RETRY_INTERVAL * self.REBOOT_RETRY_COUNT)
739 06b78e8b Michael Hanselmann
    except utils.RetryTimeout:
740 7dd106d3 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s: instance"
741 7dd106d3 Iustin Pop
                                   " did not reboot in the expected interval" %
742 7dd106d3 Iustin Pop
                                   (instance.name, ))
743 65a6f9b7 Michael Hanselmann
744 2c7a0373 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
745 2c7a0373 Guido Trotter
    """Balloon an instance memory to a certain value.
746 2c7a0373 Guido Trotter

747 2c7a0373 Guido Trotter
    @type instance: L{objects.Instance}
748 2c7a0373 Guido Trotter
    @param instance: instance to be accepted
749 2c7a0373 Guido Trotter
    @type mem: int
750 2c7a0373 Guido Trotter
    @param mem: actual memory size to use for instance runtime
751 2c7a0373 Guido Trotter

752 2c7a0373 Guido Trotter
    """
753 398fd4f6 Helga Velroyen
    result = self._RunXen(["mem-set", instance.name, mem], instance.hvparams)
754 2c7a0373 Guido Trotter
    if result.failed:
755 2c7a0373 Guido Trotter
      raise errors.HypervisorError("Failed to balloon instance %s: %s (%s)" %
756 2c7a0373 Guido Trotter
                                   (instance.name, result.fail_reason,
757 2c7a0373 Guido Trotter
                                    result.output))
758 3d942d8b Michael Hanselmann
759 3d942d8b Michael Hanselmann
    # Update configuration file
760 2c7a0373 Guido Trotter
    cmd = ["sed", "-ie", "s/^memory.*$/memory = %s/" % mem]
761 0a903309 Michael Hanselmann
    cmd.append(self._ConfigFileName(instance.name))
762 3d942d8b Michael Hanselmann
763 2c7a0373 Guido Trotter
    result = utils.RunCmd(cmd)
764 2c7a0373 Guido Trotter
    if result.failed:
765 2c7a0373 Guido Trotter
      raise errors.HypervisorError("Failed to update memory for %s: %s (%s)" %
766 2c7a0373 Guido Trotter
                                   (instance.name, result.fail_reason,
767 2c7a0373 Guido Trotter
                                    result.output))
768 2c7a0373 Guido Trotter
769 fac489a5 Helga Velroyen
  def GetNodeInfo(self, hvparams=None):
770 65a6f9b7 Michael Hanselmann
    """Return information about the node.
771 65a6f9b7 Michael Hanselmann

772 06c9a520 Michael Hanselmann
    @see: L{_GetNodeInfo} and L{_ParseNodeInfo}
773 65a6f9b7 Michael Hanselmann

774 65a6f9b7 Michael Hanselmann
    """
775 398fd4f6 Helga Velroyen
    result = self._RunXen(["info"], hvparams)
776 65a6f9b7 Michael Hanselmann
    if result.failed:
777 2609da63 Helga Velroyen
      logging.error("Can't retrieve xen hypervisor information (%s): %s",
778 2609da63 Helga Velroyen
                    result.fail_reason, result.output)
779 65a6f9b7 Michael Hanselmann
      return None
780 65a6f9b7 Michael Hanselmann
781 398fd4f6 Helga Velroyen
    instance_list = self._GetInstanceList(True, hvparams)
782 fac489a5 Helga Velroyen
    return _GetNodeInfo(result.stdout, instance_list)
783 65a6f9b7 Michael Hanselmann
784 f92d9674 Helga Velroyen
  @classmethod
785 f92d9674 Helga Velroyen
  def GetInstanceConsole(cls, instance, primary_node, hvparams, beparams):
786 65a6f9b7 Michael Hanselmann
    """Return a command for connecting to the console of an instance.
787 65a6f9b7 Michael Hanselmann

788 65a6f9b7 Michael Hanselmann
    """
789 f92d9674 Helga Velroyen
    xen_cmd = XenHypervisor._GetCommandFromHvparams(hvparams)
790 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
791 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_SSH,
792 1c3231aa Thomas Thrainer
                                   host=primary_node.name,
793 052783ff Michael Hanselmann
                                   user=constants.SSH_CONSOLE_USER,
794 b9612abb Iustin Pop
                                   command=[pathutils.XEN_CONSOLE_WRAPPER,
795 8ef418bb Helga Velroyen
                                            xen_cmd, instance.name])
796 65a6f9b7 Michael Hanselmann
797 75bf3149 Helga Velroyen
  def Verify(self, hvparams=None):
798 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
799 65a6f9b7 Michael Hanselmann

800 65a6f9b7 Michael Hanselmann
    For Xen, this verifies that the xend process is running.
801 65a6f9b7 Michael Hanselmann

802 75bf3149 Helga Velroyen
    @type hvparams: dict of strings
803 75bf3149 Helga Velroyen
    @param hvparams: hypervisor parameters to be verified against
804 75bf3149 Helga Velroyen

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

807 65a6f9b7 Michael Hanselmann
    """
808 75bf3149 Helga Velroyen
    if hvparams is None:
809 75bf3149 Helga Velroyen
      return "Could not verify the hypervisor, because no hvparams were" \
810 75bf3149 Helga Velroyen
             " provided."
811 75bf3149 Helga Velroyen
812 75bf3149 Helga Velroyen
    if constants.HV_XEN_CMD in hvparams:
813 75bf3149 Helga Velroyen
      xen_cmd = hvparams[constants.HV_XEN_CMD]
814 75bf3149 Helga Velroyen
      try:
815 75bf3149 Helga Velroyen
        self._CheckToolstack(xen_cmd)
816 75bf3149 Helga Velroyen
      except errors.HypervisorError:
817 75bf3149 Helga Velroyen
        return "The configured xen toolstack '%s' is not available on this" \
818 75bf3149 Helga Velroyen
               " node." % xen_cmd
819 75bf3149 Helga Velroyen
820 398fd4f6 Helga Velroyen
    result = self._RunXen(["info"], hvparams)
821 e3e66f02 Michael Hanselmann
    if result.failed:
822 75bf3149 Helga Velroyen
      return "Retrieving information from xen failed: %s, %s" % \
823 75bf3149 Helga Velroyen
        (result.fail_reason, result.output)
824 65a6f9b7 Michael Hanselmann
825 cd04dfd2 Michael Hanselmann
    return None
826 cd04dfd2 Michael Hanselmann
827 4390ccff Guido Trotter
  def MigrationInfo(self, instance):
828 4390ccff Guido Trotter
    """Get instance information to perform a migration.
829 4390ccff Guido Trotter

830 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
831 4390ccff Guido Trotter
    @param instance: instance to be migrated
832 4390ccff Guido Trotter
    @rtype: string
833 4390ccff Guido Trotter
    @return: content of the xen config file
834 4390ccff Guido Trotter

835 4390ccff Guido Trotter
    """
836 4390ccff Guido Trotter
    return self._ReadConfigFile(instance.name)
837 4390ccff Guido Trotter
838 4390ccff Guido Trotter
  def AcceptInstance(self, instance, info, target):
839 4390ccff Guido Trotter
    """Prepare to accept an instance.
840 4390ccff Guido Trotter

841 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
842 4390ccff Guido Trotter
    @param instance: instance to be accepted
843 4390ccff Guido Trotter
    @type info: string
844 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
845 4390ccff Guido Trotter
    @type target: string
846 4390ccff Guido Trotter
    @param target: target host (usually ip), on this node
847 4390ccff Guido Trotter

848 4390ccff Guido Trotter
    """
849 4390ccff Guido Trotter
    pass
850 4390ccff Guido Trotter
851 60af751d Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
852 4390ccff Guido Trotter
    """Finalize an instance migration.
853 4390ccff Guido Trotter

854 4390ccff Guido Trotter
    After a successful migration we write the xen config file.
855 4390ccff Guido Trotter
    We do nothing on a failure, as we did not change anything at accept time.
856 4390ccff Guido Trotter

857 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
858 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
859 4390ccff Guido Trotter
    @type info: string
860 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
861 4390ccff Guido Trotter
    @type success: boolean
862 4390ccff Guido Trotter
    @param success: whether the migration was a success or a failure
863 4390ccff Guido Trotter

864 4390ccff Guido Trotter
    """
865 4390ccff Guido Trotter
    if success:
866 c3d839f5 Michael Hanselmann
      self._WriteConfigFile(instance.name, info)
867 4390ccff Guido Trotter
868 bc0a2284 Helga Velroyen
  def MigrateInstance(self, cluster_name, instance, target, live):
869 6e7275c0 Iustin Pop
    """Migrate an instance to a target node.
870 6e7275c0 Iustin Pop

871 6e7275c0 Iustin Pop
    The migration will not be attempted if the instance is not
872 6e7275c0 Iustin Pop
    currently running.
873 6e7275c0 Iustin Pop

874 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
875 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
876 fdf7f055 Guido Trotter
    @type target: string
877 fdf7f055 Guido Trotter
    @param target: ip address of the target node
878 fdf7f055 Guido Trotter
    @type live: boolean
879 fdf7f055 Guido Trotter
    @param live: perform a live migration
880 fdf7f055 Guido Trotter

881 6e7275c0 Iustin Pop
    """
882 d8784f7d Michael Hanselmann
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
883 d8784f7d Michael Hanselmann
884 d8784f7d Michael Hanselmann
    return self._MigrateInstance(cluster_name, instance.name, target, port,
885 8351df2f Helga Velroyen
                                 live, instance.hvparams)
886 d8784f7d Michael Hanselmann
887 d8784f7d Michael Hanselmann
  def _MigrateInstance(self, cluster_name, instance_name, target, port, live,
888 8351df2f Helga Velroyen
                       hvparams, _ping_fn=netutils.TcpPing):
889 d8784f7d Michael Hanselmann
    """Migrate an instance to a target node.
890 d8784f7d Michael Hanselmann

891 d8784f7d Michael Hanselmann
    @see: L{MigrateInstance} for details
892 d8784f7d Michael Hanselmann

893 d8784f7d Michael Hanselmann
    """
894 8351df2f Helga Velroyen
    if hvparams is None:
895 8351df2f Helga Velroyen
      raise errors.HypervisorError("No hvparams provided.")
896 8351df2f Helga Velroyen
897 8351df2f Helga Velroyen
    if self.GetInstanceInfo(instance_name, hvparams=hvparams) is None:
898 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Instance not running, cannot migrate")
899 50716be0 Iustin Pop
900 398fd4f6 Helga Velroyen
    cmd = self._GetCommand(hvparams)
901 50716be0 Iustin Pop
902 d8784f7d Michael Hanselmann
    if (cmd == constants.XEN_CMD_XM and
903 d8784f7d Michael Hanselmann
        not _ping_fn(target, port, live_port_needed=True)):
904 50716be0 Iustin Pop
      raise errors.HypervisorError("Remote host %s not listening on port"
905 50716be0 Iustin Pop
                                   " %s, cannot migrate" % (target, port))
906 50716be0 Iustin Pop
907 3d942d8b Michael Hanselmann
    args = ["migrate"]
908 3d942d8b Michael Hanselmann
909 d8784f7d Michael Hanselmann
    if cmd == constants.XEN_CMD_XM:
910 0625d08f René Nussbaumer
      args.extend(["-p", "%d" % port])
911 0625d08f René Nussbaumer
      if live:
912 0625d08f René Nussbaumer
        args.append("-l")
913 3d942d8b Michael Hanselmann
914 d8784f7d Michael Hanselmann
    elif cmd == constants.XEN_CMD_XL:
915 d8784f7d Michael Hanselmann
      args.extend([
916 d8784f7d Michael Hanselmann
        "-s", constants.XL_SSH_CMD % cluster_name,
917 d8784f7d Michael Hanselmann
        "-C", self._ConfigFileName(instance_name),
918 d8784f7d Michael Hanselmann
        ])
919 3d942d8b Michael Hanselmann
920 0625d08f René Nussbaumer
    else:
921 d8784f7d Michael Hanselmann
      raise errors.HypervisorError("Unsupported Xen command: %s" % self._cmd)
922 0625d08f René Nussbaumer
923 d8784f7d Michael Hanselmann
    args.extend([instance_name, target])
924 3d942d8b Michael Hanselmann
925 398fd4f6 Helga Velroyen
    result = self._RunXen(args, hvparams)
926 6e7275c0 Iustin Pop
    if result.failed:
927 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Failed to migrate instance %s: %s" %
928 d8784f7d Michael Hanselmann
                                   (instance_name, result.output))
929 60af751d Andrea Spadaccini
930 60af751d Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
931 60af751d Andrea Spadaccini
    """Finalize the instance migration on the source node.
932 60af751d Andrea Spadaccini

933 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
934 60af751d Andrea Spadaccini
    @param instance: the instance that was migrated
935 60af751d Andrea Spadaccini
    @type success: bool
936 60af751d Andrea Spadaccini
    @param success: whether the migration succeeded or not
937 60af751d Andrea Spadaccini
    @type live: bool
938 60af751d Andrea Spadaccini
    @param live: whether the user requested a live migration or not
939 60af751d Andrea Spadaccini

940 60af751d Andrea Spadaccini
    """
941 60af751d Andrea Spadaccini
    # pylint: disable=W0613
942 60af751d Andrea Spadaccini
    if success:
943 60af751d Andrea Spadaccini
      # remove old xen file after migration succeeded
944 60af751d Andrea Spadaccini
      try:
945 60af751d Andrea Spadaccini
        self._RemoveConfigFile(instance.name)
946 60af751d Andrea Spadaccini
      except EnvironmentError:
947 60af751d Andrea Spadaccini
        logging.exception("Failure while removing instance config file")
948 60af751d Andrea Spadaccini
949 60af751d Andrea Spadaccini
  def GetMigrationStatus(self, instance):
950 60af751d Andrea Spadaccini
    """Get the migration status
951 60af751d Andrea Spadaccini

952 60af751d Andrea Spadaccini
    As MigrateInstance for Xen is still blocking, if this method is called it
953 60af751d Andrea Spadaccini
    means that MigrateInstance has completed successfully. So we can safely
954 60af751d Andrea Spadaccini
    assume that the migration was successful and notify this fact to the client.
955 60af751d Andrea Spadaccini

956 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
957 60af751d Andrea Spadaccini
    @param instance: the instance that is being migrated
958 60af751d Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
959 60af751d Andrea Spadaccini
    @return: the status of the current migration (one of
960 60af751d Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
961 60af751d Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
962 60af751d Andrea Spadaccini

963 60af751d Andrea Spadaccini
    """
964 60af751d Andrea Spadaccini
    return objects.MigrationStatus(status=constants.HV_MIGRATION_COMPLETED)
965 6e7275c0 Iustin Pop
966 8ef418bb Helga Velroyen
  def PowercycleNode(self, hvparams=None):
967 f5118ade Iustin Pop
    """Xen-specific powercycle.
968 f5118ade Iustin Pop

969 f5118ade Iustin Pop
    This first does a Linux reboot (which triggers automatically a Xen
970 f5118ade Iustin Pop
    reboot), and if that fails it tries to do a Xen reboot. The reason
971 f5118ade Iustin Pop
    we don't try a Xen reboot first is that the xen reboot launches an
972 f5118ade Iustin Pop
    external command which connects to the Xen hypervisor, and that
973 f5118ade Iustin Pop
    won't work in case the root filesystem is broken and/or the xend
974 f5118ade Iustin Pop
    daemon is not working.
975 f5118ade Iustin Pop

976 8ef418bb Helga Velroyen
    @type hvparams: dict of strings
977 8ef418bb Helga Velroyen
    @param hvparams: hypervisor params to be used on this node
978 8ef418bb Helga Velroyen

979 f5118ade Iustin Pop
    """
980 f5118ade Iustin Pop
    try:
981 8ef418bb Helga Velroyen
      self.LinuxPowercycle()
982 f5118ade Iustin Pop
    finally:
983 8ef418bb Helga Velroyen
      xen_cmd = self._GetCommand(hvparams)
984 8ef418bb Helga Velroyen
      utils.RunCmd([xen_cmd, "debug", "R"])
985 f5118ade Iustin Pop
986 75bf3149 Helga Velroyen
  def _CheckToolstack(self, xen_cmd):
987 75bf3149 Helga Velroyen
    """Check whether the given toolstack is available on the node.
988 75bf3149 Helga Velroyen

989 75bf3149 Helga Velroyen
    @type xen_cmd: string
990 75bf3149 Helga Velroyen
    @param xen_cmd: xen command (e.g. 'xm' or 'xl')
991 75bf3149 Helga Velroyen

992 75bf3149 Helga Velroyen
    """
993 75bf3149 Helga Velroyen
    binary_found = self._CheckToolstackBinary(xen_cmd)
994 75bf3149 Helga Velroyen
    if not binary_found:
995 75bf3149 Helga Velroyen
      raise errors.HypervisorError("No '%s' binary found on node." % xen_cmd)
996 75bf3149 Helga Velroyen
    elif xen_cmd == constants.XEN_CMD_XL:
997 75bf3149 Helga Velroyen
      if not self._CheckToolstackXlConfigured():
998 75bf3149 Helga Velroyen
        raise errors.HypervisorError("Toolstack '%s' is not enabled on this"
999 75bf3149 Helga Velroyen
                                     "node." % xen_cmd)
1000 75bf3149 Helga Velroyen
1001 75bf3149 Helga Velroyen
  def _CheckToolstackBinary(self, xen_cmd):
1002 75bf3149 Helga Velroyen
    """Checks whether the xen command's binary is found on the machine.
1003 75bf3149 Helga Velroyen

1004 75bf3149 Helga Velroyen
    """
1005 75bf3149 Helga Velroyen
    if xen_cmd not in constants.KNOWN_XEN_COMMANDS:
1006 75bf3149 Helga Velroyen
      raise errors.HypervisorError("Unknown xen command '%s'." % xen_cmd)
1007 75bf3149 Helga Velroyen
    result = self._run_cmd_fn(["which", xen_cmd])
1008 75bf3149 Helga Velroyen
    return not result.failed
1009 75bf3149 Helga Velroyen
1010 75bf3149 Helga Velroyen
  def _CheckToolstackXlConfigured(self):
1011 75bf3149 Helga Velroyen
    """Checks whether xl is enabled on an xl-capable node.
1012 75bf3149 Helga Velroyen

1013 75bf3149 Helga Velroyen
    @rtype: bool
1014 75bf3149 Helga Velroyen
    @returns: C{True} if 'xl' is enabled, C{False} otherwise
1015 75bf3149 Helga Velroyen

1016 75bf3149 Helga Velroyen
    """
1017 75bf3149 Helga Velroyen
    result = self._run_cmd_fn([constants.XEN_CMD_XL, "help"])
1018 75bf3149 Helga Velroyen
    if not result.failed:
1019 75bf3149 Helga Velroyen
      return True
1020 75bf3149 Helga Velroyen
    elif result.failed:
1021 75bf3149 Helga Velroyen
      if "toolstack" in result.stderr:
1022 75bf3149 Helga Velroyen
        return False
1023 75bf3149 Helga Velroyen
      # xl fails for some other reason than the toolstack
1024 75bf3149 Helga Velroyen
      else:
1025 75bf3149 Helga Velroyen
        raise errors.HypervisorError("Cannot run xen ('%s'). Error: %s."
1026 75bf3149 Helga Velroyen
                                     % (constants.XEN_CMD_XL, result.stderr))
1027 75bf3149 Helga Velroyen
1028 65a6f9b7 Michael Hanselmann
1029 65a6f9b7 Michael Hanselmann
class XenPvmHypervisor(XenHypervisor):
1030 65a6f9b7 Michael Hanselmann
  """Xen PVM hypervisor interface"""
1031 65a6f9b7 Michael Hanselmann
1032 205ab586 Iustin Pop
  PARAMETERS = {
1033 2f2dbb4b Jun Futagawa
    constants.HV_USE_BOOTLOADER: hv_base.NO_CHECK,
1034 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_PATH: hv_base.OPT_FILE_CHECK,
1035 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_ARGS: hv_base.NO_CHECK,
1036 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.REQ_FILE_CHECK,
1037 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
1038 7adf7814 René Nussbaumer
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
1039 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
1040 e2d14329 Andrea Spadaccini
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
1041 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
1042 525011bc Maciej Bliziński
    # TODO: Add a check for the blockdev prefix (matching [a-z:] or similar).
1043 525011bc Maciej Bliziński
    constants.HV_BLOCKDEV_PREFIX: hv_base.NO_CHECK,
1044 990ade2d Stephen Shirley
    constants.HV_REBOOT_BEHAVIOR:
1045 c4708267 Tsachy Shacham
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
1046 c4708267 Tsachy Shacham
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
1047 2c368f28 Guido Trotter
    constants.HV_CPU_CAP: hv_base.OPT_NONNEGATIVE_INT_CHECK,
1048 8bd977e9 Sébastien Bocahu
    constants.HV_CPU_WEIGHT:
1049 8bd977e9 Sébastien Bocahu
      (False, lambda x: 0 < x < 65536, "invalid weight", None, None),
1050 397b7844 Dimitris Aragiorgis
    constants.HV_VIF_SCRIPT: hv_base.OPT_FILE_CHECK,
1051 740394bc Helga Velroyen
    constants.HV_XEN_CMD:
1052 740394bc Helga Velroyen
      hv_base.ParamInSet(True, constants.KNOWN_XEN_COMMANDS),
1053 295ed29b Santi Raffa
    constants.HV_XEN_CPUID: hv_base.NO_CHECK,
1054 b5cad580 Raffa Santi
    constants.HV_SOUNDHW: hv_base.NO_CHECK,
1055 205ab586 Iustin Pop
    }
1056 f48148c3 Iustin Pop
1057 c3d839f5 Michael Hanselmann
  def _GetConfig(self, instance, startup_memory, block_devices):
1058 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
1059 65a6f9b7 Michael Hanselmann

1060 65a6f9b7 Michael Hanselmann
    """
1061 a985b417 Iustin Pop
    hvp = instance.hvparams
1062 65a6f9b7 Michael Hanselmann
    config = StringIO()
1063 65a6f9b7 Michael Hanselmann
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
1064 65a6f9b7 Michael Hanselmann
1065 2f2dbb4b Jun Futagawa
    # if bootloader is True, use bootloader instead of kernel and ramdisk
1066 2f2dbb4b Jun Futagawa
    # parameters.
1067 2f2dbb4b Jun Futagawa
    if hvp[constants.HV_USE_BOOTLOADER]:
1068 2f2dbb4b Jun Futagawa
      # bootloader handling
1069 2f2dbb4b Jun Futagawa
      bootloader_path = hvp[constants.HV_BOOTLOADER_PATH]
1070 2f2dbb4b Jun Futagawa
      if bootloader_path:
1071 2f2dbb4b Jun Futagawa
        config.write("bootloader = '%s'\n" % bootloader_path)
1072 2f2dbb4b Jun Futagawa
      else:
1073 2f2dbb4b Jun Futagawa
        raise errors.HypervisorError("Bootloader enabled, but missing"
1074 2f2dbb4b Jun Futagawa
                                     " bootloader path")
1075 65a6f9b7 Michael Hanselmann
1076 2f2dbb4b Jun Futagawa
      bootloader_args = hvp[constants.HV_BOOTLOADER_ARGS]
1077 2f2dbb4b Jun Futagawa
      if bootloader_args:
1078 2f2dbb4b Jun Futagawa
        config.write("bootargs = '%s'\n" % bootloader_args)
1079 2f2dbb4b Jun Futagawa
    else:
1080 2f2dbb4b Jun Futagawa
      # kernel handling
1081 2f2dbb4b Jun Futagawa
      kpath = hvp[constants.HV_KERNEL_PATH]
1082 2f2dbb4b Jun Futagawa
      config.write("kernel = '%s'\n" % kpath)
1083 2f2dbb4b Jun Futagawa
1084 2f2dbb4b Jun Futagawa
      # initrd handling
1085 2f2dbb4b Jun Futagawa
      initrd_path = hvp[constants.HV_INITRD_PATH]
1086 2f2dbb4b Jun Futagawa
      if initrd_path:
1087 2f2dbb4b Jun Futagawa
        config.write("ramdisk = '%s'\n" % initrd_path)
1088 65a6f9b7 Michael Hanselmann
1089 65a6f9b7 Michael Hanselmann
    # rest of the settings
1090 61eb1a46 Guido Trotter
    config.write("memory = %d\n" % startup_memory)
1091 80121c83 Guido Trotter
    config.write("maxmem = %d\n" % instance.beparams[constants.BE_MAXMEM])
1092 8b3fd458 Iustin Pop
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
1093 347fa0f1 Michael Hanselmann
    cpu_pinning = _CreateConfigCpus(hvp[constants.HV_CPU_MASK])
1094 c4708267 Tsachy Shacham
    if cpu_pinning:
1095 c4708267 Tsachy Shacham
      config.write("%s\n" % cpu_pinning)
1096 8bd977e9 Sébastien Bocahu
    cpu_cap = hvp[constants.HV_CPU_CAP]
1097 8bd977e9 Sébastien Bocahu
    if cpu_cap:
1098 8bd977e9 Sébastien Bocahu
      config.write("cpu_cap=%d\n" % cpu_cap)
1099 8bd977e9 Sébastien Bocahu
    cpu_weight = hvp[constants.HV_CPU_WEIGHT]
1100 8bd977e9 Sébastien Bocahu
    if cpu_weight:
1101 8bd977e9 Sébastien Bocahu
      config.write("cpu_weight=%d\n" % cpu_weight)
1102 c4708267 Tsachy Shacham
1103 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
1104 65a6f9b7 Michael Hanselmann
1105 65a6f9b7 Michael Hanselmann
    vif_data = []
1106 397b7844 Dimitris Aragiorgis
    for idx, nic in enumerate(instance.nics):
1107 503b97a9 Guido Trotter
      nic_str = "mac=%s" % (nic.mac)
1108 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
1109 65a6f9b7 Michael Hanselmann
      if ip is not None:
1110 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
1111 503b97a9 Guido Trotter
      if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1112 503b97a9 Guido Trotter
        nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK]
1113 f1f11cef Sebastian Gebhard
      if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_OVS:
1114 f1f11cef Sebastian Gebhard
        nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK]
1115 f1f11cef Sebastian Gebhard
        if nic.nicparams[constants.NIC_VLAN]:
1116 f1f11cef Sebastian Gebhard
          nic_str += "%s" % nic.nicparams[constants.NIC_VLAN]
1117 397b7844 Dimitris Aragiorgis
      if hvp[constants.HV_VIF_SCRIPT]:
1118 397b7844 Dimitris Aragiorgis
        nic_str += ", script=%s" % hvp[constants.HV_VIF_SCRIPT]
1119 0183a697 Alessandro Cincaglini
      vif_data.append("'%s'" % nic_str)
1120 2a3bbbaa Dimitris Aragiorgis
      self._WriteNICInfoFile(instance, idx, nic)
1121 65a6f9b7 Michael Hanselmann
1122 d0bb3f24 Michael Hanselmann
    disk_data = \
1123 d0bb3f24 Michael Hanselmann
      _GetConfigFileDiskData(block_devices, hvp[constants.HV_BLOCKDEV_PREFIX])
1124 7ed85ffe Iustin Pop
1125 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
1126 7ed85ffe Iustin Pop
    config.write("disk = [%s]\n" % ",".join(disk_data))
1127 074ca009 Guido Trotter
1128 7adf7814 René Nussbaumer
    if hvp[constants.HV_ROOT_PATH]:
1129 7adf7814 René Nussbaumer
      config.write("root = '%s'\n" % hvp[constants.HV_ROOT_PATH])
1130 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
1131 990ade2d Stephen Shirley
    if hvp[constants.HV_REBOOT_BEHAVIOR] == constants.INSTANCE_REBOOT_ALLOWED:
1132 990ade2d Stephen Shirley
      config.write("on_reboot = 'restart'\n")
1133 990ade2d Stephen Shirley
    else:
1134 990ade2d Stephen Shirley
      config.write("on_reboot = 'destroy'\n")
1135 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
1136 07813a9e Iustin Pop
    config.write("extra = '%s'\n" % hvp[constants.HV_KERNEL_ARGS])
1137 73cd67f4 Guido Trotter
1138 295ed29b Santi Raffa
    cpuid = hvp[constants.HV_XEN_CPUID]
1139 295ed29b Santi Raffa
    if cpuid:
1140 295ed29b Santi Raffa
      config.write("cpuid = %s\n" % _QuoteCpuidField(cpuid))
1141 295ed29b Santi Raffa
1142 b5cad580 Raffa Santi
    if hvp[constants.HV_SOUNDHW]:
1143 b5cad580 Raffa Santi
      config.write("soundhw = '%s'\n" % hvp[constants.HV_SOUNDHW])
1144 b5cad580 Raffa Santi
1145 c3d839f5 Michael Hanselmann
    return config.getvalue()
1146 65a6f9b7 Michael Hanselmann
1147 65a6f9b7 Michael Hanselmann
1148 65a6f9b7 Michael Hanselmann
class XenHvmHypervisor(XenHypervisor):
1149 65a6f9b7 Michael Hanselmann
  """Xen HVM hypervisor interface"""
1150 65a6f9b7 Michael Hanselmann
1151 69b99987 Michael Hanselmann
  ANCILLARY_FILES = XenHypervisor.ANCILLARY_FILES + [
1152 9d9bded1 Michael Hanselmann
    pathutils.VNC_PASSWORD_FILE,
1153 69b99987 Michael Hanselmann
    ]
1154 69ab2e12 Guido Trotter
  ANCILLARY_FILES_OPT = XenHypervisor.ANCILLARY_FILES_OPT + [
1155 9d9bded1 Michael Hanselmann
    pathutils.VNC_PASSWORD_FILE,
1156 69ab2e12 Guido Trotter
    ]
1157 3680f662 Guido Trotter
1158 205ab586 Iustin Pop
  PARAMETERS = {
1159 205ab586 Iustin Pop
    constants.HV_ACPI: hv_base.NO_CHECK,
1160 016d04b3 Michael Hanselmann
    constants.HV_BOOT_ORDER: (True, ) +
1161 016d04b3 Michael Hanselmann
      (lambda x: x and len(x.strip("acdn")) == 0,
1162 016d04b3 Michael Hanselmann
       "Invalid boot order specified, must be one or more of [acdn]",
1163 016d04b3 Michael Hanselmann
       None, None),
1164 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
1165 016d04b3 Michael Hanselmann
    constants.HV_DISK_TYPE:
1166 016d04b3 Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_HVM_VALID_DISK_TYPES),
1167 016d04b3 Michael Hanselmann
    constants.HV_NIC_TYPE:
1168 016d04b3 Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_HVM_VALID_NIC_TYPES),
1169 205ab586 Iustin Pop
    constants.HV_PAE: hv_base.NO_CHECK,
1170 016d04b3 Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS:
1171 8b312c1d Manuel Franceschini
      (False, netutils.IP4Address.IsValid,
1172 016d04b3 Michael Hanselmann
       "VNC bind address is not a valid IP address", None, None),
1173 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.REQ_FILE_CHECK,
1174 205ab586 Iustin Pop
    constants.HV_DEVICE_MODEL: hv_base.REQ_FILE_CHECK,
1175 6e6bb8d5 Guido Trotter
    constants.HV_VNC_PASSWORD_FILE: hv_base.REQ_FILE_CHECK,
1176 e2d14329 Andrea Spadaccini
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
1177 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
1178 6b970cef Jun Futagawa
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
1179 e695efbf Iustin Pop
    # TODO: Add a check for the blockdev prefix (matching [a-z:] or similar).
1180 e695efbf Iustin Pop
    constants.HV_BLOCKDEV_PREFIX: hv_base.NO_CHECK,
1181 87f0aa48 Jack
    # Add PCI passthrough
1182 3891c95e Bernardo Dal Seno
    constants.HV_PASSTHROUGH: hv_base.NO_CHECK,
1183 990ade2d Stephen Shirley
    constants.HV_REBOOT_BEHAVIOR:
1184 c4708267 Tsachy Shacham
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
1185 c4708267 Tsachy Shacham
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
1186 8bd977e9 Sébastien Bocahu
    constants.HV_CPU_CAP: hv_base.NO_CHECK,
1187 8bd977e9 Sébastien Bocahu
    constants.HV_CPU_WEIGHT:
1188 8bd977e9 Sébastien Bocahu
      (False, lambda x: 0 < x < 65535, "invalid weight", None, None),
1189 05440845 Helga Velroyen
    constants.HV_VIF_TYPE:
1190 05440845 Helga Velroyen
      hv_base.ParamInSet(False, constants.HT_HVM_VALID_VIF_TYPES),
1191 397b7844 Dimitris Aragiorgis
    constants.HV_VIF_SCRIPT: hv_base.OPT_FILE_CHECK,
1192 ffc27116 Thomas Thrainer
    constants.HV_VIRIDIAN: hv_base.NO_CHECK,
1193 740394bc Helga Velroyen
    constants.HV_XEN_CMD:
1194 740394bc Helga Velroyen
      hv_base.ParamInSet(True, constants.KNOWN_XEN_COMMANDS),
1195 295ed29b Santi Raffa
    constants.HV_XEN_CPUID: hv_base.NO_CHECK,
1196 b5cad580 Raffa Santi
    constants.HV_SOUNDHW: hv_base.NO_CHECK,
1197 205ab586 Iustin Pop
    }
1198 09ea8710 Iustin Pop
1199 c3d839f5 Michael Hanselmann
  def _GetConfig(self, instance, startup_memory, block_devices):
1200 65a6f9b7 Michael Hanselmann
    """Create a Xen 3.1 HVM config file.
1201 65a6f9b7 Michael Hanselmann

1202 65a6f9b7 Michael Hanselmann
    """
1203 a985b417 Iustin Pop
    hvp = instance.hvparams
1204 a985b417 Iustin Pop
1205 65a6f9b7 Michael Hanselmann
    config = StringIO()
1206 e2ee1cea Iustin Pop
1207 e2ee1cea Iustin Pop
    # kernel handling
1208 e2ee1cea Iustin Pop
    kpath = hvp[constants.HV_KERNEL_PATH]
1209 e2ee1cea Iustin Pop
    config.write("kernel = '%s'\n" % kpath)
1210 e2ee1cea Iustin Pop
1211 65a6f9b7 Michael Hanselmann
    config.write("builder = 'hvm'\n")
1212 61eb1a46 Guido Trotter
    config.write("memory = %d\n" % startup_memory)
1213 80121c83 Guido Trotter
    config.write("maxmem = %d\n" % instance.beparams[constants.BE_MAXMEM])
1214 8b3fd458 Iustin Pop
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
1215 347fa0f1 Michael Hanselmann
    cpu_pinning = _CreateConfigCpus(hvp[constants.HV_CPU_MASK])
1216 c4708267 Tsachy Shacham
    if cpu_pinning:
1217 c4708267 Tsachy Shacham
      config.write("%s\n" % cpu_pinning)
1218 8bd977e9 Sébastien Bocahu
    cpu_cap = hvp[constants.HV_CPU_CAP]
1219 8bd977e9 Sébastien Bocahu
    if cpu_cap:
1220 8bd977e9 Sébastien Bocahu
      config.write("cpu_cap=%d\n" % cpu_cap)
1221 8bd977e9 Sébastien Bocahu
    cpu_weight = hvp[constants.HV_CPU_WEIGHT]
1222 8bd977e9 Sébastien Bocahu
    if cpu_weight:
1223 8bd977e9 Sébastien Bocahu
      config.write("cpu_weight=%d\n" % cpu_weight)
1224 c4708267 Tsachy Shacham
1225 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
1226 09ea8710 Iustin Pop
    if hvp[constants.HV_PAE]:
1227 a21dda8b Iustin Pop
      config.write("pae = 1\n")
1228 a21dda8b Iustin Pop
    else:
1229 a21dda8b Iustin Pop
      config.write("pae = 0\n")
1230 09ea8710 Iustin Pop
    if hvp[constants.HV_ACPI]:
1231 a21dda8b Iustin Pop
      config.write("acpi = 1\n")
1232 a21dda8b Iustin Pop
    else:
1233 a21dda8b Iustin Pop
      config.write("acpi = 0\n")
1234 ffc27116 Thomas Thrainer
    if hvp[constants.HV_VIRIDIAN]:
1235 ffc27116 Thomas Thrainer
      config.write("viridian = 1\n")
1236 ffc27116 Thomas Thrainer
    else:
1237 ffc27116 Thomas Thrainer
      config.write("viridian = 0\n")
1238 ffc27116 Thomas Thrainer
1239 65a6f9b7 Michael Hanselmann
    config.write("apic = 1\n")
1240 09ea8710 Iustin Pop
    config.write("device_model = '%s'\n" % hvp[constants.HV_DEVICE_MODEL])
1241 a985b417 Iustin Pop
    config.write("boot = '%s'\n" % hvp[constants.HV_BOOT_ORDER])
1242 65a6f9b7 Michael Hanselmann
    config.write("sdl = 0\n")
1243 97efde45 Guido Trotter
    config.write("usb = 1\n")
1244 97efde45 Guido Trotter
    config.write("usbdevice = 'tablet'\n")
1245 65a6f9b7 Michael Hanselmann
    config.write("vnc = 1\n")
1246 a985b417 Iustin Pop
    if hvp[constants.HV_VNC_BIND_ADDRESS] is None:
1247 d0c11cf7 Alexander Schreiber
      config.write("vnclisten = '%s'\n" % constants.VNC_DEFAULT_BIND_ADDRESS)
1248 d0c11cf7 Alexander Schreiber
    else:
1249 6b405598 Guido Trotter
      config.write("vnclisten = '%s'\n" % hvp[constants.HV_VNC_BIND_ADDRESS])
1250 65a6f9b7 Michael Hanselmann
1251 377d74c9 Guido Trotter
    if instance.network_port > constants.VNC_BASE_PORT:
1252 377d74c9 Guido Trotter
      display = instance.network_port - constants.VNC_BASE_PORT
1253 65a6f9b7 Michael Hanselmann
      config.write("vncdisplay = %s\n" % display)
1254 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 0\n")
1255 65a6f9b7 Michael Hanselmann
    else:
1256 65a6f9b7 Michael Hanselmann
      config.write("# vncdisplay = 1\n")
1257 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 1\n")
1258 65a6f9b7 Michael Hanselmann
1259 6e6bb8d5 Guido Trotter
    vnc_pwd_file = hvp[constants.HV_VNC_PASSWORD_FILE]
1260 65a6f9b7 Michael Hanselmann
    try:
1261 6e6bb8d5 Guido Trotter
      password = utils.ReadFile(vnc_pwd_file)
1262 78f66a17 Guido Trotter
    except EnvironmentError, err:
1263 78f66a17 Guido Trotter
      raise errors.HypervisorError("Failed to open VNC password file %s: %s" %
1264 6e6bb8d5 Guido Trotter
                                   (vnc_pwd_file, err))
1265 65a6f9b7 Michael Hanselmann
1266 65a6f9b7 Michael Hanselmann
    config.write("vncpasswd = '%s'\n" % password.rstrip())
1267 65a6f9b7 Michael Hanselmann
1268 65a6f9b7 Michael Hanselmann
    config.write("serial = 'pty'\n")
1269 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
1270 6b970cef Jun Futagawa
      config.write("localtime = 1\n")
1271 65a6f9b7 Michael Hanselmann
1272 65a6f9b7 Michael Hanselmann
    vif_data = []
1273 05440845 Helga Velroyen
    # Note: what is called 'nic_type' here, is used as value for the xen nic
1274 05440845 Helga Velroyen
    # vif config parameter 'model'. For the xen nic vif parameter 'type', we use
1275 05440845 Helga Velroyen
    # the 'vif_type' to avoid a clash of notation.
1276 a985b417 Iustin Pop
    nic_type = hvp[constants.HV_NIC_TYPE]
1277 05440845 Helga Velroyen
1278 f48148c3 Iustin Pop
    if nic_type is None:
1279 05440845 Helga Velroyen
      vif_type_str = ""
1280 05440845 Helga Velroyen
      if hvp[constants.HV_VIF_TYPE]:
1281 05440845 Helga Velroyen
        vif_type_str = ", type=%s" % hvp[constants.HV_VIF_TYPE]
1282 f48148c3 Iustin Pop
      # ensure old instances don't change
1283 05440845 Helga Velroyen
      nic_type_str = vif_type_str
1284 d08f6067 Guido Trotter
    elif nic_type == constants.HT_NIC_PARAVIRTUAL:
1285 f48148c3 Iustin Pop
      nic_type_str = ", type=paravirtualized"
1286 f48148c3 Iustin Pop
    else:
1287 05440845 Helga Velroyen
      # parameter 'model' is only valid with type 'ioemu'
1288 05440845 Helga Velroyen
      nic_type_str = ", model=%s, type=%s" % \
1289 05440845 Helga Velroyen
        (nic_type, constants.HT_HVM_VIF_IOEMU)
1290 397b7844 Dimitris Aragiorgis
    for idx, nic in enumerate(instance.nics):
1291 503b97a9 Guido Trotter
      nic_str = "mac=%s%s" % (nic.mac, nic_type_str)
1292 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
1293 65a6f9b7 Michael Hanselmann
      if ip is not None:
1294 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
1295 503b97a9 Guido Trotter
      if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1296 503b97a9 Guido Trotter
        nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK]
1297 397b7844 Dimitris Aragiorgis
      if hvp[constants.HV_VIF_SCRIPT]:
1298 397b7844 Dimitris Aragiorgis
        nic_str += ", script=%s" % hvp[constants.HV_VIF_SCRIPT]
1299 0183a697 Alessandro Cincaglini
      vif_data.append("'%s'" % nic_str)
1300 2a3bbbaa Dimitris Aragiorgis
      self._WriteNICInfoFile(instance, idx, nic)
1301 65a6f9b7 Michael Hanselmann
1302 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
1303 525011bc Maciej Bliziński
1304 d0bb3f24 Michael Hanselmann
    disk_data = \
1305 d0bb3f24 Michael Hanselmann
      _GetConfigFileDiskData(block_devices, hvp[constants.HV_BLOCKDEV_PREFIX])
1306 525011bc Maciej Bliziński
1307 a985b417 Iustin Pop
    iso_path = hvp[constants.HV_CDROM_IMAGE_PATH]
1308 f48148c3 Iustin Pop
    if iso_path:
1309 f48148c3 Iustin Pop
      iso = "'file:%s,hdc:cdrom,r'" % iso_path
1310 a21dda8b Iustin Pop
      disk_data.append(iso)
1311 a21dda8b Iustin Pop
1312 a21dda8b Iustin Pop
    config.write("disk = [%s]\n" % (",".join(disk_data)))
1313 87f0aa48 Jack
    # Add PCI passthrough
1314 87f0aa48 Jack
    pci_pass_arr = []
1315 87f0aa48 Jack
    pci_pass = hvp[constants.HV_PASSTHROUGH]
1316 87f0aa48 Jack
    if pci_pass:
1317 3891c95e Bernardo Dal Seno
      pci_pass_arr = pci_pass.split(";")
1318 3891c95e Bernardo Dal Seno
      config.write("pci = %s\n" % pci_pass_arr)
1319 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
1320 990ade2d Stephen Shirley
    if hvp[constants.HV_REBOOT_BEHAVIOR] == constants.INSTANCE_REBOOT_ALLOWED:
1321 990ade2d Stephen Shirley
      config.write("on_reboot = 'restart'\n")
1322 990ade2d Stephen Shirley
    else:
1323 990ade2d Stephen Shirley
      config.write("on_reboot = 'destroy'\n")
1324 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
1325 73cd67f4 Guido Trotter
1326 295ed29b Santi Raffa
    cpuid = hvp[constants.HV_XEN_CPUID]
1327 295ed29b Santi Raffa
    if cpuid:
1328 295ed29b Santi Raffa
      config.write("cpuid = %s\n" % _QuoteCpuidField(cpuid))
1329 295ed29b Santi Raffa
1330 b5cad580 Raffa Santi
    if hvp[constants.HV_SOUNDHW]:
1331 b5cad580 Raffa Santi
      config.write("soundhw = '%s'\n" % hvp[constants.HV_SOUNDHW])
1332 b5cad580 Raffa Santi
1333 c3d839f5 Michael Hanselmann
    return config.getvalue()