Get rid of constants.RAPI_ENABLE
[ganeti-local] / lib / hypervisor / hv_base.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 import re
27
28
29 from ganeti import errors
30
31
32 class BaseHypervisor(object):
33   """Abstract virtualisation technology interface
34
35   The goal is that all aspects of the virtualisation technology are
36   abstracted away from the rest of code.
37
38   """
39   PARAMETERS = []
40
41   def __init__(self):
42     pass
43
44   def StartInstance(self, instance, block_devices):
45     """Start an instance."""
46     raise NotImplementedError
47
48   def StopInstance(self, instance, force=False):
49     """Stop an instance."""
50     raise NotImplementedError
51
52   def RebootInstance(self, instance):
53     """Reboot an instance."""
54     raise NotImplementedError
55
56   def ListInstances(self):
57     """Get the list of running instances."""
58     raise NotImplementedError
59
60   def GetInstanceInfo(self, instance_name):
61     """Get instance properties.
62
63     @type instance_name: string
64     @param instance_name: the instance name
65
66     @return: tuple (name, id, memory, vcpus, state, times)
67
68     """
69     raise NotImplementedError
70
71   def GetAllInstancesInfo(self):
72     """Get properties of all instances.
73
74     @return: list of tuples (name, id, memory, vcpus, stat, times)
75
76     """
77     raise NotImplementedError
78
79   def GetNodeInfo(self):
80     """Return information about the node.
81
82     @return: a dict with the following keys (values in MiB):
83           - memory_total: the total memory size on the node
84           - memory_free: the available memory on the node for instances
85           - memory_dom0: the memory used by the node itself, if available
86
87     """
88     raise NotImplementedError
89
90   @classmethod
91   def GetShellCommandForConsole(cls, instance, hvparams, beparams):
92     """Return a command for connecting to the console of an instance.
93
94     """
95     raise NotImplementedError
96
97   def Verify(self):
98     """Verify the hypervisor.
99
100     """
101     raise NotImplementedError
102
103   def MigrationInfo(self, instance):
104     """Get instance information to perform a migration.
105
106     By default assume no information is needed.
107
108     @type instance: L{objects.Instance}
109     @param instance: instance to be migrated
110     @rtype: string/data (opaque)
111     @return: instance migration information - serialized form
112
113     """
114     return ''
115
116   def AcceptInstance(self, instance, info, target):
117     """Prepare to accept an instance.
118
119     By default assume no preparation is needed.
120
121     @type instance: L{objects.Instance}
122     @param instance: instance to be accepted
123     @type info: string/data (opaque)
124     @param info: migration information, from the source node
125     @type target: string
126     @param target: target host (usually ip), on this node
127
128     """
129     pass
130
131   def FinalizeMigration(self, instance, info, success):
132     """Finalized an instance migration.
133
134     Should finalize or revert any preparation done to accept the instance.
135     Since by default we do no preparation, we also don't have anything to do
136
137     @type instance: L{objects.Instance}
138     @param instance: instance whose migration is being aborted
139     @type info: string/data (opaque)
140     @param info: migration information, from the source node
141     @type success: boolean
142     @param success: whether the migration was a success or a failure
143
144     """
145     pass
146
147   def MigrateInstance(self, name, target, live):
148     """Migrate an instance.
149
150     @type name: string
151     @param name: name of the instance to be migrated
152     @type target: string
153     @param target: hostname (usually ip) of the target node
154     @type live: boolean
155     @param live: whether to do a live or non-live migration
156
157     """
158     raise NotImplementedError
159
160   @classmethod
161   def CheckParameterSyntax(cls, hvparams):
162     """Check the given parameters for validity.
163
164     This should check the passed set of parameters for
165     validity. Classes should extend, not replace, this function.
166
167     @type hvparams:  dict
168     @param hvparams: dictionary with parameter names/value
169     @raise errors.HypervisorError: when a parameter is not valid
170
171     """
172     for key in hvparams:
173       if key not in cls.PARAMETERS:
174         raise errors.HypervisorError("Hypervisor parameter '%s'"
175                                      " not supported" % key)
176     for key in cls.PARAMETERS:
177       if key not in hvparams:
178         raise errors.HypervisorError("Hypervisor parameter '%s'"
179                                      " missing" % key)
180
181   def ValidateParameters(self, hvparams):
182     """Check the given parameters for validity.
183
184     This should check the passed set of parameters for
185     validity. Classes should extend, not replace, this function.
186
187     @type hvparams:  dict
188     @param hvparams: dictionary with parameter names/value
189     @raise errors.HypervisorError: when a parameter is not valid
190
191     """
192     pass
193
194   def GetLinuxNodeInfo(self):
195     """For linux systems, return actual OS information.
196
197     This is an abstraction for all non-hypervisor-based classes, where
198     the node actually sees all the memory and CPUs via the /proc
199     interface and standard commands. The other case if for example
200     xen, where you only see the hardware resources via xen-specific
201     tools.
202
203     @return: a dict with the following keys (values in MiB):
204           - memory_total: the total memory size on the node
205           - memory_free: the available memory on the node for instances
206           - memory_dom0: the memory used by the node itself, if available
207
208     """
209     try:
210       fh = file("/proc/meminfo")
211       try:
212         data = fh.readlines()
213       finally:
214         fh.close()
215     except EnvironmentError, err:
216       raise errors.HypervisorError("Failed to list node info: %s" % (err,))
217
218     result = {}
219     sum_free = 0
220     try:
221       for line in data:
222         splitfields = line.split(":", 1)
223
224         if len(splitfields) > 1:
225           key = splitfields[0].strip()
226           val = splitfields[1].strip()
227           if key == 'MemTotal':
228             result['memory_total'] = int(val.split()[0])/1024
229           elif key in ('MemFree', 'Buffers', 'Cached'):
230             sum_free += int(val.split()[0])/1024
231           elif key == 'Active':
232             result['memory_dom0'] = int(val.split()[0])/1024
233     except (ValueError, TypeError), err:
234       raise errors.HypervisorError("Failed to compute memory usage: %s" %
235                                    (err,))
236     result['memory_free'] = sum_free
237
238     cpu_total = 0
239     try:
240       fh = open("/proc/cpuinfo")
241       try:
242         cpu_total = len(re.findall("(?m)^processor\s*:\s*[0-9]+\s*$",
243                                    fh.read()))
244       finally:
245         fh.close()
246     except EnvironmentError, err:
247       raise errors.HypervisorError("Failed to list node info: %s" % (err,))
248     result['cpu_total'] = cpu_total
249     # FIXME: export correct data here
250     result['cpu_nodes'] = 1
251     result['cpu_sockets'] = 1
252
253     return result