diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java index e365d8bc2dc7..02aad88b617f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java @@ -33,6 +33,7 @@ import org.apache.cloudstack.api.response.ConfigurationResponse; import org.apache.cloudstack.api.response.ImageStoreResponse; import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.config.Configuration; @@ -103,6 +104,13 @@ public class ListCfgsByCmd extends BaseListCmd { @Parameter(name = ApiConstants.PARENT, type = CommandType.STRING, description = "lists configuration by parent name (primarily used for UI)", since = "4.18.0") private String parentName; + @Parameter(name = ApiConstants.NETWORK_ID, + type = CommandType.UUID, + entityType = NetworkResponse.class, + description = "the ID of the Network to list the parameter value for corresponding network", + since = "4.18.0") + private Long networkId; + // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// @@ -159,6 +167,10 @@ public Integer getPageSize() { return super.getPageSize(); } + public Long getNetworkId() { + return networkId; + } + @Override public Long getPageSizeVal() { Long defaultPageSize = 500L; @@ -200,6 +212,9 @@ private void setScope(ConfigurationResponse cfgResponse) { if (getImageStoreId() != null){ cfgResponse.setScope("imagestore"); } + if (getNetworkId() != null) { + cfgResponse.setScope("network"); + } } @Override diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ResetCfgCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ResetCfgCmd.java index f114b263b634..b31d7ff8e652 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ResetCfgCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/ResetCfgCmd.java @@ -30,6 +30,7 @@ import org.apache.cloudstack.api.response.ClusterResponse; import org.apache.cloudstack.api.response.ConfigurationResponse; import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.config.Configuration; @@ -84,6 +85,13 @@ public class ResetCfgCmd extends BaseCmd { description = "the ID of the Image Store to reset the parameter value for corresponding image store") private Long imageStoreId; + @Parameter(name = ApiConstants.NETWORK_ID, + type = CommandType.UUID, + entityType = NetworkResponse.class, + description = "the ID of the Network to reset the parameter value for corresponding network", + since = "4.18.0") + private Long networkId; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -116,6 +124,10 @@ public Long getImageStoreId() { return imageStoreId; } + public Long getNetworkId() { + return networkId; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -149,6 +161,9 @@ public void execute() { if (getImageStoreId() != null) { response.setScope(ConfigKey.Scope.ImageStore.name()); } + if (getNetworkId() != null) { + response.setScope(ConfigKey.Scope.Network.name()); + } response.setValue(cfg.second()); this.setResponseObject(response); } else { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java index dbf478df7012..eebceb981b15 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java @@ -30,6 +30,7 @@ import org.apache.cloudstack.api.response.ClusterResponse; import org.apache.cloudstack.api.response.ConfigurationResponse; import org.apache.cloudstack.api.response.ImageStoreResponse; +import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.config.Configuration; @@ -88,6 +89,13 @@ public class UpdateCfgCmd extends BaseCmd { validations = ApiArgValidator.PositiveNumber) private Long imageStoreId; + @Parameter(name = ApiConstants.NETWORK_ID, + type = CommandType.UUID, + entityType = NetworkResponse.class, + description = "the ID of the Network to update the parameter value for corresponding network", + since = "4.18.0") + private Long networkId; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -128,6 +136,10 @@ public Long getImageStoreId() { return imageStoreId; } + public Long getNetworkId() { + return networkId; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -193,6 +205,9 @@ public ConfigurationResponse setResponseScopes(ConfigurationResponse response) { if (getDomainId() != null) { response.setScope("domain"); } + if (getNetworkId() != null) { + response.setScope("network"); + } return response; } } diff --git a/engine/schema/src/main/java/com/cloud/network/dao/NetworkDetailsDao.java b/engine/schema/src/main/java/com/cloud/network/dao/NetworkDetailsDao.java index 8d6dbc7bf846..45d84cc583d1 100644 --- a/engine/schema/src/main/java/com/cloud/network/dao/NetworkDetailsDao.java +++ b/engine/schema/src/main/java/com/cloud/network/dao/NetworkDetailsDao.java @@ -16,10 +16,24 @@ // under the License. package com.cloud.network.dao; +import java.util.Map; +import java.util.List; + import org.apache.cloudstack.resourcedetail.ResourceDetailsDao; import com.cloud.utils.db.GenericDao; public interface NetworkDetailsDao extends GenericDao, ResourceDetailsDao { + boolean isNetworkUsageHidden(long networkId); + + void persist(long networkId, Map details); + + NetworkDetailVO findDetail(long networkId, String name); + + List listDetailsByName(String name); + + void deleteDetails(long networkId); + + void update(long networkId, Map details); } diff --git a/engine/schema/src/main/java/com/cloud/network/dao/NetworkDetailsDaoImpl.java b/engine/schema/src/main/java/com/cloud/network/dao/NetworkDetailsDaoImpl.java index d036b1319008..d7e5da18c4c2 100644 --- a/engine/schema/src/main/java/com/cloud/network/dao/NetworkDetailsDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/network/dao/NetworkDetailsDaoImpl.java @@ -21,10 +21,31 @@ import org.apache.cloudstack.resourcedetail.ResourceDetailsDaoBase; +import java.util.List; +import java.util.Map; + +import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.cloudstack.framework.config.ConfigKey.Scope; +import org.apache.cloudstack.framework.config.ScopedConfigStorage; + +import com.cloud.utils.db.DB; +import com.cloud.utils.db.QueryBuilder; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.TransactionLegacy; +import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.network.Network; @Component -public class NetworkDetailsDaoImpl extends ResourceDetailsDaoBase implements NetworkDetailsDao { +@DB +public class NetworkDetailsDaoImpl extends ResourceDetailsDaoBase implements NetworkDetailsDao, ScopedConfigStorage { + protected final SearchBuilder networkSearch; + + protected NetworkDetailsDaoImpl() { + networkSearch = createSearchBuilder(); + networkSearch.and("networkId", networkSearch.entity().getResourceId(), Op.EQ); + networkSearch.done(); + } @Override public void addDetail(long resourceId, String key, String value, boolean display) { @@ -36,4 +57,62 @@ public boolean isNetworkUsageHidden(long networkId) { NetworkDetailVO networkDetail = findDetail(networkId, Network.hideIpAddressUsage); return networkDetail != null && "true".equals(networkDetail.getValue()); } + + @Override + public void persist(long networkId, Map details) { + try(TransactionLegacy txn = TransactionLegacy.currentTxn()) { + txn.start(); + SearchCriteria sc = networkSearch.create(); + sc.setParameters("networkId", networkId); + expunge(sc); + for (Map.Entry detail : details.entrySet()) { + NetworkDetailVO vo = new NetworkDetailVO(networkId, detail.getKey(), detail.getValue(), true); + persist(vo); + } + txn.commit(); + } + } + + @Override + public NetworkDetailVO findDetail(long networkId, String name) { + QueryBuilder sc = QueryBuilder.create(NetworkDetailVO.class); + sc.and(sc.entity().getResourceId(), Op.EQ, networkId); + sc.and(sc.entity().getName(), Op.EQ, name); + return sc.find(); + } + + @Override + public List listDetailsByName(String name) { + QueryBuilder sc = QueryBuilder.create(NetworkDetailVO.class); + sc.and(sc.entity().getName(), Op.EQ, name); + return sc.list(); + } + + @Override + public void deleteDetails(long networkId) { + SearchCriteria sc = networkSearch.create(); + sc.setParameters("networkId", networkId); + List results = search(sc, null); + for (NetworkDetailVO result : results) { + remove(result.getId()); + } + } + + @Override + public void update(long networkId, Map details) { + Map oldDetails = listDetailsKeyPairs(networkId); + oldDetails.putAll(details); + persist(networkId, oldDetails); + } + + @Override + public Scope getScope() { + return ConfigKey.Scope.Network; + } + + @Override + public String getConfigValue(long id, ConfigKey key) { + NetworkDetailVO vo = findDetail(id, key.key()); + return vo == null ? null : vo.getValue(); + } } diff --git a/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java b/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java index df93f78fa833..2457775047f4 100644 --- a/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java +++ b/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java @@ -37,7 +37,7 @@ public class ConfigKey { public static final String CATEGORY_NETWORK = "Network"; public enum Scope { - Global, Zone, Cluster, StoragePool, Account, ManagementServer, ImageStore, Domain + Global, Zone, Cluster, StoragePool, Account, ManagementServer, ImageStore, Domain, Network } public enum Kind { diff --git a/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java b/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java index 6884043cae28..aff67298f75a 100644 --- a/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java +++ b/framework/config/src/main/java/org/apache/cloudstack/framework/config/impl/ConfigDepotImpl.java @@ -98,14 +98,15 @@ public ConfigDepotImpl() { * This map must contain all ConfigKey.Scope values, except the ConfigKey.Scope.Global. */ protected void createEmptyScopeLevelMappings() { - _scopeLevelConfigsMap = new HashMap>>(); - _scopeLevelConfigsMap.put(ConfigKey.Scope.Zone, new HashSet>()); - _scopeLevelConfigsMap.put(ConfigKey.Scope.Cluster, new HashSet>()); - _scopeLevelConfigsMap.put(ConfigKey.Scope.StoragePool, new HashSet>()); - _scopeLevelConfigsMap.put(ConfigKey.Scope.Account, new HashSet>()); - _scopeLevelConfigsMap.put(ConfigKey.Scope.ImageStore, new HashSet>()); - _scopeLevelConfigsMap.put(ConfigKey.Scope.Domain, new HashSet>()); - _scopeLevelConfigsMap.put(ConfigKey.Scope.ManagementServer, new HashSet>()); + _scopeLevelConfigsMap = new HashMap<>(); + _scopeLevelConfigsMap.put(ConfigKey.Scope.Zone, new HashSet<>()); + _scopeLevelConfigsMap.put(ConfigKey.Scope.Cluster, new HashSet<>()); + _scopeLevelConfigsMap.put(ConfigKey.Scope.StoragePool, new HashSet<>()); + _scopeLevelConfigsMap.put(ConfigKey.Scope.Account, new HashSet<>()); + _scopeLevelConfigsMap.put(ConfigKey.Scope.ImageStore, new HashSet<>()); + _scopeLevelConfigsMap.put(ConfigKey.Scope.Domain, new HashSet<>()); + _scopeLevelConfigsMap.put(ConfigKey.Scope.ManagementServer, new HashSet<>()); + _scopeLevelConfigsMap.put(ConfigKey.Scope.Network, new HashSet<>()); } @Override diff --git a/server/src/main/java/com/cloud/api/ApiDBUtils.java b/server/src/main/java/com/cloud/api/ApiDBUtils.java index 46af53d68bf8..e66bebfb5391 100644 --- a/server/src/main/java/com/cloud/api/ApiDBUtils.java +++ b/server/src/main/java/com/cloud/api/ApiDBUtils.java @@ -222,6 +222,7 @@ import com.cloud.network.dao.LoadBalancerDao; import com.cloud.network.dao.LoadBalancerVO; import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkDetailsDao; import com.cloud.network.dao.NetworkDomainDao; import com.cloud.network.dao.NetworkDomainVO; import com.cloud.network.dao.NetworkRuleConfigDao; @@ -426,6 +427,7 @@ public class ApiDBUtils { static DomainDetailsDao s_domainDetailsDao; static AccountDetailsDao s_accountDetailsDao; static NetworkDomainDao s_networkDomainDao; + static NetworkDetailsDao s_networkDetailsDao; static HighAvailabilityManager s_haMgr; static VpcManager s_vpcMgr; static TaggedResourceService s_taggedResourceService; @@ -626,6 +628,8 @@ public class ApiDBUtils { @Inject private NetworkDomainDao networkDomainDao; @Inject + private NetworkDetailsDao networkDetailsDao; + @Inject private HighAvailabilityManager haMgr; @Inject private VpcManager vpcMgr; @@ -826,6 +830,7 @@ void init() { s_domainDetailsDao = domainDetailsDao; s_accountDetailsDao = accountDetailsDao; s_networkDomainDao = networkDomainDao; + s_networkDetailsDao = networkDetailsDao; s_haMgr = haMgr; s_vpcMgr = vpcMgr; s_taggedResourceService = taggedResourceService; @@ -1510,6 +1515,11 @@ public static Map getAccountDetails(long accountId) { return details.isEmpty() ? null : details; } + public static Map getNetworkDetails(long networkId) { + Map details = s_networkDetailsDao.listDetailsKeyPairs(networkId); + return details.isEmpty() ? null : details; + } + public static Map> listNetworkOfferingServices(long networkOfferingId) { return s_networkModel.getNetworkOfferingServiceProvidersMap(networkOfferingId); } diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index b665257bb2ac..799a7d6c25f3 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -2711,6 +2711,7 @@ public NetworkResponse createNetworkResponse(ResponseView view, Network network) } response.setBytesReceived(bytesReceived); response.setBytesSent(bytesSent); + response.setDetails(ApiDBUtils.getNetworkDetails(network.getId())); if (networkOfferingDao.isIpv6Supported(network.getNetworkOfferingId())) { response.setInternetProtocol(networkOfferingDao.getNetworkOfferingInternetProtocol(network.getNetworkOfferingId(), NetUtils.InternetProtocol.IPv4).toString()); diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index a5f119000809..d8958252794b 100644 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -226,6 +226,8 @@ import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.Ipv6GuestPrefixSubnetNetworkMapDao; import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkDetailsDao; +import com.cloud.network.dao.NetworkDetailVO; import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao; @@ -418,6 +420,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Inject DomainDetailsDao _domainDetailsDao; @Inject + NetworkDetailsDao _networkDetailsDao; + @Inject PrimaryDataStoreDao _storagePoolDao; @Inject NicSecondaryIpDao _nicSecondaryIpDao; @@ -785,6 +789,21 @@ public String updateConfiguration(final long userId, final String name, final St } break; + case Network: + final NetworkVO network = _networkDao.findById(resourceId); + if (network == null) { + throw new InvalidParameterValueException(String.format("Unable to find network by ID [%s].", resourceId)); + } + NetworkDetailVO networkDetailVO = _networkDetailsDao.findDetail(resourceId, name); + if (networkDetailVO == null) { + networkDetailVO = new NetworkDetailVO(resourceId, name, value, true); + _networkDetailsDao.persist(networkDetailVO); + } else { + networkDetailVO.setValue(value); + _networkDetailsDao.update(networkDetailVO.getId(), networkDetailVO); + } + break; + default: throw new InvalidParameterValueException("Scope provided is invalid"); } @@ -916,6 +935,8 @@ public Configuration updateConfiguration(final UpdateCfgCmd cmd) throws InvalidP final Long imageStoreId = cmd.getImageStoreId(); Long accountId = cmd.getAccountId(); Long domainId = cmd.getDomainId(); + final Long networkId = cmd.getNetworkId(); + CallContext.current().setEventDetails(" Name: " + name + " New Value: " + (name.toLowerCase().contains("password") ? "*****" : value == null ? "" : value)); // check if config value exists final ConfigurationVO config = _configDao.findByName(name); String category = null; @@ -987,6 +1008,11 @@ public Configuration updateConfiguration(final UpdateCfgCmd cmd) throws InvalidP id = imageStoreId; paramCountCheck++; } + if (networkId != null) { + scope = ConfigKey.Scope.Network.toString(); + id = networkId; + paramCountCheck++; + } if (paramCountCheck > 1) { throw new InvalidParameterValueException("cannot handle multiple IDs, provide only one ID corresponding to the scope"); @@ -1040,6 +1066,8 @@ public Pair resetConfiguration(final ResetCfgCmd cmd) thr final Long accountId = cmd.getAccountId(); final Long domainId = cmd.getDomainId(); final Long imageStoreId = cmd.getImageStoreId(); + final Long networkId = cmd.getNetworkId(); + ConfigKey configKey = null; Optional optionalValue; String defaultValue; @@ -1073,6 +1101,7 @@ public Pair resetConfiguration(final ResetCfgCmd cmd) thr scopeMap.put(ConfigKey.Scope.Account.toString(), accountId); scopeMap.put(ConfigKey.Scope.StoragePool.toString(), storagepoolId); scopeMap.put(ConfigKey.Scope.ImageStore.toString(), imageStoreId); + scopeMap.put(ConfigKey.Scope.Network.toString(), networkId); ParamCountPair paramCountPair = getParamCount(scopeMap); id = paramCountPair.getId(); @@ -1164,6 +1193,21 @@ public Pair resetConfiguration(final ResetCfgCmd cmd) thr newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; break; + case Network: + final NetworkVO network = _networkDao.findById(id); + if (network == null) { + throw new InvalidParameterValueException(String.format("Unable to find network by ID [%s].", id)); + } + + NetworkDetailVO networkDetailVO = _networkDetailsDao.findDetail(id, name); + if (networkDetailVO != null) { + _networkDetailsDao.remove(networkDetailVO.getId()); + } + + optionalValue = Optional.ofNullable(configKey.valueIn(id)); + newValue = optionalValue.isPresent() ? optionalValue.get().toString() : defaultValue; + break; + default: if (!_configDao.update(name, category, defaultValue)) { logger.error("Failed to reset configuration option, name: " + name + ", defaultValue:" + defaultValue); diff --git a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManager.java b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManager.java index f77081aa96cc..72c4e485c658 100644 --- a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManager.java +++ b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManager.java @@ -45,6 +45,7 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA String SetServiceMonitorCK = "network.router.EnableServiceMonitoring"; String RouterAlertsCheckIntervalCK = "router.alerts.check.interval"; String VirtualRouterServiceOfferingCK = "router.service.offering"; + String NetworkVirtualRouterServiceOfferingCK = "network.router.service.offering"; String RouterHealthChecksConfigRefreshIntervalCK = "router.health.checks.config.refresh.interval"; String RouterHealthChecksResultFetchIntervalCK = "router.health.checks.results.fetch.interval"; @@ -78,6 +79,8 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA ConfigKey VirtualRouterServiceOffering = new ConfigKey<>(String.class, VirtualRouterServiceOfferingCK, "Advanced", "", "Uuid of the service offering used by virtual routers; if NULL - system offering will be used", true, ConfigKey.Scope.Account, null); + ConfigKey NetworkVirtualRouterServiceOffering = new ConfigKey(String.class, NetworkVirtualRouterServiceOfferingCK, "Advanced", "", + "Uuid of the service offering used by virtual routers of this network; if NULL - account/system offering will be used", true, ConfigKey.Scope.Network, null); // Health checks ConfigKey RouterHealthChecksEnabled = new ConfigKey<>(Boolean.class, "router.health.checks.enabled", "Advanced", "true", diff --git a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index b9f1350615b8..33d9a176ffd0 100644 --- a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -3333,6 +3333,7 @@ public ConfigKey[] getConfigKeys() { RouterHealthChecksMaxMemoryUsageThreshold, ExposeDnsAndBootpServer, RouterLogrotateFrequency, + NetworkVirtualRouterServiceOffering, RemoveControlIpOnStop }; } diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index 15a52d3f7509..bd3c37e348a4 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -2192,6 +2192,8 @@ public Pair, Integer> searchForConfigurations(fina final String groupName = cmd.getGroupName(); final String subGroupName = cmd.getSubGroupName(); final String parentName = cmd.getParentName(); + final Long networkId = cmd.getNetworkId(); + String scope = null; Long id = null; int paramCountCheck = 0; @@ -2230,6 +2232,11 @@ public Pair, Integer> searchForConfigurations(fina id = domainId; paramCountCheck++; } + if (networkId != null) { + scope = ConfigKey.Scope.Network.toString(); + id = networkId; + paramCountCheck++; + } if (storagepoolId != null) { scope = ConfigKey.Scope.StoragePool.toString(); id = storagepoolId; diff --git a/server/src/main/java/org/apache/cloudstack/network/router/deployment/RouterDeploymentDefinition.java b/server/src/main/java/org/apache/cloudstack/network/router/deployment/RouterDeploymentDefinition.java index 2dea5a4223fa..08dd791990a1 100644 --- a/server/src/main/java/org/apache/cloudstack/network/router/deployment/RouterDeploymentDefinition.java +++ b/server/src/main/java/org/apache/cloudstack/network/router/deployment/RouterDeploymentDefinition.java @@ -435,8 +435,25 @@ private void verifyServiceOfferingByUuid(String offeringUuid) { } } + protected void findNetworkServiceOfferingId() { + String networkRouterOffering = VirtualNetworkApplianceManager.NetworkVirtualRouterServiceOffering.valueIn(guestNetwork.getId()); + if (networkRouterOffering != null) { + ServiceOfferingVO serviceOffering = serviceOfferingDao.findByUuid(networkRouterOffering); + if (serviceOffering != null && "domainrouter".equals(serviceOffering.getVmType())) { + boolean isLocalStorage = ConfigurationManagerImpl.SystemVMUseLocalStorage.valueIn(dest.getDataCenter().getId()); + DiskOfferingVO diskOffering = diskOfferingDao.findById(serviceOffering.getDiskOfferingId()); + if (isLocalStorage == diskOffering.isUseLocalStorage()) { + serviceOfferingId = serviceOffering.getId(); + } + } + } + } + protected void findServiceOfferingId() { serviceOfferingId = networkOfferingDao.findById(guestNetwork.getNetworkOfferingId()).getServiceOfferingId(); + if (serviceOfferingId == null) { + findNetworkServiceOfferingId(); + } if (serviceOfferingId == null) { findAccountServiceOfferingId(guestNetwork.getAccountId()); } diff --git a/ui/src/components/view/SettingsTab.vue b/ui/src/components/view/SettingsTab.vue index cddbe56b83a9..2e8b20f34132 100644 --- a/ui/src/components/view/SettingsTab.vue +++ b/ui/src/components/view/SettingsTab.vue @@ -135,6 +135,9 @@ export default { case 'imagestore': this.scopeKey = 'imagestoreuuid' break + case 'guestnetwork': + this.scopeKey = 'networkid' + break default: this.scopeKey = '' } diff --git a/ui/src/config/section/network.js b/ui/src/config/section/network.js index 3d5241feb590..c53174b4a141 100644 --- a/ui/src/config/section/network.js +++ b/ui/src/config/section/network.js @@ -104,6 +104,11 @@ export default { component: shallowRef(defineAsyncComponent(() => import('@/views/network/NetworkPermissions.vue'))), show: (record, route, user) => { return 'listNetworkPermissions' in store.getters.apis && record.acltype === 'Account' && !('vpcid' in record) && (['Admin', 'DomainAdmin'].includes(user.roletype) || record.account === user.account) && !record.projectid } }, + { + name: 'settings', + component: shallowRef(defineAsyncComponent(() => import('@/components/view/SettingsTab.vue'))), + show: () => { return 'listConfigurations' in store.getters.apis } + }, { name: 'events', resourceType: 'Network',