Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ fe5b0c42

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

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

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

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

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