forked from jonpanozzo/OpenELEC
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOpenELEC.page
More file actions
executable file
·385 lines (328 loc) · 12.1 KB
/
OpenELEC.page
File metadata and controls
executable file
·385 lines (328 loc) · 12.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
Icon="OpenELEC.png"
Menu="unVMs"
Title="OpenELEC"
Type="xmenu"
---
<style>
.advanced {
display: none;
}
</style>
<?PHP
// CREATE HELP CONTENTS
$help_cpu = <<<EOT
Select the number of CPU cores from your host you wish to use with your OpenELEC VM.
EOT;
$help_memory = <<<EOT
Select the amount of RAM from your host you wish to dedicate to your OpenELEC VM.
EOT;
$help_machinetype = <<<EOT
Select the VM emulated machine type for your OpenELEC VM.
EOT;
$help_gpu = <<<EOT
Select the graphics card device you wish to use with your OpenELEC VM. Presently we only support AMD and nVIDIA GPUs and the exact list of supported devices is still growing. We do not support the assignment of on-board graphics at this time.
EOT;
$help_audio = <<<EOT
Select the sound card device you wish to use with your OpenELEC VM. For most GPUs, audio can be done through HDMI or with a DVI to HDMI adapter. For those wishing to use their on-board audio as opposed to their HDMI audio, select device 00:1b.0, if available.
EOT;
$help_other_devices = <<<EOT
Select any other PCI devices you wish to use inside your OpenELEC VM.
EOT;
$help_usb = <<<EOT
Select the USB devices you wish to use inside your OpenELEC VM. We have hidden your unRAID USB Flash Device for your protection. Not all USB devices work for this yet.
EOT;
$help_readonly = <<<EOT
Check this option to prevent OpenELEC write access to your unRAID array.
EOT;
$help_readonly = <<<EOT
Check this option to prevent OpenELEC write access to your unRAID array.
EOT;
$help_startvm = <<<EOT
Starting the VM will apply the settings you have specified above as well as bind your GPU/audio devices to the vfio-pci driver.
EOT;
$help_stopvm = <<<EOT
Click this button to stop OpenELEC.
EOT;
$help_forcevm = <<<EOT
Click this button to force OpenELEC to shutdown immediately (use if VM is stuck in hung state).
EOT;
$boolLibvirtRunning = file_exists("/var/run/libvirt/libvirtd.pid");
$boolInstalled = file_exists("/mnt/cache/.vms/kvm/OpenELEC/OpenELEC-unRAID.x86_64-5.0.4.img");
$boolRunning = (shell_exec("virsh list | grep OpenELEC") != "");
$boolACSEnabled = (strpos(file_get_contents('/proc/cmdline'), 'pcie_acs_override=') !== false);
if (!$boolLibvirtRunning) {
?><p class="notice">OpenELEC requires the libVirt service to be running.</p><?php
return;
}
if (!$boolInstalled) {
?><span class="red"><b>OpenELEC is NOT INSTALLED</b></span>
<p class="notice">OpenELEC image file is missing because the array isn't started or the image was deleted manually. You can (re)start the array to automatically download the OpenELEC image file again.</p><?php
return;
} else if ($boolRunning) {
?><span class="green"><b>OpenELEC is RUNNING</b></span><?php
}
// Check for PCIE ACS capabilities
if (!$boolACSEnabled) {
// Check the /boot/syslinux/syslinux.cfg for the existance of pcie_acs_override=downstream, add it in if not found
$arrSyslinuxCfg = file('/boot/syslinux/syslinux.cfg');
$strCurrentLabel = '';
$boolModded = false;
foreach ($arrSyslinuxCfg as &$strSyslinuxCfg) {
if (stripos(trim($strSyslinuxCfg), 'label ') === 0) {
$strCurrentLabel = trim(str_ireplace('label ', '', $strSyslinuxCfg));
}
if (stripos($strSyslinuxCfg, 'append ') !== false) {
if (stripos($strSyslinuxCfg, 'pcie_acs_override=') === false) {
// pcie_acs_override=downstream was not found so append it in
$strSyslinuxCfg = str_ireplace('append ', 'append pcie_acs_override=downstream ', $strSyslinuxCfg);
$boolModded = true;
}
// We just modify the first append line, other boot menu items are untouched
break;
}
}
if ($boolModded) {
// Backup syslinux.cfg
copy('/boot/syslinux/syslinux.cfg', '/boot/syslinux/syslinux.cfg-');
// Write Changes to syslinux.cfg
file_put_contents('/boot/syslinux/syslinux.cfg', implode('', $arrSyslinuxCfg));
}
?><p class="notice">You must reboot in to <b><?=$strCurrentLabel?></b> mode for changes to take effect for OpenELEC to operate</p><?php
return;
}
// MAKE SURE THE VM ISN'T RUNNING
if ($boolRunning) { ?>
<form target="progressFrame" action="/update.php" method="POST">
<input type="hidden" name="#command" value="virsh shutdown OpenELEC && i=0; while [ $(virsh list | grep OpenELEC | wc -l) -gt "0" -a "$i" -le "30" ]; do i=`expr $i + 1`; sleep 1; done"/>
<input type="submit" value="Stop VM"/>
</form>
<blockquote class="inline_help"><?=Markdown($help_stopvm)?></blockquote>
<form target="progressFrame" action="/update.php" method="POST">
<input type="hidden" name="#command" value="virsh destroy OpenELEC && i=0; while [ $(virsh list | grep OpenELEC | wc -l) -gt "0" -a "$i" -le "30" ]; do i=`expr $i + 1`; sleep 1; done"/>
<input type="submit" value="Force Shutdown VM"/>
</form>
<blockquote class="inline_help"><?=Markdown($help_forcevm)?></blockquote>
<?php
return;
}
$arrValidCPUCoreAmounts = [
1 => '1',
2 => '2',
3 => '3',
4 => '4'
];
$arrValidMemoryAmounts = [
512 => '512 MB',
1024 => '1 GB',
1536 => '1.5 GB',
2048 => '2 GB'
];
$arrValidMachineTypes = [
'q35' => 'Q35',
'pc' => 'i440fx'
];
// CREATE ARRAY OF GPU/AUDIO DEVICES
$arrWhitelistGPUNames = array('VGA compatible controller');
$arrWhitelistAudioNames = array('Audio device');
$arrValidGPUDevices = array();
$arrValidAudioDevices = array();
$arrValidOtherDevices = array();
exec("lspci", $arrAllPCIDevices);
foreach ($arrAllPCIDevices as $strPCIDevice) {
if (preg_match('/^(?P<id>\S+) (?P<type>.+): (?P<name>.+)$/', $strPCIDevice, $arrMatch)) {
if (in_array($arrMatch['type'], $arrWhitelistGPUNames)) {
$arrName = 'arrValidGPUDevices';
} else if (in_array($arrMatch['type'], $arrWhitelistAudioNames)) {
$arrName = 'arrValidAudioDevices';
} else {
$arrName = 'arrValidOtherDevices';
}
if (!file_exists('/sys/bus/pci/devices/0000:' . $arrMatch['id'] . '/iommu_group/')) {
// No IOMMU support for device, skip device
continue;
}
${$arrName}[] = array(
'dev_id' => $arrMatch['id'],
'dev_type' => $arrMatch['type'],
'dev_name' => $arrMatch['name']
);
}
}
// Check for available video devices, one is required
if (empty($arrValidGPUDevices)) { ?>
<p class="notice">This VM requires a valid graphics device and hardware capable of Intel VT-d or AMD Vi. If you think you are receiving this message in error, please check your BIOS settings.</p>
<?php
return;
}
// Add a 'None' option for audio
if (!empty($arrValidAudioDevices)) {
$arrValidAudioDevices[] = array(
'dev_id' => '',
'dev_type' => '',
'dev_name' => 'None'
);
}
// CREATE ARRAY OF USB DEVICES
$arrValidUSBDevices = array();
exec("lsusb", $arrAllUSBDevices);
foreach ($arrAllUSBDevices as $strUSBDevice) {
if (preg_match('/^.+ID (?P<id>\S+) (?P<name>.+)$/', $strUSBDevice, $arrMatch)) {
$arrMatch['name'] = trim($arrMatch['name']);
if (empty($arrMatch['name'])) {
// Device name is blank, skip device
continue;
}
if (stripos($GLOBALS['var']['flashGUID'], str_replace(':', '-', $arrMatch['id'])) === 0) {
// Device id matches the unraid device, skip device
continue;
}
if (trim(shell_exec('lsusb -d ' . $arrMatch['id'] . ' -v | grep \'bDeviceClass 9 Hub\'')) != '') {
// Device class is a Hub, skip device
continue;
}
$arrValidUSBDevices[] = array(
'dev_id' => $arrMatch['id'],
'dev_name' => $arrMatch['name'],
);
}
}
// Default configuration
$arrConfiguration = [
'gpu' => empty($arrValidGPUDevices) ? '' : $arrValidGPUDevices[0]['dev_id'],
'audio' => empty($arrValidAudioDevices) ? '' : $arrValidAudioDevices[0]['dev_id'],
'other' => [],
'usb' => [],
'mac' => '52:54:00:xx:xx:xx',
'bridge' => $GLOBALS['var']['BRNAME'],
'readonly' => true,
'memory' => 1024,
'vcpus' => 2,
'machinetype' => 'q35'
];
// Read existing configuration file (if available)
if (file_exists('/boot/config/plugins/OpenELEC/OpenELEC.conf')) {
if ($strConfigFile = file_get_contents('/boot/config/plugins/OpenELEC/OpenELEC.conf')) {
$arrExistingConfiguration = json_decode($strConfigFile, true);
unset($arrExistingConfiguration['bridge']); // Remove the existing bridge value for now
$arrConfiguration = array_merge($arrConfiguration, $arrExistingConfiguration);
}
}
?>
<!-- FORM START -->
<form action="/plugins/OpenELEC/OpenELEC-submit.php" method="POST" target="progressFrame">
<dl>
<div class="advanced">
<dt>CPU Cores:</dt>
<dd>
<select name="vcpus">
<?php
foreach($arrValidCPUCoreAmounts as $key => $label) {
echo mk_option($arrConfiguration['vcpus'], $key, $label);
}
?>
</select>
</dd>
<blockquote class="inline_help"><?=Markdown($help_cpu)?></blockquote>
</div>
<div class="advanced">
<dt>Memory (RAM):</dt>
<dd>
<select name="memory">
<?php
foreach($arrValidMemoryAmounts as $key => $label) {
echo mk_option($arrConfiguration['memory'], $key, $label);
}
?>
</select>
</dd>
<blockquote class="inline_help"><?=Markdown($help_memory)?></blockquote>
</div>
<div class="advanced">
<dt>Machine Type:</dt>
<dd>
<select name="machinetype">
<?php
foreach($arrValidMachineTypes as $key => $label) {
echo mk_option($arrConfiguration['machinetype'], $key, $label);
}
?>
</select>
</dd>
<blockquote class="inline_help"><?=Markdown($help_machinetype)?></blockquote>
</div>
<dt>Graphics Card:</dt>
<dd>
<?php if (!empty($arrValidGPUDevices)) { ?>
<select name="gpu">
<?php
foreach($arrValidGPUDevices as $x) {
echo mk_option($arrConfiguration['gpu'], $x['dev_id'], trim($x['dev_id'] . ' | ' . $x['dev_name'], ' |'));
}
?>
</select>
<?php } else { ?>
<i>None available</i>
<?php } ?>
</dd>
<blockquote class="inline_help"><?=Markdown($help_gpu)?></blockquote>
<dt>Sound Card:</dt>
<dd>
<?php if (!empty($arrValidAudioDevices)) { ?>
<select name="audio">
<?php
foreach($arrValidAudioDevices as $x) {
echo mk_option($arrConfiguration['audio'], $x['dev_id'], trim($x['dev_id'] . ' | ' . $x['dev_name'], ' |'));
}
?>
</select>
<?php } else { ?>
<i>None available</i>
<?php } ?>
</dd>
<blockquote class="inline_help"><?=Markdown($help_audio)?></blockquote>
<?php /*
<div class="advanced">
<dt>Other Devices:</dt>
<dd>
<?php if (!empty($arrValidOtherDevices)) { ?>
<span style="display: inline-block; padding-bottom: 10px;">
<?php foreach($arrValidOtherDevices as $i=>$x) { ?>
<label for="other<?=$i?>"><input type="checkbox" name="other[]" id="other<?=$i?>" value="<?=$x['dev_id']?>"/> <?=$x['dev_id']?> | <?=$x['dev_name']?></label><br/>
<?php } ?>
</span>
<?php } else { ?>
<i>None available</i>
<?php } ?>
</dd>
<blockquote class="inline_help"><?=Markdown($help_other_devices)?></blockquote>
</div>
*/ ?>
<dt>USB Devices:</dt>
<dd>
<?php if (!empty($arrValidUSBDevices)) { ?>
<span style="display: inline-block; padding-bottom: 10px;">
<?php foreach($arrValidUSBDevices as $i=>$x) { ?>
<label for="usb<?=$i?>"><input type="checkbox" name="usb[]" id="usb<?=$i?>" value="<?=$x['dev_id']?>" <?php if (in_array($x['dev_id'], $arrConfiguration['usb'])) echo 'checked="checked"'; ?>/> <?=$x['dev_id']?> | <?=$x['dev_name']?></label><br/>
<?php } ?>
</span>
<?php } else { ?>
<i>None available</i>
<?php } ?>
</dd>
<blockquote class="inline_help"><?=Markdown($help_usb)?></blockquote>
<input type="hidden" name="bridge" value="<?=$arrConfiguration['bridge']?>"/>
<input type="hidden" name="mac" value="<?=$arrConfiguration['mac']?>"/>
<div>
<dt>Media Readonly:</dt>
<dd>
<label for="readonly"><input type="checkbox" name="readonly" id="readonly" value="1" <?php if ($arrConfiguration['readonly'] === true) echo 'checked="checked"'; ?>/> Prevent OpenELEC write access to your media files</label>
</dd>
<blockquote class="inline_help"><?=Markdown($help_readonly)?></blockquote>
</div>
<dt><input type="button" onclick="$('.advanced').toggle('slow'); $(this).text(function(i, text){ return text === 'Show Advanced Options' ? 'Hide Advanced Options' : 'Show Advanced Options'; })" value="Show Advanced Options"/></dt>
<dd>
<input type="submit" value="Start VM"/>
</dd>
<blockquote class="inline_help"><?=Markdown($help_startvm)?></blockquote>
</dl>
</form>