25854a987a754440ce39d8b15d48f1904e30bca4
[php-virt-control.git] / classes / libvirt-domain.php
1 <?php
2         class LibvirtDomain extends LoggerBase {
3                 private $data = false;
4                 private $lang = false;
5                 private $lv = false;
6
7                 function LibvirtDomain($libvirtInstance, $languageInstance, $action = false, $input = array()) {
8                         $this->lv = $libvirtInstance;
9                         $this->lang = $languageInstance;
10
11                         if ($action)
12                                 $this->_processAction($action, $input);
13                 }
14
15                 function getData() {
16                         if (!$this->data)
17                                 return $this->log(TYPE_INFO, __CLASS__.'::'.__FUNCTION__, 'No data', 'No data set yet');
18
19                         return $this->data;
20                 }
21
22                 function _processAction($action, $input = array()) {
23                         if (!$action)
24                                 return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'No action defined', 'Cannot process empty action');
25
26                         $msg = false;
27                         $frm = false;
28                         $xml = false;
29
30                         $lv = $this->lv;
31                         $lang = $this->lang;
32
33                         if ($action == 'domain-start') {
34                                 if (!array_key_exists('dom', $input))
35                                         return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Domain start failed', 'Domain name not present');
36
37                                 $name = $input['dom'];
38                                 $msg = $lv->domain_start($name) ? $lang->get('dom-start-ok') :
39                                         $lang->get('dom-start-err').': '.$lv->get_last_error();
40                         }
41
42                         if ($action == 'domain-stop') {
43                                 if (!array_key_exists('dom', $input))
44                                         return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Domain shutdown failed', 'Domain name not present');
45
46                                 $name = $input['dom'];
47                                 $msg = $lv->domain_shutdown($name) ? $lang->get('dom-shutdown-ok') :
48                                         $lang->get('dom-shutdown-err').': '.$lv->get_last_error();
49                         }
50
51                         if ($action == 'domain-destroy') {
52                                 if (!array_key_exists('dom', $input))
53                                         return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Domain destroy failed', 'Domain name not present');
54
55                                 $name = $input['dom'];
56                                 $msg = $lv->domain_destroy($name) ? $lang->get('dom-destroy-ok') :
57                                         $lang->get('dom-destroy-err').': '.$lv->get_last_error();
58                         }
59
60                         if (($action == 'domain-undefine') && (verify_user($db, USER_PERMISSION_VM_DELETE))) {
61                                 if (!array_key_exists('dom', $input))
62                                         return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Domain undefine failed', 'Domain name not present');
63
64                                 $name = $input['dom'];
65                                 if ((!array_key_exists('confirmed', $_GET)) || ($_GET['confirmed'] != 1)) {
66                                         $frm = '<div class="section">'.$lang->get('dom-undefine').'</div>
67                                                 <table id="form-table">
68                                                 <tr>
69                                                   <td colspan="3">'.$lang->get('dom-undefine-question').' '.$lang->get('name').': <u>'.$name.'</u></td>
70                                                 </tr>
71                                                 <tr align="center">
72                                                   <td><a href="'.$_SERVER['REQUEST_URI'].'&amp;confirmed=1">'.$lang->get('delete').'</a></td>
73                                                   <td><a href="'.$_SERVER['REQUEST_URI'].'&amp;confirmed=1&amp;deldisks=1">'.$lang->get('delete-with-disks').'</a></td>
74                                                   <td><a href="?page='.$page.'">'.$lang->get('No').'</a></td>
75                                                 </td>
76                                                 </table>';
77                                 }
78                                 else {
79                                         $err = '';
80                                         if (array_key_exists('deldisks', $_GET) && $_GET['deldisks'] == 1) {
81                                                 $disks = $lv->get_disk_stats($name);
82
83                                                 for ($i = 0; $i < sizeof($disks); $i++) {
84                                                         $img = $disks[$i]['file'];
85
86                                                         if (!$lv->remove_image($img, array(2) ))
87                                                                 $err .= $img.': '.$lv->get_last_error();
88                                                 }
89                                         }
90
91                                         $msg = $lv->domain_undefine($name) ? $lang->get('dom-undefine-ok') :
92                                                 $lang->get('dom-undefine-err').': '.$lv->get_last_error();
93
94                                         if ($err)
95                                                 $msg .= ' (err: '.$err.')';
96                                 }
97                         }
98
99                         if ($action == 'domain-dump') {
100                                 if (!array_key_exists('dom', $input))
101                                         return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Domain dump failed', 'Domain name not present');
102
103                                 $name = $input['dom'];
104                                 $inactive = (!$lv->domain_is_running($name)) ? true : false;
105
106                                 $xml = $lv->domain_get_xml($name, $inactive);
107                                 $frm = '<div class="section">'.$lang->get('dom-xmldesc').' - <i>'.$name.'</i></div><form method="POST">
108                                         <table id="form-table"><tr><td>'.$lang->get('dom-xmldesc').': </td>
109                                         <td><textarea readonly="readonly" name="xmldesc" rows="25" cols="90%">'.$xml.'</textarea></td></tr><tr align="center"><td colspan="2">
110                                         </tr></form></table>';
111                         }
112
113                         if ($action == 'domain-migrate') {
114                                 if (!array_key_exists('dom', $input))
115                                         return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Domain migration failed', 'Domain name not present');
116
117                                 $name = $input['dom'];
118                                 if (!array_key_exists('dest-uri', $_POST)) {
119                                         $uris = array();
120
121                                         if (isset($conns) && $conns) {
122                                                 foreach ($conns as $conn) {
123                                                         if ($conn['connection_uri'] != $uri)
124                                                                 $uris[] = array(
125                                                                         'id' => $conn['id'],
126                                                                         'name' => $conn['connection_name']
127                                                                         );
128                                                 }
129                                         }
130                                         else
131                                                 $uris = array();
132
133                                         if (sizeof($uris) == 0)
134                                                 echo $lang->get('no-destination-present');
135                                         else {
136                                                 echo "<form method='POST'>".$lang->get('choose-destination')." ($name): <br /><select name='dest-uri' style='width: 150px'>";
137
138                                                 foreach ($uris as $cn)
139                                                         echo "<option value=\"${cn['id']}\">{$cn['name']}</option>";
140
141                                                 echo "</select><br /><input type='submit' value='".$lang->get('dom-migrate')."'>";
142                                         }
143                                 }
144                                 else {
145                                         $arr = false;
146
147                                         for ($i = 0; $i < sizeof($conns); $i++) {
148                                                 if ($conns[$i]['id'] == $_POST['dest-uri']) {
149                                                         $arr = $conns[$i];
150                                                         break;
151                                                 }
152                                         }
153
154                                         if ($arr && (!$lv->migrate($name, $arr)))
155                                                 echo '<b>'.$lang->get('error-page-title').'</b>: '.$lv->get_last_error();
156                                 }
157                         }
158
159                         if ($action == 'domain-edit') {
160                                 if (!array_key_exists('dom', $input))
161                                         return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Domain editing failed', 'Domain name not present');
162
163                                 $name = $input['dom'];
164                                 $inactive = (!$lv->domain_is_running($name)) ? true : false;
165
166                                 if (array_key_exists('xmldesc', $_POST)) {
167                                         $msg = $lv->domain_change_xml($name, $_POST['xmldesc']) ? $lang->get('dom-define-changed') :
168                                                 $lang->get('dom-define-change-err').': '.$lv->get_last_error();
169                                 }
170                                 else {
171                                         $xml = $lv->domain_get_xml($name, $inactive);
172                                         $frm = '<div class="section">'.$lang->get('dom-editxml').' - <i>'.$name.'</i></div><form method="POST"><table id="form-table"><tr><td>'.$lang->get('dom-xmldesc').': </td>
173                                                 <td><textarea name="xmldesc" rows="25" cols="90%">'.$xml.'</textarea></td></tr><tr align="center"><td colspan="2">
174                                                 <input type="submit" value=" '.$lang->get('dom-editxml').' "></tr></form></table>';
175                                 }
176                         }
177
178                         $this->data = array(
179                                         'msg' => $msg,
180                                         'frm' => $frm,
181                                         'xml' => $xml
182                                         );
183                 }
184
185                 function createNewVM($input) {
186                         if (!$this->lv)
187                                 return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Libvirt Domain', 'Libvirt class is not set');
188
189                         $lv = $this->lv;
190                         $lang = $this->lang;
191
192                         $skip = false;
193                         $msg = false;
194                         if (array_key_exists('sent', $input)) {
195                                 $features = array('apic', 'acpi', 'pae', 'hap');
196                                 $iso_path = ini_get('libvirt.iso_path');
197                                 $img = $iso_path.'/'.$input['install_img'];
198
199                                 $feature = array();
200                                 for ($i = 0; $i < sizeof($features); $i++)
201                                         if (array_key_exists('feature_'.$features[$i], $input))
202                                                 $feature[] = $features[$i];
203
204                                 $nic = array();
205                                 if ($input['setup_nic']) {
206                                         $nic['mac'] = $input['nic_mac'];
207                                         $nic['type'] = $input['nic_type'];
208                                         $nic['network'] = $input['nic_net'];
209                                 }
210                                 $disk = array();
211                                 if ($input['setup_disk']) {
212                                         if ($input['new_vm_disk']) {
213                                                 $disk['image'] = $input['name'].'.'.$input['disk_driver'];
214                                                 $disk['size'] = (int)$input['img_data'];
215                                                 $disk['bus'] = $input['disk_bus'];
216                                                 $disk['driver'] = $input['disk_driver'];
217                                         }
218                                         else {
219                                                 $disk['image'] = $input['img_data'];
220                                                 $disk['size'] = 0;
221                                                 $disk['bus'] = $input['disk_bus'];
222                                                 $disk['driver'] = $input['disk_driver'];
223                                         }
224                                 }
225
226                                 $tmp = $lv->domain_new($input['name'], $img, $input['cpu_count'], $feature, $input['memory'], $input['maxmem'], $input['clock_offset'], $nic, $disk, $input['setup_persistent']);
227                                 if (!$tmp)
228                                         $msg = $lv->get_last_error();
229                                 else {
230                                         $skip = true;
231                                         $msg = $lang->get('new-vm-created');
232                                 }
233                         }
234
235                         $isos = libvirt_get_iso_images();
236
237                         if (empty($isos))
238                                 $msg = $lang->get('no-iso');
239
240                         $ci  = $lv->get_connect_information();
241                         $maxvcpu = $ci['hypervisor_maxvcpus'];
242                         unset($ci);
243
244                         return array(
245                                                 'skip' => $skip,
246                                                 'msg' => $msg,
247                                                 'isos' => $isos,
248                                                 'maxvcpu' => $maxvcpu
249                                         );
250                 }
251
252                 function rpc_list($idUser, $lv, $ret) {
253                         return $lv->get_domains();
254                 }
255
256                 function rpc_start($idUser, $lv, $ret) {
257                         if ((!array_key_exists('data', $ret)) || (!array_key_exists('data', $ret['data'])) || (!array_key_exists('name', $ret['data']['data'])))
258                                 return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Name is missing', 'Domain name is missing');
259
260                         $name = $ret['data']['data']['name'];
261                         return ($lv->domain_start($name)) ? 'Domain started successfully' : 'Cannot start domain';
262                 }
263
264                 function rpc_stop($idUser, $lv, $ret) {
265                         if ((!array_key_exists('data', $ret)) || (!array_key_exists('data', $ret['data'])) || (!array_key_exists('name', $ret['data']['data'])))
266                                 return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Name is missing', 'Domain name is missing');
267
268                         $name = $ret['data']['data']['name'];
269                         return ($lv->domain_destroy($name)) ? 'Domain stopped successfully' : 'Cannot stop domain';
270                 }
271
272                 function rpc_reboot($idUser, $lv, $ret) {
273                         if ((!array_key_exists('data', $ret)) || (!array_key_exists('data', $ret['data'])) || (!array_key_exists('name', $ret['data']['data'])))
274                                 return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Name is missing', 'Domain name is missing');
275
276                         $name = $ret['data']['data']['name'];
277                         return ($lv->domain_reboot($name)) ? 'Domain reboot triggered successfully' : 'Cannot trigger reboot command';
278                 }
279
280                 function rpc_dump($idUser, $lv, $ret) {
281                         if ((!array_key_exists('data', $ret)) || (!array_key_exists('data', $ret['data'])) || (!array_key_exists('name', $ret['data']['data'])))
282                                 return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Name is missing', 'Domain name is missing');
283
284                         $name = $ret['data']['data']['name'];
285                         return $lv->domain_get_xml($name, ($lv->domain_is_running($name) ? false : true));
286                 }
287
288                 function rpc_migrate($idUser, $lv, $ret) {
289                         if ((!array_key_exists('data', $ret)) || (!array_key_exists('data', $ret['data'])) || (!array_key_exists('name', $ret['data']['data'])))
290                                 return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Name is missing', 'Domain name is missing');
291
292                         if ((!array_key_exists('destination', $ret['data']['data'])) || (!array_key_exists('uri', $ret['data']['data']['destination'])))
293                                 return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Destination is missing', 'Destination connection information are missing');
294
295                         $name = $ret['data']['data']['name'];
296                         $uri  = $ret['data']['data']['destination']['uri'];
297                         $user = array_key_exists('username', $ret['data']['data']['destination']) ? $ret['data']['data']['destination']['username'] : null;
298                         $pass = array_key_exists('password', $ret['data']['data']['destination']) ? $ret['data']['data']['destination']['password'] : null;
299
300                         if ($lv->get_uri() == $uri)
301                                 return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Local migration not supported', 'Local migration requested but not supported');
302
303                         $dest_lv = new Libvirt($uri, $user, $pass, false, 'en');
304                         if (!$dest_lv->is_connected()) {
305                                 unset($dest_lv);
306                                 return 'Cannot connect to destination';
307                         }
308
309                         $ret = $lv->migrate($name, $dest_lv->get_connection(), array_key_exists('live', $ret['data']['data']) ? $ret['data']['data']['live'] : false,
310                                         array_key_exists('bandwidth', $ret['data']['data']) ? $ret['data']['data']['bandwidth'] :  1000);
311                         unset($dest_lv);
312
313                         return $ret ? 'Success' : 'Error on migrate';
314                 }
315
316                 function rpc_get_screenshot($idUser, $lv, $ret) {
317                         if ((!array_key_exists('data', $ret)) || (!array_key_exists('data', $ret['data'])) || (!array_key_exists('name', $ret['data']['data'])))
318                                 return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Name is missing', 'Domain name is missing');
319
320                         $name = $ret['data']['data']['name'];
321
322                         if (!$lv->domain_is_running($name))
323                                 return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Domain not active', 'Cannot get screenshot for inactive domain');
324
325                         /* TODO: Implement. Just a placeholder for now */
326
327                         return 'Not supported yet';
328                 }
329
330                 function rpc_info($idUser, $lv, $ret) {
331                         if ((!array_key_exists('data', $ret)) || (!array_key_exists('data', $ret['data'])) || (!array_key_exists('name', $ret['data']['data'])))
332                                 return $this->log(TYPE_ERROR, __CLASS__.'::'.__FUNCTION__, 'Name is missing', 'Domain name is missing');
333
334                         $name = $ret['data']['data']['name'];
335                         $tmp = $lv->domain_get_info_call($name);
336                         $ret = $tmp[$name];
337
338                         if ($lv->domain_is_running($name))
339                                 $ret['vnc_port'] = $lv->domain_get_vnc_port($name);
340
341                         $ret['arch'] = $lv->domain_get_arch($name);
342                         $ret['boot_devices'] = $lv->domain_get_boot_devices($name);
343                         $ret['multimedia'] = array(
344                                                         'console' => $lv->domain_get_multimedia_device($name, 'console'),
345                                                         'input' => $lv->domain_get_multimedia_device($name, 'input'),
346                                                         'graphics' => $lv->domain_get_multimedia_device($name, 'graphics'),
347                                                         'video' => $lv->domain_get_multimedia_device($name, 'video')
348                                                 );
349
350                         $ret['devices'] = $lv->domain_get_host_devices($name);
351                         if (!$ret['devices']['pci'])
352                                 $ret['devices']['pci'] = 'none';
353                         if (!$ret['devices']['usb'])
354                                 $ret['devices']['usb'] = 'none';
355                         $ret['clock-offset'] = $lv->domain_get_clock_offset($name);
356
357                         $features = array('apic', 'acpi', 'pae', 'hap');
358                         $feat = array();
359                         for ($i = 0; $i < sizeof($features); $i++) {
360                                 if ($lv->domain_get_feature($name, $features[$i]))
361                                         $feat[] = $features[$i];
362                         }
363
364                         $ret['features'] = join(',', $feat);
365
366                         $ret['state'] = $lv->domain_state_translate($ret['state']);
367                         return $ret;
368                 }
369         }
370 ?>