Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ 78411c60

History | View | Annotate | Download (21.3 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 b48909c8 Iustin Pop
import logging
29 65a6f9b7 Michael Hanselmann
from cStringIO import StringIO
30 65a6f9b7 Michael Hanselmann
31 65a6f9b7 Michael Hanselmann
from ganeti import constants
32 65a6f9b7 Michael Hanselmann
from ganeti import errors
33 65a6f9b7 Michael Hanselmann
from ganeti import utils
34 a2d32034 Michael Hanselmann
from ganeti.hypervisor import hv_base
35 65a6f9b7 Michael Hanselmann
36 65a6f9b7 Michael Hanselmann
37 a2d32034 Michael Hanselmann
class XenHypervisor(hv_base.BaseHypervisor):
38 65a6f9b7 Michael Hanselmann
  """Xen generic hypervisor interface
39 65a6f9b7 Michael Hanselmann

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

43 65a6f9b7 Michael Hanselmann
  """
44 7dd106d3 Iustin Pop
  REBOOT_RETRY_COUNT = 60
45 7dd106d3 Iustin Pop
  REBOOT_RETRY_INTERVAL = 10
46 65a6f9b7 Michael Hanselmann
47 3680f662 Guido Trotter
  ANCILLARY_FILES = [
48 3680f662 Guido Trotter
    '/etc/xen/xend-config.sxp',
49 3680f662 Guido Trotter
    '/etc/xen/scripts/vif-bridge',
50 3680f662 Guido Trotter
    ]
51 3680f662 Guido Trotter
52 5661b908 Iustin Pop
  @classmethod
53 07813a9e Iustin Pop
  def _WriteConfigFile(cls, instance, block_devices):
54 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
55 65a6f9b7 Michael Hanselmann

56 65a6f9b7 Michael Hanselmann
    """
57 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
58 65a6f9b7 Michael Hanselmann
59 65a6f9b7 Michael Hanselmann
  @staticmethod
60 4390ccff Guido Trotter
  def _WriteConfigFileStatic(instance_name, data):
61 4390ccff Guido Trotter
    """Write the Xen config file for the instance.
62 4390ccff Guido Trotter

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

65 4390ccff Guido Trotter
    """
66 4390ccff Guido Trotter
    utils.WriteFile("/etc/xen/%s" % instance_name, data=data)
67 4390ccff Guido Trotter
68 4390ccff Guido Trotter
  @staticmethod
69 4390ccff Guido Trotter
  def _ReadConfigFile(instance_name):
70 4390ccff Guido Trotter
    """Returns the contents of the instance config file.
71 4390ccff Guido Trotter

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

83 65a6f9b7 Michael Hanselmann
    """
84 53c776b5 Iustin Pop
    utils.RemoveFile("/etc/xen/%s" % instance_name)
85 65a6f9b7 Michael Hanselmann
86 65a6f9b7 Michael Hanselmann
  @staticmethod
87 06b78e8b Michael Hanselmann
  def _RunXmList(xmlist_errors):
88 06b78e8b Michael Hanselmann
    """Helper function for L{_GetXMList} to run "xm list".
89 06b78e8b Michael Hanselmann

90 06b78e8b Michael Hanselmann
    """
91 06b78e8b Michael Hanselmann
    result = utils.RunCmd(["xm", "list"])
92 06b78e8b Michael Hanselmann
    if result.failed:
93 06b78e8b Michael Hanselmann
      logging.error("xm list failed (%s): %s", result.fail_reason,
94 06b78e8b Michael Hanselmann
                    result.output)
95 06b78e8b Michael Hanselmann
      xmlist_errors.append(result)
96 06b78e8b Michael Hanselmann
      raise utils.RetryAgain()
97 06b78e8b Michael Hanselmann
98 06b78e8b Michael Hanselmann
    # skip over the heading
99 06b78e8b Michael Hanselmann
    return result.stdout.splitlines()[1:]
100 06b78e8b Michael Hanselmann
101 06b78e8b Michael Hanselmann
  @classmethod
102 06b78e8b Michael Hanselmann
  def _GetXMList(cls, include_node):
103 65a6f9b7 Michael Hanselmann
    """Return the list of running instances.
104 65a6f9b7 Michael Hanselmann

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

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

110 65a6f9b7 Michael Hanselmann
    """
111 06b78e8b Michael Hanselmann
    xmlist_errors = []
112 06b78e8b Michael Hanselmann
    try:
113 06b78e8b Michael Hanselmann
      lines = utils.Retry(cls._RunXmList, 1, 5, args=(xmlist_errors, ))
114 06b78e8b Michael Hanselmann
    except utils.RetryTimeout:
115 06b78e8b Michael Hanselmann
      if xmlist_errors:
116 06b78e8b Michael Hanselmann
        xmlist_result = xmlist_errors.pop()
117 65a6f9b7 Michael Hanselmann
118 06b78e8b Michael Hanselmann
        errmsg = ("xm list failed, timeout exceeded (%s): %s" %
119 06b78e8b Michael Hanselmann
                  (xmlist_result.fail_reason, xmlist_result.output))
120 06b78e8b Michael Hanselmann
      else:
121 06b78e8b Michael Hanselmann
        errmsg = "xm list failed"
122 06b78e8b Michael Hanselmann
123 06b78e8b Michael Hanselmann
      raise errors.HypervisorError(errmsg)
124 65a6f9b7 Michael Hanselmann
125 65a6f9b7 Michael Hanselmann
    result = []
126 65a6f9b7 Michael Hanselmann
    for line in lines:
127 65a6f9b7 Michael Hanselmann
      # The format of lines is:
128 65a6f9b7 Michael Hanselmann
      # Name      ID Mem(MiB) VCPUs State  Time(s)
129 65a6f9b7 Michael Hanselmann
      # Domain-0   0  3418     4 r-----    266.2
130 65a6f9b7 Michael Hanselmann
      data = line.split()
131 65a6f9b7 Michael Hanselmann
      if len(data) != 6:
132 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("Can't parse output of xm list,"
133 65a6f9b7 Michael Hanselmann
                                     " line: %s" % line)
134 65a6f9b7 Michael Hanselmann
      try:
135 65a6f9b7 Michael Hanselmann
        data[1] = int(data[1])
136 65a6f9b7 Michael Hanselmann
        data[2] = int(data[2])
137 65a6f9b7 Michael Hanselmann
        data[3] = int(data[3])
138 65a6f9b7 Michael Hanselmann
        data[5] = float(data[5])
139 65a6f9b7 Michael Hanselmann
      except ValueError, err:
140 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("Can't parse output of xm list,"
141 65a6f9b7 Michael Hanselmann
                                     " line: %s, error: %s" % (line, err))
142 65a6f9b7 Michael Hanselmann
143 65a6f9b7 Michael Hanselmann
      # skip the Domain-0 (optional)
144 65a6f9b7 Michael Hanselmann
      if include_node or data[0] != 'Domain-0':
145 65a6f9b7 Michael Hanselmann
        result.append(data)
146 65a6f9b7 Michael Hanselmann
147 65a6f9b7 Michael Hanselmann
    return result
148 65a6f9b7 Michael Hanselmann
149 65a6f9b7 Michael Hanselmann
  def ListInstances(self):
150 65a6f9b7 Michael Hanselmann
    """Get the list of running instances.
151 65a6f9b7 Michael Hanselmann

152 65a6f9b7 Michael Hanselmann
    """
153 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(False)
154 65a6f9b7 Michael Hanselmann
    names = [info[0] for info in xm_list]
155 65a6f9b7 Michael Hanselmann
    return names
156 65a6f9b7 Michael Hanselmann
157 65a6f9b7 Michael Hanselmann
  def GetInstanceInfo(self, instance_name):
158 65a6f9b7 Michael Hanselmann
    """Get instance properties.
159 65a6f9b7 Michael Hanselmann

160 c41eea6e Iustin Pop
    @param instance_name: the instance name
161 c41eea6e Iustin Pop

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

164 65a6f9b7 Michael Hanselmann
    """
165 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(instance_name=="Domain-0")
166 65a6f9b7 Michael Hanselmann
    result = None
167 65a6f9b7 Michael Hanselmann
    for data in xm_list:
168 65a6f9b7 Michael Hanselmann
      if data[0] == instance_name:
169 65a6f9b7 Michael Hanselmann
        result = data
170 65a6f9b7 Michael Hanselmann
        break
171 65a6f9b7 Michael Hanselmann
    return result
172 65a6f9b7 Michael Hanselmann
173 65a6f9b7 Michael Hanselmann
  def GetAllInstancesInfo(self):
174 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
175 65a6f9b7 Michael Hanselmann

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

178 65a6f9b7 Michael Hanselmann
    """
179 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(False)
180 65a6f9b7 Michael Hanselmann
    return xm_list
181 65a6f9b7 Michael Hanselmann
182 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
183 c41eea6e Iustin Pop
    """Start an instance.
184 c41eea6e Iustin Pop

185 c41eea6e Iustin Pop
    """
186 07813a9e Iustin Pop
    self._WriteConfigFile(instance, block_devices)
187 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(["xm", "create", instance.name])
188 65a6f9b7 Michael Hanselmann
189 65a6f9b7 Michael Hanselmann
    if result.failed:
190 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
191 65a6f9b7 Michael Hanselmann
                                   (instance.name, result.fail_reason,
192 65a6f9b7 Michael Hanselmann
                                    result.output))
193 65a6f9b7 Michael Hanselmann
194 07b49e41 Guido Trotter
  def StopInstance(self, instance, force=False, retry=False):
195 c41eea6e Iustin Pop
    """Stop an instance.
196 c41eea6e Iustin Pop

197 c41eea6e Iustin Pop
    """
198 53c776b5 Iustin Pop
    self._RemoveConfigFile(instance.name)
199 65a6f9b7 Michael Hanselmann
    if force:
200 65a6f9b7 Michael Hanselmann
      command = ["xm", "destroy", instance.name]
201 65a6f9b7 Michael Hanselmann
    else:
202 65a6f9b7 Michael Hanselmann
      command = ["xm", "shutdown", instance.name]
203 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(command)
204 65a6f9b7 Michael Hanselmann
205 65a6f9b7 Michael Hanselmann
    if result.failed:
206 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to stop instance %s: %s, %s" %
207 3213d3c8 Iustin Pop
                                   (instance.name, result.fail_reason,
208 3213d3c8 Iustin Pop
                                    result.output))
209 65a6f9b7 Michael Hanselmann
210 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
211 c41eea6e Iustin Pop
    """Reboot an instance.
212 c41eea6e Iustin Pop

213 c41eea6e Iustin Pop
    """
214 7dd106d3 Iustin Pop
    ini_info = self.GetInstanceInfo(instance.name)
215 65a6f9b7 Michael Hanselmann
216 06b78e8b Michael Hanselmann
    result = utils.RunCmd(["xm", "reboot", instance.name])
217 65a6f9b7 Michael Hanselmann
    if result.failed:
218 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s: %s, %s" %
219 3213d3c8 Iustin Pop
                                   (instance.name, result.fail_reason,
220 3213d3c8 Iustin Pop
                                    result.output))
221 06b78e8b Michael Hanselmann
222 06b78e8b Michael Hanselmann
    def _CheckInstance():
223 7dd106d3 Iustin Pop
      new_info = self.GetInstanceInfo(instance.name)
224 06b78e8b Michael Hanselmann
225 06b78e8b Michael Hanselmann
      # check if the domain ID has changed or the run time has decreased
226 7dd106d3 Iustin Pop
      if new_info[1] != ini_info[1] or new_info[5] < ini_info[5]:
227 06b78e8b Michael Hanselmann
        return
228 7dd106d3 Iustin Pop
229 06b78e8b Michael Hanselmann
      raise utils.RetryAgain()
230 06b78e8b Michael Hanselmann
231 06b78e8b Michael Hanselmann
    try:
232 06b78e8b Michael Hanselmann
      utils.Retry(_CheckInstance, self.REBOOT_RETRY_INTERVAL,
233 06b78e8b Michael Hanselmann
                  self.REBOOT_RETRY_INTERVAL * self.REBOOT_RETRY_COUNT)
234 06b78e8b Michael Hanselmann
    except utils.RetryTimeout:
235 7dd106d3 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s: instance"
236 7dd106d3 Iustin Pop
                                   " did not reboot in the expected interval" %
237 7dd106d3 Iustin Pop
                                   (instance.name, ))
238 65a6f9b7 Michael Hanselmann
239 65a6f9b7 Michael Hanselmann
  def GetNodeInfo(self):
240 65a6f9b7 Michael Hanselmann
    """Return information about the node.
241 65a6f9b7 Michael Hanselmann

242 0105bad3 Iustin Pop
    @return: a dict with the following keys (memory values in MiB):
243 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
244 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
245 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
246 0105bad3 Iustin Pop
          - nr_cpus: total number of CPUs
247 0105bad3 Iustin Pop
          - nr_nodes: in a NUMA system, the number of domains
248 0105bad3 Iustin Pop
          - nr_sockets: the number of physical CPU sockets in the node
249 65a6f9b7 Michael Hanselmann

250 65a6f9b7 Michael Hanselmann
    """
251 65a6f9b7 Michael Hanselmann
    # note: in xen 3, memory has changed to total_memory
252 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(["xm", "info"])
253 65a6f9b7 Michael Hanselmann
    if result.failed:
254 b48909c8 Iustin Pop
      logging.error("Can't run 'xm info' (%s): %s", result.fail_reason,
255 b48909c8 Iustin Pop
                    result.output)
256 65a6f9b7 Michael Hanselmann
      return None
257 65a6f9b7 Michael Hanselmann
258 65a6f9b7 Michael Hanselmann
    xmoutput = result.stdout.splitlines()
259 65a6f9b7 Michael Hanselmann
    result = {}
260 0105bad3 Iustin Pop
    cores_per_socket = threads_per_core = nr_cpus = None
261 65a6f9b7 Michael Hanselmann
    for line in xmoutput:
262 65a6f9b7 Michael Hanselmann
      splitfields = line.split(":", 1)
263 65a6f9b7 Michael Hanselmann
264 65a6f9b7 Michael Hanselmann
      if len(splitfields) > 1:
265 65a6f9b7 Michael Hanselmann
        key = splitfields[0].strip()
266 65a6f9b7 Michael Hanselmann
        val = splitfields[1].strip()
267 65a6f9b7 Michael Hanselmann
        if key == 'memory' or key == 'total_memory':
268 65a6f9b7 Michael Hanselmann
          result['memory_total'] = int(val)
269 65a6f9b7 Michael Hanselmann
        elif key == 'free_memory':
270 65a6f9b7 Michael Hanselmann
          result['memory_free'] = int(val)
271 e8a4c138 Iustin Pop
        elif key == 'nr_cpus':
272 0105bad3 Iustin Pop
          nr_cpus = result['cpu_total'] = int(val)
273 0105bad3 Iustin Pop
        elif key == 'nr_nodes':
274 0105bad3 Iustin Pop
          result['cpu_nodes'] = int(val)
275 0105bad3 Iustin Pop
        elif key == 'cores_per_socket':
276 0105bad3 Iustin Pop
          cores_per_socket = int(val)
277 0105bad3 Iustin Pop
        elif key == 'threads_per_core':
278 0105bad3 Iustin Pop
          threads_per_core = int(val)
279 0105bad3 Iustin Pop
280 0105bad3 Iustin Pop
    if (cores_per_socket is not None and
281 0105bad3 Iustin Pop
        threads_per_core is not None and nr_cpus is not None):
282 0105bad3 Iustin Pop
      result['cpu_sockets'] = nr_cpus / (cores_per_socket * threads_per_core)
283 0105bad3 Iustin Pop
284 65a6f9b7 Michael Hanselmann
    dom0_info = self.GetInstanceInfo("Domain-0")
285 65a6f9b7 Michael Hanselmann
    if dom0_info is not None:
286 65a6f9b7 Michael Hanselmann
      result['memory_dom0'] = dom0_info[2]
287 65a6f9b7 Michael Hanselmann
288 65a6f9b7 Michael Hanselmann
    return result
289 65a6f9b7 Michael Hanselmann
290 637ce7f9 Guido Trotter
  @classmethod
291 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
292 65a6f9b7 Michael Hanselmann
    """Return a command for connecting to the console of an instance.
293 65a6f9b7 Michael Hanselmann

294 65a6f9b7 Michael Hanselmann
    """
295 04c4330c Alexander Schreiber
    return "xm console %s" % instance.name
296 04c4330c Alexander Schreiber
297 65a6f9b7 Michael Hanselmann
298 65a6f9b7 Michael Hanselmann
  def Verify(self):
299 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
300 65a6f9b7 Michael Hanselmann

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

303 65a6f9b7 Michael Hanselmann
    """
304 e3e66f02 Michael Hanselmann
    result = utils.RunCmd(["xm", "info"])
305 e3e66f02 Michael Hanselmann
    if result.failed:
306 3213d3c8 Iustin Pop
      return "'xm info' failed: %s, %s" % (result.fail_reason, result.output)
307 65a6f9b7 Michael Hanselmann
308 65a6f9b7 Michael Hanselmann
  @staticmethod
309 65a6f9b7 Michael Hanselmann
  def _GetConfigFileDiskData(disk_template, block_devices):
310 65a6f9b7 Michael Hanselmann
    """Get disk directive for xen config file.
311 65a6f9b7 Michael Hanselmann

312 65a6f9b7 Michael Hanselmann
    This method builds the xen config disk directive according to the
313 65a6f9b7 Michael Hanselmann
    given disk_template and block_devices.
314 65a6f9b7 Michael Hanselmann

315 c41eea6e Iustin Pop
    @param disk_template: string containing instance disk template
316 c41eea6e Iustin Pop
    @param block_devices: list of tuples (cfdev, rldev):
317 c41eea6e Iustin Pop
        - cfdev: dict containing ganeti config disk part
318 c41eea6e Iustin Pop
        - rldev: ganeti.bdev.BlockDev object
319 65a6f9b7 Michael Hanselmann

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

322 65a6f9b7 Michael Hanselmann
    """
323 65a6f9b7 Michael Hanselmann
    FILE_DRIVER_MAP = {
324 65a6f9b7 Michael Hanselmann
      constants.FD_LOOP: "file",
325 65a6f9b7 Michael Hanselmann
      constants.FD_BLKTAP: "tap:aio",
326 65a6f9b7 Michael Hanselmann
      }
327 65a6f9b7 Michael Hanselmann
    disk_data = []
328 2864f2d9 Iustin Pop
    if len(block_devices) > 24:
329 2864f2d9 Iustin Pop
      # 'z' - 'a' = 24
330 2864f2d9 Iustin Pop
      raise errors.HypervisorError("Too many disks")
331 2864f2d9 Iustin Pop
    # FIXME: instead of this hardcoding here, each of PVM/HVM should
332 2864f2d9 Iustin Pop
    # directly export their info (currently HVM will just sed this info)
333 2864f2d9 Iustin Pop
    namespace = ["sd" + chr(i + ord('a')) for i in range(24)]
334 069cfbf1 Iustin Pop
    for sd_name, (cfdev, dev_path) in zip(namespace, block_devices):
335 d34b16d7 Iustin Pop
      if cfdev.mode == constants.DISK_RDWR:
336 d34b16d7 Iustin Pop
        mode = "w"
337 d34b16d7 Iustin Pop
      else:
338 d34b16d7 Iustin Pop
        mode = "r"
339 65a6f9b7 Michael Hanselmann
      if cfdev.dev_type == constants.LD_FILE:
340 d34b16d7 Iustin Pop
        line = "'%s:%s,%s,%s'" % (FILE_DRIVER_MAP[cfdev.physical_id[0]],
341 d34b16d7 Iustin Pop
                                  dev_path, sd_name, mode)
342 65a6f9b7 Michael Hanselmann
      else:
343 d34b16d7 Iustin Pop
        line = "'phy:%s,%s,%s'" % (dev_path, sd_name, mode)
344 65a6f9b7 Michael Hanselmann
      disk_data.append(line)
345 65a6f9b7 Michael Hanselmann
346 65a6f9b7 Michael Hanselmann
    return disk_data
347 65a6f9b7 Michael Hanselmann
348 4390ccff Guido Trotter
  def MigrationInfo(self, instance):
349 4390ccff Guido Trotter
    """Get instance information to perform a migration.
350 4390ccff Guido Trotter

351 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
352 4390ccff Guido Trotter
    @param instance: instance to be migrated
353 4390ccff Guido Trotter
    @rtype: string
354 4390ccff Guido Trotter
    @return: content of the xen config file
355 4390ccff Guido Trotter

356 4390ccff Guido Trotter
    """
357 4390ccff Guido Trotter
    return self._ReadConfigFile(instance.name)
358 4390ccff Guido Trotter
359 4390ccff Guido Trotter
  def AcceptInstance(self, instance, info, target):
360 4390ccff Guido Trotter
    """Prepare to accept an instance.
361 4390ccff Guido Trotter

362 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
363 4390ccff Guido Trotter
    @param instance: instance to be accepted
364 4390ccff Guido Trotter
    @type info: string
365 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
366 4390ccff Guido Trotter
    @type target: string
367 4390ccff Guido Trotter
    @param target: target host (usually ip), on this node
368 4390ccff Guido Trotter

369 4390ccff Guido Trotter
    """
370 4390ccff Guido Trotter
    pass
371 4390ccff Guido Trotter
372 4390ccff Guido Trotter
  def FinalizeMigration(self, instance, info, success):
373 4390ccff Guido Trotter
    """Finalize an instance migration.
374 4390ccff Guido Trotter

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

378 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
379 4390ccff Guido Trotter
    @param instance: instance whose migration is being aborted
380 4390ccff Guido Trotter
    @type info: string
381 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
382 4390ccff Guido Trotter
    @type success: boolean
383 4390ccff Guido Trotter
    @param success: whether the migration was a success or a failure
384 4390ccff Guido Trotter

385 4390ccff Guido Trotter
    """
386 4390ccff Guido Trotter
    if success:
387 4390ccff Guido Trotter
      self._WriteConfigFileStatic(instance.name, info)
388 4390ccff Guido Trotter
389 6e7275c0 Iustin Pop
  def MigrateInstance(self, instance, target, live):
390 6e7275c0 Iustin Pop
    """Migrate an instance to a target node.
391 6e7275c0 Iustin Pop

392 6e7275c0 Iustin Pop
    The migration will not be attempted if the instance is not
393 6e7275c0 Iustin Pop
    currently running.
394 6e7275c0 Iustin Pop

395 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
396 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
397 fdf7f055 Guido Trotter
    @type target: string
398 fdf7f055 Guido Trotter
    @param target: ip address of the target node
399 fdf7f055 Guido Trotter
    @type live: boolean
400 fdf7f055 Guido Trotter
    @param live: perform a live migration
401 fdf7f055 Guido Trotter

402 6e7275c0 Iustin Pop
    """
403 58d38b02 Iustin Pop
    if self.GetInstanceInfo(instance.name) is None:
404 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Instance not running, cannot migrate")
405 6e7275c0 Iustin Pop
    args = ["xm", "migrate"]
406 6e7275c0 Iustin Pop
    if live:
407 6e7275c0 Iustin Pop
      args.append("-l")
408 58d38b02 Iustin Pop
    args.extend([instance.name, target])
409 6e7275c0 Iustin Pop
    result = utils.RunCmd(args)
410 6e7275c0 Iustin Pop
    if result.failed:
411 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Failed to migrate instance %s: %s" %
412 58d38b02 Iustin Pop
                                   (instance.name, result.output))
413 53c776b5 Iustin Pop
    # remove old xen file after migration succeeded
414 53c776b5 Iustin Pop
    try:
415 58d38b02 Iustin Pop
      self._RemoveConfigFile(instance.name)
416 c979d253 Iustin Pop
    except EnvironmentError:
417 c979d253 Iustin Pop
      logging.exception("Failure while removing instance config file")
418 6e7275c0 Iustin Pop
419 f5118ade Iustin Pop
  @classmethod
420 f5118ade Iustin Pop
  def PowercycleNode(cls):
421 f5118ade Iustin Pop
    """Xen-specific powercycle.
422 f5118ade Iustin Pop

423 f5118ade Iustin Pop
    This first does a Linux reboot (which triggers automatically a Xen
424 f5118ade Iustin Pop
    reboot), and if that fails it tries to do a Xen reboot. The reason
425 f5118ade Iustin Pop
    we don't try a Xen reboot first is that the xen reboot launches an
426 f5118ade Iustin Pop
    external command which connects to the Xen hypervisor, and that
427 f5118ade Iustin Pop
    won't work in case the root filesystem is broken and/or the xend
428 f5118ade Iustin Pop
    daemon is not working.
429 f5118ade Iustin Pop

430 f5118ade Iustin Pop
    """
431 f5118ade Iustin Pop
    try:
432 f5118ade Iustin Pop
      cls.LinuxPowercycle()
433 f5118ade Iustin Pop
    finally:
434 f5118ade Iustin Pop
      utils.RunCmd(["xm", "debug", "R"])
435 f5118ade Iustin Pop
436 65a6f9b7 Michael Hanselmann
437 65a6f9b7 Michael Hanselmann
class XenPvmHypervisor(XenHypervisor):
438 65a6f9b7 Michael Hanselmann
  """Xen PVM hypervisor interface"""
439 65a6f9b7 Michael Hanselmann
440 205ab586 Iustin Pop
  PARAMETERS = {
441 2f2dbb4b Jun Futagawa
    constants.HV_USE_BOOTLOADER: hv_base.NO_CHECK,
442 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_PATH: hv_base.OPT_FILE_CHECK,
443 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_ARGS: hv_base.NO_CHECK,
444 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.REQ_FILE_CHECK,
445 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
446 205ab586 Iustin Pop
    constants.HV_ROOT_PATH: hv_base.REQUIRED_CHECK,
447 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
448 78411c60 Iustin Pop
    constants.HV_MIGRATION_PORT: hv_base.NET_PORT_CHECK,
449 205ab586 Iustin Pop
    }
450 f48148c3 Iustin Pop
451 65a6f9b7 Michael Hanselmann
  @classmethod
452 07813a9e Iustin Pop
  def _WriteConfigFile(cls, instance, block_devices):
453 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
454 65a6f9b7 Michael Hanselmann

455 65a6f9b7 Michael Hanselmann
    """
456 a985b417 Iustin Pop
    hvp = instance.hvparams
457 65a6f9b7 Michael Hanselmann
    config = StringIO()
458 65a6f9b7 Michael Hanselmann
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
459 65a6f9b7 Michael Hanselmann
460 2f2dbb4b Jun Futagawa
    # if bootloader is True, use bootloader instead of kernel and ramdisk
461 2f2dbb4b Jun Futagawa
    # parameters.
462 2f2dbb4b Jun Futagawa
    if hvp[constants.HV_USE_BOOTLOADER]:
463 2f2dbb4b Jun Futagawa
      # bootloader handling
464 2f2dbb4b Jun Futagawa
      bootloader_path = hvp[constants.HV_BOOTLOADER_PATH]
465 2f2dbb4b Jun Futagawa
      if bootloader_path:
466 2f2dbb4b Jun Futagawa
        config.write("bootloader = '%s'\n" % bootloader_path)
467 2f2dbb4b Jun Futagawa
      else:
468 2f2dbb4b Jun Futagawa
        raise errors.HypervisorError("Bootloader enabled, but missing"
469 2f2dbb4b Jun Futagawa
                                     " bootloader path")
470 65a6f9b7 Michael Hanselmann
471 2f2dbb4b Jun Futagawa
      bootloader_args = hvp[constants.HV_BOOTLOADER_ARGS]
472 2f2dbb4b Jun Futagawa
      if bootloader_args:
473 2f2dbb4b Jun Futagawa
        config.write("bootargs = '%s'\n" % bootloader_args)
474 2f2dbb4b Jun Futagawa
    else:
475 2f2dbb4b Jun Futagawa
      # kernel handling
476 2f2dbb4b Jun Futagawa
      kpath = hvp[constants.HV_KERNEL_PATH]
477 2f2dbb4b Jun Futagawa
      config.write("kernel = '%s'\n" % kpath)
478 2f2dbb4b Jun Futagawa
479 2f2dbb4b Jun Futagawa
      # initrd handling
480 2f2dbb4b Jun Futagawa
      initrd_path = hvp[constants.HV_INITRD_PATH]
481 2f2dbb4b Jun Futagawa
      if initrd_path:
482 2f2dbb4b Jun Futagawa
        config.write("ramdisk = '%s'\n" % initrd_path)
483 65a6f9b7 Michael Hanselmann
484 65a6f9b7 Michael Hanselmann
    # rest of the settings
485 8b3fd458 Iustin Pop
    config.write("memory = %d\n" % instance.beparams[constants.BE_MEMORY])
486 8b3fd458 Iustin Pop
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
487 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
488 65a6f9b7 Michael Hanselmann
489 65a6f9b7 Michael Hanselmann
    vif_data = []
490 65a6f9b7 Michael Hanselmann
    for nic in instance.nics:
491 503b97a9 Guido Trotter
      nic_str = "mac=%s" % (nic.mac)
492 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
493 65a6f9b7 Michael Hanselmann
      if ip is not None:
494 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
495 65a6f9b7 Michael Hanselmann
      vif_data.append("'%s'" % nic_str)
496 503b97a9 Guido Trotter
      if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
497 503b97a9 Guido Trotter
        nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK]
498 65a6f9b7 Michael Hanselmann
499 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
500 65a6f9b7 Michael Hanselmann
    config.write("disk = [%s]\n" % ",".join(
501 65a6f9b7 Michael Hanselmann
                 cls._GetConfigFileDiskData(instance.disk_template,
502 65a6f9b7 Michael Hanselmann
                                            block_devices)))
503 074ca009 Guido Trotter
504 07813a9e Iustin Pop
    config.write("root = '%s'\n" % hvp[constants.HV_ROOT_PATH])
505 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
506 65a6f9b7 Michael Hanselmann
    config.write("on_reboot = 'restart'\n")
507 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
508 07813a9e Iustin Pop
    config.write("extra = '%s'\n" % hvp[constants.HV_KERNEL_ARGS])
509 65a6f9b7 Michael Hanselmann
    # just in case it exists
510 65a6f9b7 Michael Hanselmann
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
511 65a6f9b7 Michael Hanselmann
    try:
512 a985b417 Iustin Pop
      utils.WriteFile("/etc/xen/%s" % instance.name, data=config.getvalue())
513 73cd67f4 Guido Trotter
    except EnvironmentError, err:
514 73cd67f4 Guido Trotter
      raise errors.HypervisorError("Cannot write Xen instance confile"
515 73cd67f4 Guido Trotter
                                   " file /etc/xen/%s: %s" %
516 73cd67f4 Guido Trotter
                                   (instance.name, err))
517 73cd67f4 Guido Trotter
518 65a6f9b7 Michael Hanselmann
    return True
519 65a6f9b7 Michael Hanselmann
520 65a6f9b7 Michael Hanselmann
521 65a6f9b7 Michael Hanselmann
class XenHvmHypervisor(XenHypervisor):
522 65a6f9b7 Michael Hanselmann
  """Xen HVM hypervisor interface"""
523 65a6f9b7 Michael Hanselmann
524 69b99987 Michael Hanselmann
  ANCILLARY_FILES = XenHypervisor.ANCILLARY_FILES + [
525 69b99987 Michael Hanselmann
    constants.VNC_PASSWORD_FILE,
526 69b99987 Michael Hanselmann
    ]
527 3680f662 Guido Trotter
528 205ab586 Iustin Pop
  PARAMETERS = {
529 205ab586 Iustin Pop
    constants.HV_ACPI: hv_base.NO_CHECK,
530 016d04b3 Michael Hanselmann
    constants.HV_BOOT_ORDER: (True, ) +
531 016d04b3 Michael Hanselmann
      (lambda x: x and len(x.strip("acdn")) == 0,
532 016d04b3 Michael Hanselmann
       "Invalid boot order specified, must be one or more of [acdn]",
533 016d04b3 Michael Hanselmann
       None, None),
534 205ab586 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH: hv_base.OPT_FILE_CHECK,
535 016d04b3 Michael Hanselmann
    constants.HV_DISK_TYPE:
536 016d04b3 Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_HVM_VALID_DISK_TYPES),
537 016d04b3 Michael Hanselmann
    constants.HV_NIC_TYPE:
538 016d04b3 Michael Hanselmann
      hv_base.ParamInSet(True, constants.HT_HVM_VALID_NIC_TYPES),
539 205ab586 Iustin Pop
    constants.HV_PAE: hv_base.NO_CHECK,
540 016d04b3 Michael Hanselmann
    constants.HV_VNC_BIND_ADDRESS:
541 016d04b3 Michael Hanselmann
      (False, utils.IsValidIP,
542 016d04b3 Michael Hanselmann
       "VNC bind address is not a valid IP address", None, None),
543 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.REQ_FILE_CHECK,
544 205ab586 Iustin Pop
    constants.HV_DEVICE_MODEL: hv_base.REQ_FILE_CHECK,
545 6e6bb8d5 Guido Trotter
    constants.HV_VNC_PASSWORD_FILE: hv_base.REQ_FILE_CHECK,
546 78411c60 Iustin Pop
    constants.HV_MIGRATION_PORT: hv_base.NET_PORT_CHECK,
547 205ab586 Iustin Pop
    }
548 09ea8710 Iustin Pop
549 65a6f9b7 Michael Hanselmann
  @classmethod
550 07813a9e Iustin Pop
  def _WriteConfigFile(cls, instance, block_devices):
551 65a6f9b7 Michael Hanselmann
    """Create a Xen 3.1 HVM config file.
552 65a6f9b7 Michael Hanselmann

553 65a6f9b7 Michael Hanselmann
    """
554 a985b417 Iustin Pop
    hvp = instance.hvparams
555 a985b417 Iustin Pop
556 65a6f9b7 Michael Hanselmann
    config = StringIO()
557 65a6f9b7 Michael Hanselmann
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
558 e2ee1cea Iustin Pop
559 e2ee1cea Iustin Pop
    # kernel handling
560 e2ee1cea Iustin Pop
    kpath = hvp[constants.HV_KERNEL_PATH]
561 e2ee1cea Iustin Pop
    config.write("kernel = '%s'\n" % kpath)
562 e2ee1cea Iustin Pop
563 65a6f9b7 Michael Hanselmann
    config.write("builder = 'hvm'\n")
564 8b3fd458 Iustin Pop
    config.write("memory = %d\n" % instance.beparams[constants.BE_MEMORY])
565 8b3fd458 Iustin Pop
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
566 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
567 09ea8710 Iustin Pop
    if hvp[constants.HV_PAE]:
568 a21dda8b Iustin Pop
      config.write("pae = 1\n")
569 a21dda8b Iustin Pop
    else:
570 a21dda8b Iustin Pop
      config.write("pae = 0\n")
571 09ea8710 Iustin Pop
    if hvp[constants.HV_ACPI]:
572 a21dda8b Iustin Pop
      config.write("acpi = 1\n")
573 a21dda8b Iustin Pop
    else:
574 a21dda8b Iustin Pop
      config.write("acpi = 0\n")
575 65a6f9b7 Michael Hanselmann
    config.write("apic = 1\n")
576 09ea8710 Iustin Pop
    config.write("device_model = '%s'\n" % hvp[constants.HV_DEVICE_MODEL])
577 a985b417 Iustin Pop
    config.write("boot = '%s'\n" % hvp[constants.HV_BOOT_ORDER])
578 65a6f9b7 Michael Hanselmann
    config.write("sdl = 0\n")
579 97efde45 Guido Trotter
    config.write("usb = 1\n")
580 97efde45 Guido Trotter
    config.write("usbdevice = 'tablet'\n")
581 65a6f9b7 Michael Hanselmann
    config.write("vnc = 1\n")
582 a985b417 Iustin Pop
    if hvp[constants.HV_VNC_BIND_ADDRESS] is None:
583 d0c11cf7 Alexander Schreiber
      config.write("vnclisten = '%s'\n" % constants.VNC_DEFAULT_BIND_ADDRESS)
584 d0c11cf7 Alexander Schreiber
    else:
585 6b405598 Guido Trotter
      config.write("vnclisten = '%s'\n" % hvp[constants.HV_VNC_BIND_ADDRESS])
586 65a6f9b7 Michael Hanselmann
587 377d74c9 Guido Trotter
    if instance.network_port > constants.VNC_BASE_PORT:
588 377d74c9 Guido Trotter
      display = instance.network_port - constants.VNC_BASE_PORT
589 65a6f9b7 Michael Hanselmann
      config.write("vncdisplay = %s\n" % display)
590 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 0\n")
591 65a6f9b7 Michael Hanselmann
    else:
592 65a6f9b7 Michael Hanselmann
      config.write("# vncdisplay = 1\n")
593 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 1\n")
594 65a6f9b7 Michael Hanselmann
595 6e6bb8d5 Guido Trotter
    vnc_pwd_file = hvp[constants.HV_VNC_PASSWORD_FILE]
596 65a6f9b7 Michael Hanselmann
    try:
597 6e6bb8d5 Guido Trotter
      password = utils.ReadFile(vnc_pwd_file)
598 78f66a17 Guido Trotter
    except EnvironmentError, err:
599 78f66a17 Guido Trotter
      raise errors.HypervisorError("Failed to open VNC password file %s: %s" %
600 6e6bb8d5 Guido Trotter
                                   (vnc_pwd_file, err))
601 65a6f9b7 Michael Hanselmann
602 65a6f9b7 Michael Hanselmann
    config.write("vncpasswd = '%s'\n" % password.rstrip())
603 65a6f9b7 Michael Hanselmann
604 65a6f9b7 Michael Hanselmann
    config.write("serial = 'pty'\n")
605 65a6f9b7 Michael Hanselmann
    config.write("localtime = 1\n")
606 65a6f9b7 Michael Hanselmann
607 65a6f9b7 Michael Hanselmann
    vif_data = []
608 a985b417 Iustin Pop
    nic_type = hvp[constants.HV_NIC_TYPE]
609 f48148c3 Iustin Pop
    if nic_type is None:
610 f48148c3 Iustin Pop
      # ensure old instances don't change
611 f48148c3 Iustin Pop
      nic_type_str = ", type=ioemu"
612 d08f6067 Guido Trotter
    elif nic_type == constants.HT_NIC_PARAVIRTUAL:
613 f48148c3 Iustin Pop
      nic_type_str = ", type=paravirtualized"
614 f48148c3 Iustin Pop
    else:
615 f48148c3 Iustin Pop
      nic_type_str = ", model=%s, type=ioemu" % nic_type
616 65a6f9b7 Michael Hanselmann
    for nic in instance.nics:
617 503b97a9 Guido Trotter
      nic_str = "mac=%s%s" % (nic.mac, nic_type_str)
618 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
619 65a6f9b7 Michael Hanselmann
      if ip is not None:
620 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
621 65a6f9b7 Michael Hanselmann
      vif_data.append("'%s'" % nic_str)
622 503b97a9 Guido Trotter
      if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
623 503b97a9 Guido Trotter
        nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK]
624 65a6f9b7 Michael Hanselmann
625 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
626 a21dda8b Iustin Pop
    disk_data = cls._GetConfigFileDiskData(instance.disk_template,
627 a21dda8b Iustin Pop
                                            block_devices)
628 a985b417 Iustin Pop
    disk_type = hvp[constants.HV_DISK_TYPE]
629 d08f6067 Guido Trotter
    if disk_type in (None, constants.HT_DISK_IOEMU):
630 5397e0b7 Alexander Schreiber
      replacement = ",ioemu:hd"
631 5397e0b7 Alexander Schreiber
    else:
632 5397e0b7 Alexander Schreiber
      replacement = ",hd"
633 5397e0b7 Alexander Schreiber
    disk_data = [line.replace(",sd", replacement) for line in disk_data]
634 a985b417 Iustin Pop
    iso_path = hvp[constants.HV_CDROM_IMAGE_PATH]
635 f48148c3 Iustin Pop
    if iso_path:
636 f48148c3 Iustin Pop
      iso = "'file:%s,hdc:cdrom,r'" % iso_path
637 a21dda8b Iustin Pop
      disk_data.append(iso)
638 a21dda8b Iustin Pop
639 a21dda8b Iustin Pop
    config.write("disk = [%s]\n" % (",".join(disk_data)))
640 a21dda8b Iustin Pop
641 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
642 65a6f9b7 Michael Hanselmann
    config.write("on_reboot = 'restart'\n")
643 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
644 65a6f9b7 Michael Hanselmann
    # just in case it exists
645 65a6f9b7 Michael Hanselmann
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
646 65a6f9b7 Michael Hanselmann
    try:
647 73cd67f4 Guido Trotter
      utils.WriteFile("/etc/xen/%s" % instance.name,
648 73cd67f4 Guido Trotter
                      data=config.getvalue())
649 73cd67f4 Guido Trotter
    except EnvironmentError, err:
650 73cd67f4 Guido Trotter
      raise errors.HypervisorError("Cannot write Xen instance confile"
651 73cd67f4 Guido Trotter
                                   " file /etc/xen/%s: %s" %
652 73cd67f4 Guido Trotter
                                   (instance.name, err))
653 73cd67f4 Guido Trotter
654 65a6f9b7 Michael Hanselmann
    return True