Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ b43dcc5a

History | View | Annotate | Download (21.8 kB)

1 65a6f9b7 Michael Hanselmann
#
2 65a6f9b7 Michael Hanselmann
#
3 65a6f9b7 Michael Hanselmann
4 783a6c0b Iustin Pop
# Copyright (C) 2006, 2007, 2008, 2009, 2010 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 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
462 205ab586 Iustin Pop
    }
463 f48148c3 Iustin Pop
464 65a6f9b7 Michael Hanselmann
  @classmethod
465 07813a9e Iustin Pop
  def _WriteConfigFile(cls, instance, block_devices):
466 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
467 65a6f9b7 Michael Hanselmann

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

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