Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ 3213d3c8

History | View | Annotate | Download (22.4 kB)

1 65a6f9b7 Michael Hanselmann
#
2 65a6f9b7 Michael Hanselmann
#
3 65a6f9b7 Michael Hanselmann
4 65a6f9b7 Michael Hanselmann
# Copyright (C) 2006, 2007, 2008 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 65a6f9b7 Michael Hanselmann
import os
27 65a6f9b7 Michael Hanselmann
import os.path
28 65a6f9b7 Michael Hanselmann
import time
29 b48909c8 Iustin Pop
import logging
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 65a6f9b7 Michael Hanselmann
37 65a6f9b7 Michael Hanselmann
38 a2d32034 Michael Hanselmann
class XenHypervisor(hv_base.BaseHypervisor):
39 65a6f9b7 Michael Hanselmann
  """Xen generic hypervisor interface
40 65a6f9b7 Michael Hanselmann

41 65a6f9b7 Michael Hanselmann
  This is the Xen base class used for both Xen PVM and HVM. It contains
42 65a6f9b7 Michael Hanselmann
  all the functionality that is identical for both.
43 65a6f9b7 Michael Hanselmann

44 65a6f9b7 Michael Hanselmann
  """
45 65a6f9b7 Michael Hanselmann
46 5661b908 Iustin Pop
  @classmethod
47 5661b908 Iustin Pop
  def _WriteConfigFile(cls, instance, block_devices, extra_args):
48 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
49 65a6f9b7 Michael Hanselmann

50 65a6f9b7 Michael Hanselmann
    """
51 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
52 65a6f9b7 Michael Hanselmann
53 65a6f9b7 Michael Hanselmann
  @staticmethod
54 4390ccff Guido Trotter
  def _WriteConfigFileStatic(instance_name, data):
55 4390ccff Guido Trotter
    """Write the Xen config file for the instance.
56 4390ccff Guido Trotter

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

59 4390ccff Guido Trotter
    """
60 4390ccff Guido Trotter
    utils.WriteFile("/etc/xen/%s" % instance_name, data=data)
61 4390ccff Guido Trotter
62 4390ccff Guido Trotter
  @staticmethod
63 4390ccff Guido Trotter
  def _ReadConfigFile(instance_name):
64 4390ccff Guido Trotter
    """Returns the contents of the instance config file.
65 4390ccff Guido Trotter

66 4390ccff Guido Trotter
    """
67 4390ccff Guido Trotter
    try:
68 4390ccff Guido Trotter
      file_content = utils.ReadFile("/etc/xen/%s" % instance_name)
69 4390ccff Guido Trotter
    except EnvironmentError, err:
70 4390ccff Guido Trotter
      raise errors.HypervisorError("Failed to load Xen config file: %s" % err)
71 4390ccff Guido Trotter
    return file_content
72 4390ccff Guido Trotter
73 4390ccff Guido Trotter
  @staticmethod
74 53c776b5 Iustin Pop
  def _RemoveConfigFile(instance_name):
75 65a6f9b7 Michael Hanselmann
    """Remove the xen configuration file.
76 65a6f9b7 Michael Hanselmann

77 65a6f9b7 Michael Hanselmann
    """
78 53c776b5 Iustin Pop
    utils.RemoveFile("/etc/xen/%s" % instance_name)
79 65a6f9b7 Michael Hanselmann
80 65a6f9b7 Michael Hanselmann
  @staticmethod
81 65a6f9b7 Michael Hanselmann
  def _GetXMList(include_node):
82 65a6f9b7 Michael Hanselmann
    """Return the list of running instances.
83 65a6f9b7 Michael Hanselmann

84 c41eea6e Iustin Pop
    If the include_node argument is True, then we return information
85 65a6f9b7 Michael Hanselmann
    for dom0 also, otherwise we filter that from the return value.
86 65a6f9b7 Michael Hanselmann

87 c41eea6e Iustin Pop
    @return: list of (name, id, memory, vcpus, state, time spent)
88 65a6f9b7 Michael Hanselmann

89 65a6f9b7 Michael Hanselmann
    """
90 65a6f9b7 Michael Hanselmann
    for dummy in range(5):
91 65a6f9b7 Michael Hanselmann
      result = utils.RunCmd(["xm", "list"])
92 65a6f9b7 Michael Hanselmann
      if not result.failed:
93 65a6f9b7 Michael Hanselmann
        break
94 b48909c8 Iustin Pop
      logging.error("xm list failed (%s): %s", result.fail_reason,
95 b48909c8 Iustin Pop
                    result.output)
96 65a6f9b7 Michael Hanselmann
      time.sleep(1)
97 65a6f9b7 Michael Hanselmann
98 65a6f9b7 Michael Hanselmann
    if result.failed:
99 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("xm list failed, retries"
100 65a6f9b7 Michael Hanselmann
                                   " exceeded (%s): %s" %
101 3213d3c8 Iustin Pop
                                   (result.fail_reason, result.output))
102 65a6f9b7 Michael Hanselmann
103 65a6f9b7 Michael Hanselmann
    # skip over the heading
104 65a6f9b7 Michael Hanselmann
    lines = result.stdout.splitlines()[1:]
105 65a6f9b7 Michael Hanselmann
    result = []
106 65a6f9b7 Michael Hanselmann
    for line in lines:
107 65a6f9b7 Michael Hanselmann
      # The format of lines is:
108 65a6f9b7 Michael Hanselmann
      # Name      ID Mem(MiB) VCPUs State  Time(s)
109 65a6f9b7 Michael Hanselmann
      # Domain-0   0  3418     4 r-----    266.2
110 65a6f9b7 Michael Hanselmann
      data = line.split()
111 65a6f9b7 Michael Hanselmann
      if len(data) != 6:
112 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("Can't parse output of xm list,"
113 65a6f9b7 Michael Hanselmann
                                     " line: %s" % line)
114 65a6f9b7 Michael Hanselmann
      try:
115 65a6f9b7 Michael Hanselmann
        data[1] = int(data[1])
116 65a6f9b7 Michael Hanselmann
        data[2] = int(data[2])
117 65a6f9b7 Michael Hanselmann
        data[3] = int(data[3])
118 65a6f9b7 Michael Hanselmann
        data[5] = float(data[5])
119 65a6f9b7 Michael Hanselmann
      except ValueError, err:
120 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("Can't parse output of xm list,"
121 65a6f9b7 Michael Hanselmann
                                     " line: %s, error: %s" % (line, err))
122 65a6f9b7 Michael Hanselmann
123 65a6f9b7 Michael Hanselmann
      # skip the Domain-0 (optional)
124 65a6f9b7 Michael Hanselmann
      if include_node or data[0] != 'Domain-0':
125 65a6f9b7 Michael Hanselmann
        result.append(data)
126 65a6f9b7 Michael Hanselmann
127 65a6f9b7 Michael Hanselmann
    return result
128 65a6f9b7 Michael Hanselmann
129 65a6f9b7 Michael Hanselmann
  def ListInstances(self):
130 65a6f9b7 Michael Hanselmann
    """Get the list of running instances.
131 65a6f9b7 Michael Hanselmann

132 65a6f9b7 Michael Hanselmann
    """
133 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(False)
134 65a6f9b7 Michael Hanselmann
    names = [info[0] for info in xm_list]
135 65a6f9b7 Michael Hanselmann
    return names
136 65a6f9b7 Michael Hanselmann
137 65a6f9b7 Michael Hanselmann
  def GetInstanceInfo(self, instance_name):
138 65a6f9b7 Michael Hanselmann
    """Get instance properties.
139 65a6f9b7 Michael Hanselmann

140 c41eea6e Iustin Pop
    @param instance_name: the instance name
141 c41eea6e Iustin Pop

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

144 65a6f9b7 Michael Hanselmann
    """
145 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(instance_name=="Domain-0")
146 65a6f9b7 Michael Hanselmann
    result = None
147 65a6f9b7 Michael Hanselmann
    for data in xm_list:
148 65a6f9b7 Michael Hanselmann
      if data[0] == instance_name:
149 65a6f9b7 Michael Hanselmann
        result = data
150 65a6f9b7 Michael Hanselmann
        break
151 65a6f9b7 Michael Hanselmann
    return result
152 65a6f9b7 Michael Hanselmann
153 65a6f9b7 Michael Hanselmann
  def GetAllInstancesInfo(self):
154 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
155 65a6f9b7 Michael Hanselmann

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

158 65a6f9b7 Michael Hanselmann
    """
159 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(False)
160 65a6f9b7 Michael Hanselmann
    return xm_list
161 65a6f9b7 Michael Hanselmann
162 65a6f9b7 Michael Hanselmann
  def StartInstance(self, instance, block_devices, extra_args):
163 c41eea6e Iustin Pop
    """Start an instance.
164 c41eea6e Iustin Pop

165 c41eea6e Iustin Pop
    """
166 65a6f9b7 Michael Hanselmann
    self._WriteConfigFile(instance, block_devices, extra_args)
167 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(["xm", "create", instance.name])
168 65a6f9b7 Michael Hanselmann
169 65a6f9b7 Michael Hanselmann
    if result.failed:
170 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
171 65a6f9b7 Michael Hanselmann
                                   (instance.name, result.fail_reason,
172 65a6f9b7 Michael Hanselmann
                                    result.output))
173 65a6f9b7 Michael Hanselmann
174 65a6f9b7 Michael Hanselmann
  def StopInstance(self, instance, force=False):
175 c41eea6e Iustin Pop
    """Stop an instance.
176 c41eea6e Iustin Pop

177 c41eea6e Iustin Pop
    """
178 53c776b5 Iustin Pop
    self._RemoveConfigFile(instance.name)
179 65a6f9b7 Michael Hanselmann
    if force:
180 65a6f9b7 Michael Hanselmann
      command = ["xm", "destroy", instance.name]
181 65a6f9b7 Michael Hanselmann
    else:
182 65a6f9b7 Michael Hanselmann
      command = ["xm", "shutdown", instance.name]
183 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(command)
184 65a6f9b7 Michael Hanselmann
185 65a6f9b7 Michael Hanselmann
    if result.failed:
186 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to stop instance %s: %s, %s" %
187 3213d3c8 Iustin Pop
                                   (instance.name, result.fail_reason,
188 3213d3c8 Iustin Pop
                                    result.output))
189 65a6f9b7 Michael Hanselmann
190 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
191 c41eea6e Iustin Pop
    """Reboot an instance.
192 c41eea6e Iustin Pop

193 c41eea6e Iustin Pop
    """
194 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(["xm", "reboot", instance.name])
195 65a6f9b7 Michael Hanselmann
196 65a6f9b7 Michael Hanselmann
    if result.failed:
197 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s: %s, %s" %
198 3213d3c8 Iustin Pop
                                   (instance.name, result.fail_reason,
199 3213d3c8 Iustin Pop
                                    result.output))
200 65a6f9b7 Michael Hanselmann
201 65a6f9b7 Michael Hanselmann
  def GetNodeInfo(self):
202 65a6f9b7 Michael Hanselmann
    """Return information about the node.
203 65a6f9b7 Michael Hanselmann

204 0105bad3 Iustin Pop
    @return: a dict with the following keys (memory values in MiB):
205 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
206 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
207 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
208 0105bad3 Iustin Pop
          - nr_cpus: total number of CPUs
209 0105bad3 Iustin Pop
          - nr_nodes: in a NUMA system, the number of domains
210 0105bad3 Iustin Pop
          - nr_sockets: the number of physical CPU sockets in the node
211 65a6f9b7 Michael Hanselmann

212 65a6f9b7 Michael Hanselmann
    """
213 65a6f9b7 Michael Hanselmann
    # note: in xen 3, memory has changed to total_memory
214 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(["xm", "info"])
215 65a6f9b7 Michael Hanselmann
    if result.failed:
216 b48909c8 Iustin Pop
      logging.error("Can't run 'xm info' (%s): %s", result.fail_reason,
217 b48909c8 Iustin Pop
                    result.output)
218 65a6f9b7 Michael Hanselmann
      return None
219 65a6f9b7 Michael Hanselmann
220 65a6f9b7 Michael Hanselmann
    xmoutput = result.stdout.splitlines()
221 65a6f9b7 Michael Hanselmann
    result = {}
222 0105bad3 Iustin Pop
    cores_per_socket = threads_per_core = nr_cpus = None
223 65a6f9b7 Michael Hanselmann
    for line in xmoutput:
224 65a6f9b7 Michael Hanselmann
      splitfields = line.split(":", 1)
225 65a6f9b7 Michael Hanselmann
226 65a6f9b7 Michael Hanselmann
      if len(splitfields) > 1:
227 65a6f9b7 Michael Hanselmann
        key = splitfields[0].strip()
228 65a6f9b7 Michael Hanselmann
        val = splitfields[1].strip()
229 65a6f9b7 Michael Hanselmann
        if key == 'memory' or key == 'total_memory':
230 65a6f9b7 Michael Hanselmann
          result['memory_total'] = int(val)
231 65a6f9b7 Michael Hanselmann
        elif key == 'free_memory':
232 65a6f9b7 Michael Hanselmann
          result['memory_free'] = int(val)
233 e8a4c138 Iustin Pop
        elif key == 'nr_cpus':
234 0105bad3 Iustin Pop
          nr_cpus = result['cpu_total'] = int(val)
235 0105bad3 Iustin Pop
        elif key == 'nr_nodes':
236 0105bad3 Iustin Pop
          result['cpu_nodes'] = int(val)
237 0105bad3 Iustin Pop
        elif key == 'cores_per_socket':
238 0105bad3 Iustin Pop
          cores_per_socket = int(val)
239 0105bad3 Iustin Pop
        elif key == 'threads_per_core':
240 0105bad3 Iustin Pop
          threads_per_core = int(val)
241 0105bad3 Iustin Pop
242 0105bad3 Iustin Pop
    if (cores_per_socket is not None and
243 0105bad3 Iustin Pop
        threads_per_core is not None and nr_cpus is not None):
244 0105bad3 Iustin Pop
      result['cpu_sockets'] = nr_cpus / (cores_per_socket * threads_per_core)
245 0105bad3 Iustin Pop
246 65a6f9b7 Michael Hanselmann
    dom0_info = self.GetInstanceInfo("Domain-0")
247 65a6f9b7 Michael Hanselmann
    if dom0_info is not None:
248 65a6f9b7 Michael Hanselmann
      result['memory_dom0'] = dom0_info[2]
249 65a6f9b7 Michael Hanselmann
250 65a6f9b7 Michael Hanselmann
    return result
251 65a6f9b7 Michael Hanselmann
252 637ce7f9 Guido Trotter
  @classmethod
253 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
254 65a6f9b7 Michael Hanselmann
    """Return a command for connecting to the console of an instance.
255 65a6f9b7 Michael Hanselmann

256 65a6f9b7 Michael Hanselmann
    """
257 04c4330c Alexander Schreiber
    return "xm console %s" % instance.name
258 04c4330c Alexander Schreiber
259 65a6f9b7 Michael Hanselmann
260 65a6f9b7 Michael Hanselmann
  def Verify(self):
261 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
262 65a6f9b7 Michael Hanselmann

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

265 65a6f9b7 Michael Hanselmann
    """
266 e3e66f02 Michael Hanselmann
    result = utils.RunCmd(["xm", "info"])
267 e3e66f02 Michael Hanselmann
    if result.failed:
268 3213d3c8 Iustin Pop
      return "'xm info' failed: %s, %s" % (result.fail_reason, result.output)
269 65a6f9b7 Michael Hanselmann
270 65a6f9b7 Michael Hanselmann
  @staticmethod
271 65a6f9b7 Michael Hanselmann
  def _GetConfigFileDiskData(disk_template, block_devices):
272 65a6f9b7 Michael Hanselmann
    """Get disk directive for xen config file.
273 65a6f9b7 Michael Hanselmann

274 65a6f9b7 Michael Hanselmann
    This method builds the xen config disk directive according to the
275 65a6f9b7 Michael Hanselmann
    given disk_template and block_devices.
276 65a6f9b7 Michael Hanselmann

277 c41eea6e Iustin Pop
    @param disk_template: string containing instance disk template
278 c41eea6e Iustin Pop
    @param block_devices: list of tuples (cfdev, rldev):
279 c41eea6e Iustin Pop
        - cfdev: dict containing ganeti config disk part
280 c41eea6e Iustin Pop
        - rldev: ganeti.bdev.BlockDev object
281 65a6f9b7 Michael Hanselmann

282 c41eea6e Iustin Pop
    @return: string containing disk directive for xen instance config file
283 65a6f9b7 Michael Hanselmann

284 65a6f9b7 Michael Hanselmann
    """
285 65a6f9b7 Michael Hanselmann
    FILE_DRIVER_MAP = {
286 65a6f9b7 Michael Hanselmann
      constants.FD_LOOP: "file",
287 65a6f9b7 Michael Hanselmann
      constants.FD_BLKTAP: "tap:aio",
288 65a6f9b7 Michael Hanselmann
      }
289 65a6f9b7 Michael Hanselmann
    disk_data = []
290 2864f2d9 Iustin Pop
    if len(block_devices) > 24:
291 2864f2d9 Iustin Pop
      # 'z' - 'a' = 24
292 2864f2d9 Iustin Pop
      raise errors.HypervisorError("Too many disks")
293 2864f2d9 Iustin Pop
    # FIXME: instead of this hardcoding here, each of PVM/HVM should
294 2864f2d9 Iustin Pop
    # directly export their info (currently HVM will just sed this info)
295 2864f2d9 Iustin Pop
    namespace = ["sd" + chr(i + ord('a')) for i in range(24)]
296 069cfbf1 Iustin Pop
    for sd_name, (cfdev, dev_path) in zip(namespace, block_devices):
297 d34b16d7 Iustin Pop
      if cfdev.mode == constants.DISK_RDWR:
298 d34b16d7 Iustin Pop
        mode = "w"
299 d34b16d7 Iustin Pop
      else:
300 d34b16d7 Iustin Pop
        mode = "r"
301 65a6f9b7 Michael Hanselmann
      if cfdev.dev_type == constants.LD_FILE:
302 d34b16d7 Iustin Pop
        line = "'%s:%s,%s,%s'" % (FILE_DRIVER_MAP[cfdev.physical_id[0]],
303 d34b16d7 Iustin Pop
                                  dev_path, sd_name, mode)
304 65a6f9b7 Michael Hanselmann
      else:
305 d34b16d7 Iustin Pop
        line = "'phy:%s,%s,%s'" % (dev_path, sd_name, mode)
306 65a6f9b7 Michael Hanselmann
      disk_data.append(line)
307 65a6f9b7 Michael Hanselmann
308 65a6f9b7 Michael Hanselmann
    return disk_data
309 65a6f9b7 Michael Hanselmann
310 4390ccff Guido Trotter
  def MigrationInfo(self, instance):
311 4390ccff Guido Trotter
    """Get instance information to perform a migration.
312 4390ccff Guido Trotter

313 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
314 4390ccff Guido Trotter
    @param instance: instance to be migrated
315 4390ccff Guido Trotter
    @rtype: string
316 4390ccff Guido Trotter
    @return: content of the xen config file
317 4390ccff Guido Trotter

318 4390ccff Guido Trotter
    """
319 4390ccff Guido Trotter
    return self._ReadConfigFile(instance.name)
320 4390ccff Guido Trotter
321 4390ccff Guido Trotter
  def AcceptInstance(self, instance, info, target):
322 4390ccff Guido Trotter
    """Prepare to accept an instance.
323 4390ccff Guido Trotter

324 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
325 4390ccff Guido Trotter
    @param instance: instance to be accepted
326 4390ccff Guido Trotter
    @type info: string
327 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
328 4390ccff Guido Trotter
    @type target: string
329 4390ccff Guido Trotter
    @param target: target host (usually ip), on this node
330 4390ccff Guido Trotter

331 4390ccff Guido Trotter
    """
332 4390ccff Guido Trotter
    pass
333 4390ccff Guido Trotter
334 4390ccff Guido Trotter
  def FinalizeMigration(self, instance, info, success):
335 4390ccff Guido Trotter
    """Finalize an instance migration.
336 4390ccff Guido Trotter

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

340 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
341 4390ccff Guido Trotter
    @param instance: instance whose migration is being aborted
342 4390ccff Guido Trotter
    @type info: string
343 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
344 4390ccff Guido Trotter
    @type success: boolean
345 4390ccff Guido Trotter
    @param success: whether the migration was a success or a failure
346 4390ccff Guido Trotter

347 4390ccff Guido Trotter
    """
348 4390ccff Guido Trotter
    if success:
349 4390ccff Guido Trotter
      self._WriteConfigFileStatic(instance.name, info)
350 4390ccff Guido Trotter
351 6e7275c0 Iustin Pop
  def MigrateInstance(self, instance, target, live):
352 6e7275c0 Iustin Pop
    """Migrate an instance to a target node.
353 6e7275c0 Iustin Pop

354 6e7275c0 Iustin Pop
    The migration will not be attempted if the instance is not
355 6e7275c0 Iustin Pop
    currently running.
356 6e7275c0 Iustin Pop

357 fdf7f055 Guido Trotter
    @type instance: string
358 fdf7f055 Guido Trotter
    @param instance: instance name
359 fdf7f055 Guido Trotter
    @type target: string
360 fdf7f055 Guido Trotter
    @param target: ip address of the target node
361 fdf7f055 Guido Trotter
    @type live: boolean
362 fdf7f055 Guido Trotter
    @param live: perform a live migration
363 fdf7f055 Guido Trotter

364 6e7275c0 Iustin Pop
    """
365 6e7275c0 Iustin Pop
    if self.GetInstanceInfo(instance) is None:
366 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Instance not running, cannot migrate")
367 6e7275c0 Iustin Pop
    args = ["xm", "migrate"]
368 6e7275c0 Iustin Pop
    if live:
369 6e7275c0 Iustin Pop
      args.append("-l")
370 6e7275c0 Iustin Pop
    args.extend([instance, target])
371 6e7275c0 Iustin Pop
    result = utils.RunCmd(args)
372 6e7275c0 Iustin Pop
    if result.failed:
373 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Failed to migrate instance %s: %s" %
374 6e7275c0 Iustin Pop
                                   (instance, result.output))
375 53c776b5 Iustin Pop
    # remove old xen file after migration succeeded
376 53c776b5 Iustin Pop
    try:
377 53c776b5 Iustin Pop
      self._RemoveConfigFile(instance)
378 c979d253 Iustin Pop
    except EnvironmentError:
379 c979d253 Iustin Pop
      logging.exception("Failure while removing instance config file")
380 6e7275c0 Iustin Pop
381 65a6f9b7 Michael Hanselmann
382 65a6f9b7 Michael Hanselmann
class XenPvmHypervisor(XenHypervisor):
383 65a6f9b7 Michael Hanselmann
  """Xen PVM hypervisor interface"""
384 65a6f9b7 Michael Hanselmann
385 f48148c3 Iustin Pop
  PARAMETERS = [
386 f48148c3 Iustin Pop
    constants.HV_KERNEL_PATH,
387 f48148c3 Iustin Pop
    constants.HV_INITRD_PATH,
388 074ca009 Guido Trotter
    constants.HV_ROOT_PATH,
389 f48148c3 Iustin Pop
    ]
390 f48148c3 Iustin Pop
391 f48148c3 Iustin Pop
  @classmethod
392 f48148c3 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
393 f48148c3 Iustin Pop
    """Check the given parameters for validity.
394 f48148c3 Iustin Pop

395 f48148c3 Iustin Pop
    For the PVM hypervisor, this only check the existence of the
396 f48148c3 Iustin Pop
    kernel.
397 f48148c3 Iustin Pop

398 f48148c3 Iustin Pop
    @type hvparams:  dict
399 f48148c3 Iustin Pop
    @param hvparams: dictionary with parameter names/value
400 f48148c3 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
401 f48148c3 Iustin Pop

402 f48148c3 Iustin Pop
    """
403 f48148c3 Iustin Pop
    super(XenPvmHypervisor, cls).CheckParameterSyntax(hvparams)
404 f48148c3 Iustin Pop
405 f48148c3 Iustin Pop
    if not hvparams[constants.HV_KERNEL_PATH]:
406 f48148c3 Iustin Pop
      raise errors.HypervisorError("Need a kernel for the instance")
407 f48148c3 Iustin Pop
408 f48148c3 Iustin Pop
    if not os.path.isabs(hvparams[constants.HV_KERNEL_PATH]):
409 50cb2e2a Guido Trotter
      raise errors.HypervisorError("The kernel path must be an absolute path")
410 f48148c3 Iustin Pop
411 074ca009 Guido Trotter
    if not hvparams[constants.HV_ROOT_PATH]:
412 074ca009 Guido Trotter
      raise errors.HypervisorError("Need a root partition for the instance")
413 074ca009 Guido Trotter
414 f48148c3 Iustin Pop
    if hvparams[constants.HV_INITRD_PATH]:
415 f48148c3 Iustin Pop
      if not os.path.isabs(hvparams[constants.HV_INITRD_PATH]):
416 50cb2e2a Guido Trotter
        raise errors.HypervisorError("The initrd path must be an absolute path"
417 f48148c3 Iustin Pop
                                     ", if defined")
418 f48148c3 Iustin Pop
419 f48148c3 Iustin Pop
  def ValidateParameters(self, hvparams):
420 f48148c3 Iustin Pop
    """Check the given parameters for validity.
421 f48148c3 Iustin Pop

422 f48148c3 Iustin Pop
    For the PVM hypervisor, this only check the existence of the
423 f48148c3 Iustin Pop
    kernel.
424 f48148c3 Iustin Pop

425 f48148c3 Iustin Pop
    """
426 f48148c3 Iustin Pop
    super(XenPvmHypervisor, self).ValidateParameters(hvparams)
427 f48148c3 Iustin Pop
428 f48148c3 Iustin Pop
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
429 f48148c3 Iustin Pop
    if not os.path.isfile(kernel_path):
430 f48148c3 Iustin Pop
      raise errors.HypervisorError("Instance kernel '%s' not found or"
431 f48148c3 Iustin Pop
                                   " not a file" % kernel_path)
432 f48148c3 Iustin Pop
    initrd_path = hvparams[constants.HV_INITRD_PATH]
433 f48148c3 Iustin Pop
    if initrd_path and not os.path.isfile(initrd_path):
434 f48148c3 Iustin Pop
      raise errors.HypervisorError("Instance initrd '%s' not found or"
435 f48148c3 Iustin Pop
                                   " not a file" % initrd_path)
436 f48148c3 Iustin Pop
437 65a6f9b7 Michael Hanselmann
  @classmethod
438 65a6f9b7 Michael Hanselmann
  def _WriteConfigFile(cls, instance, block_devices, extra_args):
439 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
440 65a6f9b7 Michael Hanselmann

441 65a6f9b7 Michael Hanselmann
    """
442 65a6f9b7 Michael Hanselmann
    config = StringIO()
443 65a6f9b7 Michael Hanselmann
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
444 65a6f9b7 Michael Hanselmann
445 65a6f9b7 Michael Hanselmann
    # kernel handling
446 f48148c3 Iustin Pop
    kpath = instance.hvparams[constants.HV_KERNEL_PATH]
447 65a6f9b7 Michael Hanselmann
    config.write("kernel = '%s'\n" % kpath)
448 65a6f9b7 Michael Hanselmann
449 65a6f9b7 Michael Hanselmann
    # initrd handling
450 f48148c3 Iustin Pop
    initrd_path = instance.hvparams[constants.HV_INITRD_PATH]
451 65a6f9b7 Michael Hanselmann
    if initrd_path:
452 65a6f9b7 Michael Hanselmann
      config.write("ramdisk = '%s'\n" % initrd_path)
453 65a6f9b7 Michael Hanselmann
454 65a6f9b7 Michael Hanselmann
    # rest of the settings
455 8b3fd458 Iustin Pop
    config.write("memory = %d\n" % instance.beparams[constants.BE_MEMORY])
456 8b3fd458 Iustin Pop
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
457 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
458 65a6f9b7 Michael Hanselmann
459 65a6f9b7 Michael Hanselmann
    vif_data = []
460 65a6f9b7 Michael Hanselmann
    for nic in instance.nics:
461 65a6f9b7 Michael Hanselmann
      nic_str = "mac=%s, bridge=%s" % (nic.mac, nic.bridge)
462 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
463 65a6f9b7 Michael Hanselmann
      if ip is not None:
464 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
465 65a6f9b7 Michael Hanselmann
      vif_data.append("'%s'" % nic_str)
466 65a6f9b7 Michael Hanselmann
467 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
468 65a6f9b7 Michael Hanselmann
    config.write("disk = [%s]\n" % ",".join(
469 65a6f9b7 Michael Hanselmann
                 cls._GetConfigFileDiskData(instance.disk_template,
470 65a6f9b7 Michael Hanselmann
                                            block_devices)))
471 074ca009 Guido Trotter
472 074ca009 Guido Trotter
    rpath = instance.hvparams[constants.HV_ROOT_PATH]
473 074ca009 Guido Trotter
    config.write("root = '%s ro'\n" % rpath)
474 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
475 65a6f9b7 Michael Hanselmann
    config.write("on_reboot = 'restart'\n")
476 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
477 65a6f9b7 Michael Hanselmann
    if extra_args:
478 65a6f9b7 Michael Hanselmann
      config.write("extra = '%s'\n" % extra_args)
479 65a6f9b7 Michael Hanselmann
    # just in case it exists
480 65a6f9b7 Michael Hanselmann
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
481 65a6f9b7 Michael Hanselmann
    try:
482 73cd67f4 Guido Trotter
      utils.WriteFile("/etc/xen/%s" % instance.name,
483 73cd67f4 Guido Trotter
                      data=config.getvalue())
484 73cd67f4 Guido Trotter
    except EnvironmentError, err:
485 73cd67f4 Guido Trotter
      raise errors.HypervisorError("Cannot write Xen instance confile"
486 73cd67f4 Guido Trotter
                                   " file /etc/xen/%s: %s" %
487 73cd67f4 Guido Trotter
                                   (instance.name, err))
488 73cd67f4 Guido Trotter
489 65a6f9b7 Michael Hanselmann
    return True
490 65a6f9b7 Michael Hanselmann
491 65a6f9b7 Michael Hanselmann
492 65a6f9b7 Michael Hanselmann
class XenHvmHypervisor(XenHypervisor):
493 65a6f9b7 Michael Hanselmann
  """Xen HVM hypervisor interface"""
494 65a6f9b7 Michael Hanselmann
495 f48148c3 Iustin Pop
  PARAMETERS = [
496 f48148c3 Iustin Pop
    constants.HV_ACPI,
497 f48148c3 Iustin Pop
    constants.HV_BOOT_ORDER,
498 f48148c3 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH,
499 f48148c3 Iustin Pop
    constants.HV_DISK_TYPE,
500 f48148c3 Iustin Pop
    constants.HV_NIC_TYPE,
501 f48148c3 Iustin Pop
    constants.HV_PAE,
502 f48148c3 Iustin Pop
    constants.HV_VNC_BIND_ADDRESS,
503 f48148c3 Iustin Pop
    ]
504 f48148c3 Iustin Pop
505 f48148c3 Iustin Pop
  @classmethod
506 f48148c3 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
507 f48148c3 Iustin Pop
    """Check the given parameter syntax.
508 f48148c3 Iustin Pop

509 f48148c3 Iustin Pop
    """
510 f48148c3 Iustin Pop
    super(XenHvmHypervisor, cls).CheckParameterSyntax(hvparams)
511 f48148c3 Iustin Pop
    # boot order verification
512 f48148c3 Iustin Pop
    boot_order = hvparams[constants.HV_BOOT_ORDER]
513 30948aa6 Guido Trotter
    if not boot_order or len(boot_order.strip("acdn")) != 0:
514 f48148c3 Iustin Pop
      raise errors.HypervisorError("Invalid boot order '%s' specified,"
515 f48148c3 Iustin Pop
                                   " must be one or more of [acdn]" %
516 f48148c3 Iustin Pop
                                   boot_order)
517 f48148c3 Iustin Pop
    # device type checks
518 f48148c3 Iustin Pop
    nic_type = hvparams[constants.HV_NIC_TYPE]
519 f48148c3 Iustin Pop
    if nic_type not in constants.HT_HVM_VALID_NIC_TYPES:
520 5155ede7 Guido Trotter
      raise errors.HypervisorError("Invalid NIC type %s specified for the Xen"
521 5155ede7 Guido Trotter
                                   " HVM hypervisor. Please choose one of: %s"
522 5155ede7 Guido Trotter
                                   % (nic_type,
523 5155ede7 Guido Trotter
                                      constants.HT_HVM_VALID_NIC_TYPES))
524 f48148c3 Iustin Pop
    disk_type = hvparams[constants.HV_DISK_TYPE]
525 f48148c3 Iustin Pop
    if disk_type not in constants.HT_HVM_VALID_DISK_TYPES:
526 5155ede7 Guido Trotter
      raise errors.HypervisorError("Invalid disk type %s specified for the Xen"
527 5155ede7 Guido Trotter
                                   " HVM hypervisor. Please choose one of: %s"
528 5155ede7 Guido Trotter
                                   % (disk_type,
529 5155ede7 Guido Trotter
                                      constants.HT_HVM_VALID_DISK_TYPES))
530 f48148c3 Iustin Pop
    # vnc_bind_address verification
531 f48148c3 Iustin Pop
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
532 5b460366 Iustin Pop
    if vnc_bind_address:
533 f48148c3 Iustin Pop
      if not utils.IsValidIP(vnc_bind_address):
534 f48148c3 Iustin Pop
        raise errors.OpPrereqError("given VNC bind address '%s' doesn't look"
535 f48148c3 Iustin Pop
                                   " like a valid IP address" %
536 f48148c3 Iustin Pop
                                   vnc_bind_address)
537 f48148c3 Iustin Pop
538 f48148c3 Iustin Pop
    iso_path = hvparams[constants.HV_CDROM_IMAGE_PATH]
539 f48148c3 Iustin Pop
    if iso_path and not os.path.isabs(iso_path):
540 5661b908 Iustin Pop
      raise errors.HypervisorError("The path to the HVM CDROM image must"
541 5661b908 Iustin Pop
                                   " be an absolute path or None, not %s" %
542 5661b908 Iustin Pop
                                   iso_path)
543 f48148c3 Iustin Pop
544 f48148c3 Iustin Pop
  def ValidateParameters(self, hvparams):
545 f48148c3 Iustin Pop
    """Check the given parameters for validity.
546 f48148c3 Iustin Pop

547 f48148c3 Iustin Pop
    For the PVM hypervisor, this only check the existence of the
548 f48148c3 Iustin Pop
    kernel.
549 f48148c3 Iustin Pop

550 f48148c3 Iustin Pop
    @type hvparams:  dict
551 f48148c3 Iustin Pop
    @param hvparams: dictionary with parameter names/value
552 f48148c3 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
553 f48148c3 Iustin Pop

554 f48148c3 Iustin Pop
    """
555 f48148c3 Iustin Pop
    super(XenHvmHypervisor, self).ValidateParameters(hvparams)
556 f48148c3 Iustin Pop
557 f48148c3 Iustin Pop
    # hvm_cdrom_image_path verification
558 f48148c3 Iustin Pop
    iso_path = hvparams[constants.HV_CDROM_IMAGE_PATH]
559 f48148c3 Iustin Pop
    if iso_path and not os.path.isfile(iso_path):
560 e09fdcfa Iustin Pop
      raise errors.HypervisorError("The HVM CDROM image must either be a"
561 e09fdcfa Iustin Pop
                                   " regular file or a symlink pointing to"
562 e09fdcfa Iustin Pop
                                   " an existing regular file, not %s" %
563 e09fdcfa Iustin Pop
                                   iso_path)
564 f48148c3 Iustin Pop
565 65a6f9b7 Michael Hanselmann
  @classmethod
566 65a6f9b7 Michael Hanselmann
  def _WriteConfigFile(cls, instance, block_devices, extra_args):
567 65a6f9b7 Michael Hanselmann
    """Create a Xen 3.1 HVM config file.
568 65a6f9b7 Michael Hanselmann

569 65a6f9b7 Michael Hanselmann
    """
570 65a6f9b7 Michael Hanselmann
    config = StringIO()
571 65a6f9b7 Michael Hanselmann
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
572 65a6f9b7 Michael Hanselmann
    config.write("kernel = '/usr/lib/xen/boot/hvmloader'\n")
573 65a6f9b7 Michael Hanselmann
    config.write("builder = 'hvm'\n")
574 8b3fd458 Iustin Pop
    config.write("memory = %d\n" % instance.beparams[constants.BE_MEMORY])
575 8b3fd458 Iustin Pop
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
576 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
577 f48148c3 Iustin Pop
    if instance.hvparams[constants.HV_PAE]:
578 a21dda8b Iustin Pop
      config.write("pae = 1\n")
579 a21dda8b Iustin Pop
    else:
580 a21dda8b Iustin Pop
      config.write("pae = 0\n")
581 f48148c3 Iustin Pop
    if instance.hvparams[constants.HV_ACPI]:
582 a21dda8b Iustin Pop
      config.write("acpi = 1\n")
583 a21dda8b Iustin Pop
    else:
584 a21dda8b Iustin Pop
      config.write("acpi = 0\n")
585 65a6f9b7 Michael Hanselmann
    config.write("apic = 1\n")
586 65a6f9b7 Michael Hanselmann
    arch = os.uname()[4]
587 65a6f9b7 Michael Hanselmann
    if '64' in arch:
588 65a6f9b7 Michael Hanselmann
      config.write("device_model = '/usr/lib64/xen/bin/qemu-dm'\n")
589 65a6f9b7 Michael Hanselmann
    else:
590 65a6f9b7 Michael Hanselmann
      config.write("device_model = '/usr/lib/xen/bin/qemu-dm'\n")
591 30948aa6 Guido Trotter
    config.write("boot = '%s'\n" % instance.hvparams[constants.HV_BOOT_ORDER])
592 65a6f9b7 Michael Hanselmann
    config.write("sdl = 0\n")
593 97efde45 Guido Trotter
    config.write("usb = 1\n")
594 97efde45 Guido Trotter
    config.write("usbdevice = 'tablet'\n")
595 65a6f9b7 Michael Hanselmann
    config.write("vnc = 1\n")
596 f48148c3 Iustin Pop
    if instance.hvparams[constants.HV_VNC_BIND_ADDRESS] is None:
597 d0c11cf7 Alexander Schreiber
      config.write("vnclisten = '%s'\n" % constants.VNC_DEFAULT_BIND_ADDRESS)
598 d0c11cf7 Alexander Schreiber
    else:
599 f48148c3 Iustin Pop
      config.write("vnclisten = '%s'\n" %
600 f48148c3 Iustin Pop
                   instance.hvparams["vnc_bind_address"])
601 65a6f9b7 Michael Hanselmann
602 377d74c9 Guido Trotter
    if instance.network_port > constants.VNC_BASE_PORT:
603 377d74c9 Guido Trotter
      display = instance.network_port - constants.VNC_BASE_PORT
604 65a6f9b7 Michael Hanselmann
      config.write("vncdisplay = %s\n" % display)
605 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 0\n")
606 65a6f9b7 Michael Hanselmann
    else:
607 65a6f9b7 Michael Hanselmann
      config.write("# vncdisplay = 1\n")
608 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 1\n")
609 65a6f9b7 Michael Hanselmann
610 65a6f9b7 Michael Hanselmann
    try:
611 78f66a17 Guido Trotter
      password = utils.ReadFile(constants.VNC_PASSWORD_FILE)
612 78f66a17 Guido Trotter
    except EnvironmentError, err:
613 78f66a17 Guido Trotter
      raise errors.HypervisorError("Failed to open VNC password file %s: %s" %
614 78f66a17 Guido Trotter
                                   (constants.VNC_PASSWORD_FILE, err))
615 65a6f9b7 Michael Hanselmann
616 65a6f9b7 Michael Hanselmann
    config.write("vncpasswd = '%s'\n" % password.rstrip())
617 65a6f9b7 Michael Hanselmann
618 65a6f9b7 Michael Hanselmann
    config.write("serial = 'pty'\n")
619 65a6f9b7 Michael Hanselmann
    config.write("localtime = 1\n")
620 65a6f9b7 Michael Hanselmann
621 65a6f9b7 Michael Hanselmann
    vif_data = []
622 f48148c3 Iustin Pop
    nic_type = instance.hvparams[constants.HV_NIC_TYPE]
623 f48148c3 Iustin Pop
    if nic_type is None:
624 f48148c3 Iustin Pop
      # ensure old instances don't change
625 f48148c3 Iustin Pop
      nic_type_str = ", type=ioemu"
626 d08f6067 Guido Trotter
    elif nic_type == constants.HT_NIC_PARAVIRTUAL:
627 f48148c3 Iustin Pop
      nic_type_str = ", type=paravirtualized"
628 f48148c3 Iustin Pop
    else:
629 f48148c3 Iustin Pop
      nic_type_str = ", model=%s, type=ioemu" % nic_type
630 65a6f9b7 Michael Hanselmann
    for nic in instance.nics:
631 f48148c3 Iustin Pop
      nic_str = "mac=%s, bridge=%s%s" % (nic.mac, nic.bridge, nic_type_str)
632 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
633 65a6f9b7 Michael Hanselmann
      if ip is not None:
634 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
635 65a6f9b7 Michael Hanselmann
      vif_data.append("'%s'" % nic_str)
636 65a6f9b7 Michael Hanselmann
637 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
638 a21dda8b Iustin Pop
    disk_data = cls._GetConfigFileDiskData(instance.disk_template,
639 a21dda8b Iustin Pop
                                            block_devices)
640 f48148c3 Iustin Pop
    disk_type = instance.hvparams[constants.HV_DISK_TYPE]
641 d08f6067 Guido Trotter
    if disk_type in (None, constants.HT_DISK_IOEMU):
642 5397e0b7 Alexander Schreiber
      replacement = ",ioemu:hd"
643 5397e0b7 Alexander Schreiber
    else:
644 5397e0b7 Alexander Schreiber
      replacement = ",hd"
645 5397e0b7 Alexander Schreiber
    disk_data = [line.replace(",sd", replacement) for line in disk_data]
646 f48148c3 Iustin Pop
    iso_path = instance.hvparams[constants.HV_CDROM_IMAGE_PATH]
647 f48148c3 Iustin Pop
    if iso_path:
648 f48148c3 Iustin Pop
      iso = "'file:%s,hdc:cdrom,r'" % iso_path
649 a21dda8b Iustin Pop
      disk_data.append(iso)
650 a21dda8b Iustin Pop
651 a21dda8b Iustin Pop
    config.write("disk = [%s]\n" % (",".join(disk_data)))
652 a21dda8b Iustin Pop
653 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
654 65a6f9b7 Michael Hanselmann
    config.write("on_reboot = 'restart'\n")
655 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
656 65a6f9b7 Michael Hanselmann
    if extra_args:
657 65a6f9b7 Michael Hanselmann
      config.write("extra = '%s'\n" % extra_args)
658 65a6f9b7 Michael Hanselmann
    # just in case it exists
659 65a6f9b7 Michael Hanselmann
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
660 65a6f9b7 Michael Hanselmann
    try:
661 73cd67f4 Guido Trotter
      utils.WriteFile("/etc/xen/%s" % instance.name,
662 73cd67f4 Guido Trotter
                      data=config.getvalue())
663 73cd67f4 Guido Trotter
    except EnvironmentError, err:
664 73cd67f4 Guido Trotter
      raise errors.HypervisorError("Cannot write Xen instance confile"
665 73cd67f4 Guido Trotter
                                   " file /etc/xen/%s: %s" %
666 73cd67f4 Guido Trotter
                                   (instance.name, err))
667 73cd67f4 Guido Trotter
668 65a6f9b7 Michael Hanselmann
    return True