Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ a52978c7

History | View | Annotate | Download (24.5 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 c4708267 Tsachy Shacham
  @classmethod
88 c4708267 Tsachy Shacham
  def _CreateConfigCpus(cls, cpu_mask):
89 c4708267 Tsachy Shacham
    """Create a CPU config string that's compatible with Xen's
90 c4708267 Tsachy Shacham
    configuration file.
91 c4708267 Tsachy Shacham

92 c4708267 Tsachy Shacham
    """
93 c4708267 Tsachy Shacham
    # Convert the string CPU mask to a list of list of int's
94 c4708267 Tsachy Shacham
    cpu_list = utils.ParseMultiCpuMask(cpu_mask)
95 c4708267 Tsachy Shacham
96 c4708267 Tsachy Shacham
    if len(cpu_list) == 1:
97 c4708267 Tsachy Shacham
      all_cpu_mapping = cpu_list[0]
98 5b43cc23 Tsachy Shacham
      if all_cpu_mapping == constants.CPU_PINNING_OFF:
99 c4708267 Tsachy Shacham
        # If CPU pinning has 1 entry that's "all", then remove the
100 c4708267 Tsachy Shacham
        # parameter from the config file
101 c4708267 Tsachy Shacham
        return None
102 c4708267 Tsachy Shacham
      else:
103 c4708267 Tsachy Shacham
        # If CPU pinning has one non-all entry, mapping all vCPUS (the entire
104 c4708267 Tsachy Shacham
        # VM) to one physical CPU, using format 'cpu = "C"'
105 c4708267 Tsachy Shacham
        return "cpu = \"%s\"" % ",".join(map(str, all_cpu_mapping))
106 c4708267 Tsachy Shacham
    else:
107 c4708267 Tsachy Shacham
      def _GetCPUMap(vcpu):
108 c4708267 Tsachy Shacham
        if vcpu[0] == constants.CPU_PINNING_ALL_VAL:
109 c4708267 Tsachy Shacham
          cpu_map = constants.CPU_PINNING_ALL_XEN
110 c4708267 Tsachy Shacham
        else:
111 c4708267 Tsachy Shacham
          cpu_map = ",".join(map(str, vcpu))
112 c4708267 Tsachy Shacham
        return "\"%s\"" % cpu_map
113 c4708267 Tsachy Shacham
114 c4708267 Tsachy Shacham
      # build the result string in format 'cpus = [ "c", "c", "c" ]',
115 c4708267 Tsachy Shacham
      # where each c is a physical CPU number, a range, a list, or any
116 c4708267 Tsachy Shacham
      # combination
117 c4708267 Tsachy Shacham
      return "cpus = [ %s ]" % ", ".join(map(_GetCPUMap, cpu_list))
118 c4708267 Tsachy Shacham
119 65a6f9b7 Michael Hanselmann
  @staticmethod
120 06b78e8b Michael Hanselmann
  def _RunXmList(xmlist_errors):
121 06b78e8b Michael Hanselmann
    """Helper function for L{_GetXMList} to run "xm list".
122 06b78e8b Michael Hanselmann

123 06b78e8b Michael Hanselmann
    """
124 06b78e8b Michael Hanselmann
    result = utils.RunCmd(["xm", "list"])
125 06b78e8b Michael Hanselmann
    if result.failed:
126 06b78e8b Michael Hanselmann
      logging.error("xm list failed (%s): %s", result.fail_reason,
127 06b78e8b Michael Hanselmann
                    result.output)
128 06b78e8b Michael Hanselmann
      xmlist_errors.append(result)
129 06b78e8b Michael Hanselmann
      raise utils.RetryAgain()
130 06b78e8b Michael Hanselmann
131 06b78e8b Michael Hanselmann
    # skip over the heading
132 06b78e8b Michael Hanselmann
    return result.stdout.splitlines()[1:]
133 06b78e8b Michael Hanselmann
134 06b78e8b Michael Hanselmann
  @classmethod
135 06b78e8b Michael Hanselmann
  def _GetXMList(cls, include_node):
136 65a6f9b7 Michael Hanselmann
    """Return the list of running instances.
137 65a6f9b7 Michael Hanselmann

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

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

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

185 65a6f9b7 Michael Hanselmann
    """
186 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(False)
187 65a6f9b7 Michael Hanselmann
    names = [info[0] for info in xm_list]
188 65a6f9b7 Michael Hanselmann
    return names
189 65a6f9b7 Michael Hanselmann
190 65a6f9b7 Michael Hanselmann
  def GetInstanceInfo(self, instance_name):
191 65a6f9b7 Michael Hanselmann
    """Get instance properties.
192 65a6f9b7 Michael Hanselmann

193 c41eea6e Iustin Pop
    @param instance_name: the instance name
194 c41eea6e Iustin Pop

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

197 65a6f9b7 Michael Hanselmann
    """
198 e687ec01 Michael Hanselmann
    xm_list = self._GetXMList(instance_name == "Domain-0")
199 65a6f9b7 Michael Hanselmann
    result = None
200 65a6f9b7 Michael Hanselmann
    for data in xm_list:
201 65a6f9b7 Michael Hanselmann
      if data[0] == instance_name:
202 65a6f9b7 Michael Hanselmann
        result = data
203 65a6f9b7 Michael Hanselmann
        break
204 65a6f9b7 Michael Hanselmann
    return result
205 65a6f9b7 Michael Hanselmann
206 65a6f9b7 Michael Hanselmann
  def GetAllInstancesInfo(self):
207 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
208 65a6f9b7 Michael Hanselmann

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

211 65a6f9b7 Michael Hanselmann
    """
212 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(False)
213 65a6f9b7 Michael Hanselmann
    return xm_list
214 65a6f9b7 Michael Hanselmann
215 323f9095 Stephen Shirley
  def StartInstance(self, instance, block_devices, startup_paused):
216 c41eea6e Iustin Pop
    """Start an instance.
217 c41eea6e Iustin Pop

218 c41eea6e Iustin Pop
    """
219 07813a9e Iustin Pop
    self._WriteConfigFile(instance, block_devices)
220 323f9095 Stephen Shirley
    cmd = ["xm", "create"]
221 323f9095 Stephen Shirley
    if startup_paused:
222 323f9095 Stephen Shirley
      cmd.extend(["--paused"])
223 323f9095 Stephen Shirley
    cmd.extend([instance.name])
224 323f9095 Stephen Shirley
    result = utils.RunCmd(cmd)
225 65a6f9b7 Michael Hanselmann
226 65a6f9b7 Michael Hanselmann
    if result.failed:
227 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
228 65a6f9b7 Michael Hanselmann
                                   (instance.name, result.fail_reason,
229 65a6f9b7 Michael Hanselmann
                                    result.output))
230 65a6f9b7 Michael Hanselmann
231 bbcf7ad0 Iustin Pop
  def StopInstance(self, instance, force=False, retry=False, name=None):
232 c41eea6e Iustin Pop
    """Stop an instance.
233 c41eea6e Iustin Pop

234 c41eea6e Iustin Pop
    """
235 bbcf7ad0 Iustin Pop
    if name is None:
236 bbcf7ad0 Iustin Pop
      name = instance.name
237 bbcf7ad0 Iustin Pop
    self._RemoveConfigFile(name)
238 65a6f9b7 Michael Hanselmann
    if force:
239 bbcf7ad0 Iustin Pop
      command = ["xm", "destroy", name]
240 65a6f9b7 Michael Hanselmann
    else:
241 bbcf7ad0 Iustin Pop
      command = ["xm", "shutdown", name]
242 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(command)
243 65a6f9b7 Michael Hanselmann
244 65a6f9b7 Michael Hanselmann
    if result.failed:
245 3213d3c8 Iustin Pop
      raise errors.HypervisorError("Failed to stop instance %s: %s, %s" %
246 bbcf7ad0 Iustin Pop
                                   (name, result.fail_reason, result.output))
247 65a6f9b7 Michael Hanselmann
248 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
249 c41eea6e Iustin Pop
    """Reboot an instance.
250 c41eea6e Iustin Pop

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

285 0105bad3 Iustin Pop
    @return: a dict with the following keys (memory values in MiB):
286 c41eea6e Iustin Pop
          - memory_total: the total memory size on the node
287 c41eea6e Iustin Pop
          - memory_free: the available memory on the node for instances
288 c41eea6e Iustin Pop
          - memory_dom0: the memory used by the node itself, if available
289 0105bad3 Iustin Pop
          - nr_cpus: total number of CPUs
290 0105bad3 Iustin Pop
          - nr_nodes: in a NUMA system, the number of domains
291 0105bad3 Iustin Pop
          - nr_sockets: the number of physical CPU sockets in the node
292 65a6f9b7 Michael Hanselmann

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

448 6e7275c0 Iustin Pop
    """
449 58d38b02 Iustin Pop
    if self.GetInstanceInfo(instance.name) is None:
450 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Instance not running, cannot migrate")
451 50716be0 Iustin Pop
452 641ae041 Iustin Pop
    port = instance.hvparams[constants.HV_MIGRATION_PORT]
453 50716be0 Iustin Pop
454 a744b676 Manuel Franceschini
    if not netutils.TcpPing(target, port, live_port_needed=True):
455 50716be0 Iustin Pop
      raise errors.HypervisorError("Remote host %s not listening on port"
456 50716be0 Iustin Pop
                                   " %s, cannot migrate" % (target, port))
457 50716be0 Iustin Pop
458 641ae041 Iustin Pop
    args = ["xm", "migrate", "-p", "%d" % port]
459 6e7275c0 Iustin Pop
    if live:
460 6e7275c0 Iustin Pop
      args.append("-l")
461 58d38b02 Iustin Pop
    args.extend([instance.name, target])
462 6e7275c0 Iustin Pop
    result = utils.RunCmd(args)
463 6e7275c0 Iustin Pop
    if result.failed:
464 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Failed to migrate instance %s: %s" %
465 58d38b02 Iustin Pop
                                   (instance.name, result.output))
466 53c776b5 Iustin Pop
    # remove old xen file after migration succeeded
467 53c776b5 Iustin Pop
    try:
468 58d38b02 Iustin Pop
      self._RemoveConfigFile(instance.name)
469 c979d253 Iustin Pop
    except EnvironmentError:
470 c979d253 Iustin Pop
      logging.exception("Failure while removing instance config file")
471 6e7275c0 Iustin Pop
472 f5118ade Iustin Pop
  @classmethod
473 f5118ade Iustin Pop
  def PowercycleNode(cls):
474 f5118ade Iustin Pop
    """Xen-specific powercycle.
475 f5118ade Iustin Pop

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

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

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

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