Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ 364c350f

History | View | Annotate | Download (34.6 kB)

1 65a6f9b7 Michael Hanselmann
#
2 65a6f9b7 Michael Hanselmann
#
3 65a6f9b7 Michael Hanselmann
4 1a63f285 Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Google Inc.
5 65a6f9b7 Michael Hanselmann
#
6 65a6f9b7 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 65a6f9b7 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 65a6f9b7 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 65a6f9b7 Michael Hanselmann
# (at your option) any later version.
10 65a6f9b7 Michael Hanselmann
#
11 65a6f9b7 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 65a6f9b7 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 65a6f9b7 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 65a6f9b7 Michael Hanselmann
# General Public License for more details.
15 65a6f9b7 Michael Hanselmann
#
16 65a6f9b7 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 65a6f9b7 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 65a6f9b7 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 65a6f9b7 Michael Hanselmann
# 02110-1301, USA.
20 65a6f9b7 Michael Hanselmann
21 65a6f9b7 Michael Hanselmann
22 65a6f9b7 Michael Hanselmann
"""Xen hypervisors
23 65a6f9b7 Michael Hanselmann

24 65a6f9b7 Michael Hanselmann
"""
25 65a6f9b7 Michael Hanselmann
26 b48909c8 Iustin Pop
import logging
27 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 d0bb3f24 Michael Hanselmann
  }
51 22d568c2 Guido Trotter
52 22d568c2 Guido Trotter
53 347fa0f1 Michael Hanselmann
def _CreateConfigCpus(cpu_mask):
54 347fa0f1 Michael Hanselmann
  """Create a CPU config string for Xen's config file.
55 347fa0f1 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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