Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ 748e4b5a

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

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

42 65a6f9b7 Michael Hanselmann
  """
43 d271c6fd Iustin Pop
  CAN_MIGRATE = True
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 691744c4 Iustin Pop
      except (TypeError, 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 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
195 c41eea6e Iustin Pop
    """Stop an instance.
196 c41eea6e Iustin Pop

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

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

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

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

300 65a6f9b7 Michael Hanselmann
    """
301 04c4330c Alexander Schreiber
    return "xm console %s" % instance.name
302 04c4330c Alexander Schreiber
303 65a6f9b7 Michael Hanselmann
304 65a6f9b7 Michael Hanselmann
  def Verify(self):
305 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
306 65a6f9b7 Michael Hanselmann

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

309 65a6f9b7 Michael Hanselmann
    """
310 e3e66f02 Michael Hanselmann
    result = utils.RunCmd(["xm", "info"])
311 e3e66f02 Michael Hanselmann
    if result.failed:
312 3213d3c8 Iustin Pop
      return "'xm info' failed: %s, %s" % (result.fail_reason, result.output)
313 65a6f9b7 Michael Hanselmann
314 65a6f9b7 Michael Hanselmann
  @staticmethod
315 7ed85ffe Iustin Pop
  def _GetConfigFileDiskData(block_devices):
316 65a6f9b7 Michael Hanselmann
    """Get disk directive for xen config file.
317 65a6f9b7 Michael Hanselmann

318 65a6f9b7 Michael Hanselmann
    This method builds the xen config disk directive according to the
319 65a6f9b7 Michael Hanselmann
    given disk_template and block_devices.
320 65a6f9b7 Michael Hanselmann

321 c41eea6e Iustin Pop
    @param block_devices: list of tuples (cfdev, rldev):
322 c41eea6e Iustin Pop
        - cfdev: dict containing ganeti config disk part
323 c41eea6e Iustin Pop
        - rldev: ganeti.bdev.BlockDev object
324 65a6f9b7 Michael Hanselmann

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

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

356 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
357 4390ccff Guido Trotter
    @param instance: instance to be migrated
358 4390ccff Guido Trotter
    @rtype: string
359 4390ccff Guido Trotter
    @return: content of the xen config file
360 4390ccff Guido Trotter

361 4390ccff Guido Trotter
    """
362 4390ccff Guido Trotter
    return self._ReadConfigFile(instance.name)
363 4390ccff Guido Trotter
364 4390ccff Guido Trotter
  def AcceptInstance(self, instance, info, target):
365 4390ccff Guido Trotter
    """Prepare to accept an instance.
366 4390ccff Guido Trotter

367 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
368 4390ccff Guido Trotter
    @param instance: instance to be accepted
369 4390ccff Guido Trotter
    @type info: string
370 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
371 4390ccff Guido Trotter
    @type target: string
372 4390ccff Guido Trotter
    @param target: target host (usually ip), on this node
373 4390ccff Guido Trotter

374 4390ccff Guido Trotter
    """
375 4390ccff Guido Trotter
    pass
376 4390ccff Guido Trotter
377 4390ccff Guido Trotter
  def FinalizeMigration(self, instance, info, success):
378 4390ccff Guido Trotter
    """Finalize an instance migration.
379 4390ccff Guido Trotter

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

383 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
384 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
385 4390ccff Guido Trotter
    @type info: string
386 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
387 4390ccff Guido Trotter
    @type success: boolean
388 4390ccff Guido Trotter
    @param success: whether the migration was a success or a failure
389 4390ccff Guido Trotter

390 4390ccff Guido Trotter
    """
391 4390ccff Guido Trotter
    if success:
392 4390ccff Guido Trotter
      self._WriteConfigFileStatic(instance.name, info)
393 4390ccff Guido Trotter
394 6e7275c0 Iustin Pop
  def MigrateInstance(self, instance, target, live):
395 6e7275c0 Iustin Pop
    """Migrate an instance to a target node.
396 6e7275c0 Iustin Pop

397 6e7275c0 Iustin Pop
    The migration will not be attempted if the instance is not
398 6e7275c0 Iustin Pop
    currently running.
399 6e7275c0 Iustin Pop

400 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
401 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
402 fdf7f055 Guido Trotter
    @type target: string
403 fdf7f055 Guido Trotter
    @param target: ip address of the target node
404 fdf7f055 Guido Trotter
    @type live: boolean
405 fdf7f055 Guido Trotter
    @param live: perform a live migration
406 fdf7f055 Guido Trotter

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

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

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

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

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