summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJannik Schönartz2019-05-05 22:58:34 +0200
committerJannik Schönartz2019-05-05 22:58:34 +0200
commitc6141d8aba461e2ff7851087c5801fa2cd156265 (patch)
tree5a4e68ff879431f6c9c42ea02c0b9a9f837a2649
parent[webapp] very small ui changes (diff)
downloadbas-c6141d8aba461e2ff7851087c5801fa2cd156265.tar.gz
bas-c6141d8aba461e2ff7851087c5801fa2cd156265.tar.xz
bas-c6141d8aba461e2ff7851087c5801fa2cd156265.zip
[ipxe builder] Merge efi and bios ipxe builder to one tab & add parameters ui
[server] Remove all req, res from the shell.js library Add ipxe config for the build parameters & parameter list Add api getter/setter methods for the ipxe config [webapp] Add ui for repository, branch and build targets Output: All of the scroll to bottom is now clickable
-rw-r--r--server/.gitignore4
-rw-r--r--server/api/ipxe.js83
-rw-r--r--server/config/ipxe.template.json9
-rw-r--r--server/ipxe/console.h (renamed from server/ipxe/console_bios.h)0
-rw-r--r--server/ipxe/console_efi.h69
-rw-r--r--server/ipxe/embedded.ipxe (renamed from server/ipxe/embedded_bios.ipxe)8
-rw-r--r--server/ipxe/embedded_efi.ipxe16
-rw-r--r--server/ipxe/general.h (renamed from server/ipxe/general_bios.h)0
-rw-r--r--server/ipxe/general_efi.h205
-rw-r--r--server/lib/shell.js140
-rw-r--r--webapp/src/components/IpxeBuilderModule.vue18
-rw-r--r--webapp/src/components/IpxeBuilderModuleConfig.vue224
12 files changed, 325 insertions, 451 deletions
diff --git a/server/.gitignore b/server/.gitignore
index c74fd45..94cc4f7 100644
--- a/server/.gitignore
+++ b/server/.gitignore
@@ -4,8 +4,8 @@
/config/*
!/config/*.template.json
-/ipxe/ipxe_*
-/ipxe/log_*
+/ipxe/ipxeGIT
+/ipxe/ipxelog
.DS_Store
node_modules/
diff --git a/server/api/ipxe.js b/server/api/ipxe.js
index 2e89e32..7b5ad85 100644
--- a/server/api/ipxe.js
+++ b/server/api/ipxe.js
@@ -7,30 +7,30 @@ var router = express.Router()
var noAuthRouter = express.Router()
// GET requests.
-router.get('/:version/script', (req, res) => {
+router.get('/script', (req, res) => {
res.setHeader('content-type', 'text/plain')
- res.sendFile(path.join(__appdir, 'ipxe', 'embedded_' + req.params.version + '.ipxe'))
+ res.sendFile(path.join(__appdir, 'ipxe', 'embedded.ipxe'))
})
-router.get('/:version/certificate', (req, res) => {
+router.get('/certificate', (req, res) => {
res.setHeader('content-type', 'text/plain')
res.sendFile(path.join(__appdir, 'bin', 'fullchain.pem'))
})
-router.get('/:version/general', (req, res) => {
+router.get('/general', (req, res) => {
res.setHeader('content-type', 'text/plain')
- res.sendFile(path.join(__appdir, 'ipxe', 'general_' + req.params.version + '.h'))
+ res.sendFile(path.join(__appdir, 'ipxe', 'general.h'))
})
-router.get('/:version/console', (req, res) => {
+router.get('/console', (req, res) => {
res.setHeader('content-type', 'text/plain')
- res.sendFile(path.join(__appdir, 'ipxe', 'console_' + req.params.version + '.h'))
+ res.sendFile(path.join(__appdir, 'ipxe', 'console.h'))
})
-router.get('/:version/log', async (req, res) => {
+router.get('/log', async (req, res) => {
const max = req.query.max ? req.query.max : -1
res.setHeader('content-type', 'text/plain')
- const filepath = path.join(__appdir, 'ipxe', 'log_' + req.params.version + '.txt')
+ const filepath = path.join(__appdir, 'ipxe', 'ipxelog.txt')
fs.readFile(filepath, 'utf-8', function (err, content) {
if (err) res.end()
@@ -42,13 +42,41 @@ router.get('/:version/log', async (req, res) => {
})
})
-router.put('/:version/:filename', (req, res) => {
+router.get('/config', (req, res) => {
+ delete require.cache[require.resolve(path.join(__appdir, 'config', 'ipxe'))]
+ var config = require(path.join(__appdir, 'config', 'ipxe'))
+ res.send(config)
+})
+
+router.post('/config', (req, res) => {
+ let buildTargets = req.body.buildTargets
+ const targetList = req.body.targetList
+ const branch = req.body.branch
+ const repository = req.body.repository
+ var config = require(path.join(__appdir, 'config', 'ipxe'))
+
+ if (repository) config.repository = repository
+ if (branch) config.branch = branch
+ if (targetList && config.targets.custom) config.targets.list = targetList
+
+ if (buildTargets) {
+ if (!config.targets.custom) buildTargets = buildTargets.filter(target => config.targets.list.indexOf(target) >= 0)
+ config.targets.build = buildTargets
+ }
+
+ fs.writeFile(path.join(__appdir, 'config', 'ipxe.json'), JSON.stringify(config, null, 4), {}, (err) => {
+ if (err) res.status(500).end()
+ else res.send()
+ })
+})
+
+router.put('/:filename', (req, res) => {
var filepath = null
// Set the file path
if (req.params.filename === 'script') {
- filepath = path.join(__appdir, 'ipxe', 'embedded_' + req.params.version + '.ipxe')
+ filepath = path.join(__appdir, 'ipxe', 'embedded.ipxe')
} else if (req.params.filename === 'console' || req.params.filename === 'general') {
- filepath = path.join(__appdir, 'ipxe', req.params.filename + '_' + req.params.version + '.h')
+ filepath = path.join(__appdir, 'ipxe', req.params.filename + '.h')
} else if (req.params.filename === 'certificate') {
filepath = path.join(__appdir, 'bin', 'fullchain.pem')
} else {
@@ -66,31 +94,24 @@ router.put('/:version/:filename', (req, res) => {
/*
* @return: Rebuild the ipxe.
*/
-router.get('/:version/build', async (req, res) => {
- if (req.params.version === 'efi' || req.params.version === 'bios') {
- shell.buildIpxe(req, res)
- } else {
- res.status(400).send({ status: 'error', msg: 'Unknown ipxe version (' + req.params.version + ')' })
- }
+router.get('/build', async (req, res) => {
+ delete require.cache[require.resolve(path.join(__appdir, 'config', 'ipxe'))]
+ const config = require(path.join(__appdir, 'config', 'ipxe'))
+ const build = await shell.buildIpxe(config.targets.build.join(' '), config.repository, config.branch)
+ res.send(build)
})
-router.get('/:version/cancel', async (req, res) => {
- if (req.params.version === 'efi' || req.params.version === 'bios') {
- shell.cancelBuilding(req, res)
- } else {
- res.status(400).send({ status: 'error', msg: 'Unknown ipxe version (' + req.params.version + ')' })
- }
+router.get('/cancel', async (req, res) => {
+ const result = await shell.cancelBuilding(req, res)
+ res.send(result)
})
-router.get('/:version/clean', (req, res) => {
- if (req.params.version === 'efi' || req.params.version === 'bios') {
- shell.clean(req, res)
- } else {
- res.status(400).send({ status: 'error', msg: 'Unknown ipxe version (' + req.params.version + ')' })
- }
+router.get('/clean', async (req, res) => {
+ const result = await shell.clean()
+ res.send(result)
})
-router.get('/:version/status', (req, res) => {
+router.get('/status', (req, res) => {
res.send({ status: 'SUCCESS', data: shell.status(req.params.version) })
})
diff --git a/server/config/ipxe.template.json b/server/config/ipxe.template.json
new file mode 100644
index 0000000..8f62dec
--- /dev/null
+++ b/server/config/ipxe.template.json
@@ -0,0 +1,9 @@
+{
+ "repository": "https://git.openslx.org/openslx-ng/ipxe.git",
+ "branch": "",
+ "targets": {
+ "build": ["bin-i386-pcbios/undionly.kpxe", "bin-x86_64-efi/snponly.efi"],
+ "list": ["bin-i386-pcbios/undionly.kpxe", "bin-x86_64-efi/snponly.efi"],
+ "custom": true
+ }
+} \ No newline at end of file
diff --git a/server/ipxe/console_bios.h b/server/ipxe/console.h
index bfc00d7..bfc00d7 100644
--- a/server/ipxe/console_bios.h
+++ b/server/ipxe/console.h
diff --git a/server/ipxe/console_efi.h b/server/ipxe/console_efi.h
deleted file mode 100644
index d351ee7..0000000
--- a/server/ipxe/console_efi.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef CONFIG_CONSOLE_H
-#define CONFIG_CONSOLE_H
-
-/** @file
- *
- * Console configuration
- *
- * These options specify the console types that iPXE will use for
- * interaction with the user.
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <config/defaults.h>
-
-/*
- * Default console types
- *
- * These are all enabled by default for the appropriate platforms.
- * You may disable them if needed.
- *
- */
-
-#undef CONSOLE_PCBIOS /* Default BIOS console */
-#define CONSOLE_EFI /* Default EFI console */
-//#undef CONSOLE_LINUX /* Default Linux console */
-
-/*
- * Additional console types
- *
- * These are not enabled by default, but may be useful in your
- * environment.
- *
- */
-
-#define CONSOLE_SERIAL /* Serial port console */
-#define CONSOLE_FRAMEBUFFER /* Graphical framebuffer console */
-#define CONSOLE_SYSLOG /* Syslog console */
-//#define CONSOLE_SYSLOGS /* Encrypted syslog console */
-//#define CONSOLE_VMWARE /* VMware logfile console */
-//#define CONSOLE_DEBUGCON /* Bochs/QEMU/KVM debug port console */
-//#define CONSOLE_INT13 /* INT13 disk log console */
-
-/*
- * Very obscure console types
- *
- * You almost certainly do not need to enable these.
- *
- */
-
-//#define CONSOLE_DIRECT_VGA /* Direct access to VGA card */
-//#define CONSOLE_PC_KBD /* Direct access to PC keyboard */
-
-/* Keyboard map (available maps in hci/keymap/) */
-#define KEYBOARD_MAP us
-
-/* Control which syslog() messages are generated.
- *
- * Note that this is not related in any way to CONSOLE_SYSLOG.
- */
-#define LOG_LEVEL LOG_NONE
-
-#include <config/named.h>
-#include NAMED_CONFIG(console.h)
-#include <config/local/console.h>
-#include LOCAL_NAMED_CONFIG(console.h)
-
-#endif /* CONFIG_CONSOLE_H */
diff --git a/server/ipxe/embedded_bios.ipxe b/server/ipxe/embedded.ipxe
index 8d6258a..d09689e 100644
--- a/server/ipxe/embedded_bios.ipxe
+++ b/server/ipxe/embedded.ipxe
@@ -1,14 +1,14 @@
#!ipxe
-################
-# BIOS Version #
-################
+###################
+# EMBEDDED SCRIPT #
+###################
ifopen
dhcp
# Wallpaper
-set img https://bas.intra.uni-freiburg.de/files/ipxe_wallpaper.png
+set img https://bas.intra.uni-freiburg.de/files/ipxe_wallpaper.png || goto loop
console --picture ${img} --x 800 --y 600
:loop
diff --git a/server/ipxe/embedded_efi.ipxe b/server/ipxe/embedded_efi.ipxe
deleted file mode 100644
index 09d3aaa..0000000
--- a/server/ipxe/embedded_efi.ipxe
+++ /dev/null
@@ -1,16 +0,0 @@
-#!ipxe
-
-################
-# EFI Version #
-################
-
-ifopen
-dhcp
-
-# Wallpaper
-set img https://bas.intra.uni-freiburg.de/files/ipxe_wallpaper.png
-console --picture ${img} --x 800 --y 600
-
-:loop
-chain https://bas.intra.uni-freiburg.de/api/configloader/${uuid}
-goto loop \ No newline at end of file
diff --git a/server/ipxe/general_bios.h b/server/ipxe/general.h
index 5ee8d0e..5ee8d0e 100644
--- a/server/ipxe/general_bios.h
+++ b/server/ipxe/general.h
diff --git a/server/ipxe/general_efi.h b/server/ipxe/general_efi.h
deleted file mode 100644
index 1f60fa2..0000000
--- a/server/ipxe/general_efi.h
+++ /dev/null
@@ -1,205 +0,0 @@
-#ifndef CONFIG_GENERAL_H
-#define CONFIG_GENERAL_H
-
-/** @file
- *
- * General configuration
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <config/defaults.h>
-
-/*
- * Banner timeout configuration
- *
- * This controls the timeout for the "Press Ctrl-B for the iPXE
- * command line" banner displayed when iPXE starts up. The value is
- * specified in tenths of a second for which the banner should appear.
- * A value of 0 disables the banner.
- *
- * ROM_BANNER_TIMEOUT controls the "Press Ctrl-B to configure iPXE"
- * banner displayed only by ROM builds of iPXE during POST. This
- * defaults to being twice the length of BANNER_TIMEOUT, to allow for
- * BIOSes that switch video modes immediately before calling the
- * initialisation vector, thus rendering the banner almost invisible
- * to the user.
- */
-#define BANNER_TIMEOUT 20
-#define ROM_BANNER_TIMEOUT ( 2 * BANNER_TIMEOUT )
-
-/*
- * Network protocols
- *
- */
-
-#define NET_PROTO_IPV4 /* IPv4 protocol */
-#undef NET_PROTO_IPV6 /* IPv6 protocol */
-#undef NET_PROTO_FCOE /* Fibre Channel over Ethernet protocol */
-#define NET_PROTO_STP /* Spanning Tree protocol */
-#define NET_PROTO_LACP /* Link Aggregation control protocol */
-
-/*
- * PXE support
- *
- */
-#undef PXE_STACK /* PXE stack in iPXE - you want this! */
-#undef PXE_MENU /* PXE menu booting */
-
-/*
- * Download protocols
- *
- */
-
-#define DOWNLOAD_PROTO_TFTP /* Trivial File Transfer Protocol */
-#define DOWNLOAD_PROTO_HTTP /* Hypertext Transfer Protocol */
-#define DOWNLOAD_PROTO_HTTPS /* Secure Hypertext Transfer Protocol */
-#undef DOWNLOAD_PROTO_FTP /* File Transfer Protocol */
-#undef DOWNLOAD_PROTO_SLAM /* Scalable Local Area Multicast */
-#undef DOWNLOAD_PROTO_NFS /* Network File System Protocol */
-//#undef DOWNLOAD_PROTO_FILE /* Local filesystem access */
-
-/*
- * SAN boot protocols
- *
- */
-
-//#undef SANBOOT_PROTO_ISCSI /* iSCSI protocol */
-//#undef SANBOOT_PROTO_AOE /* AoE protocol */
-//#undef SANBOOT_PROTO_IB_SRP /* Infiniband SCSI RDMA protocol */
-//#undef SANBOOT_PROTO_FCP /* Fibre Channel protocol */
-//#undef SANBOOT_PROTO_HTTP /* HTTP SAN protocol */
-
-/*
- * HTTP extensions
- *
- */
-#define HTTP_AUTH_BASIC /* Basic authentication */
-#define HTTP_AUTH_DIGEST /* Digest authentication */
-//#define HTTP_AUTH_NTLM /* NTLM authentication */
-//#define HTTP_ENC_PEERDIST /* PeerDist content encoding */
-//#define HTTP_HACK_GCE /* Google Compute Engine hacks */
-
-/*
- * 802.11 cryptosystems and handshaking protocols
- *
- */
-#define CRYPTO_80211_WEP /* WEP encryption (deprecated and insecure!) */
-#define CRYPTO_80211_WPA /* WPA Personal, authenticating with passphrase */
-#define CRYPTO_80211_WPA2 /* Add support for stronger WPA cryptography */
-
-/*
- * Name resolution modules
- *
- */
-
-#define DNS_RESOLVER /* DNS resolver */
-
-/*
- * Image types
- *
- * Etherboot supports various image formats. Select whichever ones
- * you want to use.
- *
- */
-//#define IMAGE_NBI /* NBI image support */
-//#define IMAGE_ELF /* ELF image support */
-//#define IMAGE_MULTIBOOT /* MultiBoot image support */
-//#define IMAGE_PXE /* PXE image support */
-//#define IMAGE_SCRIPT /* iPXE script image support */
-//#define IMAGE_BZIMAGE /* Linux bzImage image support */
-//#define IMAGE_COMBOOT /* SYSLINUX COMBOOT image support */
-//#define IMAGE_EFI /* EFI image support */
-//#define IMAGE_SDI /* SDI image support */
-//#define IMAGE_PNM /* PNM image support */
-#define IMAGE_PNG /* PNG image support */
-#define IMAGE_DER /* DER image support */
-#define IMAGE_PEM /* PEM image support */
-
-/*
- * Command-line commands to include
- *
- */
-#define AUTOBOOT_CMD /* Automatic booting */
-#define NVO_CMD /* Non-volatile option storage commands */
-#define CONFIG_CMD /* Option configuration console */
-#define IFMGMT_CMD /* Interface management commands */
-#define IWMGMT_CMD /* Wireless interface management commands */
-#define IBMGMT_CMD /* Infiniband management commands */
-#define FCMGMT_CMD /* Fibre Channel management commands */
-#define ROUTE_CMD /* Routing table management commands */
-#define IMAGE_CMD /* Image management commands */
-#define DHCP_CMD /* DHCP management commands */
-#define SANBOOT_CMD /* SAN boot commands */
-#define MENU_CMD /* Menu commands */
-#define LOGIN_CMD /* Login command */
-#define SYNC_CMD /* Sync command */
-#define SHELL_CMD /* Shell command */
-#define NSLOOKUP_CMD /* DNS resolving command */
-//#define TIME_CMD /* Time commands */
-//#define DIGEST_CMD /* Image crypto digest commands */
-//#define LOTEST_CMD /* Loopback testing commands */
-//#define VLAN_CMD /* VLAN commands */
-//#define PXE_CMD /* PXE commands */
-#define REBOOT_CMD /* Reboot command */
-#define POWEROFF_CMD /* Power off command */
-//#define IMAGE_TRUST_CMD /* Image trust management commands */
-//#define PCI_CMD /* PCI commands */
-#define PARAM_CMD /* Form parameter commands */
-//#define NEIGHBOUR_CMD /* Neighbour management commands */
-//#define PING_CMD /* Ping command */
-#define CONSOLE_CMD /* Console command */
-//#define IPSTAT_CMD /* IP statistics commands */
-//#define PROFSTAT_CMD /* Profiling commands */
-//#define NTP_CMD /* NTP commands */
-//#define CERT_CMD /* Certificate management commands */
-
-/*
- * ROM-specific options
- *
- */
-#undef NONPNP_HOOK_INT19 /* Hook INT19 on non-PnP BIOSes */
-#define AUTOBOOT_ROM_FILTER /* Autoboot only devices matching our ROM */
-
-/*
- * Virtual network devices
- *
- */
-#define VNIC_IPOIB /* Infiniband IPoIB virtual NICs */
-//#define VNIC_XSIGO /* Infiniband Xsigo virtual NICs */
-
-/*
- * Error message tables to include
- *
- */
-#undef ERRMSG_80211 /* All 802.11 error descriptions (~3.3kb) */
-
-/*
- * Obscure configuration options
- *
- * You probably don't need to touch these.
- *
- */
-
-#undef BUILD_SERIAL /* Include an automatic build serial
- * number. Add "bs" to the list of
- * make targets. For example:
- * "make bin/rtl8139.dsk bs" */
-#undef BUILD_ID /* Include a custom build ID string,
- * e.g "test-foo" */
-#undef NULL_TRAP /* Attempt to catch NULL function calls */
-#undef GDBSERIAL /* Remote GDB debugging over serial */
-#undef GDBUDP /* Remote GDB debugging over UDP
- * (both may be set) */
-//#define EFI_DOWNGRADE_UX /* Downgrade UEFI user experience */
-#define TIVOLI_VMM_WORKAROUND /* Work around the Tivoli VMM's garbling of SSE
- * registers when iPXE traps to it due to
- * privileged instructions */
-
-#include <config/named.h>
-#include NAMED_CONFIG(general.h)
-#include <config/local/general.h>
-#include LOCAL_NAMED_CONFIG(general.h)
-
-#endif /* CONFIG_GENERAL_H */
diff --git a/server/lib/shell.js b/server/lib/shell.js
index 863e06b..ed2f4cd 100644
--- a/server/lib/shell.js
+++ b/server/lib/shell.js
@@ -1,87 +1,68 @@
/* global __appdir */
var path = require('path')
var shell = require('shelljs')
-// var child = require('child_process')
-// var ipxeGIT = 'git://git.ipxe.org/ipxe.git'
-var ipxeGIT = 'http://git.ipxe.org/ipxe.git'
var io = require(path.join(__appdir, 'lib', 'socketio'))
const fs = require('fs')
-
// Only one building process per version at a time.
-var building = { efi: false, bios: false }
-var make = {}
module.exports = {
- buildIpxe: async function (req, res) {
- const ipxeVersion = req.params.version
-
- // Different make commands for efi / bios are needed.
+ buildIpxe: async function (buildParameter = '', gitURL = 'http://git.ipxe.org/ipxe.git', gitBranch = '') {
var makeCmd = ''
- // Only one building process can be running.
- if (!building[ipxeVersion]) {
- makeCmd = 'make '
- if (ipxeVersion === 'efi') makeCmd += 'bin-x86_64-efi/snponly.efi '
- makeCmd += 'EMBED=' + path.join(__appdir, 'ipxe', 'embedded_' + ipxeVersion + '.ipxe') + ' TRUST=' + path.join(__appdir, 'bin', 'fullchain.pem')// + ' bin/undionly.kpxe'
-
- updateInProgress(ipxeVersion, true)
- } else {
- res.send({ status: 'ALREADY_BUILDING', error: 'Building ' + ipxeVersion + '-iPXE is already in progress.' })
- return
- }
- // Sending feedback, that the ipxe building progress started.
- res.status(200).send({ status: 'SUCCESS', msg: 'Starting iPXE building process' })
+ // Only one building process can be running. (lock the ipxe directory)
+ // TODO:
+ // If file is already locked
+ // if (false) return { status: 'ALREADY_BUILDING', error: 'iPXE-building process is already in progress.' }
+
+ makeCmd = 'make ' + buildParameter
+ makeCmd += ' EMBED=' + path.join(__appdir, 'ipxe', 'embedded.ipxe')
+ makeCmd += ' TRUST=' + path.join(__appdir, 'bin', 'fullchain.pem')
// Cloning git.
- sendToLog(ipxeVersion, 'Cloning git ...\n', 'primary')
- await cloneIpxe(ipxeVersion)
- if (!building[ipxeVersion]) return
+ sendToLog('Cloning git ...\n', 'primary')
+ await cloneIpxe(gitURL, gitBranch)
// Copying configs.
- sendToLog(ipxeVersion, 'Copying configs ...\n', 'primary')
- copyConfigs(ipxeVersion)
- if (!building[ipxeVersion]) return
+ sendToLog('Copying configs ...\n', 'primary')
+ copyConfigs()
// Make ipxe.
- sendToLog(ipxeVersion, 'Make iPXE ...\n', 'primary')
- shell.cd(path.join(__appdir, 'ipxe', 'ipxe_' + ipxeVersion, 'src'))
+ sendToLog('Make iPXE ...\n', 'primary')
+ shell.cd(path.join(__appdir, 'ipxe', 'ipxeGIT', 'src'))
await new Promise((resolve, reject) => {
- if (!building[ipxeVersion]) return
- make[ipxeVersion] = shell.exec(makeCmd, { async: true }, () => {
- // make[ipxeVersion] = child.exec(makeCmd, { async: true }, () => {
+ const process = shell.exec(makeCmd, { async: true }, () => {
resolve()
})
// Send the output to the frontend log.
- make[ipxeVersion].stdout.on('data', data => {
+ process.stdout.on('data', data => {
const multiline = data.split('\n')
if (multiline.length > 2) {
multiline.forEach(line => {
- if (line) sendToLog(ipxeVersion, line, 'normal')
+ if (line) sendToLog(line, 'normal')
})
- } else sendToLog(ipxeVersion, data, 'normal')
+ } else sendToLog(data, 'normal')
})
- make[ipxeVersion].stderr.on('data', data => {
+ process.stderr.on('data', data => {
const multiline = data.split('\n')
if (multiline.length > 2) {
multiline.forEach(line => {
- if (line) sendToLog(ipxeVersion, line, 'error')
+ if (line) sendToLog(line, 'error')
})
- } else sendToLog(ipxeVersion, data, 'error')
+ } else sendToLog(data, 'error')
})
})
-
- if (!building[ipxeVersion]) return
// Copy and rename the ipxe file.
- sendToLog(ipxeVersion, 'Copying ipxe file ...\n', 'primary')
- shell.cp('bin/undionly.kpxe', path.join(__appdir, 'ipxe'))
- shell.mv(path.join(__appdir, 'ipxe', 'undionly.kpxe'), path.join(__appdir, 'ipxe', 'ipxe.' + ipxeVersion))
- sendToLog(ipxeVersion, 'done\n', 'success')
- updateInProgress(ipxeVersion, false)
+ // sendToLog('Copying ipxe file ...\n', 'primary')
+ // shell.cp('bin/undionly.kpxe', path.join(__appdir, 'ipxe'))
+ // shell.mv(path.join(__appdir, 'ipxe', 'undionly.kpxe'), path.join(__appdir, 'ipxe', 'ipxe.' + ipxeVersion))
+ // sendToLog(ipxeVersion, 'done\n', 'success')
+ // updateInProgress(ipxeVersion, false)
},
- cancelBuilding: async function (req, res) {
+ cancelBuilding: async function () {
+ /*
const ipxeVersion = req.params.version
const process = make[ipxeVersion]
if (process) {
@@ -90,66 +71,55 @@ module.exports = {
updateInProgress(ipxeVersion, false)
}
res.send({ status: 'SUCCESS', data: process })
+ */
},
- clean: async function (req, res) {
- const ipxeVersion = req.params.version
- if (building[ipxeVersion]) {
- res.send({ status: 'ALREADY_BUILDING', error: 'Can\'t clean, while building' + ipxeVersion + '-iPXE is in progress.' })
- return
- } else {
- updateInProgress(ipxeVersion, true)
- res.send({ status: 'SUCCESS', msg: 'Cleaning iPXE started' })
- }
+ clean: async function () {
+ // If building return
+ // return { status: 'ALREADY_BUILDING', error: 'Can\'t clean, while iPXE-building is in progress.' }
+ // TODO more logging of what get's deleted
shell.cd(path.join(__appdir, 'ipxe'))
- shell.rm('-rf', 'ipxe_' + ipxeVersion)
- shell.rm(path.join(__appdir, 'ipxe', 'ipxe.' + ipxeVersion))
- shell.rm(path.join(__appdir, 'ipxe', 'log_' + ipxeVersion + '.txt'))
- updateInProgress(ipxeVersion, false)
- sendToLog(ipxeVersion, 'iPXE files successfully cleaned', 'success', false)
+ shell.rm('-rf', 'ipxeGIT')
+ shell.rm(path.join(__appdir, 'ipxe', 'ipxelog.txt'))
+ sendToLog('iPXE files successfully cleaned', 'success', false)
+ return { status: 'SUCCESS', msg: 'Cleaning iPXE started' }
},
status: function (ipxeVersion) {
- return building[ipxeVersion]
+ return false
}
}
-async function cloneIpxe (ipxeVersion) {
+async function cloneIpxe (url, branch) {
// Check if git is installed on the server.
- if (!shell.which('git')) {
- return { status: 'GIT_MISSING', error: 'Please install git on the server.' }
- }
+ if (!shell.which('git')) return { status: 'GIT_MISSING', error: 'Please install git on the server.' }
shell.cd(path.join(__appdir, 'ipxe'))
return new Promise((resolve, reject) => {
- var clone = shell.exec('git clone ' + ipxeGIT + ' ipxe_' + ipxeVersion, { async: true }, () => {
+ let command = 'git clone ' + url
+ if (branch) command += ' --branch ' + branch + ' --single-branch'
+ var clone = shell.exec(command + ' ipxeGIT', { async: true }, () => {
resolve()
})
clone.stdout.on('data', data => {
- sendToLog(ipxeVersion, data, 'normal')
+ sendToLog(data, 'normal')
})
clone.stderr.on('data', data => {
- sendToLog(ipxeVersion, data, 'error')
+ sendToLog(data, 'error')
})
})
}
function copyConfigs (ipxeVersion) {
// Remove the default configs and paste in the customized ones.
- shell.rm(path.join(__appdir, 'ipxe', 'ipxe_' + ipxeVersion, 'src', 'config', 'general.h'))
- shell.rm(path.join(__appdir, 'ipxe', 'ipxe_' + ipxeVersion, 'src', 'config', 'console.h'))
- shell.cp(path.join(__appdir, 'ipxe', 'general_' + ipxeVersion + '.h'), path.join(__appdir, 'ipxe', 'ipxe_' + ipxeVersion, 'src', 'config', 'general.h'))
- shell.cp(path.join(__appdir, 'ipxe', 'console_' + ipxeVersion + '.h'), path.join(__appdir, 'ipxe', 'ipxe_' + ipxeVersion, 'src', 'config', 'console.h'))
-}
-
-function updateInProgress (ipxeVersion, inProgress) {
- building[ipxeVersion] = inProgress
- const event = ipxeVersion + ' inProgress'
- io.in('broadcast ipxeBuild').emit(event, inProgress)
+ shell.rm(path.join(__appdir, 'ipxe', 'ipxeGIT', 'src', 'config', 'general.h'))
+ shell.rm(path.join(__appdir, 'ipxe', 'ipxeGIT', 'src', 'config', 'console.h'))
+ shell.cp(path.join(__appdir, 'ipxe', 'general.h'), path.join(__appdir, 'ipxe', 'ipxeGIT', 'src', 'config', 'general.h'))
+ shell.cp(path.join(__appdir, 'ipxe', 'console.h'), path.join(__appdir, 'ipxe', 'ipxeGIT', 'src', 'config', 'console.h'))
}
-function sendToLog (ipxeVersion, msg, status, log = true) {
+function sendToLog (msg, status, log = true) {
const date = new Date()
const pad = x => x < 10 ? '0' + x : x
var dateString = '[' + date.getFullYear() + '-'
@@ -161,13 +131,13 @@ function sendToLog (ipxeVersion, msg, status, log = true) {
const logEntry = { date: dateString, status: status, msg: msg }
- const event = ipxeVersion + ' log'
+ const event = 'log'
io.in('broadcast ipxeBuild').emit(event, logEntry)
- if (log) writeLog(ipxeVersion, logEntry)
+ if (log) writeLog(logEntry)
}
-function writeLog (ipxeVersion, logEntry) {
- fs.writeFile(path.join(__appdir, 'ipxe', 'log_' + ipxeVersion + '.txt'), logEntry.date + '\t' + logEntry.status + '\t' + logEntry.msg, { flag: 'a+' }, (err) => {
+function writeLog (logEntry) {
+ fs.writeFile(path.join(__appdir, 'ipxe', 'ipxelog.txt'), logEntry.date + '\t' + logEntry.status + '\t' + logEntry.msg, { flag: 'a+' }, (err) => {
if (err) throw err
})
}
diff --git a/webapp/src/components/IpxeBuilderModule.vue b/webapp/src/components/IpxeBuilderModule.vue
index f72e6ef..e2c38ff 100644
--- a/webapp/src/components/IpxeBuilderModule.vue
+++ b/webapp/src/components/IpxeBuilderModule.vue
@@ -1,12 +1,10 @@
<i18n>
{
"en": {
- "efi": "EFI",
- "bios": "BIOS"
+ "ipxe": "iPXE"
},
"de": {
- "efi": "EFI",
- "bios": "BIOS"
+ "ipxe": "iPXE"
}
}
</i18n>
@@ -16,20 +14,14 @@
<v-layout>
<v-flex xl10 offset-xl1 lg12>
<v-card class="tabbar-card">
- <v-tabs v-model="tabs" grow :dark="tabsDark" :color="tabsColor" :slider-color="tabsSliderColor">
- <v-tab><v-icon class="tabbar-tabicon">memory</v-icon>{{ $t('efi') }}</v-tab>
- <v-tab><v-icon class="tabbar-tabicon">memory</v-icon>{{ $t('bios') }}</v-tab>
+ <v-tabs v-model="tabs" grow :dark="tabsDark" :color="tabsColor" :slider-color="tabsSliderColor" hide-slider>
+ <v-tab><v-icon class="tabbar-tabicon">memory</v-icon>{{ $t('ipxe') }}</v-tab>
</v-tabs>
</v-card>
-
<v-tabs-items v-model="tabs" style="padding-bottom: 20px">
<v-tab-item lazy :transition="false" :reverse-transition="false">
- <ipxe-builder-module-config :ipxeVersion="'efi'"></ipxe-builder-module-config>
- </v-tab-item>
- <v-tab-item lazy :transition="false" :reverse-transition="false">
- <ipxe-builder-module-config :ipxeVersion="'bios'"></ipxe-builder-module-config>
+ <ipxe-builder-module-config></ipxe-builder-module-config>
</v-tab-item>
-
</v-tabs-items>
</v-flex>
</v-layout>
diff --git a/webapp/src/components/IpxeBuilderModuleConfig.vue b/webapp/src/components/IpxeBuilderModuleConfig.vue
index 638de2d..230e82a 100644
--- a/webapp/src/components/IpxeBuilderModuleConfig.vue
+++ b/webapp/src/components/IpxeBuilderModuleConfig.vue
@@ -3,8 +3,10 @@
"en": {
"alreadyBuiling": "The iPXE building process not finished",
"bios": "BIOS",
+ "branchName": "Branch Name",
"buildingIpxe": "Building iPXE ...",
"buildIpxe": "Build iPXE",
+ "buildTargetsLabel": "Build Targets",
"cancelIpxe": "Cancel iPXE",
"certificateSaved": "Certificate saved successfully",
"cleaningIpxe": "Cleaning iPXE ...",
@@ -15,8 +17,11 @@
"general": "general.h",
"generalSaved": "general.h saved successfully",
"ipxe": "iPXE",
- "scripts": "Scripts",
+ "output": "Output",
+ "parameters": "Parameters",
+ "repoUrl": "Repository URL",
"script": "Embedded script (EMBED=)",
+ "scripts": "Scripts",
"scriptSaved": "Embedded script saved successfully",
"scrollDown": "Go to the bottom",
"trust": "Embedded certificate (TRUST=)"
@@ -24,8 +29,10 @@
"de": {
"alreadyBuiling": "Der iPXE build-Prozess ist noch nicht abgeschlossen",
"bios": "BIOS",
+ "branchName": "Branch Name",
"buildingIpxe": "iPXE wird gebaut ...",
"buildIpxe": "iPXE bauen",
+ "buildTargetsLabel": "Build Targets",
"cancelIpxe": "iPXE stoppen",
"certificateSaved": "Zertifikat wurde erfolgreich gespeichert",
"console": "console.h",
@@ -35,9 +42,12 @@
"efi": "EFI",
"general": "general.h",
"generalSaved": "general.h wurde erfolgreich gespeichert",
- "scripts": "Skripte",
"ipxe": "iPXE",
+ "output": "Output",
+ "parameters": "Parameter",
+ "repoUrl": "Repository URL",
"script": "Eingebettetes Skript (EMBED=)",
+ "scripts": "Skripte",
"scriptSaved": "Eingebettetes Skript wurde erfolgreich gespeichert",
"scrollDown": "Gehe nach unten",
"trust": "Eingebettetes Zertifikat (TRUST=)"
@@ -47,8 +57,116 @@
<template>
<div>
- <v-subheader>{{ $t('ipxe') }}</v-subheader>
+ <v-subheader>{{ $t('parameters') }}</v-subheader>
+ <v-card>
+ <v-card-text>
+ <v-layout wrap>
+
+ <v-flex lg5 md8 sm8 xs12 order-lg1 order-md1 order-sm1 order-xs2>
+ <v-layout column>
+ <div class="info-input">
+ <div class="info-heading"><v-icon>label</v-icon><span>{{ $t('repoUrl') }}</span></div>
+ <div v-if="!editParametersMode" class="info-text">{{ repoUrl }}</div>
+ <v-text-field v-else v-model="repoUrl" class="info-text pa-0" hide-details></v-text-field>
+ </div>
+ </v-layout>
+ </v-flex>
+
+ <v-flex lg4 md6 sm6 xs12 order-lg2 order-md4 order-sm4 order-xs3>
+ <v-layout column>
+ <div class="info-input">
+ <div class="info-heading"><v-icon>label</v-icon><span>{{ $t('branchName') }}</span></div>
+ <div v-if="!editParametersMode" class="info-text">{{ branchName }}</div>
+ <v-text-field v-else v-model="branchName" class="info-text pa-0" hide-details></v-text-field>
+ </div>
+ </v-layout>
+ </v-flex>
+
+ <v-flex lg9 md6 sm6 xs12 order-lg4 order-md3 order-sm3 order-xs4>
+ <v-layout column>
+ <div class="info-input">
+ <div class="info-heading"><v-icon>my_location</v-icon><span>{{ $t('buildTargetsLabel') }}</span></div>
+
+ <div v-if="!editParametersMode" class="non-selectable info-text">
+ <v-chip v-for="target in buildTargets" :key="target" small>
+ <span class="chip-text">{{ target }}</span>
+ </v-chip>
+ </div>
+ <v-select
+ class="info-text"
+ v-else-if="editParametersMode && !allowCustomTargets"
+ v-model="buildTargets"
+ :items=targets
+ multiple
+ small-chips
+ menu-props="offsetY"
+ >
+ </v-select>
+ <v-combobox
+ class="info-text"
+ v-else-if="editParametersMode && allowCustomTargets"
+ v-model="buildTargets"
+ :items="targets"
+ :search-input.sync="search"
+ hide-selected
+ multiple
+ persistent-hint
+ small-chips
+ deletable-chips
+ hide-details
+ dense
+ style="padding: 0px"
+ @input="createTarget"
+ >
+ <template #no-data>
+ <v-list-tile>
+ <v-list-tile-content>
+ <v-list-tile-title>
+ No results matching "<strong>{{ search }}</strong>". Press <kbd>enter</kbd> to create a new one
+ </v-list-tile-title>
+ </v-list-tile-content>
+ </v-list-tile>
+ </template>
+
+ <template #item="{ index, item }">
+ <v-list-tile-content>
+ {{ item }}
+ </v-list-tile-content>
+ <v-list-tile-action @click.stop>
+ <v-btn icon @click.stop.prevent="deleteTarget(item)">
+ <v-icon color="error">delete</v-icon>
+ </v-btn>
+ </v-list-tile-action>
+ </template>
+
+ </v-combobox>
+
+ </div>
+ </v-layout>
+ </v-flex>
+ <v-flex v-if="!editParametersMode" lg3 md4 sm4 xs12 order-lg3 order-md2 order-sm2 order-xs1 class="text-xs-right">
+ <div class="info-input">
+ <v-btn color="primary" flat @click="editParameters" class="info-buttons">
+ <v-icon left>create</v-icon>{{ $t('edit') }}
+ </v-btn>
+ </div>
+ </v-flex>
+
+ <v-flex v-else lg3 md4 sm4 xs12 order-lg3 order-md2 order-sm2 order-xs1 class="text-xs-right">
+ <div class="info-input">
+ <v-btn color="primary" flat @click="cancelEditParameters" class="info-buttons">{{ $t('cancel') }}</v-btn>
+ <v-btn color="primary" @click="submitParameters" class="info-buttons">
+ <v-icon left>save</v-icon>{{ $t('save') }}
+ </v-btn>
+ </div>
+ </v-flex>
+
+ </v-layout>
+ </v-card-text>
+ </v-card>
+
+ <v-subheader>{{ $t('output') }}</v-subheader>
<!--
<v-card v-on:wheel="manualScroll">
<div>
@@ -68,8 +186,8 @@
</template>
</v-card>
- <div class="scroll-overlay non-selectable" v-if="!autoscroll">
- <div @click="toTheBottom" style="cursor: pointer; height: 100%; display: flex; align-items: center;">
+ <div class="scroll-overlay non-selectable" v-if="!autoscroll" @click="toTheBottom" style="cursor: pointer">
+ <div style="height: 100%; display: flex; align-items: center;">
<v-icon style="margin-right: 10px">vertical_align_bottom</v-icon><pre>{{ $t('scrollDown') }}</pre>
</div>
</div>
@@ -139,31 +257,44 @@
<script>
import { mapGetters } from 'vuex'
-import axios from 'axios'
export default {
name: 'IpxeBuilderModuleConfig',
- props: ['ipxeVersion'],
components: {
},
data () {
return {
- tabs: 0,
- script: '',
+ allowCustomTargets: false,
+ autoscroll: true,
+ buildTargets: [],
+ branchName: '',
certificate: '',
- general: '',
console: '',
- log: [],
disableButtons: false,
- autoscroll: true
+ editParametersMode: false,
+ general: '',
+ log: [],
+ repoUrl: '',
+ script: '',
+ search: '',
+ tabs: 0,
+ targets: []
}
},
computed: {
...mapGetters(['tabsDark', 'tabsColor', 'tabsSliderColor'])
},
methods: {
+ createTarget (list) {
+ const index = list.length - 1
+ if (this.allowCustomTargets && this.targets.indexOf(list[index]) === -1) this.targets.push(list[index])
+ },
+ deleteTarget (item) {
+ const index = this.targets.indexOf(item)
+ if (this.allowCustomTargets) this.targets.splice(index, 1)
+ },
save (apiPath) {
- axios.put('/api/ipxe/' + this.ipxeVersion + '/' + apiPath, { data: this[apiPath] }).then(result => {
+ this.$http.put('/api/ipxe/' + apiPath, { data: this[apiPath] }).then(result => {
const saveMsg = apiPath + 'Saved'
if (result.data.status === 'SUCCESS') this.$snackbar({ color: 'success', text: this.$tc(saveMsg) })
else this.$snackbar({ color: 'error', text: result.data.error })
@@ -176,19 +307,19 @@ export default {
this.$refs[element].codemirror.redo()
},
buildIpxe () {
- axios.get('/api/ipxe/' + this.ipxeVersion + '/build').then(result => {
+ this.$http.get('/api/ipxe/build').then(result => {
if (result.data.status === 'SUCCESS') this.$snackbar({ color: 'primary', text: this.$tc('buildingIpxe') })
else if (result.data.status === 'ALREADY_BUILDING') this.$snackbar({ color: 'error', text: this.$tc('alreadyBuiling') })
})
},
cleanIpxe () {
- axios.get('/api/ipxe/' + this.ipxeVersion + '/clean').then(result => {
+ this.$http.get('/api/ipxe/clean').then(result => {
if (result.data.status === 'SUCCESS') this.$snackbar({ color: 'primary', text: this.$tc('cleaningIpxe') })
else if (result.data.status === 'ALREADY_BUILDING') this.$snackbar({ color: 'error', text: this.$tc('alreadyBuiling') })
})
},
cancelIpxe () {
- axios.get('/api/ipxe/' + this.ipxeVersion + '/cancel').then(result => {
+ this.$http.get('/api/ipxe/cancel').then(result => {
if (result.data.status === 'SUCCESS') this.$snackbar({ color: 'primary', text: this.$tc('cleaningIpxe') }) // TODO:
})
},
@@ -198,24 +329,48 @@ export default {
},
toTheBottom () {
this.autoscroll = true
+ },
+ editParameters () {
+ this.editParametersMode = true
+ },
+ cancelEditParameters () {
+ this.editParametersMode = false
+ },
+ getParameters () {
+ this.$http.get('/api/ipxe/config').then(config => {
+ config = config.data
+ this.branchName = config.branch
+ this.repoUrl = config.repository
+ this.targets = config.targets.list
+ this.buildTargets = config.targets.build
+ this.allowCustomTargets = config.targets.custom
+ })
+ },
+ submitParameters () {
+ const data = { repository: this.repoUrl, branch: this.branchName, buildTargets: this.buildTargets, targetList: this.targets }
+ this.$http.post('/api/ipxe/config', data).then(response => {
+ this.editParametersMode = false
+ })
}
},
created () {
+ this.getParameters()
+
// Load the data.
- axios.get('/api/ipxe/' + this.ipxeVersion + '/script').then(result => {
+ this.$http.get('/api/ipxe/script').then(result => {
this.script = result.data
})
- axios.get('/api/ipxe/' + this.ipxeVersion + '/certificate').then(result => {
+ this.$http.get('/api/ipxe/certificate').then(result => {
this.certificate = result.data
})
- axios.get('/api/ipxe/' + this.ipxeVersion + '/general').then(result => {
+ this.$http.get('/api/ipxe/general').then(result => {
this.general = result.data
})
- axios.get('/api/ipxe/' + this.ipxeVersion + '/console').then(result => {
+ this.$http.get('/api/ipxe/console').then(result => {
this.console = result.data
})
- axios.get('/api/ipxe/' + this.ipxeVersion + '/log?max=500').then(result => {
+ this.$http.get('/api/ipxe/log?max=500').then(result => {
var lines = result.data.split('\n')
for (var line in lines) {
if (lines[line] === '') continue
@@ -225,18 +380,18 @@ export default {
})
// Socket io event listeners
- this.$socket.on(this.ipxeVersion + ' log', entry => {
+ this.$socket.on('log', entry => {
this.log.push({ id: this.log.length, msg: entry.msg, status: entry.status, date: entry.date })
})
// Disable the buttons if a building process is running.
- axios.get('/api/ipxe/' + this.ipxeVersion + '/status').then(result => {
+ this.$http.get('/api/ipxe/status').then(result => {
this.disableButtons = result.data.data
})
- this.$socket.on(this.ipxeVersion + ' inProgress', inProgress => {
- this.disableButtons = inProgress
- })
+ // this.$socket.on('inProgress', inProgress => {
+ // this.disableButtons = inProgress
+ // })
},
updated () {
if (this.autoscroll) {
@@ -270,4 +425,21 @@ export default {
.subtabs {
z-index: 1;
}
+
+ .info-input {
+ margin: 20px;
+ }
+
+ .info-heading > span {
+ margin-left: 10px;
+ }
+
+ .info-buttons {
+ margin: 0;
+ }
+
+ .info-text {
+ margin-left: 34px;
+ font-family: 'Roboto Mono';
+ }
</style>