summaryrefslogblamecommitdiffstats
path: root/server/lib/shell.js
blob: 8aa4cf2c4b615d1f94c25fc90cc13bd4136dc30c (plain) (tree)
1
2
3
4
5
6
7
8
9
                     

                              

                                                        
                                                   
 
                  
                                                                                                             
                    
 




                                                                                                               
                                                 

                                                                       
 
                   

                                             
 
                       

                                                 

                 

                                                           
 
                                            
                                                                  

                 
 
                                             
                                         


                                          
                                               
            
                                        
        
                                         


                                          
                                              
            
                                       

        



                                                                            
                                                                                                                                                                                                                                                                   







                                                                                                                                                  
                                                  
                                                                                                                 
                                           

    

                                     

                                          
                  

                                            
                                          

                                                  
      

    


                                                                                                        
 
                                              
                                         



                                                                  


                                  
                























                                                                                 







                                                                                                                       
       

                     





                                           

   
 
                                        
                                             
                                                                                                       
 

                                           


                                                                         


                                     
                               

                                     
                              



      
                                    
                                                                 



                                                                                                                          

 
                                              

                                       
                                                 
                                              



                                            
 
                                                                 
 
                     
                                                    
                             

 

                                                                                                                                                   


                      
/* global __appdir */
var path = require('path')
var shell = require('shelljs')
var io = require(path.join(__appdir, 'lib', 'socketio'))
const fs = require('fs')
// Only one building process per version at a time.

module.exports = {
  buildIpxe: async function (buildParameters = [], gitURL = 'http://git.ipxe.org/ipxe.git', gitBranch = '') {
    var makeCmd = ''

    // 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 ' + buildParameters.join(' ')
    makeCmd += ' EMBED=' + path.join(__appdir, 'ipxe', 'embedded.ipxe')
    makeCmd += ' TRUST=' + path.join(__appdir, 'bin', 'fullchain.pem')

    // Cloning git.
    sendToLog('Cloning git ...\n', 'primary')
    await cloneIpxe(gitURL, gitBranch)

    // Copying configs.
    sendToLog('Copying configs ...\n', 'primary')
    copyConfigs()

    // Make ipxe.
    sendToLog('Make iPXE ...\n', 'primary')
    shell.cd(path.join(__appdir, 'ipxe', 'ipxeGIT', 'src'))

    await new Promise((resolve, reject) => {
      const process = shell.exec(makeCmd, { async: true }, () => {
        resolve()
      })

      // Send the output to the frontend log.
      process.stdout.on('data', data => {
        const multiline = data.split('\n')
        if (multiline.length > 2) {
          multiline.forEach(line => {
            if (line) sendToLog(line, 'normal')
          })
        } else sendToLog(data, 'normal')
      })
      process.stderr.on('data', data => {
        const multiline = data.split('\n')
        if (multiline.length > 2) {
          multiline.forEach(line => {
            if (line) sendToLog(line, 'error')
          })
        } else sendToLog(data, 'error')
      })
    })

    // Copy and rename the ipxe file to the __appdir/ipxe/builds/<date> dir.
    sendToLog('Copying ipxe file(s) ...\n', 'primary')
    const date = new Date()
    const timestamp = date.getFullYear() + '-' + ('0' + (date.getMonth() + 1)).slice(-2) + '-' + ('0' + date.getDate()).slice(-2) + '_' + ('0' + date.getHours()).slice(-2) + '-' + ('0' + date.getMinutes()).slice(-2) + '-' + ('0' + date.getSeconds()).slice(-2)

    for (let buildtarget of buildParameters) {
      const target = buildtarget.split('/')
      shell.mkdir('-p', path.join(__appdir, 'ipxe', 'builds', timestamp, target[0]))
      shell.cp(path.join(__appdir, 'ipxe', 'ipxeGIT', 'src', buildtarget), path.join(__appdir, 'ipxe', 'builds', timestamp, target[0], target[1]))
      sendToLog('Copyed ' + buildtarget, 'success')
    }
    sendToLog('Finished copying\n', 'success')
    // sendToLog(ipxeVersion, 'done\n', 'success')
    // shell.mv(path.join(__appdir, 'ipxe', 'undionly.kpxe'), path.join(__appdir, 'ipxe', 'ipxe.' + ipxeVersion))
    // updateInProgress(ipxeVersion, false)
  },

  cancelBuilding: async function () {
    /*
    const ipxeVersion = req.params.version
    const process = make[ipxeVersion]
    if (process) {
      const kill = 'pkill -P ' + process.pid
      shell.exec(kill)
      updateInProgress(ipxeVersion, false)
    }
    res.send({ status: 'SUCCESS', data: process })
    */
  },

  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', '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 false
  },

  /* Changes or creates a symbolic link to a builded ipxe */
  forceSymlink: function (source, dest) {
    // Because of the shelljs lib is bugged handle broken links deletetion myself
    var destinationExists
    try {
      fs.lstatSync(dest)
      destinationExists = true
    } catch (err) {
      destinationExists = false
    }

    if (destinationExists) {
      fs.unlinkSync(dest)
    }

    const ln = shell.ln('-sf', source, dest)
    if (ln.stderr) return { status: 'ERROR', error: ln.stderr }
    else return { status: 'SUCCESS' }
  },

  readdirRecursive: function (buildsPath) {
    let structure = []
    try {
      const directory = fs.readdirSync(buildsPath)
      for (let obj of directory) {
        if (!fs.lstatSync(path.join(buildsPath, obj)).isDirectory()) {
          structure.push({ name: obj, type: 'file' })
        } else {
          structure.push({ name: obj, type: 'directory', children: this.readdirRecursive(path.join(buildsPath, obj)) })
        }
      }
    } catch (error) {
      return []
    }
    return structure
  },

  forceDeleteBuild: function (buildsPath) {
    shell.rm('-rf', path.join(buildsPath))
  }
}

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.' }

  shell.cd(path.join(__appdir, 'ipxe'))
  return new Promise((resolve, reject) => {
    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(data, 'normal')
    })
    clone.stderr.on('data', data => {
      sendToLog(data, 'error')
    })
  })
}

function copyConfigs (ipxeVersion) {
  // Remove the default configs and paste in the customized ones.
  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 (msg, status, log = true) {
  const date = new Date()
  const pad = x => x < 10 ? '0' + x : x
  var dateString = '[' + date.getFullYear() + '-'
  dateString += pad(date.getMonth() + 1) + '-'
  dateString += pad(date.getDate()) + ' '
  dateString += pad(date.getHours()) + ':'
  dateString += pad(date.getMinutes()) + ':'
  dateString += pad(date.getSeconds()) + ']'

  const logEntry = { date: dateString, status: status, msg: msg }

  const event = 'log'
  io.in('broadcast ipxeBuild').emit(event, logEntry)
  if (log) writeLog(logEntry)
}

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
  })
}