Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ 43fcf0d3

History | View | Annotate | Download (22.3 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 55cc0a44 Michael Hanselmann
from ganeti import objects
35 65a6f9b7 Michael Hanselmann
36 65a6f9b7 Michael Hanselmann
37 a2d32034 Michael Hanselmann
class XenHypervisor(hv_base.BaseHypervisor):
38 65a6f9b7 Michael Hanselmann
  """Xen generic hypervisor interface
39 65a6f9b7 Michael Hanselmann

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

43 65a6f9b7 Michael Hanselmann
  """
44 d271c6fd Iustin Pop
  CAN_MIGRATE = True
45 7dd106d3 Iustin Pop
  REBOOT_RETRY_COUNT = 60
46 7dd106d3 Iustin Pop
  REBOOT_RETRY_INTERVAL = 10
47 65a6f9b7 Michael Hanselmann
48 3680f662 Guido Trotter
  ANCILLARY_FILES = [
49 3680f662 Guido Trotter
    '/etc/xen/xend-config.sxp',
50 3680f662 Guido Trotter
    '/etc/xen/scripts/vif-bridge',
51 3680f662 Guido Trotter
    ]
52 3680f662 Guido Trotter
53 5661b908 Iustin Pop
  @classmethod
54 07813a9e Iustin Pop
  def _WriteConfigFile(cls, instance, block_devices):
55 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
56 65a6f9b7 Michael Hanselmann

57 65a6f9b7 Michael Hanselmann
    """
58 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
59 65a6f9b7 Michael Hanselmann
60 65a6f9b7 Michael Hanselmann
  @staticmethod
61 4390ccff Guido Trotter
  def _WriteConfigFileStatic(instance_name, data):
62 4390ccff Guido Trotter
    """Write the Xen config file for the instance.
63 4390ccff Guido Trotter

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

66 4390ccff Guido Trotter
    """
67 4390ccff Guido Trotter
    utils.WriteFile("/etc/xen/%s" % instance_name, data=data)
68 4390ccff Guido Trotter
69 4390ccff Guido Trotter
  @staticmethod
70 4390ccff Guido Trotter
  def _ReadConfigFile(instance_name):
71 4390ccff Guido Trotter
    """Returns the contents of the instance config file.
72 4390ccff Guido Trotter

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

84 65a6f9b7 Michael Hanselmann
    """
85 53c776b5 Iustin Pop
    utils.RemoveFile("/etc/xen/%s" % instance_name)
86 65a6f9b7 Michael Hanselmann
87 65a6f9b7 Michael Hanselmann
  @staticmethod
88 06b78e8b Michael Hanselmann
  def _RunXmList(xmlist_errors):
89 06b78e8b Michael Hanselmann
    """Helper function for L{_GetXMList} to run "xm list".
90 06b78e8b Michael Hanselmann

91 06b78e8b Michael Hanselmann
    """
92 06b78e8b Michael Hanselmann
    result = utils.RunCmd(["xm", "list"])
93 06b78e8b Michael Hanselmann
    if result.failed:
94 06b78e8b Michael Hanselmann
      logging.error("xm list failed (%s): %s", result.fail_reason,
95 06b78e8b Michael Hanselmann
                    result.output)
96 06b78e8b Michael Hanselmann
      xmlist_errors.append(result)
97 06b78e8b Michael Hanselmann
      raise utils.RetryAgain()
98 06b78e8b Michael Hanselmann
99 06b78e8b Michael Hanselmann
    # skip over the heading
100 06b78e8b Michael Hanselmann
    return result.stdout.splitlines()[1:]
101 06b78e8b Michael Hanselmann
102 06b78e8b Michael Hanselmann
  @classmethod
103 06b78e8b Michael Hanselmann
  def _GetXMList(cls, include_node):
104 65a6f9b7 Michael Hanselmann
    """Return the list of running instances.
105 65a6f9b7 Michael Hanselmann

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

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

111 65a6f9b7 Michael Hanselmann
    """
112 06b78e8b Michael Hanselmann
    xmlist_errors = []
113 06b78e8b Michael Hanselmann
    try:
114 06b78e8b Michael Hanselmann
      lines = utils.Retry(cls._RunXmList, 1, 5, args=(xmlist_errors, ))
115 06b78e8b Michael Hanselmann
    except utils.RetryTimeout:
116 06b78e8b Michael Hanselmann
      if xmlist_errors:
117 06b78e8b Michael Hanselmann
        xmlist_result = xmlist_errors.pop()
118 65a6f9b7 Michael Hanselmann
119 06b78e8b Michael Hanselmann
        errmsg = ("xm list failed, timeout exceeded (%s): %s" %
120 06b78e8b Michael Hanselmann
                  (xmlist_result.fail_reason, xmlist_result.output))
121 06b78e8b Michael Hanselmann
      else:
122 06b78e8b Michael Hanselmann
        errmsg = "xm list failed"
123 06b78e8b Michael Hanselmann
124 06b78e8b Michael Hanselmann
      raise errors.HypervisorError(errmsg)
125 65a6f9b7 Michael Hanselmann
126 65a6f9b7 Michael Hanselmann
    result = []
127 65a6f9b7 Michael Hanselmann
    for line in lines:
128 65a6f9b7 Michael Hanselmann
      # The format of lines is:
129 65a6f9b7 Michael Hanselmann
      # Name      ID Mem(MiB) VCPUs State  Time(s)
130 65a6f9b7 Michael Hanselmann
      # Domain-0   0  3418     4 r-----    266.2
131 65a6f9b7 Michael Hanselmann
      data = line.split()
132 65a6f9b7 Michael Hanselmann
      if len(data) != 6:
133 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("Can't parse output of xm list,"
134 65a6f9b7 Michael Hanselmann
                                     " line: %s" % line)
135 65a6f9b7 Michael Hanselmann
      try:
136 65a6f9b7 Michael Hanselmann
        data[1] = int(data[1])
137 65a6f9b7 Michael Hanselmann
        data[2] = int(data[2])
138 65a6f9b7 Michael Hanselmann
        data[3] = int(data[3])
139 65a6f9b7 Michael Hanselmann
        data[5] = float(data[5])
140 691744c4 Iustin Pop
      except (TypeError, ValueError), err:
141 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("Can't parse output of xm list,"
142 65a6f9b7 Michael Hanselmann
                                     " line: %s, error: %s" % (line, err))
143 65a6f9b7 Michael Hanselmann
144 65a6f9b7 Michael Hanselmann
      # skip the Domain-0 (optional)
145 65a6f9b7 Michael Hanselmann
      if include_node or data[0] != 'Domain-0':
146 65a6f9b7 Michael Hanselmann
        result.append(data)
147 65a6f9b7 Michael Hanselmann
148 65a6f9b7 Michael Hanselmann
    return result
149 65a6f9b7 Michael Hanselmann
150 65a6f9b7 Michael Hanselmann
  def ListInstances(self):
151 65a6f9b7 Michael Hanselmann
    """Get the list of running instances.
152 65a6f9b7 Michael Hanselmann

153 65a6f9b7 Michael Hanselmann
    """
154 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(False)
155 65a6f9b7 Michael Hanselmann
    names = [info[0] for info in xm_list]
156 65a6f9b7 Michael Hanselmann
    return names
157 65a6f9b7 Michael Hanselmann
158 65a6f9b7 Michael Hanselmann
  def GetInstanceInfo(self, instance_name):
159 65a6f9b7 Michael Hanselmann
    """Get instance properties.
160 65a6f9b7 Michael Hanselmann

161 c41eea6e Iustin Pop
    @param instance_name: the instance name
162 c41eea6e Iustin Pop

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

165 65a6f9b7 Michael Hanselmann
    """
166 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(instance_name=="Domain-0")
167 65a6f9b7 Michael Hanselmann
    result = None
168 65a6f9b7 Michael Hanselmann
    for data in xm_list:
169 65a6f9b7 Michael Hanselmann
      if data[0] == instance_name:
170 65a6f9b7 Michael Hanselmann
        result = data
171 65a6f9b7 Michael Hanselmann
        break
172 65a6f9b7 Michael Hanselmann
    return result
173 65a6f9b7 Michael Hanselmann
174 65a6f9b7 Michael Hanselmann
  def GetAllInstancesInfo(self):
175 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
176 65a6f9b7 Michael Hanselmann

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

179 65a6f9b7 Michael Hanselmann
    """
180 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(False)
181 65a6f9b7 Michael Hanselmann
    return xm_list
182 65a6f9b7 Michael Hanselmann
183 07813a9e Iustin Pop
  def StartInstance(self, instance, block_devices):
184 c41eea6e Iustin Pop
    """Start an instance.
185 c41eea6e Iustin Pop

186 c41eea6e Iustin Pop
    """
187 07813a9e Iustin Pop
    self._WriteConfigFile(instance, block_devices)
188 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(["xm", "create", instance.name])
189 65a6f9b7 Michael Hanselmann
190 65a6f9b7 Michael Hanselmann
    if result.failed:
191 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
192 65a6f9b7 Michael Hanselmann
                                   (instance.name, result.fail_reason,
193 65a6f9b7 Michael Hanselmann
                                    result.output))
194 65a6f9b7 Michael Hanselmann
195 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
196 c41eea6e Iustin Pop
    """Stop an instance.
197 c41eea6e Iustin Pop

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

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

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

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

301 65a6f9b7 Michael Hanselmann
    """
302 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
303 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_SSH,
304 55cc0a44 Michael Hanselmann
                                   host=instance.primary_node,
305 55cc0a44 Michael Hanselmann
                                   user=constants.GANETI_RUNAS,
306 55cc0a44 Michael Hanselmann
                                   command=["xm", "console", instance.name])
307 65a6f9b7 Michael Hanselmann
308 65a6f9b7 Michael Hanselmann
  def Verify(self):
309 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
310 65a6f9b7 Michael Hanselmann

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

313 65a6f9b7 Michael Hanselmann
    """
314 e3e66f02 Michael Hanselmann
    result = utils.RunCmd(["xm", "info"])
315 e3e66f02 Michael Hanselmann
    if result.failed:
316 3213d3c8 Iustin Pop
      return "'xm info' failed: %s, %s" % (result.fail_reason, result.output)
317 65a6f9b7 Michael Hanselmann
318 65a6f9b7 Michael Hanselmann
  @staticmethod
319 525011bc Maciej Bliziński
  def _GetConfigFileDiskData(block_devices, blockdev_prefix):
320 65a6f9b7 Michael Hanselmann
    """Get disk directive for xen config file.
321 65a6f9b7 Michael Hanselmann

322 65a6f9b7 Michael Hanselmann
    This method builds the xen config disk directive according to the
323 65a6f9b7 Michael Hanselmann
    given disk_template and block_devices.
324 65a6f9b7 Michael Hanselmann

325 c41eea6e Iustin Pop
    @param block_devices: list of tuples (cfdev, rldev):
326 c41eea6e Iustin Pop
        - cfdev: dict containing ganeti config disk part
327 c41eea6e Iustin Pop
        - rldev: ganeti.bdev.BlockDev object
328 525011bc Maciej Bliziński
    @param blockdev_prefix: a string containing blockdevice prefix,
329 525011bc Maciej Bliziński
                            e.g. "sd" for /dev/sda
330 65a6f9b7 Michael Hanselmann

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

333 65a6f9b7 Michael Hanselmann
    """
334 65a6f9b7 Michael Hanselmann
    FILE_DRIVER_MAP = {
335 65a6f9b7 Michael Hanselmann
      constants.FD_LOOP: "file",
336 65a6f9b7 Michael Hanselmann
      constants.FD_BLKTAP: "tap:aio",
337 65a6f9b7 Michael Hanselmann
      }
338 65a6f9b7 Michael Hanselmann
    disk_data = []
339 2864f2d9 Iustin Pop
    if len(block_devices) > 24:
340 2864f2d9 Iustin Pop
      # 'z' - 'a' = 24
341 2864f2d9 Iustin Pop
      raise errors.HypervisorError("Too many disks")
342 525011bc Maciej Bliziński
    namespace = [blockdev_prefix + chr(i + ord('a')) for i in range(24)]
343 069cfbf1 Iustin Pop
    for sd_name, (cfdev, dev_path) in zip(namespace, block_devices):
344 d34b16d7 Iustin Pop
      if cfdev.mode == constants.DISK_RDWR:
345 d34b16d7 Iustin Pop
        mode = "w"
346 d34b16d7 Iustin Pop
      else:
347 d34b16d7 Iustin Pop
        mode = "r"
348 65a6f9b7 Michael Hanselmann
      if cfdev.dev_type == constants.LD_FILE:
349 d34b16d7 Iustin Pop
        line = "'%s:%s,%s,%s'" % (FILE_DRIVER_MAP[cfdev.physical_id[0]],
350 d34b16d7 Iustin Pop
                                  dev_path, sd_name, mode)
351 65a6f9b7 Michael Hanselmann
      else:
352 d34b16d7 Iustin Pop
        line = "'phy:%s,%s,%s'" % (dev_path, sd_name, mode)
353 65a6f9b7 Michael Hanselmann
      disk_data.append(line)
354 65a6f9b7 Michael Hanselmann
355 65a6f9b7 Michael Hanselmann
    return disk_data
356 65a6f9b7 Michael Hanselmann
357 4390ccff Guido Trotter
  def MigrationInfo(self, instance):
358 4390ccff Guido Trotter
    """Get instance information to perform a migration.
359 4390ccff Guido Trotter

360 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
361 4390ccff Guido Trotter
    @param instance: instance to be migrated
362 4390ccff Guido Trotter
    @rtype: string
363 4390ccff Guido Trotter
    @return: content of the xen config file
364 4390ccff Guido Trotter

365 4390ccff Guido Trotter
    """
366 4390ccff Guido Trotter
    return self._ReadConfigFile(instance.name)
367 4390ccff Guido Trotter
368 4390ccff Guido Trotter
  def AcceptInstance(self, instance, info, target):
369 4390ccff Guido Trotter
    """Prepare to accept an instance.
370 4390ccff Guido Trotter

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

378 4390ccff Guido Trotter
    """
379 4390ccff Guido Trotter
    pass
380 4390ccff Guido Trotter
381 4390ccff Guido Trotter
  def FinalizeMigration(self, instance, info, success):
382 4390ccff Guido Trotter
    """Finalize an instance migration.
383 4390ccff Guido Trotter

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

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

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

401 6e7275c0 Iustin Pop
    The migration will not be attempted if the instance is not
402 6e7275c0 Iustin Pop
    currently running.
403 6e7275c0 Iustin Pop

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

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

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

446 f5118ade Iustin Pop
    """
447 f5118ade Iustin Pop
    try:
448 f5118ade Iustin Pop
      cls.LinuxPowercycle()
449 f5118ade Iustin Pop
    finally:
450 f5118ade Iustin Pop
      utils.RunCmd(["xm", "debug", "R"])
451 f5118ade Iustin Pop
452 65a6f9b7 Michael Hanselmann
453 65a6f9b7 Michael Hanselmann
class XenPvmHypervisor(XenHypervisor):
454 65a6f9b7 Michael Hanselmann
  """Xen PVM hypervisor interface"""
455 65a6f9b7 Michael Hanselmann
456 205ab586 Iustin Pop
  PARAMETERS = {
457 2f2dbb4b Jun Futagawa
    constants.HV_USE_BOOTLOADER: hv_base.NO_CHECK,
458 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_PATH: hv_base.OPT_FILE_CHECK,
459 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_ARGS: hv_base.NO_CHECK,
460 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.REQ_FILE_CHECK,
461 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
462 205ab586 Iustin Pop
    constants.HV_ROOT_PATH: hv_base.REQUIRED_CHECK,
463 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
464 78411c60 Iustin Pop
    constants.HV_MIGRATION_PORT: hv_base.NET_PORT_CHECK,
465 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
466 525011bc Maciej Bliziński
    # TODO: Add a check for the blockdev prefix (matching [a-z:] or similar).
467 525011bc Maciej Bliziński
    constants.HV_BLOCKDEV_PREFIX: hv_base.NO_CHECK,
468 205ab586 Iustin Pop
    }
469 f48148c3 Iustin Pop
470 65a6f9b7 Michael Hanselmann
  @classmethod
471 07813a9e Iustin Pop
  def _WriteConfigFile(cls, instance, block_devices):
472 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
473 65a6f9b7 Michael Hanselmann

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

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