Revision 65a6f9b7

b/Makefile.am
9 9

  
10 10
pre-check: ganeti
11 11
	$(MAKE) -C lib $@
12
	$(MAKE) -C lib/hypervisor $@
12 13

  
13 14
# a dist hook rule for catching revision control directories
14 15
distcheck-hook:
b/configure.ac
117 117
  doc/Makefile
118 118
  doc/examples/Makefile
119 119
  lib/Makefile
120
  lib/hypervisor/Makefile
120 121
  man/Makefile
121 122
  qa/Makefile
122 123
  qa/hooks/Makefile
b/lib/Makefile.am
1 1
CLEANFILES = $(nodist_pkgpython_PYTHON) *.py[oc]
2
SUBDIRS = hypervisor
2 3

  
3 4
nodist_pkgpython_PYTHON = _autoconf.py
4 5
pkgpython_PYTHON = __init__.py backend.py cli.py cmdlib.py config.py \
5 6
	objects.py errors.py logger.py ssh.py utils.py rpc.py \
6
	bdev.py hypervisor.py opcodes.py mcpu.py constants.py \
7
	bdev.py opcodes.py mcpu.py constants.py \
7 8
	ssconf.py locking.py luxi.py jqueue.py serializer.py
8 9
python_files = $(pkgpython_PYTHON)
9 10

  
b/lib/hypervisor/BaseHypervisor.py
1
#
2
#
3

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

  
21

  
22
"""Base class for all hypervisors
23

  
24
"""
25

  
26
class BaseHypervisor(object):
27
  """Abstract virtualisation technology interface
28

  
29
  The goal is that all aspects of the virtualisation technology must
30
  be abstracted away from the rest of code.
31

  
32
  """
33
  def __init__(self):
34
    pass
35

  
36
  def StartInstance(self, instance, block_devices, extra_args):
37
    """Start an instance."""
38
    raise NotImplementedError
39

  
40
  def StopInstance(self, instance, force=False):
41
    """Stop an instance."""
42
    raise NotImplementedError
43

  
44
  def RebootInstance(self, instance):
45
    """Reboot an instance."""
46
    raise NotImplementedError
47

  
48
  def ListInstances(self):
49
    """Get the list of running instances."""
50
    raise NotImplementedError
51

  
52
  def GetInstanceInfo(self, instance_name):
53
    """Get instance properties.
54

  
55
    Args:
56
      instance_name: the instance name
57

  
58
    Returns:
59
      (name, id, memory, vcpus, state, times)
60

  
61
    """
62
    raise NotImplementedError
63

  
64
  def GetAllInstancesInfo(self):
65
    """Get properties of all instances.
66

  
67
    Returns:
68
      [(name, id, memory, vcpus, stat, times),...]
69
    """
70
    raise NotImplementedError
71

  
72
  def GetNodeInfo(self):
73
    """Return information about the node.
74

  
75
    The return value is a dict, which has to have the following items:
76
      (all values in MiB)
77
      - memory_total: the total memory size on the node
78
      - memory_free: the available memory on the node for instances
79
      - memory_dom0: the memory used by the node itself, if available
80

  
81
    """
82
    raise NotImplementedError
83

  
84
  @staticmethod
85
  def GetShellCommandForConsole(instance):
86
    """Return a command for connecting to the console of an instance.
87

  
88
    """
89
    raise NotImplementedError
90

  
91
  def Verify(self):
92
    """Verify the hypervisor.
93

  
94
    """
95
    raise NotImplementedError
b/lib/hypervisor/FakeHypervisor.py
1
#
2
#
3

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

  
21

  
22
"""Fake hypervisor
23

  
24
"""
25

  
26
import os
27
import os.path
28

  
29
from ganeti import utils
30
from ganeti import constants
31
from ganeti import errors
32
from ganeti.hypervisor import BaseHypervisor
33

  
34

  
35
class FakeHypervisor(BaseHypervisor.BaseHypervisor):
36
  """Fake hypervisor interface.
37

  
38
  This can be used for testing the ganeti code without having to have
39
  a real virtualisation software installed.
40

  
41
  """
42
  _ROOT_DIR = constants.RUN_DIR + "/ganeti-fake-hypervisor"
43

  
44
  def __init__(self):
45
    BaseHypervisor.__init__(self)
46
    if not os.path.exists(self._ROOT_DIR):
47
      os.mkdir(self._ROOT_DIR)
48

  
49
  def ListInstances(self):
50
    """Get the list of running instances.
51

  
52
    """
53
    return os.listdir(self._ROOT_DIR)
54

  
55
  def GetInstanceInfo(self, instance_name):
56
    """Get instance properties.
57

  
58
    Args:
59
      instance_name: the instance name
60

  
61
    Returns:
62
      (name, id, memory, vcpus, stat, times)
63
    """
64
    file_name = "%s/%s" % (self._ROOT_DIR, instance_name)
65
    if not os.path.exists(file_name):
66
      return None
67
    try:
68
      fh = file(file_name, "r")
69
      try:
70
        inst_id = fh.readline().strip()
71
        memory = fh.readline().strip()
72
        vcpus = fh.readline().strip()
73
        stat = "---b-"
74
        times = "0"
75
        return (instance_name, inst_id, memory, vcpus, stat, times)
76
      finally:
77
        fh.close()
78
    except IOError, err:
79
      raise errors.HypervisorError("Failed to list instance %s: %s" %
80
                                   (instance_name, err))
81

  
82
  def GetAllInstancesInfo(self):
83
    """Get properties of all instances.
84

  
85
    Returns:
86
      [(name, id, memory, vcpus, stat, times),...]
87
    """
88
    data = []
89
    for file_name in os.listdir(self._ROOT_DIR):
90
      try:
91
        fh = file(self._ROOT_DIR+"/"+file_name, "r")
92
        inst_id = "-1"
93
        memory = "0"
94
        stat = "-----"
95
        times = "-1"
96
        try:
97
          inst_id = fh.readline().strip()
98
          memory = fh.readline().strip()
99
          vcpus = fh.readline().strip()
100
          stat = "---b-"
101
          times = "0"
102
        finally:
103
          fh.close()
104
        data.append((file_name, inst_id, memory, vcpus, stat, times))
105
      except IOError, err:
106
        raise errors.HypervisorError("Failed to list instances: %s" % err)
107
    return data
108

  
109
  def StartInstance(self, instance, force, extra_args):
110
    """Start an instance.
111

  
112
    For the fake hypervisor, it just creates a file in the base dir,
113
    creating an exception if it already exists. We don't actually
114
    handle race conditions properly, since these are *FAKE* instances.
115

  
116
    """
117
    file_name = self._ROOT_DIR + "/%s" % instance.name
118
    if os.path.exists(file_name):
119
      raise errors.HypervisorError("Failed to start instance %s: %s" %
120
                                   (instance.name, "already running"))
121
    try:
122
      fh = file(file_name, "w")
123
      try:
124
        fh.write("0\n%d\n%d\n" % (instance.memory, instance.vcpus))
125
      finally:
126
        fh.close()
127
    except IOError, err:
128
      raise errors.HypervisorError("Failed to start instance %s: %s" %
129
                                   (instance.name, err))
130

  
131
  def StopInstance(self, instance, force=False):
132
    """Stop an instance.
133

  
134
    For the fake hypervisor, this just removes the file in the base
135
    dir, if it exist, otherwise we raise an exception.
136

  
137
    """
138
    file_name = self._ROOT_DIR + "/%s" % instance.name
139
    if not os.path.exists(file_name):
140
      raise errors.HypervisorError("Failed to stop instance %s: %s" %
141
                                   (instance.name, "not running"))
142
    utils.RemoveFile(file_name)
143

  
144
  def RebootInstance(self, instance):
145
    """Reboot an instance.
146

  
147
    For the fake hypervisor, this does nothing.
148

  
149
    """
150
    return
151

  
152
  def GetNodeInfo(self):
153
    """Return information about the node.
154

  
155
    The return value is a dict, which has to have the following items:
156
      (all values in MiB)
157
      - memory_total: the total memory size on the node
158
      - memory_free: the available memory on the node for instances
159
      - memory_dom0: the memory used by the node itself, if available
160

  
161
    """
162
    # global ram usage from the xm info command
163
    # memory                 : 3583
164
    # free_memory            : 747
165
    # note: in xen 3, memory has changed to total_memory
166
    try:
167
      fh = file("/proc/meminfo")
168
      try:
169
        data = fh.readlines()
170
      finally:
171
        fh.close()
172
    except IOError, err:
173
      raise errors.HypervisorError("Failed to list node info: %s" % err)
174

  
175
    result = {}
176
    sum_free = 0
177
    for line in data:
178
      splitfields = line.split(":", 1)
179

  
180
      if len(splitfields) > 1:
181
        key = splitfields[0].strip()
182
        val = splitfields[1].strip()
183
        if key == 'MemTotal':
184
          result['memory_total'] = int(val.split()[0])/1024
185
        elif key in ('MemFree', 'Buffers', 'Cached'):
186
          sum_free += int(val.split()[0])/1024
187
        elif key == 'Active':
188
          result['memory_dom0'] = int(val.split()[0])/1024
189

  
190
    result['memory_free'] = sum_free
191
    return result
192

  
193
  @staticmethod
194
  def GetShellCommandForConsole(instance):
195
    """Return a command for connecting to the console of an instance.
196

  
197
    """
198
    return "echo Console not available for fake hypervisor"
199

  
200
  def Verify(self):
201
    """Verify the hypervisor.
202

  
203
    For the fake hypervisor, it just checks the existence of the base
204
    dir.
205

  
206
    """
207
    if not os.path.exists(self._ROOT_DIR):
208
      return "The required directory '%s' does not exist." % self._ROOT_DIR
b/lib/hypervisor/Makefile.am
1
CLEANFILES = *.py[oc]
2

  
3
hypervisordir = $(pkgpythondir)/hypervisor
4
hypervisor_PYTHON = __init__.py XenHypervisor.py FakeHypervisor.py \
5
	BaseHypervisor.py
6
python_files = $(hypervisor_PYTHON)
7

  
8
include $(srcdir)/../Makefile.libcommon
b/lib/hypervisor/XenHypervisor.py
1
#
2
#
3

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

  
21

  
22
"""Xen hypervisors
23

  
24
"""
25

  
26
import os
27
import os.path
28
import time
29
from cStringIO import StringIO
30

  
31
from ganeti import constants
32
from ganeti import errors
33
from ganeti import logger
34
from ganeti import utils
35
from ganeti.hypervisor import BaseHypervisor
36

  
37

  
38
class XenHypervisor(BaseHypervisor.BaseHypervisor):
39
  """Xen generic hypervisor interface
40

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

  
44
  """
45

  
46
  @staticmethod
47
  def _WriteConfigFile(instance, block_devices, extra_args):
48
    """Write the Xen config file for the instance.
49

  
50
    """
51
    raise NotImplementedError
52

  
53
  @staticmethod
54
  def _RemoveConfigFile(instance):
55
    """Remove the xen configuration file.
56

  
57
    """
58
    utils.RemoveFile("/etc/xen/%s" % instance.name)
59

  
60
  @staticmethod
61
  def _GetXMList(include_node):
62
    """Return the list of running instances.
63

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

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

  
69
    """
70
    for dummy in range(5):
71
      result = utils.RunCmd(["xm", "list"])
72
      if not result.failed:
73
        break
74
      logger.Error("xm list failed (%s): %s" % (result.fail_reason,
75
                                                result.output))
76
      time.sleep(1)
77

  
78
    if result.failed:
79
      raise errors.HypervisorError("xm list failed, retries"
80
                                   " exceeded (%s): %s" %
81
                                   (result.fail_reason, result.stderr))
82

  
83
    # skip over the heading
84
    lines = result.stdout.splitlines()[1:]
85
    result = []
86
    for line in lines:
87
      # The format of lines is:
88
      # Name      ID Mem(MiB) VCPUs State  Time(s)
89
      # Domain-0   0  3418     4 r-----    266.2
90
      data = line.split()
91
      if len(data) != 6:
92
        raise errors.HypervisorError("Can't parse output of xm list,"
93
                                     " line: %s" % line)
94
      try:
95
        data[1] = int(data[1])
96
        data[2] = int(data[2])
97
        data[3] = int(data[3])
98
        data[5] = float(data[5])
99
      except ValueError, err:
100
        raise errors.HypervisorError("Can't parse output of xm list,"
101
                                     " line: %s, error: %s" % (line, err))
102

  
103
      # skip the Domain-0 (optional)
104
      if include_node or data[0] != 'Domain-0':
105
        result.append(data)
106

  
107
    return result
108

  
109
  def ListInstances(self):
110
    """Get the list of running instances.
111

  
112
    """
113
    xm_list = self._GetXMList(False)
114
    names = [info[0] for info in xm_list]
115
    return names
116

  
117
  def GetInstanceInfo(self, instance_name):
118
    """Get instance properties.
119

  
120
    Args:
121
      instance_name: the instance name
122

  
123
    Returns:
124
      (name, id, memory, vcpus, stat, times)
125
    """
126
    xm_list = self._GetXMList(instance_name=="Domain-0")
127
    result = None
128
    for data in xm_list:
129
      if data[0] == instance_name:
130
        result = data
131
        break
132
    return result
133

  
134
  def GetAllInstancesInfo(self):
135
    """Get properties of all instances.
136

  
137
    Returns:
138
      [(name, id, memory, vcpus, stat, times),...]
139
    """
140
    xm_list = self._GetXMList(False)
141
    return xm_list
142

  
143
  def StartInstance(self, instance, block_devices, extra_args):
144
    """Start an instance."""
145
    self._WriteConfigFile(instance, block_devices, extra_args)
146
    result = utils.RunCmd(["xm", "create", instance.name])
147

  
148
    if result.failed:
149
      raise errors.HypervisorError("Failed to start instance %s: %s (%s)" %
150
                                   (instance.name, result.fail_reason,
151
                                    result.output))
152

  
153
  def StopInstance(self, instance, force=False):
154
    """Stop an instance."""
155
    self._RemoveConfigFile(instance)
156
    if force:
157
      command = ["xm", "destroy", instance.name]
158
    else:
159
      command = ["xm", "shutdown", instance.name]
160
    result = utils.RunCmd(command)
161

  
162
    if result.failed:
163
      raise errors.HypervisorError("Failed to stop instance %s: %s" %
164
                                   (instance.name, result.fail_reason))
165

  
166
  def RebootInstance(self, instance):
167
    """Reboot an instance."""
168
    result = utils.RunCmd(["xm", "reboot", instance.name])
169

  
170
    if result.failed:
171
      raise errors.HypervisorError("Failed to reboot instance %s: %s" %
172
                                   (instance.name, result.fail_reason))
173

  
174
  def GetNodeInfo(self):
175
    """Return information about the node.
176

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

  
183
    """
184
    # note: in xen 3, memory has changed to total_memory
185
    result = utils.RunCmd(["xm", "info"])
186
    if result.failed:
187
      logger.Error("Can't run 'xm info': %s" % result.fail_reason)
188
      return None
189

  
190
    xmoutput = result.stdout.splitlines()
191
    result = {}
192
    for line in xmoutput:
193
      splitfields = line.split(":", 1)
194

  
195
      if len(splitfields) > 1:
196
        key = splitfields[0].strip()
197
        val = splitfields[1].strip()
198
        if key == 'memory' or key == 'total_memory':
199
          result['memory_total'] = int(val)
200
        elif key == 'free_memory':
201
          result['memory_free'] = int(val)
202
    dom0_info = self.GetInstanceInfo("Domain-0")
203
    if dom0_info is not None:
204
      result['memory_dom0'] = dom0_info[2]
205

  
206
    return result
207

  
208
  @staticmethod
209
  def GetShellCommandForConsole(instance):
210
    """Return a command for connecting to the console of an instance.
211

  
212
    """
213
    raise NotImplementedError
214

  
215

  
216
  def Verify(self):
217
    """Verify the hypervisor.
218

  
219
    For Xen, this verifies that the xend process is running.
220

  
221
    """
222
    if not utils.CheckDaemonAlive('/var/run/xend.pid', 'xend'):
223
      return "xend daemon is not running"
224

  
225
  @staticmethod
226
  def _GetConfigFileDiskData(disk_template, block_devices):
227
    """Get disk directive for xen config file.
228

  
229
    This method builds the xen config disk directive according to the
230
    given disk_template and block_devices.
231

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

  
239
    Returns:
240
      String containing disk directive for xen instance config file
241

  
242
    """
243
    FILE_DRIVER_MAP = {
244
      constants.FD_LOOP: "file",
245
      constants.FD_BLKTAP: "tap:aio",
246
      }
247
    disk_data = []
248
    for cfdev, rldev in block_devices:
249
      if cfdev.dev_type == constants.LD_FILE:
250
        line = "'%s:%s,%s,w'" % (FILE_DRIVER_MAP[cfdev.physical_id[0]],
251
                                 rldev.dev_path, cfdev.iv_name)
252
      else:
253
        line = "'phy:%s,%s,w'" % (rldev.dev_path, cfdev.iv_name)
254
      disk_data.append(line)
255

  
256
    return disk_data
257

  
258

  
259
class XenPvmHypervisor(XenHypervisor):
260
  """Xen PVM hypervisor interface"""
261

  
262
  @classmethod
263
  def _WriteConfigFile(cls, instance, block_devices, extra_args):
264
    """Write the Xen config file for the instance.
265

  
266
    """
267
    config = StringIO()
268
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
269

  
270
    # kernel handling
271
    if instance.kernel_path in (None, constants.VALUE_DEFAULT):
272
      kpath = constants.XEN_KERNEL
273
    else:
274
      if not os.path.exists(instance.kernel_path):
275
        raise errors.HypervisorError("The kernel %s for instance %s is"
276
                                     " missing" % (instance.kernel_path,
277
                                                   instance.name))
278
      kpath = instance.kernel_path
279
    config.write("kernel = '%s'\n" % kpath)
280

  
281
    # initrd handling
282
    if instance.initrd_path in (None, constants.VALUE_DEFAULT):
283
      if os.path.exists(constants.XEN_INITRD):
284
        initrd_path = constants.XEN_INITRD
285
      else:
286
        initrd_path = None
287
    elif instance.initrd_path == constants.VALUE_NONE:
288
      initrd_path = None
289
    else:
290
      if not os.path.exists(instance.initrd_path):
291
        raise errors.HypervisorError("The initrd %s for instance %s is"
292
                                     " missing" % (instance.initrd_path,
293
                                                   instance.name))
294
      initrd_path = instance.initrd_path
295

  
296
    if initrd_path:
297
      config.write("ramdisk = '%s'\n" % initrd_path)
298

  
299
    # rest of the settings
300
    config.write("memory = %d\n" % instance.memory)
301
    config.write("vcpus = %d\n" % instance.vcpus)
302
    config.write("name = '%s'\n" % instance.name)
303

  
304
    vif_data = []
305
    for nic in instance.nics:
306
      nic_str = "mac=%s, bridge=%s" % (nic.mac, nic.bridge)
307
      ip = getattr(nic, "ip", None)
308
      if ip is not None:
309
        nic_str += ", ip=%s" % ip
310
      vif_data.append("'%s'" % nic_str)
311

  
312
    config.write("vif = [%s]\n" % ",".join(vif_data))
313
    config.write("disk = [%s]\n" % ",".join(
314
                 cls._GetConfigFileDiskData(instance.disk_template,
315
                                            block_devices)))
316
    config.write("root = '/dev/sda ro'\n")
317
    config.write("on_poweroff = 'destroy'\n")
318
    config.write("on_reboot = 'restart'\n")
319
    config.write("on_crash = 'restart'\n")
320
    if extra_args:
321
      config.write("extra = '%s'\n" % extra_args)
322
    # just in case it exists
323
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
324
    try:
325
      f = open("/etc/xen/%s" % instance.name, "w")
326
      try:
327
        f.write(config.getvalue())
328
      finally:
329
        f.close()
330
    except IOError, err:
331
      raise errors.OpExecError("Cannot write Xen instance confile"
332
                               " file /etc/xen/%s: %s" % (instance.name, err))
333
    return True
334

  
335
  @staticmethod
336
  def GetShellCommandForConsole(instance):
337
    """Return a command for connecting to the console of an instance.
338

  
339
    """
340
    return "xm console %s" % instance.name
341

  
342

  
343
class XenHvmHypervisor(XenHypervisor):
344
  """Xen HVM hypervisor interface"""
345

  
346
  @classmethod
347
  def _WriteConfigFile(cls, instance, block_devices, extra_args):
348
    """Create a Xen 3.1 HVM config file.
349

  
350
    """
351
    config = StringIO()
352
    config.write("# this is autogenerated by Ganeti, please do not edit\n#\n")
353
    config.write("kernel = '/usr/lib/xen/boot/hvmloader'\n")
354
    config.write("builder = 'hvm'\n")
355
    config.write("memory = %d\n" % instance.memory)
356
    config.write("vcpus = %d\n" % instance.vcpus)
357
    config.write("name = '%s'\n" % instance.name)
358
    config.write("pae = 1\n")
359
    config.write("acpi = 1\n")
360
    config.write("apic = 1\n")
361
    arch = os.uname()[4]
362
    if '64' in arch:
363
      config.write("device_model = '/usr/lib64/xen/bin/qemu-dm'\n")
364
    else:
365
      config.write("device_model = '/usr/lib/xen/bin/qemu-dm'\n")
366
    if instance.hvm_boot_order is None:
367
      config.write("boot = '%s'\n" % constants.HT_HVM_DEFAULT_BOOT_ORDER)
368
    else:
369
      config.write("boot = '%s'\n" % instance.hvm_boot_order)
370
    config.write("sdl = 0\n")
371
    config.write("usb = 1\n");
372
    config.write("usbdevice = 'tablet'\n");
373
    config.write("vnc = 1\n")
374
    config.write("vnclisten = '0.0.0.0'\n")
375

  
376
    if instance.network_port > constants.HT_HVM_VNC_BASE_PORT:
377
      display = instance.network_port - constants.HT_HVM_VNC_BASE_PORT
378
      config.write("vncdisplay = %s\n" % display)
379
      config.write("vncunused = 0\n")
380
    else:
381
      config.write("# vncdisplay = 1\n")
382
      config.write("vncunused = 1\n")
383

  
384
    try:
385
      password_file = open(constants.VNC_PASSWORD_FILE, "r")
386
      try:
387
        password = password_file.readline()
388
      finally:
389
        password_file.close()
390
    except IOError:
391
      raise errors.OpExecError("failed to open VNC password file %s " %
392
                               constants.VNC_PASSWORD_FILE)
393

  
394
    config.write("vncpasswd = '%s'\n" % password.rstrip())
395

  
396
    config.write("serial = 'pty'\n")
397
    config.write("localtime = 1\n")
398

  
399
    vif_data = []
400
    for nic in instance.nics:
401
      nic_str = "mac=%s, bridge=%s, type=ioemu" % (nic.mac, nic.bridge)
402
      ip = getattr(nic, "ip", None)
403
      if ip is not None:
404
        nic_str += ", ip=%s" % ip
405
      vif_data.append("'%s'" % nic_str)
406

  
407
    config.write("vif = [%s]\n" % ",".join(vif_data))
408
    iso = "'file:/srv/ganeti/iso/hvm-install.iso,hdc:cdrom,r'"
409
    config.write("disk = [%s, %s]\n" % (",".join(
410
                 cls._GetConfigFileDiskData(instance.disk_template,
411
                                            block_devices)), iso))
412
    config.write("on_poweroff = 'destroy'\n")
413
    config.write("on_reboot = 'restart'\n")
414
    config.write("on_crash = 'restart'\n")
415
    if extra_args:
416
      config.write("extra = '%s'\n" % extra_args)
417
    # just in case it exists
418
    utils.RemoveFile("/etc/xen/auto/%s" % instance.name)
419
    try:
420
      f = open("/etc/xen/%s" % instance.name, "w")
421
      try:
422
        f.write(config.getvalue())
423
      finally:
424
        f.close()
425
    except IOError, err:
426
      raise errors.OpExecError("Cannot write Xen instance confile"
427
                               " file /etc/xen/%s: %s" % (instance.name, err))
428
    return True
429

  
430
  @staticmethod
431
  def GetShellCommandForConsole(instance):
432
    """Return a command for connecting to the console of an instance.
433

  
434
    """
435
    if instance.network_port is None:
436
      raise errors.OpExecError("no console port defined for %s"
437
                               % instance.name)
438
    else:
439
      raise errors.OpExecError("no PTY console, connect to %s:%s via VNC"
440
                               % (instance.primary_node,
441
                                  instance.network_port))
b/lib/hypervisor/__init__.py
1
#
2
#
3

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

  
21

  
22
"""Virtualization interface abstraction
23

  
24
"""
25

  
26
from ganeti import ssconf
27
from ganeti import constants
28
from ganeti import errors
29

  
30
from ganeti.hypervisor import FakeHypervisor
31
from ganeti.hypervisor import XenHypervisor
32

  
33

  
34
def GetHypervisor():
35
  """Return a Hypervisor instance.
36

  
37
  This function parses the cluster hypervisor configuration file and
38
  instantiates a class based on the value of this file.
39

  
40
  """
41
  ht_kind = ssconf.SimpleStore().GetHypervisorType()
42
  if ht_kind == constants.HT_XEN_PVM30:
43
    cls = XenHypervisor.XenPvmHypervisor
44
  elif ht_kind == constants.HT_XEN_HVM31:
45
    cls = XenHypervisor.XenHvmHypervisor
46
  elif ht_kind == constants.HT_FAKE:
47
    cls = FakeHypervisor.FakeHypervisor
48
  else:
49
    raise errors.HypervisorError("Unknown hypervisor type '%s'" % ht_kind)
50
  return cls()

Also available in: Unified diff