From 57092ee788d3de16e21f54857e13176159f8ddf8 Mon Sep 17 00:00:00 2001 From: Pierre Donias Date: Wed, 28 Sep 2016 15:09:17 +0200 Subject: [PATCH] feat(vif.set): support for network, MAC and currently_attached (#403) Fixes vatesfr/xo-web#1446 --- src/api/vif.js | 49 +++++++++++++++++++++++++++++++---- src/api/vm.coffee | 34 +++++++++++++++++++++--- src/xapi/index.js | 16 +++--------- src/xapi/mixins/networking.js | 22 ++++++++++++++++ 4 files changed, 99 insertions(+), 22 deletions(-) diff --git a/src/api/vif.js b/src/api/vif.js index 268afc190..32489d17b 100644 --- a/src/api/vif.js +++ b/src/api/vif.js @@ -34,7 +34,7 @@ delete_.resolve = { // TODO: move into vm and rename to disconnectInterface export async function disconnect ({vif}) { // TODO: check if VIF is attached before - await this.getXapi(vif).call('VIF.unplug_force', vif._xapiRef) + await this.getXapi(vif).disconnectVif(vif._xapiId) } disconnect.params = { @@ -49,7 +49,7 @@ disconnect.resolve = { // TODO: move into vm and rename to connectInterface export async function connect ({vif}) { // TODO: check if VIF is attached before - await this.getXapi(vif).call('VIF.plug', vif._xapiRef) + await this.getXapi(vif).connectVif(vif._xapiId) } connect.params = { @@ -62,7 +62,41 @@ connect.resolve = { // ------------------------------------------------------------------- -export function set ({ vif, allowedIpv4Addresses, allowedIpv6Addresses }) { +export async function set ({ + vif, + network, + mac, + allowedIpv4Addresses, + allowedIpv6Addresses, + attached +}) { + if (network || mac) { + const xapi = this.getXapi(vif) + + const vm = xapi.getObject(vif.$VM) + mac == null && (mac = vif.MAC) + network = xapi.getObject(network && network.id || vif.$network) + allowedIpv4Addresses == null && (allowedIpv4Addresses = vif.allowedIpv4Addresses) + allowedIpv6Addresses == null && (allowedIpv6Addresses = vif.allowedIpv6Addresses) + attached == null && (attached = vif.attached) + + // remove previous VIF + const dealloc = address => { + this.deallocIpAddress(address, vif.id)::pCatch(noop) + } + forEach(vif.allowedIpv4Addresses, dealloc) + forEach(vif.allowedIpv6Addresses, dealloc) + xapi.deleteVif(vif._xapiId)::pCatch(noop) + + // create new VIF with new parameters + await xapi.createVif(vm.$id, network.$id, { + mac, + currently_attached: attached + }) + + return + } + const { id } = vif const handle = ([ newAddresses, oldAddresses ]) => { forEach(newAddresses, address => { @@ -82,6 +116,9 @@ export function set ({ vif, allowedIpv4Addresses, allowedIpv6Addresses }) { } set.params = { + id: { type: 'string' }, + network: { type: 'string', optional: true }, + mac: { type: 'string', optional: true }, allowedIpv4Addresses: { type: 'array', items: { @@ -95,9 +132,11 @@ set.params = { type: 'string' }, optional: true - } + }, + attached: { type: 'boolean', optional: true } } set.resolve = { - vif: ['id', 'VIF', 'operate'] + vif: ['id', 'VIF', 'operate'], + network: ['network', 'network', 'operate'] } diff --git a/src/api/vm.coffee b/src/api/vm.coffee index f342177c2..3b542bfa8 100644 --- a/src/api/vm.coffee +++ b/src/api/vm.coffee @@ -1054,21 +1054,47 @@ exports.attachDisk = attachDisk #--------------------------------------------------------------------- # TODO: implement resource sets -createInterface = $coroutine ({vm, network, position, mtu, mac}) -> +createInterface = $coroutine ({ + vm, + network, + position, + mac, + allowedIpv4Addresses, + allowedIpv6Addresses +}) -> vif = yield @getXapi(vm).createVif(vm._xapiId, network._xapiId, { mac, - mtu, - position + position, + ipv4_allowed: allowedIpv4Addresses, + ipv6_allowed: allowedIpv6Addresses }) + alloc = (address) => + @allocIpAddress(address, vif.$id)::pCatch(noop) + forEach(allowedIpv4Addresses, alloc) + forEach(allowedIpv6Addresses, alloc) + return vif.$id createInterface.params = { vm: { type: 'string' } network: { type: 'string' } position: { type: ['integer', 'string'], optional: true } - mtu: { type: ['integer', 'string'], optional: true } mac: { type: 'string', optional: true } + allowedIpv4Addresses: { + type: 'array', + items: { + type: 'string' + }, + optional: true + }, + allowedIpv6Addresses: { + type: 'array', + items: { + type: 'string' + }, + optional: true + } } createInterface.resolve = { diff --git a/src/xapi/index.js b/src/xapi/index.js index 6d6216bfb..98b3a66f0 100644 --- a/src/xapi/index.js +++ b/src/xapi/index.js @@ -1799,15 +1799,14 @@ export default class Xapi extends XapiBase { async _createVif (vm, network, { mac = '', - mtu = network.MTU, position = undefined, + currently_attached = true, device = position != null ? String(position) : undefined, ipv4_allowed = undefined, ipv6_allowed = undefined, locking_mode = undefined, MAC = mac, - MTU = mtu, other_config = {}, qos_algorithm_params = {}, qos_algorithm_type = '' @@ -1824,7 +1823,7 @@ export default class Xapi extends XapiBase { ipv6_allowed, locking_mode, MAC, - MTU: asInteger(MTU), + MTU: asInteger(network.MTU), network: network.$ref, other_config, qos_algorithm_params, @@ -1832,18 +1831,13 @@ export default class Xapi extends XapiBase { VM: vm.$ref })) - if (isVmRunning(vm)) { + if (currently_attached && isVmRunning(vm)) { await this.call('VIF.plug', vifRef) } return vifRef } - // TODO: check whether the VIF was unplugged before. - async _deleteVif (vif) { - await this.call('VIF.destroy', vif.$ref) - } - async createVif (vmId, networkId, opts = undefined) { return /* await */ this._getOrWaitObject( await this._createVif( @@ -1854,10 +1848,6 @@ export default class Xapi extends XapiBase { ) } - async deleteVif (vifId) { - await this._deleteVif(this.getObject(vifId)) - } - async createNetwork ({ name, description = 'Created with Xen Orchestra', diff --git a/src/xapi/mixins/networking.js b/src/xapi/mixins/networking.js index c6a9d41c4..cc779c227 100644 --- a/src/xapi/mixins/networking.js +++ b/src/xapi/mixins/networking.js @@ -3,6 +3,28 @@ import { isEmpty } from '../../utils' import { makeEditObject } from '../utils' export default { + async _connectVif (vif) { + await this.call('VIF.plug', vif.$ref) + }, + async connectVif (vifId) { + await this._connectVif(this.getObject(vifId)) + }, + async _deleteVif (vif) { + await this.call('VIF.destroy', vif.$ref) + }, + async deleteVif (vifId) { + const vif = this.getObject(vifId) + if (vif.currently_attached) { + await this._disconnectVif(vif) + } + await this._deleteVif(vif) + }, + async _disconnectVif (vif) { + await this.call('VIF.unplug_force', vif.$ref) + }, + async disconnectVif (vifId) { + await this._disconnectVif(this.getObject(vifId)) + }, editVif: makeEditObject({ ipv4Allowed: { get: true,