Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (21.5 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 7ed85ffe Iustin Pop
  def _GetConfigFileDiskData(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 block_devices: list of tuples (cfdev, rldev):
316 c41eea6e Iustin Pop
        - cfdev: dict containing ganeti config disk part
317 c41eea6e Iustin Pop
        - rldev: ganeti.bdev.BlockDev object
318 65a6f9b7 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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