summaryrefslogtreecommitdiffstats
path: root/modules/serversetup
diff options
context:
space:
mode:
authorJonathan Bauer2016-04-01 16:50:13 +0200
committerJonathan Bauer2016-04-01 16:50:13 +0200
commitdbc0d9614421e064cc62aacf116ebb783c83f2f3 (patch)
tree091844b8578ff1d9ac18edfd3cee3e63210133d7 /modules/serversetup
parent[ldapauth] Add homedir conf to ldap wizard (diff)
downloadslx-admin-dbc0d9614421e064cc62aacf116ebb783c83f2f3.tar.gz
slx-admin-dbc0d9614421e064cc62aacf116ebb783c83f2f3.tar.xz
slx-admin-dbc0d9614421e064cc62aacf116ebb783c83f2f3.zip
[merge] merging c3sl / fr - initial commit
Diffstat (limited to 'modules/serversetup')
-rw-r--r--modules/serversetup/config.json4
-rw-r--r--modules/serversetup/module.inc.php186
-rw-r--r--modules/serversetup/templates/ipaddress.html34
-rw-r--r--modules/serversetup/templates/ipxe.html149
-rw-r--r--modules/serversetup/templates/ipxe_update.html20
5 files changed, 393 insertions, 0 deletions
diff --git a/modules/serversetup/config.json b/modules/serversetup/config.json
new file mode 100644
index 00000000..93209f62
--- /dev/null
+++ b/modules/serversetup/config.json
@@ -0,0 +1,4 @@
+{
+ "category":"settings",
+ "enabled":"true"
+}
diff --git a/modules/serversetup/module.inc.php b/modules/serversetup/module.inc.php
new file mode 100644
index 00000000..e37d7d40
--- /dev/null
+++ b/modules/serversetup/module.inc.php
@@ -0,0 +1,186 @@
+<?php
+
+class Page_ServerSetup extends Page
+{
+
+ private $mountIpxeTask;
+ private $taskStatus;
+ private $currentAddress;
+ private $currentMenu;
+
+ protected function doPreprocess()
+ {
+ User::load();
+
+ if (!User::hasPermission('superadmin')) {
+ Message::addError('no-permission');
+ Util::redirect('?do=Main');
+ }
+
+ $this->currentMenu = Property::getBootMenu();
+
+ if(Request::get('download') !== false){
+ $this->downloadIpxe(Request::get('download'));
+ }
+
+ if(Request::get('defaultIpxe') !== false){
+ $this->defaultIpxe(Request::get('defaultIpxe'));
+ }
+
+ $action = Request::post('action');
+
+ if ($action === false) {
+ $this->currentAddress = Property::getServerIp();
+ $this->getLocalAddresses();
+ }
+
+ if ($action === 'ip') {
+ // New address is to be set
+ $this->getLocalAddresses();
+ $this->updateLocalAddress();
+ }
+
+ if ($action === 'ipxe') {
+ // iPXE stuff changes
+ $this->updatePxeMenu();
+ }
+
+ if($action === 'save-script') {
+ // Save new iPXE script
+ $this->updateIpxeScript();
+ }
+
+ if($action === 'default-script') {
+ // Restore iPXE script to default
+ $this->defaultIpxe();
+ }
+ }
+
+ protected function doRender()
+ {
+ Render::setTitle(Dictionary::translate('lang_serverConfiguration'));
+
+ $taskid = Request::any('taskid');
+ if ($taskid !== false && Taskmanager::isTask($taskid)) {
+ Render::addTemplate('ipxe_update', array('taskid' => $taskid));
+ }
+
+ Render::addTemplate('ipaddress', array(
+ 'ips' => $this->taskStatus['data']['addresses']
+ ));
+ $data = $this->currentMenu;
+ if (!isset($data['defaultentry']))
+ $data['defaultentry'] = 'net';
+ if ($data['defaultentry'] === 'net')
+ $data['active-net'] = 'checked';
+ if ($data['defaultentry'] === 'hdd')
+ $data['active-hdd'] = 'checked';
+ if ($data['defaultentry'] === 'custom')
+ $data['active-custom'] = 'checked';
+ Render::addTemplate('ipxe', $data);
+ }
+
+ // -----------------------------------------------------------------------------------------------
+
+ private function getLocalAddresses()
+ {
+ $this->taskStatus = Taskmanager::submit('LocalAddressesList', array());
+
+ if ($this->taskStatus === false) {
+ $this->taskStatus['data']['addresses'] = false;
+ return false;
+ }
+
+ if ($this->taskStatus['statusCode'] === TASK_WAITING) { // TODO: Async if just displaying
+ $this->taskStatus = Taskmanager::waitComplete($this->taskStatus['id']);
+ }
+
+ $sortIp = array();
+ foreach (array_keys($this->taskStatus['data']['addresses']) as $key) {
+ $item = & $this->taskStatus['data']['addresses'][$key];
+ if (!isset($item['ip']) || !preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $item['ip']) || substr($item['ip'], 0, 4) === '127.') {
+ unset($this->taskStatus['data']['addresses'][$key]);
+ continue;
+ }
+ if ($this->currentAddress === $item['ip']) {
+ $item['default'] = true;
+ }
+ $sortIp[] = $item['ip'];
+ }
+ unset($item);
+ array_multisort($sortIp, SORT_STRING, $this->taskStatus['data']['addresses']);
+ return true;
+ }
+
+ private function updateLocalAddress()
+ {
+ $newAddress = Request::post('ip', 'none');
+ $valid = false;
+ foreach ($this->taskStatus['data']['addresses'] as $item) {
+ if ($item['ip'] !== $newAddress)
+ continue;
+ $valid = true;
+ break;
+ }
+ if ($valid) {
+ Property::setServerIp($newAddress);
+ global $tidIpxe;
+ if (isset($tidIpxe) && $tidIpxe !== false)
+ Util::redirect('?do=ServerSetup&taskid=' . $tidIpxe);
+ } else {
+ Message::addError('invalid-ip', $newAddress);
+ }
+ Util::redirect();
+ }
+
+ private function updatePxeMenu()
+ {
+ $timeout = Request::post('timeout', 10);
+ if ($timeout === '')
+ $timeout = 0;
+ if (!is_numeric($timeout) || $timeout < 0) {
+ Message::addError('value-invalid', 'timeout', $timeout);
+ }
+ $this->currentMenu['defaultentry'] = Request::post('defaultentry', 'net');
+ $this->currentMenu['timeout'] = $timeout;
+ $this->currentMenu['custom'] = Request::post('custom', '');
+ $this->currentMenu['masterpasswordclear'] = Request::post('masterpassword', '');
+ if (empty($this->currentMenu['masterpasswordclear']))
+ $this->currentMenu['masterpassword'] = 'invalid';
+ else
+ $this->currentMenu['masterpassword'] = Crypto::hash6($this->currentMenu['masterpasswordclear']);
+ Property::setBootMenu($this->currentMenu);
+ $id = Trigger::ipxe();
+ Util::redirect('?do=ServerSetup&taskid=' . $id);
+ }
+
+ private function downloadIpxe($ipxe){
+ $file = '/opt/taskmanager/data/ipxe/src/bin/ipxe.' . $ipxe;
+ if (file_exists($file)) {
+ header('Content-Description: File Transfer');
+ header('Content-Type: application/octet-stream');
+ header('Content-Disposition: attachment; filename='.basename($file));
+ header('Expires: 0');
+ header('Cache-Control: must-revalidate');
+ header('Pragma: public');
+ header('Content-Length: ' . filesize($file));
+ ob_clean();
+ flush();
+ readfile($file);
+ exit();
+ }
+ }
+
+ private function updateIpxeScript(){
+ $newScript = Request::post('custom-script');
+ file_put_contents("/opt/taskmanager/data/pxe.embed",$newScript);
+ Util::redirect('?do=ServerSetup');
+ }
+
+ private function defaultIpxe(){
+ $default = file_get_contents("/opt/taskmanager/data/pxe_default.embed");
+ $default = str_replace("{{ip}}", "http://" . Property::getServerIp(), $default);
+ file_put_contents("/opt/taskmanager/data/pxe.embed",$default);
+ Util::redirect('?do=ServerSetup');
+ }
+}
diff --git a/modules/serversetup/templates/ipaddress.html b/modules/serversetup/templates/ipaddress.html
new file mode 100644
index 00000000..e4967703
--- /dev/null
+++ b/modules/serversetup/templates/ipaddress.html
@@ -0,0 +1,34 @@
+<div class="panel panel-default">
+ <div class="panel-heading">
+ {{lang_bootAddress}}
+ </div>
+ <div class="panel-body">
+ <p>
+ {{lang_chooseIP}}
+ </p>
+ <form method="post" action="?do=ServerSetup">
+ <input type="hidden" name="action" value="ip">
+ <input type="hidden" name="token" value="{{token}}">
+ <table class="slx-table">
+ {{#ips}}
+ <tr>
+ <td>{{ip}}</td>
+ {{#default}}
+ <td>
+ <span class="btn btn-success btn-xs"><span class="glyphicon glyphicon-ok"></span> {{lang_active}}</span>
+ </td>
+ {{/default}}
+ {{^default}}
+ <td>
+ <button class="btn btn-primary btn-xs" name="ip" value="{{ip}}"><span class="glyphicon glyphicon-flag"></span> {{lang_set}}</button>
+ </td>
+ {{/default}}
+ </tr>
+ {{/ips}}
+ </table>
+ <p>
+ {{lang_bootHint}}
+ </p>
+ </form>
+ </div>
+</div> \ No newline at end of file
diff --git a/modules/serversetup/templates/ipxe.html b/modules/serversetup/templates/ipxe.html
new file mode 100644
index 00000000..54d7db16
--- /dev/null
+++ b/modules/serversetup/templates/ipxe.html
@@ -0,0 +1,149 @@
+<div class="panel panel-default">
+ <div class="panel-heading">
+ {{lang_mountIpxe}}
+ </div>
+ <div class="panel-body">
+ <p>{{lang_ipxeInfo}}</p>
+ <label for="ext">{{lang_extension}}:</label>
+ <select name="ext" class="form-control">
+ <option value="kkpxe">.kkpxe</option>
+ <option value="usb">.usb</option>
+ <option value="iso">.iso</option>
+ </select>
+ <br>
+ <form method="post" action="?do=ServerSetup" style="display:inline;">
+ <input type="hidden" name="action" value="save-script">
+ <input type="hidden" name="token" value="{{token}}">
+
+ <label for="custom-script">{{lang_customScript}}</label>
+ <textarea class="form-control" name="custom-script" rows="9" style="resize:none">{{script}}</textarea>
+ <br>
+ <input class="btn btn-default btn-sm" type="submit" value="{{lang_saveScript}}" />
+ </form>
+ <form method="post" action="?do=ServerSetup" style="display:inline;">
+ <input type="hidden" name="action" value="default-script">
+ <input type="hidden" name="token" value="{{token}}">
+ <input class="btn btn-default btn-sm" type="submit" value="{{lang_restoreDefault}}" />
+ </form>
+ </div>
+ <div class="panel-footer">
+ <button id="mount-button" onclick="mountIpxe();" class="btn btn-primary" type="button" data-toggle="modal" data-target="#ipxe-modal" data-backdrop="static"> {{lang_compile}}
+ </button>
+ </div>
+</div>
+
+<form method="post" action="?do=ServerSetup">
+ <input type="text" name="prevent_autofill" id="prevent_autofill" value="" style="display:none;">
+ <input type="password" name="password_fake" id="password_fake" value="" style="display:none;">
+ <input type="hidden" name="action" value="ipxe">
+ <input type="hidden" name="token" value="{{token}}">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ {{lang_bootMenu}}
+ </div>
+ <div class="panel-body">
+ <p>
+ {{lang_bootInfo}}
+ </p>
+ <br>
+
+ <div class="form-group">
+ <strong>{{lang_bootBehavior}}</strong>
+ <div><label class="radio-inline"><input type="radio" name="defaultentry" value="net" {{active-net}}> bwLehrpool</label></div>
+ <div><label class="radio-inline"><input type="radio" name="defaultentry" value="hdd" {{active-hdd}}> {{lang_localHDD}}</label></div>
+ <div><label class="radio-inline"><input type="radio" name="defaultentry" value="custom" {{active-custom}}> {{lang_customEntry}} (&quot;custom&quot;)</label></div>
+ </div>
+
+ <div class="form-group">
+ <strong>{{lang_menuDisplayTime}}</strong>
+ <div class="input-group form-narrow">
+ <input type="text" class="form-control" name="timeout" value="{{timeout}}" pattern="\d+">
+ <span class="input-group-addon">{{lang_seconds}}</span>
+ </div>
+ </div>
+
+ <div class="form-group">
+ <strong>{{lang_masterPassword}}</strong>
+ <div class="form-narrow">
+ <input type="{{password_type}}" class="form-control" name="masterpassword" value="{{masterpasswordclear}}">
+ </div>
+ <i>{{lang_masterPasswordHelp}}</i>
+ </div>
+
+ <div class="form-group">
+ <strong>{{lang_menuCustom}}</strong> <a class="btn btn-default btn-xs" data-toggle="modal" data-target="#help-custom"><span class="glyphicon glyphicon-question-sign"></span></a>
+ <textarea class="form-control" name="custom" rows="8">{{custom}}</textarea>
+ </div>
+ </div>
+
+ <div class="panel-footer">
+ <button class="btn btn-primary" name="action" value="ipxe">{{lang_bootMenuCreate}}</button>
+ </div>
+ </div>
+</form>
+
+<div class="modal fade" id="help-custom" tabindex="-1" role="dialog">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">{{lang_menuCustom}}</div>
+ <div class="modal-body">
+ {{lang_menuCustomHint1}}
+ <br>{{lang_example}}:
+ <pre>LABEL custom
+ MENU LABEL ^My Boot Entry
+ KERNEL http://1.2.3.4/kernel
+ INITRD http://1.2.3.4/initramfs-stage31
+ APPEND custom=option
+ IPAPPEND 3</pre>
+ {{lang_menuCustomHint2}} LABEL <strong>custom</strong>
+ {{lang_menuCustomHint3}}
+ </div>
+ <div class="modal-footer"><a class="btn btn-primary" data-dismiss="modal">{{lang_close}}</a></div>
+ </div>
+ </div>
+</div>
+
+<div class="modal fade" id="ipxe-modal" tabindex="-1" role="dialog" aria-labelledby="ipxe-modal-label" aria-hidden="true">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+ <h4 class="modal-title" id="ipxe-modal-label">{{lang_compilingIpxe}}</h4>
+ </div>
+ <div class="modal-body" id="ipxe-modal-body">
+
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">{{lang_cancel}}</button>
+ <button id="download-btn" type="button" class="btn btn-primary" disabled="disabled" onclick="downloadIpxe()">{{lang_download}}</button>
+ </div>
+ </div>
+ </div>
+</div>
+
+<script>
+ function mountIpxe() {
+ document.getElementById('ipxe-modal-body').innerHTML = "<div class='alert alert-info' role='alert'>{{lang_ipxeWarning}}</div>"
+ + "{{lang_loading}} <img src='fonts/loader.gif'/>";
+ $("#download-btn").prop("disabled",true);
+ var xmlhttp = new XMLHttpRequest();
+ var extension = $("select[name=ext]").val();
+ xmlhttp.open("GET","?do=ServerSetup&async=true&submitTask=true&extension=" + extension,true);
+ xmlhttp.onreadystatechange= function() {
+ if (xmlhttp.readyState==4 && xmlhttp.status==200) {
+ var initResponse = xmlhttp.responseText;
+ if(initResponse != "success")
+ document.getElementById('ipxe-modal-body').innerHTML = initResponse;
+ else {
+ document.getElementById('ipxe-modal-body').innerHTML = "{{lang_success}}: ipxe." + extension;
+ $("#download-btn").prop("disabled",false);
+ }
+ }
+ }
+ xmlhttp.send();
+ }
+
+ function downloadIpxe() {
+ window.location = "?do=ServerSetup&download=" + $("select[name=ext]").val();
+ }
+</script>
diff --git a/modules/serversetup/templates/ipxe_update.html b/modules/serversetup/templates/ipxe_update.html
new file mode 100644
index 00000000..9c598667
--- /dev/null
+++ b/modules/serversetup/templates/ipxe_update.html
@@ -0,0 +1,20 @@
+<div class="panel panel-default">
+ <div class="panel-heading">{{lang_menuGeneration}}</div>
+ <div class="panel-body">
+ <div data-tm-id="{{taskid}}" data-tm-log="error" data-tm-callback="restartCb">{{lang_menuGeneration}}</div>
+ <div id="genfailed" class="alert alert-danger" style="display:none">
+ {{lang_generationFailed}}
+ </div>
+ </div>
+</div>
+
+<script type="text/javascript">
+ function restartCb(task)
+ {
+ if (!task || !task.statusCode)
+ return;
+ if (task.statusCode === 'TASK_ERROR') {
+ $('#genfailed').show('slow');
+ }
+ }
+</script>