Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ a21dda8b

History | View | Annotate | Download (14.6 kB)

1 65a6f9b7 Michael Hanselmann
#
2 65a6f9b7 Michael Hanselmann
#
3 65a6f9b7 Michael Hanselmann
4 65a6f9b7 Michael Hanselmann
# Copyright (C) 2006, 2007, 2008 Google Inc.
5 65a6f9b7 Michael Hanselmann
#
6 65a6f9b7 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 65a6f9b7 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 65a6f9b7 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 65a6f9b7 Michael Hanselmann
# (at your option) any later version.
10 65a6f9b7 Michael Hanselmann
#
11 65a6f9b7 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 65a6f9b7 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 65a6f9b7 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 65a6f9b7 Michael Hanselmann
# General Public License for more details.
15 65a6f9b7 Michael Hanselmann
#
16 65a6f9b7 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 65a6f9b7 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 65a6f9b7 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 65a6f9b7 Michael Hanselmann
# 02110-1301, USA.
20 65a6f9b7 Michael Hanselmann
21 65a6f9b7 Michael Hanselmann
22 65a6f9b7 Michael Hanselmann
"""Xen hypervisors
23 65a6f9b7 Michael Hanselmann

24 65a6f9b7 Michael Hanselmann
"""
25 65a6f9b7 Michael Hanselmann
26 65a6f9b7 Michael Hanselmann
import os
27 65a6f9b7 Michael Hanselmann
import os.path
28 65a6f9b7 Michael Hanselmann
import time
29 65a6f9b7 Michael Hanselmann
from cStringIO import StringIO
30 65a6f9b7 Michael Hanselmann
31 65a6f9b7 Michael Hanselmann
from ganeti import constants
32 65a6f9b7 Michael Hanselmann
from ganeti import errors
33 65a6f9b7 Michael Hanselmann
from ganeti import logger
34 65a6f9b7 Michael Hanselmann
from ganeti import utils
35 a2d32034 Michael Hanselmann
from ganeti.hypervisor import hv_base
36 65a6f9b7 Michael Hanselmann
37 65a6f9b7 Michael Hanselmann
38 a2d32034 Michael Hanselmann
class XenHypervisor(hv_base.BaseHypervisor):
39 65a6f9b7 Michael Hanselmann
  """Xen generic hypervisor interface
40 65a6f9b7 Michael Hanselmann

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

44 65a6f9b7 Michael Hanselmann
  """
45 65a6f9b7 Michael Hanselmann
46 65a6f9b7 Michael Hanselmann
  @staticmethod
47 65a6f9b7 Michael Hanselmann
  def _WriteConfigFile(instance, block_devices, extra_args):
48 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
49 65a6f9b7 Michael Hanselmann

50 65a6f9b7 Michael Hanselmann
    """
51 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
52 65a6f9b7 Michael Hanselmann
53 65a6f9b7 Michael Hanselmann
  @staticmethod
54 65a6f9b7 Michael Hanselmann
  def _RemoveConfigFile(instance):
55 65a6f9b7 Michael Hanselmann
    """Remove the xen configuration file.
56 65a6f9b7 Michael Hanselmann

57 65a6f9b7 Michael Hanselmann
    """
58 65a6f9b7 Michael Hanselmann
    utils.RemoveFile("/etc/xen/%s" % instance.name)
59 65a6f9b7 Michael Hanselmann
60 65a6f9b7 Michael Hanselmann
  @staticmethod
61 65a6f9b7 Michael Hanselmann
  def _GetXMList(include_node):
62 65a6f9b7 Michael Hanselmann
    """Return the list of running instances.
63 65a6f9b7 Michael Hanselmann

64 65a6f9b7 Michael Hanselmann
    If the `include_node` argument is True, then we return information
65 65a6f9b7 Michael Hanselmann
    for dom0 also, otherwise we filter that from the return value.
66 65a6f9b7 Michael Hanselmann

67 65a6f9b7 Michael Hanselmann
    The return value is a list of (name, id, memory, vcpus, state, time spent)
68 65a6f9b7 Michael Hanselmann

69 65a6f9b7 Michael Hanselmann
    """
70 65a6f9b7 Michael Hanselmann
    for dummy in range(5):
71 65a6f9b7 Michael Hanselmann
      result = utils.RunCmd(["xm", "list"])
72 65a6f9b7 Michael Hanselmann
      if not result.failed:
73 65a6f9b7 Michael Hanselmann
        break
74 65a6f9b7 Michael Hanselmann
      logger.Error("xm list failed (%s): %s" % (result.fail_reason,
75 65a6f9b7 Michael Hanselmann
                                                result.output))
76 65a6f9b7 Michael Hanselmann
      time.sleep(1)
77 65a6f9b7 Michael Hanselmann
78 65a6f9b7 Michael Hanselmann
    if result.failed:
79 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("xm list failed, retries"
80 65a6f9b7 Michael Hanselmann
                                   " exceeded (%s): %s" %
81 65a6f9b7 Michael Hanselmann
                                   (result.fail_reason, result.stderr))
82 65a6f9b7 Michael Hanselmann
83 65a6f9b7 Michael Hanselmann
    # skip over the heading
84 65a6f9b7 Michael Hanselmann
    lines = result.stdout.splitlines()[1:]
85 65a6f9b7 Michael Hanselmann
    result = []
86 65a6f9b7 Michael Hanselmann
    for line in lines:
87 65a6f9b7 Michael Hanselmann
      # The format of lines is:
88 65a6f9b7 Michael Hanselmann
      # Name      ID Mem(MiB) VCPUs State  Time(s)
89 65a6f9b7 Michael Hanselmann
      # Domain-0   0  3418     4 r-----    266.2
90 65a6f9b7 Michael Hanselmann
      data = line.split()
91 65a6f9b7 Michael Hanselmann
      if len(data) != 6:
92 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("Can't parse output of xm list,"
93 65a6f9b7 Michael Hanselmann
                                     " line: %s" % line)
94 65a6f9b7 Michael Hanselmann
      try:
95 65a6f9b7 Michael Hanselmann
        data[1] = int(data[1])
96 65a6f9b7 Michael Hanselmann
        data[2] = int(data[2])
97 65a6f9b7 Michael Hanselmann
        data[3] = int(data[3])
98 65a6f9b7 Michael Hanselmann
        data[5] = float(data[5])
99 65a6f9b7 Michael Hanselmann
      except ValueError, err:
100 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("Can't parse output of xm list,"
101 65a6f9b7 Michael Hanselmann
                                     " line: %s, error: %s" % (line, err))
102 65a6f9b7 Michael Hanselmann
103 65a6f9b7 Michael Hanselmann
      # skip the Domain-0 (optional)
104 65a6f9b7 Michael Hanselmann
      if include_node or data[0] != 'Domain-0':
105 65a6f9b7 Michael Hanselmann
        result.append(data)
106 65a6f9b7 Michael Hanselmann
107 65a6f9b7 Michael Hanselmann
    return result
108 65a6f9b7 Michael Hanselmann
109 65a6f9b7 Michael Hanselmann
  def ListInstances(self):
110 65a6f9b7 Michael Hanselmann
    """Get the list of running instances.
111 65a6f9b7 Michael Hanselmann

112 65a6f9b7 Michael Hanselmann
    """
113 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(False)
114 65a6f9b7 Michael Hanselmann
    names = [info[0] for info in xm_list]
115 65a6f9b7 Michael Hanselmann
    return names
116 65a6f9b7 Michael Hanselmann
117 65a6f9b7 Michael Hanselmann
  def GetInstanceInfo(self, instance_name):
118 65a6f9b7 Michael Hanselmann
    """Get instance properties.
119 65a6f9b7 Michael Hanselmann

120 65a6f9b7 Michael Hanselmann
    Args:
121 65a6f9b7 Michael Hanselmann
      instance_name: the instance name
122 65a6f9b7 Michael Hanselmann

123 65a6f9b7 Michael Hanselmann
    Returns:
124 65a6f9b7 Michael Hanselmann
      (name, id, memory, vcpus, stat, times)
125 65a6f9b7 Michael Hanselmann
    """
126 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(instance_name=="Domain-0")
127 65a6f9b7 Michael Hanselmann
    result = None
128 65a6f9b7 Michael Hanselmann
    for data in xm_list:
129 65a6f9b7 Michael Hanselmann
      if data[0] == instance_name:
130 65a6f9b7 Michael Hanselmann
        result = data
131 65a6f9b7 Michael Hanselmann
        break
132 65a6f9b7 Michael Hanselmann
    return result
133 65a6f9b7 Michael Hanselmann
134 65a6f9b7 Michael Hanselmann
  def GetAllInstancesInfo(self):
135 65a6f9b7 Michael Hanselmann
    """Get properties of all instances.
136 65a6f9b7 Michael Hanselmann

137 65a6f9b7 Michael Hanselmann
    Returns:
138 65a6f9b7 Michael Hanselmann
      [(name, id, memory, vcpus, stat, times),...]
139 65a6f9b7 Michael Hanselmann
    """
140 65a6f9b7 Michael Hanselmann
    xm_list = self._GetXMList(False)
141 65a6f9b7 Michael Hanselmann
    return xm_list
142 65a6f9b7 Michael Hanselmann
143 65a6f9b7 Michael Hanselmann
  def StartInstance(self, instance, block_devices, extra_args):
144 65a6f9b7 Michael Hanselmann
    """Start an instance."""
145 65a6f9b7 Michael Hanselmann
    self._WriteConfigFile(instance, block_devices, extra_args)
146 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(["xm", "create", instance.name])
147 65a6f9b7 Michael Hanselmann
148 65a6f9b7 Michael Hanselmann
    if result.failed:
149 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
150 65a6f9b7 Michael Hanselmann
                                   (instance.name, result.fail_reason,
151 65a6f9b7 Michael Hanselmann
                                    result.output))
152 65a6f9b7 Michael Hanselmann
153 65a6f9b7 Michael Hanselmann
  def StopInstance(self, instance, force=False):
154 65a6f9b7 Michael Hanselmann
    """Stop an instance."""
155 65a6f9b7 Michael Hanselmann
    self._RemoveConfigFile(instance)
156 65a6f9b7 Michael Hanselmann
    if force:
157 65a6f9b7 Michael Hanselmann
      command = ["xm", "destroy", instance.name]
158 65a6f9b7 Michael Hanselmann
    else:
159 65a6f9b7 Michael Hanselmann
      command = ["xm", "shutdown", instance.name]
160 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(command)
161 65a6f9b7 Michael Hanselmann
162 65a6f9b7 Michael Hanselmann
    if result.failed:
163 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to stop instance %s: %s" %
164 65a6f9b7 Michael Hanselmann
                                   (instance.name, result.fail_reason))
165 65a6f9b7 Michael Hanselmann
166 65a6f9b7 Michael Hanselmann
  def RebootInstance(self, instance):
167 65a6f9b7 Michael Hanselmann
    """Reboot an instance."""
168 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(["xm", "reboot", instance.name])
169 65a6f9b7 Michael Hanselmann
170 65a6f9b7 Michael Hanselmann
    if result.failed:
171 65a6f9b7 Michael Hanselmann
      raise errors.HypervisorError("Failed to reboot instance %s: %s" %
172 65a6f9b7 Michael Hanselmann
                                   (instance.name, result.fail_reason))
173 65a6f9b7 Michael Hanselmann
174 65a6f9b7 Michael Hanselmann
  def GetNodeInfo(self):
175 65a6f9b7 Michael Hanselmann
    """Return information about the node.
176 65a6f9b7 Michael Hanselmann

177 65a6f9b7 Michael Hanselmann
    The return value is a dict, which has to have the following items:
178 65a6f9b7 Michael Hanselmann
      (all values in MiB)
179 65a6f9b7 Michael Hanselmann
      - memory_total: the total memory size on the node
180 65a6f9b7 Michael Hanselmann
      - memory_free: the available memory on the node for instances
181 65a6f9b7 Michael Hanselmann
      - memory_dom0: the memory used by the node itself, if available
182 65a6f9b7 Michael Hanselmann

183 65a6f9b7 Michael Hanselmann
    """
184 65a6f9b7 Michael Hanselmann
    # note: in xen 3, memory has changed to total_memory
185 65a6f9b7 Michael Hanselmann
    result = utils.RunCmd(["xm", "info"])
186 65a6f9b7 Michael Hanselmann
    if result.failed:
187 65a6f9b7 Michael Hanselmann
      logger.Error("Can't run 'xm info': %s" % result.fail_reason)
188 65a6f9b7 Michael Hanselmann
      return None
189 65a6f9b7 Michael Hanselmann
190 65a6f9b7 Michael Hanselmann
    xmoutput = result.stdout.splitlines()
191 65a6f9b7 Michael Hanselmann
    result = {}
192 65a6f9b7 Michael Hanselmann
    for line in xmoutput:
193 65a6f9b7 Michael Hanselmann
      splitfields = line.split(":", 1)
194 65a6f9b7 Michael Hanselmann
195 65a6f9b7 Michael Hanselmann
      if len(splitfields) > 1:
196 65a6f9b7 Michael Hanselmann
        key = splitfields[0].strip()
197 65a6f9b7 Michael Hanselmann
        val = splitfields[1].strip()
198 65a6f9b7 Michael Hanselmann
        if key == 'memory' or key == 'total_memory':
199 65a6f9b7 Michael Hanselmann
          result['memory_total'] = int(val)
200 65a6f9b7 Michael Hanselmann
        elif key == 'free_memory':
201 65a6f9b7 Michael Hanselmann
          result['memory_free'] = int(val)
202 e8a4c138 Iustin Pop
        elif key == 'nr_cpus':
203 e8a4c138 Iustin Pop
          result['cpu_total'] = int(val)
204 65a6f9b7 Michael Hanselmann
    dom0_info = self.GetInstanceInfo("Domain-0")
205 65a6f9b7 Michael Hanselmann
    if dom0_info is not None:
206 65a6f9b7 Michael Hanselmann
      result['memory_dom0'] = dom0_info[2]
207 65a6f9b7 Michael Hanselmann
208 65a6f9b7 Michael Hanselmann
    return result
209 65a6f9b7 Michael Hanselmann
210 65a6f9b7 Michael Hanselmann
  @staticmethod
211 65a6f9b7 Michael Hanselmann
  def GetShellCommandForConsole(instance):
212 65a6f9b7 Michael Hanselmann
    """Return a command for connecting to the console of an instance.
213 65a6f9b7 Michael Hanselmann

214 65a6f9b7 Michael Hanselmann
    """
215 65a6f9b7 Michael Hanselmann
    raise NotImplementedError
216 65a6f9b7 Michael Hanselmann
217 65a6f9b7 Michael Hanselmann
  def Verify(self):
218 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
219 65a6f9b7 Michael Hanselmann

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

222 65a6f9b7 Michael Hanselmann
    """
223 e3e66f02 Michael Hanselmann
    result = utils.RunCmd(["xm", "info"])
224 e3e66f02 Michael Hanselmann
    if result.failed:
225 e3e66f02 Michael Hanselmann
      return "'xm info' failed: %s" % result.fail_reason
226 65a6f9b7 Michael Hanselmann
227 65a6f9b7 Michael Hanselmann
  @staticmethod
228 65a6f9b7 Michael Hanselmann
  def _GetConfigFileDiskData(disk_template, block_devices):
229 65a6f9b7 Michael Hanselmann
    """Get disk directive for xen config file.
230 65a6f9b7 Michael Hanselmann

231 65a6f9b7 Michael Hanselmann
    This method builds the xen config disk directive according to the
232 65a6f9b7 Michael Hanselmann
    given disk_template and block_devices.
233 65a6f9b7 Michael Hanselmann

234 65a6f9b7 Michael Hanselmann
    Args:
235 65a6f9b7 Michael Hanselmann
      disk_template: String containing instance disk template
236 65a6f9b7 Michael Hanselmann
      block_devices: List[tuple1,tuple2,...]
237 65a6f9b7 Michael Hanselmann
        tuple: (cfdev, rldev)
238 65a6f9b7 Michael Hanselmann
          cfdev: dict containing ganeti config disk part
239 65a6f9b7 Michael Hanselmann
          rldev: ganeti.bdev.BlockDev object
240 65a6f9b7 Michael Hanselmann

241 65a6f9b7 Michael Hanselmann
    Returns:
242 65a6f9b7 Michael Hanselmann
      String containing disk directive for xen instance config file
243 65a6f9b7 Michael Hanselmann

244 65a6f9b7 Michael Hanselmann
    """
245 65a6f9b7 Michael Hanselmann
    FILE_DRIVER_MAP = {
246 65a6f9b7 Michael Hanselmann
      constants.FD_LOOP: "file",
247 65a6f9b7 Michael Hanselmann
      constants.FD_BLKTAP: "tap:aio",
248 65a6f9b7 Michael Hanselmann
      }
249 65a6f9b7 Michael Hanselmann
    disk_data = []
250 65a6f9b7 Michael Hanselmann
    for cfdev, rldev in block_devices:
251 65a6f9b7 Michael Hanselmann
      if cfdev.dev_type == constants.LD_FILE:
252 65a6f9b7 Michael Hanselmann
        line = "'%s:%s,%s,w'" % (FILE_DRIVER_MAP[cfdev.physical_id[0]],
253 65a6f9b7 Michael Hanselmann
                                 rldev.dev_path, cfdev.iv_name)
254 65a6f9b7 Michael Hanselmann
      else:
255 65a6f9b7 Michael Hanselmann
        line = "'phy:%s,%s,w'" % (rldev.dev_path, cfdev.iv_name)
256 65a6f9b7 Michael Hanselmann
      disk_data.append(line)
257 65a6f9b7 Michael Hanselmann
258 65a6f9b7 Michael Hanselmann
    return disk_data
259 65a6f9b7 Michael Hanselmann
260 65a6f9b7 Michael Hanselmann
261 65a6f9b7 Michael Hanselmann
class XenPvmHypervisor(XenHypervisor):
262 65a6f9b7 Michael Hanselmann
  """Xen PVM hypervisor interface"""
263 65a6f9b7 Michael Hanselmann
264 65a6f9b7 Michael Hanselmann
  @classmethod
265 65a6f9b7 Michael Hanselmann
  def _WriteConfigFile(cls, instance, block_devices, extra_args):
266 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
267 65a6f9b7 Michael Hanselmann

268 65a6f9b7 Michael Hanselmann
    """
269 65a6f9b7 Michael Hanselmann
    config = StringIO()
270 65a6f9b7 Michael Hanselmann
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
271 65a6f9b7 Michael Hanselmann
272 65a6f9b7 Michael Hanselmann
    # kernel handling
273 65a6f9b7 Michael Hanselmann
    if instance.kernel_path in (None, constants.VALUE_DEFAULT):
274 65a6f9b7 Michael Hanselmann
      kpath = constants.XEN_KERNEL
275 65a6f9b7 Michael Hanselmann
    else:
276 65a6f9b7 Michael Hanselmann
      if not os.path.exists(instance.kernel_path):
277 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("The kernel %s for instance %s is"
278 65a6f9b7 Michael Hanselmann
                                     " missing" % (instance.kernel_path,
279 65a6f9b7 Michael Hanselmann
                                                   instance.name))
280 65a6f9b7 Michael Hanselmann
      kpath = instance.kernel_path
281 65a6f9b7 Michael Hanselmann
    config.write("kernel = '%s'\n" % kpath)
282 65a6f9b7 Michael Hanselmann
283 65a6f9b7 Michael Hanselmann
    # initrd handling
284 65a6f9b7 Michael Hanselmann
    if instance.initrd_path in (None, constants.VALUE_DEFAULT):
285 65a6f9b7 Michael Hanselmann
      if os.path.exists(constants.XEN_INITRD):
286 65a6f9b7 Michael Hanselmann
        initrd_path = constants.XEN_INITRD
287 65a6f9b7 Michael Hanselmann
      else:
288 65a6f9b7 Michael Hanselmann
        initrd_path = None
289 65a6f9b7 Michael Hanselmann
    elif instance.initrd_path == constants.VALUE_NONE:
290 65a6f9b7 Michael Hanselmann
      initrd_path = None
291 65a6f9b7 Michael Hanselmann
    else:
292 65a6f9b7 Michael Hanselmann
      if not os.path.exists(instance.initrd_path):
293 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("The initrd %s for instance %s is"
294 65a6f9b7 Michael Hanselmann
                                     " missing" % (instance.initrd_path,
295 65a6f9b7 Michael Hanselmann
                                                   instance.name))
296 65a6f9b7 Michael Hanselmann
      initrd_path = instance.initrd_path
297 65a6f9b7 Michael Hanselmann
298 65a6f9b7 Michael Hanselmann
    if initrd_path:
299 65a6f9b7 Michael Hanselmann
      config.write("ramdisk = '%s'\n" % initrd_path)
300 65a6f9b7 Michael Hanselmann
301 65a6f9b7 Michael Hanselmann
    # rest of the settings
302 65a6f9b7 Michael Hanselmann
    config.write("memory = %d\n" % instance.memory)
303 65a6f9b7 Michael Hanselmann
    config.write("vcpus = %d\n" % instance.vcpus)
304 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
305 65a6f9b7 Michael Hanselmann
306 65a6f9b7 Michael Hanselmann
    vif_data = []
307 65a6f9b7 Michael Hanselmann
    for nic in instance.nics:
308 65a6f9b7 Michael Hanselmann
      nic_str = "mac=%s, bridge=%s" % (nic.mac, nic.bridge)
309 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
310 65a6f9b7 Michael Hanselmann
      if ip is not None:
311 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
312 65a6f9b7 Michael Hanselmann
      vif_data.append("'%s'" % nic_str)
313 65a6f9b7 Michael Hanselmann
314 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
315 65a6f9b7 Michael Hanselmann
    config.write("disk = [%s]\n" % ",".join(
316 65a6f9b7 Michael Hanselmann
                 cls._GetConfigFileDiskData(instance.disk_template,
317 65a6f9b7 Michael Hanselmann
                                            block_devices)))
318 65a6f9b7 Michael Hanselmann
    config.write("root = '/dev/sda ro'\n")
319 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
320 65a6f9b7 Michael Hanselmann
    config.write("on_reboot = 'restart'\n")
321 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
322 65a6f9b7 Michael Hanselmann
    if extra_args:
323 65a6f9b7 Michael Hanselmann
      config.write("extra = '%s'\n" % extra_args)
324 65a6f9b7 Michael Hanselmann
    # just in case it exists
325 65a6f9b7 Michael Hanselmann
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
326 65a6f9b7 Michael Hanselmann
    try:
327 65a6f9b7 Michael Hanselmann
      f = open("/etc/xen/%s" % instance.name, "w")
328 65a6f9b7 Michael Hanselmann
      try:
329 65a6f9b7 Michael Hanselmann
        f.write(config.getvalue())
330 65a6f9b7 Michael Hanselmann
      finally:
331 65a6f9b7 Michael Hanselmann
        f.close()
332 65a6f9b7 Michael Hanselmann
    except IOError, err:
333 65a6f9b7 Michael Hanselmann
      raise errors.OpExecError("Cannot write Xen instance confile"
334 65a6f9b7 Michael Hanselmann
                               " file /etc/xen/%s: %s" % (instance.name, err))
335 65a6f9b7 Michael Hanselmann
    return True
336 65a6f9b7 Michael Hanselmann
337 65a6f9b7 Michael Hanselmann
  @staticmethod
338 65a6f9b7 Michael Hanselmann
  def GetShellCommandForConsole(instance):
339 65a6f9b7 Michael Hanselmann
    """Return a command for connecting to the console of an instance.
340 65a6f9b7 Michael Hanselmann

341 65a6f9b7 Michael Hanselmann
    """
342 65a6f9b7 Michael Hanselmann
    return "xm console %s" % instance.name
343 65a6f9b7 Michael Hanselmann
344 65a6f9b7 Michael Hanselmann
345 65a6f9b7 Michael Hanselmann
class XenHvmHypervisor(XenHypervisor):
346 65a6f9b7 Michael Hanselmann
  """Xen HVM hypervisor interface"""
347 65a6f9b7 Michael Hanselmann
348 65a6f9b7 Michael Hanselmann
  @classmethod
349 65a6f9b7 Michael Hanselmann
  def _WriteConfigFile(cls, instance, block_devices, extra_args):
350 65a6f9b7 Michael Hanselmann
    """Create a Xen 3.1 HVM config file.
351 65a6f9b7 Michael Hanselmann

352 65a6f9b7 Michael Hanselmann
    """
353 65a6f9b7 Michael Hanselmann
    config = StringIO()
354 65a6f9b7 Michael Hanselmann
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
355 65a6f9b7 Michael Hanselmann
    config.write("kernel = '/usr/lib/xen/boot/hvmloader'\n")
356 65a6f9b7 Michael Hanselmann
    config.write("builder = 'hvm'\n")
357 65a6f9b7 Michael Hanselmann
    config.write("memory = %d\n" % instance.memory)
358 65a6f9b7 Michael Hanselmann
    config.write("vcpus = %d\n" % instance.vcpus)
359 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
360 a21dda8b Iustin Pop
    if instance.hvm_pae:
361 a21dda8b Iustin Pop
      config.write("pae = 1\n")
362 a21dda8b Iustin Pop
    else:
363 a21dda8b Iustin Pop
      config.write("pae = 0\n")
364 a21dda8b Iustin Pop
    if instance.hvm_acpi:
365 a21dda8b Iustin Pop
      config.write("acpi = 1\n")
366 a21dda8b Iustin Pop
    else:
367 a21dda8b Iustin Pop
      config.write("acpi = 0\n")
368 65a6f9b7 Michael Hanselmann
    config.write("apic = 1\n")
369 65a6f9b7 Michael Hanselmann
    arch = os.uname()[4]
370 65a6f9b7 Michael Hanselmann
    if '64' in arch:
371 65a6f9b7 Michael Hanselmann
      config.write("device_model = '/usr/lib64/xen/bin/qemu-dm'\n")
372 65a6f9b7 Michael Hanselmann
    else:
373 65a6f9b7 Michael Hanselmann
      config.write("device_model = '/usr/lib/xen/bin/qemu-dm'\n")
374 65a6f9b7 Michael Hanselmann
    if instance.hvm_boot_order is None:
375 65a6f9b7 Michael Hanselmann
      config.write("boot = '%s'\n" % constants.HT_HVM_DEFAULT_BOOT_ORDER)
376 65a6f9b7 Michael Hanselmann
    else:
377 65a6f9b7 Michael Hanselmann
      config.write("boot = '%s'\n" % instance.hvm_boot_order)
378 65a6f9b7 Michael Hanselmann
    config.write("sdl = 0\n")
379 65a6f9b7 Michael Hanselmann
    config.write("usb = 1\n");
380 65a6f9b7 Michael Hanselmann
    config.write("usbdevice = 'tablet'\n");
381 65a6f9b7 Michael Hanselmann
    config.write("vnc = 1\n")
382 a21dda8b Iustin Pop
    config.write("vnclisten = '%s'\n" % instance.vnc_bind_address)
383 65a6f9b7 Michael Hanselmann
384 65a6f9b7 Michael Hanselmann
    if instance.network_port > constants.HT_HVM_VNC_BASE_PORT:
385 65a6f9b7 Michael Hanselmann
      display = instance.network_port - constants.HT_HVM_VNC_BASE_PORT
386 65a6f9b7 Michael Hanselmann
      config.write("vncdisplay = %s\n" % display)
387 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 0\n")
388 65a6f9b7 Michael Hanselmann
    else:
389 65a6f9b7 Michael Hanselmann
      config.write("# vncdisplay = 1\n")
390 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 1\n")
391 65a6f9b7 Michael Hanselmann
392 65a6f9b7 Michael Hanselmann
    try:
393 65a6f9b7 Michael Hanselmann
      password_file = open(constants.VNC_PASSWORD_FILE, "r")
394 65a6f9b7 Michael Hanselmann
      try:
395 65a6f9b7 Michael Hanselmann
        password = password_file.readline()
396 65a6f9b7 Michael Hanselmann
      finally:
397 65a6f9b7 Michael Hanselmann
        password_file.close()
398 65a6f9b7 Michael Hanselmann
    except IOError:
399 65a6f9b7 Michael Hanselmann
      raise errors.OpExecError("failed to open VNC password file %s " %
400 65a6f9b7 Michael Hanselmann
                               constants.VNC_PASSWORD_FILE)
401 65a6f9b7 Michael Hanselmann
402 65a6f9b7 Michael Hanselmann
    config.write("vncpasswd = '%s'\n" % password.rstrip())
403 65a6f9b7 Michael Hanselmann
404 65a6f9b7 Michael Hanselmann
    config.write("serial = 'pty'\n")
405 65a6f9b7 Michael Hanselmann
    config.write("localtime = 1\n")
406 65a6f9b7 Michael Hanselmann
407 65a6f9b7 Michael Hanselmann
    vif_data = []
408 65a6f9b7 Michael Hanselmann
    for nic in instance.nics:
409 65a6f9b7 Michael Hanselmann
      nic_str = "mac=%s, bridge=%s, type=ioemu" % (nic.mac, nic.bridge)
410 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
411 65a6f9b7 Michael Hanselmann
      if ip is not None:
412 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
413 65a6f9b7 Michael Hanselmann
      vif_data.append("'%s'" % nic_str)
414 65a6f9b7 Michael Hanselmann
415 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
416 a21dda8b Iustin Pop
    disk_data = cls._GetConfigFileDiskData(instance.disk_template,
417 a21dda8b Iustin Pop
                                            block_devices)
418 a21dda8b Iustin Pop
    disk_data = [line.replace(",sd", ",ioemu:hd") for line in disk_data]
419 a21dda8b Iustin Pop
    if instance.hvm_cdrom_image_path is not None:
420 a21dda8b Iustin Pop
      iso = "'file:%s,hdc:cdrom,r'" % (instance.hvm_cdrom_image_path)
421 a21dda8b Iustin Pop
      disk_data.append(iso)
422 a21dda8b Iustin Pop
423 a21dda8b Iustin Pop
    config.write("disk = [%s]\n" % (",".join(disk_data)))
424 a21dda8b Iustin Pop
425 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
426 65a6f9b7 Michael Hanselmann
    config.write("on_reboot = 'restart'\n")
427 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
428 65a6f9b7 Michael Hanselmann
    if extra_args:
429 65a6f9b7 Michael Hanselmann
      config.write("extra = '%s'\n" % extra_args)
430 65a6f9b7 Michael Hanselmann
    # just in case it exists
431 65a6f9b7 Michael Hanselmann
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
432 65a6f9b7 Michael Hanselmann
    try:
433 65a6f9b7 Michael Hanselmann
      f = open("/etc/xen/%s" % instance.name, "w")
434 65a6f9b7 Michael Hanselmann
      try:
435 65a6f9b7 Michael Hanselmann
        f.write(config.getvalue())
436 65a6f9b7 Michael Hanselmann
      finally:
437 65a6f9b7 Michael Hanselmann
        f.close()
438 65a6f9b7 Michael Hanselmann
    except IOError, err:
439 65a6f9b7 Michael Hanselmann
      raise errors.OpExecError("Cannot write Xen instance confile"
440 65a6f9b7 Michael Hanselmann
                               " file /etc/xen/%s: %s" % (instance.name, err))
441 65a6f9b7 Michael Hanselmann
    return True
442 65a6f9b7 Michael Hanselmann
443 65a6f9b7 Michael Hanselmann
  @staticmethod
444 65a6f9b7 Michael Hanselmann
  def GetShellCommandForConsole(instance):
445 65a6f9b7 Michael Hanselmann
    """Return a command for connecting to the console of an instance.
446 65a6f9b7 Michael Hanselmann

447 65a6f9b7 Michael Hanselmann
    """
448 65a6f9b7 Michael Hanselmann
    if instance.network_port is None:
449 65a6f9b7 Michael Hanselmann
      raise errors.OpExecError("no console port defined for %s"
450 65a6f9b7 Michael Hanselmann
                               % instance.name)
451 a21dda8b Iustin Pop
    elif instance.vnc_bind_address == constants.BIND_ADDRESS_GLOBAL:
452 65a6f9b7 Michael Hanselmann
      raise errors.OpExecError("no PTY console, connect to %s:%s via VNC"
453 65a6f9b7 Michael Hanselmann
                               % (instance.primary_node,
454 65a6f9b7 Michael Hanselmann
                                  instance.network_port))
455 a21dda8b Iustin Pop
    else:
456 a21dda8b Iustin Pop
      raise errors.OpExecError("no PTY console, connect to %s:%s via VNC"
457 a21dda8b Iustin Pop
                               % (instance.vnc_bind_address,
458 a21dda8b Iustin Pop
                                  instance.network_port))