Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ 7bc2c097

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

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

89 b255379d Michael Hanselmann
  @type fn: callable
90 b255379d Michael Hanselmann
  @param fn: Function returning result of running C{xm list}
91 b255379d Michael Hanselmann
  @type xmllist_errors: list
92 b255379d Michael Hanselmann
  @param xmllist_errors: Error list
93 b255379d Michael Hanselmann
  @rtype: list
94 b255379d Michael Hanselmann

95 b255379d Michael Hanselmann
  """
96 b255379d Michael Hanselmann
  result = fn()
97 b255379d Michael Hanselmann
  if result.failed:
98 b255379d Michael Hanselmann
    logging.error("xm list failed (%s): %s", result.fail_reason,
99 b255379d Michael Hanselmann
                  result.output)
100 b255379d Michael Hanselmann
    xmllist_errors.append(result)
101 b255379d Michael Hanselmann
    raise utils.RetryAgain()
102 b255379d Michael Hanselmann
103 b255379d Michael Hanselmann
  # skip over the heading
104 b255379d Michael Hanselmann
  return result.stdout.splitlines()
105 b255379d Michael Hanselmann
106 b255379d Michael Hanselmann
107 b255379d Michael Hanselmann
def _ParseXmList(lines, include_node):
108 b255379d Michael Hanselmann
  """Parses the output of C{xm list}.
109 b255379d Michael Hanselmann

110 b255379d Michael Hanselmann
  @type lines: list
111 b255379d Michael Hanselmann
  @param lines: Output lines of C{xm list}
112 b255379d Michael Hanselmann
  @type include_node: boolean
113 b255379d Michael Hanselmann
  @param include_node: If True, return information for Dom0
114 b255379d Michael Hanselmann
  @return: list of tuple containing (name, id, memory, vcpus, state, time
115 b255379d Michael Hanselmann
    spent)
116 b255379d Michael Hanselmann

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

148 b255379d Michael Hanselmann
  See L{_RunXmList} and L{_ParseXmList} for parameter details.
149 b255379d Michael Hanselmann

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

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

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

240 06c9a520 Michael Hanselmann
  @type info: dict
241 06c9a520 Michael Hanselmann
  @param info: Result from L{_ParseNodeInfo}
242 06c9a520 Michael Hanselmann
  @type fn: callable
243 06c9a520 Michael Hanselmann
  @param fn: Function returning result of running C{xm list}
244 06c9a520 Michael Hanselmann
  @rtype: dict
245 06c9a520 Michael Hanselmann

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

270 06c9a520 Michael Hanselmann
  """
271 06c9a520 Michael Hanselmann
  return _MergeInstanceInfo(_ParseNodeInfo(info), fn)
272 06c9a520 Michael Hanselmann
273 06c9a520 Michael Hanselmann
274 d0bb3f24 Michael Hanselmann
def _GetConfigFileDiskData(block_devices, blockdev_prefix,
275 d0bb3f24 Michael Hanselmann
                           _letters=_DISK_LETTERS):
276 d0bb3f24 Michael Hanselmann
  """Get disk directives for Xen config file.
277 d0bb3f24 Michael Hanselmann

278 d0bb3f24 Michael Hanselmann
  This method builds the xen config disk directive according to the
279 d0bb3f24 Michael Hanselmann
  given disk_template and block_devices.
280 d0bb3f24 Michael Hanselmann

281 d0bb3f24 Michael Hanselmann
  @param block_devices: list of tuples (cfdev, rldev):
282 d0bb3f24 Michael Hanselmann
      - cfdev: dict containing ganeti config disk part
283 d0bb3f24 Michael Hanselmann
      - rldev: ganeti.bdev.BlockDev object
284 d0bb3f24 Michael Hanselmann
  @param blockdev_prefix: a string containing blockdevice prefix,
285 d0bb3f24 Michael Hanselmann
                          e.g. "sd" for /dev/sda
286 d0bb3f24 Michael Hanselmann

287 d0bb3f24 Michael Hanselmann
  @return: string containing disk directive for xen instance config file
288 d0bb3f24 Michael Hanselmann

289 d0bb3f24 Michael Hanselmann
  """
290 d0bb3f24 Michael Hanselmann
  if len(block_devices) > len(_letters):
291 d0bb3f24 Michael Hanselmann
    raise errors.HypervisorError("Too many disks")
292 d0bb3f24 Michael Hanselmann
293 d0bb3f24 Michael Hanselmann
  disk_data = []
294 d0bb3f24 Michael Hanselmann
295 d0bb3f24 Michael Hanselmann
  for sd_suffix, (cfdev, dev_path) in zip(_letters, block_devices):
296 d0bb3f24 Michael Hanselmann
    sd_name = blockdev_prefix + sd_suffix
297 d0bb3f24 Michael Hanselmann
298 d0bb3f24 Michael Hanselmann
    if cfdev.mode == constants.DISK_RDWR:
299 d0bb3f24 Michael Hanselmann
      mode = "w"
300 d0bb3f24 Michael Hanselmann
    else:
301 d0bb3f24 Michael Hanselmann
      mode = "r"
302 d0bb3f24 Michael Hanselmann
303 d0bb3f24 Michael Hanselmann
    if cfdev.dev_type == constants.LD_FILE:
304 d0bb3f24 Michael Hanselmann
      driver = _FILE_DRIVER_MAP[cfdev.physical_id[0]]
305 d0bb3f24 Michael Hanselmann
    else:
306 d0bb3f24 Michael Hanselmann
      driver = "phy"
307 d0bb3f24 Michael Hanselmann
308 d0bb3f24 Michael Hanselmann
    disk_data.append("'%s:%s,%s,%s'" % (driver, dev_path, sd_name, mode))
309 d0bb3f24 Michael Hanselmann
310 d0bb3f24 Michael Hanselmann
  return disk_data
311 d0bb3f24 Michael Hanselmann
312 d0bb3f24 Michael Hanselmann
313 a2d32034 Michael Hanselmann
class XenHypervisor(hv_base.BaseHypervisor):
314 65a6f9b7 Michael Hanselmann
  """Xen generic hypervisor interface
315 65a6f9b7 Michael Hanselmann

316 65a6f9b7 Michael Hanselmann
  This is the Xen base class used for both Xen PVM and HVM. It contains
317 65a6f9b7 Michael Hanselmann
  all the functionality that is identical for both.
318 65a6f9b7 Michael Hanselmann

319 65a6f9b7 Michael Hanselmann
  """
320 d271c6fd Iustin Pop
  CAN_MIGRATE = True
321 7dd106d3 Iustin Pop
  REBOOT_RETRY_COUNT = 60
322 7dd106d3 Iustin Pop
  REBOOT_RETRY_INTERVAL = 10
323 65a6f9b7 Michael Hanselmann
324 3680f662 Guido Trotter
  ANCILLARY_FILES = [
325 22d568c2 Guido Trotter
    XEND_CONFIG_FILE,
326 22d568c2 Guido Trotter
    XL_CONFIG_FILE,
327 22d568c2 Guido Trotter
    VIF_BRIDGE_SCRIPT,
328 3680f662 Guido Trotter
    ]
329 69ab2e12 Guido Trotter
  ANCILLARY_FILES_OPT = [
330 69ab2e12 Guido Trotter
    XL_CONFIG_FILE,
331 3680f662 Guido Trotter
    ]
332 3680f662 Guido Trotter
333 3d942d8b Michael Hanselmann
  def __init__(self, _cfgdir=None, _run_cmd_fn=None, _cmd=None):
334 0a903309 Michael Hanselmann
    hv_base.BaseHypervisor.__init__(self)
335 0a903309 Michael Hanselmann
336 0a903309 Michael Hanselmann
    if _cfgdir is None:
337 0a903309 Michael Hanselmann
      self._cfgdir = pathutils.XEN_CONFIG_DIR
338 0a903309 Michael Hanselmann
    else:
339 0a903309 Michael Hanselmann
      self._cfgdir = _cfgdir
340 0a903309 Michael Hanselmann
341 3d942d8b Michael Hanselmann
    if _run_cmd_fn is None:
342 3d942d8b Michael Hanselmann
      self._run_cmd_fn = utils.RunCmd
343 3d942d8b Michael Hanselmann
    else:
344 3d942d8b Michael Hanselmann
      self._run_cmd_fn = _run_cmd_fn
345 3d942d8b Michael Hanselmann
346 3d942d8b Michael Hanselmann
    self._cmd = _cmd
347 3d942d8b Michael Hanselmann
348 3d942d8b Michael Hanselmann
  def _GetCommand(self):
349 d8784f7d Michael Hanselmann
    """Returns Xen command to use.
350 d8784f7d Michael Hanselmann

351 d8784f7d Michael Hanselmann
    """
352 3d942d8b Michael Hanselmann
    if self._cmd is None:
353 3d942d8b Michael Hanselmann
      # TODO: Make command a hypervisor parameter
354 3d942d8b Michael Hanselmann
      cmd = constants.XEN_CMD
355 3d942d8b Michael Hanselmann
    else:
356 3d942d8b Michael Hanselmann
      cmd = self._cmd
357 3d942d8b Michael Hanselmann
358 3d942d8b Michael Hanselmann
    if cmd not in constants.KNOWN_XEN_COMMANDS:
359 3d942d8b Michael Hanselmann
      raise errors.ProgrammerError("Unknown Xen command '%s'" % cmd)
360 3d942d8b Michael Hanselmann
361 3d942d8b Michael Hanselmann
    return cmd
362 3d942d8b Michael Hanselmann
363 3d942d8b Michael Hanselmann
  def _RunXen(self, args):
364 81124130 Michael Hanselmann
    """Wrapper around L{utils.process.RunCmd} to run Xen command.
365 3d942d8b Michael Hanselmann

366 81124130 Michael Hanselmann
    @see: L{utils.process.RunCmd}
367 3d942d8b Michael Hanselmann

368 3d942d8b Michael Hanselmann
    """
369 3d942d8b Michael Hanselmann
    cmd = [self._GetCommand()]
370 3d942d8b Michael Hanselmann
    cmd.extend(args)
371 3d942d8b Michael Hanselmann
372 3d942d8b Michael Hanselmann
    return self._run_cmd_fn(cmd)
373 3d942d8b Michael Hanselmann
374 0a903309 Michael Hanselmann
  def _ConfigFileName(self, instance_name):
375 c2be2532 Guido Trotter
    """Get the config file name for an instance.
376 c2be2532 Guido Trotter

377 c2be2532 Guido Trotter
    @param instance_name: instance name
378 c2be2532 Guido Trotter
    @type instance_name: str
379 c2be2532 Guido Trotter
    @return: fully qualified path to instance config file
380 c2be2532 Guido Trotter
    @rtype: str
381 c2be2532 Guido Trotter

382 c2be2532 Guido Trotter
    """
383 0a903309 Michael Hanselmann
    return utils.PathJoin(self._cfgdir, instance_name)
384 c2be2532 Guido Trotter
385 5661b908 Iustin Pop
  @classmethod
386 c3d839f5 Michael Hanselmann
  def _GetConfig(cls, instance, startup_memory, block_devices):
387 c3d839f5 Michael Hanselmann
    """Build Xen configuration for an instance.
388 65a6f9b7 Michael Hanselmann

389 65a6f9b7 Michael Hanselmann
    """
390 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
391 65a6f9b7 Michael Hanselmann
392 c3d839f5 Michael Hanselmann
  def _WriteConfigFile(self, instance_name, data):
393 4390ccff Guido Trotter
    """Write the Xen config file for the instance.
394 4390ccff Guido Trotter

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

397 4390ccff Guido Trotter
    """
398 1a63f285 Iustin Pop
    # just in case it exists
399 0a903309 Michael Hanselmann
    utils.RemoveFile(utils.PathJoin(self._cfgdir, "auto", instance_name))
400 a8e8c0c6 Michael Hanselmann
401 0a903309 Michael Hanselmann
    cfg_file = self._ConfigFileName(instance_name)
402 1a63f285 Iustin Pop
    try:
403 1a63f285 Iustin Pop
      utils.WriteFile(cfg_file, data=data)
404 1a63f285 Iustin Pop
    except EnvironmentError, err:
405 1a63f285 Iustin Pop
      raise errors.HypervisorError("Cannot write Xen instance configuration"
406 1a63f285 Iustin Pop
                                   " file %s: %s" % (cfg_file, err))
407 4390ccff Guido Trotter
408 0a903309 Michael Hanselmann
  def _ReadConfigFile(self, instance_name):
409 4390ccff Guido Trotter
    """Returns the contents of the instance config file.
410 4390ccff Guido Trotter

411 4390ccff Guido Trotter
    """
412 0a903309 Michael Hanselmann
    filename = self._ConfigFileName(instance_name)
413 76c364d9 Michael Hanselmann
414 4390ccff Guido Trotter
    try:
415 76c364d9 Michael Hanselmann
      file_content = utils.ReadFile(filename)
416 4390ccff Guido Trotter
    except EnvironmentError, err:
417 4390ccff Guido Trotter
      raise errors.HypervisorError("Failed to load Xen config file: %s" % err)
418 76c364d9 Michael Hanselmann
419 4390ccff Guido Trotter
    return file_content
420 4390ccff Guido Trotter
421 0a903309 Michael Hanselmann
  def _RemoveConfigFile(self, instance_name):
422 65a6f9b7 Michael Hanselmann
    """Remove the xen configuration file.
423 65a6f9b7 Michael Hanselmann

424 65a6f9b7 Michael Hanselmann
    """
425 0a903309 Michael Hanselmann
    utils.RemoveFile(self._ConfigFileName(instance_name))
426 65a6f9b7 Michael Hanselmann
427 48bba9de Balazs Lecz
  def _StashConfigFile(self, instance_name):
428 48bba9de Balazs Lecz
    """Move the Xen config file to the log directory and return its new path.
429 48bba9de Balazs Lecz

430 48bba9de Balazs Lecz
    """
431 48bba9de Balazs Lecz
    old_filename = self._ConfigFileName(instance_name)
432 48bba9de Balazs Lecz
    base = ("%s-%s" %
433 48bba9de Balazs Lecz
            (instance_name, utils.TimestampForFilename()))
434 48bba9de Balazs Lecz
    new_filename = utils.PathJoin(pathutils.LOG_XEN_DIR, base)
435 48bba9de Balazs Lecz
    utils.RenameFile(old_filename, new_filename)
436 48bba9de Balazs Lecz
    return new_filename
437 48bba9de Balazs Lecz
438 3d942d8b Michael Hanselmann
  def _GetXmList(self, include_node):
439 b255379d Michael Hanselmann
    """Wrapper around module level L{_GetXmList}.
440 06b78e8b Michael Hanselmann

441 06b78e8b Michael Hanselmann
    """
442 3d942d8b Michael Hanselmann
    return _GetXmList(lambda: self._RunXen(["list"]), include_node)
443 65a6f9b7 Michael Hanselmann
444 65a6f9b7 Michael Hanselmann
  def ListInstances(self):
445 65a6f9b7 Michael Hanselmann
    """Get the list of running instances.
446 65a6f9b7 Michael Hanselmann

447 65a6f9b7 Michael Hanselmann
    """
448 b255379d Michael Hanselmann
    xm_list = self._GetXmList(False)
449 65a6f9b7 Michael Hanselmann
    names = [info[0] for info in xm_list]
450 65a6f9b7 Michael Hanselmann
    return names
451 65a6f9b7 Michael Hanselmann
452 65a6f9b7 Michael Hanselmann
  def GetInstanceInfo(self, instance_name):
453 65a6f9b7 Michael Hanselmann
    """Get instance properties.
454 65a6f9b7 Michael Hanselmann

455 c41eea6e Iustin Pop
    @param instance_name: the instance name
456 c41eea6e Iustin Pop

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

459 65a6f9b7 Michael Hanselmann
    """
460 b255379d Michael Hanselmann
    xm_list = self._GetXmList(instance_name == _DOM0_NAME)
461 65a6f9b7 Michael Hanselmann
    result = None
462 65a6f9b7 Michael Hanselmann
    for data in xm_list:
463 65a6f9b7 Michael Hanselmann
      if data[0] == instance_name:
464 65a6f9b7 Michael Hanselmann
        result = data
465 65a6f9b7 Michael Hanselmann
        break
466 65a6f9b7 Michael Hanselmann
    return result
467 65a6f9b7 Michael Hanselmann
468 65a6f9b7 Michael Hanselmann
  def GetAllInstancesInfo(self):
469 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
470 65a6f9b7 Michael Hanselmann

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

473 65a6f9b7 Michael Hanselmann
    """
474 b255379d Michael Hanselmann
    xm_list = self._GetXmList(False)
475 65a6f9b7 Michael Hanselmann
    return xm_list
476 65a6f9b7 Michael Hanselmann
477 c3d839f5 Michael Hanselmann
  def _MakeConfigFile(self, instance, startup_memory, block_devices):
478 c3d839f5 Michael Hanselmann
    """Gather configuration details and write to disk.
479 c3d839f5 Michael Hanselmann

480 c3d839f5 Michael Hanselmann
    See L{_GetConfig} for arguments.
481 c3d839f5 Michael Hanselmann

482 c3d839f5 Michael Hanselmann
    """
483 c3d839f5 Michael Hanselmann
    buf = StringIO()
484 c3d839f5 Michael Hanselmann
    buf.write("# Automatically generated by Ganeti. Do not edit!\n")
485 c3d839f5 Michael Hanselmann
    buf.write("\n")
486 c3d839f5 Michael Hanselmann
    buf.write(self._GetConfig(instance, startup_memory, block_devices))
487 c3d839f5 Michael Hanselmann
    buf.write("\n")
488 c3d839f5 Michael Hanselmann
489 c3d839f5 Michael Hanselmann
    self._WriteConfigFile(instance.name, buf.getvalue())
490 c3d839f5 Michael Hanselmann
491 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
492 c41eea6e Iustin Pop
    """Start an instance.
493 c41eea6e Iustin Pop

494 c41eea6e Iustin Pop
    """
495 61eb1a46 Guido Trotter
    startup_memory = self._InstanceStartupMemory(instance)
496 c3d839f5 Michael Hanselmann
497 c3d839f5 Michael Hanselmann
    self._MakeConfigFile(instance, startup_memory, block_devices)
498 c3d839f5 Michael Hanselmann
499 3d942d8b Michael Hanselmann
    cmd = ["create"]
500 323f9095 Stephen Shirley
    if startup_paused:
501 3d942d8b Michael Hanselmann
      cmd.append("-p")
502 3d942d8b Michael Hanselmann
    cmd.append(self._ConfigFileName(instance.name))
503 65a6f9b7 Michael Hanselmann
504 3d942d8b Michael Hanselmann
    result = self._RunXen(cmd)
505 65a6f9b7 Michael Hanselmann
    if result.failed:
506 48bba9de Balazs Lecz
      # Move the Xen configuration file to the log directory to avoid
507 48bba9de Balazs Lecz
      # leaving a stale config file behind.
508 48bba9de Balazs Lecz
      stashed_config = self._StashConfigFile(instance.name)
509 48bba9de Balazs Lecz
      raise errors.HypervisorError("Failed to start instance %s: %s (%s). Moved"
510 48bba9de Balazs Lecz
                                   " config file to %s" %
511 65a6f9b7 Michael Hanselmann
                                   (instance.name, result.fail_reason,
512 48bba9de Balazs Lecz
                                    result.output, stashed_config))
513 65a6f9b7 Michael Hanselmann
514 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
515 c41eea6e Iustin Pop
    """Stop an instance.
516 c41eea6e Iustin Pop

517 c41eea6e Iustin Pop
    """
518 bbcf7ad0 Iustin Pop
    if name is None:
519 bbcf7ad0 Iustin Pop
      name = instance.name
520 4b8b172d Michael Hanselmann
521 31da5ab5 Michael Hanselmann
    return self._StopInstance(name, force)
522 31da5ab5 Michael Hanselmann
523 364c350f Jose A. Lopes
  def _ShutdownInstance(self, name):
524 364c350f Jose A. Lopes
    """Shutdown an instance if the instance is running.
525 364c350f Jose A. Lopes

526 364c350f Jose A. Lopes
    @type name: string
527 364c350f Jose A. Lopes
    @param name: name of the instance to stop
528 364c350f Jose A. Lopes

529 364c350f Jose A. Lopes
    The '-w' flag waits for shutdown to complete which avoids the need
530 364c350f Jose A. Lopes
    to poll in the case where we want to destroy the domain
531 364c350f Jose A. Lopes
    immediately after shutdown.
532 364c350f Jose A. Lopes

533 364c350f Jose A. Lopes
    """
534 364c350f Jose A. Lopes
    instance_info = self.GetInstanceInfo(name)
535 364c350f Jose A. Lopes
536 364c350f Jose A. Lopes
    if instance_info is None or _IsInstanceShutdown(instance_info[4]):
537 364c350f Jose A. Lopes
      logging.info("Failed to shutdown instance %s, not running", name)
538 364c350f Jose A. Lopes
      return None
539 364c350f Jose A. Lopes
540 364c350f Jose A. Lopes
    return self._RunXen(["shutdown", "-w", name])
541 364c350f Jose A. Lopes
542 364c350f Jose A. Lopes
  def _DestroyInstance(self, name):
543 364c350f Jose A. Lopes
    """Destroy an instance if the instance if the instance exists.
544 364c350f Jose A. Lopes

545 364c350f Jose A. Lopes
    @type name: string
546 364c350f Jose A. Lopes
    @param name: name of the instance to destroy
547 364c350f Jose A. Lopes

548 364c350f Jose A. Lopes
    """
549 364c350f Jose A. Lopes
    instance_info = self.GetInstanceInfo(name)
550 364c350f Jose A. Lopes
551 364c350f Jose A. Lopes
    if instance_info is None:
552 364c350f Jose A. Lopes
      logging.info("Failed to destroy instance %s, does not exist", name)
553 364c350f Jose A. Lopes
      return None
554 364c350f Jose A. Lopes
555 364c350f Jose A. Lopes
    return self._RunXen(["destroy", name])
556 364c350f Jose A. Lopes
557 31da5ab5 Michael Hanselmann
  def _StopInstance(self, name, force):
558 31da5ab5 Michael Hanselmann
    """Stop an instance.
559 31da5ab5 Michael Hanselmann

560 364c350f Jose A. Lopes
    @type name: string
561 364c350f Jose A. Lopes
    @param name: name of the instance to destroy
562 364c350f Jose A. Lopes

563 364c350f Jose A. Lopes
    @type force: boolean
564 364c350f Jose A. Lopes
    @param force: whether to do a "hard" stop (destroy)
565 364c350f Jose A. Lopes

566 31da5ab5 Michael Hanselmann
    """
567 65a6f9b7 Michael Hanselmann
    if force:
568 364c350f Jose A. Lopes
      result = self._DestroyInstance(name)
569 65a6f9b7 Michael Hanselmann
    else:
570 364c350f Jose A. Lopes
      self._ShutdownInstance(name)
571 364c350f Jose A. Lopes
      result = self._DestroyInstance(name)
572 65a6f9b7 Michael Hanselmann
573 364c350f Jose A. Lopes
    if result is not None and result.failed and \
574 364c350f Jose A. Lopes
          self.GetInstanceInfo(name) is not None:
575 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to stop instance %s: %s, %s" %
576 bbcf7ad0 Iustin Pop
                                   (name, result.fail_reason, result.output))
577 65a6f9b7 Michael Hanselmann
578 4b8b172d Michael Hanselmann
    # Remove configuration file if stopping/starting instance was successful
579 4b8b172d Michael Hanselmann
    self._RemoveConfigFile(name)
580 4b8b172d Michael Hanselmann
581 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
582 c41eea6e Iustin Pop
    """Reboot an instance.
583 c41eea6e Iustin Pop

584 c41eea6e Iustin Pop
    """
585 7dd106d3 Iustin Pop
    ini_info = self.GetInstanceInfo(instance.name)
586 65a6f9b7 Michael Hanselmann
587 e0561198 Iustin Pop
    if ini_info is None:
588 e0561198 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s,"
589 e0561198 Iustin Pop
                                   " not running" % instance.name)
590 e0561198 Iustin Pop
591 3d942d8b Michael Hanselmann
    result = self._RunXen(["reboot", instance.name])
592 65a6f9b7 Michael Hanselmann
    if result.failed:
593 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s: %s, %s" %
594 3213d3c8 Iustin Pop
                                   (instance.name, result.fail_reason,
595 3213d3c8 Iustin Pop
                                    result.output))
596 06b78e8b Michael Hanselmann
597 06b78e8b Michael Hanselmann
    def _CheckInstance():
598 7dd106d3 Iustin Pop
      new_info = self.GetInstanceInfo(instance.name)
599 06b78e8b Michael Hanselmann
600 06b78e8b Michael Hanselmann
      # check if the domain ID has changed or the run time has decreased
601 e0561198 Iustin Pop
      if (new_info is not None and
602 e0561198 Iustin Pop
          (new_info[1] != ini_info[1] or new_info[5] < ini_info[5])):
603 06b78e8b Michael Hanselmann
        return
604 7dd106d3 Iustin Pop
605 06b78e8b Michael Hanselmann
      raise utils.RetryAgain()
606 06b78e8b Michael Hanselmann
607 06b78e8b Michael Hanselmann
    try:
608 06b78e8b Michael Hanselmann
      utils.Retry(_CheckInstance, self.REBOOT_RETRY_INTERVAL,
609 06b78e8b Michael Hanselmann
                  self.REBOOT_RETRY_INTERVAL * self.REBOOT_RETRY_COUNT)
610 06b78e8b Michael Hanselmann
    except utils.RetryTimeout:
611 7dd106d3 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s: instance"
612 7dd106d3 Iustin Pop
                                   " did not reboot in the expected interval" %
613 7dd106d3 Iustin Pop
                                   (instance.name, ))
614 65a6f9b7 Michael Hanselmann
615 2c7a0373 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
616 2c7a0373 Guido Trotter
    """Balloon an instance memory to a certain value.
617 2c7a0373 Guido Trotter

618 2c7a0373 Guido Trotter
    @type instance: L{objects.Instance}
619 2c7a0373 Guido Trotter
    @param instance: instance to be accepted
620 2c7a0373 Guido Trotter
    @type mem: int
621 2c7a0373 Guido Trotter
    @param mem: actual memory size to use for instance runtime
622 2c7a0373 Guido Trotter

623 2c7a0373 Guido Trotter
    """
624 3d942d8b Michael Hanselmann
    result = self._RunXen(["mem-set", instance.name, mem])
625 2c7a0373 Guido Trotter
    if result.failed:
626 2c7a0373 Guido Trotter
      raise errors.HypervisorError("Failed to balloon instance %s: %s (%s)" %
627 2c7a0373 Guido Trotter
                                   (instance.name, result.fail_reason,
628 2c7a0373 Guido Trotter
                                    result.output))
629 3d942d8b Michael Hanselmann
630 3d942d8b Michael Hanselmann
    # Update configuration file
631 2c7a0373 Guido Trotter
    cmd = ["sed", "-ie", "s/^memory.*$/memory = %s/" % mem]
632 0a903309 Michael Hanselmann
    cmd.append(self._ConfigFileName(instance.name))
633 3d942d8b Michael Hanselmann
634 2c7a0373 Guido Trotter
    result = utils.RunCmd(cmd)
635 2c7a0373 Guido Trotter
    if result.failed:
636 2c7a0373 Guido Trotter
      raise errors.HypervisorError("Failed to update memory for %s: %s (%s)" %
637 2c7a0373 Guido Trotter
                                   (instance.name, result.fail_reason,
638 2c7a0373 Guido Trotter
                                    result.output))
639 2c7a0373 Guido Trotter
640 65a6f9b7 Michael Hanselmann
  def GetNodeInfo(self):
641 65a6f9b7 Michael Hanselmann
    """Return information about the node.
642 65a6f9b7 Michael Hanselmann

643 06c9a520 Michael Hanselmann
    @see: L{_GetNodeInfo} and L{_ParseNodeInfo}
644 65a6f9b7 Michael Hanselmann

645 65a6f9b7 Michael Hanselmann
    """
646 3d942d8b Michael Hanselmann
    result = self._RunXen(["info"])
647 65a6f9b7 Michael Hanselmann
    if result.failed:
648 b48909c8 Iustin Pop
      logging.error("Can't run 'xm info' (%s): %s", result.fail_reason,
649 b48909c8 Iustin Pop
                    result.output)
650 65a6f9b7 Michael Hanselmann
      return None
651 65a6f9b7 Michael Hanselmann
652 06c9a520 Michael Hanselmann
    return _GetNodeInfo(result.stdout, self._GetXmList)
653 65a6f9b7 Michael Hanselmann
654 637ce7f9 Guido Trotter
  @classmethod
655 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
656 65a6f9b7 Michael Hanselmann
    """Return a command for connecting to the console of an instance.
657 65a6f9b7 Michael Hanselmann

658 65a6f9b7 Michael Hanselmann
    """
659 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
660 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_SSH,
661 55cc0a44 Michael Hanselmann
                                   host=instance.primary_node,
662 052783ff Michael Hanselmann
                                   user=constants.SSH_CONSOLE_USER,
663 b9612abb Iustin Pop
                                   command=[pathutils.XEN_CONSOLE_WRAPPER,
664 1f5557ca Guido Trotter
                                            constants.XEN_CMD, instance.name])
665 65a6f9b7 Michael Hanselmann
666 65a6f9b7 Michael Hanselmann
  def Verify(self):
667 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
668 65a6f9b7 Michael Hanselmann

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

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

673 65a6f9b7 Michael Hanselmann
    """
674 3d942d8b Michael Hanselmann
    result = self._RunXen(["info"])
675 e3e66f02 Michael Hanselmann
    if result.failed:
676 3213d3c8 Iustin Pop
      return "'xm info' failed: %s, %s" % (result.fail_reason, result.output)
677 65a6f9b7 Michael Hanselmann
678 cd04dfd2 Michael Hanselmann
    return None
679 cd04dfd2 Michael Hanselmann
680 4390ccff Guido Trotter
  def MigrationInfo(self, instance):
681 4390ccff Guido Trotter
    """Get instance information to perform a migration.
682 4390ccff Guido Trotter

683 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
684 4390ccff Guido Trotter
    @param instance: instance to be migrated
685 4390ccff Guido Trotter
    @rtype: string
686 4390ccff Guido Trotter
    @return: content of the xen config file
687 4390ccff Guido Trotter

688 4390ccff Guido Trotter
    """
689 4390ccff Guido Trotter
    return self._ReadConfigFile(instance.name)
690 4390ccff Guido Trotter
691 4390ccff Guido Trotter
  def AcceptInstance(self, instance, info, target):
692 4390ccff Guido Trotter
    """Prepare to accept an instance.
693 4390ccff Guido Trotter

694 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
695 4390ccff Guido Trotter
    @param instance: instance to be accepted
696 4390ccff Guido Trotter
    @type info: string
697 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
698 4390ccff Guido Trotter
    @type target: string
699 4390ccff Guido Trotter
    @param target: target host (usually ip), on this node
700 4390ccff Guido Trotter

701 4390ccff Guido Trotter
    """
702 4390ccff Guido Trotter
    pass
703 4390ccff Guido Trotter
704 60af751d Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
705 4390ccff Guido Trotter
    """Finalize an instance migration.
706 4390ccff Guido Trotter

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

710 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
711 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
712 4390ccff Guido Trotter
    @type info: string
713 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
714 4390ccff Guido Trotter
    @type success: boolean
715 4390ccff Guido Trotter
    @param success: whether the migration was a success or a failure
716 4390ccff Guido Trotter

717 4390ccff Guido Trotter
    """
718 4390ccff Guido Trotter
    if success:
719 c3d839f5 Michael Hanselmann
      self._WriteConfigFile(instance.name, info)
720 4390ccff Guido Trotter
721 6e7275c0 Iustin Pop
  def MigrateInstance(self, instance, target, live):
722 6e7275c0 Iustin Pop
    """Migrate an instance to a target node.
723 6e7275c0 Iustin Pop

724 6e7275c0 Iustin Pop
    The migration will not be attempted if the instance is not
725 6e7275c0 Iustin Pop
    currently running.
726 6e7275c0 Iustin Pop

727 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
728 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
729 fdf7f055 Guido Trotter
    @type target: string
730 fdf7f055 Guido Trotter
    @param target: ip address of the target node
731 fdf7f055 Guido Trotter
    @type live: boolean
732 fdf7f055 Guido Trotter
    @param live: perform a live migration
733 fdf7f055 Guido Trotter

734 6e7275c0 Iustin Pop
    """
735 d8784f7d Michael Hanselmann
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
736 d8784f7d Michael Hanselmann
737 d8784f7d Michael Hanselmann
    # TODO: Pass cluster name via RPC
738 d8784f7d Michael Hanselmann
    cluster_name = ssconf.SimpleStore().GetClusterName()
739 d8784f7d Michael Hanselmann
740 d8784f7d Michael Hanselmann
    return self._MigrateInstance(cluster_name, instance.name, target, port,
741 d8784f7d Michael Hanselmann
                                 live)
742 d8784f7d Michael Hanselmann
743 d8784f7d Michael Hanselmann
  def _MigrateInstance(self, cluster_name, instance_name, target, port, live,
744 d8784f7d Michael Hanselmann
                       _ping_fn=netutils.TcpPing):
745 d8784f7d Michael Hanselmann
    """Migrate an instance to a target node.
746 d8784f7d Michael Hanselmann

747 d8784f7d Michael Hanselmann
    @see: L{MigrateInstance} for details
748 d8784f7d Michael Hanselmann

749 d8784f7d Michael Hanselmann
    """
750 d8784f7d Michael Hanselmann
    if self.GetInstanceInfo(instance_name) is None:
751 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Instance not running, cannot migrate")
752 50716be0 Iustin Pop
753 d8784f7d Michael Hanselmann
    cmd = self._GetCommand()
754 50716be0 Iustin Pop
755 d8784f7d Michael Hanselmann
    if (cmd == constants.XEN_CMD_XM and
756 d8784f7d Michael Hanselmann
        not _ping_fn(target, port, live_port_needed=True)):
757 50716be0 Iustin Pop
      raise errors.HypervisorError("Remote host %s not listening on port"
758 50716be0 Iustin Pop
                                   " %s, cannot migrate" % (target, port))
759 50716be0 Iustin Pop
760 3d942d8b Michael Hanselmann
    args = ["migrate"]
761 3d942d8b Michael Hanselmann
762 d8784f7d Michael Hanselmann
    if cmd == constants.XEN_CMD_XM:
763 0625d08f René Nussbaumer
      args.extend(["-p", "%d" % port])
764 0625d08f René Nussbaumer
      if live:
765 0625d08f René Nussbaumer
        args.append("-l")
766 3d942d8b Michael Hanselmann
767 d8784f7d Michael Hanselmann
    elif cmd == constants.XEN_CMD_XL:
768 d8784f7d Michael Hanselmann
      args.extend([
769 d8784f7d Michael Hanselmann
        "-s", constants.XL_SSH_CMD % cluster_name,
770 d8784f7d Michael Hanselmann
        "-C", self._ConfigFileName(instance_name),
771 d8784f7d Michael Hanselmann
        ])
772 3d942d8b Michael Hanselmann
773 0625d08f René Nussbaumer
    else:
774 d8784f7d Michael Hanselmann
      raise errors.HypervisorError("Unsupported Xen command: %s" % self._cmd)
775 0625d08f René Nussbaumer
776 d8784f7d Michael Hanselmann
    args.extend([instance_name, target])
777 3d942d8b Michael Hanselmann
778 3d942d8b Michael Hanselmann
    result = self._RunXen(args)
779 6e7275c0 Iustin Pop
    if result.failed:
780 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Failed to migrate instance %s: %s" %
781 d8784f7d Michael Hanselmann
                                   (instance_name, result.output))
782 60af751d Andrea Spadaccini
783 60af751d Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
784 60af751d Andrea Spadaccini
    """Finalize the instance migration on the source node.
785 60af751d Andrea Spadaccini

786 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
787 60af751d Andrea Spadaccini
    @param instance: the instance that was migrated
788 60af751d Andrea Spadaccini
    @type success: bool
789 60af751d Andrea Spadaccini
    @param success: whether the migration succeeded or not
790 60af751d Andrea Spadaccini
    @type live: bool
791 60af751d Andrea Spadaccini
    @param live: whether the user requested a live migration or not
792 60af751d Andrea Spadaccini

793 60af751d Andrea Spadaccini
    """
794 60af751d Andrea Spadaccini
    # pylint: disable=W0613
795 60af751d Andrea Spadaccini
    if success:
796 60af751d Andrea Spadaccini
      # remove old xen file after migration succeeded
797 60af751d Andrea Spadaccini
      try:
798 60af751d Andrea Spadaccini
        self._RemoveConfigFile(instance.name)
799 60af751d Andrea Spadaccini
      except EnvironmentError:
800 60af751d Andrea Spadaccini
        logging.exception("Failure while removing instance config file")
801 60af751d Andrea Spadaccini
802 60af751d Andrea Spadaccini
  def GetMigrationStatus(self, instance):
803 60af751d Andrea Spadaccini
    """Get the migration status
804 60af751d Andrea Spadaccini

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

809 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
810 60af751d Andrea Spadaccini
    @param instance: the instance that is being migrated
811 60af751d Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
812 60af751d Andrea Spadaccini
    @return: the status of the current migration (one of
813 60af751d Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
814 60af751d Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
815 60af751d Andrea Spadaccini

816 60af751d Andrea Spadaccini
    """
817 60af751d Andrea Spadaccini
    return objects.MigrationStatus(status=constants.HV_MIGRATION_COMPLETED)
818 6e7275c0 Iustin Pop
819 f5118ade Iustin Pop
  @classmethod
820 f5118ade Iustin Pop
  def PowercycleNode(cls):
821 f5118ade Iustin Pop
    """Xen-specific powercycle.
822 f5118ade Iustin Pop

823 f5118ade Iustin Pop
    This first does a Linux reboot (which triggers automatically a Xen
824 f5118ade Iustin Pop
    reboot), and if that fails it tries to do a Xen reboot. The reason
825 f5118ade Iustin Pop
    we don't try a Xen reboot first is that the xen reboot launches an
826 f5118ade Iustin Pop
    external command which connects to the Xen hypervisor, and that
827 f5118ade Iustin Pop
    won't work in case the root filesystem is broken and/or the xend
828 f5118ade Iustin Pop
    daemon is not working.
829 f5118ade Iustin Pop

830 f5118ade Iustin Pop
    """
831 f5118ade Iustin Pop
    try:
832 f5118ade Iustin Pop
      cls.LinuxPowercycle()
833 f5118ade Iustin Pop
    finally:
834 2876c2d6 Guido Trotter
      utils.RunCmd([constants.XEN_CMD, "debug", "R"])
835 f5118ade Iustin Pop
836 65a6f9b7 Michael Hanselmann
837 65a6f9b7 Michael Hanselmann
class XenPvmHypervisor(XenHypervisor):
838 65a6f9b7 Michael Hanselmann
  """Xen PVM hypervisor interface"""
839 65a6f9b7 Michael Hanselmann
840 205ab586 Iustin Pop
  PARAMETERS = {
841 2f2dbb4b Jun Futagawa
    constants.HV_USE_BOOTLOADER: hv_base.NO_CHECK,
842 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_PATH: hv_base.OPT_FILE_CHECK,
843 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_ARGS: hv_base.NO_CHECK,
844 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.REQ_FILE_CHECK,
845 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
846 7adf7814 René Nussbaumer
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
847 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
848 e2d14329 Andrea Spadaccini
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
849 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
850 525011bc Maciej Bliziński
    # TODO: Add a check for the blockdev prefix (matching [a-z:] or similar).
851 525011bc Maciej Bliziński
    constants.HV_BLOCKDEV_PREFIX: hv_base.NO_CHECK,
852 990ade2d Stephen Shirley
    constants.HV_REBOOT_BEHAVIOR:
853 c4708267 Tsachy Shacham
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
854 c4708267 Tsachy Shacham
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
855 2c368f28 Guido Trotter
    constants.HV_CPU_CAP: hv_base.OPT_NONNEGATIVE_INT_CHECK,
856 8bd977e9 Sébastien Bocahu
    constants.HV_CPU_WEIGHT:
857 8bd977e9 Sébastien Bocahu
      (False, lambda x: 0 < x < 65536, "invalid weight", None, None),
858 205ab586 Iustin Pop
    }
859 f48148c3 Iustin Pop
860 c3d839f5 Michael Hanselmann
  def _GetConfig(self, instance, startup_memory, block_devices):
861 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
862 65a6f9b7 Michael Hanselmann

863 65a6f9b7 Michael Hanselmann
    """
864 a985b417 Iustin Pop
    hvp = instance.hvparams
865 65a6f9b7 Michael Hanselmann
    config = StringIO()
866 65a6f9b7 Michael Hanselmann
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
867 65a6f9b7 Michael Hanselmann
868 2f2dbb4b Jun Futagawa
    # if bootloader is True, use bootloader instead of kernel and ramdisk
869 2f2dbb4b Jun Futagawa
    # parameters.
870 2f2dbb4b Jun Futagawa
    if hvp[constants.HV_USE_BOOTLOADER]:
871 2f2dbb4b Jun Futagawa
      # bootloader handling
872 2f2dbb4b Jun Futagawa
      bootloader_path = hvp[constants.HV_BOOTLOADER_PATH]
873 2f2dbb4b Jun Futagawa
      if bootloader_path:
874 2f2dbb4b Jun Futagawa
        config.write("bootloader = '%s'\n" % bootloader_path)
875 2f2dbb4b Jun Futagawa
      else:
876 2f2dbb4b Jun Futagawa
        raise errors.HypervisorError("Bootloader enabled, but missing"
877 2f2dbb4b Jun Futagawa
                                     " bootloader path")
878 65a6f9b7 Michael Hanselmann
879 2f2dbb4b Jun Futagawa
      bootloader_args = hvp[constants.HV_BOOTLOADER_ARGS]
880 2f2dbb4b Jun Futagawa
      if bootloader_args:
881 2f2dbb4b Jun Futagawa
        config.write("bootargs = '%s'\n" % bootloader_args)
882 2f2dbb4b Jun Futagawa
    else:
883 2f2dbb4b Jun Futagawa
      # kernel handling
884 2f2dbb4b Jun Futagawa
      kpath = hvp[constants.HV_KERNEL_PATH]
885 2f2dbb4b Jun Futagawa
      config.write("kernel = '%s'\n" % kpath)
886 2f2dbb4b Jun Futagawa
887 2f2dbb4b Jun Futagawa
      # initrd handling
888 2f2dbb4b Jun Futagawa
      initrd_path = hvp[constants.HV_INITRD_PATH]
889 2f2dbb4b Jun Futagawa
      if initrd_path:
890 2f2dbb4b Jun Futagawa
        config.write("ramdisk = '%s'\n" % initrd_path)
891 65a6f9b7 Michael Hanselmann
892 65a6f9b7 Michael Hanselmann
    # rest of the settings
893 61eb1a46 Guido Trotter
    config.write("memory = %d\n" % startup_memory)
894 80121c83 Guido Trotter
    config.write("maxmem = %d\n" % instance.beparams[constants.BE_MAXMEM])
895 8b3fd458 Iustin Pop
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
896 347fa0f1 Michael Hanselmann
    cpu_pinning = _CreateConfigCpus(hvp[constants.HV_CPU_MASK])
897 c4708267 Tsachy Shacham
    if cpu_pinning:
898 c4708267 Tsachy Shacham
      config.write("%s\n" % cpu_pinning)
899 8bd977e9 Sébastien Bocahu
    cpu_cap = hvp[constants.HV_CPU_CAP]
900 8bd977e9 Sébastien Bocahu
    if cpu_cap:
901 8bd977e9 Sébastien Bocahu
      config.write("cpu_cap=%d\n" % cpu_cap)
902 8bd977e9 Sébastien Bocahu
    cpu_weight = hvp[constants.HV_CPU_WEIGHT]
903 8bd977e9 Sébastien Bocahu
    if cpu_weight:
904 8bd977e9 Sébastien Bocahu
      config.write("cpu_weight=%d\n" % cpu_weight)
905 c4708267 Tsachy Shacham
906 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
907 65a6f9b7 Michael Hanselmann
908 65a6f9b7 Michael Hanselmann
    vif_data = []
909 65a6f9b7 Michael Hanselmann
    for nic in instance.nics:
910 503b97a9 Guido Trotter
      nic_str = "mac=%s" % (nic.mac)
911 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
912 65a6f9b7 Michael Hanselmann
      if ip is not None:
913 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
914 503b97a9 Guido Trotter
      if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
915 503b97a9 Guido Trotter
        nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK]
916 0183a697 Alessandro Cincaglini
      vif_data.append("'%s'" % nic_str)
917 65a6f9b7 Michael Hanselmann
918 d0bb3f24 Michael Hanselmann
    disk_data = \
919 d0bb3f24 Michael Hanselmann
      _GetConfigFileDiskData(block_devices, hvp[constants.HV_BLOCKDEV_PREFIX])
920 7ed85ffe Iustin Pop
921 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
922 7ed85ffe Iustin Pop
    config.write("disk = [%s]\n" % ",".join(disk_data))
923 074ca009 Guido Trotter
924 7adf7814 René Nussbaumer
    if hvp[constants.HV_ROOT_PATH]:
925 7adf7814 René Nussbaumer
      config.write("root = '%s'\n" % hvp[constants.HV_ROOT_PATH])
926 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
927 990ade2d Stephen Shirley
    if hvp[constants.HV_REBOOT_BEHAVIOR] == constants.INSTANCE_REBOOT_ALLOWED:
928 990ade2d Stephen Shirley
      config.write("on_reboot = 'restart'\n")
929 990ade2d Stephen Shirley
    else:
930 990ade2d Stephen Shirley
      config.write("on_reboot = 'destroy'\n")
931 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
932 07813a9e Iustin Pop
    config.write("extra = '%s'\n" % hvp[constants.HV_KERNEL_ARGS])
933 73cd67f4 Guido Trotter
934 c3d839f5 Michael Hanselmann
    return config.getvalue()
935 65a6f9b7 Michael Hanselmann
936 65a6f9b7 Michael Hanselmann
937 65a6f9b7 Michael Hanselmann
class XenHvmHypervisor(XenHypervisor):
938 65a6f9b7 Michael Hanselmann
  """Xen HVM hypervisor interface"""
939 65a6f9b7 Michael Hanselmann
940 69b99987 Michael Hanselmann
  ANCILLARY_FILES = XenHypervisor.ANCILLARY_FILES + [
941 9d9bded1 Michael Hanselmann
    pathutils.VNC_PASSWORD_FILE,
942 69b99987 Michael Hanselmann
    ]
943 69ab2e12 Guido Trotter
  ANCILLARY_FILES_OPT = XenHypervisor.ANCILLARY_FILES_OPT + [
944 9d9bded1 Michael Hanselmann
    pathutils.VNC_PASSWORD_FILE,
945 69ab2e12 Guido Trotter
    ]
946 3680f662 Guido Trotter
947 205ab586 Iustin Pop
  PARAMETERS = {
948 205ab586 Iustin Pop
    constants.HV_ACPI: hv_base.NO_CHECK,
949 016d04b3 Michael Hanselmann
    constants.HV_BOOT_ORDER: (True, ) +
950 016d04b3 Michael Hanselmann
      (lambda x: x and len(x.strip("acdn")) == 0,
951 016d04b3 Michael Hanselmann
       "Invalid boot order specified, must be one or more of [acdn]",
952 016d04b3 Michael Hanselmann
       None, None),
953 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
954 016d04b3 Michael Hanselmann
    constants.HV_DISK_TYPE:
955 016d04b3 Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_HVM_VALID_DISK_TYPES),
956 016d04b3 Michael Hanselmann
    constants.HV_NIC_TYPE:
957 016d04b3 Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_HVM_VALID_NIC_TYPES),
958 205ab586 Iustin Pop
    constants.HV_PAE: hv_base.NO_CHECK,
959 016d04b3 Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS:
960 8b312c1d Manuel Franceschini
      (False, netutils.IP4Address.IsValid,
961 016d04b3 Michael Hanselmann
       "VNC bind address is not a valid IP address", None, None),
962 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.REQ_FILE_CHECK,
963 205ab586 Iustin Pop
    constants.HV_DEVICE_MODEL: hv_base.REQ_FILE_CHECK,
964 6e6bb8d5 Guido Trotter
    constants.HV_VNC_PASSWORD_FILE: hv_base.REQ_FILE_CHECK,
965 e2d14329 Andrea Spadaccini
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
966 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
967 6b970cef Jun Futagawa
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
968 e695efbf Iustin Pop
    # TODO: Add a check for the blockdev prefix (matching [a-z:] or similar).
969 e695efbf Iustin Pop
    constants.HV_BLOCKDEV_PREFIX: hv_base.NO_CHECK,
970 87f0aa48 Jack
    # Add PCI passthrough
971 3891c95e Bernardo Dal Seno
    constants.HV_PASSTHROUGH: hv_base.NO_CHECK,
972 990ade2d Stephen Shirley
    constants.HV_REBOOT_BEHAVIOR:
973 c4708267 Tsachy Shacham
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
974 c4708267 Tsachy Shacham
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
975 8bd977e9 Sébastien Bocahu
    constants.HV_CPU_CAP: hv_base.NO_CHECK,
976 8bd977e9 Sébastien Bocahu
    constants.HV_CPU_WEIGHT:
977 8bd977e9 Sébastien Bocahu
      (False, lambda x: 0 < x < 65535, "invalid weight", None, None),
978 05440845 Helga Velroyen
    constants.HV_VIF_TYPE:
979 05440845 Helga Velroyen
      hv_base.ParamInSet(False, constants.HT_HVM_VALID_VIF_TYPES),
980 ffc27116 Thomas Thrainer
    constants.HV_VIRIDIAN: hv_base.NO_CHECK,
981 205ab586 Iustin Pop
    }
982 09ea8710 Iustin Pop
983 c3d839f5 Michael Hanselmann
  def _GetConfig(self, instance, startup_memory, block_devices):
984 65a6f9b7 Michael Hanselmann
    """Create a Xen 3.1 HVM config file.
985 65a6f9b7 Michael Hanselmann

986 65a6f9b7 Michael Hanselmann
    """
987 a985b417 Iustin Pop
    hvp = instance.hvparams
988 a985b417 Iustin Pop
989 65a6f9b7 Michael Hanselmann
    config = StringIO()
990 e2ee1cea Iustin Pop
991 e2ee1cea Iustin Pop
    # kernel handling
992 e2ee1cea Iustin Pop
    kpath = hvp[constants.HV_KERNEL_PATH]
993 e2ee1cea Iustin Pop
    config.write("kernel = '%s'\n" % kpath)
994 e2ee1cea Iustin Pop
995 65a6f9b7 Michael Hanselmann
    config.write("builder = 'hvm'\n")
996 61eb1a46 Guido Trotter
    config.write("memory = %d\n" % startup_memory)
997 80121c83 Guido Trotter
    config.write("maxmem = %d\n" % instance.beparams[constants.BE_MAXMEM])
998 8b3fd458 Iustin Pop
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
999 347fa0f1 Michael Hanselmann
    cpu_pinning = _CreateConfigCpus(hvp[constants.HV_CPU_MASK])
1000 c4708267 Tsachy Shacham
    if cpu_pinning:
1001 c4708267 Tsachy Shacham
      config.write("%s\n" % cpu_pinning)
1002 8bd977e9 Sébastien Bocahu
    cpu_cap = hvp[constants.HV_CPU_CAP]
1003 8bd977e9 Sébastien Bocahu
    if cpu_cap:
1004 8bd977e9 Sébastien Bocahu
      config.write("cpu_cap=%d\n" % cpu_cap)
1005 8bd977e9 Sébastien Bocahu
    cpu_weight = hvp[constants.HV_CPU_WEIGHT]
1006 8bd977e9 Sébastien Bocahu
    if cpu_weight:
1007 8bd977e9 Sébastien Bocahu
      config.write("cpu_weight=%d\n" % cpu_weight)
1008 c4708267 Tsachy Shacham
1009 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
1010 09ea8710 Iustin Pop
    if hvp[constants.HV_PAE]:
1011 a21dda8b Iustin Pop
      config.write("pae = 1\n")
1012 a21dda8b Iustin Pop
    else:
1013 a21dda8b Iustin Pop
      config.write("pae = 0\n")
1014 09ea8710 Iustin Pop
    if hvp[constants.HV_ACPI]:
1015 a21dda8b Iustin Pop
      config.write("acpi = 1\n")
1016 a21dda8b Iustin Pop
    else:
1017 a21dda8b Iustin Pop
      config.write("acpi = 0\n")
1018 ffc27116 Thomas Thrainer
    if hvp[constants.HV_VIRIDIAN]:
1019 ffc27116 Thomas Thrainer
      config.write("viridian = 1\n")
1020 ffc27116 Thomas Thrainer
    else:
1021 ffc27116 Thomas Thrainer
      config.write("viridian = 0\n")
1022 ffc27116 Thomas Thrainer
1023 65a6f9b7 Michael Hanselmann
    config.write("apic = 1\n")
1024 09ea8710 Iustin Pop
    config.write("device_model = '%s'\n" % hvp[constants.HV_DEVICE_MODEL])
1025 a985b417 Iustin Pop
    config.write("boot = '%s'\n" % hvp[constants.HV_BOOT_ORDER])
1026 65a6f9b7 Michael Hanselmann
    config.write("sdl = 0\n")
1027 97efde45 Guido Trotter
    config.write("usb = 1\n")
1028 97efde45 Guido Trotter
    config.write("usbdevice = 'tablet'\n")
1029 65a6f9b7 Michael Hanselmann
    config.write("vnc = 1\n")
1030 a985b417 Iustin Pop
    if hvp[constants.HV_VNC_BIND_ADDRESS] is None:
1031 d0c11cf7 Alexander Schreiber
      config.write("vnclisten = '%s'\n" % constants.VNC_DEFAULT_BIND_ADDRESS)
1032 d0c11cf7 Alexander Schreiber
    else:
1033 6b405598 Guido Trotter
      config.write("vnclisten = '%s'\n" % hvp[constants.HV_VNC_BIND_ADDRESS])
1034 65a6f9b7 Michael Hanselmann
1035 377d74c9 Guido Trotter
    if instance.network_port > constants.VNC_BASE_PORT:
1036 377d74c9 Guido Trotter
      display = instance.network_port - constants.VNC_BASE_PORT
1037 65a6f9b7 Michael Hanselmann
      config.write("vncdisplay = %s\n" % display)
1038 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 0\n")
1039 65a6f9b7 Michael Hanselmann
    else:
1040 65a6f9b7 Michael Hanselmann
      config.write("# vncdisplay = 1\n")
1041 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 1\n")
1042 65a6f9b7 Michael Hanselmann
1043 6e6bb8d5 Guido Trotter
    vnc_pwd_file = hvp[constants.HV_VNC_PASSWORD_FILE]
1044 65a6f9b7 Michael Hanselmann
    try:
1045 6e6bb8d5 Guido Trotter
      password = utils.ReadFile(vnc_pwd_file)
1046 78f66a17 Guido Trotter
    except EnvironmentError, err:
1047 78f66a17 Guido Trotter
      raise errors.HypervisorError("Failed to open VNC password file %s: %s" %
1048 6e6bb8d5 Guido Trotter
                                   (vnc_pwd_file, err))
1049 65a6f9b7 Michael Hanselmann
1050 65a6f9b7 Michael Hanselmann
    config.write("vncpasswd = '%s'\n" % password.rstrip())
1051 65a6f9b7 Michael Hanselmann
1052 65a6f9b7 Michael Hanselmann
    config.write("serial = 'pty'\n")
1053 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
1054 6b970cef Jun Futagawa
      config.write("localtime = 1\n")
1055 65a6f9b7 Michael Hanselmann
1056 65a6f9b7 Michael Hanselmann
    vif_data = []
1057 05440845 Helga Velroyen
    # Note: what is called 'nic_type' here, is used as value for the xen nic
1058 05440845 Helga Velroyen
    # vif config parameter 'model'. For the xen nic vif parameter 'type', we use
1059 05440845 Helga Velroyen
    # the 'vif_type' to avoid a clash of notation.
1060 a985b417 Iustin Pop
    nic_type = hvp[constants.HV_NIC_TYPE]
1061 05440845 Helga Velroyen
1062 f48148c3 Iustin Pop
    if nic_type is None:
1063 05440845 Helga Velroyen
      vif_type_str = ""
1064 05440845 Helga Velroyen
      if hvp[constants.HV_VIF_TYPE]:
1065 05440845 Helga Velroyen
        vif_type_str = ", type=%s" % hvp[constants.HV_VIF_TYPE]
1066 f48148c3 Iustin Pop
      # ensure old instances don't change
1067 05440845 Helga Velroyen
      nic_type_str = vif_type_str
1068 d08f6067 Guido Trotter
    elif nic_type == constants.HT_NIC_PARAVIRTUAL:
1069 f48148c3 Iustin Pop
      nic_type_str = ", type=paravirtualized"
1070 f48148c3 Iustin Pop
    else:
1071 05440845 Helga Velroyen
      # parameter 'model' is only valid with type 'ioemu'
1072 05440845 Helga Velroyen
      nic_type_str = ", model=%s, type=%s" % \
1073 05440845 Helga Velroyen
        (nic_type, constants.HT_HVM_VIF_IOEMU)
1074 65a6f9b7 Michael Hanselmann
    for nic in instance.nics:
1075 503b97a9 Guido Trotter
      nic_str = "mac=%s%s" % (nic.mac, nic_type_str)
1076 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
1077 65a6f9b7 Michael Hanselmann
      if ip is not None:
1078 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
1079 503b97a9 Guido Trotter
      if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1080 503b97a9 Guido Trotter
        nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK]
1081 0183a697 Alessandro Cincaglini
      vif_data.append("'%s'" % nic_str)
1082 65a6f9b7 Michael Hanselmann
1083 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
1084 525011bc Maciej Bliziński
1085 d0bb3f24 Michael Hanselmann
    disk_data = \
1086 d0bb3f24 Michael Hanselmann
      _GetConfigFileDiskData(block_devices, hvp[constants.HV_BLOCKDEV_PREFIX])
1087 525011bc Maciej Bliziński
1088 a985b417 Iustin Pop
    iso_path = hvp[constants.HV_CDROM_IMAGE_PATH]
1089 f48148c3 Iustin Pop
    if iso_path:
1090 f48148c3 Iustin Pop
      iso = "'file:%s,hdc:cdrom,r'" % iso_path
1091 a21dda8b Iustin Pop
      disk_data.append(iso)
1092 a21dda8b Iustin Pop
1093 a21dda8b Iustin Pop
    config.write("disk = [%s]\n" % (",".join(disk_data)))
1094 87f0aa48 Jack
    # Add PCI passthrough
1095 87f0aa48 Jack
    pci_pass_arr = []
1096 87f0aa48 Jack
    pci_pass = hvp[constants.HV_PASSTHROUGH]
1097 87f0aa48 Jack
    if pci_pass:
1098 3891c95e Bernardo Dal Seno
      pci_pass_arr = pci_pass.split(";")
1099 3891c95e Bernardo Dal Seno
      config.write("pci = %s\n" % pci_pass_arr)
1100 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
1101 990ade2d Stephen Shirley
    if hvp[constants.HV_REBOOT_BEHAVIOR] == constants.INSTANCE_REBOOT_ALLOWED:
1102 990ade2d Stephen Shirley
      config.write("on_reboot = 'restart'\n")
1103 990ade2d Stephen Shirley
    else:
1104 990ade2d Stephen Shirley
      config.write("on_reboot = 'destroy'\n")
1105 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
1106 73cd67f4 Guido Trotter
1107 c3d839f5 Michael Hanselmann
    return config.getvalue()