Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ 2a7e887b

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

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

44 65a6f9b7 Michael Hanselmann
  """
45 7dd106d3 Iustin Pop
  REBOOT_RETRY_COUNT = 60
46 7dd106d3 Iustin Pop
  REBOOT_RETRY_INTERVAL = 10
47 65a6f9b7 Michael Hanselmann
48 5661b908 Iustin Pop
  @classmethod
49 07813a9e Iustin Pop
  def _WriteConfigFile(cls, instance, block_devices):
50 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
51 65a6f9b7 Michael Hanselmann

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

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

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

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

79 65a6f9b7 Michael Hanselmann
    """
80 53c776b5 Iustin Pop
    utils.RemoveFile("/etc/xen/%s" % instance_name)
81 65a6f9b7 Michael Hanselmann
82 65a6f9b7 Michael Hanselmann
  @staticmethod
83 65a6f9b7 Michael Hanselmann
  def _GetXMList(include_node):
84 65a6f9b7 Michael Hanselmann
    """Return the list of running instances.
85 65a6f9b7 Michael Hanselmann

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

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

91 65a6f9b7 Michael Hanselmann
    """
92 65a6f9b7 Michael Hanselmann
    for dummy in range(5):
93 65a6f9b7 Michael Hanselmann
      result = utils.RunCmd(["xm", "list"])
94 65a6f9b7 Michael Hanselmann
      if not result.failed:
95 65a6f9b7 Michael Hanselmann
        break
96 b48909c8 Iustin Pop
      logging.error("xm list failed (%s): %s", result.fail_reason,
97 b48909c8 Iustin Pop
                    result.output)
98 65a6f9b7 Michael Hanselmann
      time.sleep(1)
99 65a6f9b7 Michael Hanselmann
100 65a6f9b7 Michael Hanselmann
    if result.failed:
101 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("xm list failed, retries"
102 65a6f9b7 Michael Hanselmann
                                   " exceeded (%s): %s" %
103 3213d3c8 Iustin Pop
                                   (result.fail_reason, result.output))
104 65a6f9b7 Michael Hanselmann
105 65a6f9b7 Michael Hanselmann
    # skip over the heading
106 65a6f9b7 Michael Hanselmann
    lines = result.stdout.splitlines()[1:]
107 65a6f9b7 Michael Hanselmann
    result = []
108 65a6f9b7 Michael Hanselmann
    for line in lines:
109 65a6f9b7 Michael Hanselmann
      # The format of lines is:
110 65a6f9b7 Michael Hanselmann
      # Name      ID Mem(MiB) VCPUs State  Time(s)
111 65a6f9b7 Michael Hanselmann
      # Domain-0   0  3418     4 r-----    266.2
112 65a6f9b7 Michael Hanselmann
      data = line.split()
113 65a6f9b7 Michael Hanselmann
      if len(data) != 6:
114 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("Can't parse output of xm list,"
115 65a6f9b7 Michael Hanselmann
                                     " line: %s" % line)
116 65a6f9b7 Michael Hanselmann
      try:
117 65a6f9b7 Michael Hanselmann
        data[1] = int(data[1])
118 65a6f9b7 Michael Hanselmann
        data[2] = int(data[2])
119 65a6f9b7 Michael Hanselmann
        data[3] = int(data[3])
120 65a6f9b7 Michael Hanselmann
        data[5] = float(data[5])
121 65a6f9b7 Michael Hanselmann
      except ValueError, err:
122 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("Can't parse output of xm list,"
123 65a6f9b7 Michael Hanselmann
                                     " line: %s, error: %s" % (line, err))
124 65a6f9b7 Michael Hanselmann
125 65a6f9b7 Michael Hanselmann
      # skip the Domain-0 (optional)
126 65a6f9b7 Michael Hanselmann
      if include_node or data[0] != 'Domain-0':
127 65a6f9b7 Michael Hanselmann
        result.append(data)
128 65a6f9b7 Michael Hanselmann
129 65a6f9b7 Michael Hanselmann
    return result
130 65a6f9b7 Michael Hanselmann
131 65a6f9b7 Michael Hanselmann
  def ListInstances(self):
132 65a6f9b7 Michael Hanselmann
    """Get the list of running instances.
133 65a6f9b7 Michael Hanselmann

134 65a6f9b7 Michael Hanselmann
    """
135 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(False)
136 65a6f9b7 Michael Hanselmann
    names = [info[0] for info in xm_list]
137 65a6f9b7 Michael Hanselmann
    return names
138 65a6f9b7 Michael Hanselmann
139 65a6f9b7 Michael Hanselmann
  def GetInstanceInfo(self, instance_name):
140 65a6f9b7 Michael Hanselmann
    """Get instance properties.
141 65a6f9b7 Michael Hanselmann

142 c41eea6e Iustin Pop
    @param instance_name: the instance name
143 c41eea6e Iustin Pop

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

146 65a6f9b7 Michael Hanselmann
    """
147 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(instance_name=="Domain-0")
148 65a6f9b7 Michael Hanselmann
    result = None
149 65a6f9b7 Michael Hanselmann
    for data in xm_list:
150 65a6f9b7 Michael Hanselmann
      if data[0] == instance_name:
151 65a6f9b7 Michael Hanselmann
        result = data
152 65a6f9b7 Michael Hanselmann
        break
153 65a6f9b7 Michael Hanselmann
    return result
154 65a6f9b7 Michael Hanselmann
155 65a6f9b7 Michael Hanselmann
  def GetAllInstancesInfo(self):
156 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
157 65a6f9b7 Michael Hanselmann

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

160 65a6f9b7 Michael Hanselmann
    """
161 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(False)
162 65a6f9b7 Michael Hanselmann
    return xm_list
163 65a6f9b7 Michael Hanselmann
164 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
165 c41eea6e Iustin Pop
    """Start an instance.
166 c41eea6e Iustin Pop

167 c41eea6e Iustin Pop
    """
168 07813a9e Iustin Pop
    self._WriteConfigFile(instance, block_devices)
169 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(["xm", "create", instance.name])
170 65a6f9b7 Michael Hanselmann
171 65a6f9b7 Michael Hanselmann
    if result.failed:
172 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
173 65a6f9b7 Michael Hanselmann
                                   (instance.name, result.fail_reason,
174 65a6f9b7 Michael Hanselmann
                                    result.output))
175 65a6f9b7 Michael Hanselmann
176 65a6f9b7 Michael Hanselmann
  def StopInstance(self, instance, force=False):
177 c41eea6e Iustin Pop
    """Stop an instance.
178 c41eea6e Iustin Pop

179 c41eea6e Iustin Pop
    """
180 53c776b5 Iustin Pop
    self._RemoveConfigFile(instance.name)
181 65a6f9b7 Michael Hanselmann
    if force:
182 65a6f9b7 Michael Hanselmann
      command = ["xm", "destroy", instance.name]
183 65a6f9b7 Michael Hanselmann
    else:
184 65a6f9b7 Michael Hanselmann
      command = ["xm", "shutdown", instance.name]
185 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(command)
186 65a6f9b7 Michael Hanselmann
187 65a6f9b7 Michael Hanselmann
    if result.failed:
188 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to stop instance %s: %s, %s" %
189 3213d3c8 Iustin Pop
                                   (instance.name, result.fail_reason,
190 3213d3c8 Iustin Pop
                                    result.output))
191 65a6f9b7 Michael Hanselmann
192 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
193 c41eea6e Iustin Pop
    """Reboot an instance.
194 c41eea6e Iustin Pop

195 c41eea6e Iustin Pop
    """
196 7dd106d3 Iustin Pop
    ini_info = self.GetInstanceInfo(instance.name)
197 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(["xm", "reboot", instance.name])
198 65a6f9b7 Michael Hanselmann
199 65a6f9b7 Michael Hanselmann
    if result.failed:
200 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s: %s, %s" %
201 3213d3c8 Iustin Pop
                                   (instance.name, result.fail_reason,
202 3213d3c8 Iustin Pop
                                    result.output))
203 7dd106d3 Iustin Pop
    done = False
204 7dd106d3 Iustin Pop
    retries = self.REBOOT_RETRY_COUNT
205 7dd106d3 Iustin Pop
    while retries > 0:
206 7dd106d3 Iustin Pop
      new_info = self.GetInstanceInfo(instance.name)
207 7dd106d3 Iustin Pop
      # check if the domain ID has changed or the run time has
208 7dd106d3 Iustin Pop
      # decreased
209 7dd106d3 Iustin Pop
      if new_info[1] != ini_info[1] or new_info[5] < ini_info[5]:
210 7dd106d3 Iustin Pop
        done = True
211 7dd106d3 Iustin Pop
        break
212 7dd106d3 Iustin Pop
      time.sleep(self.REBOOT_RETRY_INTERVAL)
213 7dd106d3 Iustin Pop
      retries -= 1
214 7dd106d3 Iustin Pop
215 7dd106d3 Iustin Pop
    if not done:
216 7dd106d3 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s: instance"
217 7dd106d3 Iustin Pop
                                   " did not reboot in the expected interval" %
218 7dd106d3 Iustin Pop
                                   (instance.name, ))
219 65a6f9b7 Michael Hanselmann
220 65a6f9b7 Michael Hanselmann
  def GetNodeInfo(self):
221 65a6f9b7 Michael Hanselmann
    """Return information about the node.
222 65a6f9b7 Michael Hanselmann

223 0105bad3 Iustin Pop
    @return: a dict with the following keys (memory values in MiB):
224 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
225 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
226 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
227 0105bad3 Iustin Pop
          - nr_cpus: total number of CPUs
228 0105bad3 Iustin Pop
          - nr_nodes: in a NUMA system, the number of domains
229 0105bad3 Iustin Pop
          - nr_sockets: the number of physical CPU sockets in the node
230 65a6f9b7 Michael Hanselmann

231 65a6f9b7 Michael Hanselmann
    """
232 65a6f9b7 Michael Hanselmann
    # note: in xen 3, memory has changed to total_memory
233 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(["xm", "info"])
234 65a6f9b7 Michael Hanselmann
    if result.failed:
235 b48909c8 Iustin Pop
      logging.error("Can't run 'xm info' (%s): %s", result.fail_reason,
236 b48909c8 Iustin Pop
                    result.output)
237 65a6f9b7 Michael Hanselmann
      return None
238 65a6f9b7 Michael Hanselmann
239 65a6f9b7 Michael Hanselmann
    xmoutput = result.stdout.splitlines()
240 65a6f9b7 Michael Hanselmann
    result = {}
241 0105bad3 Iustin Pop
    cores_per_socket = threads_per_core = nr_cpus = None
242 65a6f9b7 Michael Hanselmann
    for line in xmoutput:
243 65a6f9b7 Michael Hanselmann
      splitfields = line.split(":", 1)
244 65a6f9b7 Michael Hanselmann
245 65a6f9b7 Michael Hanselmann
      if len(splitfields) > 1:
246 65a6f9b7 Michael Hanselmann
        key = splitfields[0].strip()
247 65a6f9b7 Michael Hanselmann
        val = splitfields[1].strip()
248 65a6f9b7 Michael Hanselmann
        if key == 'memory' or key == 'total_memory':
249 65a6f9b7 Michael Hanselmann
          result['memory_total'] = int(val)
250 65a6f9b7 Michael Hanselmann
        elif key == 'free_memory':
251 65a6f9b7 Michael Hanselmann
          result['memory_free'] = int(val)
252 e8a4c138 Iustin Pop
        elif key == 'nr_cpus':
253 0105bad3 Iustin Pop
          nr_cpus = result['cpu_total'] = int(val)
254 0105bad3 Iustin Pop
        elif key == 'nr_nodes':
255 0105bad3 Iustin Pop
          result['cpu_nodes'] = int(val)
256 0105bad3 Iustin Pop
        elif key == 'cores_per_socket':
257 0105bad3 Iustin Pop
          cores_per_socket = int(val)
258 0105bad3 Iustin Pop
        elif key == 'threads_per_core':
259 0105bad3 Iustin Pop
          threads_per_core = int(val)
260 0105bad3 Iustin Pop
261 0105bad3 Iustin Pop
    if (cores_per_socket is not None and
262 0105bad3 Iustin Pop
        threads_per_core is not None and nr_cpus is not None):
263 0105bad3 Iustin Pop
      result['cpu_sockets'] = nr_cpus / (cores_per_socket * threads_per_core)
264 0105bad3 Iustin Pop
265 65a6f9b7 Michael Hanselmann
    dom0_info = self.GetInstanceInfo("Domain-0")
266 65a6f9b7 Michael Hanselmann
    if dom0_info is not None:
267 65a6f9b7 Michael Hanselmann
      result['memory_dom0'] = dom0_info[2]
268 65a6f9b7 Michael Hanselmann
269 65a6f9b7 Michael Hanselmann
    return result
270 65a6f9b7 Michael Hanselmann
271 637ce7f9 Guido Trotter
  @classmethod
272 5431b2e4 Guido Trotter
  def GetShellCommandForConsole(cls, instance, hvparams, beparams):
273 65a6f9b7 Michael Hanselmann
    """Return a command for connecting to the console of an instance.
274 65a6f9b7 Michael Hanselmann

275 65a6f9b7 Michael Hanselmann
    """
276 04c4330c Alexander Schreiber
    return "xm console %s" % instance.name
277 04c4330c Alexander Schreiber
278 65a6f9b7 Michael Hanselmann
279 65a6f9b7 Michael Hanselmann
  def Verify(self):
280 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
281 65a6f9b7 Michael Hanselmann

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

284 65a6f9b7 Michael Hanselmann
    """
285 e3e66f02 Michael Hanselmann
    result = utils.RunCmd(["xm", "info"])
286 e3e66f02 Michael Hanselmann
    if result.failed:
287 3213d3c8 Iustin Pop
      return "'xm info' failed: %s, %s" % (result.fail_reason, result.output)
288 65a6f9b7 Michael Hanselmann
289 65a6f9b7 Michael Hanselmann
  @staticmethod
290 65a6f9b7 Michael Hanselmann
  def _GetConfigFileDiskData(disk_template, block_devices):
291 65a6f9b7 Michael Hanselmann
    """Get disk directive for xen config file.
292 65a6f9b7 Michael Hanselmann

293 65a6f9b7 Michael Hanselmann
    This method builds the xen config disk directive according to the
294 65a6f9b7 Michael Hanselmann
    given disk_template and block_devices.
295 65a6f9b7 Michael Hanselmann

296 c41eea6e Iustin Pop
    @param disk_template: string containing instance disk template
297 c41eea6e Iustin Pop
    @param block_devices: list of tuples (cfdev, rldev):
298 c41eea6e Iustin Pop
        - cfdev: dict containing ganeti config disk part
299 c41eea6e Iustin Pop
        - rldev: ganeti.bdev.BlockDev object
300 65a6f9b7 Michael Hanselmann

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

303 65a6f9b7 Michael Hanselmann
    """
304 65a6f9b7 Michael Hanselmann
    FILE_DRIVER_MAP = {
305 65a6f9b7 Michael Hanselmann
      constants.FD_LOOP: "file",
306 65a6f9b7 Michael Hanselmann
      constants.FD_BLKTAP: "tap:aio",
307 65a6f9b7 Michael Hanselmann
      }
308 65a6f9b7 Michael Hanselmann
    disk_data = []
309 2864f2d9 Iustin Pop
    if len(block_devices) > 24:
310 2864f2d9 Iustin Pop
      # 'z' - 'a' = 24
311 2864f2d9 Iustin Pop
      raise errors.HypervisorError("Too many disks")
312 2864f2d9 Iustin Pop
    # FIXME: instead of this hardcoding here, each of PVM/HVM should
313 2864f2d9 Iustin Pop
    # directly export their info (currently HVM will just sed this info)
314 2864f2d9 Iustin Pop
    namespace = ["sd" + chr(i + ord('a')) for i in range(24)]
315 069cfbf1 Iustin Pop
    for sd_name, (cfdev, dev_path) in zip(namespace, block_devices):
316 d34b16d7 Iustin Pop
      if cfdev.mode == constants.DISK_RDWR:
317 d34b16d7 Iustin Pop
        mode = "w"
318 d34b16d7 Iustin Pop
      else:
319 d34b16d7 Iustin Pop
        mode = "r"
320 65a6f9b7 Michael Hanselmann
      if cfdev.dev_type == constants.LD_FILE:
321 d34b16d7 Iustin Pop
        line = "'%s:%s,%s,%s'" % (FILE_DRIVER_MAP[cfdev.physical_id[0]],
322 d34b16d7 Iustin Pop
                                  dev_path, sd_name, mode)
323 65a6f9b7 Michael Hanselmann
      else:
324 d34b16d7 Iustin Pop
        line = "'phy:%s,%s,%s'" % (dev_path, sd_name, mode)
325 65a6f9b7 Michael Hanselmann
      disk_data.append(line)
326 65a6f9b7 Michael Hanselmann
327 65a6f9b7 Michael Hanselmann
    return disk_data
328 65a6f9b7 Michael Hanselmann
329 4390ccff Guido Trotter
  def MigrationInfo(self, instance):
330 4390ccff Guido Trotter
    """Get instance information to perform a migration.
331 4390ccff Guido Trotter

332 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
333 4390ccff Guido Trotter
    @param instance: instance to be migrated
334 4390ccff Guido Trotter
    @rtype: string
335 4390ccff Guido Trotter
    @return: content of the xen config file
336 4390ccff Guido Trotter

337 4390ccff Guido Trotter
    """
338 4390ccff Guido Trotter
    return self._ReadConfigFile(instance.name)
339 4390ccff Guido Trotter
340 4390ccff Guido Trotter
  def AcceptInstance(self, instance, info, target):
341 4390ccff Guido Trotter
    """Prepare to accept an instance.
342 4390ccff Guido Trotter

343 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
344 4390ccff Guido Trotter
    @param instance: instance to be accepted
345 4390ccff Guido Trotter
    @type info: string
346 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
347 4390ccff Guido Trotter
    @type target: string
348 4390ccff Guido Trotter
    @param target: target host (usually ip), on this node
349 4390ccff Guido Trotter

350 4390ccff Guido Trotter
    """
351 4390ccff Guido Trotter
    pass
352 4390ccff Guido Trotter
353 4390ccff Guido Trotter
  def FinalizeMigration(self, instance, info, success):
354 4390ccff Guido Trotter
    """Finalize an instance migration.
355 4390ccff Guido Trotter

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

359 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
360 4390ccff Guido Trotter
    @param instance: instance whose migration is being aborted
361 4390ccff Guido Trotter
    @type info: string
362 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
363 4390ccff Guido Trotter
    @type success: boolean
364 4390ccff Guido Trotter
    @param success: whether the migration was a success or a failure
365 4390ccff Guido Trotter

366 4390ccff Guido Trotter
    """
367 4390ccff Guido Trotter
    if success:
368 4390ccff Guido Trotter
      self._WriteConfigFileStatic(instance.name, info)
369 4390ccff Guido Trotter
370 6e7275c0 Iustin Pop
  def MigrateInstance(self, instance, target, live):
371 6e7275c0 Iustin Pop
    """Migrate an instance to a target node.
372 6e7275c0 Iustin Pop

373 6e7275c0 Iustin Pop
    The migration will not be attempted if the instance is not
374 6e7275c0 Iustin Pop
    currently running.
375 6e7275c0 Iustin Pop

376 fdf7f055 Guido Trotter
    @type instance: string
377 fdf7f055 Guido Trotter
    @param instance: instance name
378 fdf7f055 Guido Trotter
    @type target: string
379 fdf7f055 Guido Trotter
    @param target: ip address of the target node
380 fdf7f055 Guido Trotter
    @type live: boolean
381 fdf7f055 Guido Trotter
    @param live: perform a live migration
382 fdf7f055 Guido Trotter

383 6e7275c0 Iustin Pop
    """
384 6e7275c0 Iustin Pop
    if self.GetInstanceInfo(instance) is None:
385 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Instance not running, cannot migrate")
386 6e7275c0 Iustin Pop
    args = ["xm", "migrate"]
387 6e7275c0 Iustin Pop
    if live:
388 6e7275c0 Iustin Pop
      args.append("-l")
389 6e7275c0 Iustin Pop
    args.extend([instance, target])
390 6e7275c0 Iustin Pop
    result = utils.RunCmd(args)
391 6e7275c0 Iustin Pop
    if result.failed:
392 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Failed to migrate instance %s: %s" %
393 6e7275c0 Iustin Pop
                                   (instance, result.output))
394 53c776b5 Iustin Pop
    # remove old xen file after migration succeeded
395 53c776b5 Iustin Pop
    try:
396 53c776b5 Iustin Pop
      self._RemoveConfigFile(instance)
397 c979d253 Iustin Pop
    except EnvironmentError:
398 c979d253 Iustin Pop
      logging.exception("Failure while removing instance config file")
399 6e7275c0 Iustin Pop
400 65a6f9b7 Michael Hanselmann
401 65a6f9b7 Michael Hanselmann
class XenPvmHypervisor(XenHypervisor):
402 65a6f9b7 Michael Hanselmann
  """Xen PVM hypervisor interface"""
403 65a6f9b7 Michael Hanselmann
404 f48148c3 Iustin Pop
  PARAMETERS = [
405 f48148c3 Iustin Pop
    constants.HV_KERNEL_PATH,
406 f48148c3 Iustin Pop
    constants.HV_INITRD_PATH,
407 074ca009 Guido Trotter
    constants.HV_ROOT_PATH,
408 07813a9e Iustin Pop
    constants.HV_KERNEL_ARGS,
409 f48148c3 Iustin Pop
    ]
410 f48148c3 Iustin Pop
411 f48148c3 Iustin Pop
  @classmethod
412 f48148c3 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
413 f48148c3 Iustin Pop
    """Check the given parameters for validity.
414 f48148c3 Iustin Pop

415 f48148c3 Iustin Pop
    For the PVM hypervisor, this only check the existence of the
416 f48148c3 Iustin Pop
    kernel.
417 f48148c3 Iustin Pop

418 f48148c3 Iustin Pop
    @type hvparams:  dict
419 f48148c3 Iustin Pop
    @param hvparams: dictionary with parameter names/value
420 f48148c3 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
421 f48148c3 Iustin Pop

422 f48148c3 Iustin Pop
    """
423 f48148c3 Iustin Pop
    super(XenPvmHypervisor, cls).CheckParameterSyntax(hvparams)
424 f48148c3 Iustin Pop
425 f48148c3 Iustin Pop
    if not hvparams[constants.HV_KERNEL_PATH]:
426 f48148c3 Iustin Pop
      raise errors.HypervisorError("Need a kernel for the instance")
427 f48148c3 Iustin Pop
428 f48148c3 Iustin Pop
    if not os.path.isabs(hvparams[constants.HV_KERNEL_PATH]):
429 50cb2e2a Guido Trotter
      raise errors.HypervisorError("The kernel path must be an absolute path")
430 f48148c3 Iustin Pop
431 074ca009 Guido Trotter
    if not hvparams[constants.HV_ROOT_PATH]:
432 074ca009 Guido Trotter
      raise errors.HypervisorError("Need a root partition for the instance")
433 074ca009 Guido Trotter
434 f48148c3 Iustin Pop
    if hvparams[constants.HV_INITRD_PATH]:
435 f48148c3 Iustin Pop
      if not os.path.isabs(hvparams[constants.HV_INITRD_PATH]):
436 50cb2e2a Guido Trotter
        raise errors.HypervisorError("The initrd path must be an absolute path"
437 f48148c3 Iustin Pop
                                     ", if defined")
438 f48148c3 Iustin Pop
439 f48148c3 Iustin Pop
  def ValidateParameters(self, hvparams):
440 f48148c3 Iustin Pop
    """Check the given parameters for validity.
441 f48148c3 Iustin Pop

442 f48148c3 Iustin Pop
    For the PVM hypervisor, this only check the existence of the
443 f48148c3 Iustin Pop
    kernel.
444 f48148c3 Iustin Pop

445 f48148c3 Iustin Pop
    """
446 f48148c3 Iustin Pop
    super(XenPvmHypervisor, self).ValidateParameters(hvparams)
447 f48148c3 Iustin Pop
448 f48148c3 Iustin Pop
    kernel_path = hvparams[constants.HV_KERNEL_PATH]
449 f48148c3 Iustin Pop
    if not os.path.isfile(kernel_path):
450 f48148c3 Iustin Pop
      raise errors.HypervisorError("Instance kernel '%s' not found or"
451 f48148c3 Iustin Pop
                                   " not a file" % kernel_path)
452 f48148c3 Iustin Pop
    initrd_path = hvparams[constants.HV_INITRD_PATH]
453 f48148c3 Iustin Pop
    if initrd_path and not os.path.isfile(initrd_path):
454 f48148c3 Iustin Pop
      raise errors.HypervisorError("Instance initrd '%s' not found or"
455 f48148c3 Iustin Pop
                                   " not a file" % initrd_path)
456 f48148c3 Iustin Pop
457 65a6f9b7 Michael Hanselmann
  @classmethod
458 07813a9e Iustin Pop
  def _WriteConfigFile(cls, instance, block_devices):
459 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
460 65a6f9b7 Michael Hanselmann

461 65a6f9b7 Michael Hanselmann
    """
462 a985b417 Iustin Pop
    hvp = instance.hvparams
463 65a6f9b7 Michael Hanselmann
    config = StringIO()
464 65a6f9b7 Michael Hanselmann
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
465 65a6f9b7 Michael Hanselmann
466 65a6f9b7 Michael Hanselmann
    # kernel handling
467 a985b417 Iustin Pop
    kpath = hvp[constants.HV_KERNEL_PATH]
468 65a6f9b7 Michael Hanselmann
    config.write("kernel = '%s'\n" % kpath)
469 65a6f9b7 Michael Hanselmann
470 65a6f9b7 Michael Hanselmann
    # initrd handling
471 a985b417 Iustin Pop
    initrd_path = hvp[constants.HV_INITRD_PATH]
472 65a6f9b7 Michael Hanselmann
    if initrd_path:
473 65a6f9b7 Michael Hanselmann
      config.write("ramdisk = '%s'\n" % initrd_path)
474 65a6f9b7 Michael Hanselmann
475 65a6f9b7 Michael Hanselmann
    # rest of the settings
476 8b3fd458 Iustin Pop
    config.write("memory = %d\n" % instance.beparams[constants.BE_MEMORY])
477 8b3fd458 Iustin Pop
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
478 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
479 65a6f9b7 Michael Hanselmann
480 65a6f9b7 Michael Hanselmann
    vif_data = []
481 65a6f9b7 Michael Hanselmann
    for nic in instance.nics:
482 65a6f9b7 Michael Hanselmann
      nic_str = "mac=%s, bridge=%s" % (nic.mac, nic.bridge)
483 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
484 65a6f9b7 Michael Hanselmann
      if ip is not None:
485 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
486 65a6f9b7 Michael Hanselmann
      vif_data.append("'%s'" % nic_str)
487 65a6f9b7 Michael Hanselmann
488 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
489 65a6f9b7 Michael Hanselmann
    config.write("disk = [%s]\n" % ",".join(
490 65a6f9b7 Michael Hanselmann
                 cls._GetConfigFileDiskData(instance.disk_template,
491 65a6f9b7 Michael Hanselmann
                                            block_devices)))
492 074ca009 Guido Trotter
493 07813a9e Iustin Pop
    config.write("root = '%s'\n" % hvp[constants.HV_ROOT_PATH])
494 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
495 65a6f9b7 Michael Hanselmann
    config.write("on_reboot = 'restart'\n")
496 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
497 07813a9e Iustin Pop
    config.write("extra = '%s'\n" % hvp[constants.HV_KERNEL_ARGS])
498 65a6f9b7 Michael Hanselmann
    # just in case it exists
499 65a6f9b7 Michael Hanselmann
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
500 65a6f9b7 Michael Hanselmann
    try:
501 a985b417 Iustin Pop
      utils.WriteFile("/etc/xen/%s" % instance.name, data=config.getvalue())
502 73cd67f4 Guido Trotter
    except EnvironmentError, err:
503 73cd67f4 Guido Trotter
      raise errors.HypervisorError("Cannot write Xen instance confile"
504 73cd67f4 Guido Trotter
                                   " file /etc/xen/%s: %s" %
505 73cd67f4 Guido Trotter
                                   (instance.name, err))
506 73cd67f4 Guido Trotter
507 65a6f9b7 Michael Hanselmann
    return True
508 65a6f9b7 Michael Hanselmann
509 65a6f9b7 Michael Hanselmann
510 65a6f9b7 Michael Hanselmann
class XenHvmHypervisor(XenHypervisor):
511 65a6f9b7 Michael Hanselmann
  """Xen HVM hypervisor interface"""
512 65a6f9b7 Michael Hanselmann
513 f48148c3 Iustin Pop
  PARAMETERS = [
514 f48148c3 Iustin Pop
    constants.HV_ACPI,
515 f48148c3 Iustin Pop
    constants.HV_BOOT_ORDER,
516 f48148c3 Iustin Pop
    constants.HV_CDROM_IMAGE_PATH,
517 f48148c3 Iustin Pop
    constants.HV_DISK_TYPE,
518 f48148c3 Iustin Pop
    constants.HV_NIC_TYPE,
519 f48148c3 Iustin Pop
    constants.HV_PAE,
520 f48148c3 Iustin Pop
    constants.HV_VNC_BIND_ADDRESS,
521 f48148c3 Iustin Pop
    ]
522 f48148c3 Iustin Pop
523 f48148c3 Iustin Pop
  @classmethod
524 f48148c3 Iustin Pop
  def CheckParameterSyntax(cls, hvparams):
525 f48148c3 Iustin Pop
    """Check the given parameter syntax.
526 f48148c3 Iustin Pop

527 f48148c3 Iustin Pop
    """
528 f48148c3 Iustin Pop
    super(XenHvmHypervisor, cls).CheckParameterSyntax(hvparams)
529 f48148c3 Iustin Pop
    # boot order verification
530 f48148c3 Iustin Pop
    boot_order = hvparams[constants.HV_BOOT_ORDER]
531 30948aa6 Guido Trotter
    if not boot_order or len(boot_order.strip("acdn")) != 0:
532 f48148c3 Iustin Pop
      raise errors.HypervisorError("Invalid boot order '%s' specified,"
533 f48148c3 Iustin Pop
                                   " must be one or more of [acdn]" %
534 f48148c3 Iustin Pop
                                   boot_order)
535 f48148c3 Iustin Pop
    # device type checks
536 f48148c3 Iustin Pop
    nic_type = hvparams[constants.HV_NIC_TYPE]
537 f48148c3 Iustin Pop
    if nic_type not in constants.HT_HVM_VALID_NIC_TYPES:
538 5155ede7 Guido Trotter
      raise errors.HypervisorError("Invalid NIC type %s specified for the Xen"
539 5155ede7 Guido Trotter
                                   " HVM hypervisor. Please choose one of: %s"
540 5155ede7 Guido Trotter
                                   % (nic_type,
541 5155ede7 Guido Trotter
                                      constants.HT_HVM_VALID_NIC_TYPES))
542 f48148c3 Iustin Pop
    disk_type = hvparams[constants.HV_DISK_TYPE]
543 f48148c3 Iustin Pop
    if disk_type not in constants.HT_HVM_VALID_DISK_TYPES:
544 5155ede7 Guido Trotter
      raise errors.HypervisorError("Invalid disk type %s specified for the Xen"
545 5155ede7 Guido Trotter
                                   " HVM hypervisor. Please choose one of: %s"
546 5155ede7 Guido Trotter
                                   % (disk_type,
547 5155ede7 Guido Trotter
                                      constants.HT_HVM_VALID_DISK_TYPES))
548 f48148c3 Iustin Pop
    # vnc_bind_address verification
549 f48148c3 Iustin Pop
    vnc_bind_address = hvparams[constants.HV_VNC_BIND_ADDRESS]
550 5b460366 Iustin Pop
    if vnc_bind_address:
551 f48148c3 Iustin Pop
      if not utils.IsValidIP(vnc_bind_address):
552 f48148c3 Iustin Pop
        raise errors.OpPrereqError("given VNC bind address '%s' doesn't look"
553 f48148c3 Iustin Pop
                                   " like a valid IP address" %
554 f48148c3 Iustin Pop
                                   vnc_bind_address)
555 f48148c3 Iustin Pop
556 f48148c3 Iustin Pop
    iso_path = hvparams[constants.HV_CDROM_IMAGE_PATH]
557 f48148c3 Iustin Pop
    if iso_path and not os.path.isabs(iso_path):
558 5661b908 Iustin Pop
      raise errors.HypervisorError("The path to the HVM CDROM image must"
559 5661b908 Iustin Pop
                                   " be an absolute path or None, not %s" %
560 5661b908 Iustin Pop
                                   iso_path)
561 f48148c3 Iustin Pop
562 f48148c3 Iustin Pop
  def ValidateParameters(self, hvparams):
563 f48148c3 Iustin Pop
    """Check the given parameters for validity.
564 f48148c3 Iustin Pop

565 f48148c3 Iustin Pop
    For the PVM hypervisor, this only check the existence of the
566 f48148c3 Iustin Pop
    kernel.
567 f48148c3 Iustin Pop

568 f48148c3 Iustin Pop
    @type hvparams:  dict
569 f48148c3 Iustin Pop
    @param hvparams: dictionary with parameter names/value
570 f48148c3 Iustin Pop
    @raise errors.HypervisorError: when a parameter is not valid
571 f48148c3 Iustin Pop

572 f48148c3 Iustin Pop
    """
573 f48148c3 Iustin Pop
    super(XenHvmHypervisor, self).ValidateParameters(hvparams)
574 f48148c3 Iustin Pop
575 f48148c3 Iustin Pop
    # hvm_cdrom_image_path verification
576 f48148c3 Iustin Pop
    iso_path = hvparams[constants.HV_CDROM_IMAGE_PATH]
577 f48148c3 Iustin Pop
    if iso_path and not os.path.isfile(iso_path):
578 e09fdcfa Iustin Pop
      raise errors.HypervisorError("The HVM CDROM image must either be a"
579 e09fdcfa Iustin Pop
                                   " regular file or a symlink pointing to"
580 e09fdcfa Iustin Pop
                                   " an existing regular file, not %s" %
581 e09fdcfa Iustin Pop
                                   iso_path)
582 f48148c3 Iustin Pop
583 65a6f9b7 Michael Hanselmann
  @classmethod
584 07813a9e Iustin Pop
  def _WriteConfigFile(cls, instance, block_devices):
585 65a6f9b7 Michael Hanselmann
    """Create a Xen 3.1 HVM config file.
586 65a6f9b7 Michael Hanselmann

587 65a6f9b7 Michael Hanselmann
    """
588 a985b417 Iustin Pop
    hvp = instance.hvparams
589 a985b417 Iustin Pop
590 65a6f9b7 Michael Hanselmann
    config = StringIO()
591 65a6f9b7 Michael Hanselmann
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
592 65a6f9b7 Michael Hanselmann
    config.write("kernel = '/usr/lib/xen/boot/hvmloader'\n")
593 65a6f9b7 Michael Hanselmann
    config.write("builder = 'hvm'\n")
594 8b3fd458 Iustin Pop
    config.write("memory = %d\n" % instance.beparams[constants.BE_MEMORY])
595 8b3fd458 Iustin Pop
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
596 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
597 f48148c3 Iustin Pop
    if instance.hvparams[constants.HV_PAE]:
598 a21dda8b Iustin Pop
      config.write("pae = 1\n")
599 a21dda8b Iustin Pop
    else:
600 a21dda8b Iustin Pop
      config.write("pae = 0\n")
601 f48148c3 Iustin Pop
    if instance.hvparams[constants.HV_ACPI]:
602 a21dda8b Iustin Pop
      config.write("acpi = 1\n")
603 a21dda8b Iustin Pop
    else:
604 a21dda8b Iustin Pop
      config.write("acpi = 0\n")
605 65a6f9b7 Michael Hanselmann
    config.write("apic = 1\n")
606 65a6f9b7 Michael Hanselmann
    arch = os.uname()[4]
607 65a6f9b7 Michael Hanselmann
    if '64' in arch:
608 65a6f9b7 Michael Hanselmann
      config.write("device_model = '/usr/lib64/xen/bin/qemu-dm'\n")
609 65a6f9b7 Michael Hanselmann
    else:
610 65a6f9b7 Michael Hanselmann
      config.write("device_model = '/usr/lib/xen/bin/qemu-dm'\n")
611 a985b417 Iustin Pop
    config.write("boot = '%s'\n" % hvp[constants.HV_BOOT_ORDER])
612 65a6f9b7 Michael Hanselmann
    config.write("sdl = 0\n")
613 97efde45 Guido Trotter
    config.write("usb = 1\n")
614 97efde45 Guido Trotter
    config.write("usbdevice = 'tablet'\n")
615 65a6f9b7 Michael Hanselmann
    config.write("vnc = 1\n")
616 a985b417 Iustin Pop
    if hvp[constants.HV_VNC_BIND_ADDRESS] is None:
617 d0c11cf7 Alexander Schreiber
      config.write("vnclisten = '%s'\n" % constants.VNC_DEFAULT_BIND_ADDRESS)
618 d0c11cf7 Alexander Schreiber
    else:
619 6b405598 Guido Trotter
      config.write("vnclisten = '%s'\n" % hvp[constants.HV_VNC_BIND_ADDRESS])
620 65a6f9b7 Michael Hanselmann
621 377d74c9 Guido Trotter
    if instance.network_port > constants.VNC_BASE_PORT:
622 377d74c9 Guido Trotter
      display = instance.network_port - constants.VNC_BASE_PORT
623 65a6f9b7 Michael Hanselmann
      config.write("vncdisplay = %s\n" % display)
624 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 0\n")
625 65a6f9b7 Michael Hanselmann
    else:
626 65a6f9b7 Michael Hanselmann
      config.write("# vncdisplay = 1\n")
627 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 1\n")
628 65a6f9b7 Michael Hanselmann
629 65a6f9b7 Michael Hanselmann
    try:
630 78f66a17 Guido Trotter
      password = utils.ReadFile(constants.VNC_PASSWORD_FILE)
631 78f66a17 Guido Trotter
    except EnvironmentError, err:
632 78f66a17 Guido Trotter
      raise errors.HypervisorError("Failed to open VNC password file %s: %s" %
633 78f66a17 Guido Trotter
                                   (constants.VNC_PASSWORD_FILE, err))
634 65a6f9b7 Michael Hanselmann
635 65a6f9b7 Michael Hanselmann
    config.write("vncpasswd = '%s'\n" % password.rstrip())
636 65a6f9b7 Michael Hanselmann
637 65a6f9b7 Michael Hanselmann
    config.write("serial = 'pty'\n")
638 65a6f9b7 Michael Hanselmann
    config.write("localtime = 1\n")
639 65a6f9b7 Michael Hanselmann
640 65a6f9b7 Michael Hanselmann
    vif_data = []
641 a985b417 Iustin Pop
    nic_type = hvp[constants.HV_NIC_TYPE]
642 f48148c3 Iustin Pop
    if nic_type is None:
643 f48148c3 Iustin Pop
      # ensure old instances don't change
644 f48148c3 Iustin Pop
      nic_type_str = ", type=ioemu"
645 d08f6067 Guido Trotter
    elif nic_type == constants.HT_NIC_PARAVIRTUAL:
646 f48148c3 Iustin Pop
      nic_type_str = ", type=paravirtualized"
647 f48148c3 Iustin Pop
    else:
648 f48148c3 Iustin Pop
      nic_type_str = ", model=%s, type=ioemu" % nic_type
649 65a6f9b7 Michael Hanselmann
    for nic in instance.nics:
650 f48148c3 Iustin Pop
      nic_str = "mac=%s, bridge=%s%s" % (nic.mac, nic.bridge, nic_type_str)
651 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
652 65a6f9b7 Michael Hanselmann
      if ip is not None:
653 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
654 65a6f9b7 Michael Hanselmann
      vif_data.append("'%s'" % nic_str)
655 65a6f9b7 Michael Hanselmann
656 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
657 a21dda8b Iustin Pop
    disk_data = cls._GetConfigFileDiskData(instance.disk_template,
658 a21dda8b Iustin Pop
                                            block_devices)
659 a985b417 Iustin Pop
    disk_type = hvp[constants.HV_DISK_TYPE]
660 d08f6067 Guido Trotter
    if disk_type in (None, constants.HT_DISK_IOEMU):
661 5397e0b7 Alexander Schreiber
      replacement = ",ioemu:hd"
662 5397e0b7 Alexander Schreiber
    else:
663 5397e0b7 Alexander Schreiber
      replacement = ",hd"
664 5397e0b7 Alexander Schreiber
    disk_data = [line.replace(",sd", replacement) for line in disk_data]
665 a985b417 Iustin Pop
    iso_path = hvp[constants.HV_CDROM_IMAGE_PATH]
666 f48148c3 Iustin Pop
    if iso_path:
667 f48148c3 Iustin Pop
      iso = "'file:%s,hdc:cdrom,r'" % iso_path
668 a21dda8b Iustin Pop
      disk_data.append(iso)
669 a21dda8b Iustin Pop
670 a21dda8b Iustin Pop
    config.write("disk = [%s]\n" % (",".join(disk_data)))
671 a21dda8b Iustin Pop
672 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
673 65a6f9b7 Michael Hanselmann
    config.write("on_reboot = 'restart'\n")
674 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
675 65a6f9b7 Michael Hanselmann
    # just in case it exists
676 65a6f9b7 Michael Hanselmann
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
677 65a6f9b7 Michael Hanselmann
    try:
678 73cd67f4 Guido Trotter
      utils.WriteFile("/etc/xen/%s" % instance.name,
679 73cd67f4 Guido Trotter
                      data=config.getvalue())
680 73cd67f4 Guido Trotter
    except EnvironmentError, err:
681 73cd67f4 Guido Trotter
      raise errors.HypervisorError("Cannot write Xen instance confile"
682 73cd67f4 Guido Trotter
                                   " file /etc/xen/%s: %s" %
683 73cd67f4 Guido Trotter
                                   (instance.name, err))
684 73cd67f4 Guido Trotter
685 65a6f9b7 Michael Hanselmann
    return True