Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ 31d3b918

History | View | Annotate | Download (45.1 kB)

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

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

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

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

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

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

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

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

153 b255379d Michael Hanselmann
  """
154 ff19ac20 Helga Velroyen
  instance_list_errors = []
155 b255379d Michael Hanselmann
  try:
156 ff19ac20 Helga Velroyen
    lines = utils.Retry(_RunInstanceList, (0.3, 1.5, 1.0), _timeout,
157 ff19ac20 Helga Velroyen
                        args=(fn, instance_list_errors))
158 b255379d Michael Hanselmann
  except utils.RetryTimeout:
159 ff19ac20 Helga Velroyen
    if instance_list_errors:
160 ff19ac20 Helga Velroyen
      instance_list_result = instance_list_errors.pop()
161 b255379d Michael Hanselmann
162 ff19ac20 Helga Velroyen
      errmsg = ("listing instances failed, timeout exceeded (%s): %s" %
163 ff19ac20 Helga Velroyen
                (instance_list_result.fail_reason, instance_list_result.output))
164 b255379d Michael Hanselmann
    else:
165 ff19ac20 Helga Velroyen
      errmsg = "listing instances failed"
166 b255379d Michael Hanselmann
167 b255379d Michael Hanselmann
    raise errors.HypervisorError(errmsg)
168 b255379d Michael Hanselmann
169 2609da63 Helga Velroyen
  return _ParseInstanceList(lines, include_node)
170 b255379d Michael Hanselmann
171 b255379d Michael Hanselmann
172 fd201010 Jose A. Lopes
# Determine whether an instance is running
173 fd201010 Jose A. Lopes
#
174 fd201010 Jose A. Lopes
# An instance is running if it is in the following Xen states:
175 fd201010 Jose A. Lopes
# running, blocked, or paused.
176 9d22cc90 Jose A. Lopes
def _IsInstanceRunning(instance_info):
177 9d22cc90 Jose A. Lopes
  return instance_info == "r-----" \
178 fd201010 Jose A. Lopes
      or instance_info == "-b----" \
179 fd201010 Jose A. Lopes
      or instance_info == "--p---"
180 9d22cc90 Jose A. Lopes
181 9d22cc90 Jose A. Lopes
182 9d22cc90 Jose A. Lopes
def _IsInstanceShutdown(instance_info):
183 9d22cc90 Jose A. Lopes
  return instance_info == "---s--"
184 9d22cc90 Jose A. Lopes
185 9d22cc90 Jose A. Lopes
186 9d22cc90 Jose A. Lopes
def _XenToHypervisorInstanceState(instance_info):
187 9d22cc90 Jose A. Lopes
  if _IsInstanceRunning(instance_info):
188 9d22cc90 Jose A. Lopes
    return hv_base.HvInstanceState.RUNNING
189 9d22cc90 Jose A. Lopes
  elif _IsInstanceShutdown(instance_info):
190 9d22cc90 Jose A. Lopes
    return hv_base.HvInstanceState.SHUTDOWN
191 9d22cc90 Jose A. Lopes
  else:
192 9d22cc90 Jose A. Lopes
    raise errors.HypervisorError("hv_xen._XenToHypervisorInstanceState:"
193 9d22cc90 Jose A. Lopes
                                 " unhandled Xen instance state '%s'" %
194 9d22cc90 Jose A. Lopes
                                   instance_info)
195 9d22cc90 Jose A. Lopes
196 9d22cc90 Jose A. Lopes
197 9d22cc90 Jose A. Lopes
def _GetRunningInstanceList(fn, include_node, _timeout=5):
198 9d22cc90 Jose A. Lopes
  """Return the list of running instances.
199 9d22cc90 Jose A. Lopes

200 9d22cc90 Jose A. Lopes
  See L{_GetAllInstanceList} for parameter details.
201 9d22cc90 Jose A. Lopes

202 9d22cc90 Jose A. Lopes
  """
203 9d22cc90 Jose A. Lopes
  instances = _GetAllInstanceList(fn, include_node, _timeout)
204 9d22cc90 Jose A. Lopes
  return [i for i in instances if hv_base.HvInstanceState.IsRunning(i[4])]
205 9d22cc90 Jose A. Lopes
206 9d22cc90 Jose A. Lopes
207 9d22cc90 Jose A. Lopes
def _GetShutdownInstanceList(fn, include_node, _timeout=5):
208 9d22cc90 Jose A. Lopes
  """Return the list of shutdown instances.
209 9d22cc90 Jose A. Lopes

210 9d22cc90 Jose A. Lopes
  See L{_GetAllInstanceList} for parameter details.
211 9d22cc90 Jose A. Lopes

212 9d22cc90 Jose A. Lopes
  """
213 9d22cc90 Jose A. Lopes
  instances = _GetAllInstanceList(fn, include_node, _timeout)
214 9d22cc90 Jose A. Lopes
  return [i for i in instances if hv_base.HvInstanceState.IsShutdown(i[4])]
215 9d22cc90 Jose A. Lopes
216 9d22cc90 Jose A. Lopes
217 06c9a520 Michael Hanselmann
def _ParseNodeInfo(info):
218 06c9a520 Michael Hanselmann
  """Return information about the node.
219 06c9a520 Michael Hanselmann

220 06c9a520 Michael Hanselmann
  @return: a dict with the following keys (memory values in MiB):
221 06c9a520 Michael Hanselmann
        - memory_total: the total memory size on the node
222 06c9a520 Michael Hanselmann
        - memory_free: the available memory on the node for instances
223 06c9a520 Michael Hanselmann
        - nr_cpus: total number of CPUs
224 06c9a520 Michael Hanselmann
        - nr_nodes: in a NUMA system, the number of domains
225 06c9a520 Michael Hanselmann
        - nr_sockets: the number of physical CPU sockets in the node
226 06c9a520 Michael Hanselmann
        - hv_version: the hypervisor version in the form (major, minor)
227 06c9a520 Michael Hanselmann

228 06c9a520 Michael Hanselmann
  """
229 06c9a520 Michael Hanselmann
  result = {}
230 06c9a520 Michael Hanselmann
  cores_per_socket = threads_per_core = nr_cpus = None
231 06c9a520 Michael Hanselmann
  xen_major, xen_minor = None, None
232 06c9a520 Michael Hanselmann
  memory_total = None
233 06c9a520 Michael Hanselmann
  memory_free = None
234 06c9a520 Michael Hanselmann
235 06c9a520 Michael Hanselmann
  for line in info.splitlines():
236 06c9a520 Michael Hanselmann
    fields = line.split(":", 1)
237 06c9a520 Michael Hanselmann
238 06c9a520 Michael Hanselmann
    if len(fields) < 2:
239 06c9a520 Michael Hanselmann
      continue
240 06c9a520 Michael Hanselmann
241 06c9a520 Michael Hanselmann
    (key, val) = map(lambda s: s.strip(), fields)
242 06c9a520 Michael Hanselmann
243 06c9a520 Michael Hanselmann
    # Note: in Xen 3, memory has changed to total_memory
244 06c9a520 Michael Hanselmann
    if key in ("memory", "total_memory"):
245 06c9a520 Michael Hanselmann
      memory_total = int(val)
246 06c9a520 Michael Hanselmann
    elif key == "free_memory":
247 06c9a520 Michael Hanselmann
      memory_free = int(val)
248 06c9a520 Michael Hanselmann
    elif key == "nr_cpus":
249 06c9a520 Michael Hanselmann
      nr_cpus = result["cpu_total"] = int(val)
250 06c9a520 Michael Hanselmann
    elif key == "nr_nodes":
251 06c9a520 Michael Hanselmann
      result["cpu_nodes"] = int(val)
252 06c9a520 Michael Hanselmann
    elif key == "cores_per_socket":
253 06c9a520 Michael Hanselmann
      cores_per_socket = int(val)
254 06c9a520 Michael Hanselmann
    elif key == "threads_per_core":
255 06c9a520 Michael Hanselmann
      threads_per_core = int(val)
256 06c9a520 Michael Hanselmann
    elif key == "xen_major":
257 06c9a520 Michael Hanselmann
      xen_major = int(val)
258 06c9a520 Michael Hanselmann
    elif key == "xen_minor":
259 06c9a520 Michael Hanselmann
      xen_minor = int(val)
260 06c9a520 Michael Hanselmann
261 06c9a520 Michael Hanselmann
  if None not in [cores_per_socket, threads_per_core, nr_cpus]:
262 06c9a520 Michael Hanselmann
    result["cpu_sockets"] = nr_cpus / (cores_per_socket * threads_per_core)
263 06c9a520 Michael Hanselmann
264 06c9a520 Michael Hanselmann
  if memory_free is not None:
265 06c9a520 Michael Hanselmann
    result["memory_free"] = memory_free
266 06c9a520 Michael Hanselmann
267 06c9a520 Michael Hanselmann
  if memory_total is not None:
268 06c9a520 Michael Hanselmann
    result["memory_total"] = memory_total
269 06c9a520 Michael Hanselmann
270 06c9a520 Michael Hanselmann
  if not (xen_major is None or xen_minor is None):
271 06c9a520 Michael Hanselmann
    result[constants.HV_NODEINFO_KEY_VERSION] = (xen_major, xen_minor)
272 06c9a520 Michael Hanselmann
273 06c9a520 Michael Hanselmann
  return result
274 06c9a520 Michael Hanselmann
275 06c9a520 Michael Hanselmann
276 fac489a5 Helga Velroyen
def _MergeInstanceInfo(info, instance_list):
277 06c9a520 Michael Hanselmann
  """Updates node information from L{_ParseNodeInfo} with instance info.
278 06c9a520 Michael Hanselmann

279 06c9a520 Michael Hanselmann
  @type info: dict
280 06c9a520 Michael Hanselmann
  @param info: Result from L{_ParseNodeInfo}
281 fac489a5 Helga Velroyen
  @type instance_list: list of tuples
282 fac489a5 Helga Velroyen
  @param instance_list: list of instance information; one tuple per instance
283 06c9a520 Michael Hanselmann
  @rtype: dict
284 06c9a520 Michael Hanselmann

285 06c9a520 Michael Hanselmann
  """
286 06c9a520 Michael Hanselmann
  total_instmem = 0
287 06c9a520 Michael Hanselmann
288 fac489a5 Helga Velroyen
  for (name, _, mem, vcpus, _, _) in instance_list:
289 06c9a520 Michael Hanselmann
    if name == _DOM0_NAME:
290 06c9a520 Michael Hanselmann
      info["memory_dom0"] = mem
291 ff05ff94 Bernardo Dal Seno
      info["cpu_dom0"] = vcpus
292 06c9a520 Michael Hanselmann
293 06c9a520 Michael Hanselmann
    # Include Dom0 in total memory usage
294 06c9a520 Michael Hanselmann
    total_instmem += mem
295 06c9a520 Michael Hanselmann
296 06c9a520 Michael Hanselmann
  memory_free = info.get("memory_free")
297 06c9a520 Michael Hanselmann
  memory_total = info.get("memory_total")
298 06c9a520 Michael Hanselmann
299 06c9a520 Michael Hanselmann
  # Calculate memory used by hypervisor
300 06c9a520 Michael Hanselmann
  if None not in [memory_total, memory_free, total_instmem]:
301 06c9a520 Michael Hanselmann
    info["memory_hv"] = memory_total - memory_free - total_instmem
302 06c9a520 Michael Hanselmann
303 06c9a520 Michael Hanselmann
  return info
304 06c9a520 Michael Hanselmann
305 06c9a520 Michael Hanselmann
306 fac489a5 Helga Velroyen
def _GetNodeInfo(info, instance_list):
307 06c9a520 Michael Hanselmann
  """Combines L{_MergeInstanceInfo} and L{_ParseNodeInfo}.
308 06c9a520 Michael Hanselmann

309 fac489a5 Helga Velroyen
  @type instance_list: list of tuples
310 fac489a5 Helga Velroyen
  @param instance_list: list of instance information; one tuple per instance
311 fac489a5 Helga Velroyen

312 06c9a520 Michael Hanselmann
  """
313 fac489a5 Helga Velroyen
  return _MergeInstanceInfo(_ParseNodeInfo(info), instance_list)
314 06c9a520 Michael Hanselmann
315 06c9a520 Michael Hanselmann
316 d0bb3f24 Michael Hanselmann
def _GetConfigFileDiskData(block_devices, blockdev_prefix,
317 d0bb3f24 Michael Hanselmann
                           _letters=_DISK_LETTERS):
318 d0bb3f24 Michael Hanselmann
  """Get disk directives for Xen config file.
319 d0bb3f24 Michael Hanselmann

320 d0bb3f24 Michael Hanselmann
  This method builds the xen config disk directive according to the
321 d0bb3f24 Michael Hanselmann
  given disk_template and block_devices.
322 d0bb3f24 Michael Hanselmann

323 d0bb3f24 Michael Hanselmann
  @param block_devices: list of tuples (cfdev, rldev):
324 d0bb3f24 Michael Hanselmann
      - cfdev: dict containing ganeti config disk part
325 ce9283c1 Thomas Thrainer
      - rldev: ganeti.block.bdev.BlockDev object
326 d0bb3f24 Michael Hanselmann
  @param blockdev_prefix: a string containing blockdevice prefix,
327 d0bb3f24 Michael Hanselmann
                          e.g. "sd" for /dev/sda
328 d0bb3f24 Michael Hanselmann

329 d0bb3f24 Michael Hanselmann
  @return: string containing disk directive for xen instance config file
330 d0bb3f24 Michael Hanselmann

331 d0bb3f24 Michael Hanselmann
  """
332 d0bb3f24 Michael Hanselmann
  if len(block_devices) > len(_letters):
333 d0bb3f24 Michael Hanselmann
    raise errors.HypervisorError("Too many disks")
334 d0bb3f24 Michael Hanselmann
335 d0bb3f24 Michael Hanselmann
  disk_data = []
336 d0bb3f24 Michael Hanselmann
337 117a85a0 Raffa Santi
  for sd_suffix, (cfdev, dev_path, _) in zip(_letters, block_devices):
338 d0bb3f24 Michael Hanselmann
    sd_name = blockdev_prefix + sd_suffix
339 d0bb3f24 Michael Hanselmann
340 d0bb3f24 Michael Hanselmann
    if cfdev.mode == constants.DISK_RDWR:
341 d0bb3f24 Michael Hanselmann
      mode = "w"
342 d0bb3f24 Michael Hanselmann
    else:
343 d0bb3f24 Michael Hanselmann
      mode = "r"
344 d0bb3f24 Michael Hanselmann
345 a09639d1 Santi Raffa
    if cfdev.dev_type in constants.DTS_FILEBASED:
346 a57e502a Thomas Thrainer
      driver = _FILE_DRIVER_MAP[cfdev.logical_id[0]]
347 d0bb3f24 Michael Hanselmann
    else:
348 d0bb3f24 Michael Hanselmann
      driver = "phy"
349 d0bb3f24 Michael Hanselmann
350 d0bb3f24 Michael Hanselmann
    disk_data.append("'%s:%s,%s,%s'" % (driver, dev_path, sd_name, mode))
351 d0bb3f24 Michael Hanselmann
352 d0bb3f24 Michael Hanselmann
  return disk_data
353 d0bb3f24 Michael Hanselmann
354 d0bb3f24 Michael Hanselmann
355 295ed29b Santi Raffa
def _QuoteCpuidField(data):
356 295ed29b Santi Raffa
  """Add quotes around the CPUID field only if necessary.
357 295ed29b Santi Raffa

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

361 295ed29b Santi Raffa
  @param data: Either type of parameter.
362 295ed29b Santi Raffa
  @return: The quoted version thereof.
363 295ed29b Santi Raffa

364 295ed29b Santi Raffa
  """
365 295ed29b Santi Raffa
  return "'%s'" % data if data.startswith("host") else data
366 295ed29b Santi Raffa
367 295ed29b Santi Raffa
368 a2d32034 Michael Hanselmann
class XenHypervisor(hv_base.BaseHypervisor):
369 65a6f9b7 Michael Hanselmann
  """Xen generic hypervisor interface
370 65a6f9b7 Michael Hanselmann

371 65a6f9b7 Michael Hanselmann
  This is the Xen base class used for both Xen PVM and HVM. It contains
372 65a6f9b7 Michael Hanselmann
  all the functionality that is identical for both.
373 65a6f9b7 Michael Hanselmann

374 65a6f9b7 Michael Hanselmann
  """
375 d271c6fd Iustin Pop
  CAN_MIGRATE = True
376 7dd106d3 Iustin Pop
  REBOOT_RETRY_COUNT = 60
377 7dd106d3 Iustin Pop
  REBOOT_RETRY_INTERVAL = 10
378 397b7844 Dimitris Aragiorgis
  _ROOT_DIR = pathutils.RUN_DIR + "/xen-hypervisor"
379 397b7844 Dimitris Aragiorgis
  _NICS_DIR = _ROOT_DIR + "/nic" # contains NICs' info
380 397b7844 Dimitris Aragiorgis
  _DIRS = [_ROOT_DIR, _NICS_DIR]
381 65a6f9b7 Michael Hanselmann
382 3680f662 Guido Trotter
  ANCILLARY_FILES = [
383 22d568c2 Guido Trotter
    XEND_CONFIG_FILE,
384 22d568c2 Guido Trotter
    XL_CONFIG_FILE,
385 22d568c2 Guido Trotter
    VIF_BRIDGE_SCRIPT,
386 3680f662 Guido Trotter
    ]
387 69ab2e12 Guido Trotter
  ANCILLARY_FILES_OPT = [
388 69ab2e12 Guido Trotter
    XL_CONFIG_FILE,
389 3680f662 Guido Trotter
    ]
390 3680f662 Guido Trotter
391 3d942d8b Michael Hanselmann
  def __init__(self, _cfgdir=None, _run_cmd_fn=None, _cmd=None):
392 0a903309 Michael Hanselmann
    hv_base.BaseHypervisor.__init__(self)
393 0a903309 Michael Hanselmann
394 0a903309 Michael Hanselmann
    if _cfgdir is None:
395 0a903309 Michael Hanselmann
      self._cfgdir = pathutils.XEN_CONFIG_DIR
396 0a903309 Michael Hanselmann
    else:
397 0a903309 Michael Hanselmann
      self._cfgdir = _cfgdir
398 0a903309 Michael Hanselmann
399 3d942d8b Michael Hanselmann
    if _run_cmd_fn is None:
400 3d942d8b Michael Hanselmann
      self._run_cmd_fn = utils.RunCmd
401 3d942d8b Michael Hanselmann
    else:
402 3d942d8b Michael Hanselmann
      self._run_cmd_fn = _run_cmd_fn
403 3d942d8b Michael Hanselmann
404 3d942d8b Michael Hanselmann
    self._cmd = _cmd
405 3d942d8b Michael Hanselmann
406 f92d9674 Helga Velroyen
  @staticmethod
407 f92d9674 Helga Velroyen
  def _GetCommandFromHvparams(hvparams):
408 f92d9674 Helga Velroyen
    """Returns the Xen command extracted from the given hvparams.
409 f92d9674 Helga Velroyen

410 f92d9674 Helga Velroyen
    @type hvparams: dict of strings
411 f92d9674 Helga Velroyen
    @param hvparams: hypervisor parameters
412 f92d9674 Helga Velroyen

413 f92d9674 Helga Velroyen
    """
414 f92d9674 Helga Velroyen
    if hvparams is None or constants.HV_XEN_CMD not in hvparams:
415 f92d9674 Helga Velroyen
      raise errors.HypervisorError("Cannot determine xen command.")
416 f92d9674 Helga Velroyen
    else:
417 f92d9674 Helga Velroyen
      return hvparams[constants.HV_XEN_CMD]
418 f92d9674 Helga Velroyen
419 398fd4f6 Helga Velroyen
  def _GetCommand(self, hvparams):
420 d8784f7d Michael Hanselmann
    """Returns Xen command to use.
421 d8784f7d Michael Hanselmann

422 51a95d00 Helga Velroyen
    @type hvparams: dict of strings
423 51a95d00 Helga Velroyen
    @param hvparams: hypervisor parameters
424 51a95d00 Helga Velroyen

425 d8784f7d Michael Hanselmann
    """
426 3d942d8b Michael Hanselmann
    if self._cmd is None:
427 f92d9674 Helga Velroyen
      cmd = XenHypervisor._GetCommandFromHvparams(hvparams)
428 3d942d8b Michael Hanselmann
    else:
429 3d942d8b Michael Hanselmann
      cmd = self._cmd
430 3d942d8b Michael Hanselmann
431 3d942d8b Michael Hanselmann
    if cmd not in constants.KNOWN_XEN_COMMANDS:
432 3d942d8b Michael Hanselmann
      raise errors.ProgrammerError("Unknown Xen command '%s'" % cmd)
433 3d942d8b Michael Hanselmann
434 3d942d8b Michael Hanselmann
    return cmd
435 3d942d8b Michael Hanselmann
436 398fd4f6 Helga Velroyen
  def _RunXen(self, args, hvparams):
437 81124130 Michael Hanselmann
    """Wrapper around L{utils.process.RunCmd} to run Xen command.
438 3d942d8b Michael Hanselmann

439 58e356a9 Helga Velroyen
    @type hvparams: dict of strings
440 58e356a9 Helga Velroyen
    @param hvparams: dictionary of hypervisor params
441 81124130 Michael Hanselmann
    @see: L{utils.process.RunCmd}
442 3d942d8b Michael Hanselmann

443 3d942d8b Michael Hanselmann
    """
444 398fd4f6 Helga Velroyen
    cmd = [self._GetCommand(hvparams)]
445 3d942d8b Michael Hanselmann
    cmd.extend(args)
446 3d942d8b Michael Hanselmann
447 3d942d8b Michael Hanselmann
    return self._run_cmd_fn(cmd)
448 3d942d8b Michael Hanselmann
449 0a903309 Michael Hanselmann
  def _ConfigFileName(self, instance_name):
450 c2be2532 Guido Trotter
    """Get the config file name for an instance.
451 c2be2532 Guido Trotter

452 c2be2532 Guido Trotter
    @param instance_name: instance name
453 c2be2532 Guido Trotter
    @type instance_name: str
454 c2be2532 Guido Trotter
    @return: fully qualified path to instance config file
455 c2be2532 Guido Trotter
    @rtype: str
456 c2be2532 Guido Trotter

457 c2be2532 Guido Trotter
    """
458 0a903309 Michael Hanselmann
    return utils.PathJoin(self._cfgdir, instance_name)
459 c2be2532 Guido Trotter
460 5661b908 Iustin Pop
  @classmethod
461 2a3bbbaa Dimitris Aragiorgis
  def _WriteNICInfoFile(cls, instance, idx, nic):
462 397b7844 Dimitris Aragiorgis
    """Write the Xen config file for the instance.
463 397b7844 Dimitris Aragiorgis

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

466 397b7844 Dimitris Aragiorgis
    """
467 2a3bbbaa Dimitris Aragiorgis
    instance_name = instance.name
468 397b7844 Dimitris Aragiorgis
    dirs = [(dname, constants.RUN_DIRS_MODE)
469 397b7844 Dimitris Aragiorgis
            for dname in cls._DIRS + [cls._InstanceNICDir(instance_name)]]
470 397b7844 Dimitris Aragiorgis
    utils.EnsureDirs(dirs)
471 397b7844 Dimitris Aragiorgis
472 397b7844 Dimitris Aragiorgis
    cfg_file = cls._InstanceNICFile(instance_name, idx)
473 397b7844 Dimitris Aragiorgis
    data = StringIO()
474 397b7844 Dimitris Aragiorgis
475 4a65d4fd Thomas Thrainer
    data.write("TAGS=%s\n" % r"\ ".join(instance.GetTags()))
476 397b7844 Dimitris Aragiorgis
    if nic.netinfo:
477 397b7844 Dimitris Aragiorgis
      netinfo = objects.Network.FromDict(nic.netinfo)
478 884ec6d4 Dimitris Aragiorgis
      for k, v in netinfo.HooksDict().iteritems():
479 884ec6d4 Dimitris Aragiorgis
        data.write("%s=%s\n" % (k, v))
480 397b7844 Dimitris Aragiorgis
481 397b7844 Dimitris Aragiorgis
    data.write("MAC=%s\n" % nic.mac)
482 cc6fd3da Dimitris Aragiorgis
    if nic.ip:
483 cc6fd3da Dimitris Aragiorgis
      data.write("IP=%s\n" % nic.ip)
484 cc6fd3da Dimitris Aragiorgis
    data.write("INTERFACE_INDEX=%s\n" % str(idx))
485 cc6fd3da Dimitris Aragiorgis
    if nic.name:
486 cc6fd3da Dimitris Aragiorgis
      data.write("INTERFACE_NAME=%s\n" % nic.name)
487 cc6fd3da Dimitris Aragiorgis
    data.write("INTERFACE_UUID=%s\n" % nic.uuid)
488 397b7844 Dimitris Aragiorgis
    data.write("MODE=%s\n" % nic.nicparams[constants.NIC_MODE])
489 397b7844 Dimitris Aragiorgis
    data.write("LINK=%s\n" % nic.nicparams[constants.NIC_LINK])
490 397b7844 Dimitris Aragiorgis
491 397b7844 Dimitris Aragiorgis
    try:
492 397b7844 Dimitris Aragiorgis
      utils.WriteFile(cfg_file, data=data.getvalue())
493 397b7844 Dimitris Aragiorgis
    except EnvironmentError, err:
494 397b7844 Dimitris Aragiorgis
      raise errors.HypervisorError("Cannot write Xen instance configuration"
495 397b7844 Dimitris Aragiorgis
                                   " file %s: %s" % (cfg_file, err))
496 397b7844 Dimitris Aragiorgis
497 397b7844 Dimitris Aragiorgis
  @classmethod
498 397b7844 Dimitris Aragiorgis
  def _InstanceNICDir(cls, instance_name):
499 397b7844 Dimitris Aragiorgis
    """Returns the directory holding the tap device files for a given instance.
500 397b7844 Dimitris Aragiorgis

501 397b7844 Dimitris Aragiorgis
    """
502 397b7844 Dimitris Aragiorgis
    return utils.PathJoin(cls._NICS_DIR, instance_name)
503 397b7844 Dimitris Aragiorgis
504 397b7844 Dimitris Aragiorgis
  @classmethod
505 397b7844 Dimitris Aragiorgis
  def _InstanceNICFile(cls, instance_name, seq):
506 397b7844 Dimitris Aragiorgis
    """Returns the name of the file containing the tap device for a given NIC
507 397b7844 Dimitris Aragiorgis

508 397b7844 Dimitris Aragiorgis
    """
509 397b7844 Dimitris Aragiorgis
    return utils.PathJoin(cls._InstanceNICDir(instance_name), str(seq))
510 397b7844 Dimitris Aragiorgis
511 397b7844 Dimitris Aragiorgis
  @classmethod
512 c3d839f5 Michael Hanselmann
  def _GetConfig(cls, instance, startup_memory, block_devices):
513 c3d839f5 Michael Hanselmann
    """Build Xen configuration for an instance.
514 65a6f9b7 Michael Hanselmann

515 65a6f9b7 Michael Hanselmann
    """
516 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
517 65a6f9b7 Michael Hanselmann
518 c3d839f5 Michael Hanselmann
  def _WriteConfigFile(self, instance_name, data):
519 4390ccff Guido Trotter
    """Write the Xen config file for the instance.
520 4390ccff Guido Trotter

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

523 4390ccff Guido Trotter
    """
524 1a63f285 Iustin Pop
    # just in case it exists
525 0a903309 Michael Hanselmann
    utils.RemoveFile(utils.PathJoin(self._cfgdir, "auto", instance_name))
526 a8e8c0c6 Michael Hanselmann
527 0a903309 Michael Hanselmann
    cfg_file = self._ConfigFileName(instance_name)
528 1a63f285 Iustin Pop
    try:
529 1a63f285 Iustin Pop
      utils.WriteFile(cfg_file, data=data)
530 1a63f285 Iustin Pop
    except EnvironmentError, err:
531 1a63f285 Iustin Pop
      raise errors.HypervisorError("Cannot write Xen instance configuration"
532 1a63f285 Iustin Pop
                                   " file %s: %s" % (cfg_file, err))
533 4390ccff Guido Trotter
534 0a903309 Michael Hanselmann
  def _ReadConfigFile(self, instance_name):
535 4390ccff Guido Trotter
    """Returns the contents of the instance config file.
536 4390ccff Guido Trotter

537 4390ccff Guido Trotter
    """
538 0a903309 Michael Hanselmann
    filename = self._ConfigFileName(instance_name)
539 76c364d9 Michael Hanselmann
540 4390ccff Guido Trotter
    try:
541 76c364d9 Michael Hanselmann
      file_content = utils.ReadFile(filename)
542 4390ccff Guido Trotter
    except EnvironmentError, err:
543 4390ccff Guido Trotter
      raise errors.HypervisorError("Failed to load Xen config file: %s" % err)
544 76c364d9 Michael Hanselmann
545 4390ccff Guido Trotter
    return file_content
546 4390ccff Guido Trotter
547 0a903309 Michael Hanselmann
  def _RemoveConfigFile(self, instance_name):
548 65a6f9b7 Michael Hanselmann
    """Remove the xen configuration file.
549 65a6f9b7 Michael Hanselmann

550 65a6f9b7 Michael Hanselmann
    """
551 0a903309 Michael Hanselmann
    utils.RemoveFile(self._ConfigFileName(instance_name))
552 397b7844 Dimitris Aragiorgis
    try:
553 397b7844 Dimitris Aragiorgis
      shutil.rmtree(self._InstanceNICDir(instance_name))
554 397b7844 Dimitris Aragiorgis
    except OSError, err:
555 397b7844 Dimitris Aragiorgis
      if err.errno != errno.ENOENT:
556 397b7844 Dimitris Aragiorgis
        raise
557 65a6f9b7 Michael Hanselmann
558 48bba9de Balazs Lecz
  def _StashConfigFile(self, instance_name):
559 48bba9de Balazs Lecz
    """Move the Xen config file to the log directory and return its new path.
560 48bba9de Balazs Lecz

561 48bba9de Balazs Lecz
    """
562 48bba9de Balazs Lecz
    old_filename = self._ConfigFileName(instance_name)
563 48bba9de Balazs Lecz
    base = ("%s-%s" %
564 48bba9de Balazs Lecz
            (instance_name, utils.TimestampForFilename()))
565 48bba9de Balazs Lecz
    new_filename = utils.PathJoin(pathutils.LOG_XEN_DIR, base)
566 48bba9de Balazs Lecz
    utils.RenameFile(old_filename, new_filename)
567 48bba9de Balazs Lecz
    return new_filename
568 48bba9de Balazs Lecz
569 398fd4f6 Helga Velroyen
  def _GetInstanceList(self, include_node, hvparams):
570 9d22cc90 Jose A. Lopes
    """Wrapper around module level L{_GetAllInstanceList}.
571 06b78e8b Michael Hanselmann

572 398fd4f6 Helga Velroyen
    @type hvparams: dict of strings
573 398fd4f6 Helga Velroyen
    @param hvparams: hypervisor parameters to be used on this node
574 398fd4f6 Helga Velroyen

575 06b78e8b Michael Hanselmann
    """
576 9d22cc90 Jose A. Lopes
    return _GetAllInstanceList(lambda: self._RunXen(["list"], hvparams),
577 9d22cc90 Jose A. Lopes
                               include_node)
578 65a6f9b7 Michael Hanselmann
579 58e356a9 Helga Velroyen
  def ListInstances(self, hvparams=None):
580 65a6f9b7 Michael Hanselmann
    """Get the list of running instances.
581 65a6f9b7 Michael Hanselmann

582 65a6f9b7 Michael Hanselmann
    """
583 398fd4f6 Helga Velroyen
    instance_list = self._GetInstanceList(False, hvparams)
584 36bebc53 Helga Velroyen
    names = [info[0] for info in instance_list]
585 65a6f9b7 Michael Hanselmann
    return names
586 65a6f9b7 Michael Hanselmann
587 0bbec3af Helga Velroyen
  def GetInstanceInfo(self, instance_name, hvparams=None):
588 65a6f9b7 Michael Hanselmann
    """Get instance properties.
589 65a6f9b7 Michael Hanselmann

590 0bbec3af Helga Velroyen
    @type instance_name: string
591 c41eea6e Iustin Pop
    @param instance_name: the instance name
592 0bbec3af Helga Velroyen
    @type hvparams: dict of strings
593 0bbec3af Helga Velroyen
    @param hvparams: the instance's hypervisor params
594 c41eea6e Iustin Pop

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

597 65a6f9b7 Michael Hanselmann
    """
598 398fd4f6 Helga Velroyen
    instance_list = self._GetInstanceList(instance_name == _DOM0_NAME, hvparams)
599 65a6f9b7 Michael Hanselmann
    result = None
600 36bebc53 Helga Velroyen
    for data in instance_list:
601 65a6f9b7 Michael Hanselmann
      if data[0] == instance_name:
602 65a6f9b7 Michael Hanselmann
        result = data
603 65a6f9b7 Michael Hanselmann
        break
604 65a6f9b7 Michael Hanselmann
    return result
605 65a6f9b7 Michael Hanselmann
606 0200a1af Helga Velroyen
  def GetAllInstancesInfo(self, hvparams=None):
607 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
608 65a6f9b7 Michael Hanselmann

609 0200a1af Helga Velroyen
    @type hvparams: dict of strings
610 0200a1af Helga Velroyen
    @param hvparams: hypervisor parameters
611 9d22cc90 Jose A. Lopes

612 9d22cc90 Jose A. Lopes
    @rtype: (string, string, int, int, HypervisorInstanceState, int)
613 9d22cc90 Jose A. Lopes
    @return: list of tuples (name, id, memory, vcpus, state, times)
614 c41eea6e Iustin Pop

615 65a6f9b7 Michael Hanselmann
    """
616 398fd4f6 Helga Velroyen
    return self._GetInstanceList(False, hvparams)
617 65a6f9b7 Michael Hanselmann
618 c3d839f5 Michael Hanselmann
  def _MakeConfigFile(self, instance, startup_memory, block_devices):
619 c3d839f5 Michael Hanselmann
    """Gather configuration details and write to disk.
620 c3d839f5 Michael Hanselmann

621 c3d839f5 Michael Hanselmann
    See L{_GetConfig} for arguments.
622 c3d839f5 Michael Hanselmann

623 c3d839f5 Michael Hanselmann
    """
624 c3d839f5 Michael Hanselmann
    buf = StringIO()
625 c3d839f5 Michael Hanselmann
    buf.write("# Automatically generated by Ganeti. Do not edit!\n")
626 c3d839f5 Michael Hanselmann
    buf.write("\n")
627 c3d839f5 Michael Hanselmann
    buf.write(self._GetConfig(instance, startup_memory, block_devices))
628 c3d839f5 Michael Hanselmann
    buf.write("\n")
629 c3d839f5 Michael Hanselmann
630 c3d839f5 Michael Hanselmann
    self._WriteConfigFile(instance.name, buf.getvalue())
631 c3d839f5 Michael Hanselmann
632 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
633 c41eea6e Iustin Pop
    """Start an instance.
634 c41eea6e Iustin Pop

635 c41eea6e Iustin Pop
    """
636 30b12688 Jose A. Lopes
    startup_memory = self._InstanceStartupMemory(instance)
637 c3d839f5 Michael Hanselmann
638 c3d839f5 Michael Hanselmann
    self._MakeConfigFile(instance, startup_memory, block_devices)
639 c3d839f5 Michael Hanselmann
640 3d942d8b Michael Hanselmann
    cmd = ["create"]
641 323f9095 Stephen Shirley
    if startup_paused:
642 3d942d8b Michael Hanselmann
      cmd.append("-p")
643 3d942d8b Michael Hanselmann
    cmd.append(self._ConfigFileName(instance.name))
644 65a6f9b7 Michael Hanselmann
645 398fd4f6 Helga Velroyen
    result = self._RunXen(cmd, instance.hvparams)
646 65a6f9b7 Michael Hanselmann
    if result.failed:
647 48bba9de Balazs Lecz
      # Move the Xen configuration file to the log directory to avoid
648 48bba9de Balazs Lecz
      # leaving a stale config file behind.
649 48bba9de Balazs Lecz
      stashed_config = self._StashConfigFile(instance.name)
650 48bba9de Balazs Lecz
      raise errors.HypervisorError("Failed to start instance %s: %s (%s). Moved"
651 48bba9de Balazs Lecz
                                   " config file to %s" %
652 65a6f9b7 Michael Hanselmann
                                   (instance.name, result.fail_reason,
653 48bba9de Balazs Lecz
                                    result.output, stashed_config))
654 65a6f9b7 Michael Hanselmann
655 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
656 c41eea6e Iustin Pop
    """Stop an instance.
657 c41eea6e Iustin Pop

658 c41eea6e Iustin Pop
    """
659 bbcf7ad0 Iustin Pop
    if name is None:
660 bbcf7ad0 Iustin Pop
      name = instance.name
661 4b8b172d Michael Hanselmann
662 58e356a9 Helga Velroyen
    return self._StopInstance(name, force, instance.hvparams)
663 31da5ab5 Michael Hanselmann
664 affe1792 Klaus Aehlig
  def _ShutdownInstance(self, name, hvparams):
665 364c350f Jose A. Lopes
    """Shutdown an instance if the instance is running.
666 364c350f Jose A. Lopes

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

672 364c350f Jose A. Lopes
    The '-w' flag waits for shutdown to complete which avoids the need
673 364c350f Jose A. Lopes
    to poll in the case where we want to destroy the domain
674 364c350f Jose A. Lopes
    immediately after shutdown.
675 364c350f Jose A. Lopes

676 364c350f Jose A. Lopes
    """
677 3d680d45 Klaus Aehlig
    instance_info = self.GetInstanceInfo(name, hvparams=hvparams)
678 364c350f Jose A. Lopes
679 364c350f Jose A. Lopes
    if instance_info is None or _IsInstanceShutdown(instance_info[4]):
680 364c350f Jose A. Lopes
      logging.info("Failed to shutdown instance %s, not running", name)
681 364c350f Jose A. Lopes
      return None
682 364c350f Jose A. Lopes
683 affe1792 Klaus Aehlig
    return self._RunXen(["shutdown", "-w", name], hvparams)
684 9d22cc90 Jose A. Lopes
685 9d22cc90 Jose A. Lopes
  def _DestroyInstance(self, name, hvparams):
686 364c350f Jose A. Lopes
    """Destroy an instance if the instance if the instance exists.
687 70d8491f Jose A. Lopes

688 364c350f Jose A. Lopes
    @type name: string
689 364c350f Jose A. Lopes
    @param name: name of the instance to destroy
690 affe1792 Klaus Aehlig
    @type hvparams: dict of string
691 affe1792 Klaus Aehlig
    @param hvparams: hypervisor parameters of the instance
692 364c350f Jose A. Lopes

693 364c350f Jose A. Lopes
    """
694 3d680d45 Klaus Aehlig
    instance_info = self.GetInstanceInfo(name, hvparams=hvparams)
695 364c350f Jose A. Lopes
696 364c350f Jose A. Lopes
    if instance_info is None:
697 364c350f Jose A. Lopes
      logging.info("Failed to destroy instance %s, does not exist", name)
698 364c350f Jose A. Lopes
      return None
699 364c350f Jose A. Lopes
700 affe1792 Klaus Aehlig
    return self._RunXen(["destroy", name], hvparams)
701 9d22cc90 Jose A. Lopes
702 70d8491f Jose A. Lopes
  # Destroy a domain only if necessary
703 70d8491f Jose A. Lopes
  #
704 70d8491f Jose A. Lopes
  # This method checks if the domain has already been destroyed before
705 70d8491f Jose A. Lopes
  # issuing the 'destroy' command.  This step is necessary to handle
706 70d8491f Jose A. Lopes
  # domains created by other versions of Ganeti.  For example, an
707 70d8491f Jose A. Lopes
  # instance created with 2.10 will be destroy by the
708 70d8491f Jose A. Lopes
  # '_ShutdownInstance', thus not requiring an additional destroy,
709 70d8491f Jose A. Lopes
  # which would cause an error if issued.  See issue 619.
710 70d8491f Jose A. Lopes
  def _DestroyInstanceIfAlive(self, name, hvparams):
711 70d8491f Jose A. Lopes
    instance_info = self.GetInstanceInfo(name, hvparams=hvparams)
712 70d8491f Jose A. Lopes
713 70d8491f Jose A. Lopes
    if instance_info is None:
714 70d8491f Jose A. Lopes
      raise errors.HypervisorError("Failed to destroy instance %s, already"
715 70d8491f Jose A. Lopes
                                   " destroyed" % name)
716 70d8491f Jose A. Lopes
    else:
717 70d8491f Jose A. Lopes
      self._DestroyInstance(name, hvparams)
718 70d8491f Jose A. Lopes
719 58e356a9 Helga Velroyen
  def _StopInstance(self, name, force, hvparams):
720 31da5ab5 Michael Hanselmann
    """Stop an instance.
721 31da5ab5 Michael Hanselmann

722 58e356a9 Helga Velroyen
    @type name: string
723 364c350f Jose A. Lopes
    @param name: name of the instance to destroy
724 364c350f Jose A. Lopes

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

728 58e356a9 Helga Velroyen
    @type hvparams: dict of string
729 58e356a9 Helga Velroyen
    @param hvparams: hypervisor parameters of the instance
730 58e356a9 Helga Velroyen

731 31da5ab5 Michael Hanselmann
    """
732 9d22cc90 Jose A. Lopes
    instance_info = self.GetInstanceInfo(name, hvparams=hvparams)
733 9d22cc90 Jose A. Lopes
734 9d22cc90 Jose A. Lopes
    if instance_info is None:
735 9d22cc90 Jose A. Lopes
      raise errors.HypervisorError("Failed to shutdown instance %s,"
736 9d22cc90 Jose A. Lopes
                                   " not running" % name)
737 9d22cc90 Jose A. Lopes
738 65a6f9b7 Michael Hanselmann
    if force:
739 f3ac6f36 Klaus Aehlig
      result = self._DestroyInstanceIfAlive(name, hvparams)
740 65a6f9b7 Michael Hanselmann
    else:
741 affe1792 Klaus Aehlig
      self._ShutdownInstance(name, hvparams)
742 f3ac6f36 Klaus Aehlig
      result = self._DestroyInstanceIfAlive(name, hvparams)
743 65a6f9b7 Michael Hanselmann
744 364c350f Jose A. Lopes
    if result is not None and result.failed and \
745 3d680d45 Klaus Aehlig
          self.GetInstanceInfo(name, hvparams=hvparams) is not None:
746 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to stop instance %s: %s, %s" %
747 bbcf7ad0 Iustin Pop
                                   (name, result.fail_reason, result.output))
748 65a6f9b7 Michael Hanselmann
749 4b8b172d Michael Hanselmann
    # Remove configuration file if stopping/starting instance was successful
750 4b8b172d Michael Hanselmann
    self._RemoveConfigFile(name)
751 4b8b172d Michael Hanselmann
752 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
753 c41eea6e Iustin Pop
    """Reboot an instance.
754 c41eea6e Iustin Pop

755 c41eea6e Iustin Pop
    """
756 0bbec3af Helga Velroyen
    ini_info = self.GetInstanceInfo(instance.name, hvparams=instance.hvparams)
757 65a6f9b7 Michael Hanselmann
758 e0561198 Iustin Pop
    if ini_info is None:
759 e0561198 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s,"
760 e0561198 Iustin Pop
                                   " not running" % instance.name)
761 e0561198 Iustin Pop
762 398fd4f6 Helga Velroyen
    result = self._RunXen(["reboot", instance.name], instance.hvparams)
763 65a6f9b7 Michael Hanselmann
    if result.failed:
764 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s: %s, %s" %
765 3213d3c8 Iustin Pop
                                   (instance.name, result.fail_reason,
766 3213d3c8 Iustin Pop
                                    result.output))
767 06b78e8b Michael Hanselmann
768 06b78e8b Michael Hanselmann
    def _CheckInstance():
769 0bbec3af Helga Velroyen
      new_info = self.GetInstanceInfo(instance.name, hvparams=instance.hvparams)
770 06b78e8b Michael Hanselmann
771 06b78e8b Michael Hanselmann
      # check if the domain ID has changed or the run time has decreased
772 e0561198 Iustin Pop
      if (new_info is not None and
773 e0561198 Iustin Pop
          (new_info[1] != ini_info[1] or new_info[5] < ini_info[5])):
774 06b78e8b Michael Hanselmann
        return
775 7dd106d3 Iustin Pop
776 06b78e8b Michael Hanselmann
      raise utils.RetryAgain()
777 06b78e8b Michael Hanselmann
778 06b78e8b Michael Hanselmann
    try:
779 06b78e8b Michael Hanselmann
      utils.Retry(_CheckInstance, self.REBOOT_RETRY_INTERVAL,
780 06b78e8b Michael Hanselmann
                  self.REBOOT_RETRY_INTERVAL * self.REBOOT_RETRY_COUNT)
781 06b78e8b Michael Hanselmann
    except utils.RetryTimeout:
782 7dd106d3 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s: instance"
783 7dd106d3 Iustin Pop
                                   " did not reboot in the expected interval" %
784 7dd106d3 Iustin Pop
                                   (instance.name, ))
785 65a6f9b7 Michael Hanselmann
786 2c7a0373 Guido Trotter
  def BalloonInstanceMemory(self, instance, mem):
787 2c7a0373 Guido Trotter
    """Balloon an instance memory to a certain value.
788 2c7a0373 Guido Trotter

789 2c7a0373 Guido Trotter
    @type instance: L{objects.Instance}
790 2c7a0373 Guido Trotter
    @param instance: instance to be accepted
791 2c7a0373 Guido Trotter
    @type mem: int
792 2c7a0373 Guido Trotter
    @param mem: actual memory size to use for instance runtime
793 2c7a0373 Guido Trotter

794 2c7a0373 Guido Trotter
    """
795 398fd4f6 Helga Velroyen
    result = self._RunXen(["mem-set", instance.name, mem], instance.hvparams)
796 2c7a0373 Guido Trotter
    if result.failed:
797 2c7a0373 Guido Trotter
      raise errors.HypervisorError("Failed to balloon instance %s: %s (%s)" %
798 2c7a0373 Guido Trotter
                                   (instance.name, result.fail_reason,
799 2c7a0373 Guido Trotter
                                    result.output))
800 3d942d8b Michael Hanselmann
801 3d942d8b Michael Hanselmann
    # Update configuration file
802 2c7a0373 Guido Trotter
    cmd = ["sed", "-ie", "s/^memory.*$/memory = %s/" % mem]
803 0a903309 Michael Hanselmann
    cmd.append(self._ConfigFileName(instance.name))
804 3d942d8b Michael Hanselmann
805 2c7a0373 Guido Trotter
    result = utils.RunCmd(cmd)
806 2c7a0373 Guido Trotter
    if result.failed:
807 2c7a0373 Guido Trotter
      raise errors.HypervisorError("Failed to update memory for %s: %s (%s)" %
808 2c7a0373 Guido Trotter
                                   (instance.name, result.fail_reason,
809 2c7a0373 Guido Trotter
                                    result.output))
810 2c7a0373 Guido Trotter
811 fac489a5 Helga Velroyen
  def GetNodeInfo(self, hvparams=None):
812 65a6f9b7 Michael Hanselmann
    """Return information about the node.
813 65a6f9b7 Michael Hanselmann

814 06c9a520 Michael Hanselmann
    @see: L{_GetNodeInfo} and L{_ParseNodeInfo}
815 65a6f9b7 Michael Hanselmann

816 65a6f9b7 Michael Hanselmann
    """
817 398fd4f6 Helga Velroyen
    result = self._RunXen(["info"], hvparams)
818 65a6f9b7 Michael Hanselmann
    if result.failed:
819 2609da63 Helga Velroyen
      logging.error("Can't retrieve xen hypervisor information (%s): %s",
820 2609da63 Helga Velroyen
                    result.fail_reason, result.output)
821 65a6f9b7 Michael Hanselmann
      return None
822 65a6f9b7 Michael Hanselmann
823 398fd4f6 Helga Velroyen
    instance_list = self._GetInstanceList(True, hvparams)
824 fac489a5 Helga Velroyen
    return _GetNodeInfo(result.stdout, instance_list)
825 65a6f9b7 Michael Hanselmann
826 f92d9674 Helga Velroyen
  @classmethod
827 a4417db4 Thomas Thrainer
  def GetInstanceConsole(cls, instance, primary_node, node_group,
828 c42be2c0 Petr Pudlak
                         hvparams, beparams):
829 65a6f9b7 Michael Hanselmann
    """Return a command for connecting to the console of an instance.
830 65a6f9b7 Michael Hanselmann

831 65a6f9b7 Michael Hanselmann
    """
832 f92d9674 Helga Velroyen
    xen_cmd = XenHypervisor._GetCommandFromHvparams(hvparams)
833 c42be2c0 Petr Pudlak
    ndparams = node_group.FillND(primary_node)
834 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
835 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_SSH,
836 1c3231aa Thomas Thrainer
                                   host=primary_node.name,
837 c42be2c0 Petr Pudlak
                                   port=ndparams.get(constants.ND_SSH_PORT),
838 052783ff Michael Hanselmann
                                   user=constants.SSH_CONSOLE_USER,
839 b9612abb Iustin Pop
                                   command=[pathutils.XEN_CONSOLE_WRAPPER,
840 8ef418bb Helga Velroyen
                                            xen_cmd, instance.name])
841 65a6f9b7 Michael Hanselmann
842 75bf3149 Helga Velroyen
  def Verify(self, hvparams=None):
843 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
844 65a6f9b7 Michael Hanselmann

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

847 75bf3149 Helga Velroyen
    @type hvparams: dict of strings
848 75bf3149 Helga Velroyen
    @param hvparams: hypervisor parameters to be verified against
849 75bf3149 Helga Velroyen

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

852 65a6f9b7 Michael Hanselmann
    """
853 75bf3149 Helga Velroyen
    if hvparams is None:
854 75bf3149 Helga Velroyen
      return "Could not verify the hypervisor, because no hvparams were" \
855 75bf3149 Helga Velroyen
             " provided."
856 75bf3149 Helga Velroyen
857 75bf3149 Helga Velroyen
    if constants.HV_XEN_CMD in hvparams:
858 75bf3149 Helga Velroyen
      xen_cmd = hvparams[constants.HV_XEN_CMD]
859 75bf3149 Helga Velroyen
      try:
860 75bf3149 Helga Velroyen
        self._CheckToolstack(xen_cmd)
861 75bf3149 Helga Velroyen
      except errors.HypervisorError:
862 75bf3149 Helga Velroyen
        return "The configured xen toolstack '%s' is not available on this" \
863 75bf3149 Helga Velroyen
               " node." % xen_cmd
864 75bf3149 Helga Velroyen
865 398fd4f6 Helga Velroyen
    result = self._RunXen(["info"], hvparams)
866 e3e66f02 Michael Hanselmann
    if result.failed:
867 75bf3149 Helga Velroyen
      return "Retrieving information from xen failed: %s, %s" % \
868 75bf3149 Helga Velroyen
        (result.fail_reason, result.output)
869 65a6f9b7 Michael Hanselmann
870 cd04dfd2 Michael Hanselmann
    return None
871 cd04dfd2 Michael Hanselmann
872 4390ccff Guido Trotter
  def MigrationInfo(self, instance):
873 4390ccff Guido Trotter
    """Get instance information to perform a migration.
874 4390ccff Guido Trotter

875 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
876 4390ccff Guido Trotter
    @param instance: instance to be migrated
877 4390ccff Guido Trotter
    @rtype: string
878 4390ccff Guido Trotter
    @return: content of the xen config file
879 4390ccff Guido Trotter

880 4390ccff Guido Trotter
    """
881 4390ccff Guido Trotter
    return self._ReadConfigFile(instance.name)
882 4390ccff Guido Trotter
883 4390ccff Guido Trotter
  def AcceptInstance(self, instance, info, target):
884 4390ccff Guido Trotter
    """Prepare to accept an instance.
885 4390ccff Guido Trotter

886 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
887 4390ccff Guido Trotter
    @param instance: instance to be accepted
888 4390ccff Guido Trotter
    @type info: string
889 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
890 4390ccff Guido Trotter
    @type target: string
891 4390ccff Guido Trotter
    @param target: target host (usually ip), on this node
892 4390ccff Guido Trotter

893 4390ccff Guido Trotter
    """
894 4390ccff Guido Trotter
    pass
895 4390ccff Guido Trotter
896 60af751d Andrea Spadaccini
  def FinalizeMigrationDst(self, instance, info, success):
897 4390ccff Guido Trotter
    """Finalize an instance migration.
898 4390ccff Guido Trotter

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

902 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
903 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
904 4390ccff Guido Trotter
    @type info: string
905 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
906 4390ccff Guido Trotter
    @type success: boolean
907 4390ccff Guido Trotter
    @param success: whether the migration was a success or a failure
908 4390ccff Guido Trotter

909 4390ccff Guido Trotter
    """
910 4390ccff Guido Trotter
    if success:
911 c3d839f5 Michael Hanselmann
      self._WriteConfigFile(instance.name, info)
912 4390ccff Guido Trotter
913 bc0a2284 Helga Velroyen
  def MigrateInstance(self, cluster_name, instance, target, live):
914 6e7275c0 Iustin Pop
    """Migrate an instance to a target node.
915 6e7275c0 Iustin Pop

916 6e7275c0 Iustin Pop
    The migration will not be attempted if the instance is not
917 6e7275c0 Iustin Pop
    currently running.
918 6e7275c0 Iustin Pop

919 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
920 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
921 fdf7f055 Guido Trotter
    @type target: string
922 fdf7f055 Guido Trotter
    @param target: ip address of the target node
923 fdf7f055 Guido Trotter
    @type live: boolean
924 fdf7f055 Guido Trotter
    @param live: perform a live migration
925 fdf7f055 Guido Trotter

926 6e7275c0 Iustin Pop
    """
927 d8784f7d Michael Hanselmann
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
928 d8784f7d Michael Hanselmann
929 d8784f7d Michael Hanselmann
    return self._MigrateInstance(cluster_name, instance.name, target, port,
930 8351df2f Helga Velroyen
                                 live, instance.hvparams)
931 d8784f7d Michael Hanselmann
932 d8784f7d Michael Hanselmann
  def _MigrateInstance(self, cluster_name, instance_name, target, port, live,
933 8351df2f Helga Velroyen
                       hvparams, _ping_fn=netutils.TcpPing):
934 d8784f7d Michael Hanselmann
    """Migrate an instance to a target node.
935 d8784f7d Michael Hanselmann

936 d8784f7d Michael Hanselmann
    @see: L{MigrateInstance} for details
937 d8784f7d Michael Hanselmann

938 d8784f7d Michael Hanselmann
    """
939 8351df2f Helga Velroyen
    if hvparams is None:
940 8351df2f Helga Velroyen
      raise errors.HypervisorError("No hvparams provided.")
941 8351df2f Helga Velroyen
942 8351df2f Helga Velroyen
    if self.GetInstanceInfo(instance_name, hvparams=hvparams) is None:
943 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Instance not running, cannot migrate")
944 50716be0 Iustin Pop
945 398fd4f6 Helga Velroyen
    cmd = self._GetCommand(hvparams)
946 50716be0 Iustin Pop
947 d8784f7d Michael Hanselmann
    if (cmd == constants.XEN_CMD_XM and
948 d8784f7d Michael Hanselmann
        not _ping_fn(target, port, live_port_needed=True)):
949 50716be0 Iustin Pop
      raise errors.HypervisorError("Remote host %s not listening on port"
950 50716be0 Iustin Pop
                                   " %s, cannot migrate" % (target, port))
951 50716be0 Iustin Pop
952 3d942d8b Michael Hanselmann
    args = ["migrate"]
953 3d942d8b Michael Hanselmann
954 d8784f7d Michael Hanselmann
    if cmd == constants.XEN_CMD_XM:
955 0625d08f René Nussbaumer
      args.extend(["-p", "%d" % port])
956 0625d08f René Nussbaumer
      if live:
957 0625d08f René Nussbaumer
        args.append("-l")
958 3d942d8b Michael Hanselmann
959 d8784f7d Michael Hanselmann
    elif cmd == constants.XEN_CMD_XL:
960 d8784f7d Michael Hanselmann
      args.extend([
961 d8784f7d Michael Hanselmann
        "-s", constants.XL_SSH_CMD % cluster_name,
962 d8784f7d Michael Hanselmann
        "-C", self._ConfigFileName(instance_name),
963 d8784f7d Michael Hanselmann
        ])
964 3d942d8b Michael Hanselmann
965 0625d08f René Nussbaumer
    else:
966 d8784f7d Michael Hanselmann
      raise errors.HypervisorError("Unsupported Xen command: %s" % self._cmd)
967 0625d08f René Nussbaumer
968 d8784f7d Michael Hanselmann
    args.extend([instance_name, target])
969 3d942d8b Michael Hanselmann
970 398fd4f6 Helga Velroyen
    result = self._RunXen(args, hvparams)
971 6e7275c0 Iustin Pop
    if result.failed:
972 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Failed to migrate instance %s: %s" %
973 d8784f7d Michael Hanselmann
                                   (instance_name, result.output))
974 60af751d Andrea Spadaccini
975 60af751d Andrea Spadaccini
  def FinalizeMigrationSource(self, instance, success, live):
976 60af751d Andrea Spadaccini
    """Finalize the instance migration on the source node.
977 60af751d Andrea Spadaccini

978 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
979 60af751d Andrea Spadaccini
    @param instance: the instance that was migrated
980 60af751d Andrea Spadaccini
    @type success: bool
981 60af751d Andrea Spadaccini
    @param success: whether the migration succeeded or not
982 60af751d Andrea Spadaccini
    @type live: bool
983 60af751d Andrea Spadaccini
    @param live: whether the user requested a live migration or not
984 60af751d Andrea Spadaccini

985 60af751d Andrea Spadaccini
    """
986 60af751d Andrea Spadaccini
    # pylint: disable=W0613
987 60af751d Andrea Spadaccini
    if success:
988 60af751d Andrea Spadaccini
      # remove old xen file after migration succeeded
989 60af751d Andrea Spadaccini
      try:
990 60af751d Andrea Spadaccini
        self._RemoveConfigFile(instance.name)
991 60af751d Andrea Spadaccini
      except EnvironmentError:
992 60af751d Andrea Spadaccini
        logging.exception("Failure while removing instance config file")
993 60af751d Andrea Spadaccini
994 60af751d Andrea Spadaccini
  def GetMigrationStatus(self, instance):
995 60af751d Andrea Spadaccini
    """Get the migration status
996 60af751d Andrea Spadaccini

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

1001 60af751d Andrea Spadaccini
    @type instance: L{objects.Instance}
1002 60af751d Andrea Spadaccini
    @param instance: the instance that is being migrated
1003 60af751d Andrea Spadaccini
    @rtype: L{objects.MigrationStatus}
1004 60af751d Andrea Spadaccini
    @return: the status of the current migration (one of
1005 60af751d Andrea Spadaccini
             L{constants.HV_MIGRATION_VALID_STATUSES}), plus any additional
1006 60af751d Andrea Spadaccini
             progress info that can be retrieved from the hypervisor
1007 60af751d Andrea Spadaccini

1008 60af751d Andrea Spadaccini
    """
1009 60af751d Andrea Spadaccini
    return objects.MigrationStatus(status=constants.HV_MIGRATION_COMPLETED)
1010 6e7275c0 Iustin Pop
1011 8ef418bb Helga Velroyen
  def PowercycleNode(self, hvparams=None):
1012 f5118ade Iustin Pop
    """Xen-specific powercycle.
1013 f5118ade Iustin Pop

1014 f5118ade Iustin Pop
    This first does a Linux reboot (which triggers automatically a Xen
1015 f5118ade Iustin Pop
    reboot), and if that fails it tries to do a Xen reboot. The reason
1016 f5118ade Iustin Pop
    we don't try a Xen reboot first is that the xen reboot launches an
1017 f5118ade Iustin Pop
    external command which connects to the Xen hypervisor, and that
1018 f5118ade Iustin Pop
    won't work in case the root filesystem is broken and/or the xend
1019 f5118ade Iustin Pop
    daemon is not working.
1020 f5118ade Iustin Pop

1021 8ef418bb Helga Velroyen
    @type hvparams: dict of strings
1022 8ef418bb Helga Velroyen
    @param hvparams: hypervisor params to be used on this node
1023 8ef418bb Helga Velroyen

1024 f5118ade Iustin Pop
    """
1025 f5118ade Iustin Pop
    try:
1026 8ef418bb Helga Velroyen
      self.LinuxPowercycle()
1027 f5118ade Iustin Pop
    finally:
1028 8ef418bb Helga Velroyen
      xen_cmd = self._GetCommand(hvparams)
1029 8ef418bb Helga Velroyen
      utils.RunCmd([xen_cmd, "debug", "R"])
1030 f5118ade Iustin Pop
1031 75bf3149 Helga Velroyen
  def _CheckToolstack(self, xen_cmd):
1032 75bf3149 Helga Velroyen
    """Check whether the given toolstack is available on the node.
1033 75bf3149 Helga Velroyen

1034 75bf3149 Helga Velroyen
    @type xen_cmd: string
1035 75bf3149 Helga Velroyen
    @param xen_cmd: xen command (e.g. 'xm' or 'xl')
1036 75bf3149 Helga Velroyen

1037 75bf3149 Helga Velroyen
    """
1038 75bf3149 Helga Velroyen
    binary_found = self._CheckToolstackBinary(xen_cmd)
1039 75bf3149 Helga Velroyen
    if not binary_found:
1040 75bf3149 Helga Velroyen
      raise errors.HypervisorError("No '%s' binary found on node." % xen_cmd)
1041 75bf3149 Helga Velroyen
    elif xen_cmd == constants.XEN_CMD_XL:
1042 75bf3149 Helga Velroyen
      if not self._CheckToolstackXlConfigured():
1043 75bf3149 Helga Velroyen
        raise errors.HypervisorError("Toolstack '%s' is not enabled on this"
1044 75bf3149 Helga Velroyen
                                     "node." % xen_cmd)
1045 75bf3149 Helga Velroyen
1046 75bf3149 Helga Velroyen
  def _CheckToolstackBinary(self, xen_cmd):
1047 75bf3149 Helga Velroyen
    """Checks whether the xen command's binary is found on the machine.
1048 75bf3149 Helga Velroyen

1049 75bf3149 Helga Velroyen
    """
1050 75bf3149 Helga Velroyen
    if xen_cmd not in constants.KNOWN_XEN_COMMANDS:
1051 75bf3149 Helga Velroyen
      raise errors.HypervisorError("Unknown xen command '%s'." % xen_cmd)
1052 75bf3149 Helga Velroyen
    result = self._run_cmd_fn(["which", xen_cmd])
1053 75bf3149 Helga Velroyen
    return not result.failed
1054 75bf3149 Helga Velroyen
1055 75bf3149 Helga Velroyen
  def _CheckToolstackXlConfigured(self):
1056 75bf3149 Helga Velroyen
    """Checks whether xl is enabled on an xl-capable node.
1057 75bf3149 Helga Velroyen

1058 75bf3149 Helga Velroyen
    @rtype: bool
1059 75bf3149 Helga Velroyen
    @returns: C{True} if 'xl' is enabled, C{False} otherwise
1060 75bf3149 Helga Velroyen

1061 75bf3149 Helga Velroyen
    """
1062 75bf3149 Helga Velroyen
    result = self._run_cmd_fn([constants.XEN_CMD_XL, "help"])
1063 75bf3149 Helga Velroyen
    if not result.failed:
1064 75bf3149 Helga Velroyen
      return True
1065 75bf3149 Helga Velroyen
    elif result.failed:
1066 75bf3149 Helga Velroyen
      if "toolstack" in result.stderr:
1067 75bf3149 Helga Velroyen
        return False
1068 75bf3149 Helga Velroyen
      # xl fails for some other reason than the toolstack
1069 75bf3149 Helga Velroyen
      else:
1070 75bf3149 Helga Velroyen
        raise errors.HypervisorError("Cannot run xen ('%s'). Error: %s."
1071 75bf3149 Helga Velroyen
                                     % (constants.XEN_CMD_XL, result.stderr))
1072 75bf3149 Helga Velroyen
1073 65a6f9b7 Michael Hanselmann
1074 931419e5 Jose A. Lopes
def WriteXenConfigEvents(config, hvp):
1075 931419e5 Jose A. Lopes
  config.write("on_poweroff = 'preserve'\n")
1076 931419e5 Jose A. Lopes
  if hvp[constants.HV_REBOOT_BEHAVIOR] == constants.INSTANCE_REBOOT_ALLOWED:
1077 931419e5 Jose A. Lopes
    config.write("on_reboot = 'restart'\n")
1078 931419e5 Jose A. Lopes
  else:
1079 931419e5 Jose A. Lopes
    config.write("on_reboot = 'destroy'\n")
1080 931419e5 Jose A. Lopes
  config.write("on_crash = 'restart'\n")
1081 931419e5 Jose A. Lopes
1082 931419e5 Jose A. Lopes
1083 65a6f9b7 Michael Hanselmann
class XenPvmHypervisor(XenHypervisor):
1084 65a6f9b7 Michael Hanselmann
  """Xen PVM hypervisor interface"""
1085 65a6f9b7 Michael Hanselmann
1086 205ab586 Iustin Pop
  PARAMETERS = {
1087 2f2dbb4b Jun Futagawa
    constants.HV_USE_BOOTLOADER: hv_base.NO_CHECK,
1088 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_PATH: hv_base.OPT_FILE_CHECK,
1089 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_ARGS: hv_base.NO_CHECK,
1090 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.REQ_FILE_CHECK,
1091 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
1092 7adf7814 René Nussbaumer
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
1093 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
1094 e2d14329 Andrea Spadaccini
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
1095 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
1096 525011bc Maciej Bliziński
    # TODO: Add a check for the blockdev prefix (matching [a-z:] or similar).
1097 525011bc Maciej Bliziński
    constants.HV_BLOCKDEV_PREFIX: hv_base.NO_CHECK,
1098 990ade2d Stephen Shirley
    constants.HV_REBOOT_BEHAVIOR:
1099 c4708267 Tsachy Shacham
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
1100 c4708267 Tsachy Shacham
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
1101 2c368f28 Guido Trotter
    constants.HV_CPU_CAP: hv_base.OPT_NONNEGATIVE_INT_CHECK,
1102 8bd977e9 Sébastien Bocahu
    constants.HV_CPU_WEIGHT:
1103 8bd977e9 Sébastien Bocahu
      (False, lambda x: 0 < x < 65536, "invalid weight", None, None),
1104 397b7844 Dimitris Aragiorgis
    constants.HV_VIF_SCRIPT: hv_base.OPT_FILE_CHECK,
1105 740394bc Helga Velroyen
    constants.HV_XEN_CMD:
1106 740394bc Helga Velroyen
      hv_base.ParamInSet(True, constants.KNOWN_XEN_COMMANDS),
1107 295ed29b Santi Raffa
    constants.HV_XEN_CPUID: hv_base.NO_CHECK,
1108 b5cad580 Raffa Santi
    constants.HV_SOUNDHW: hv_base.NO_CHECK,
1109 205ab586 Iustin Pop
    }
1110 f48148c3 Iustin Pop
1111 c3d839f5 Michael Hanselmann
  def _GetConfig(self, instance, startup_memory, block_devices):
1112 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
1113 65a6f9b7 Michael Hanselmann

1114 65a6f9b7 Michael Hanselmann
    """
1115 a985b417 Iustin Pop
    hvp = instance.hvparams
1116 65a6f9b7 Michael Hanselmann
    config = StringIO()
1117 65a6f9b7 Michael Hanselmann
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
1118 65a6f9b7 Michael Hanselmann
1119 2f2dbb4b Jun Futagawa
    # if bootloader is True, use bootloader instead of kernel and ramdisk
1120 2f2dbb4b Jun Futagawa
    # parameters.
1121 2f2dbb4b Jun Futagawa
    if hvp[constants.HV_USE_BOOTLOADER]:
1122 2f2dbb4b Jun Futagawa
      # bootloader handling
1123 2f2dbb4b Jun Futagawa
      bootloader_path = hvp[constants.HV_BOOTLOADER_PATH]
1124 2f2dbb4b Jun Futagawa
      if bootloader_path:
1125 2f2dbb4b Jun Futagawa
        config.write("bootloader = '%s'\n" % bootloader_path)
1126 2f2dbb4b Jun Futagawa
      else:
1127 2f2dbb4b Jun Futagawa
        raise errors.HypervisorError("Bootloader enabled, but missing"
1128 2f2dbb4b Jun Futagawa
                                     " bootloader path")
1129 65a6f9b7 Michael Hanselmann
1130 2f2dbb4b Jun Futagawa
      bootloader_args = hvp[constants.HV_BOOTLOADER_ARGS]
1131 2f2dbb4b Jun Futagawa
      if bootloader_args:
1132 2f2dbb4b Jun Futagawa
        config.write("bootargs = '%s'\n" % bootloader_args)
1133 2f2dbb4b Jun Futagawa
    else:
1134 2f2dbb4b Jun Futagawa
      # kernel handling
1135 2f2dbb4b Jun Futagawa
      kpath = hvp[constants.HV_KERNEL_PATH]
1136 2f2dbb4b Jun Futagawa
      config.write("kernel = '%s'\n" % kpath)
1137 2f2dbb4b Jun Futagawa
1138 2f2dbb4b Jun Futagawa
      # initrd handling
1139 2f2dbb4b Jun Futagawa
      initrd_path = hvp[constants.HV_INITRD_PATH]
1140 2f2dbb4b Jun Futagawa
      if initrd_path:
1141 2f2dbb4b Jun Futagawa
        config.write("ramdisk = '%s'\n" % initrd_path)
1142 65a6f9b7 Michael Hanselmann
1143 65a6f9b7 Michael Hanselmann
    # rest of the settings
1144 61eb1a46 Guido Trotter
    config.write("memory = %d\n" % startup_memory)
1145 80121c83 Guido Trotter
    config.write("maxmem = %d\n" % instance.beparams[constants.BE_MAXMEM])
1146 8b3fd458 Iustin Pop
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
1147 347fa0f1 Michael Hanselmann
    cpu_pinning = _CreateConfigCpus(hvp[constants.HV_CPU_MASK])
1148 c4708267 Tsachy Shacham
    if cpu_pinning:
1149 c4708267 Tsachy Shacham
      config.write("%s\n" % cpu_pinning)
1150 8bd977e9 Sébastien Bocahu
    cpu_cap = hvp[constants.HV_CPU_CAP]
1151 8bd977e9 Sébastien Bocahu
    if cpu_cap:
1152 8bd977e9 Sébastien Bocahu
      config.write("cpu_cap=%d\n" % cpu_cap)
1153 8bd977e9 Sébastien Bocahu
    cpu_weight = hvp[constants.HV_CPU_WEIGHT]
1154 8bd977e9 Sébastien Bocahu
    if cpu_weight:
1155 8bd977e9 Sébastien Bocahu
      config.write("cpu_weight=%d\n" % cpu_weight)
1156 c4708267 Tsachy Shacham
1157 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
1158 65a6f9b7 Michael Hanselmann
1159 65a6f9b7 Michael Hanselmann
    vif_data = []
1160 397b7844 Dimitris Aragiorgis
    for idx, nic in enumerate(instance.nics):
1161 503b97a9 Guido Trotter
      nic_str = "mac=%s" % (nic.mac)
1162 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
1163 65a6f9b7 Michael Hanselmann
      if ip is not None:
1164 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
1165 503b97a9 Guido Trotter
      if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1166 503b97a9 Guido Trotter
        nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK]
1167 f1f11cef Sebastian Gebhard
      if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_OVS:
1168 f1f11cef Sebastian Gebhard
        nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK]
1169 f1f11cef Sebastian Gebhard
        if nic.nicparams[constants.NIC_VLAN]:
1170 f1f11cef Sebastian Gebhard
          nic_str += "%s" % nic.nicparams[constants.NIC_VLAN]
1171 397b7844 Dimitris Aragiorgis
      if hvp[constants.HV_VIF_SCRIPT]:
1172 397b7844 Dimitris Aragiorgis
        nic_str += ", script=%s" % hvp[constants.HV_VIF_SCRIPT]
1173 0183a697 Alessandro Cincaglini
      vif_data.append("'%s'" % nic_str)
1174 2a3bbbaa Dimitris Aragiorgis
      self._WriteNICInfoFile(instance, idx, nic)
1175 65a6f9b7 Michael Hanselmann
1176 d0bb3f24 Michael Hanselmann
    disk_data = \
1177 d0bb3f24 Michael Hanselmann
      _GetConfigFileDiskData(block_devices, hvp[constants.HV_BLOCKDEV_PREFIX])
1178 7ed85ffe Iustin Pop
1179 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
1180 7ed85ffe Iustin Pop
    config.write("disk = [%s]\n" % ",".join(disk_data))
1181 074ca009 Guido Trotter
1182 7adf7814 René Nussbaumer
    if hvp[constants.HV_ROOT_PATH]:
1183 7adf7814 René Nussbaumer
      config.write("root = '%s'\n" % hvp[constants.HV_ROOT_PATH])
1184 931419e5 Jose A. Lopes
1185 931419e5 Jose A. Lopes
    WriteXenConfigEvents(config, hvp)
1186 07813a9e Iustin Pop
    config.write("extra = '%s'\n" % hvp[constants.HV_KERNEL_ARGS])
1187 73cd67f4 Guido Trotter
1188 295ed29b Santi Raffa
    cpuid = hvp[constants.HV_XEN_CPUID]
1189 295ed29b Santi Raffa
    if cpuid:
1190 295ed29b Santi Raffa
      config.write("cpuid = %s\n" % _QuoteCpuidField(cpuid))
1191 295ed29b Santi Raffa
1192 b5cad580 Raffa Santi
    if hvp[constants.HV_SOUNDHW]:
1193 b5cad580 Raffa Santi
      config.write("soundhw = '%s'\n" % hvp[constants.HV_SOUNDHW])
1194 b5cad580 Raffa Santi
1195 c3d839f5 Michael Hanselmann
    return config.getvalue()
1196 65a6f9b7 Michael Hanselmann
1197 65a6f9b7 Michael Hanselmann
1198 65a6f9b7 Michael Hanselmann
class XenHvmHypervisor(XenHypervisor):
1199 65a6f9b7 Michael Hanselmann
  """Xen HVM hypervisor interface"""
1200 65a6f9b7 Michael Hanselmann
1201 69b99987 Michael Hanselmann
  ANCILLARY_FILES = XenHypervisor.ANCILLARY_FILES + [
1202 9d9bded1 Michael Hanselmann
    pathutils.VNC_PASSWORD_FILE,
1203 69b99987 Michael Hanselmann
    ]
1204 69ab2e12 Guido Trotter
  ANCILLARY_FILES_OPT = XenHypervisor.ANCILLARY_FILES_OPT + [
1205 9d9bded1 Michael Hanselmann
    pathutils.VNC_PASSWORD_FILE,
1206 69ab2e12 Guido Trotter
    ]
1207 3680f662 Guido Trotter
1208 205ab586 Iustin Pop
  PARAMETERS = {
1209 205ab586 Iustin Pop
    constants.HV_ACPI: hv_base.NO_CHECK,
1210 016d04b3 Michael Hanselmann
    constants.HV_BOOT_ORDER: (True, ) +
1211 016d04b3 Michael Hanselmann
      (lambda x: x and len(x.strip("acdn")) == 0,
1212 016d04b3 Michael Hanselmann
       "Invalid boot order specified, must be one or more of [acdn]",
1213 016d04b3 Michael Hanselmann
       None, None),
1214 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
1215 016d04b3 Michael Hanselmann
    constants.HV_DISK_TYPE:
1216 016d04b3 Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_HVM_VALID_DISK_TYPES),
1217 016d04b3 Michael Hanselmann
    constants.HV_NIC_TYPE:
1218 016d04b3 Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_HVM_VALID_NIC_TYPES),
1219 205ab586 Iustin Pop
    constants.HV_PAE: hv_base.NO_CHECK,
1220 016d04b3 Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS:
1221 8b312c1d Manuel Franceschini
      (False, netutils.IP4Address.IsValid,
1222 016d04b3 Michael Hanselmann
       "VNC bind address is not a valid IP address", None, None),
1223 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.REQ_FILE_CHECK,
1224 205ab586 Iustin Pop
    constants.HV_DEVICE_MODEL: hv_base.REQ_FILE_CHECK,
1225 6e6bb8d5 Guido Trotter
    constants.HV_VNC_PASSWORD_FILE: hv_base.REQ_FILE_CHECK,
1226 e2d14329 Andrea Spadaccini
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
1227 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
1228 6b970cef Jun Futagawa
    constants.HV_USE_LOCALTIME: hv_base.NO_CHECK,
1229 e695efbf Iustin Pop
    # TODO: Add a check for the blockdev prefix (matching [a-z:] or similar).
1230 e695efbf Iustin Pop
    constants.HV_BLOCKDEV_PREFIX: hv_base.NO_CHECK,
1231 87f0aa48 Jack
    # Add PCI passthrough
1232 3891c95e Bernardo Dal Seno
    constants.HV_PASSTHROUGH: hv_base.NO_CHECK,
1233 990ade2d Stephen Shirley
    constants.HV_REBOOT_BEHAVIOR:
1234 c4708267 Tsachy Shacham
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS),
1235 c4708267 Tsachy Shacham
    constants.HV_CPU_MASK: hv_base.OPT_MULTI_CPU_MASK_CHECK,
1236 8bd977e9 Sébastien Bocahu
    constants.HV_CPU_CAP: hv_base.NO_CHECK,
1237 8bd977e9 Sébastien Bocahu
    constants.HV_CPU_WEIGHT:
1238 8bd977e9 Sébastien Bocahu
      (False, lambda x: 0 < x < 65535, "invalid weight", None, None),
1239 05440845 Helga Velroyen
    constants.HV_VIF_TYPE:
1240 05440845 Helga Velroyen
      hv_base.ParamInSet(False, constants.HT_HVM_VALID_VIF_TYPES),
1241 397b7844 Dimitris Aragiorgis
    constants.HV_VIF_SCRIPT: hv_base.OPT_FILE_CHECK,
1242 ffc27116 Thomas Thrainer
    constants.HV_VIRIDIAN: hv_base.NO_CHECK,
1243 740394bc Helga Velroyen
    constants.HV_XEN_CMD:
1244 740394bc Helga Velroyen
      hv_base.ParamInSet(True, constants.KNOWN_XEN_COMMANDS),
1245 295ed29b Santi Raffa
    constants.HV_XEN_CPUID: hv_base.NO_CHECK,
1246 b5cad580 Raffa Santi
    constants.HV_SOUNDHW: hv_base.NO_CHECK,
1247 205ab586 Iustin Pop
    }
1248 09ea8710 Iustin Pop
1249 c3d839f5 Michael Hanselmann
  def _GetConfig(self, instance, startup_memory, block_devices):
1250 65a6f9b7 Michael Hanselmann
    """Create a Xen 3.1 HVM config file.
1251 65a6f9b7 Michael Hanselmann

1252 65a6f9b7 Michael Hanselmann
    """
1253 a985b417 Iustin Pop
    hvp = instance.hvparams
1254 a985b417 Iustin Pop
1255 65a6f9b7 Michael Hanselmann
    config = StringIO()
1256 e2ee1cea Iustin Pop
1257 e2ee1cea Iustin Pop
    # kernel handling
1258 e2ee1cea Iustin Pop
    kpath = hvp[constants.HV_KERNEL_PATH]
1259 e2ee1cea Iustin Pop
    config.write("kernel = '%s'\n" % kpath)
1260 e2ee1cea Iustin Pop
1261 65a6f9b7 Michael Hanselmann
    config.write("builder = 'hvm'\n")
1262 61eb1a46 Guido Trotter
    config.write("memory = %d\n" % startup_memory)
1263 80121c83 Guido Trotter
    config.write("maxmem = %d\n" % instance.beparams[constants.BE_MAXMEM])
1264 8b3fd458 Iustin Pop
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
1265 347fa0f1 Michael Hanselmann
    cpu_pinning = _CreateConfigCpus(hvp[constants.HV_CPU_MASK])
1266 c4708267 Tsachy Shacham
    if cpu_pinning:
1267 c4708267 Tsachy Shacham
      config.write("%s\n" % cpu_pinning)
1268 8bd977e9 Sébastien Bocahu
    cpu_cap = hvp[constants.HV_CPU_CAP]
1269 8bd977e9 Sébastien Bocahu
    if cpu_cap:
1270 8bd977e9 Sébastien Bocahu
      config.write("cpu_cap=%d\n" % cpu_cap)
1271 8bd977e9 Sébastien Bocahu
    cpu_weight = hvp[constants.HV_CPU_WEIGHT]
1272 8bd977e9 Sébastien Bocahu
    if cpu_weight:
1273 8bd977e9 Sébastien Bocahu
      config.write("cpu_weight=%d\n" % cpu_weight)
1274 c4708267 Tsachy Shacham
1275 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
1276 09ea8710 Iustin Pop
    if hvp[constants.HV_PAE]:
1277 a21dda8b Iustin Pop
      config.write("pae = 1\n")
1278 a21dda8b Iustin Pop
    else:
1279 a21dda8b Iustin Pop
      config.write("pae = 0\n")
1280 09ea8710 Iustin Pop
    if hvp[constants.HV_ACPI]:
1281 a21dda8b Iustin Pop
      config.write("acpi = 1\n")
1282 a21dda8b Iustin Pop
    else:
1283 a21dda8b Iustin Pop
      config.write("acpi = 0\n")
1284 ffc27116 Thomas Thrainer
    if hvp[constants.HV_VIRIDIAN]:
1285 ffc27116 Thomas Thrainer
      config.write("viridian = 1\n")
1286 ffc27116 Thomas Thrainer
    else:
1287 ffc27116 Thomas Thrainer
      config.write("viridian = 0\n")
1288 ffc27116 Thomas Thrainer
1289 65a6f9b7 Michael Hanselmann
    config.write("apic = 1\n")
1290 09ea8710 Iustin Pop
    config.write("device_model = '%s'\n" % hvp[constants.HV_DEVICE_MODEL])
1291 a985b417 Iustin Pop
    config.write("boot = '%s'\n" % hvp[constants.HV_BOOT_ORDER])
1292 65a6f9b7 Michael Hanselmann
    config.write("sdl = 0\n")
1293 97efde45 Guido Trotter
    config.write("usb = 1\n")
1294 97efde45 Guido Trotter
    config.write("usbdevice = 'tablet'\n")
1295 65a6f9b7 Michael Hanselmann
    config.write("vnc = 1\n")
1296 a985b417 Iustin Pop
    if hvp[constants.HV_VNC_BIND_ADDRESS] is None:
1297 d0c11cf7 Alexander Schreiber
      config.write("vnclisten = '%s'\n" % constants.VNC_DEFAULT_BIND_ADDRESS)
1298 d0c11cf7 Alexander Schreiber
    else:
1299 6b405598 Guido Trotter
      config.write("vnclisten = '%s'\n" % hvp[constants.HV_VNC_BIND_ADDRESS])
1300 65a6f9b7 Michael Hanselmann
1301 377d74c9 Guido Trotter
    if instance.network_port > constants.VNC_BASE_PORT:
1302 377d74c9 Guido Trotter
      display = instance.network_port - constants.VNC_BASE_PORT
1303 65a6f9b7 Michael Hanselmann
      config.write("vncdisplay = %s\n" % display)
1304 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 0\n")
1305 65a6f9b7 Michael Hanselmann
    else:
1306 65a6f9b7 Michael Hanselmann
      config.write("# vncdisplay = 1\n")
1307 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 1\n")
1308 65a6f9b7 Michael Hanselmann
1309 6e6bb8d5 Guido Trotter
    vnc_pwd_file = hvp[constants.HV_VNC_PASSWORD_FILE]
1310 65a6f9b7 Michael Hanselmann
    try:
1311 6e6bb8d5 Guido Trotter
      password = utils.ReadFile(vnc_pwd_file)
1312 78f66a17 Guido Trotter
    except EnvironmentError, err:
1313 78f66a17 Guido Trotter
      raise errors.HypervisorError("Failed to open VNC password file %s: %s" %
1314 6e6bb8d5 Guido Trotter
                                   (vnc_pwd_file, err))
1315 65a6f9b7 Michael Hanselmann
1316 65a6f9b7 Michael Hanselmann
    config.write("vncpasswd = '%s'\n" % password.rstrip())
1317 65a6f9b7 Michael Hanselmann
1318 65a6f9b7 Michael Hanselmann
    config.write("serial = 'pty'\n")
1319 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
1320 6b970cef Jun Futagawa
      config.write("localtime = 1\n")
1321 65a6f9b7 Michael Hanselmann
1322 65a6f9b7 Michael Hanselmann
    vif_data = []
1323 05440845 Helga Velroyen
    # Note: what is called 'nic_type' here, is used as value for the xen nic
1324 05440845 Helga Velroyen
    # vif config parameter 'model'. For the xen nic vif parameter 'type', we use
1325 05440845 Helga Velroyen
    # the 'vif_type' to avoid a clash of notation.
1326 a985b417 Iustin Pop
    nic_type = hvp[constants.HV_NIC_TYPE]
1327 05440845 Helga Velroyen
1328 f48148c3 Iustin Pop
    if nic_type is None:
1329 05440845 Helga Velroyen
      vif_type_str = ""
1330 05440845 Helga Velroyen
      if hvp[constants.HV_VIF_TYPE]:
1331 05440845 Helga Velroyen
        vif_type_str = ", type=%s" % hvp[constants.HV_VIF_TYPE]
1332 f48148c3 Iustin Pop
      # ensure old instances don't change
1333 05440845 Helga Velroyen
      nic_type_str = vif_type_str
1334 d08f6067 Guido Trotter
    elif nic_type == constants.HT_NIC_PARAVIRTUAL:
1335 f48148c3 Iustin Pop
      nic_type_str = ", type=paravirtualized"
1336 f48148c3 Iustin Pop
    else:
1337 05440845 Helga Velroyen
      # parameter 'model' is only valid with type 'ioemu'
1338 05440845 Helga Velroyen
      nic_type_str = ", model=%s, type=%s" % \
1339 05440845 Helga Velroyen
        (nic_type, constants.HT_HVM_VIF_IOEMU)
1340 397b7844 Dimitris Aragiorgis
    for idx, nic in enumerate(instance.nics):
1341 503b97a9 Guido Trotter
      nic_str = "mac=%s%s" % (nic.mac, nic_type_str)
1342 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
1343 65a6f9b7 Michael Hanselmann
      if ip is not None:
1344 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
1345 503b97a9 Guido Trotter
      if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
1346 503b97a9 Guido Trotter
        nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK]
1347 397b7844 Dimitris Aragiorgis
      if hvp[constants.HV_VIF_SCRIPT]:
1348 397b7844 Dimitris Aragiorgis
        nic_str += ", script=%s" % hvp[constants.HV_VIF_SCRIPT]
1349 0183a697 Alessandro Cincaglini
      vif_data.append("'%s'" % nic_str)
1350 2a3bbbaa Dimitris Aragiorgis
      self._WriteNICInfoFile(instance, idx, nic)
1351 65a6f9b7 Michael Hanselmann
1352 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
1353 525011bc Maciej Bliziński
1354 d0bb3f24 Michael Hanselmann
    disk_data = \
1355 d0bb3f24 Michael Hanselmann
      _GetConfigFileDiskData(block_devices, hvp[constants.HV_BLOCKDEV_PREFIX])
1356 525011bc Maciej Bliziński
1357 a985b417 Iustin Pop
    iso_path = hvp[constants.HV_CDROM_IMAGE_PATH]
1358 f48148c3 Iustin Pop
    if iso_path:
1359 f48148c3 Iustin Pop
      iso = "'file:%s,hdc:cdrom,r'" % iso_path
1360 a21dda8b Iustin Pop
      disk_data.append(iso)
1361 a21dda8b Iustin Pop
1362 a21dda8b Iustin Pop
    config.write("disk = [%s]\n" % (",".join(disk_data)))
1363 87f0aa48 Jack
    # Add PCI passthrough
1364 87f0aa48 Jack
    pci_pass_arr = []
1365 87f0aa48 Jack
    pci_pass = hvp[constants.HV_PASSTHROUGH]
1366 87f0aa48 Jack
    if pci_pass:
1367 3891c95e Bernardo Dal Seno
      pci_pass_arr = pci_pass.split(";")
1368 3891c95e Bernardo Dal Seno
      config.write("pci = %s\n" % pci_pass_arr)
1369 931419e5 Jose A. Lopes
1370 931419e5 Jose A. Lopes
    WriteXenConfigEvents(config, hvp)
1371 73cd67f4 Guido Trotter
1372 295ed29b Santi Raffa
    cpuid = hvp[constants.HV_XEN_CPUID]
1373 295ed29b Santi Raffa
    if cpuid:
1374 295ed29b Santi Raffa
      config.write("cpuid = %s\n" % _QuoteCpuidField(cpuid))
1375 295ed29b Santi Raffa
1376 b5cad580 Raffa Santi
    if hvp[constants.HV_SOUNDHW]:
1377 b5cad580 Raffa Santi
      config.write("soundhw = '%s'\n" % hvp[constants.HV_SOUNDHW])
1378 b5cad580 Raffa Santi
1379 c3d839f5 Michael Hanselmann
    return config.getvalue()