Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ e2d14329

History | View | Annotate | Download (22.9 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 d0c8c01d Iustin Pop
    "/etc/xen/xend-config.sxp",
50 d0c8c01d Iustin Pop
    "/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 d0c8c01d Iustin Pop
      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 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
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 323f9095 Stephen Shirley
    cmd = ["xm", "create"]
189 323f9095 Stephen Shirley
    if startup_paused:
190 323f9095 Stephen Shirley
      cmd.extend(["--paused"])
191 323f9095 Stephen Shirley
    cmd.extend([instance.name])
192 323f9095 Stephen Shirley
    result = utils.RunCmd(cmd)
193 65a6f9b7 Michael Hanselmann
194 65a6f9b7 Michael Hanselmann
    if result.failed:
195 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
196 65a6f9b7 Michael Hanselmann
                                   (instance.name, result.fail_reason,
197 65a6f9b7 Michael Hanselmann
                                    result.output))
198 65a6f9b7 Michael Hanselmann
199 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
200 c41eea6e Iustin Pop
    """Stop an instance.
201 c41eea6e Iustin Pop

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

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

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

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

305 65a6f9b7 Michael Hanselmann
    """
306 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
307 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_SSH,
308 55cc0a44 Michael Hanselmann
                                   host=instance.primary_node,
309 55cc0a44 Michael Hanselmann
                                   user=constants.GANETI_RUNAS,
310 61631293 Stephen Shirley
                                   command=[constants.XM_CONSOLE_WRAPPER,
311 61631293 Stephen Shirley
                                            instance.name])
312 65a6f9b7 Michael Hanselmann
313 65a6f9b7 Michael Hanselmann
  def Verify(self):
314 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
315 65a6f9b7 Michael Hanselmann

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

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

327 65a6f9b7 Michael Hanselmann
    This method builds the xen config disk directive according to the
328 65a6f9b7 Michael Hanselmann
    given disk_template and block_devices.
329 65a6f9b7 Michael Hanselmann

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

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

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

365 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
366 4390ccff Guido Trotter
    @param instance: instance to be migrated
367 4390ccff Guido Trotter
    @rtype: string
368 4390ccff Guido Trotter
    @return: content of the xen config file
369 4390ccff Guido Trotter

370 4390ccff Guido Trotter
    """
371 4390ccff Guido Trotter
    return self._ReadConfigFile(instance.name)
372 4390ccff Guido Trotter
373 4390ccff Guido Trotter
  def AcceptInstance(self, instance, info, target):
374 4390ccff Guido Trotter
    """Prepare to accept an instance.
375 4390ccff Guido Trotter

376 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
377 4390ccff Guido Trotter
    @param instance: instance to be accepted
378 4390ccff Guido Trotter
    @type info: string
379 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
380 4390ccff Guido Trotter
    @type target: string
381 4390ccff Guido Trotter
    @param target: target host (usually ip), on this node
382 4390ccff Guido Trotter

383 4390ccff Guido Trotter
    """
384 4390ccff Guido Trotter
    pass
385 4390ccff Guido Trotter
386 4390ccff Guido Trotter
  def FinalizeMigration(self, instance, info, success):
387 4390ccff Guido Trotter
    """Finalize an instance migration.
388 4390ccff Guido Trotter

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

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

399 4390ccff Guido Trotter
    """
400 4390ccff Guido Trotter
    if success:
401 4390ccff Guido Trotter
      self._WriteConfigFileStatic(instance.name, info)
402 4390ccff Guido Trotter
403 6e7275c0 Iustin Pop
  def MigrateInstance(self, instance, target, live):
404 6e7275c0 Iustin Pop
    """Migrate an instance to a target node.
405 6e7275c0 Iustin Pop

406 6e7275c0 Iustin Pop
    The migration will not be attempted if the instance is not
407 6e7275c0 Iustin Pop
    currently running.
408 6e7275c0 Iustin Pop

409 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
410 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
411 fdf7f055 Guido Trotter
    @type target: string
412 fdf7f055 Guido Trotter
    @param target: ip address of the target node
413 fdf7f055 Guido Trotter
    @type live: boolean
414 fdf7f055 Guido Trotter
    @param live: perform a live migration
415 fdf7f055 Guido Trotter

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

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

451 f5118ade Iustin Pop
    """
452 f5118ade Iustin Pop
    try:
453 f5118ade Iustin Pop
      cls.LinuxPowercycle()
454 f5118ade Iustin Pop
    finally:
455 f5118ade Iustin Pop
      utils.RunCmd(["xm", "debug", "R"])
456 f5118ade Iustin Pop
457 65a6f9b7 Michael Hanselmann
458 65a6f9b7 Michael Hanselmann
class XenPvmHypervisor(XenHypervisor):
459 65a6f9b7 Michael Hanselmann
  """Xen PVM hypervisor interface"""
460 65a6f9b7 Michael Hanselmann
461 205ab586 Iustin Pop
  PARAMETERS = {
462 2f2dbb4b Jun Futagawa
    constants.HV_USE_BOOTLOADER: hv_base.NO_CHECK,
463 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_PATH: hv_base.OPT_FILE_CHECK,
464 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_ARGS: hv_base.NO_CHECK,
465 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.REQ_FILE_CHECK,
466 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
467 7adf7814 René Nussbaumer
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
468 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
469 e2d14329 Andrea Spadaccini
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
470 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
471 525011bc Maciej Bliziński
    # TODO: Add a check for the blockdev prefix (matching [a-z:] or similar).
472 525011bc Maciej Bliziński
    constants.HV_BLOCKDEV_PREFIX: hv_base.NO_CHECK,
473 990ade2d Stephen Shirley
    constants.HV_REBOOT_BEHAVIOR:
474 990ade2d Stephen Shirley
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS)
475 205ab586 Iustin Pop
    }
476 f48148c3 Iustin Pop
477 65a6f9b7 Michael Hanselmann
  @classmethod
478 07813a9e Iustin Pop
  def _WriteConfigFile(cls, instance, block_devices):
479 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
480 65a6f9b7 Michael Hanselmann

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

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