mirror of https://github.com/apache/cloudstack.git
Merge 4d9c38218f into cd5bb09d0d
This commit is contained in:
commit
732c232db2
|
|
@ -43,7 +43,7 @@ import java.util.List;
|
||||||
public class DeployVnfApplianceCmd extends DeployVMCmd implements UserCmd {
|
public class DeployVnfApplianceCmd extends DeployVMCmd implements UserCmd {
|
||||||
|
|
||||||
@Parameter(name = ApiConstants.VNF_CONFIGURE_MANAGEMENT, type = CommandType.BOOLEAN, required = false,
|
@Parameter(name = ApiConstants.VNF_CONFIGURE_MANAGEMENT, type = CommandType.BOOLEAN, required = false,
|
||||||
description = "True by default, security group or network rules (source nat and firewall rules) will be configured for VNF management interfaces. False otherwise. " +
|
description = "False by default, security group or network rules (source nat and firewall rules) will be configured for VNF management interfaces. True otherwise. " +
|
||||||
"Network rules are configured if management network is an isolated network or shared network with security groups.")
|
"Network rules are configured if management network is an isolated network or shared network with security groups.")
|
||||||
private Boolean vnfConfigureManagement;
|
private Boolean vnfConfigureManagement;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import org.apache.cloudstack.api.command.user.template.UpdateVnfTemplateCmd;
|
||||||
import org.apache.cloudstack.api.command.user.vm.DeployVnfApplianceCmd;
|
import org.apache.cloudstack.api.command.user.vm.DeployVnfApplianceCmd;
|
||||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public interface VnfTemplateManager {
|
public interface VnfTemplateManager {
|
||||||
|
|
||||||
|
|
@ -42,11 +43,12 @@ public interface VnfTemplateManager {
|
||||||
|
|
||||||
void updateVnfTemplate(long templateId, UpdateVnfTemplateCmd cmd);
|
void updateVnfTemplate(long templateId, UpdateVnfTemplateCmd cmd);
|
||||||
|
|
||||||
void validateVnfApplianceNics(VirtualMachineTemplate template, List<Long> networkIds);
|
void validateVnfApplianceNics(VirtualMachineTemplate template, List<Long> networkIds, Map<Integer, Long> vmNetworkMap);
|
||||||
|
|
||||||
SecurityGroup createSecurityGroupForVnfAppliance(DataCenter zone, VirtualMachineTemplate template, Account owner, DeployVnfApplianceCmd cmd);
|
SecurityGroup createSecurityGroupForVnfAppliance(DataCenter zone, VirtualMachineTemplate template, Account owner, DeployVnfApplianceCmd cmd);
|
||||||
|
|
||||||
void createIsolatedNetworkRulesForVnfAppliance(DataCenter zone, VirtualMachineTemplate template, Account owner,
|
void createIsolatedNetworkRulesForVnfAppliance(DataCenter zone, VirtualMachineTemplate template, Account owner,
|
||||||
UserVm vm, DeployVnfApplianceCmd cmd)
|
UserVm vm, DeployVnfApplianceCmd cmd)
|
||||||
throws InsufficientAddressCapacityException, ResourceAllocationException, ResourceUnavailableException;
|
throws InsufficientAddressCapacityException, ResourceAllocationException, ResourceUnavailableException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
// under the License.
|
// under the License.
|
||||||
package org.apache.cloudstack.storage.template;
|
package org.apache.cloudstack.storage.template;
|
||||||
|
|
||||||
|
import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
|
||||||
import com.cloud.exception.InvalidParameterValueException;
|
import com.cloud.exception.InvalidParameterValueException;
|
||||||
import com.cloud.network.VNF;
|
import com.cloud.network.VNF;
|
||||||
import com.cloud.storage.Storage;
|
import com.cloud.storage.Storage;
|
||||||
|
|
@ -124,6 +125,9 @@ public class VnfTemplateUtils {
|
||||||
public static void validateApiCommandParams(BaseCmd cmd, VirtualMachineTemplate template) {
|
public static void validateApiCommandParams(BaseCmd cmd, VirtualMachineTemplate template) {
|
||||||
if (cmd instanceof RegisterVnfTemplateCmd) {
|
if (cmd instanceof RegisterVnfTemplateCmd) {
|
||||||
RegisterVnfTemplateCmd registerCmd = (RegisterVnfTemplateCmd) cmd;
|
RegisterVnfTemplateCmd registerCmd = (RegisterVnfTemplateCmd) cmd;
|
||||||
|
if (registerCmd.isDeployAsIs() && CollectionUtils.isNotEmpty(registerCmd.getVnfNics())) {
|
||||||
|
throw new InvalidParameterValueException("VNF nics cannot be specified when register a deploy-as-is Template. Please wait until Template settings are read from OVA.");
|
||||||
|
}
|
||||||
validateApiCommandParams(registerCmd.getVnfDetails(), registerCmd.getVnfNics(), registerCmd.getTemplateType());
|
validateApiCommandParams(registerCmd.getVnfDetails(), registerCmd.getVnfNics(), registerCmd.getTemplateType());
|
||||||
} else if (cmd instanceof UpdateVnfTemplateCmd) {
|
} else if (cmd instanceof UpdateVnfTemplateCmd) {
|
||||||
UpdateVnfTemplateCmd updateCmd = (UpdateVnfTemplateCmd) cmd;
|
UpdateVnfTemplateCmd updateCmd = (UpdateVnfTemplateCmd) cmd;
|
||||||
|
|
@ -149,4 +153,18 @@ public class VnfTemplateUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void validateDeployAsIsTemplateVnfNics(List<OVFNetworkTO> ovfNetworks, List<VNF.VnfNic> vnfNics) {
|
||||||
|
if (CollectionUtils.isEmpty(vnfNics)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isEmpty(ovfNetworks)) {
|
||||||
|
throw new InvalidParameterValueException("The list of networks read from OVA is empty. Please wait until the template is fully downloaded and processed.");
|
||||||
|
}
|
||||||
|
for (VNF.VnfNic vnfNic : vnfNics) {
|
||||||
|
if (vnfNic.getDeviceId() < ovfNetworks.size() && !vnfNic.isRequired()) {
|
||||||
|
throw new InvalidParameterValueException(String.format("The VNF nic [device ID: %s ] is required as it is defined in the OVA template.", vnfNic.getDeviceId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,7 @@ import com.cloud.agent.api.to.DatadiskTO;
|
||||||
import com.cloud.agent.api.to.DiskTO;
|
import com.cloud.agent.api.to.DiskTO;
|
||||||
import com.cloud.agent.api.to.NfsTO;
|
import com.cloud.agent.api.to.NfsTO;
|
||||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||||
|
import com.cloud.agent.api.to.deployasis.OVFNetworkTO;
|
||||||
import com.cloud.api.ApiDBUtils;
|
import com.cloud.api.ApiDBUtils;
|
||||||
import com.cloud.api.query.dao.UserVmJoinDao;
|
import com.cloud.api.query.dao.UserVmJoinDao;
|
||||||
import com.cloud.api.query.vo.UserVmJoinVO;
|
import com.cloud.api.query.vo.UserVmJoinVO;
|
||||||
|
|
@ -131,6 +132,7 @@ import com.cloud.dc.DataCenter;
|
||||||
import com.cloud.dc.DataCenterVO;
|
import com.cloud.dc.DataCenterVO;
|
||||||
import com.cloud.dc.dao.DataCenterDao;
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
import com.cloud.deploy.DeployDestination;
|
import com.cloud.deploy.DeployDestination;
|
||||||
|
import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao;
|
||||||
import com.cloud.domain.Domain;
|
import com.cloud.domain.Domain;
|
||||||
import com.cloud.domain.dao.DomainDao;
|
import com.cloud.domain.dao.DomainDao;
|
||||||
import com.cloud.event.ActionEvent;
|
import com.cloud.event.ActionEvent;
|
||||||
|
|
@ -313,6 +315,8 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
||||||
protected SnapshotHelper snapshotHelper;
|
protected SnapshotHelper snapshotHelper;
|
||||||
@Inject
|
@Inject
|
||||||
VnfTemplateManager vnfTemplateManager;
|
VnfTemplateManager vnfTemplateManager;
|
||||||
|
@Inject
|
||||||
|
TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private SecondaryStorageHeuristicDao secondaryStorageHeuristicDao;
|
private SecondaryStorageHeuristicDao secondaryStorageHeuristicDao;
|
||||||
|
|
@ -2172,6 +2176,11 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
|
||||||
templateType = validateTemplateType(cmd, isAdmin, template.isCrossZones());
|
templateType = validateTemplateType(cmd, isAdmin, template.isCrossZones());
|
||||||
if (cmd instanceof UpdateVnfTemplateCmd) {
|
if (cmd instanceof UpdateVnfTemplateCmd) {
|
||||||
VnfTemplateUtils.validateApiCommandParams(cmd, template);
|
VnfTemplateUtils.validateApiCommandParams(cmd, template);
|
||||||
|
UpdateVnfTemplateCmd updateCmd = (UpdateVnfTemplateCmd) cmd;
|
||||||
|
if (template.isDeployAsIs() && CollectionUtils.isNotEmpty(updateCmd.getVnfNics())) {
|
||||||
|
List<OVFNetworkTO> ovfNetworks = templateDeployAsIsDetailsDao.listNetworkRequirementsByTemplateId(template.getId());
|
||||||
|
VnfTemplateUtils.validateDeployAsIsTemplateVnfNics(ovfNetworks, updateCmd.getVnfNics());
|
||||||
|
}
|
||||||
vnfTemplateManager.updateVnfTemplate(template.getId(), (UpdateVnfTemplateCmd) cmd);
|
vnfTemplateManager.updateVnfTemplate(template.getId(), (UpdateVnfTemplateCmd) cmd);
|
||||||
}
|
}
|
||||||
templateTag = ((UpdateTemplateCmd)cmd).getTemplateTag();
|
templateTag = ((UpdateTemplateCmd)cmd).getTemplateTag();
|
||||||
|
|
|
||||||
|
|
@ -6127,7 +6127,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
||||||
throw new InvalidParameterValueException("Unable to use template " + templateId);
|
throw new InvalidParameterValueException("Unable to use template " + templateId);
|
||||||
}
|
}
|
||||||
if (TemplateType.VNF.equals(template.getTemplateType())) {
|
if (TemplateType.VNF.equals(template.getTemplateType())) {
|
||||||
vnfTemplateManager.validateVnfApplianceNics(template, cmd.getNetworkIds());
|
vnfTemplateManager.validateVnfApplianceNics(template, cmd.getNetworkIds(), cmd.getVmNetworkMap());
|
||||||
} else if (cmd instanceof DeployVnfApplianceCmd) {
|
} else if (cmd instanceof DeployVnfApplianceCmd) {
|
||||||
throw new InvalidParameterValueException("Can't deploy VNF appliance from a non-VNF template");
|
throw new InvalidParameterValueException("Can't deploy VNF appliance from a non-VNF template");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,14 @@ public class VnfTemplateManagerImpl extends ManagerBase implements VnfTemplateMa
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void validateVnfApplianceNics(VirtualMachineTemplate template, List<Long> networkIds) {
|
public void validateVnfApplianceNics(VirtualMachineTemplate template, List<Long> networkIds, Map<Integer, Long> vmNetworkMap) {
|
||||||
|
if (template.isDeployAsIs()) {
|
||||||
|
if (CollectionUtils.isNotEmpty(networkIds)) {
|
||||||
|
throw new InvalidParameterValueException("VNF nics mappings should be empty for deploy-as-is templates");
|
||||||
|
}
|
||||||
|
validateVnfApplianceNetworksMap(template, vmNetworkMap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (CollectionUtils.isEmpty(networkIds)) {
|
if (CollectionUtils.isEmpty(networkIds)) {
|
||||||
throw new InvalidParameterValueException("VNF nics list is empty");
|
throw new InvalidParameterValueException("VNF nics list is empty");
|
||||||
}
|
}
|
||||||
|
|
@ -213,6 +220,18 @@ public class VnfTemplateManagerImpl extends ManagerBase implements VnfTemplateMa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateVnfApplianceNetworksMap(VirtualMachineTemplate template, Map<Integer, Long> vmNetworkMap) {
|
||||||
|
if (MapUtils.isEmpty(vmNetworkMap)) {
|
||||||
|
throw new InvalidParameterValueException("VNF networks map is empty");
|
||||||
|
}
|
||||||
|
List<VnfTemplateNicVO> vnfNics = vnfTemplateNicDao.listByTemplateId(template.getId());
|
||||||
|
for (VnfTemplateNicVO vnfNic : vnfNics) {
|
||||||
|
if (vnfNic.isRequired() && vmNetworkMap.size() <= vnfNic.getDeviceId()) {
|
||||||
|
throw new InvalidParameterValueException("VNF nic is required but not found: " + vnfNic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected Set<Integer> getOpenPortsForVnfAppliance(VirtualMachineTemplate template) {
|
protected Set<Integer> getOpenPortsForVnfAppliance(VirtualMachineTemplate template) {
|
||||||
Set<Integer> ports = new HashSet<>();
|
Set<Integer> ports = new HashSet<>();
|
||||||
VnfTemplateDetailVO accessMethodsDetail = vnfTemplateDetailsDao.findDetail(template.getId(), VNF.AccessDetail.ACCESS_METHODS.name().toLowerCase());
|
VnfTemplateDetailVO accessMethodsDetail = vnfTemplateDetailsDao.findDetail(template.getId(), VNF.AccessDetail.ACCESS_METHODS.name().toLowerCase());
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import com.cloud.agent.AgentManager;
|
||||||
import com.cloud.api.query.dao.UserVmJoinDao;
|
import com.cloud.api.query.dao.UserVmJoinDao;
|
||||||
import com.cloud.configuration.Resource;
|
import com.cloud.configuration.Resource;
|
||||||
import com.cloud.dc.dao.DataCenterDao;
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
|
import com.cloud.deployasis.dao.TemplateDeployAsIsDetailsDao;
|
||||||
import com.cloud.domain.dao.DomainDao;
|
import com.cloud.domain.dao.DomainDao;
|
||||||
import com.cloud.event.dao.UsageEventDao;
|
import com.cloud.event.dao.UsageEventDao;
|
||||||
import com.cloud.exception.InvalidParameterValueException;
|
import com.cloud.exception.InvalidParameterValueException;
|
||||||
|
|
@ -204,6 +205,8 @@ public class TemplateManagerImplTest {
|
||||||
AccountManager _accountMgr;
|
AccountManager _accountMgr;
|
||||||
@Inject
|
@Inject
|
||||||
VnfTemplateManager vnfTemplateManager;
|
VnfTemplateManager vnfTemplateManager;
|
||||||
|
@Inject
|
||||||
|
TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
HeuristicRuleHelper heuristicRuleHelperMock;
|
HeuristicRuleHelper heuristicRuleHelperMock;
|
||||||
|
|
@ -956,6 +959,11 @@ public class TemplateManagerImplTest {
|
||||||
return Mockito.mock(VnfTemplateManager.class);
|
return Mockito.mock(VnfTemplateManager.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public TemplateDeployAsIsDetailsDao templateDeployAsIsDetailsDao() {
|
||||||
|
return Mockito.mock(TemplateDeployAsIsDetailsDao.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SnapshotHelper snapshotHelper() {
|
public SnapshotHelper snapshotHelper() {
|
||||||
return Mockito.mock(SnapshotHelper.class);
|
return Mockito.mock(SnapshotHelper.class);
|
||||||
|
|
|
||||||
|
|
@ -2528,7 +2528,7 @@
|
||||||
"label.vnf.cidr.list": "CIDR from which access to the VNF appliance's Management interface should be allowed from",
|
"label.vnf.cidr.list": "CIDR from which access to the VNF appliance's Management interface should be allowed from",
|
||||||
"label.vnf.cidr.list.tooltip": "the CIDR list to forward traffic from to the VNF management interface. Multiple entries must be separated by a single comma character (,). The default value is 0.0.0.0/0.",
|
"label.vnf.cidr.list.tooltip": "the CIDR list to forward traffic from to the VNF management interface. Multiple entries must be separated by a single comma character (,). The default value is 0.0.0.0/0.",
|
||||||
"label.vnf.configure.management": "Configure network rules for VNF's management interfaces",
|
"label.vnf.configure.management": "Configure network rules for VNF's management interfaces",
|
||||||
"label.vnf.configure.management.tooltip": "True by default, security group or network rules (source nat and firewall rules) will be configured for VNF management interfaces. False otherwise. Learn what rules are configured at http://docs.cloudstack.apache.org/en/latest/adminguide/networking/vnf_templates_appliances.html#deploying-vnf-appliances",
|
"label.vnf.configure.management.tooltip": "False by default, security group or network rules (source nat and firewall rules) will be configured for VNF management interfaces. True otherwise. Learn what rules are configured at http://docs.cloudstack.apache.org/en/latest/adminguide/networking/vnf_templates_appliances.html#deploying-vnf-appliances",
|
||||||
"label.vnf.detail.add": "Add VNF detail",
|
"label.vnf.detail.add": "Add VNF detail",
|
||||||
"label.vnf.detail.remove": "Remove VNF detail",
|
"label.vnf.detail.remove": "Remove VNF detail",
|
||||||
"label.vnf.details": "VNF Details",
|
"label.vnf.details": "VNF Details",
|
||||||
|
|
|
||||||
|
|
@ -372,6 +372,7 @@
|
||||||
<div>
|
<div>
|
||||||
<vnf-nics-selection
|
<vnf-nics-selection
|
||||||
:items="templateVnfNics"
|
:items="templateVnfNics"
|
||||||
|
:templateNics="templateNics"
|
||||||
:networks="networks"
|
:networks="networks"
|
||||||
@update-vnf-nic-networks="($event) => updateVnfNicNetworks($event)" />
|
@update-vnf-nic-networks="($event) => updateVnfNicNetworks($event)" />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1293,7 +1294,8 @@ export default {
|
||||||
return tabList
|
return tabList
|
||||||
},
|
},
|
||||||
showVnfNicsSection () {
|
showVnfNicsSection () {
|
||||||
return this.networks && this.networks.length > 0 && this.vm.templateid && this.templateVnfNics && this.templateVnfNics.length > 0
|
return ((this.networks && this.networks.length > 0) || (this.templateNics && this.templateNics.length > 0)) &&
|
||||||
|
this.vm.templateid && this.templateVnfNics && this.templateVnfNics.length > 0
|
||||||
},
|
},
|
||||||
showVnfConfigureManagement () {
|
showVnfConfigureManagement () {
|
||||||
const managementDeviceIds = []
|
const managementDeviceIds = []
|
||||||
|
|
@ -1303,6 +1305,11 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const deviceId of managementDeviceIds) {
|
for (const deviceId of managementDeviceIds) {
|
||||||
|
if (this.templateNics && this.templateNics[deviceId] &&
|
||||||
|
((this.templateNics[deviceId].selectednetworktype === 'Isolated' && this.templateNics[deviceId].selectednetworkvpcid === undefined) ||
|
||||||
|
(this.templateNics[deviceId].selectednetworktype === 'Shared' && this.templateNics[deviceId].selectednetworkwithsg))) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
if (this.vnfNicNetworks && this.vnfNicNetworks[deviceId] &&
|
if (this.vnfNicNetworks && this.vnfNicNetworks[deviceId] &&
|
||||||
((this.vnfNicNetworks[deviceId].type === 'Isolated' && this.vnfNicNetworks[deviceId].vpcid === undefined) ||
|
((this.vnfNicNetworks[deviceId].type === 'Isolated' && this.vnfNicNetworks[deviceId].vpcid === undefined) ||
|
||||||
(this.vnfNicNetworks[deviceId].type === 'Shared' && this.vnfNicNetworks[deviceId].service.filter(svc => svc.name === 'SecurityGroupProvider')))) {
|
(this.vnfNicNetworks[deviceId].type === 'Shared' && this.vnfNicNetworks[deviceId].service.filter(svc => svc.name === 'SecurityGroupProvider')))) {
|
||||||
|
|
@ -2005,7 +2012,7 @@ export default {
|
||||||
// All checked networks should be used and only once.
|
// All checked networks should be used and only once.
|
||||||
// Required NIC must be associated to a network
|
// Required NIC must be associated to a network
|
||||||
// DeviceID must be consequent
|
// DeviceID must be consequent
|
||||||
if (this.templateVnfNics && this.templateVnfNics.length > 0) {
|
if (this.templateVnfNics && this.templateVnfNics.length > 0 && (!this.templateNics || this.templateNics.length === 0)) {
|
||||||
let nextDeviceId = 0
|
let nextDeviceId = 0
|
||||||
const usedNetworkIds = []
|
const usedNetworkIds = []
|
||||||
const keys = Object.keys(this.vnfNicNetworks)
|
const keys = Object.keys(this.vnfNicNetworks)
|
||||||
|
|
@ -2629,6 +2636,9 @@ export default {
|
||||||
var network = this.options.networks[Math.min(i, this.options.networks.length - 1)]
|
var network = this.options.networks[Math.min(i, this.options.networks.length - 1)]
|
||||||
nic.selectednetworkid = network.id
|
nic.selectednetworkid = network.id
|
||||||
nic.selectednetworkname = network.name
|
nic.selectednetworkname = network.name
|
||||||
|
nic.selectednetworktype = network.type
|
||||||
|
nic.selectednetworkvpcid = network.vpcid
|
||||||
|
nic.selectednetworkwithsg = network.service.filter(svc => svc.name === 'SecurityGroupProvider').length > 0
|
||||||
this.nicToNetworkSelection.push({ nic: nic.id, network: network.id })
|
this.nicToNetworkSelection.push({ nic: nic.id, network: network.id })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@
|
||||||
<template #network="{ record }">
|
<template #network="{ record }">
|
||||||
<a-form-item style="display: block" :name="'nic-' + record.deviceid">
|
<a-form-item style="display: block" :name="'nic-' + record.deviceid">
|
||||||
<a-select
|
<a-select
|
||||||
|
disabled="templateNics && templateNics.length > 0"
|
||||||
@change="updateNicNetworkValue($event, record.deviceid)"
|
@change="updateNicNetworkValue($event, record.deviceid)"
|
||||||
optionFilterProp="label"
|
optionFilterProp="label"
|
||||||
:filterOption="(input, option) => {
|
:filterOption="(input, option) => {
|
||||||
|
|
@ -75,6 +76,10 @@ export default {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => []
|
default: () => []
|
||||||
},
|
},
|
||||||
|
templateNics: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
networks: {
|
networks: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => []
|
default: () => []
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue