From a3e2cb36b0cbceb025753c7aeae0553de043b968 Mon Sep 17 00:00:00 2001 From: Jannik Schönartz Date: Sun, 7 Apr 2019 23:42:35 +0000 Subject: [server/backends] Add infoblox ipxe ip selection stuff --- server/lib/external-backends/backendhelper.js | 28 ++++- .../external-backends/backends/infoblox-backend.js | 118 ++++++++++++++++----- server/lib/external-backends/index.js | 12 +++ 3 files changed, 132 insertions(+), 26 deletions(-) (limited to 'server/lib/external-backends') diff --git a/server/lib/external-backends/backendhelper.js b/server/lib/external-backends/backendhelper.js index d8d4b24..b7a8a9b 100644 --- a/server/lib/external-backends/backendhelper.js +++ b/server/lib/external-backends/backendhelper.js @@ -4,7 +4,7 @@ const ExternalBackends = require(path.join(__appdir, 'lib', 'external-backends') const db = require(path.join(__appdir, 'lib', 'sequelize')) const log = require(path.join(__appdir, 'lib', 'log')) -module.exports = { addClient, updateClient, deleteClients, uploadFiles } +module.exports = { addClient, getDhcp, updateClient, deleteClients, uploadFiles } async function addClient (client) { // Get all backends and call addClient for each instance. @@ -123,3 +123,29 @@ async function uploadFiles (clientId, files) { } return results } + +async function getDhcp () { + const backends = await db.backend.findAll() + + let dhcp = false + for (let b in backends) { + const backend = backends[b] + const ba = new ExternalBackends() + const instance = ba.getInstance(backend.type) + + const isDHCP = await instance.isDhcp(backend.credentials) + if (isDHCP) { + if (!dhcp) dhcp = { instance: instance, backend: backend } + else { + // Conflict occured! + const conflict = await db.conflict.create({ description: 'Multiple dhcp backends found' }) + + // Add both backends to the conflict. + conflict.createObject({ objectType: 'BACKEND', objectId: backend.id }) + conflict.createObject({ objectType: 'BACKEND', objectId: dhcp.backend.id }) + return false + } + } + } + return dhcp +} diff --git a/server/lib/external-backends/backends/infoblox-backend.js b/server/lib/external-backends/backends/infoblox-backend.js index 2b2c6d1..27aa0b4 100644 --- a/server/lib/external-backends/backends/infoblox-backend.js +++ b/server/lib/external-backends/backends/infoblox-backend.js @@ -64,6 +64,64 @@ class InfobloxBackend extends ExternalBackends { }) } + async checkIp (credentials, ipv4) { + const c = this.mapCredentials(credentials) + + // Login + const ipam = new Infoblox({ + ip: c.url, + apiVersion: c.version + }) + const login = await ipam.login(c.username, c.password) + if (!login) return false + + // Get the host and check the leased state + let host = JSON.parse(await ipam.getHost(ipv4))[0] + if (host.lease_state && host.lease_state === 'ACTIVE') { + // If leased return the next 20 free ips of the subnet. + const dhcpNetwork = JSON.parse(await ipam.getNetworkFromIp(ipv4)) + const nextIps = await ipam.getNext(dhcpNetwork[0]._ref, 20) + return nextIps + } + return false + } + + async setIp (credentials, ipv4, mac, name, setNextIp = false) { + const c = this.mapCredentials(credentials) + + const ipam = new Infoblox({ + ip: c.url, + apiVersion: c.version + }) + const login = await ipam.login(c.username, c.password) + if (!login) return { error: 'LOGIN_FAILED' } + + // If setNextIp is true, use the next available ip from the subnet + if (setNextIp) { + const network = JSON.parse(await ipam.getNetworkFromIp(ipv4)) + ipv4 = 'func:nextavailableip:' + network[0].network + } + const domain = await ipam.getDomain() + const createHost = await ipam.create('record:host?_return_fields%2B=ipv4addrs&_return_as_object=1', { + 'name': name + '.' + domain, + 'ipv4addrs': [ + { + 'ipv4addr': ipv4, + 'mac': mac + } + ] + }) + + // Return error if there is one + if (createHost.Error) { + return { error: 'ERROR_INFOBLOX', msg: createHost.text } + } else return { host: createHost.result.ipv4addrs[0].host, ip: createHost.result.ipv4addrs[0].ipv4addr } + } + + isDhcp () { + return true + } + // ############################################################################ // ####################### helper/optional functions ######################### // Helper function, to map the array of credential objects into a single js object. @@ -80,38 +138,48 @@ class InfobloxBackend extends ExternalBackends { } // #### TEST FUNCTIONS ### - test (credentials) { - var c = this.mapCredentials(credentials) + async test (credentials) { + const c = this.mapCredentials(credentials) - var ipam = new Infoblox({ + const ipam = new Infoblox({ ip: c.url, apiVersion: c.version }) - var promise = new Promise((resolve, reject) => { - ipam.login(c.username, c.password).then(response => { - if (response) { - // ipam.create('record:host?_return_fields%2B=na13me,ipv4addrs&_return_as_object=1', {'name': 'wapiTest.lp.privat', 'ipv4addrs': [{'ipv4addr': '10.21.9.141', 'mac': 'aa:bb:cc:11:22:21'}]}).then(function (response) { - // return response - // }) - // Get the network from the ip. - // ipam.getHost('10.21.9.78').then(function (response) { - ipam.getNetworkFromIp('10.21.9.78').then(response => { - // ipam.getIpsFromSubnet('10.21.9.0/24').then(function (response) { - // ipam.list('record:host').then(function (response) { - // ipam.getDomain().then(function (response) { - response = JSON.parse(response) - // ipam.getNext(response[0]._ref, 1).then(r => { - resolve(response) - // }) - // res.send(JSON.parse(response)) - }) - } else { - return { success: false, error: 'TEST' } + const login = await ipam.login(c.username, c.password) + let result = {} + if (!login) return { error: 'LOGIN_FAILED' } + // Get network from ip + result['getNetworkFromIp'] = JSON.parse(await ipam.getNetworkFromIp('10.21.9.78')) + // Get host + // result["getHost.78"] = JSON.parse(await ipam.getHost('10.21.9.78')) + // result["getHost.219"] = JSON.parse(await ipam.getHost('10.21.9.219')) + // Get ips from subnet + // result["getIpsFromSubnet"] = JSON.parse(await ipam.getIpsFromSubnet('10.21.9.0/24')) + // List records + // result["list"] = JSON.parse(await ipam.list('record:host')) + // Get Domain + result['getDomain'] = await ipam.getDomain() + // Get next ip + // result["getNextIp.1"] = await ipam.getNext(result["getNetworkFromIp"][0]._ref, 1) + // Get next 20 ips + // result["getNextIp.20"] = await ipam.getNext(result["getNetworkFromIp"][0]._ref, 20) + + // Create Host + // result['createHost'] = await ipam.create('record:host?_return_fields%2B=ipv4addrs&_return_as_object=1', {'name': 'wapiTest2.lp.privat', 'ipv4addrs': [{'ipv4addr': '10.21.9.218', 'mac': 'aa:bb:cc:11:22:21'}]}) + /* + result['create'] = await ipam.create('record:host?_return_fields%2B=ipv4addrs&_return_as_object=1', { + 'name': 'test.lp.privat', + 'ipv4addrs': [ + { + 'ipv4addr': 'func:nextavailableip:' + result['getNetworkFromIp'][0].network, + 'mac': 'aa:bb:cc:11:22:21' } - }) + ] }) - return promise + result['create'] + */ + return result } } diff --git a/server/lib/external-backends/index.js b/server/lib/external-backends/index.js index 7acaa85..8dcae5a 100644 --- a/server/lib/external-backends/index.js +++ b/server/lib/external-backends/index.js @@ -166,6 +166,18 @@ class ExternalBackends { async getFile (credentials, externalId, filename) { return { error: 'NOT_IMPLEMENTED_EXCEPTION', message: 'The provided backend does not have an getFile method' } } + async checkIp (credentials, ipv4) { + return { error: 'NOT_IMPLEMENTED_EXCEPTION', message: 'The provided backend does not have a checkIp method' } + } + async setIp (credentials, ipv4, mac) { + return { error: 'NOT_IMPLEMENTED_EXCEPTION', message: 'The provided backend does not have a setIp method' } + } + /* + * Only one dhcp backend should be configures or it causes problems in the registration. + */ + isDhcp () { + return false + } } module.exports = ExternalBackends -- cgit v1.2.3-55-g7522