Statistics
| Branch: | Tag: | Revision:

root / lib / hypervisor / hv_xen.py @ 1daae384

History | View | Annotate | Download (15.1 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 04c4330c Alexander Schreiber
    return "xm console %s" % instance.name
216 04c4330c Alexander Schreiber
217 65a6f9b7 Michael Hanselmann
218 65a6f9b7 Michael Hanselmann
  def Verify(self):
219 65a6f9b7 Michael Hanselmann
    """Verify the hypervisor.
220 65a6f9b7 Michael Hanselmann

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

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

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

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

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

245 65a6f9b7 Michael Hanselmann
    """
246 65a6f9b7 Michael Hanselmann
    FILE_DRIVER_MAP = {
247 65a6f9b7 Michael Hanselmann
      constants.FD_LOOP: "file",
248 65a6f9b7 Michael Hanselmann
      constants.FD_BLKTAP: "tap:aio",
249 65a6f9b7 Michael Hanselmann
      }
250 65a6f9b7 Michael Hanselmann
    disk_data = []
251 65a6f9b7 Michael Hanselmann
    for cfdev, rldev in block_devices:
252 65a6f9b7 Michael Hanselmann
      if cfdev.dev_type == constants.LD_FILE:
253 65a6f9b7 Michael Hanselmann
        line = "'%s:%s,%s,w'" % (FILE_DRIVER_MAP[cfdev.physical_id[0]],
254 65a6f9b7 Michael Hanselmann
                                 rldev.dev_path, cfdev.iv_name)
255 65a6f9b7 Michael Hanselmann
      else:
256 65a6f9b7 Michael Hanselmann
        line = "'phy:%s,%s,w'" % (rldev.dev_path, cfdev.iv_name)
257 65a6f9b7 Michael Hanselmann
      disk_data.append(line)
258 65a6f9b7 Michael Hanselmann
259 65a6f9b7 Michael Hanselmann
    return disk_data
260 65a6f9b7 Michael Hanselmann
261 6e7275c0 Iustin Pop
  def MigrateInstance(self, instance, target, live):
262 6e7275c0 Iustin Pop
    """Migrate an instance to a target node.
263 6e7275c0 Iustin Pop

264 6e7275c0 Iustin Pop
    Arguments:
265 6e7275c0 Iustin Pop
      - instance: the name of the instance
266 6e7275c0 Iustin Pop
      - target: the ip of the target node
267 6e7275c0 Iustin Pop
      - live: whether to do live migration or not
268 6e7275c0 Iustin Pop

269 6e7275c0 Iustin Pop
    Returns: none, errors will be signaled by exception.
270 6e7275c0 Iustin Pop

271 6e7275c0 Iustin Pop
    The migration will not be attempted if the instance is not
272 6e7275c0 Iustin Pop
    currently running.
273 6e7275c0 Iustin Pop

274 6e7275c0 Iustin Pop
    """
275 6e7275c0 Iustin Pop
    if self.GetInstanceInfo(instance) is None:
276 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Instance not running, cannot migrate")
277 6e7275c0 Iustin Pop
    args = ["xm", "migrate"]
278 6e7275c0 Iustin Pop
    if live:
279 6e7275c0 Iustin Pop
      args.append("-l")
280 6e7275c0 Iustin Pop
    args.extend([instance, target])
281 6e7275c0 Iustin Pop
    result = utils.RunCmd(args)
282 6e7275c0 Iustin Pop
    if result.failed:
283 6e7275c0 Iustin Pop
      raise errors.HypervisorError("Failed to migrate instance %s: %s" %
284 6e7275c0 Iustin Pop
                                   (instance, result.output))
285 6e7275c0 Iustin Pop
286 65a6f9b7 Michael Hanselmann
287 65a6f9b7 Michael Hanselmann
class XenPvmHypervisor(XenHypervisor):
288 65a6f9b7 Michael Hanselmann
  """Xen PVM hypervisor interface"""
289 65a6f9b7 Michael Hanselmann
290 65a6f9b7 Michael Hanselmann
  @classmethod
291 65a6f9b7 Michael Hanselmann
  def _WriteConfigFile(cls, instance, block_devices, extra_args):
292 65a6f9b7 Michael Hanselmann
    """Write the Xen config file for the instance.
293 65a6f9b7 Michael Hanselmann

294 65a6f9b7 Michael Hanselmann
    """
295 65a6f9b7 Michael Hanselmann
    config = StringIO()
296 65a6f9b7 Michael Hanselmann
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
297 65a6f9b7 Michael Hanselmann
298 65a6f9b7 Michael Hanselmann
    # kernel handling
299 65a6f9b7 Michael Hanselmann
    if instance.kernel_path in (None, constants.VALUE_DEFAULT):
300 65a6f9b7 Michael Hanselmann
      kpath = constants.XEN_KERNEL
301 65a6f9b7 Michael Hanselmann
    else:
302 65a6f9b7 Michael Hanselmann
      if not os.path.exists(instance.kernel_path):
303 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("The kernel %s for instance %s is"
304 65a6f9b7 Michael Hanselmann
                                     " missing" % (instance.kernel_path,
305 65a6f9b7 Michael Hanselmann
                                                   instance.name))
306 65a6f9b7 Michael Hanselmann
      kpath = instance.kernel_path
307 65a6f9b7 Michael Hanselmann
    config.write("kernel = '%s'\n" % kpath)
308 65a6f9b7 Michael Hanselmann
309 65a6f9b7 Michael Hanselmann
    # initrd handling
310 65a6f9b7 Michael Hanselmann
    if instance.initrd_path in (None, constants.VALUE_DEFAULT):
311 65a6f9b7 Michael Hanselmann
      if os.path.exists(constants.XEN_INITRD):
312 65a6f9b7 Michael Hanselmann
        initrd_path = constants.XEN_INITRD
313 65a6f9b7 Michael Hanselmann
      else:
314 65a6f9b7 Michael Hanselmann
        initrd_path = None
315 65a6f9b7 Michael Hanselmann
    elif instance.initrd_path == constants.VALUE_NONE:
316 65a6f9b7 Michael Hanselmann
      initrd_path = None
317 65a6f9b7 Michael Hanselmann
    else:
318 65a6f9b7 Michael Hanselmann
      if not os.path.exists(instance.initrd_path):
319 65a6f9b7 Michael Hanselmann
        raise errors.HypervisorError("The initrd %s for instance %s is"
320 65a6f9b7 Michael Hanselmann
                                     " missing" % (instance.initrd_path,
321 65a6f9b7 Michael Hanselmann
                                                   instance.name))
322 65a6f9b7 Michael Hanselmann
      initrd_path = instance.initrd_path
323 65a6f9b7 Michael Hanselmann
324 65a6f9b7 Michael Hanselmann
    if initrd_path:
325 65a6f9b7 Michael Hanselmann
      config.write("ramdisk = '%s'\n" % initrd_path)
326 65a6f9b7 Michael Hanselmann
327 65a6f9b7 Michael Hanselmann
    # rest of the settings
328 65a6f9b7 Michael Hanselmann
    config.write("memory = %d\n" % instance.memory)
329 65a6f9b7 Michael Hanselmann
    config.write("vcpus = %d\n" % instance.vcpus)
330 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
331 65a6f9b7 Michael Hanselmann
332 65a6f9b7 Michael Hanselmann
    vif_data = []
333 65a6f9b7 Michael Hanselmann
    for nic in instance.nics:
334 65a6f9b7 Michael Hanselmann
      nic_str = "mac=%s, bridge=%s" % (nic.mac, nic.bridge)
335 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
336 65a6f9b7 Michael Hanselmann
      if ip is not None:
337 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
338 65a6f9b7 Michael Hanselmann
      vif_data.append("'%s'" % nic_str)
339 65a6f9b7 Michael Hanselmann
340 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
341 65a6f9b7 Michael Hanselmann
    config.write("disk = [%s]\n" % ",".join(
342 65a6f9b7 Michael Hanselmann
                 cls._GetConfigFileDiskData(instance.disk_template,
343 65a6f9b7 Michael Hanselmann
                                            block_devices)))
344 65a6f9b7 Michael Hanselmann
    config.write("root = '/dev/sda ro'\n")
345 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
346 65a6f9b7 Michael Hanselmann
    config.write("on_reboot = 'restart'\n")
347 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
348 65a6f9b7 Michael Hanselmann
    if extra_args:
349 65a6f9b7 Michael Hanselmann
      config.write("extra = '%s'\n" % extra_args)
350 65a6f9b7 Michael Hanselmann
    # just in case it exists
351 65a6f9b7 Michael Hanselmann
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
352 65a6f9b7 Michael Hanselmann
    try:
353 65a6f9b7 Michael Hanselmann
      f = open("/etc/xen/%s" % instance.name, "w")
354 65a6f9b7 Michael Hanselmann
      try:
355 65a6f9b7 Michael Hanselmann
        f.write(config.getvalue())
356 65a6f9b7 Michael Hanselmann
      finally:
357 65a6f9b7 Michael Hanselmann
        f.close()
358 65a6f9b7 Michael Hanselmann
    except IOError, err:
359 65a6f9b7 Michael Hanselmann
      raise errors.OpExecError("Cannot write Xen instance confile"
360 65a6f9b7 Michael Hanselmann
                               " file /etc/xen/%s: %s" % (instance.name, err))
361 65a6f9b7 Michael Hanselmann
    return True
362 65a6f9b7 Michael Hanselmann
363 65a6f9b7 Michael Hanselmann
364 65a6f9b7 Michael Hanselmann
class XenHvmHypervisor(XenHypervisor):
365 65a6f9b7 Michael Hanselmann
  """Xen HVM hypervisor interface"""
366 65a6f9b7 Michael Hanselmann
367 65a6f9b7 Michael Hanselmann
  @classmethod
368 65a6f9b7 Michael Hanselmann
  def _WriteConfigFile(cls, instance, block_devices, extra_args):
369 65a6f9b7 Michael Hanselmann
    """Create a Xen 3.1 HVM config file.
370 65a6f9b7 Michael Hanselmann

371 65a6f9b7 Michael Hanselmann
    """
372 65a6f9b7 Michael Hanselmann
    config = StringIO()
373 65a6f9b7 Michael Hanselmann
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
374 65a6f9b7 Michael Hanselmann
    config.write("kernel = '/usr/lib/xen/boot/hvmloader'\n")
375 65a6f9b7 Michael Hanselmann
    config.write("builder = 'hvm'\n")
376 65a6f9b7 Michael Hanselmann
    config.write("memory = %d\n" % instance.memory)
377 65a6f9b7 Michael Hanselmann
    config.write("vcpus = %d\n" % instance.vcpus)
378 65a6f9b7 Michael Hanselmann
    config.write("name = '%s'\n" % instance.name)
379 a21dda8b Iustin Pop
    if instance.hvm_pae:
380 a21dda8b Iustin Pop
      config.write("pae = 1\n")
381 a21dda8b Iustin Pop
    else:
382 a21dda8b Iustin Pop
      config.write("pae = 0\n")
383 a21dda8b Iustin Pop
    if instance.hvm_acpi:
384 a21dda8b Iustin Pop
      config.write("acpi = 1\n")
385 a21dda8b Iustin Pop
    else:
386 a21dda8b Iustin Pop
      config.write("acpi = 0\n")
387 65a6f9b7 Michael Hanselmann
    config.write("apic = 1\n")
388 65a6f9b7 Michael Hanselmann
    arch = os.uname()[4]
389 65a6f9b7 Michael Hanselmann
    if '64' in arch:
390 65a6f9b7 Michael Hanselmann
      config.write("device_model = '/usr/lib64/xen/bin/qemu-dm'\n")
391 65a6f9b7 Michael Hanselmann
    else:
392 65a6f9b7 Michael Hanselmann
      config.write("device_model = '/usr/lib/xen/bin/qemu-dm'\n")
393 65a6f9b7 Michael Hanselmann
    if instance.hvm_boot_order is None:
394 65a6f9b7 Michael Hanselmann
      config.write("boot = '%s'\n" % constants.HT_HVM_DEFAULT_BOOT_ORDER)
395 65a6f9b7 Michael Hanselmann
    else:
396 65a6f9b7 Michael Hanselmann
      config.write("boot = '%s'\n" % instance.hvm_boot_order)
397 65a6f9b7 Michael Hanselmann
    config.write("sdl = 0\n")
398 97efde45 Guido Trotter
    config.write("usb = 1\n")
399 97efde45 Guido Trotter
    config.write("usbdevice = 'tablet'\n")
400 65a6f9b7 Michael Hanselmann
    config.write("vnc = 1\n")
401 d0c11cf7 Alexander Schreiber
    if instance.vnc_bind_address is None:
402 d0c11cf7 Alexander Schreiber
      config.write("vnclisten = '%s'\n" % constants.VNC_DEFAULT_BIND_ADDRESS)
403 d0c11cf7 Alexander Schreiber
    else:
404 d0c11cf7 Alexander Schreiber
      config.write("vnclisten = '%s'\n" % instance.vnc_bind_address)
405 65a6f9b7 Michael Hanselmann
406 65a6f9b7 Michael Hanselmann
    if instance.network_port > constants.HT_HVM_VNC_BASE_PORT:
407 65a6f9b7 Michael Hanselmann
      display = instance.network_port - constants.HT_HVM_VNC_BASE_PORT
408 65a6f9b7 Michael Hanselmann
      config.write("vncdisplay = %s\n" % display)
409 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 0\n")
410 65a6f9b7 Michael Hanselmann
    else:
411 65a6f9b7 Michael Hanselmann
      config.write("# vncdisplay = 1\n")
412 65a6f9b7 Michael Hanselmann
      config.write("vncunused = 1\n")
413 65a6f9b7 Michael Hanselmann
414 65a6f9b7 Michael Hanselmann
    try:
415 65a6f9b7 Michael Hanselmann
      password_file = open(constants.VNC_PASSWORD_FILE, "r")
416 65a6f9b7 Michael Hanselmann
      try:
417 65a6f9b7 Michael Hanselmann
        password = password_file.readline()
418 65a6f9b7 Michael Hanselmann
      finally:
419 65a6f9b7 Michael Hanselmann
        password_file.close()
420 65a6f9b7 Michael Hanselmann
    except IOError:
421 65a6f9b7 Michael Hanselmann
      raise errors.OpExecError("failed to open VNC password file %s " %
422 65a6f9b7 Michael Hanselmann
                               constants.VNC_PASSWORD_FILE)
423 65a6f9b7 Michael Hanselmann
424 65a6f9b7 Michael Hanselmann
    config.write("vncpasswd = '%s'\n" % password.rstrip())
425 65a6f9b7 Michael Hanselmann
426 65a6f9b7 Michael Hanselmann
    config.write("serial = 'pty'\n")
427 65a6f9b7 Michael Hanselmann
    config.write("localtime = 1\n")
428 65a6f9b7 Michael Hanselmann
429 65a6f9b7 Michael Hanselmann
    vif_data = []
430 65a6f9b7 Michael Hanselmann
    for nic in instance.nics:
431 5397e0b7 Alexander Schreiber
      if instance.hvm_nic_type is None: # ensure old instances don't change
432 5397e0b7 Alexander Schreiber
        nic_type = ", type=ioemu"
433 5397e0b7 Alexander Schreiber
      elif instance.hvm_nic_type == constants.HT_HVM_DEV_PARAVIRTUAL:
434 5397e0b7 Alexander Schreiber
        nic_type = ", type=paravirtualized"
435 5397e0b7 Alexander Schreiber
      else:
436 5397e0b7 Alexander Schreiber
        nic_type = ", model=%s, type=ioemu" % instance.hvm_nic_type
437 5397e0b7 Alexander Schreiber
438 5397e0b7 Alexander Schreiber
      nic_str = "mac=%s, bridge=%s%s" % (nic.mac, nic.bridge, nic_type)
439 65a6f9b7 Michael Hanselmann
      ip = getattr(nic, "ip", None)
440 65a6f9b7 Michael Hanselmann
      if ip is not None:
441 65a6f9b7 Michael Hanselmann
        nic_str += ", ip=%s" % ip
442 65a6f9b7 Michael Hanselmann
      vif_data.append("'%s'" % nic_str)
443 65a6f9b7 Michael Hanselmann
444 65a6f9b7 Michael Hanselmann
    config.write("vif = [%s]\n" % ",".join(vif_data))
445 a21dda8b Iustin Pop
    disk_data = cls._GetConfigFileDiskData(instance.disk_template,
446 a21dda8b Iustin Pop
                                            block_devices)
447 5397e0b7 Alexander Schreiber
    if ((instance.hvm_disk_type is None) or
448 5397e0b7 Alexander Schreiber
        (instance.hvm_disk_type == constants.HT_HVM_DEV_IOEMU)):
449 5397e0b7 Alexander Schreiber
      replacement = ",ioemu:hd"
450 5397e0b7 Alexander Schreiber
    else:
451 5397e0b7 Alexander Schreiber
      replacement = ",hd"
452 5397e0b7 Alexander Schreiber
    disk_data = [line.replace(",sd", replacement) for line in disk_data]
453 a21dda8b Iustin Pop
    if instance.hvm_cdrom_image_path is not None:
454 a21dda8b Iustin Pop
      iso = "'file:%s,hdc:cdrom,r'" % (instance.hvm_cdrom_image_path)
455 a21dda8b Iustin Pop
      disk_data.append(iso)
456 a21dda8b Iustin Pop
457 a21dda8b Iustin Pop
    config.write("disk = [%s]\n" % (",".join(disk_data)))
458 a21dda8b Iustin Pop
459 65a6f9b7 Michael Hanselmann
    config.write("on_poweroff = 'destroy'\n")
460 65a6f9b7 Michael Hanselmann
    config.write("on_reboot = 'restart'\n")
461 65a6f9b7 Michael Hanselmann
    config.write("on_crash = 'restart'\n")
462 65a6f9b7 Michael Hanselmann
    if extra_args:
463 65a6f9b7 Michael Hanselmann
      config.write("extra = '%s'\n" % extra_args)
464 65a6f9b7 Michael Hanselmann
    # just in case it exists
465 65a6f9b7 Michael Hanselmann
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
466 65a6f9b7 Michael Hanselmann
    try:
467 65a6f9b7 Michael Hanselmann
      f = open("/etc/xen/%s" % instance.name, "w")
468 65a6f9b7 Michael Hanselmann
      try:
469 65a6f9b7 Michael Hanselmann
        f.write(config.getvalue())
470 65a6f9b7 Michael Hanselmann
      finally:
471 65a6f9b7 Michael Hanselmann
        f.close()
472 65a6f9b7 Michael Hanselmann
    except IOError, err:
473 65a6f9b7 Michael Hanselmann
      raise errors.OpExecError("Cannot write Xen instance confile"
474 65a6f9b7 Michael Hanselmann
                               " file /etc/xen/%s: %s" % (instance.name, err))
475 65a6f9b7 Michael Hanselmann
    return True