feat(VM creation): support automatic networks (#3958)

Fixes #3916
This commit is contained in:
Enishowk 2019-03-06 14:46:22 +01:00 committed by Julien Fontanet
parent 5ba170bf1f
commit 08ddfe0649
7 changed files with 81 additions and 37 deletions

View File

@ -3,6 +3,7 @@
### Enhancements
- [SR/Disk] Disable actions on unmanaged VDIs [#3988](https://github.com/vatesfr/xen-orchestra/issues/3988) (PR [#4000](https://github.com/vatesfr/xen-orchestra/pull/4000))
- [Pool] Specify automatic networks on a Pool [#3916](https://github.com/vatesfr/xen-orchestra/issues/3916) (PR [#3958](https://github.com/vatesfr/xen-orchestra/pull/3958))
### Bug fixes

View File

@ -85,34 +85,35 @@ createBonded.description =
// ===================================================================
export async function set({
network,
automatic,
defaultIsLocked,
name_description: nameDescription,
name_label: nameLabel,
defaultIsLocked,
id,
network,
}) {
await this.getXapi(network).setNetworkProperties(network._xapiId, {
automatic,
defaultIsLocked,
nameDescription,
nameLabel,
defaultIsLocked,
})
}
set.params = {
id: {
type: 'string',
automatic: {
type: 'boolean',
optional: true,
},
name_label: {
type: 'string',
defaultIsLocked: {
type: 'boolean',
optional: true,
},
name_description: {
type: 'string',
optional: true,
},
defaultIsLocked: {
type: 'boolean',
name_label: {
type: 'string',
optional: true,
},
}

View File

@ -578,6 +578,7 @@ const TRANSFORMS = {
network(obj) {
return {
automatic: obj.other_config?.automatic === 'true',
bridge: obj.bridge,
defaultIsLocked: obj.default_locking_mode === 'disabled',
MTU: +obj.MTU,

View File

@ -305,17 +305,23 @@ export default class Xapi extends XapiBase {
async setNetworkProperties(
id,
{ nameLabel, nameDescription, defaultIsLocked }
{ automatic, defaultIsLocked, nameDescription, nameLabel }
) {
let defaultLockingMode
if (defaultIsLocked != null) {
defaultLockingMode = defaultIsLocked ? 'disabled' : 'unlocked'
}
await this._setObjectProperties(this.getObject(id), {
nameLabel,
nameDescription,
defaultLockingMode,
})
const network = this.getObject(id)
await Promise.all([
this._setObjectProperties(network, {
defaultLockingMode,
nameDescription,
nameLabel,
}),
this._updateObjectMapProperty(network, 'other_config', {
automatic: automatic === undefined ? undefined : automatic ? 'true' : null,
}),
])
}
// =================================================================

View File

@ -733,6 +733,7 @@ const messages = {
memoryLeftTooltip: '{used}% used ({free} free)',
// ----- Pool network tab -----
pif: 'PIF',
poolNetworkAutomatic: 'Automatic',
poolNetworkNameLabel: 'Name',
poolNetworkDescription: 'Description',
poolNetworkPif: 'PIFs',

View File

@ -81,6 +81,7 @@ import {
resolveResourceSet,
} from 'utils'
import {
createFilter,
createSelector,
createGetObject,
createGetObjectsOfType,
@ -485,20 +486,19 @@ export default class NewVm extends BaseComponent {
}
})
const VIFs = []
let VIFs = []
const defaultNetworkIds = this._getDefaultNetworkIds(template)
forEach(template.VIFs, vifId => {
const vif = getObject(storeState, vifId, resourceSet)
VIFs.push({
network:
pool || isInResourceSet(vif.$network)
? vif.$network
: this._getDefaultNetworkId(template),
: defaultNetworkIds[0],
})
})
if (VIFs.length === 0) {
VIFs.push({
network: this._getDefaultNetworkId(template),
})
VIFs = defaultNetworkIds.map(id => ({ network: id }))
}
const name_label =
state.name_label === '' || !state.name_labelHasChanged
@ -631,21 +631,38 @@ export default class NewVm extends BaseComponent {
)
}
)
_getDefaultNetworkId = template => {
_getAutomaticNetworks = createSelector(
createFilter(this._getPoolNetworks, [network => network.automatic]),
networks => networks.map(_ => _.id)
)
_getDefaultNetworkIds = template => {
if (template === undefined) {
return
return []
}
const network =
this.props.pool === undefined
? find(this._getResolvedResourceSet().objectsByType.network, {
$pool: template.$pool,
})
: find(this._getPoolNetworks(), network => {
const pif = getObject(store.getState(), network.PIFs[0])
return pif && pif.management
})
return network && network.id
if (this.props.pool === undefined) {
const network = find(
this._getResolvedResourceSet().objectsByType.network,
{
$pool: template.$pool,
}
)
return network !== undefined ? [network.id] : []
}
const automaticNetworks = this._getAutomaticNetworks()
if (automaticNetworks.length !== 0) {
return automaticNetworks
}
const network = find(this._getPoolNetworks(), network => {
const pif = getObject(store.getState(), network.PIFs[0])
return pif && pif.management
})
return network !== undefined ? [network.id] : []
}
_buildVmsNameTemplate = createSelector(
@ -788,9 +805,7 @@ export default class NewVm extends BaseComponent {
this._setState({
VIFs: [
...state.VIFs,
{
network: this._getDefaultNetworkId(state.template),
},
{ network: this._getDefaultNetworkIds(state.template)[0] },
],
})
}

View File

@ -79,6 +79,21 @@ class Name extends Component {
// -----------------------------------------------------------------------------
class AutomaticNetwork extends Component {
_editAutomaticNetwork = automatic =>
editNetwork(this.props.network, { automatic })
render() {
const { network } = this.props
return (
<Toggle onChange={this._editAutomaticNetwork} value={network.automatic} />
)
}
}
// -----------------------------------------------------------------------------
class Description extends Component {
_editDescription = value =>
editNetwork(this.props.network, { name_description: value })
@ -343,6 +358,10 @@ const NETWORKS_COLUMNS = [
itemRenderer: network =>
!isEmpty(network.PIFs) && <PifsItem network={network} />,
},
{
name: _('poolNetworkAutomatic'),
itemRenderer: network => <AutomaticNetwork network={network} />,
},
{
name: '',
itemRenderer: network => <NetworkActions network={network} />,