Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ 69ab2e12

History | View | Annotate | Download (24.4 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 22d568c2 Guido Trotter
XEND_CONFIG_FILE = "/etc/xen/xend-config.sxp"
38 22d568c2 Guido Trotter
XL_CONFIG_FILE = "/etc/xen/xl.conf"
39 22d568c2 Guido Trotter
VIF_BRIDGE_SCRIPT = "/etc/xen/scripts/vif-bridge"
40 22d568c2 Guido Trotter
41 22d568c2 Guido Trotter
42 a2d32034 Michael Hanselmann
class XenHypervisor(hv_base.BaseHypervisor):
43 65a6f9b7 Michael Hanselmann
  """Xen generic hypervisor interface
44 65a6f9b7 Michael Hanselmann

45 65a6f9b7 Michael Hanselmann
  This is the Xen base class used for both Xen PVM and HVM. It contains
46 65a6f9b7 Michael Hanselmann
  all the functionality that is identical for both.
47 65a6f9b7 Michael Hanselmann

48 65a6f9b7 Michael Hanselmann
  """
49 d271c6fd Iustin Pop
  CAN_MIGRATE = True
50 7dd106d3 Iustin Pop
  REBOOT_RETRY_COUNT = 60
51 7dd106d3 Iustin Pop
  REBOOT_RETRY_INTERVAL = 10
52 65a6f9b7 Michael Hanselmann
53 3680f662 Guido Trotter
  ANCILLARY_FILES = [
54 22d568c2 Guido Trotter
    XEND_CONFIG_FILE,
55 22d568c2 Guido Trotter
    XL_CONFIG_FILE,
56 22d568c2 Guido Trotter
    VIF_BRIDGE_SCRIPT,
57 3680f662 Guido Trotter
    ]
58 69ab2e12 Guido Trotter
  ANCILLARY_FILES_OPT = [
59 69ab2e12 Guido Trotter
    XL_CONFIG_FILE,
60 69ab2e12 Guido Trotter
    ]
61 3680f662 Guido Trotter
62 c2be2532 Guido Trotter
  @staticmethod
63 c2be2532 Guido Trotter
  def _ConfigFileName(instance_name):
64 c2be2532 Guido Trotter
    """Get the config file name for an instance.
65 c2be2532 Guido Trotter

66 c2be2532 Guido Trotter
    @param instance_name: instance name
67 c2be2532 Guido Trotter
    @type instance_name: str
68 c2be2532 Guido Trotter
    @return: fully qualified path to instance config file
69 c2be2532 Guido Trotter
    @rtype: str
70 c2be2532 Guido Trotter

71 c2be2532 Guido Trotter
    """
72 c2be2532 Guido Trotter
    return "/etc/xen/%s" % instance_name
73 c2be2532 Guido Trotter
74 5661b908 Iustin Pop
  @classmethod
75 07813a9e Iustin Pop
  def _WriteConfigFile(cls, instance, block_devices):
76 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
77 65a6f9b7 Michael Hanselmann

78 65a6f9b7 Michael Hanselmann
    """
79 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
80 65a6f9b7 Michael Hanselmann
81 65a6f9b7 Michael Hanselmann
  @staticmethod
82 4390ccff Guido Trotter
  def _WriteConfigFileStatic(instance_name, data):
83 4390ccff Guido Trotter
    """Write the Xen config file for the instance.
84 4390ccff Guido Trotter

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

87 4390ccff Guido Trotter
    """
88 c2be2532 Guido Trotter
    utils.WriteFile(XenHypervisor._ConfigFileName(instance_name), data=data)
89 4390ccff Guido Trotter
90 4390ccff Guido Trotter
  @staticmethod
91 4390ccff Guido Trotter
  def _ReadConfigFile(instance_name):
92 4390ccff Guido Trotter
    """Returns the contents of the instance config file.
93 4390ccff Guido Trotter

94 4390ccff Guido Trotter
    """
95 4390ccff Guido Trotter
    try:
96 c2be2532 Guido Trotter
      file_content = utils.ReadFile(
97 c2be2532 Guido Trotter
                       XenHypervisor._ConfigFileName(instance_name))
98 4390ccff Guido Trotter
    except EnvironmentError, err:
99 4390ccff Guido Trotter
      raise errors.HypervisorError("Failed to load Xen config file: %s" % err)
100 4390ccff Guido Trotter
    return file_content
101 4390ccff Guido Trotter
102 4390ccff Guido Trotter
  @staticmethod
103 53c776b5 Iustin Pop
  def _RemoveConfigFile(instance_name):
104 65a6f9b7 Michael Hanselmann
    """Remove the xen configuration file.
105 65a6f9b7 Michael Hanselmann

106 65a6f9b7 Michael Hanselmann
    """
107 c2be2532 Guido Trotter
    utils.RemoveFile(XenHypervisor._ConfigFileName(instance_name))
108 65a6f9b7 Michael Hanselmann
109 65a6f9b7 Michael Hanselmann
  @staticmethod
110 06b78e8b Michael Hanselmann
  def _RunXmList(xmlist_errors):
111 06b78e8b Michael Hanselmann
    """Helper function for L{_GetXMList} to run "xm list".
112 06b78e8b Michael Hanselmann

113 06b78e8b Michael Hanselmann
    """
114 2876c2d6 Guido Trotter
    result = utils.RunCmd([constants.XEN_CMD, "list"])
115 06b78e8b Michael Hanselmann
    if result.failed:
116 06b78e8b Michael Hanselmann
      logging.error("xm list failed (%s): %s", result.fail_reason,
117 06b78e8b Michael Hanselmann
                    result.output)
118 06b78e8b Michael Hanselmann
      xmlist_errors.append(result)
119 06b78e8b Michael Hanselmann
      raise utils.RetryAgain()
120 06b78e8b Michael Hanselmann
121 06b78e8b Michael Hanselmann
    # skip over the heading
122 06b78e8b Michael Hanselmann
    return result.stdout.splitlines()[1:]
123 06b78e8b Michael Hanselmann
124 06b78e8b Michael Hanselmann
  @classmethod
125 06b78e8b Michael Hanselmann
  def _GetXMList(cls, include_node):
126 65a6f9b7 Michael Hanselmann
    """Return the list of running instances.
127 65a6f9b7 Michael Hanselmann

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

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

133 65a6f9b7 Michael Hanselmann
    """
134 06b78e8b Michael Hanselmann
    xmlist_errors = []
135 06b78e8b Michael Hanselmann
    try:
136 06b78e8b Michael Hanselmann
      lines = utils.Retry(cls._RunXmList, 1, 5, args=(xmlist_errors, ))
137 06b78e8b Michael Hanselmann
    except utils.RetryTimeout:
138 06b78e8b Michael Hanselmann
      if xmlist_errors:
139 06b78e8b Michael Hanselmann
        xmlist_result = xmlist_errors.pop()
140 65a6f9b7 Michael Hanselmann
141 06b78e8b Michael Hanselmann
        errmsg = ("xm list failed, timeout exceeded (%s): %s" %
142 06b78e8b Michael Hanselmann
                  (xmlist_result.fail_reason, xmlist_result.output))
143 06b78e8b Michael Hanselmann
      else:
144 06b78e8b Michael Hanselmann
        errmsg = "xm list failed"
145 06b78e8b Michael Hanselmann
146 06b78e8b Michael Hanselmann
      raise errors.HypervisorError(errmsg)
147 65a6f9b7 Michael Hanselmann
148 65a6f9b7 Michael Hanselmann
    result = []
149 65a6f9b7 Michael Hanselmann
    for line in lines:
150 65a6f9b7 Michael Hanselmann
      # The format of lines is:
151 65a6f9b7 Michael Hanselmann
      # Name      ID Mem(MiB) VCPUs State  Time(s)
152 65a6f9b7 Michael Hanselmann
      # Domain-0   0  3418     4 r-----    266.2
153 65a6f9b7 Michael Hanselmann
      data = line.split()
154 65a6f9b7 Michael Hanselmann
      if len(data) != 6:
155 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("Can't parse output of xm list,"
156 65a6f9b7 Michael Hanselmann
                                     " line: %s" % line)
157 65a6f9b7 Michael Hanselmann
      try:
158 65a6f9b7 Michael Hanselmann
        data[1] = int(data[1])
159 65a6f9b7 Michael Hanselmann
        data[2] = int(data[2])
160 65a6f9b7 Michael Hanselmann
        data[3] = int(data[3])
161 65a6f9b7 Michael Hanselmann
        data[5] = float(data[5])
162 691744c4 Iustin Pop
      except (TypeError, ValueError), err:
163 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("Can't parse output of xm list,"
164 65a6f9b7 Michael Hanselmann
                                     " line: %s, error: %s" % (line, err))
165 65a6f9b7 Michael Hanselmann
166 65a6f9b7 Michael Hanselmann
      # skip the Domain-0 (optional)
167 d0c8c01d Iustin Pop
      if include_node or data[0] != "Domain-0":
168 65a6f9b7 Michael Hanselmann
        result.append(data)
169 65a6f9b7 Michael Hanselmann
170 65a6f9b7 Michael Hanselmann
    return result
171 65a6f9b7 Michael Hanselmann
172 65a6f9b7 Michael Hanselmann
  def ListInstances(self):
173 65a6f9b7 Michael Hanselmann
    """Get the list of running instances.
174 65a6f9b7 Michael Hanselmann

175 65a6f9b7 Michael Hanselmann
    """
176 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(False)
177 65a6f9b7 Michael Hanselmann
    names = [info[0] for info in xm_list]
178 65a6f9b7 Michael Hanselmann
    return names
179 65a6f9b7 Michael Hanselmann
180 65a6f9b7 Michael Hanselmann
  def GetInstanceInfo(self, instance_name):
181 65a6f9b7 Michael Hanselmann
    """Get instance properties.
182 65a6f9b7 Michael Hanselmann

183 c41eea6e Iustin Pop
    @param instance_name: the instance name
184 c41eea6e Iustin Pop

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

187 65a6f9b7 Michael Hanselmann
    """
188 e687ec01 Michael Hanselmann
    xm_list = self._GetXMList(instance_name == "Domain-0")
189 65a6f9b7 Michael Hanselmann
    result = None
190 65a6f9b7 Michael Hanselmann
    for data in xm_list:
191 65a6f9b7 Michael Hanselmann
      if data[0] == instance_name:
192 65a6f9b7 Michael Hanselmann
        result = data
193 65a6f9b7 Michael Hanselmann
        break
194 65a6f9b7 Michael Hanselmann
    return result
195 65a6f9b7 Michael Hanselmann
196 65a6f9b7 Michael Hanselmann
  def GetAllInstancesInfo(self):
197 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
198 65a6f9b7 Michael Hanselmann

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

201 65a6f9b7 Michael Hanselmann
    """
202 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(False)
203 65a6f9b7 Michael Hanselmann
    return xm_list
204 65a6f9b7 Michael Hanselmann
205 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
206 c41eea6e Iustin Pop
    """Start an instance.
207 c41eea6e Iustin Pop

208 c41eea6e Iustin Pop
    """
209 07813a9e Iustin Pop
    self._WriteConfigFile(instance, block_devices)
210 2876c2d6 Guido Trotter
    cmd = [constants.XEN_CMD, "create"]
211 323f9095 Stephen Shirley
    if startup_paused:
212 6555373d Guido Trotter
      cmd.extend(["-p"])
213 6555373d Guido Trotter
    cmd.extend([self._ConfigFileName(instance.name)])
214 323f9095 Stephen Shirley
    result = utils.RunCmd(cmd)
215 65a6f9b7 Michael Hanselmann
216 65a6f9b7 Michael Hanselmann
    if result.failed:
217 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
218 65a6f9b7 Michael Hanselmann
                                   (instance.name, result.fail_reason,
219 65a6f9b7 Michael Hanselmann
                                    result.output))
220 65a6f9b7 Michael Hanselmann
221 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
222 c41eea6e Iustin Pop
    """Stop an instance.
223 c41eea6e Iustin Pop

224 c41eea6e Iustin Pop
    """
225 bbcf7ad0 Iustin Pop
    if name is None:
226 bbcf7ad0 Iustin Pop
      name = instance.name
227 bbcf7ad0 Iustin Pop
    self._RemoveConfigFile(name)
228 65a6f9b7 Michael Hanselmann
    if force:
229 2876c2d6 Guido Trotter
      command = [constants.XEN_CMD, "destroy", name]
230 65a6f9b7 Michael Hanselmann
    else:
231 2876c2d6 Guido Trotter
      command = [constants.XEN_CMD, "shutdown", name]
232 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(command)
233 65a6f9b7 Michael Hanselmann
234 65a6f9b7 Michael Hanselmann
    if result.failed:
235 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to stop instance %s: %s, %s" %
236 bbcf7ad0 Iustin Pop
                                   (name, result.fail_reason, result.output))
237 65a6f9b7 Michael Hanselmann
238 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
239 c41eea6e Iustin Pop
    """Reboot an instance.
240 c41eea6e Iustin Pop

241 c41eea6e Iustin Pop
    """
242 7dd106d3 Iustin Pop
    ini_info = self.GetInstanceInfo(instance.name)
243 65a6f9b7 Michael Hanselmann
244 e0561198 Iustin Pop
    if ini_info is None:
245 e0561198 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s,"
246 e0561198 Iustin Pop
                                   " not running" % instance.name)
247 e0561198 Iustin Pop
248 2876c2d6 Guido Trotter
    result = utils.RunCmd([constants.XEN_CMD, "reboot", instance.name])
249 65a6f9b7 Michael Hanselmann
    if result.failed:
250 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s: %s, %s" %
251 3213d3c8 Iustin Pop
                                   (instance.name, result.fail_reason,
252 3213d3c8 Iustin Pop
                                    result.output))
253 06b78e8b Michael Hanselmann
254 06b78e8b Michael Hanselmann
    def _CheckInstance():
255 7dd106d3 Iustin Pop
      new_info = self.GetInstanceInfo(instance.name)
256 06b78e8b Michael Hanselmann
257 06b78e8b Michael Hanselmann
      # check if the domain ID has changed or the run time has decreased
258 e0561198 Iustin Pop
      if (new_info is not None and
259 e0561198 Iustin Pop
          (new_info[1] != ini_info[1] or new_info[5] < ini_info[5])):
260 06b78e8b Michael Hanselmann
        return
261 7dd106d3 Iustin Pop
262 06b78e8b Michael Hanselmann
      raise utils.RetryAgain()
263 06b78e8b Michael Hanselmann
264 06b78e8b Michael Hanselmann
    try:
265 06b78e8b Michael Hanselmann
      utils.Retry(_CheckInstance, self.REBOOT_RETRY_INTERVAL,
266 06b78e8b Michael Hanselmann
                  self.REBOOT_RETRY_INTERVAL * self.REBOOT_RETRY_COUNT)
267 06b78e8b Michael Hanselmann
    except utils.RetryTimeout:
268 7dd106d3 Iustin Pop
      raise errors.HypervisorError("Failed to reboot instance %s: instance"
269 7dd106d3 Iustin Pop
                                   " did not reboot in the expected interval" %
270 7dd106d3 Iustin Pop
                                   (instance.name, ))
271 65a6f9b7 Michael Hanselmann
272 65a6f9b7 Michael Hanselmann
  def GetNodeInfo(self):
273 65a6f9b7 Michael Hanselmann
    """Return information about the node.
274 65a6f9b7 Michael Hanselmann

275 0105bad3 Iustin Pop
    @return: a dict with the following keys (memory values in MiB):
276 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
277 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
278 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
279 0105bad3 Iustin Pop
          - nr_cpus: total number of CPUs
280 0105bad3 Iustin Pop
          - nr_nodes: in a NUMA system, the number of domains
281 0105bad3 Iustin Pop
          - nr_sockets: the number of physical CPU sockets in the node
282 34fbc862 Andrea Spadaccini
          - hv_version: the hypervisor version in the form (major, minor)
283 65a6f9b7 Michael Hanselmann

284 65a6f9b7 Michael Hanselmann
    """
285 65a6f9b7 Michael Hanselmann
    # note: in xen 3, memory has changed to total_memory
286 2876c2d6 Guido Trotter
    result = utils.RunCmd([constants.XEN_CMD, "info"])
287 65a6f9b7 Michael Hanselmann
    if result.failed:
288 b48909c8 Iustin Pop
      logging.error("Can't run 'xm info' (%s): %s", result.fail_reason,
289 b48909c8 Iustin Pop
                    result.output)
290 65a6f9b7 Michael Hanselmann
      return None
291 65a6f9b7 Michael Hanselmann
292 65a6f9b7 Michael Hanselmann
    xmoutput = result.stdout.splitlines()
293 65a6f9b7 Michael Hanselmann
    result = {}
294 0105bad3 Iustin Pop
    cores_per_socket = threads_per_core = nr_cpus = None
295 34fbc862 Andrea Spadaccini
    xen_major, xen_minor = None, None
296 65a6f9b7 Michael Hanselmann
    for line in xmoutput:
297 65a6f9b7 Michael Hanselmann
      splitfields = line.split(":", 1)
298 65a6f9b7 Michael Hanselmann
299 65a6f9b7 Michael Hanselmann
      if len(splitfields) > 1:
300 65a6f9b7 Michael Hanselmann
        key = splitfields[0].strip()
301 65a6f9b7 Michael Hanselmann
        val = splitfields[1].strip()
302 d0c8c01d Iustin Pop
        if key == "memory" or key == "total_memory":
303 d0c8c01d Iustin Pop
          result["memory_total"] = int(val)
304 d0c8c01d Iustin Pop
        elif key == "free_memory":
305 d0c8c01d Iustin Pop
          result["memory_free"] = int(val)
306 d0c8c01d Iustin Pop
        elif key == "nr_cpus":
307 d0c8c01d Iustin Pop
          nr_cpus = result["cpu_total"] = int(val)
308 d0c8c01d Iustin Pop
        elif key == "nr_nodes":
309 d0c8c01d Iustin Pop
          result["cpu_nodes"] = int(val)
310 d0c8c01d Iustin Pop
        elif key == "cores_per_socket":
311 0105bad3 Iustin Pop
          cores_per_socket = int(val)
312 d0c8c01d Iustin Pop
        elif key == "threads_per_core":
313 0105bad3 Iustin Pop
          threads_per_core = int(val)
314 34fbc862 Andrea Spadaccini
        elif key == "xen_major":
315 34fbc862 Andrea Spadaccini
          xen_major = int(val)
316 34fbc862 Andrea Spadaccini
        elif key == "xen_minor":
317 34fbc862 Andrea Spadaccini
          xen_minor = int(val)
318 0105bad3 Iustin Pop
319 0105bad3 Iustin Pop
    if (cores_per_socket is not None and
320 0105bad3 Iustin Pop
        threads_per_core is not None and nr_cpus is not None):
321 d0c8c01d Iustin Pop
      result["cpu_sockets"] = nr_cpus / (cores_per_socket * threads_per_core)
322 0105bad3 Iustin Pop
323 65a6f9b7 Michael Hanselmann
    dom0_info = self.GetInstanceInfo("Domain-0")
324 65a6f9b7 Michael Hanselmann
    if dom0_info is not None:
325 d0c8c01d Iustin Pop
      result["memory_dom0"] = dom0_info[2]
326 65a6f9b7 Michael Hanselmann
327 34fbc862 Andrea Spadaccini
    if not (xen_major is None or xen_minor is None):
328 34fbc862 Andrea Spadaccini
      result[constants.HV_NODEINFO_KEY_VERSION] = (xen_major, xen_minor)
329 34fbc862 Andrea Spadaccini
330 65a6f9b7 Michael Hanselmann
    return result
331 65a6f9b7 Michael Hanselmann
332 637ce7f9 Guido Trotter
  @classmethod
333 55cc0a44 Michael Hanselmann
  def GetInstanceConsole(cls, instance, hvparams, beparams):
334 65a6f9b7 Michael Hanselmann
    """Return a command for connecting to the console of an instance.
335 65a6f9b7 Michael Hanselmann

336 65a6f9b7 Michael Hanselmann
    """
337 55cc0a44 Michael Hanselmann
    return objects.InstanceConsole(instance=instance.name,
338 55cc0a44 Michael Hanselmann
                                   kind=constants.CONS_SSH,
339 55cc0a44 Michael Hanselmann
                                   host=instance.primary_node,
340 55cc0a44 Michael Hanselmann
                                   user=constants.GANETI_RUNAS,
341 61631293 Stephen Shirley
                                   command=[constants.XM_CONSOLE_WRAPPER,
342 61631293 Stephen Shirley
                                            instance.name])
343 65a6f9b7 Michael Hanselmann
344 65a6f9b7 Michael Hanselmann
  def Verify(self):
345 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
346 65a6f9b7 Michael Hanselmann

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

349 65a6f9b7 Michael Hanselmann
    """
350 2876c2d6 Guido Trotter
    result = utils.RunCmd([constants.XEN_CMD, "info"])
351 e3e66f02 Michael Hanselmann
    if result.failed:
352 3213d3c8 Iustin Pop
      return "'xm info' failed: %s, %s" % (result.fail_reason, result.output)
353 65a6f9b7 Michael Hanselmann
354 65a6f9b7 Michael Hanselmann
  @staticmethod
355 525011bc Maciej Bliziński
  def _GetConfigFileDiskData(block_devices, blockdev_prefix):
356 65a6f9b7 Michael Hanselmann
    """Get disk directive for xen config file.
357 65a6f9b7 Michael Hanselmann

358 65a6f9b7 Michael Hanselmann
    This method builds the xen config disk directive according to the
359 65a6f9b7 Michael Hanselmann
    given disk_template and block_devices.
360 65a6f9b7 Michael Hanselmann

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

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

369 65a6f9b7 Michael Hanselmann
    """
370 65a6f9b7 Michael Hanselmann
    FILE_DRIVER_MAP = {
371 65a6f9b7 Michael Hanselmann
      constants.FD_LOOP: "file",
372 65a6f9b7 Michael Hanselmann
      constants.FD_BLKTAP: "tap:aio",
373 65a6f9b7 Michael Hanselmann
      }
374 65a6f9b7 Michael Hanselmann
    disk_data = []
375 2864f2d9 Iustin Pop
    if len(block_devices) > 24:
376 2864f2d9 Iustin Pop
      # 'z' - 'a' = 24
377 2864f2d9 Iustin Pop
      raise errors.HypervisorError("Too many disks")
378 d0c8c01d Iustin Pop
    namespace = [blockdev_prefix + chr(i + ord("a")) for i in range(24)]
379 069cfbf1 Iustin Pop
    for sd_name, (cfdev, dev_path) in zip(namespace, block_devices):
380 d34b16d7 Iustin Pop
      if cfdev.mode == constants.DISK_RDWR:
381 d34b16d7 Iustin Pop
        mode = "w"
382 d34b16d7 Iustin Pop
      else:
383 d34b16d7 Iustin Pop
        mode = "r"
384 65a6f9b7 Michael Hanselmann
      if cfdev.dev_type == constants.LD_FILE:
385 d34b16d7 Iustin Pop
        line = "'%s:%s,%s,%s'" % (FILE_DRIVER_MAP[cfdev.physical_id[0]],
386 d34b16d7 Iustin Pop
                                  dev_path, sd_name, mode)
387 65a6f9b7 Michael Hanselmann
      else:
388 d34b16d7 Iustin Pop
        line = "'phy:%s,%s,%s'" % (dev_path, sd_name, mode)
389 65a6f9b7 Michael Hanselmann
      disk_data.append(line)
390 65a6f9b7 Michael Hanselmann
391 65a6f9b7 Michael Hanselmann
    return disk_data
392 65a6f9b7 Michael Hanselmann
393 4390ccff Guido Trotter
  def MigrationInfo(self, instance):
394 4390ccff Guido Trotter
    """Get instance information to perform a migration.
395 4390ccff Guido Trotter

396 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
397 4390ccff Guido Trotter
    @param instance: instance to be migrated
398 4390ccff Guido Trotter
    @rtype: string
399 4390ccff Guido Trotter
    @return: content of the xen config file
400 4390ccff Guido Trotter

401 4390ccff Guido Trotter
    """
402 4390ccff Guido Trotter
    return self._ReadConfigFile(instance.name)
403 4390ccff Guido Trotter
404 4390ccff Guido Trotter
  def AcceptInstance(self, instance, info, target):
405 4390ccff Guido Trotter
    """Prepare to accept an instance.
406 4390ccff Guido Trotter

407 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
408 4390ccff Guido Trotter
    @param instance: instance to be accepted
409 4390ccff Guido Trotter
    @type info: string
410 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
411 4390ccff Guido Trotter
    @type target: string
412 4390ccff Guido Trotter
    @param target: target host (usually ip), on this node
413 4390ccff Guido Trotter

414 4390ccff Guido Trotter
    """
415 4390ccff Guido Trotter
    pass
416 4390ccff Guido Trotter
417 4390ccff Guido Trotter
  def FinalizeMigration(self, instance, info, success):
418 4390ccff Guido Trotter
    """Finalize an instance migration.
419 4390ccff Guido Trotter

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

423 4390ccff Guido Trotter
    @type instance: L{objects.Instance}
424 fea922fa Guido Trotter
    @param instance: instance whose migration is being finalized
425 4390ccff Guido Trotter
    @type info: string
426 4390ccff Guido Trotter
    @param info: content of the xen config file on the source node
427 4390ccff Guido Trotter
    @type success: boolean
428 4390ccff Guido Trotter
    @param success: whether the migration was a success or a failure
429 4390ccff Guido Trotter

430 4390ccff Guido Trotter
    """
431 4390ccff Guido Trotter
    if success:
432 4390ccff Guido Trotter
      self._WriteConfigFileStatic(instance.name, info)
433 4390ccff Guido Trotter
434 6e7275c0 Iustin Pop
  def MigrateInstance(self, instance, target, live):
435 6e7275c0 Iustin Pop
    """Migrate an instance to a target node.
436 6e7275c0 Iustin Pop

437 6e7275c0 Iustin Pop
    The migration will not be attempted if the instance is not
438 6e7275c0 Iustin Pop
    currently running.
439 6e7275c0 Iustin Pop

440 58d38b02 Iustin Pop
    @type instance: L{objects.Instance}
441 58d38b02 Iustin Pop
    @param instance: the instance to be migrated
442 fdf7f055 Guido Trotter
    @type target: string
443 fdf7f055 Guido Trotter
    @param target: ip address of the target node
444 fdf7f055 Guido Trotter
    @type live: boolean
445 fdf7f055 Guido Trotter
    @param live: perform a live migration
446 fdf7f055 Guido Trotter

447 6e7275c0 Iustin Pop
    """
448 58d38b02 Iustin Pop
    if self.GetInstanceInfo(instance.name) is None:
449 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Instance not running, cannot migrate")
450 50716be0 Iustin Pop
451 641ae041 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
452 50716be0 Iustin Pop
453 a744b676 Manuel Franceschini
    if not netutils.TcpPing(target, port, live_port_needed=True):
454 50716be0 Iustin Pop
      raise errors.HypervisorError("Remote host %s not listening on port"
455 50716be0 Iustin Pop
                                   " %s, cannot migrate" % (target, port))
456 50716be0 Iustin Pop
457 6555373d Guido Trotter
    # FIXME: migrate must be upgraded for transitioning to "xl" (xen 4.1).
458 6555373d Guido Trotter
    #  -l doesn't exist anymore
459 6555373d Guido Trotter
    #  -p doesn't exist anymore
460 6555373d Guido Trotter
    #  -C config_file must be passed
461 6555373d Guido Trotter
    #  ssh must recognize the key of the target host for the migration
462 2876c2d6 Guido Trotter
    args = [constants.XEN_CMD, "migrate", "-p", "%d" % port]
463 6e7275c0 Iustin Pop
    if live:
464 6e7275c0 Iustin Pop
      args.append("-l")
465 58d38b02 Iustin Pop
    args.extend([instance.name, target])
466 6e7275c0 Iustin Pop
    result = utils.RunCmd(args)
467 6e7275c0 Iustin Pop
    if result.failed:
468 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Failed to migrate instance %s: %s" %
469 58d38b02 Iustin Pop
                                   (instance.name, result.output))
470 53c776b5 Iustin Pop
    # remove old xen file after migration succeeded
471 53c776b5 Iustin Pop
    try:
472 58d38b02 Iustin Pop
      self._RemoveConfigFile(instance.name)
473 c979d253 Iustin Pop
    except EnvironmentError:
474 c979d253 Iustin Pop
      logging.exception("Failure while removing instance config file")
475 6e7275c0 Iustin Pop
476 f5118ade Iustin Pop
  @classmethod
477 f5118ade Iustin Pop
  def PowercycleNode(cls):
478 f5118ade Iustin Pop
    """Xen-specific powercycle.
479 f5118ade Iustin Pop

480 f5118ade Iustin Pop
    This first does a Linux reboot (which triggers automatically a Xen
481 f5118ade Iustin Pop
    reboot), and if that fails it tries to do a Xen reboot. The reason
482 f5118ade Iustin Pop
    we don't try a Xen reboot first is that the xen reboot launches an
483 f5118ade Iustin Pop
    external command which connects to the Xen hypervisor, and that
484 f5118ade Iustin Pop
    won't work in case the root filesystem is broken and/or the xend
485 f5118ade Iustin Pop
    daemon is not working.
486 f5118ade Iustin Pop

487 f5118ade Iustin Pop
    """
488 f5118ade Iustin Pop
    try:
489 f5118ade Iustin Pop
      cls.LinuxPowercycle()
490 f5118ade Iustin Pop
    finally:
491 2876c2d6 Guido Trotter
      utils.RunCmd([constants.XEN_CMD, "debug", "R"])
492 f5118ade Iustin Pop
493 65a6f9b7 Michael Hanselmann
494 65a6f9b7 Michael Hanselmann
class XenPvmHypervisor(XenHypervisor):
495 65a6f9b7 Michael Hanselmann
  """Xen PVM hypervisor interface"""
496 65a6f9b7 Michael Hanselmann
497 205ab586 Iustin Pop
  PARAMETERS = {
498 2f2dbb4b Jun Futagawa
    constants.HV_USE_BOOTLOADER: hv_base.NO_CHECK,
499 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_PATH: hv_base.OPT_FILE_CHECK,
500 2f2dbb4b Jun Futagawa
    constants.HV_BOOTLOADER_ARGS: hv_base.NO_CHECK,
501 205ab586 Iustin Pop
    constants.HV_KERNEL_PATH: hv_base.REQ_FILE_CHECK,
502 205ab586 Iustin Pop
    constants.HV_INITRD_PATH: hv_base.OPT_FILE_CHECK,
503 7adf7814 René Nussbaumer
    constants.HV_ROOT_PATH: hv_base.NO_CHECK,
504 205ab586 Iustin Pop
    constants.HV_KERNEL_ARGS: hv_base.NO_CHECK,
505 e2d14329 Andrea Spadaccini
    constants.HV_MIGRATION_PORT: hv_base.REQ_NET_PORT_CHECK,
506 783a6c0b Iustin Pop
    constants.HV_MIGRATION_MODE: hv_base.MIGRATION_MODE_CHECK,
507 525011bc Maciej Bliziński
    # TODO: Add a check for the blockdev prefix (matching [a-z:] or similar).
508 525011bc Maciej Bliziński
    constants.HV_BLOCKDEV_PREFIX: hv_base.NO_CHECK,
509 990ade2d Stephen Shirley
    constants.HV_REBOOT_BEHAVIOR:
510 990ade2d Stephen Shirley
      hv_base.ParamInSet(True, constants.REBOOT_BEHAVIORS)
511 205ab586 Iustin Pop
    }
512 f48148c3 Iustin Pop
513 65a6f9b7 Michael Hanselmann
  @classmethod
514 07813a9e Iustin Pop
  def _WriteConfigFile(cls, instance, block_devices):
515 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
516 65a6f9b7 Michael Hanselmann

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

630 65a6f9b7 Michael Hanselmann
    """
631 a985b417 Iustin Pop
    hvp = instance.hvparams
632 a985b417 Iustin Pop
633 65a6f9b7 Michael Hanselmann
    config = StringIO()
634 65a6f9b7 Michael Hanselmann
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
635 e2ee1cea Iustin Pop
636 e2ee1cea Iustin Pop
    # kernel handling
637 e2ee1cea Iustin Pop
    kpath = hvp[constants.HV_KERNEL_PATH]
638 e2ee1cea Iustin Pop
    config.write("kernel = '%s'\n" % kpath)
639 e2ee1cea Iustin Pop
640 65a6f9b7 Michael Hanselmann
    config.write("builder = 'hvm'\n")
641 8b3fd458 Iustin Pop
    config.write("memory = %d\n" % instance.beparams[constants.BE_MEMORY])
642 8b3fd458 Iustin Pop
    config.write("vcpus = %d\n" % instance.beparams[constants.BE_VCPUS])
643 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
644 09ea8710 Iustin Pop
    if hvp[constants.HV_PAE]:
645 a21dda8b Iustin Pop
      config.write("pae = 1\n")
646 a21dda8b Iustin Pop
    else:
647 a21dda8b Iustin Pop
      config.write("pae = 0\n")
648 09ea8710 Iustin Pop
    if hvp[constants.HV_ACPI]:
649 a21dda8b Iustin Pop
      config.write("acpi = 1\n")
650 a21dda8b Iustin Pop
    else:
651 a21dda8b Iustin Pop
      config.write("acpi = 0\n")
652 65a6f9b7 Michael Hanselmann
    config.write("apic = 1\n")
653 09ea8710 Iustin Pop
    config.write("device_model = '%s'\n" % hvp[constants.HV_DEVICE_MODEL])
654 a985b417 Iustin Pop
    config.write("boot = '%s'\n" % hvp[constants.HV_BOOT_ORDER])
655 65a6f9b7 Michael Hanselmann
    config.write("sdl = 0\n")
656 97efde45 Guido Trotter
    config.write("usb = 1\n")
657 97efde45 Guido Trotter
    config.write("usbdevice = 'tablet'\n")
658 65a6f9b7 Michael Hanselmann
    config.write("vnc = 1\n")
659 a985b417 Iustin Pop
    if hvp[constants.HV_VNC_BIND_ADDRESS] is None:
660 d0c11cf7 Alexander Schreiber
      config.write("vnclisten = '%s'\n" % constants.VNC_DEFAULT_BIND_ADDRESS)
661 d0c11cf7 Alexander Schreiber
    else:
662 6b405598 Guido Trotter
      config.write("vnclisten = '%s'\n" % hvp[constants.HV_VNC_BIND_ADDRESS])
663 65a6f9b7 Michael Hanselmann
664 377d74c9 Guido Trotter
    if instance.network_port > constants.VNC_BASE_PORT:
665 377d74c9 Guido Trotter
      display = instance.network_port - constants.VNC_BASE_PORT
666 65a6f9b7 Michael Hanselmann
      config.write("vncdisplay = %s\n" % display)
667 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 0\n")
668 65a6f9b7 Michael Hanselmann
    else:
669 65a6f9b7 Michael Hanselmann
      config.write("# vncdisplay = 1\n")
670 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 1\n")
671 65a6f9b7 Michael Hanselmann
672 6e6bb8d5 Guido Trotter
    vnc_pwd_file = hvp[constants.HV_VNC_PASSWORD_FILE]
673 65a6f9b7 Michael Hanselmann
    try:
674 6e6bb8d5 Guido Trotter
      password = utils.ReadFile(vnc_pwd_file)
675 78f66a17 Guido Trotter
    except EnvironmentError, err:
676 78f66a17 Guido Trotter
      raise errors.HypervisorError("Failed to open VNC password file %s: %s" %
677 6e6bb8d5 Guido Trotter
                                   (vnc_pwd_file, err))
678 65a6f9b7 Michael Hanselmann
679 65a6f9b7 Michael Hanselmann
    config.write("vncpasswd = '%s'\n" % password.rstrip())
680 65a6f9b7 Michael Hanselmann
681 65a6f9b7 Michael Hanselmann
    config.write("serial = 'pty'\n")
682 6b970cef Jun Futagawa
    if hvp[constants.HV_USE_LOCALTIME]:
683 6b970cef Jun Futagawa
      config.write("localtime = 1\n")
684 65a6f9b7 Michael Hanselmann
685 65a6f9b7 Michael Hanselmann
    vif_data = []
686 a985b417 Iustin Pop
    nic_type = hvp[constants.HV_NIC_TYPE]
687 f48148c3 Iustin Pop
    if nic_type is None:
688 f48148c3 Iustin Pop
      # ensure old instances don't change
689 f48148c3 Iustin Pop
      nic_type_str = ", type=ioemu"
690 d08f6067 Guido Trotter
    elif nic_type == constants.HT_NIC_PARAVIRTUAL:
691 f48148c3 Iustin Pop
      nic_type_str = ", type=paravirtualized"
692 f48148c3 Iustin Pop
    else:
693 f48148c3 Iustin Pop
      nic_type_str = ", model=%s, type=ioemu" % nic_type
694 65a6f9b7 Michael Hanselmann
    for nic in instance.nics:
695 503b97a9 Guido Trotter
      nic_str = "mac=%s%s" % (nic.mac, nic_type_str)
696 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
697 65a6f9b7 Michael Hanselmann
      if ip is not None:
698 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
699 503b97a9 Guido Trotter
      if nic.nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED:
700 503b97a9 Guido Trotter
        nic_str += ", bridge=%s" % nic.nicparams[constants.NIC_LINK]
701 0183a697 Alessandro Cincaglini
      vif_data.append("'%s'" % nic_str)
702 65a6f9b7 Michael Hanselmann
703 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
704 525011bc Maciej Bliziński
705 525011bc Maciej Bliziński
    disk_data = cls._GetConfigFileDiskData(block_devices,
706 525011bc Maciej Bliziński
                                           hvp[constants.HV_BLOCKDEV_PREFIX])
707 525011bc Maciej Bliziński
708 a985b417 Iustin Pop
    iso_path = hvp[constants.HV_CDROM_IMAGE_PATH]
709 f48148c3 Iustin Pop
    if iso_path:
710 f48148c3 Iustin Pop
      iso = "'file:%s,hdc:cdrom,r'" % iso_path
711 a21dda8b Iustin Pop
      disk_data.append(iso)
712 a21dda8b Iustin Pop
713 a21dda8b Iustin Pop
    config.write("disk = [%s]\n" % (",".join(disk_data)))
714 a21dda8b Iustin Pop
715 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
716 990ade2d Stephen Shirley
    if hvp[constants.HV_REBOOT_BEHAVIOR] == constants.INSTANCE_REBOOT_ALLOWED:
717 990ade2d Stephen Shirley
      config.write("on_reboot = 'restart'\n")
718 990ade2d Stephen Shirley
    else:
719 990ade2d Stephen Shirley
      config.write("on_reboot = 'destroy'\n")
720 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
721 65a6f9b7 Michael Hanselmann
    # just in case it exists
722 65a6f9b7 Michael Hanselmann
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
723 65a6f9b7 Michael Hanselmann
    try:
724 c2be2532 Guido Trotter
      utils.WriteFile(cls._ConfigFileName(instance.name),
725 73cd67f4 Guido Trotter
                      data=config.getvalue())
726 73cd67f4 Guido Trotter
    except EnvironmentError, err:
727 73cd67f4 Guido Trotter
      raise errors.HypervisorError("Cannot write Xen instance confile"
728 c2be2532 Guido Trotter
                                   " file %s: %s" %
729 c2be2532 Guido Trotter
                                   (cls._ConfigFileName(instance.name), err))
730 73cd67f4 Guido Trotter
731 65a6f9b7 Michael Hanselmann
    return True