Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ 30b12688

History | View | Annotate | Download (41.9 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 d0bb3f24 Michael Hanselmann
  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 d0bb3f24 Michael Hanselmann
      driver = _FILE_DRIVER_MAP[cfdev.physical_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 a2d32034 Michael Hanselmann
class XenHypervisor(hv_base.BaseHypervisor):
319 65a6f9b7 Michael Hanselmann
  """Xen generic hypervisor interface
320 65a6f9b7 Michael Hanselmann

321 65a6f9b7 Michael Hanselmann
  This is the Xen base class used for both Xen PVM and HVM. It contains
322 65a6f9b7 Michael Hanselmann
  all the functionality that is identical for both.
323 65a6f9b7 Michael Hanselmann

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

360 f92d9674 Helga Velroyen
    @type hvparams: dict of strings
361 f92d9674 Helga Velroyen
    @param hvparams: hypervisor parameters
362 f92d9674 Helga Velroyen

363 f92d9674 Helga Velroyen
    """
364 f92d9674 Helga Velroyen
    if hvparams is None or constants.HV_XEN_CMD not in hvparams:
365 f92d9674 Helga Velroyen
      raise errors.HypervisorError("Cannot determine xen command.")
366 f92d9674 Helga Velroyen
    else:
367 f92d9674 Helga Velroyen
      return hvparams[constants.HV_XEN_CMD]
368 f92d9674 Helga Velroyen
369 398fd4f6 Helga Velroyen
  def _GetCommand(self, hvparams):
370 d8784f7d Michael Hanselmann
    """Returns Xen command to use.
371 d8784f7d Michael Hanselmann

372 51a95d00 Helga Velroyen
    @type hvparams: dict of strings
373 51a95d00 Helga Velroyen
    @param hvparams: hypervisor parameters
374 51a95d00 Helga Velroyen

375 d8784f7d Michael Hanselmann
    """
376 3d942d8b Michael Hanselmann
    if self._cmd is None:
377 f92d9674 Helga Velroyen
      cmd = XenHypervisor._GetCommandFromHvparams(hvparams)
378 3d942d8b Michael Hanselmann
    else:
379 3d942d8b Michael Hanselmann
      cmd = self._cmd
380 3d942d8b Michael Hanselmann
381 3d942d8b Michael Hanselmann
    if cmd not in constants.KNOWN_XEN_COMMANDS:
382 3d942d8b Michael Hanselmann
      raise errors.ProgrammerError("Unknown Xen command '%s'" % cmd)
383 3d942d8b Michael Hanselmann
384 3d942d8b Michael Hanselmann
    return cmd
385 3d942d8b Michael Hanselmann
386 398fd4f6 Helga Velroyen
  def _RunXen(self, args, hvparams):
387 81124130 Michael Hanselmann
    """Wrapper around L{utils.process.RunCmd} to run Xen command.
388 3d942d8b Michael Hanselmann

389 58e356a9 Helga Velroyen
    @type hvparams: dict of strings
390 58e356a9 Helga Velroyen
    @param hvparams: dictionary of hypervisor params
391 81124130 Michael Hanselmann
    @see: L{utils.process.RunCmd}
392 3d942d8b Michael Hanselmann

393 3d942d8b Michael Hanselmann
    """
394 398fd4f6 Helga Velroyen
    cmd = [self._GetCommand(hvparams)]
395 3d942d8b Michael Hanselmann
    cmd.extend(args)
396 3d942d8b Michael Hanselmann
397 3d942d8b Michael Hanselmann
    return self._run_cmd_fn(cmd)
398 3d942d8b Michael Hanselmann
399 0a903309 Michael Hanselmann
  def _ConfigFileName(self, instance_name):
400 c2be2532 Guido Trotter
    """Get the config file name for an instance.
401 c2be2532 Guido Trotter

402 c2be2532 Guido Trotter
    @param instance_name: instance name
403 c2be2532 Guido Trotter
    @type instance_name: str
404 c2be2532 Guido Trotter
    @return: fully qualified path to instance config file
405 c2be2532 Guido Trotter
    @rtype: str
406 c2be2532 Guido Trotter

407 c2be2532 Guido Trotter
    """
408 0a903309 Michael Hanselmann
    return utils.PathJoin(self._cfgdir, instance_name)
409 c2be2532 Guido Trotter
410 5661b908 Iustin Pop
  @classmethod
411 397b7844 Dimitris Aragiorgis
  def _WriteNICInfoFile(cls, instance_name, idx, nic):
412 397b7844 Dimitris Aragiorgis
    """Write the Xen config file for the instance.
413 397b7844 Dimitris Aragiorgis

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

416 397b7844 Dimitris Aragiorgis
    """
417 397b7844 Dimitris Aragiorgis
    dirs = [(dname, constants.RUN_DIRS_MODE)
418 397b7844 Dimitris Aragiorgis
            for dname in cls._DIRS + [cls._InstanceNICDir(instance_name)]]
419 397b7844 Dimitris Aragiorgis
    utils.EnsureDirs(dirs)
420 397b7844 Dimitris Aragiorgis
421 397b7844 Dimitris Aragiorgis
    cfg_file = cls._InstanceNICFile(instance_name, idx)
422 397b7844 Dimitris Aragiorgis
    data = StringIO()
423 397b7844 Dimitris Aragiorgis
424 397b7844 Dimitris Aragiorgis
    if nic.netinfo:
425 397b7844 Dimitris Aragiorgis
      netinfo = objects.Network.FromDict(nic.netinfo)
426 397b7844 Dimitris Aragiorgis
      data.write("NETWORK_NAME=%s\n" % netinfo.name)
427 397b7844 Dimitris Aragiorgis
      if netinfo.network:
428 397b7844 Dimitris Aragiorgis
        data.write("NETWORK_SUBNET=%s\n" % netinfo.network)
429 397b7844 Dimitris Aragiorgis
      if netinfo.gateway:
430 397b7844 Dimitris Aragiorgis
        data.write("NETWORK_GATEWAY=%s\n" % netinfo.gateway)
431 397b7844 Dimitris Aragiorgis
      if netinfo.network6:
432 397b7844 Dimitris Aragiorgis
        data.write("NETWORK_SUBNET6=%s\n" % netinfo.network6)
433 397b7844 Dimitris Aragiorgis
      if netinfo.gateway6:
434 397b7844 Dimitris Aragiorgis
        data.write("NETWORK_GATEWAY6=%s\n" % netinfo.gateway6)
435 397b7844 Dimitris Aragiorgis
      if netinfo.mac_prefix:
436 397b7844 Dimitris Aragiorgis
        data.write("NETWORK_MAC_PREFIX=%s\n" % netinfo.mac_prefix)
437 397b7844 Dimitris Aragiorgis
      if netinfo.tags:
438 78f99abb Michele Tartara
        data.write("NETWORK_TAGS=%s\n" % r"\ ".join(netinfo.tags))
439 397b7844 Dimitris Aragiorgis
440 397b7844 Dimitris Aragiorgis
    data.write("MAC=%s\n" % nic.mac)
441 397b7844 Dimitris Aragiorgis
    data.write("IP=%s\n" % nic.ip)
442 397b7844 Dimitris Aragiorgis
    data.write("MODE=%s\n" % nic.nicparams[constants.NIC_MODE])
443 397b7844 Dimitris Aragiorgis
    data.write("LINK=%s\n" % nic.nicparams[constants.NIC_LINK])
444 397b7844 Dimitris Aragiorgis
445 397b7844 Dimitris Aragiorgis
    try:
446 397b7844 Dimitris Aragiorgis
      utils.WriteFile(cfg_file, data=data.getvalue())
447 397b7844 Dimitris Aragiorgis
    except EnvironmentError, err:
448 397b7844 Dimitris Aragiorgis
      raise errors.HypervisorError("Cannot write Xen instance configuration"
449 397b7844 Dimitris Aragiorgis
                                   " file %s: %s" % (cfg_file, err))
450 397b7844 Dimitris Aragiorgis
451 397b7844 Dimitris Aragiorgis
  @classmethod
452 397b7844 Dimitris Aragiorgis
  def _InstanceNICDir(cls, instance_name):
453 397b7844 Dimitris Aragiorgis
    """Returns the directory holding the tap device files for a given instance.
454 397b7844 Dimitris Aragiorgis

455 397b7844 Dimitris Aragiorgis
    """
456 397b7844 Dimitris Aragiorgis
    return utils.PathJoin(cls._NICS_DIR, instance_name)
457 397b7844 Dimitris Aragiorgis
458 397b7844 Dimitris Aragiorgis
  @classmethod
459 397b7844 Dimitris Aragiorgis
  def _InstanceNICFile(cls, instance_name, seq):
460 397b7844 Dimitris Aragiorgis
    """Returns the name of the file containing the tap device for a given NIC
461 397b7844 Dimitris Aragiorgis

462 397b7844 Dimitris Aragiorgis
    """
463 397b7844 Dimitris Aragiorgis
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
464 397b7844 Dimitris Aragiorgis
465 397b7844 Dimitris Aragiorgis
  @classmethod
466 c3d839f5 Michael Hanselmann
  def _GetConfig(cls, instance, startup_memory, block_devices):
467 c3d839f5 Michael Hanselmann
    """Build Xen configuration for an instance.
468 65a6f9b7 Michael Hanselmann

469 65a6f9b7 Michael Hanselmann
    """
470 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
471 65a6f9b7 Michael Hanselmann
472 c3d839f5 Michael Hanselmann
  def _WriteConfigFile(self, instance_name, data):
473 4390ccff Guido Trotter
    """Write the Xen config file for the instance.
474 4390ccff Guido Trotter

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

477 4390ccff Guido Trotter
    """
478 1a63f285 Iustin Pop
    # just in case it exists
479 0a903309 Michael Hanselmann
    utils.RemoveFile(utils.PathJoin(self._cfgdir, "auto", instance_name))
480 a8e8c0c6 Michael Hanselmann
481 0a903309 Michael Hanselmann
    cfg_file = self._ConfigFileName(instance_name)
482 1a63f285 Iustin Pop
    try:
483 1a63f285 Iustin Pop
      utils.WriteFile(cfg_file, data=data)
484 1a63f285 Iustin Pop
    except EnvironmentError, err:
485 1a63f285 Iustin Pop
      raise errors.HypervisorError("Cannot write Xen instance configuration"
486 1a63f285 Iustin Pop
                                   " file %s: %s" % (cfg_file, err))
487 4390ccff Guido Trotter
488 0a903309 Michael Hanselmann
  def _ReadConfigFile(self, instance_name):
489 4390ccff Guido Trotter
    """Returns the contents of the instance config file.
490 4390ccff Guido Trotter

491 4390ccff Guido Trotter
    """
492 0a903309 Michael Hanselmann
    filename = self._ConfigFileName(instance_name)
493 76c364d9 Michael Hanselmann
494 4390ccff Guido Trotter
    try:
495 76c364d9 Michael Hanselmann
      file_content = utils.ReadFile(filename)
496 4390ccff Guido Trotter
    except EnvironmentError, err:
497 4390ccff Guido Trotter
      raise errors.HypervisorError("Failed to load Xen config file: %s" % err)
498 76c364d9 Michael Hanselmann
499 4390ccff Guido Trotter
    return file_content
500 4390ccff Guido Trotter
501 0a903309 Michael Hanselmann
  def _RemoveConfigFile(self, instance_name):
502 65a6f9b7 Michael Hanselmann
    """Remove the xen configuration file.
503 65a6f9b7 Michael Hanselmann

504 65a6f9b7 Michael Hanselmann
    """
505 0a903309 Michael Hanselmann
    utils.RemoveFile(self._ConfigFileName(instance_name))
506 397b7844 Dimitris Aragiorgis
    try:
507 397b7844 Dimitris Aragiorgis
      shutil.rmtree(self._InstanceNICDir(instance_name))
508 397b7844 Dimitris Aragiorgis
    except OSError, err:
509 397b7844 Dimitris Aragiorgis
      if err.errno != errno.ENOENT:
510 397b7844 Dimitris Aragiorgis
        raise
511 65a6f9b7 Michael Hanselmann
512 48bba9de Balazs Lecz
  def _StashConfigFile(self, instance_name):
513 48bba9de Balazs Lecz
    """Move the Xen config file to the log directory and return its new path.
514 48bba9de Balazs Lecz

515 48bba9de Balazs Lecz
    """
516 48bba9de Balazs Lecz
    old_filename = self._ConfigFileName(instance_name)
517 48bba9de Balazs Lecz
    base = ("%s-%s" %
518 48bba9de Balazs Lecz
            (instance_name, utils.TimestampForFilename()))
519 48bba9de Balazs Lecz
    new_filename = utils.PathJoin(pathutils.LOG_XEN_DIR, base)
520 48bba9de Balazs Lecz
    utils.RenameFile(old_filename, new_filename)
521 48bba9de Balazs Lecz
    return new_filename
522 48bba9de Balazs Lecz
523 398fd4f6 Helga Velroyen
  def _GetInstanceList(self, include_node, hvparams):
524 36bebc53 Helga Velroyen
    """Wrapper around module level L{_GetInstanceList}.
525 06b78e8b Michael Hanselmann

526 398fd4f6 Helga Velroyen
    @type hvparams: dict of strings
527 398fd4f6 Helga Velroyen
    @param hvparams: hypervisor parameters to be used on this node
528 398fd4f6 Helga Velroyen

529 06b78e8b Michael Hanselmann
    """
530 398fd4f6 Helga Velroyen
    return _GetInstanceList(lambda: self._RunXen(["list"], hvparams),
531 58e356a9 Helga Velroyen
                            include_node)
532 65a6f9b7 Michael Hanselmann
533 58e356a9 Helga Velroyen
  def ListInstances(self, hvparams=None):
534 65a6f9b7 Michael Hanselmann
    """Get the list of running instances.
535 65a6f9b7 Michael Hanselmann

536 65a6f9b7 Michael Hanselmann
    """
537 398fd4f6 Helga Velroyen
    instance_list = self._GetInstanceList(False, hvparams)
538 36bebc53 Helga Velroyen
    names = [info[0] for info in instance_list]
539 65a6f9b7 Michael Hanselmann
    return names
540 65a6f9b7 Michael Hanselmann
541 0bbec3af Helga Velroyen
  def GetInstanceInfo(self, instance_name, hvparams=None):
542 65a6f9b7 Michael Hanselmann
    """Get instance properties.
543 65a6f9b7 Michael Hanselmann

544 0bbec3af Helga Velroyen
    @type instance_name: string
545 c41eea6e Iustin Pop
    @param instance_name: the instance name
546 0bbec3af Helga Velroyen
    @type hvparams: dict of strings
547 0bbec3af Helga Velroyen
    @param hvparams: the instance's hypervisor params
548 c41eea6e Iustin Pop

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

551 65a6f9b7 Michael Hanselmann
    """
552 398fd4f6 Helga Velroyen
    instance_list = self._GetInstanceList(instance_name == _DOM0_NAME, hvparams)
553 65a6f9b7 Michael Hanselmann
    result = None
554 36bebc53 Helga Velroyen
    for data in instance_list:
555 65a6f9b7 Michael Hanselmann
      if data[0] == instance_name:
556 65a6f9b7 Michael Hanselmann
        result = data
557 65a6f9b7 Michael Hanselmann
        break
558 65a6f9b7 Michael Hanselmann
    return result
559 65a6f9b7 Michael Hanselmann
560 0200a1af Helga Velroyen
  def GetAllInstancesInfo(self, hvparams=None):
561 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
562 65a6f9b7 Michael Hanselmann

563 0200a1af Helga Velroyen
    @type hvparams: dict of strings
564 0200a1af Helga Velroyen
    @param hvparams: hypervisor parameters
565 c41eea6e Iustin Pop
    @return: list of tuples (name, id, memory, vcpus, stat, times)
566 c41eea6e Iustin Pop

567 65a6f9b7 Michael Hanselmann
    """
568 398fd4f6 Helga Velroyen
    return self._GetInstanceList(False, hvparams)
569 65a6f9b7 Michael Hanselmann
570 c3d839f5 Michael Hanselmann
  def _MakeConfigFile(self, instance, startup_memory, block_devices):
571 c3d839f5 Michael Hanselmann
    """Gather configuration details and write to disk.
572 c3d839f5 Michael Hanselmann

573 c3d839f5 Michael Hanselmann
    See L{_GetConfig} for arguments.
574 c3d839f5 Michael Hanselmann

575 c3d839f5 Michael Hanselmann
    """
576 c3d839f5 Michael Hanselmann
    buf = StringIO()
577 c3d839f5 Michael Hanselmann
    buf.write("# Automatically generated by Ganeti. Do not edit!\n")
578 c3d839f5 Michael Hanselmann
    buf.write("\n")
579 c3d839f5 Michael Hanselmann
    buf.write(self._GetConfig(instance, startup_memory, block_devices))
580 c3d839f5 Michael Hanselmann
    buf.write("\n")
581 c3d839f5 Michael Hanselmann
582 c3d839f5 Michael Hanselmann
    self._WriteConfigFile(instance.name, buf.getvalue())
583 c3d839f5 Michael Hanselmann
584 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
585 c41eea6e Iustin Pop
    """Start an instance.
586 c41eea6e Iustin Pop

587 c41eea6e Iustin Pop
    """
588 30b12688 Jose A. Lopes
    startup_memory = self._InstanceStartupMemory(instance)
589 c3d839f5 Michael Hanselmann
590 c3d839f5 Michael Hanselmann
    self._MakeConfigFile(instance, startup_memory, block_devices)
591 c3d839f5 Michael Hanselmann
592 3d942d8b Michael Hanselmann
    cmd = ["create"]
593 323f9095 Stephen Shirley
    if startup_paused:
594 3d942d8b Michael Hanselmann
      cmd.append("-p")
595 3d942d8b Michael Hanselmann
    cmd.append(self._ConfigFileName(instance.name))
596 65a6f9b7 Michael Hanselmann
597 398fd4f6 Helga Velroyen
    result = self._RunXen(cmd, instance.hvparams)
598 65a6f9b7 Michael Hanselmann
    if result.failed:
599 48bba9de Balazs Lecz
      # Move the Xen configuration file to the log directory to avoid
600 48bba9de Balazs Lecz
      # leaving a stale config file behind.
601 48bba9de Balazs Lecz
      stashed_config = self._StashConfigFile(instance.name)
602 48bba9de Balazs Lecz
      raise errors.HypervisorError("Failed to start instance %s: %s (%s). Moved"
603 48bba9de Balazs Lecz
                                   " config file to %s" %
604 65a6f9b7 Michael Hanselmann
                                   (instance.name, result.fail_reason,
605 48bba9de Balazs Lecz
                                    result.output, stashed_config))
606 65a6f9b7 Michael Hanselmann
607 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
608 c41eea6e Iustin Pop
    """Stop an instance.
609 c41eea6e Iustin Pop

610 c41eea6e Iustin Pop
    """
611 bbcf7ad0 Iustin Pop
    if name is None:
612 bbcf7ad0 Iustin Pop
      name = instance.name
613 4b8b172d Michael Hanselmann
614 58e356a9 Helga Velroyen
    return self._StopInstance(name, force, instance.hvparams)
615 31da5ab5 Michael Hanselmann
616 affe1792 Klaus Aehlig
  def _ShutdownInstance(self, name, hvparams):
617 364c350f Jose A. Lopes
    """Shutdown an instance if the instance is running.
618 364c350f Jose A. Lopes

619 364c350f Jose A. Lopes
    @type name: string
620 364c350f Jose A. Lopes
    @param name: name of the instance to stop
621 affe1792 Klaus Aehlig
    @type hvparams: dict of string
622 affe1792 Klaus Aehlig
    @param hvparams: hypervisor parameters of the instance
623 364c350f Jose A. Lopes

624 364c350f Jose A. Lopes
    The '-w' flag waits for shutdown to complete which avoids the need
625 364c350f Jose A. Lopes
    to poll in the case where we want to destroy the domain
626 364c350f Jose A. Lopes
    immediately after shutdown.
627 364c350f Jose A. Lopes

628 364c350f Jose A. Lopes
    """
629 3d680d45 Klaus Aehlig
    instance_info = self.GetInstanceInfo(name, hvparams=hvparams)
630 364c350f Jose A. Lopes
631 364c350f Jose A. Lopes
    if instance_info is None or _IsInstanceShutdown(instance_info[4]):
632 364c350f Jose A. Lopes
      logging.info("Failed to shutdown instance %s, not running", name)
633 364c350f Jose A. Lopes
      return None
634 364c350f Jose A. Lopes
635 affe1792 Klaus Aehlig
    return self._RunXen(["shutdown", "-w", name], hvparams)
636 364c350f Jose A. Lopes
637 affe1792 Klaus Aehlig
  def _DestroyInstance(self, name, hvparams):
638 364c350f Jose A. Lopes
    """Destroy an instance if the instance if the instance exists.
639 364c350f Jose A. Lopes

640 364c350f Jose A. Lopes
    @type name: string
641 364c350f Jose A. Lopes
    @param name: name of the instance to destroy
642 affe1792 Klaus Aehlig
    @type hvparams: dict of string
643 affe1792 Klaus Aehlig
    @param hvparams: hypervisor parameters of the instance
644 364c350f Jose A. Lopes

645 364c350f Jose A. Lopes
    """
646 3d680d45 Klaus Aehlig
    instance_info = self.GetInstanceInfo(name, hvparams=hvparams)
647 364c350f Jose A. Lopes
648 364c350f Jose A. Lopes
    if instance_info is None:
649 364c350f Jose A. Lopes
      logging.info("Failed to destroy instance %s, does not exist", name)
650 364c350f Jose A. Lopes
      return None
651 364c350f Jose A. Lopes
652 affe1792 Klaus Aehlig
    return self._RunXen(["destroy", name], hvparams)
653 364c350f Jose A. Lopes
654 58e356a9 Helga Velroyen
  def _StopInstance(self, name, force, hvparams):
655 31da5ab5 Michael Hanselmann
    """Stop an instance.
656 31da5ab5 Michael Hanselmann

657 58e356a9 Helga Velroyen
    @type name: string
658 364c350f Jose A. Lopes
    @param name: name of the instance to destroy
659 364c350f Jose A. Lopes

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

663 58e356a9 Helga Velroyen
    @type hvparams: dict of string
664 58e356a9 Helga Velroyen
    @param hvparams: hypervisor parameters of the instance
665 58e356a9 Helga Velroyen

666 31da5ab5 Michael Hanselmann
    """
667 65a6f9b7 Michael Hanselmann
    if force:
668 affe1792 Klaus Aehlig
      result = self._DestroyInstance(name, hvparams)
669 65a6f9b7 Michael Hanselmann
    else:
670 affe1792 Klaus Aehlig
      self._ShutdownInstance(name, hvparams)
671 affe1792 Klaus Aehlig
      result = self._DestroyInstance(name, hvparams)
672 65a6f9b7 Michael Hanselmann
673 364c350f Jose A. Lopes
    if result is not None and result.failed and \
674 3d680d45 Klaus Aehlig
          self.GetInstanceInfo(name, hvparams=hvparams) is not None:
675 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to stop instance %s: %s, %s" %
676 bbcf7ad0 Iustin Pop
                                   (name, result.fail_reason, result.output))
677 65a6f9b7 Michael Hanselmann
678 4b8b172d Michael Hanselmann
    # Remove configuration file if stopping/starting instance was successful
679 4b8b172d Michael Hanselmann
    self._RemoveConfigFile(name)
680 4b8b172d Michael Hanselmann
681 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
682 c41eea6e Iustin Pop
    """Reboot an instance.
683 c41eea6e Iustin Pop

684 c41eea6e Iustin Pop
    """
685 0bbec3af Helga Velroyen
    ini_info = self.GetInstanceInfo(instance.name, hvparams=instance.hvparams)
686 65a6f9b7 Michael Hanselmann
687 e0561198 Iustin Pop
    if ini_info is None:
688 e0561198 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s,"
689 e0561198 Iustin Pop
                                   " not running" % instance.name)
690 e0561198 Iustin Pop
691 398fd4f6 Helga Velroyen
    result = self._RunXen(["reboot", instance.name], instance.hvparams)
692 65a6f9b7 Michael Hanselmann
    if result.failed:
693 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s: %s, %s" %
694 3213d3c8 Iustin Pop
                                   (instance.name, result.fail_reason,
695 3213d3c8 Iustin Pop
                                    result.output))
696 06b78e8b Michael Hanselmann
697 06b78e8b Michael Hanselmann
    def _CheckInstance():
698 0bbec3af Helga Velroyen
      new_info = self.GetInstanceInfo(instance.name, hvparams=instance.hvparams)
699 06b78e8b Michael Hanselmann
700 06b78e8b Michael Hanselmann
      # check if the domain ID has changed or the run time has decreased
701 e0561198 Iustin Pop
      if (new_info is not None and
702 e0561198 Iustin Pop
          (new_info[1] != ini_info[1] or new_info[5] < ini_info[5])):
703 06b78e8b Michael Hanselmann
        return
704 7dd106d3 Iustin Pop
705 06b78e8b Michael Hanselmann
      raise utils.RetryAgain()
706 06b78e8b Michael Hanselmann
707 06b78e8b Michael Hanselmann
    try:
708 06b78e8b Michael Hanselmann
      utils.Retry(_CheckInstance, self.REBOOT_RETRY_INTERVAL,
709 06b78e8b Michael Hanselmann
                  self.REBOOT_RETRY_INTERVAL * self.REBOOT_RETRY_COUNT)
710 06b78e8b Michael Hanselmann
    except utils.RetryTimeout:
711 7dd106d3 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s: instance"
712 7dd106d3 Iustin Pop
                                   " did not reboot in the expected interval" %
713 7dd106d3 Iustin Pop
                                   (instance.name, ))
714 65a6f9b7 Michael Hanselmann
715 2c7a0373 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
716 2c7a0373 Guido Trotter
    """Balloon an instance memory to a certain value.
717 2c7a0373 Guido Trotter

718 2c7a0373 Guido Trotter
    @type instance: L{objects.Instance}
719 2c7a0373 Guido Trotter
    @param instance: instance to be accepted
720 2c7a0373 Guido Trotter
    @type mem: int
721 2c7a0373 Guido Trotter
    @param mem: actual memory size to use for instance runtime
722 2c7a0373 Guido Trotter

723 2c7a0373 Guido Trotter
    """
724 398fd4f6 Helga Velroyen
    result = self._RunXen(["mem-set", instance.name, mem], instance.hvparams)
725 2c7a0373 Guido Trotter
    if result.failed:
726 2c7a0373 Guido Trotter
      raise errors.HypervisorError("Failed to balloon instance %s: %s (%s)" %
727 2c7a0373 Guido Trotter
                                   (instance.name, result.fail_reason,
728 2c7a0373 Guido Trotter
                                    result.output))
729 3d942d8b Michael Hanselmann
730 3d942d8b Michael Hanselmann
    # Update configuration file
731 2c7a0373 Guido Trotter
    cmd = ["sed", "-ie", "s/^memory.*$/memory = %s/" % mem]
732 0a903309 Michael Hanselmann
    cmd.append(self._ConfigFileName(instance.name))
733 3d942d8b Michael Hanselmann
734 2c7a0373 Guido Trotter
    result = utils.RunCmd(cmd)
735 2c7a0373 Guido Trotter
    if result.failed:
736 2c7a0373 Guido Trotter
      raise errors.HypervisorError("Failed to update memory for %s: %s (%s)" %
737 2c7a0373 Guido Trotter
                                   (instance.name, result.fail_reason,
738 2c7a0373 Guido Trotter
                                    result.output))
739 2c7a0373 Guido Trotter
740 fac489a5 Helga Velroyen
  def GetNodeInfo(self, hvparams=None):
741 65a6f9b7 Michael Hanselmann
    """Return information about the node.
742 65a6f9b7 Michael Hanselmann

743 06c9a520 Michael Hanselmann
    @see: L{_GetNodeInfo} and L{_ParseNodeInfo}
744 65a6f9b7 Michael Hanselmann

745 65a6f9b7 Michael Hanselmann
    """
746 398fd4f6 Helga Velroyen
    result = self._RunXen(["info"], hvparams)
747 65a6f9b7 Michael Hanselmann
    if result.failed:
748 2609da63 Helga Velroyen
      logging.error("Can't retrieve xen hypervisor information (%s): %s",
749 2609da63 Helga Velroyen
                    result.fail_reason, result.output)
750 65a6f9b7 Michael Hanselmann
      return None
751 65a6f9b7 Michael Hanselmann
752 398fd4f6 Helga Velroyen
    instance_list = self._GetInstanceList(True, hvparams)
753 fac489a5 Helga Velroyen
    return _GetNodeInfo(result.stdout, instance_list)
754 65a6f9b7 Michael Hanselmann
755 f92d9674 Helga Velroyen
  @classmethod
756 f92d9674 Helga Velroyen
  def GetInstanceConsole(cls, instance, primary_node, hvparams, beparams):
757 65a6f9b7 Michael Hanselmann
    """Return a command for connecting to the console of an instance.
758 65a6f9b7 Michael Hanselmann

759 65a6f9b7 Michael Hanselmann
    """
760 f92d9674 Helga Velroyen
    xen_cmd = XenHypervisor._GetCommandFromHvparams(hvparams)
761 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
762 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_SSH,
763 1c3231aa Thomas Thrainer
                                   host=primary_node.name,
764 052783ff Michael Hanselmann
                                   user=constants.SSH_CONSOLE_USER,
765 b9612abb Iustin Pop
                                   command=[pathutils.XEN_CONSOLE_WRAPPER,
766 8ef418bb Helga Velroyen
                                            xen_cmd, instance.name])
767 65a6f9b7 Michael Hanselmann
768 75bf3149 Helga Velroyen
  def Verify(self, hvparams=None):
769 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
770 65a6f9b7 Michael Hanselmann

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

773 75bf3149 Helga Velroyen
    @type hvparams: dict of strings
774 75bf3149 Helga Velroyen
    @param hvparams: hypervisor parameters to be verified against
775 75bf3149 Helga Velroyen

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

778 65a6f9b7 Michael Hanselmann
    """
779 75bf3149 Helga Velroyen
    if hvparams is None:
780 75bf3149 Helga Velroyen
      return "Could not verify the hypervisor, because no hvparams were" \
781 75bf3149 Helga Velroyen
             " provided."
782 75bf3149 Helga Velroyen
783 75bf3149 Helga Velroyen
    if constants.HV_XEN_CMD in hvparams:
784 75bf3149 Helga Velroyen
      xen_cmd = hvparams[constants.HV_XEN_CMD]
785 75bf3149 Helga Velroyen
      try:
786 75bf3149 Helga Velroyen
        self._CheckToolstack(xen_cmd)
787 75bf3149 Helga Velroyen
      except errors.HypervisorError:
788 75bf3149 Helga Velroyen
        return "The configured xen toolstack '%s' is not available on this" \
789 75bf3149 Helga Velroyen
               " node." % xen_cmd
790 75bf3149 Helga Velroyen
791 398fd4f6 Helga Velroyen
    result = self._RunXen(["info"], hvparams)
792 e3e66f02 Michael Hanselmann
    if result.failed:
793 75bf3149 Helga Velroyen
      return "Retrieving information from xen failed: %s, %s" % \
794 75bf3149 Helga Velroyen
        (result.fail_reason, result.output)
795 65a6f9b7 Michael Hanselmann
796 cd04dfd2 Michael Hanselmann
    return None
797 cd04dfd2 Michael Hanselmann
798 4390ccff Guido Trotter
  def MigrationInfo(self, instance):
799 4390ccff Guido Trotter
    """Get instance information to perform a migration.
800 4390ccff Guido Trotter

801 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
802 4390ccff Guido Trotter
    @param instance: instance to be migrated
803 4390ccff Guido Trotter
    @rtype: string
804 4390ccff Guido Trotter
    @return: content of the xen config file
805 4390ccff Guido Trotter

806 4390ccff Guido Trotter
    """
807 4390ccff Guido Trotter
    return self._ReadConfigFile(instance.name)
808 4390ccff Guido Trotter
809 4390ccff Guido Trotter
  def AcceptInstance(self, instance, info, target):
810 4390ccff Guido Trotter
    """Prepare to accept an instance.
811 4390ccff Guido Trotter

812 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
813 4390ccff Guido Trotter
    @param instance: instance to be accepted
814 4390ccff Guido Trotter
    @type info: string
815 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
816 4390ccff Guido Trotter
    @type target: string
817 4390ccff Guido Trotter
    @param target: target host (usually ip), on this node
818 4390ccff Guido Trotter

819 4390ccff Guido Trotter
    """
820 4390ccff Guido Trotter
    pass
821 4390ccff Guido Trotter
822 60af751d Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
823 4390ccff Guido Trotter
    """Finalize an instance migration.
824 4390ccff Guido Trotter

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

828 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
829 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
830 4390ccff Guido Trotter
    @type info: string
831 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
832 4390ccff Guido Trotter
    @type success: boolean
833 4390ccff Guido Trotter
    @param success: whether the migration was a success or a failure
834 4390ccff Guido Trotter

835 4390ccff Guido Trotter
    """
836 4390ccff Guido Trotter
    if success:
837 c3d839f5 Michael Hanselmann
      self._WriteConfigFile(instance.name, info)
838 4390ccff Guido Trotter
839 bc0a2284 Helga Velroyen
  def MigrateInstance(self, cluster_name, instance, target, live):
840 6e7275c0 Iustin Pop
    """Migrate an instance to a target node.
841 6e7275c0 Iustin Pop

842 6e7275c0 Iustin Pop
    The migration will not be attempted if the instance is not
843 6e7275c0 Iustin Pop
    currently running.
844 6e7275c0 Iustin Pop

845 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
846 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
847 fdf7f055 Guido Trotter
    @type target: string
848 fdf7f055 Guido Trotter
    @param target: ip address of the target node
849 fdf7f055 Guido Trotter
    @type live: boolean
850 fdf7f055 Guido Trotter
    @param live: perform a live migration
851 fdf7f055 Guido Trotter

852 6e7275c0 Iustin Pop
    """
853 d8784f7d Michael Hanselmann
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
854 d8784f7d Michael Hanselmann
855 d8784f7d Michael Hanselmann
    return self._MigrateInstance(cluster_name, instance.name, target, port,
856 8351df2f Helga Velroyen
                                 live, instance.hvparams)
857 d8784f7d Michael Hanselmann
858 d8784f7d Michael Hanselmann
  def _MigrateInstance(self, cluster_name, instance_name, target, port, live,
859 8351df2f Helga Velroyen
                       hvparams, _ping_fn=netutils.TcpPing):
860 d8784f7d Michael Hanselmann
    """Migrate an instance to a target node.
861 d8784f7d Michael Hanselmann

862 d8784f7d Michael Hanselmann
    @see: L{MigrateInstance} for details
863 d8784f7d Michael Hanselmann

864 d8784f7d Michael Hanselmann
    """
865 8351df2f Helga Velroyen
    if hvparams is None:
866 8351df2f Helga Velroyen
      raise errors.HypervisorError("No hvparams provided.")
867 8351df2f Helga Velroyen
868 8351df2f Helga Velroyen
    if self.GetInstanceInfo(instance_name, hvparams=hvparams) is None:
869 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Instance not running, cannot migrate")
870 50716be0 Iustin Pop
871 398fd4f6 Helga Velroyen
    cmd = self._GetCommand(hvparams)
872 50716be0 Iustin Pop
873 d8784f7d Michael Hanselmann
    if (cmd == constants.XEN_CMD_XM and
874 d8784f7d Michael Hanselmann
        not _ping_fn(target, port, live_port_needed=True)):
875 50716be0 Iustin Pop
      raise errors.HypervisorError("Remote host %s not listening on port"
876 50716be0 Iustin Pop
                                   " %s, cannot migrate" % (target, port))
877 50716be0 Iustin Pop
878 3d942d8b Michael Hanselmann
    args = ["migrate"]
879 3d942d8b Michael Hanselmann
880 d8784f7d Michael Hanselmann
    if cmd == constants.XEN_CMD_XM:
881 0625d08f René Nussbaumer
      args.extend(["-p", "%d" % port])
882 0625d08f René Nussbaumer
      if live:
883 0625d08f René Nussbaumer
        args.append("-l")
884 3d942d8b Michael Hanselmann
885 d8784f7d Michael Hanselmann
    elif cmd == constants.XEN_CMD_XL:
886 d8784f7d Michael Hanselmann
      args.extend([
887 d8784f7d Michael Hanselmann
        "-s", constants.XL_SSH_CMD % cluster_name,
888 d8784f7d Michael Hanselmann
        "-C", self._ConfigFileName(instance_name),
889 d8784f7d Michael Hanselmann
        ])
890 3d942d8b Michael Hanselmann
891 0625d08f René Nussbaumer
    else:
892 d8784f7d Michael Hanselmann
      raise errors.HypervisorError("Unsupported Xen command: %s" % self._cmd)
893 0625d08f René Nussbaumer
894 d8784f7d Michael Hanselmann
    args.extend([instance_name, target])
895 3d942d8b Michael Hanselmann
896 398fd4f6 Helga Velroyen
    result = self._RunXen(args, hvparams)
897 6e7275c0 Iustin Pop
    if result.failed:
898 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Failed to migrate instance %s: %s" %
899 d8784f7d Michael Hanselmann
                                   (instance_name, result.output))
900 60af751d Andrea Spadaccini
901 60af751d Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
902 60af751d Andrea Spadaccini
    """Finalize the instance migration on the source node.
903 60af751d Andrea Spadaccini

904 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
905 60af751d Andrea Spadaccini
    @param instance: the instance that was migrated
906 60af751d Andrea Spadaccini
    @type success: bool
907 60af751d Andrea Spadaccini
    @param success: whether the migration succeeded or not
908 60af751d Andrea Spadaccini
    @type live: bool
909 60af751d Andrea Spadaccini
    @param live: whether the user requested a live migration or not
910 60af751d Andrea Spadaccini

911 60af751d Andrea Spadaccini
    """
912 60af751d Andrea Spadaccini
    # pylint: disable=W0613
913 60af751d Andrea Spadaccini
    if success:
914 60af751d Andrea Spadaccini
      # remove old xen file after migration succeeded
915 60af751d Andrea Spadaccini
      try:
916 60af751d Andrea Spadaccini
        self._RemoveConfigFile(instance.name)
917 60af751d Andrea Spadaccini
      except EnvironmentError:
918 60af751d Andrea Spadaccini
        logging.exception("Failure while removing instance config file")
919 60af751d Andrea Spadaccini
920 60af751d Andrea Spadaccini
  def GetMigrationStatus(self, instance):
921 60af751d Andrea Spadaccini
    """Get the migration status
922 60af751d Andrea Spadaccini

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

927 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
928 60af751d Andrea Spadaccini
    @param instance: the instance that is being migrated
929 60af751d Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
930 60af751d Andrea Spadaccini
    @return: the status of the current migration (one of
931 60af751d Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
932 60af751d Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
933 60af751d Andrea Spadaccini

934 60af751d Andrea Spadaccini
    """
935 60af751d Andrea Spadaccini
    return objects.MigrationStatus(status=constants.HV_MIGRATION_COMPLETED)
936 6e7275c0 Iustin Pop
937 8ef418bb Helga Velroyen
  def PowercycleNode(self, hvparams=None):
938 f5118ade Iustin Pop
    """Xen-specific powercycle.
939 f5118ade Iustin Pop

940 f5118ade Iustin Pop
    This first does a Linux reboot (which triggers automatically a Xen
941 f5118ade Iustin Pop
    reboot), and if that fails it tries to do a Xen reboot. The reason
942 f5118ade Iustin Pop
    we don't try a Xen reboot first is that the xen reboot launches an
943 f5118ade Iustin Pop
    external command which connects to the Xen hypervisor, and that
944 f5118ade Iustin Pop
    won't work in case the root filesystem is broken and/or the xend
945 f5118ade Iustin Pop
    daemon is not working.
946 f5118ade Iustin Pop

947 8ef418bb Helga Velroyen
    @type hvparams: dict of strings
948 8ef418bb Helga Velroyen
    @param hvparams: hypervisor params to be used on this node
949 8ef418bb Helga Velroyen

950 f5118ade Iustin Pop
    """
951 f5118ade Iustin Pop
    try:
952 8ef418bb Helga Velroyen
      self.LinuxPowercycle()
953 f5118ade Iustin Pop
    finally:
954 8ef418bb Helga Velroyen
      xen_cmd = self._GetCommand(hvparams)
955 8ef418bb Helga Velroyen
      utils.RunCmd([xen_cmd, "debug", "R"])
956 f5118ade Iustin Pop
957 75bf3149 Helga Velroyen
  def _CheckToolstack(self, xen_cmd):
958 75bf3149 Helga Velroyen
    """Check whether the given toolstack is available on the node.
959 75bf3149 Helga Velroyen

960 75bf3149 Helga Velroyen
    @type xen_cmd: string
961 75bf3149 Helga Velroyen
    @param xen_cmd: xen command (e.g. 'xm' or 'xl')
962 75bf3149 Helga Velroyen

963 75bf3149 Helga Velroyen
    """
964 75bf3149 Helga Velroyen
    binary_found = self._CheckToolstackBinary(xen_cmd)
965 75bf3149 Helga Velroyen
    if not binary_found:
966 75bf3149 Helga Velroyen
      raise errors.HypervisorError("No '%s' binary found on node." % xen_cmd)
967 75bf3149 Helga Velroyen
    elif xen_cmd == constants.XEN_CMD_XL:
968 75bf3149 Helga Velroyen
      if not self._CheckToolstackXlConfigured():
969 75bf3149 Helga Velroyen
        raise errors.HypervisorError("Toolstack '%s' is not enabled on this"
970 75bf3149 Helga Velroyen
                                     "node." % xen_cmd)
971 75bf3149 Helga Velroyen
972 75bf3149 Helga Velroyen
  def _CheckToolstackBinary(self, xen_cmd):
973 75bf3149 Helga Velroyen
    """Checks whether the xen command's binary is found on the machine.
974 75bf3149 Helga Velroyen

975 75bf3149 Helga Velroyen
    """
976 75bf3149 Helga Velroyen
    if xen_cmd not in constants.KNOWN_XEN_COMMANDS:
977 75bf3149 Helga Velroyen
      raise errors.HypervisorError("Unknown xen command '%s'." % xen_cmd)
978 75bf3149 Helga Velroyen
    result = self._run_cmd_fn(["which", xen_cmd])
979 75bf3149 Helga Velroyen
    return not result.failed
980 75bf3149 Helga Velroyen
981 75bf3149 Helga Velroyen
  def _CheckToolstackXlConfigured(self):
982 75bf3149 Helga Velroyen
    """Checks whether xl is enabled on an xl-capable node.
983 75bf3149 Helga Velroyen

984 75bf3149 Helga Velroyen
    @rtype: bool
985 75bf3149 Helga Velroyen
    @returns: C{True} if 'xl' is enabled, C{False} otherwise
986 75bf3149 Helga Velroyen

987 75bf3149 Helga Velroyen
    """
988 75bf3149 Helga Velroyen
    result = self._run_cmd_fn([constants.XEN_CMD_XL, "help"])
989 75bf3149 Helga Velroyen
    if not result.failed:
990 75bf3149 Helga Velroyen
      return True
991 75bf3149 Helga Velroyen
    elif result.failed:
992 75bf3149 Helga Velroyen
      if "toolstack" in result.stderr:
993 75bf3149 Helga Velroyen
        return False
994 75bf3149 Helga Velroyen
      # xl fails for some other reason than the toolstack
995 75bf3149 Helga Velroyen
      else:
996 75bf3149 Helga Velroyen
        raise errors.HypervisorError("Cannot run xen ('%s'). Error: %s."
997 75bf3149 Helga Velroyen
                                     % (constants.XEN_CMD_XL, result.stderr))
998 75bf3149 Helga Velroyen
999 65a6f9b7 Michael Hanselmann
1000 65a6f9b7 Michael Hanselmann
class XenPvmHypervisor(XenHypervisor):
1001 65a6f9b7 Michael Hanselmann
  """Xen PVM hypervisor interface"""
1002 65a6f9b7 Michael Hanselmann
1003 205ab586 Iustin Pop
  PARAMETERS = {
1004 2f2dbb4b Jun Futagawa
    constants.HV_USE_BOOTLOADER: hv_base.NO_CHECK,
1005 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_PATH: hv_base.OPT_FILE_CHECK,
1006 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_ARGS: hv_base.NO_CHECK,
1007 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.REQ_FILE_CHECK,
1008 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
1009 7adf7814 René Nussbaumer
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
1010 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
1011 e2d14329 Andrea Spadaccini
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
1012 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
1013 525011bc Maciej Bliziński
    # TODO: Add a check for the blockdev prefix (matching [a-z:] or similar).
1014 525011bc Maciej Bliziński
    constants.HV_BLOCKDEV_PREFIX: hv_base.NO_CHECK,
1015 990ade2d Stephen Shirley
    constants.HV_REBOOT_BEHAVIOR:
1016 c4708267 Tsachy Shacham
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
1017 c4708267 Tsachy Shacham
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
1018 2c368f28 Guido Trotter
    constants.HV_CPU_CAP: hv_base.OPT_NONNEGATIVE_INT_CHECK,
1019 8bd977e9 Sébastien Bocahu
    constants.HV_CPU_WEIGHT:
1020 8bd977e9 Sébastien Bocahu
      (False, lambda x: 0 < x < 65536, "invalid weight", None, None),
1021 397b7844 Dimitris Aragiorgis
    constants.HV_VIF_SCRIPT: hv_base.OPT_FILE_CHECK,
1022 740394bc Helga Velroyen
    constants.HV_XEN_CMD:
1023 740394bc Helga Velroyen
      hv_base.ParamInSet(True, constants.KNOWN_XEN_COMMANDS),
1024 205ab586 Iustin Pop
    }
1025 f48148c3 Iustin Pop
1026 c3d839f5 Michael Hanselmann
  def _GetConfig(self, instance, startup_memory, block_devices):
1027 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
1028 65a6f9b7 Michael Hanselmann

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

1158 65a6f9b7 Michael Hanselmann
    """
1159 a985b417 Iustin Pop
    hvp = instance.hvparams
1160 a985b417 Iustin Pop
1161 65a6f9b7 Michael Hanselmann
    config = StringIO()
1162 e2ee1cea Iustin Pop
1163 e2ee1cea Iustin Pop
    # kernel handling
1164 e2ee1cea Iustin Pop
    kpath = hvp[constants.HV_KERNEL_PATH]
1165 e2ee1cea Iustin Pop
    config.write("kernel = '%s'\n" % kpath)
1166 e2ee1cea Iustin Pop
1167 65a6f9b7 Michael Hanselmann
    config.write("builder = 'hvm'\n")
1168 61eb1a46 Guido Trotter
    config.write("memory = %d\n" % startup_memory)
1169 80121c83 Guido Trotter
    config.write("maxmem = %d\n" % instance.beparams[constants.BE_MAXMEM])
1170 8b3fd458 Iustin Pop
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
1171 347fa0f1 Michael Hanselmann
    cpu_pinning = _CreateConfigCpus(hvp[constants.HV_CPU_MASK])
1172 c4708267 Tsachy Shacham
    if cpu_pinning:
1173 c4708267 Tsachy Shacham
      config.write("%s\n" % cpu_pinning)
1174 8bd977e9 Sébastien Bocahu
    cpu_cap = hvp[constants.HV_CPU_CAP]
1175 8bd977e9 Sébastien Bocahu
    if cpu_cap:
1176 8bd977e9 Sébastien Bocahu
      config.write("cpu_cap=%d\n" % cpu_cap)
1177 8bd977e9 Sébastien Bocahu
    cpu_weight = hvp[constants.HV_CPU_WEIGHT]
1178 8bd977e9 Sébastien Bocahu
    if cpu_weight:
1179 8bd977e9 Sébastien Bocahu
      config.write("cpu_weight=%d\n" % cpu_weight)
1180 c4708267 Tsachy Shacham
1181 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
1182 09ea8710 Iustin Pop
    if hvp[constants.HV_PAE]:
1183 a21dda8b Iustin Pop
      config.write("pae = 1\n")
1184 a21dda8b Iustin Pop
    else:
1185 a21dda8b Iustin Pop
      config.write("pae = 0\n")
1186 09ea8710 Iustin Pop
    if hvp[constants.HV_ACPI]:
1187 a21dda8b Iustin Pop
      config.write("acpi = 1\n")
1188 a21dda8b Iustin Pop
    else:
1189 a21dda8b Iustin Pop
      config.write("acpi = 0\n")
1190 ffc27116 Thomas Thrainer
    if hvp[constants.HV_VIRIDIAN]:
1191 ffc27116 Thomas Thrainer
      config.write("viridian = 1\n")
1192 ffc27116 Thomas Thrainer
    else:
1193 ffc27116 Thomas Thrainer
      config.write("viridian = 0\n")
1194 ffc27116 Thomas Thrainer
1195 65a6f9b7 Michael Hanselmann
    config.write("apic = 1\n")
1196 09ea8710 Iustin Pop
    config.write("device_model = '%s'\n" % hvp[constants.HV_DEVICE_MODEL])
1197 a985b417 Iustin Pop
    config.write("boot = '%s'\n" % hvp[constants.HV_BOOT_ORDER])
1198 65a6f9b7 Michael Hanselmann
    config.write("sdl = 0\n")
1199 97efde45 Guido Trotter
    config.write("usb = 1\n")
1200 97efde45 Guido Trotter
    config.write("usbdevice = 'tablet'\n")
1201 65a6f9b7 Michael Hanselmann
    config.write("vnc = 1\n")
1202 a985b417 Iustin Pop
    if hvp[constants.HV_VNC_BIND_ADDRESS] is None:
1203 d0c11cf7 Alexander Schreiber
      config.write("vnclisten = '%s'\n" % constants.VNC_DEFAULT_BIND_ADDRESS)
1204 d0c11cf7 Alexander Schreiber
    else:
1205 6b405598 Guido Trotter
      config.write("vnclisten = '%s'\n" % hvp[constants.HV_VNC_BIND_ADDRESS])
1206 65a6f9b7 Michael Hanselmann
1207 377d74c9 Guido Trotter
    if instance.network_port > constants.VNC_BASE_PORT:
1208 377d74c9 Guido Trotter
      display = instance.network_port - constants.VNC_BASE_PORT
1209 65a6f9b7 Michael Hanselmann
      config.write("vncdisplay = %s\n" % display)
1210 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 0\n")
1211 65a6f9b7 Michael Hanselmann
    else:
1212 65a6f9b7 Michael Hanselmann
      config.write("# vncdisplay = 1\n")
1213 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 1\n")
1214 65a6f9b7 Michael Hanselmann
1215 6e6bb8d5 Guido Trotter
    vnc_pwd_file = hvp[constants.HV_VNC_PASSWORD_FILE]
1216 65a6f9b7 Michael Hanselmann
    try:
1217 6e6bb8d5 Guido Trotter
      password = utils.ReadFile(vnc_pwd_file)
1218 78f66a17 Guido Trotter
    except EnvironmentError, err:
1219 78f66a17 Guido Trotter
      raise errors.HypervisorError("Failed to open VNC password file %s: %s" %
1220 6e6bb8d5 Guido Trotter
                                   (vnc_pwd_file, err))
1221 65a6f9b7 Michael Hanselmann
1222 65a6f9b7 Michael Hanselmann
    config.write("vncpasswd = '%s'\n" % password.rstrip())
1223 65a6f9b7 Michael Hanselmann
1224 65a6f9b7 Michael Hanselmann
    config.write("serial = 'pty'\n")
1225 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
1226 6b970cef Jun Futagawa
      config.write("localtime = 1\n")
1227 65a6f9b7 Michael Hanselmann
1228 65a6f9b7 Michael Hanselmann
    vif_data = []
1229 05440845 Helga Velroyen
    # Note: what is called 'nic_type' here, is used as value for the xen nic
1230 05440845 Helga Velroyen
    # vif config parameter 'model'. For the xen nic vif parameter 'type', we use
1231 05440845 Helga Velroyen
    # the 'vif_type' to avoid a clash of notation.
1232 a985b417 Iustin Pop
    nic_type = hvp[constants.HV_NIC_TYPE]
1233 05440845 Helga Velroyen
1234 f48148c3 Iustin Pop
    if nic_type is None:
1235 05440845 Helga Velroyen
      vif_type_str = ""
1236 05440845 Helga Velroyen
      if hvp[constants.HV_VIF_TYPE]:
1237 05440845 Helga Velroyen
        vif_type_str = ", type=%s" % hvp[constants.HV_VIF_TYPE]
1238 f48148c3 Iustin Pop
      # ensure old instances don't change
1239 05440845 Helga Velroyen
      nic_type_str = vif_type_str
1240 d08f6067 Guido Trotter
    elif nic_type == constants.HT_NIC_PARAVIRTUAL:
1241 f48148c3 Iustin Pop
      nic_type_str = ", type=paravirtualized"
1242 f48148c3 Iustin Pop
    else:
1243 05440845 Helga Velroyen
      # parameter 'model' is only valid with type 'ioemu'
1244 05440845 Helga Velroyen
      nic_type_str = ", model=%s, type=%s" % \
1245 05440845 Helga Velroyen
        (nic_type, constants.HT_HVM_VIF_IOEMU)
1246 397b7844 Dimitris Aragiorgis
    for idx, nic in enumerate(instance.nics):
1247 503b97a9 Guido Trotter
      nic_str = "mac=%s%s" % (nic.mac, nic_type_str)
1248 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
1249 65a6f9b7 Michael Hanselmann
      if ip is not None:
1250 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
1251 503b97a9 Guido Trotter
      if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1252 503b97a9 Guido Trotter
        nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK]
1253 397b7844 Dimitris Aragiorgis
      if hvp[constants.HV_VIF_SCRIPT]:
1254 397b7844 Dimitris Aragiorgis
        nic_str += ", script=%s" % hvp[constants.HV_VIF_SCRIPT]
1255 0183a697 Alessandro Cincaglini
      vif_data.append("'%s'" % nic_str)
1256 397b7844 Dimitris Aragiorgis
      self._WriteNICInfoFile(instance.name, idx, nic)
1257 65a6f9b7 Michael Hanselmann
1258 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
1259 525011bc Maciej Bliziński
1260 d0bb3f24 Michael Hanselmann
    disk_data = \
1261 d0bb3f24 Michael Hanselmann
      _GetConfigFileDiskData(block_devices, hvp[constants.HV_BLOCKDEV_PREFIX])
1262 525011bc Maciej Bliziński
1263 a985b417 Iustin Pop
    iso_path = hvp[constants.HV_CDROM_IMAGE_PATH]
1264 f48148c3 Iustin Pop
    if iso_path:
1265 f48148c3 Iustin Pop
      iso = "'file:%s,hdc:cdrom,r'" % iso_path
1266 a21dda8b Iustin Pop
      disk_data.append(iso)
1267 a21dda8b Iustin Pop
1268 a21dda8b Iustin Pop
    config.write("disk = [%s]\n" % (",".join(disk_data)))
1269 87f0aa48 Jack
    # Add PCI passthrough
1270 87f0aa48 Jack
    pci_pass_arr = []
1271 87f0aa48 Jack
    pci_pass = hvp[constants.HV_PASSTHROUGH]
1272 87f0aa48 Jack
    if pci_pass:
1273 3891c95e Bernardo Dal Seno
      pci_pass_arr = pci_pass.split(";")
1274 3891c95e Bernardo Dal Seno
      config.write("pci = %s\n" % pci_pass_arr)
1275 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
1276 990ade2d Stephen Shirley
    if hvp[constants.HV_REBOOT_BEHAVIOR] == constants.INSTANCE_REBOOT_ALLOWED:
1277 990ade2d Stephen Shirley
      config.write("on_reboot = 'restart'\n")
1278 990ade2d Stephen Shirley
    else:
1279 990ade2d Stephen Shirley
      config.write("on_reboot = 'destroy'\n")
1280 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
1281 73cd67f4 Guido Trotter
1282 c3d839f5 Michael Hanselmann
    return config.getvalue()