mirror of https://github.com/apache/cloudstack.git
NE: more unit tests and UI optimization
This commit is contained in:
parent
cc3049d91d
commit
d409852b45
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
|||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
||||
|
|
@ -53,4 +54,20 @@ public class NetworkTest {
|
|||
Network.Provider transientProviderNew = Network.Provider.createTransientProvider("NetworkExtension");
|
||||
assertTrue("List should contain the new transient provider with same name", providers.contains(transientProviderNew));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomActionServiceLookup() {
|
||||
Network.Service customAction = Network.Service.getService("CustomAction");
|
||||
assertNotNull("CustomAction service should be available", customAction);
|
||||
assertTrue("CustomAction should be part of the supported services list",
|
||||
Network.Service.listAllServices().contains(customAction));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransientProviderIsNotGloballyRegistered() {
|
||||
Network.Provider transientProvider = Network.Provider.createTransientProvider("TransientOnly");
|
||||
assertNotNull(transientProvider);
|
||||
assertNull("Transient provider should not be retrievable from the global registry",
|
||||
Network.Provider.getProvider("TransientOnly"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4984,7 +4984,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
|
||||
@Override
|
||||
public void expungeLbVmRefs(List<Long> vmIds, Long batchSize) {
|
||||
if (CollectionUtils.isEmpty(getNetworkElementsIncludingExtensions()) || CollectionUtils.isEmpty(vmIds)) {
|
||||
if (CollectionUtils.isEmpty(vmIds)) {
|
||||
return;
|
||||
}
|
||||
for (NetworkElement element : getNetworkElementsIncludingExtensions()) {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ import static org.mockito.Mockito.never;
|
|||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.withSettings;
|
||||
|
||||
import java.io.File;
|
||||
import java.security.InvalidParameterException;
|
||||
|
|
@ -136,6 +137,8 @@ import com.cloud.network.dao.PhysicalNetworkDao;
|
|||
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
|
||||
import com.cloud.network.dao.PhysicalNetworkVO;
|
||||
import com.cloud.network.element.NetworkElement;
|
||||
import com.cloud.network.vpc.Vpc;
|
||||
import com.cloud.network.vpc.dao.VpcServiceMapDao;
|
||||
import org.apache.cloudstack.extension.NetworkCustomActionProvider;
|
||||
import com.cloud.org.Cluster;
|
||||
import com.cloud.serializer.GsonHelper;
|
||||
|
|
@ -207,6 +210,8 @@ public class ExtensionsManagerImplTest {
|
|||
@Mock
|
||||
private NetworkServiceMapDao networkServiceMapDao;
|
||||
@Mock
|
||||
private VpcServiceMapDao vpcServiceMapDao;
|
||||
@Mock
|
||||
private NetworkModel networkModel;
|
||||
|
||||
@Mock
|
||||
|
|
@ -1830,6 +1835,231 @@ public class ExtensionsManagerImplTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runNetworkCustomAction_NoProviderFound_ReturnsFailureResponse() {
|
||||
Network network = mock(Network.class);
|
||||
when(network.getId()).thenReturn(11L);
|
||||
|
||||
ExtensionCustomActionVO actionVO = mock(ExtensionCustomActionVO.class);
|
||||
when(actionVO.getId()).thenReturn(10L);
|
||||
when(actionVO.getUuid()).thenReturn("action-uuid");
|
||||
when(actionVO.getName()).thenReturn("dump-config");
|
||||
when(extensionCustomActionDetailsDao.listDetailsKeyPairsWithVisibility(10L))
|
||||
.thenReturn(new Pair<>(new HashMap<>(), new HashMap<>()));
|
||||
|
||||
ExtensionVO extensionVO = mock(ExtensionVO.class);
|
||||
|
||||
CustomActionResultResponse response = extensionsManager.runNetworkCustomAction(
|
||||
network, actionVO, extensionVO, ExtensionCustomAction.ResourceType.Network, Collections.emptyMap());
|
||||
|
||||
assertFalse(response.getSuccess());
|
||||
assertEquals("No network service provider found for this network", response.getResult().get(ApiConstants.DETAILS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runNetworkCustomAction_ProviderElementMissing_ReturnsFailureResponse() {
|
||||
Network network = mock(Network.class);
|
||||
when(network.getId()).thenReturn(12L);
|
||||
when(networkServiceMapDao.getProviderForServiceInNetwork(12L, Network.Service.CustomAction)).thenReturn("ExtProvider");
|
||||
when(networkModel.getElementImplementingProvider("ExtProvider")).thenReturn(null);
|
||||
|
||||
ExtensionCustomActionVO actionVO = mock(ExtensionCustomActionVO.class);
|
||||
when(actionVO.getId()).thenReturn(11L);
|
||||
when(actionVO.getUuid()).thenReturn("action-uuid");
|
||||
when(actionVO.getName()).thenReturn("dump-config");
|
||||
when(extensionCustomActionDetailsDao.listDetailsKeyPairsWithVisibility(11L))
|
||||
.thenReturn(new Pair<>(new HashMap<>(), new HashMap<>()));
|
||||
|
||||
ExtensionVO extensionVO = mock(ExtensionVO.class);
|
||||
|
||||
CustomActionResultResponse response = extensionsManager.runNetworkCustomAction(
|
||||
network, actionVO, extensionVO, ExtensionCustomAction.ResourceType.Network, Collections.emptyMap());
|
||||
|
||||
assertFalse(response.getSuccess());
|
||||
assertEquals("No network element found for provider: ExtProvider", response.getResult().get(ApiConstants.DETAILS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runNetworkCustomAction_ProviderCannotHandle_ReturnsFailureResponse() {
|
||||
Network network = mock(Network.class);
|
||||
when(network.getId()).thenReturn(13L);
|
||||
when(networkServiceMapDao.getProviderForServiceInNetwork(13L, Network.Service.CustomAction)).thenReturn("ExtProvider");
|
||||
|
||||
NetworkElement element = mock(NetworkElement.class, withSettings().extraInterfaces(NetworkCustomActionProvider.class));
|
||||
NetworkCustomActionProvider provider = (NetworkCustomActionProvider) element;
|
||||
when(networkModel.getElementImplementingProvider("ExtProvider")).thenReturn(element);
|
||||
when(provider.canHandleCustomAction(network)).thenReturn(false);
|
||||
|
||||
ExtensionCustomActionVO actionVO = mock(ExtensionCustomActionVO.class);
|
||||
when(actionVO.getId()).thenReturn(12L);
|
||||
when(actionVO.getUuid()).thenReturn("action-uuid");
|
||||
when(actionVO.getName()).thenReturn("dump-config");
|
||||
when(extensionCustomActionDetailsDao.listDetailsKeyPairsWithVisibility(12L))
|
||||
.thenReturn(new Pair<>(new HashMap<>(), new HashMap<>()));
|
||||
|
||||
ExtensionVO extensionVO = mock(ExtensionVO.class);
|
||||
|
||||
CustomActionResultResponse response = extensionsManager.runNetworkCustomAction(
|
||||
network, actionVO, extensionVO, ExtensionCustomAction.ResourceType.Network, Collections.emptyMap());
|
||||
|
||||
assertFalse(response.getSuccess());
|
||||
assertTrue(response.getResult().get(ApiConstants.DETAILS).contains("cannot handle custom action"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runNetworkCustomAction_ProviderDoesNotImplementCustomAction_ReturnsFailureResponse() {
|
||||
Network network = mock(Network.class);
|
||||
when(network.getId()).thenReturn(131L);
|
||||
when(networkServiceMapDao.getProviderForServiceInNetwork(131L, Network.Service.CustomAction)).thenReturn("ExtProvider");
|
||||
|
||||
NetworkElement element = mock(NetworkElement.class);
|
||||
when(networkModel.getElementImplementingProvider("ExtProvider")).thenReturn(element);
|
||||
|
||||
ExtensionCustomActionVO actionVO = mock(ExtensionCustomActionVO.class);
|
||||
when(actionVO.getId()).thenReturn(121L);
|
||||
when(actionVO.getUuid()).thenReturn("action-uuid");
|
||||
when(actionVO.getName()).thenReturn("dump-config");
|
||||
when(extensionCustomActionDetailsDao.listDetailsKeyPairsWithVisibility(121L))
|
||||
.thenReturn(new Pair<>(new HashMap<>(), new HashMap<>()));
|
||||
|
||||
ExtensionVO extensionVO = mock(ExtensionVO.class);
|
||||
|
||||
CustomActionResultResponse response = extensionsManager.runNetworkCustomAction(
|
||||
network, actionVO, extensionVO, ExtensionCustomAction.ResourceType.Network, Collections.emptyMap());
|
||||
|
||||
assertFalse(response.getSuccess());
|
||||
assertTrue(response.getResult().get(ApiConstants.DETAILS).contains("does not support custom actions"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runNetworkCustomAction_SuccessfulExecution_ReturnsSuccessResponse() {
|
||||
Network network = mock(Network.class);
|
||||
when(network.getId()).thenReturn(14L);
|
||||
when(networkServiceMapDao.getProviderForServiceInNetwork(14L, Network.Service.CustomAction)).thenReturn("ExtProvider");
|
||||
|
||||
NetworkElement element = mock(NetworkElement.class, withSettings().extraInterfaces(NetworkCustomActionProvider.class));
|
||||
NetworkCustomActionProvider provider = (NetworkCustomActionProvider) element;
|
||||
when(networkModel.getElementImplementingProvider("ExtProvider")).thenReturn(element);
|
||||
when(provider.canHandleCustomAction(network)).thenReturn(true);
|
||||
when(provider.runCustomAction(eq(network), eq("dump-config"), any())).thenReturn("dump-output");
|
||||
|
||||
ExtensionCustomActionVO actionVO = mock(ExtensionCustomActionVO.class);
|
||||
when(actionVO.getId()).thenReturn(13L);
|
||||
when(actionVO.getUuid()).thenReturn("action-uuid");
|
||||
when(actionVO.getName()).thenReturn("dump-config");
|
||||
when(extensionCustomActionDetailsDao.listDetailsKeyPairsWithVisibility(13L))
|
||||
.thenReturn(new Pair<>(new HashMap<>(), new HashMap<>()));
|
||||
|
||||
ExtensionVO extensionVO = mock(ExtensionVO.class);
|
||||
|
||||
CustomActionResultResponse response = extensionsManager.runNetworkCustomAction(
|
||||
network, actionVO, extensionVO, ExtensionCustomAction.ResourceType.Network, Collections.emptyMap());
|
||||
|
||||
assertTrue(response.getSuccess());
|
||||
assertEquals("dump-output", response.getResult().get(ApiConstants.DETAILS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runVpcCustomAction_ProviderNotCustomActionProvider_ReturnsFailureResponse() {
|
||||
Vpc vpc = mock(Vpc.class);
|
||||
when(vpc.getId()).thenReturn(21L);
|
||||
when(vpcServiceMapDao.getProviderForServiceInVpc(21L, Network.Service.CustomAction)).thenReturn("VpcProvider");
|
||||
|
||||
NetworkElement element = mock(NetworkElement.class);
|
||||
when(networkModel.getElementImplementingProvider("VpcProvider")).thenReturn(element);
|
||||
|
||||
ExtensionCustomActionVO actionVO = mock(ExtensionCustomActionVO.class);
|
||||
when(actionVO.getId()).thenReturn(20L);
|
||||
when(actionVO.getUuid()).thenReturn("action-uuid");
|
||||
when(actionVO.getName()).thenReturn("dump-config");
|
||||
when(extensionCustomActionDetailsDao.listDetailsKeyPairsWithVisibility(20L))
|
||||
.thenReturn(new Pair<>(new HashMap<>(), new HashMap<>()));
|
||||
|
||||
ExtensionVO extensionVO = mock(ExtensionVO.class);
|
||||
|
||||
CustomActionResultResponse response = extensionsManager.runVpcCustomAction(
|
||||
vpc, actionVO, extensionVO, ExtensionCustomAction.ResourceType.Vpc, Collections.emptyMap());
|
||||
|
||||
assertFalse(response.getSuccess());
|
||||
assertTrue(response.getResult().get(ApiConstants.DETAILS).contains("does not support custom actions"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runVpcCustomAction_NoProviderFound_ReturnsFailureResponse() {
|
||||
Vpc vpc = mock(Vpc.class);
|
||||
when(vpc.getId()).thenReturn(211L);
|
||||
|
||||
ExtensionCustomActionVO actionVO = mock(ExtensionCustomActionVO.class);
|
||||
when(actionVO.getId()).thenReturn(201L);
|
||||
when(actionVO.getUuid()).thenReturn("action-uuid");
|
||||
when(actionVO.getName()).thenReturn("dump-config");
|
||||
when(extensionCustomActionDetailsDao.listDetailsKeyPairsWithVisibility(201L))
|
||||
.thenReturn(new Pair<>(new HashMap<>(), new HashMap<>()));
|
||||
|
||||
ExtensionVO extensionVO = mock(ExtensionVO.class);
|
||||
|
||||
CustomActionResultResponse response = extensionsManager.runVpcCustomAction(
|
||||
vpc, actionVO, extensionVO, ExtensionCustomAction.ResourceType.Vpc, Collections.emptyMap());
|
||||
|
||||
assertFalse(response.getSuccess());
|
||||
assertEquals("No VPC service provider found for this VPC", response.getResult().get(ApiConstants.DETAILS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runVpcCustomAction_ProviderCannotHandleVpc_ReturnsFailureResponse() {
|
||||
Vpc vpc = mock(Vpc.class);
|
||||
when(vpc.getId()).thenReturn(212L);
|
||||
when(vpcServiceMapDao.getProviderForServiceInVpc(212L, Network.Service.CustomAction)).thenReturn("VpcProvider");
|
||||
|
||||
NetworkElement element = mock(NetworkElement.class, withSettings().extraInterfaces(NetworkCustomActionProvider.class));
|
||||
NetworkCustomActionProvider provider = (NetworkCustomActionProvider) element;
|
||||
when(networkModel.getElementImplementingProvider("VpcProvider")).thenReturn(element);
|
||||
when(provider.canHandleVpcCustomAction(vpc)).thenReturn(false);
|
||||
|
||||
ExtensionCustomActionVO actionVO = mock(ExtensionCustomActionVO.class);
|
||||
when(actionVO.getId()).thenReturn(202L);
|
||||
when(actionVO.getUuid()).thenReturn("action-uuid");
|
||||
when(actionVO.getName()).thenReturn("dump-config");
|
||||
when(extensionCustomActionDetailsDao.listDetailsKeyPairsWithVisibility(202L))
|
||||
.thenReturn(new Pair<>(new HashMap<>(), new HashMap<>()));
|
||||
|
||||
ExtensionVO extensionVO = mock(ExtensionVO.class);
|
||||
|
||||
CustomActionResultResponse response = extensionsManager.runVpcCustomAction(
|
||||
vpc, actionVO, extensionVO, ExtensionCustomAction.ResourceType.Vpc, Collections.emptyMap());
|
||||
|
||||
assertFalse(response.getSuccess());
|
||||
assertTrue(response.getResult().get(ApiConstants.DETAILS).contains("cannot handle custom action"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runVpcCustomAction_SuccessfulExecution_ReturnsSuccessResponse() {
|
||||
Vpc vpc = mock(Vpc.class);
|
||||
when(vpc.getId()).thenReturn(22L);
|
||||
when(vpcServiceMapDao.getProviderForServiceInVpc(22L, Network.Service.CustomAction)).thenReturn("VpcProvider");
|
||||
|
||||
NetworkElement element = mock(NetworkElement.class, withSettings().extraInterfaces(NetworkCustomActionProvider.class));
|
||||
NetworkCustomActionProvider provider = (NetworkCustomActionProvider) element;
|
||||
when(networkModel.getElementImplementingProvider("VpcProvider")).thenReturn(element);
|
||||
when(provider.canHandleVpcCustomAction(vpc)).thenReturn(true);
|
||||
when(provider.runCustomAction(eq(vpc), eq("dump-config"), any())).thenReturn("vpc-dump-output");
|
||||
|
||||
ExtensionCustomActionVO actionVO = mock(ExtensionCustomActionVO.class);
|
||||
when(actionVO.getId()).thenReturn(21L);
|
||||
when(actionVO.getUuid()).thenReturn("action-uuid");
|
||||
when(actionVO.getName()).thenReturn("dump-config");
|
||||
when(extensionCustomActionDetailsDao.listDetailsKeyPairsWithVisibility(21L))
|
||||
.thenReturn(new Pair<>(new HashMap<>(), new HashMap<>()));
|
||||
|
||||
ExtensionVO extensionVO = mock(ExtensionVO.class);
|
||||
|
||||
CustomActionResultResponse response = extensionsManager.runVpcCustomAction(
|
||||
vpc, actionVO, extensionVO, ExtensionCustomAction.ResourceType.Vpc, Collections.emptyMap());
|
||||
|
||||
assertTrue(response.getSuccess());
|
||||
assertEquals("vpc-dump-output", response.getResult().get(ApiConstants.DETAILS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createCustomActionResponse_SetsBasicFields() {
|
||||
ExtensionCustomAction action = mock(ExtensionCustomAction.class);
|
||||
|
|
|
|||
|
|
@ -2839,4 +2839,3 @@ class TestNetworkExtensionNamespace(cloudstackTestCase):
|
|||
self._teardown_extension()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ export default {
|
|||
data () {
|
||||
return {
|
||||
roleTypes: [],
|
||||
resourceTypeOptions: ['VirtualMachine', 'Network'],
|
||||
resourceTypeOptions: ['VirtualMachine', 'Network', 'Vpc'],
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
|
|
@ -204,13 +204,13 @@ export default {
|
|||
updateResourceTypeByExtension (selectedExtension) {
|
||||
const type = selectedExtension?.type
|
||||
if (type === 'NetworkOrchestrator') {
|
||||
this.resourceTypeOptions = ['Network']
|
||||
this.resourceTypeOptions = ['Network', 'Vpc']
|
||||
this.form.resourcetype = 'Network'
|
||||
} else if (type === 'Orchestrator') {
|
||||
this.resourceTypeOptions = ['VirtualMachine']
|
||||
this.form.resourcetype = 'VirtualMachine'
|
||||
} else {
|
||||
this.resourceTypeOptions = ['VirtualMachine', 'Network']
|
||||
this.resourceTypeOptions = ['VirtualMachine', 'Network', 'Vpc']
|
||||
if (!this.form.resourcetype) {
|
||||
this.form.resourcetype = 'VirtualMachine'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
<template v-if="column.key === 'actions'">
|
||||
<span style="margin-right: 5px">
|
||||
<tooltip-button
|
||||
v-if="'updateRegisteredExtension' in $store.getters.apis"
|
||||
:tooltip="$t('label.action.update.extension.resource')"
|
||||
type="default"
|
||||
icon="edit-outlined"
|
||||
|
|
|
|||
|
|
@ -60,10 +60,10 @@
|
|||
<a-radio-button value="isolated">
|
||||
{{ $t('label.isolated') }}
|
||||
</a-radio-button>
|
||||
<a-radio-button value="l2" v-if="form.provider !== 'NSX' && form.provider !== 'Netris' && !isExternalNetworkProvider">
|
||||
<a-radio-button value="l2" v-if="form.provider !== 'NSX' && form.provider !== 'Netris'">
|
||||
{{ $t('label.l2') }}
|
||||
</a-radio-button>
|
||||
<a-radio-button value="shared" v-if="form.provider !== 'NSX' && form.provider !== 'Netris' && !isExternalNetworkProvider">
|
||||
<a-radio-button value="shared" v-if="form.provider !== 'NSX' && form.provider !== 'Netris'">
|
||||
{{ $t('label.shared') }}
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
|
|
@ -138,7 +138,7 @@
|
|||
<a-select-option key="" >{{ }}</a-select-option>
|
||||
<a-select-option :value="'NSX'" :label="$t('label.nsx')"> {{ $t('label.nsx') }} </a-select-option>
|
||||
<a-select-option :value="'Netris'" :label="$t('label.netris')"> {{ $t('label.netris') }} </a-select-option>
|
||||
</a-select>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
|
@ -208,7 +208,7 @@
|
|||
</a-form-item>
|
||||
<a-row :gutter="12">
|
||||
<a-col :md="12" :lg="12">
|
||||
<a-form-item name="promiscuousmode" ref="promiscuousmode" v-if="form.provider !== 'NSX' && form.provider !== 'Netris' && !isExternalNetworkProvider">
|
||||
<a-form-item name="promiscuousmode" ref="promiscuousmode" v-if="form.provider !== 'NSX' && form.provider !== 'Netris'">
|
||||
<template #label>
|
||||
<tooltip-label :title="$t('label.promiscuousmode')" :tooltip="$t('message.network.offering.promiscuous.mode')"/>
|
||||
</template>
|
||||
|
|
@ -303,8 +303,8 @@
|
|||
<CheckBoxSelectPair
|
||||
:resourceKey="item.name"
|
||||
:checkBoxLabel="item.description"
|
||||
:forExternalNetProvider="form.provider === 'NSX' || form.provider === 'Netris' || isExternalNetworkProvider"
|
||||
:defaultCheckBoxValue="form.provider === 'NSX' || form.provider === 'Netris' || isExternalNetworkProvider"
|
||||
:forExternalNetProvider="form.provider === 'NSX' || form.provider === 'Netris'"
|
||||
:defaultCheckBoxValue="form.provider === 'NSX' || form.provider === 'Netris'"
|
||||
:selectOptions="!supportedServiceLoading ? item.provider: []"
|
||||
@handle-checkselectpair-change="handleSupportedServiceChange"/>
|
||||
</a-list-item>
|
||||
|
|
@ -669,20 +669,8 @@ export default {
|
|||
description: 'Netris',
|
||||
enabled: true
|
||||
},
|
||||
externalNetworkProviderObj: {
|
||||
name: '',
|
||||
description: 'External Network',
|
||||
enabled: true
|
||||
},
|
||||
nsxSupportedServicesMap: {},
|
||||
netrisSupportedServicesMap: {},
|
||||
externalNetworkSupportedServicesMap: {},
|
||||
availableExtensionProviders: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isExternalNetworkProvider () {
|
||||
return this.availableExtensionProviders.some(e => e.name === this.provider)
|
||||
netrisSupportedServicesMap: {}
|
||||
}
|
||||
},
|
||||
beforeCreate () {
|
||||
|
|
@ -744,30 +732,6 @@ export default {
|
|||
this.fetchServiceOfferingData()
|
||||
this.fetchIpv6NetworkOfferingConfiguration()
|
||||
this.fetchRoutedNetworkConfiguration()
|
||||
this.fetchExtensionProviders()
|
||||
},
|
||||
fetchExtensionProviders () {
|
||||
// Load NetworkOrchestrator extensions that are registered to at least one
|
||||
// physical network (i.e. have a corresponding NetworkServiceProvider entry).
|
||||
// Only these can be selected as a provider when creating a network offering.
|
||||
getAPI('listExtensions', { type: 'NetworkOrchestrator', state: 'Enabled' }).then(json => {
|
||||
const allExts = (json.listextensionsresponse && json.listextensionsresponse.extension) || []
|
||||
if (allExts.length === 0) {
|
||||
this.availableExtensionProviders = []
|
||||
return
|
||||
}
|
||||
// Filter to those which have at least one matching NSP (nsp name == extension name)
|
||||
getAPI('listNetworkServiceProviders', {}).then(nspJson => {
|
||||
const nsps = (nspJson.listnetworkserviceprovidersresponse && nspJson.listnetworkserviceprovidersresponse.networkserviceprovider) || []
|
||||
const nspNames = new Set(nsps.map(n => n.name))
|
||||
this.availableExtensionProviders = allExts.filter(e => nspNames.has(e.name))
|
||||
}).catch(() => {
|
||||
// Fallback: show all enabled extensions
|
||||
this.availableExtensionProviders = allExts
|
||||
})
|
||||
}).catch(() => {
|
||||
this.availableExtensionProviders = []
|
||||
})
|
||||
},
|
||||
isAdmin () {
|
||||
return isAdmin()
|
||||
|
|
@ -942,7 +906,7 @@ export default {
|
|||
this.supportedServiceLoading = true
|
||||
var supportedServices = this.supportedServices
|
||||
var self = this
|
||||
if (this.provider !== 'NSX' && this.provider !== 'Netris' && !this.isExternalNetworkProvider) {
|
||||
if (this.provider !== 'NSX' && this.provider !== 'Netris') {
|
||||
if (this.networkmode === 'ROUTED' && this.guestType === 'isolated') {
|
||||
supportedServices = supportedServices.filter(service => {
|
||||
return !['SourceNat', 'StaticNat', 'Lb', 'PortForwarding', 'Vpn'].includes(service.name)
|
||||
|
|
@ -953,11 +917,13 @@ export default {
|
|||
var providers = svc.provider
|
||||
providers.forEach(function (provider, providerIndex) {
|
||||
if (self.forVpc) { // *** vpc ***
|
||||
var enabledProviders = ['VpcVirtualRouter', 'Netscaler', 'BigSwitchBcf', 'ConfigDrive']
|
||||
if (self.lbType === 'internalLb') {
|
||||
enabledProviders.push('InternalLbVm')
|
||||
// For VPC offerings, keep router-specific invalid providers disabled,
|
||||
// but allow extension/external providers to be selected.
|
||||
if (provider.name === 'InternalLbVm') {
|
||||
provider.enabled = self.lbType === 'internalLb' && svc.name === 'Lb'
|
||||
} else {
|
||||
provider.enabled = !['VirtualRouter', 'Nsx', 'Netris'].includes(provider.name)
|
||||
}
|
||||
provider.enabled = enabledProviders.includes(provider.name)
|
||||
} else { // *** non-vpc ***
|
||||
provider.enabled = !['InternalLbVm', 'VpcVirtualRouter', 'Nsx', 'Netris'].includes(provider.name)
|
||||
}
|
||||
|
|
@ -979,8 +945,6 @@ export default {
|
|||
return Object.keys(this.nsxSupportedServicesMap).includes(svc.name)
|
||||
} else if (this.provider === 'Netris') {
|
||||
return Object.keys(this.netrisSupportedServicesMap).includes(svc.name)
|
||||
} else if (this.isExternalNetworkProvider) {
|
||||
return Object.keys(this.externalNetworkSupportedServicesMap).includes(svc.name)
|
||||
}
|
||||
})
|
||||
supportedServices = supportedServices.map(svc => {
|
||||
|
|
@ -989,8 +953,6 @@ export default {
|
|||
svc.provider = [this.NSX]
|
||||
} else if (this.provider === 'Netris') {
|
||||
svc.provider = [this.Netris]
|
||||
} else if (this.isExternalNetworkProvider) {
|
||||
svc.provider = [this.externalNetworkProviderObj]
|
||||
}
|
||||
} else {
|
||||
if (this.forVpc) {
|
||||
|
|
@ -1069,46 +1031,9 @@ export default {
|
|||
...(this.forVpc && { NetworkACL: this.Netris }),
|
||||
...(!this.forVpc && { Firewall: this.Netris })
|
||||
}
|
||||
} else if (this.isExternalNetworkProvider) {
|
||||
// Extension-backed provider: services come from the extension's network.services detail.
|
||||
// this.provider is the extension name (= NSP name)
|
||||
const extProviderObj = {
|
||||
name: this.provider,
|
||||
description: this.provider,
|
||||
enabled: true
|
||||
}
|
||||
const svcMap = { Dhcp: this.VR, Dns: this.VR, UserData: this.VR }
|
||||
// Infer services from the selected extension's network.services detail
|
||||
const extDef = this.availableExtensionProviders.find(e => e.name === this.provider)
|
||||
const services = this._getExtensionServices(extDef)
|
||||
if (services.length > 0) {
|
||||
services.forEach(svc => {
|
||||
if (!['Dhcp', 'Dns', 'UserData'].includes(svc)) {
|
||||
svcMap[svc] = extProviderObj
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// Default services if no capabilities declared
|
||||
svcMap.SourceNat = extProviderObj
|
||||
svcMap.StaticNat = extProviderObj
|
||||
svcMap.PortForwarding = extProviderObj
|
||||
svcMap.Firewall = extProviderObj
|
||||
svcMap.Gateway = extProviderObj
|
||||
}
|
||||
this.externalNetworkSupportedServicesMap = svcMap
|
||||
this.externalNetworkProviderObj = extProviderObj
|
||||
}
|
||||
this.fetchSupportedServiceData()
|
||||
},
|
||||
_getExtensionServices (extDef) {
|
||||
if (!extDef || !extDef.details) return []
|
||||
|
||||
const servicesCsv = extDef.details['network.services']
|
||||
if (servicesCsv && typeof servicesCsv === 'string') {
|
||||
return servicesCsv.split(',').map(x => x.trim()).filter(x => x.length > 0)
|
||||
}
|
||||
return []
|
||||
},
|
||||
handleForNetworkModeChange (networkMode) {
|
||||
this.networkmode = networkMode
|
||||
this.fetchSupportedServiceData()
|
||||
|
|
|
|||
|
|
@ -337,22 +337,9 @@ export default {
|
|||
enabled: true
|
||||
},
|
||||
nsxSupportedServicesMap: {},
|
||||
externalNetworkProviderObj: {
|
||||
name: '',
|
||||
description: 'External Network',
|
||||
enabled: true
|
||||
},
|
||||
externalNetworkSupportedServicesMap: {},
|
||||
availableExtensionProviders: [],
|
||||
conservemode: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isExternalNetworkProvider () {
|
||||
const selectedProvider = this.form?.provider || this.provider
|
||||
return this.availableExtensionProviders.some(e => e.name === selectedProvider)
|
||||
}
|
||||
},
|
||||
beforeCreate () {
|
||||
this.apiParams = this.$getApiParams('createVPCOffering')
|
||||
},
|
||||
|
|
@ -397,25 +384,6 @@ export default {
|
|||
this.fetchSupportedServiceData()
|
||||
this.fetchIpv6NetworkOfferingConfiguration()
|
||||
this.fetchRoutedNetworkConfiguration()
|
||||
this.fetchExtensionProviders()
|
||||
},
|
||||
fetchExtensionProviders () {
|
||||
getAPI('listExtensions', { type: 'NetworkOrchestrator', state: 'Enabled' }).then(json => {
|
||||
const allExts = (json.listextensionsresponse && json.listextensionsresponse.extension) || []
|
||||
if (allExts.length === 0) {
|
||||
this.availableExtensionProviders = []
|
||||
return
|
||||
}
|
||||
getAPI('listNetworkServiceProviders', {}).then(nspJson => {
|
||||
const nsps = (nspJson.listnetworkserviceprovidersresponse && nspJson.listnetworkserviceprovidersresponse.networkserviceprovider) || []
|
||||
const nspNames = new Set(nsps.map(n => n.name))
|
||||
this.availableExtensionProviders = allExts.filter(e => nspNames.has(e.name))
|
||||
}).catch(() => {
|
||||
this.availableExtensionProviders = allExts
|
||||
})
|
||||
}).catch(() => {
|
||||
this.availableExtensionProviders = []
|
||||
})
|
||||
},
|
||||
isAdmin () {
|
||||
return isAdmin()
|
||||
|
|
@ -465,18 +433,7 @@ export default {
|
|||
},
|
||||
fetchSupportedServiceData () {
|
||||
var services = []
|
||||
if (this.isExternalNetworkProvider) {
|
||||
const serviceMap = this._buildExternalVpcServiceMap()
|
||||
Object.keys(serviceMap).forEach(serviceName => {
|
||||
services.push({
|
||||
name: serviceName,
|
||||
enabled: true,
|
||||
provider: Array.isArray(serviceMap[serviceName])
|
||||
? serviceMap[serviceName]
|
||||
: [serviceMap[serviceName]]
|
||||
})
|
||||
})
|
||||
} else if (this.provider === 'NSX') {
|
||||
if (this.provider === 'NSX') {
|
||||
services.push({
|
||||
name: 'Dhcp',
|
||||
enabled: true,
|
||||
|
|
@ -563,82 +520,48 @@ export default {
|
|||
provider: [{ name: 'VpcVirtualRouter' }]
|
||||
})
|
||||
} else {
|
||||
services.push({
|
||||
name: 'Dhcp',
|
||||
provider: [
|
||||
{ name: 'VpcVirtualRouter' },
|
||||
{ name: 'ConfigDrive' }
|
||||
]
|
||||
})
|
||||
services.push({
|
||||
name: 'Dns',
|
||||
provider: [
|
||||
{ name: 'VpcVirtualRouter' },
|
||||
{ name: 'ConfigDrive' }
|
||||
]
|
||||
})
|
||||
services.push({
|
||||
name: 'Lb',
|
||||
provider: [
|
||||
{ name: 'VpcVirtualRouter' },
|
||||
{ name: 'InternalLbVm' }
|
||||
]
|
||||
})
|
||||
services.push({
|
||||
name: 'Gateway',
|
||||
provider: [
|
||||
{ name: 'VpcVirtualRouter' },
|
||||
{ name: 'BigSwitchBcf' }
|
||||
]
|
||||
})
|
||||
services.push({
|
||||
name: 'StaticNat',
|
||||
provider: [
|
||||
{ name: 'VpcVirtualRouter' },
|
||||
{ name: 'BigSwitchBcf' }
|
||||
]
|
||||
})
|
||||
services.push({
|
||||
name: 'SourceNat',
|
||||
provider: [
|
||||
{ name: 'VpcVirtualRouter' },
|
||||
{ name: 'BigSwitchBcf' }
|
||||
]
|
||||
})
|
||||
services.push({
|
||||
name: 'NetworkACL',
|
||||
provider: [
|
||||
{ name: 'VpcVirtualRouter' },
|
||||
{ name: 'BigSwitchBcf' }
|
||||
]
|
||||
})
|
||||
services.push({
|
||||
name: 'PortForwarding',
|
||||
provider: [{ name: 'VpcVirtualRouter' }]
|
||||
})
|
||||
services.push({
|
||||
name: 'UserData',
|
||||
provider: [
|
||||
{ name: 'VpcVirtualRouter' },
|
||||
{ name: 'ConfigDrive' }
|
||||
]
|
||||
})
|
||||
services.push({
|
||||
name: 'Vpn',
|
||||
provider: [
|
||||
{ name: 'VpcVirtualRouter' },
|
||||
{ name: 'BigSwitchBcf' }
|
||||
]
|
||||
})
|
||||
services.push({
|
||||
name: 'Connectivity',
|
||||
provider: [
|
||||
{ name: 'BigSwitchBcf' },
|
||||
{ name: 'NiciraNvp' },
|
||||
{ name: 'Ovs' },
|
||||
{ name: 'JuniperContrailVpcRouter' }
|
||||
]
|
||||
this.supportedServiceLoading = true
|
||||
getAPI('listSupportedNetworkServices').then(json => {
|
||||
const vpcServices = ['Dhcp', 'Dns', 'Lb', 'Gateway', 'StaticNat', 'SourceNat', 'NetworkACL', 'PortForwarding', 'UserData', 'Vpn', 'Connectivity', 'CustomAction']
|
||||
services = (json?.listsupportednetworkservicesresponse?.networkservice || [])
|
||||
.filter(service => vpcServices.includes(service.name))
|
||||
.map(service => {
|
||||
const providerMap = {}
|
||||
const providers = [...(service.provider || []), ...(service.name === 'Lb' ? [{ name: 'InternalLbVm' }] : [])]
|
||||
.map(provider => {
|
||||
const providerName = provider.name === 'VirtualRouter' ? 'VpcVirtualRouter' : provider.name
|
||||
const enabled = providerName === 'InternalLbVm'
|
||||
? service.name === 'Lb'
|
||||
: !['VirtualRouter', 'Nsx', 'Netris'].includes(providerName)
|
||||
return {
|
||||
name: providerName,
|
||||
description: providerName,
|
||||
enabled
|
||||
}
|
||||
})
|
||||
.filter(provider => {
|
||||
if (providerMap[provider.name]) {
|
||||
return false
|
||||
}
|
||||
providerMap[provider.name] = true
|
||||
return true
|
||||
})
|
||||
return {
|
||||
...service,
|
||||
description: service.name,
|
||||
provider: providers
|
||||
}
|
||||
})
|
||||
|
||||
this.supportedServices = []
|
||||
if (this.networkmode === 'ROUTED') {
|
||||
services = services.filter(service => !['SourceNat', 'StaticNat', 'Lb', 'PortForwarding', 'Vpn'].includes(service.name))
|
||||
}
|
||||
this.supportedServices = services
|
||||
}).finally(() => {
|
||||
this.supportedServiceLoading = false
|
||||
})
|
||||
return
|
||||
}
|
||||
this.supportedServices = []
|
||||
if (this.networkmode === 'ROUTED') {
|
||||
|
|
@ -667,64 +590,9 @@ export default {
|
|||
if (this.provider === 'NSX') {
|
||||
this.form.nsxsupportlb = true
|
||||
this.handleNsxLbService(true)
|
||||
} else if (this.isExternalNetworkProvider) {
|
||||
this._buildExternalVpcServiceMap()
|
||||
}
|
||||
this.fetchSupportedServiceData()
|
||||
},
|
||||
_getExtensionServices (extDef) {
|
||||
if (!extDef || !extDef.details) {
|
||||
return []
|
||||
}
|
||||
|
||||
const servicesCsv = extDef.details['network.services']
|
||||
if (servicesCsv && typeof servicesCsv === 'string') {
|
||||
return servicesCsv.split(',').map(x => x.trim()).filter(x => x.length > 0)
|
||||
}
|
||||
return []
|
||||
},
|
||||
_buildExternalVpcServiceMap () {
|
||||
const selectedProvider = this.form?.provider || this.provider
|
||||
const extProviderObj = {
|
||||
name: selectedProvider,
|
||||
description: selectedProvider,
|
||||
enabled: true
|
||||
}
|
||||
const extWithFallbackProviders = [
|
||||
{ name: selectedProvider },
|
||||
{ name: 'VpcVirtualRouter' },
|
||||
{ name: 'ConfigDrive' }
|
||||
]
|
||||
const serviceMap = {
|
||||
Dhcp: extWithFallbackProviders,
|
||||
Dns: extWithFallbackProviders,
|
||||
UserData: extWithFallbackProviders
|
||||
}
|
||||
|
||||
const extDef = this.availableExtensionProviders.find(e => e.name === selectedProvider)
|
||||
const services = this._getExtensionServices(extDef)
|
||||
const allowedVpcServices = new Set([
|
||||
'Gateway', 'Lb', 'StaticNat', 'SourceNat', 'NetworkACL', 'PortForwarding', 'Vpn', 'CustomAction'
|
||||
])
|
||||
|
||||
services.forEach(service => {
|
||||
if (allowedVpcServices.has(service)) {
|
||||
serviceMap[service] = [{ name: selectedProvider }]
|
||||
}
|
||||
})
|
||||
|
||||
// Fallback for older extensions that only declare partial details.
|
||||
if (Object.keys(serviceMap).length <= 3) {
|
||||
serviceMap.SourceNat = [{ name: selectedProvider }]
|
||||
serviceMap.StaticNat = [{ name: selectedProvider }]
|
||||
serviceMap.PortForwarding = [{ name: selectedProvider }]
|
||||
serviceMap.NetworkACL = [{ name: selectedProvider }]
|
||||
}
|
||||
|
||||
this.externalNetworkProviderObj = extProviderObj
|
||||
this.externalNetworkSupportedServicesMap = serviceMap
|
||||
return serviceMap
|
||||
},
|
||||
handleNsxLbService (supportLb) {
|
||||
console.log(supportLb)
|
||||
if (!supportLb) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue