Misc s/func/certmaster/ replacements
[certmaster.git] / certmaster / minion / modules / virt.py
1 """
2 Virt management features
3
4 Copyright 2007, Red Hat, Inc
5 Michael DeHaan <mdehaan@redhat.com>
6
7 This software may be freely redistributed under the terms of the GNU
8 general public license.
9
10 You should have received a copy of the GNU General Public License
11 along with this program; if not, write to the Free Software
12 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
13 """
14
15 # warning: virt management is rather complicated
16 # to see a simple example of func, look at the
17 # service control module. API docs on how
18 # to use this to come.
19
20 # other modules
21 import os
22 import sub_process
23 import libvirt
24
25 # our modules
26 import codes
27 import func_module
28
29 VIRT_STATE_NAME_MAP = {
30 0 : "running",
31 1 : "running",
32 2 : "running",
33 3 : "paused",
34 4 : "shutdown",
35 5 : "shutdown",
36 6 : "crashed"
37 }
38
39 class FuncLibvirtConnection(object):
40
41 version = "0.0.1"
42 api_version = "0.0.1"
43 description = "Virtualization items through func."
44
45 def __init__(self):
46
47 cmd = sub_process.Popen("uname -r", shell=True, stdout=sub_process.PIPE)
48 output = cmd.communicate()[0]
49
50 if output.find("xen") != -1:
51 conn = libvirt.open(None)
52 else:
53 conn = libvirt.open("qemu:///system")
54
55 if not conn:
56 raise codes.FuncException("hypervisor connection failure")
57
58 self.conn = conn
59
60 def find_vm(self, vmid):
61 """
62 Extra bonus feature: vmid = -1 returns a list of everything
63 """
64 conn = self.conn
65
66 vms = []
67
68 # this block of code borrowed from virt-manager:
69 # get working domain's name
70 ids = conn.listDomainsID();
71 for id in ids:
72 vm = conn.lookupByID(id)
73 vms.append(vm)
74 # get defined domain
75 names = conn.listDefinedDomains()
76 for name in names:
77 vm = conn.lookupByName(name)
78 vms.append(vm)
79
80 if vmid == -1:
81 return vms
82
83 for vm in vms:
84 if vm.name() == vmid:
85 return vm
86
87 raise codes.FuncException("virtual machine %s not found" % vmid)
88
89 def shutdown(self, vmid):
90 return self.find_vm(vmid).shutdown()
91
92 def pause(self, vmid):
93 return self.suspend(self.conn,vmid)
94
95 def unpause(self, vmid):
96 return self.resume(self.conn,vmid)
97
98 def suspend(self, vmid):
99 return self.find_vm(vmid).suspend()
100
101 def resume(self, vmid):
102 return self.find_vm(vmid).resume()
103
104 def create(self, vmid):
105 return self.find_vm(vmid).create()
106
107 def destroy(self, vmid):
108 return self.find_vm(vmid).destroy()
109
110 def undefine(self, vmid):
111 return self.find_vm(vmid).undefine()
112
113 def get_status2(self, vm):
114 state = vm.info()[0]
115 # print "DEBUG: state: %s" % state
116 return VIRT_STATE_NAME_MAP.get(state,"unknown")
117
118 def get_status(self, vmid):
119 state = self.find_vm(vmid).info()[0]
120 return VIRT_STATE_NAME_MAP.get(state,"unknown")
121
122
123
124 class Virt(func_module.FuncModule):
125
126 def __get_conn(self):
127 self.conn = FuncLibvirtConnection()
128 return self.conn
129
130 def state(self):
131 vms = self.list_vms()
132 state = []
133 for vm in vms:
134 state_blurb = self.conn.get_status(vm)
135 state.append("%s %s" % (vm,state_blurb))
136 return state
137
138
139 def info(self):
140 vms = self.list_vms()
141 info = dict()
142 for vm in vms:
143 data = self.conn.find_vm(vm).info()
144 # libvirt returns maxMem, memory, and cpuTime as long()'s, which
145 # xmlrpclib tries to convert to regular int's during serialization.
146 # This throws exceptions, so convert them to strings here and
147 # assume the other end of the xmlrpc connection can figure things
148 # out or doesn't care.
149 info[vm] = {
150 "state" : VIRT_STATE_NAME_MAP.get(data[0],"unknown"),
151 "maxMem" : str(data[1]),
152 "memory" : str(data[2]),
153 "nrVirtCpu" : data[3],
154 "cpuTime" : str(data[4])
155 }
156 return info
157
158
159 def list_vms(self):
160 self.conn = self.__get_conn()
161 vms = self.conn.find_vm(-1)
162 results = []
163 for x in vms:
164 try:
165 results.append(x.name())
166 except:
167 pass
168 return results
169
170 def install(self, server_name, target_name, system=False):
171
172 """
173 Install a new virt system by way of a named cobbler profile.
174 """
175
176 # Example:
177 # install("bootserver.example.org", "fc7webserver", True)
178
179 conn = self.__get_conn()
180
181 if conn is None:
182 raise codes.FuncException("no connection")
183
184 if not os.path.exists("/usr/bin/koan"):
185 raise codes.FuncException("no /usr/bin/koan")
186 target = "profile"
187 if system:
188 target = "system"
189
190 # TODO: FUTURE: set --virt-path in cobbler or here
191 koan_args = [
192 "/usr/bin/koan",
193 "--virt",
194 "--virt-graphics", # enable VNC
195 "--%s=%s" % (target, target_name),
196 "--server=%s" % server_name
197 ]
198
199 rc = sub_process.call(koan_args,shell=False)
200 if rc == 0:
201 return 0
202 else:
203 raise codes.FuncException("koan returned %d" % rc)
204
205
206 def shutdown(self, vmid):
207 """
208 Make the machine with the given vmid stop running.
209 Whatever that takes.
210 """
211 self.__get_conn()
212 self.conn.shutdown(vmid)
213 return 0
214
215
216 def pause(self, vmid):
217
218 """
219 Pause the machine with the given vmid.
220 """
221 self.__get_conn()
222 self.conn.suspend(vmid)
223 return 0
224
225
226 def unpause(self, vmid):
227
228 """
229 Unpause the machine with the given vmid.
230 """
231
232 self.__get_conn()
233 self.conn.resume(vmid)
234 return 0
235
236
237 def create(self, vmid):
238
239 """
240 Start the machine via the given mac address.
241 """
242 self.__get_conn()
243 self.conn.create(vmid)
244 return 0
245
246
247 def destroy(self, vmid):
248
249 """
250 Pull the virtual power from the virtual domain, giving it virtually no
251 time to virtually shut down.
252 """
253 self.__get_conn()
254 self.conn.destroy(vmid)
255 return 0
256
257
258 def undefine(self, vmid):
259
260 """
261 Stop a domain, and then wipe it from the face of the earth.
262 by deleting the disk image and it's configuration file.
263 """
264
265 self.__get_conn()
266 self.conn.undefine(vmid)
267 return 0
268
269
270 def get_status(self, vmid):
271
272 """
273 Return a state suitable for server consumption. Aka, codes.py values, not XM output.
274 """
275
276 self.__get_conn()
277 return self.conn.get_status(vmid)