From 0e87040eb29ea6385df7eb8b86d71ac334ceb7b4 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Wed, 19 Jun 2019 10:25:59 +0530 Subject: [PATCH] network: allow ability to specify if network's ipaddress usage need to be hidden (#3235) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Admins don’t want to charge for IP address usage on certain (shared) networks. Root Cause: There is no flag or detail for admins to provide using UI or API when creating networks to specify if they want IP address usage of the network hidden. Solution: A new boolean hideipaddressusage flag is added to the createNetwork API and a checkbox in the ‘Add guest network’ UI for the root admins to specify if they want the shared network’s IP address usage to be hidden in the listUsageRecords API response. The provided flag is saved as the ‘hideIpAddressUsage’ detail in the cloud.network_details table for the network. For existing (shared) networks, root admins can also specify the same boolean API parameter hideipaddressusage with the updateNetwork API request to configure the behaviour for an existing network. When the detail/flag is true, the IP address usage for the (shared) network is not exported in the listUsageRecords API response. The listNetworks API response will include the details of a network for root admin only. (note usage is still recorded in the usage database but not return by the listUsageRecords API) The API flag works for any kind of network via the API, but the checkbox is only shown while creating shared networks in the UI. Signed-off-by: Rohit Yadav --- .../main/java/com/cloud/network/Network.java | 7 +- .../com/cloud/network/NetworkService.java | 4 +- .../apache/cloudstack/api/ApiConstants.java | 1 + .../network/CreateNetworkCmdByAdmin.java | 10 + .../network/UpdateNetworkCmdByAdmin.java | 24 +- .../admin/usage/ListUsageRecordsCmd.java | 11 +- .../user/network/UpdateNetworkCmd.java | 13 +- .../api/response/NetworkResponse.java | 11 +- .../cloud/network/dao/NetworkDetailVO.java | 8 + .../java/com/cloud/api/ApiResponseHelper.java | 393 +++++++++--------- .../com/cloud/network/NetworkServiceImpl.java | 40 +- .../com/cloud/vpc/MockNetworkManagerImpl.java | 12 +- ui/l10n/en.js | 1 + ui/scripts/docs.js | 4 + ui/scripts/sharedFunctions.js | 13 + 15 files changed, 323 insertions(+), 229 deletions(-) diff --git a/api/src/main/java/com/cloud/network/Network.java b/api/src/main/java/com/cloud/network/Network.java index 2aa241d7183..2cabd021418 100644 --- a/api/src/main/java/com/cloud/network/Network.java +++ b/api/src/main/java/com/cloud/network/Network.java @@ -40,13 +40,14 @@ import com.cloud.utils.fsm.StateObject; */ public interface Network extends ControlledEntity, StateObject, InternalIdentity, Identity, Serializable, Displayable { - public enum GuestType { + enum GuestType { Shared, Isolated, L2 } - public String updatingInSequence ="updatingInSequence"; + String updatingInSequence = "updatingInSequence"; + String hideIpAddressUsage = "hideIpAddressUsage"; - public static class Service { + class Service { private static List supportedServices = new ArrayList(); public static final Service Vpn = new Service("Vpn", Capability.SupportedVpnProtocols, Capability.VpnTypes); diff --git a/api/src/main/java/com/cloud/network/NetworkService.java b/api/src/main/java/com/cloud/network/NetworkService.java index aa33defba93..b228c59e52f 100644 --- a/api/src/main/java/com/cloud/network/NetworkService.java +++ b/api/src/main/java/com/cloud/network/NetworkService.java @@ -26,6 +26,7 @@ import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementors import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; +import org.apache.cloudstack.api.command.user.network.UpdateNetworkCmd; import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; import org.apache.cloudstack.api.response.AcquirePodIpCmdResponse; @@ -81,8 +82,7 @@ public interface NetworkService { IpAddress getIp(long id); - Network updateGuestNetwork(long networkId, String name, String displayText, Account callerAccount, User callerUser, String domainSuffix, Long networkOfferingId, - Boolean changeCidr, String guestVmCidr, Boolean displayNetwork, String newUUID, boolean updateInSequence, boolean forced); + Network updateGuestNetwork(final UpdateNetworkCmd cmd); /** * Migrate a network from one physical network to another physical network diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index 0d8cb03cd3e..99efafc5cbd 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -150,6 +150,7 @@ public class ApiConstants { public static final String HA_PROVIDER = "haprovider"; public static final String HA_STATE = "hastate"; public static final String HEALTH = "health"; + public static final String HIDE_IP_ADDRESS_USAGE = "hideipaddressusage"; public static final String HOST_ID = "hostid"; public static final String HOST_NAME = "hostname"; public static final String HYPERVISOR = "hypervisor"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkCmdByAdmin.java index 2dfd749ddca..7a609408595 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkCmdByAdmin.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/CreateNetworkCmdByAdmin.java @@ -43,6 +43,9 @@ public class CreateNetworkCmdByAdmin extends CreateNetworkCmd { @Parameter(name=ApiConstants.BYPASS_VLAN_OVERLAP_CHECK, type=CommandType.BOOLEAN, description="when true bypasses VLAN id/range overlap check during network creation for shared and L2 networks") private Boolean bypassVlanOverlapCheck; + @Parameter(name=ApiConstants.HIDE_IP_ADDRESS_USAGE, type=CommandType.BOOLEAN, description="when true ip address usage for the network will not be exported by the listUsageRecords API") + private Boolean hideIpAddressUsage; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -58,6 +61,13 @@ public class CreateNetworkCmdByAdmin extends CreateNetworkCmd { return false; } + public Boolean getHideIpAddressUsage() { + if (hideIpAddressUsage != null) { + return hideIpAddressUsage; + } + return false; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateNetworkCmdByAdmin.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateNetworkCmdByAdmin.java index 388348c592c..487ed144da7 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateNetworkCmdByAdmin.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/network/UpdateNetworkCmdByAdmin.java @@ -16,42 +16,44 @@ // under the License. package org.apache.cloudstack.api.command.admin.network; -import org.apache.log4j.Logger; - import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.user.network.UpdateNetworkCmd; import org.apache.cloudstack.api.response.NetworkResponse; -import org.apache.cloudstack.context.CallContext; +import org.apache.log4j.Logger; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.Network; -import com.cloud.user.Account; -import com.cloud.user.User; @APICommand(name = "updateNetwork", description = "Updates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Full, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateNetworkCmdByAdmin extends UpdateNetworkCmd { public static final Logger s_logger = Logger.getLogger(UpdateNetworkCmdByAdmin.class.getName()); + @Parameter(name= ApiConstants.HIDE_IP_ADDRESS_USAGE, type=CommandType.BOOLEAN, description="when true ip address usage for the network will not be exported by the listUsageRecords API") + private Boolean hideIpAddressUsage; + + public Boolean getHideIpAddressUsage() { + if (hideIpAddressUsage == null) { + return false; + } + return hideIpAddressUsage; + } @Override public void execute() throws InsufficientCapacityException, ConcurrentOperationException{ - User callerUser = _accountService.getActiveUser(CallContext.current().getCallingUserId()); - Account callerAccount = _accountService.getActiveAccountById(callerUser.getAccountId()); Network network = _networkService.getNetwork(id); if (network == null) { throw new InvalidParameterValueException("Couldn't find network by id"); } - Network result = _networkService.updateGuestNetwork(getId(), getNetworkName(), getDisplayText(), callerAccount, - callerUser, getNetworkDomain(), getNetworkOfferingId(), getChangeCidr(), getGuestVmCidr(), getDisplayNetwork(), getCustomId(), getUpdateInSequence(),getForced()); - - + Network result = _networkService.updateGuestNetwork(this); if (result != null) { NetworkResponse response = _responseGenerator.createNetworkResponse(ResponseView.Full, result); response.setResponseName(getCommandName()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListUsageRecordsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListUsageRecordsCmd.java index 605439fde0e..2698c819c85 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListUsageRecordsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/usage/ListUsageRecordsCmd.java @@ -22,7 +22,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import com.cloud.utils.Pair; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; @@ -36,6 +35,8 @@ import org.apache.cloudstack.api.response.ResourceTagResponse; import org.apache.cloudstack.api.response.UsageRecordResponse; import org.apache.cloudstack.usage.Usage; +import com.cloud.utils.Pair; + @APICommand(name = ListUsageRecordsCmd.APINAME, description = "Lists usage records for accounts", responseObject = UsageRecordResponse.class, @@ -168,11 +169,13 @@ public class ListUsageRecordsCmd extends BaseListCmd { } for (Usage usageRecord : usageRecords.first()) { UsageRecordResponse usageResponse = _responseGenerator.createUsageResponse(usageRecord, resourceTagResponseMap); - usageResponse.setObjectName("usagerecord"); - usageResponses.add(usageResponse); + if (usageResponse != null) { + usageResponse.setObjectName("usagerecord"); + usageResponses.add(usageResponse); + } } - response.setResponses(usageResponses, usageRecords.second()); + response.setResponses(usageResponses, usageResponses.size()); } response.setResponseName(getCommandName()); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java index c313f369b0e..3e93e5edd3f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java @@ -16,8 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.network; -import org.apache.log4j.Logger; - import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -31,7 +29,7 @@ import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.NetworkOfferingResponse; import org.apache.cloudstack.api.response.NetworkResponse; -import org.apache.cloudstack.context.CallContext; +import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.exception.ConcurrentOperationException; @@ -39,8 +37,6 @@ import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.Network; import com.cloud.offering.NetworkOffering; -import com.cloud.user.Account; -import com.cloud.user.User; @APICommand(name = "updateNetwork", description = "Updates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) @@ -159,17 +155,12 @@ public class UpdateNetworkCmd extends BaseAsyncCustomIdCmd { @Override public void execute() throws InsufficientCapacityException, ConcurrentOperationException { - User callerUser = _accountService.getActiveUser(CallContext.current().getCallingUserId()); - Account callerAccount = _accountService.getActiveAccountById(callerUser.getAccountId()); Network network = _networkService.getNetwork(id); if (network == null) { throw new InvalidParameterValueException("Couldn't find network by ID"); } - Network result = - _networkService.updateGuestNetwork(getId(), getNetworkName(), getDisplayText(), callerAccount, callerUser, getNetworkDomain(), getNetworkOfferingId(), - getChangeCidr(), getGuestVmCidr(), getDisplayNetwork(), getCustomId(), getUpdateInSequence(), getForced()); - + Network result = _networkService.updateGuestNetwork(this); if (result != null) { NetworkResponse response = _responseGenerator.createNetworkResponse(ResponseView.Restricted, result); response.setResponseName(getCommandName()); diff --git a/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java index 8d0f725500b..84a5aaa8b19 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/NetworkResponse.java @@ -17,8 +17,9 @@ package org.apache.cloudstack.api.response; import java.util.List; - +import java.util.Map; import java.util.Set; + import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; @@ -201,6 +202,10 @@ public class NetworkResponse extends BaseResponse implements ControlledEntityRes @Param(description = "the list of resource tags associated with network", responseObject = ResourceTagResponse.class) private List tags; + @SerializedName(ApiConstants.DETAILS) + @Param(description = "the details of the network") + private Map details; + @SerializedName(ApiConstants.IP6_GATEWAY) @Param(description = "the gateway of IPv6 network") private String ip6Gateway; @@ -414,6 +419,10 @@ public class NetworkResponse extends BaseResponse implements ControlledEntityRes this.tags = tags; } + public void setDetails(Map details) { + this.details = details; + } + public void setIp6Gateway(String ip6Gateway) { this.ip6Gateway = ip6Gateway; } diff --git a/engine/schema/src/main/java/com/cloud/network/dao/NetworkDetailVO.java b/engine/schema/src/main/java/com/cloud/network/dao/NetworkDetailVO.java index e6cad17210d..23c85f7f044 100644 --- a/engine/schema/src/main/java/com/cloud/network/dao/NetworkDetailVO.java +++ b/engine/schema/src/main/java/com/cloud/network/dao/NetworkDetailVO.java @@ -79,4 +79,12 @@ public class NetworkDetailVO implements ResourceDetail { public boolean isDisplay() { return display; } + + public void setValue(String value) { + this.value = value; + } + + public void setDisplay(boolean display) { + this.display = display; + } } diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index c10744d2e42..9deaa962f2b 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -16,173 +16,21 @@ // under the License. package com.cloud.api; -import org.apache.cloudstack.management.ManagementServerHost; -import com.cloud.utils.crypt.DBEncryptionUtil; -import com.cloud.tags.dao.ResourceTagDao; -import com.cloud.agent.api.VgpuTypesInfo; -import com.cloud.api.query.ViewResponseHelper; -import com.cloud.api.query.vo.AccountJoinVO; -import com.cloud.api.query.vo.AsyncJobJoinVO; -import com.cloud.api.query.vo.ControlledViewEntity; -import com.cloud.api.query.vo.DataCenterJoinVO; -import com.cloud.api.query.vo.DiskOfferingJoinVO; -import com.cloud.api.query.vo.DomainRouterJoinVO; -import com.cloud.api.query.vo.EventJoinVO; -import com.cloud.api.query.vo.HostJoinVO; -import com.cloud.api.query.vo.ImageStoreJoinVO; -import com.cloud.api.query.vo.InstanceGroupJoinVO; -import com.cloud.api.query.vo.ProjectAccountJoinVO; -import com.cloud.api.query.vo.ProjectInvitationJoinVO; -import com.cloud.api.query.vo.ProjectJoinVO; -import com.cloud.api.query.vo.ResourceTagJoinVO; -import com.cloud.api.query.vo.SecurityGroupJoinVO; -import com.cloud.api.query.vo.ServiceOfferingJoinVO; -import com.cloud.api.query.vo.StoragePoolJoinVO; -import com.cloud.api.query.vo.TemplateJoinVO; -import com.cloud.api.query.vo.UserAccountJoinVO; -import com.cloud.api.query.vo.UserVmJoinVO; -import com.cloud.api.query.vo.VolumeJoinVO; -import com.cloud.api.response.ApiResponseSerializer; -import com.cloud.capacity.Capacity; -import com.cloud.capacity.CapacityVO; -import com.cloud.capacity.dao.CapacityDaoImpl.SummedCapacity; -import com.cloud.configuration.ConfigurationManager; -import com.cloud.configuration.Resource.ResourceOwnerType; -import com.cloud.configuration.Resource.ResourceType; -import com.cloud.configuration.ResourceCount; -import com.cloud.configuration.ResourceLimit; -import com.cloud.dc.ClusterDetailsDao; -import com.cloud.dc.ClusterVO; -import com.cloud.dc.DataCenter; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.HostPodVO; -import com.cloud.dc.Pod; -import com.cloud.dc.StorageNetworkIpRange; -import com.cloud.dc.Vlan; -import com.cloud.dc.Vlan.VlanType; -import com.cloud.dc.VlanVO; -import com.cloud.domain.Domain; -import com.cloud.domain.DomainVO; -import com.cloud.event.Event; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.PermissionDeniedException; -import com.cloud.gpu.GPU; -import com.cloud.host.Host; -import com.cloud.host.HostVO; -import com.cloud.hypervisor.HypervisorCapabilities; -import com.cloud.network.GuestVlan; -import com.cloud.network.IpAddress; -import com.cloud.network.Network; -import com.cloud.network.Network.Capability; -import com.cloud.network.Network.Provider; -import com.cloud.network.Network.Service; -import com.cloud.network.NetworkModel; -import com.cloud.network.NetworkProfile; -import com.cloud.network.Networks.BroadcastDomainType; -import com.cloud.network.Networks.IsolationType; -import com.cloud.network.Networks.TrafficType; -import com.cloud.network.OvsProvider; -import com.cloud.network.PhysicalNetwork; -import com.cloud.network.PhysicalNetworkServiceProvider; -import com.cloud.network.PhysicalNetworkTrafficType; -import com.cloud.network.RemoteAccessVpn; -import com.cloud.network.Site2SiteCustomerGateway; -import com.cloud.network.Site2SiteVpnConnection; -import com.cloud.network.Site2SiteVpnGateway; -import com.cloud.network.VirtualRouterProvider; -import com.cloud.network.VpnUser; -import com.cloud.network.VpnUserVO; -import com.cloud.network.as.AutoScalePolicy; -import com.cloud.network.as.AutoScaleVmGroup; -import com.cloud.network.as.AutoScaleVmProfile; -import com.cloud.network.as.AutoScaleVmProfileVO; -import com.cloud.network.as.Condition; -import com.cloud.network.as.ConditionVO; -import com.cloud.network.as.Counter; -import com.cloud.network.dao.IPAddressDao; -import com.cloud.network.dao.IPAddressVO; -import com.cloud.network.dao.LoadBalancerVO; -import com.cloud.network.dao.NetworkVO; -import com.cloud.network.dao.PhysicalNetworkVO; -import com.cloud.network.router.VirtualRouter; -import com.cloud.network.rules.FirewallRule; -import com.cloud.network.rules.FirewallRuleVO; -import com.cloud.network.rules.HealthCheckPolicy; -import com.cloud.network.rules.LoadBalancer; -import com.cloud.network.rules.LoadBalancerContainer.Scheme; -import com.cloud.network.rules.PortForwardingRule; -import com.cloud.network.rules.PortForwardingRuleVO; -import com.cloud.network.rules.StaticNatRule; -import com.cloud.network.rules.StickinessPolicy; -import com.cloud.network.security.SecurityGroup; -import com.cloud.network.security.SecurityGroupVO; -import com.cloud.network.security.SecurityRule; -import com.cloud.network.security.SecurityRule.SecurityRuleType; -import com.cloud.network.vpc.NetworkACL; -import com.cloud.network.vpc.NetworkACLItem; -import com.cloud.network.vpc.PrivateGateway; -import com.cloud.network.vpc.StaticRoute; -import com.cloud.network.vpc.Vpc; -import com.cloud.network.vpc.VpcOffering; -import com.cloud.offering.DiskOffering; -import com.cloud.offering.NetworkOffering; -import com.cloud.offering.NetworkOffering.Detail; -import com.cloud.offering.ServiceOffering; -import com.cloud.offerings.NetworkOfferingVO; -import com.cloud.org.Cluster; -import com.cloud.projects.Project; -import com.cloud.projects.ProjectAccount; -import com.cloud.projects.ProjectInvitation; -import com.cloud.region.ha.GlobalLoadBalancerRule; -import com.cloud.server.ResourceTag; -import com.cloud.server.ResourceTag.ResourceObjectType; -import com.cloud.service.ServiceOfferingVO; -import com.cloud.storage.DataStoreRole; -import com.cloud.storage.DiskOfferingVO; -import com.cloud.storage.GuestOS; -import com.cloud.storage.GuestOSCategoryVO; -import com.cloud.storage.GuestOSHypervisor; -import com.cloud.storage.ImageStore; -import com.cloud.storage.Snapshot; -import com.cloud.storage.SnapshotVO; -import com.cloud.storage.StoragePool; -import com.cloud.storage.Upload; -import com.cloud.storage.UploadVO; -import com.cloud.storage.VMTemplateVO; -import com.cloud.storage.Volume; -import com.cloud.storage.VolumeVO; -import com.cloud.storage.dao.VolumeDao; -import com.cloud.storage.snapshot.SnapshotPolicy; -import com.cloud.storage.snapshot.SnapshotSchedule; -import com.cloud.template.VirtualMachineTemplate; -import com.cloud.user.Account; -import com.cloud.user.AccountManager; -import com.cloud.user.SSHKeyPair; -import com.cloud.user.User; -import com.cloud.user.UserAccount; -import com.cloud.uservm.UserVm; -import com.cloud.utils.Pair; -import com.cloud.utils.StringUtils; -import com.cloud.utils.db.EntityManager; -import com.cloud.utils.net.Dhcp; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.net.Ip; -import com.cloud.utils.net.NetUtils; -import com.cloud.vm.ConsoleProxyVO; -import com.cloud.vm.InstanceGroup; -import com.cloud.vm.Nic; -import com.cloud.vm.NicExtraDhcpOptionVO; -import com.cloud.vm.NicProfile; -import com.cloud.vm.NicSecondaryIp; -import com.cloud.vm.NicVO; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachine; -import com.cloud.vm.VirtualMachine.Type; -import com.cloud.vm.dao.NicExtraDhcpOptionDao; -import com.cloud.vm.dao.NicSecondaryIpVO; -import com.cloud.vm.snapshot.VMSnapshot; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; +import java.util.stream.Collectors; + +import javax.inject.Inject; + import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.affinity.AffinityGroup; @@ -300,6 +148,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.framework.jobs.AsyncJob; import org.apache.cloudstack.framework.jobs.AsyncJobManager; +import org.apache.cloudstack.management.ManagementServerHost; import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRule; import org.apache.cloudstack.region.PortableIp; import org.apache.cloudstack.region.PortableIpRange; @@ -314,19 +163,174 @@ import org.apache.cloudstack.usage.UsageTypes; import org.apache.commons.collections.CollectionUtils; import org.apache.log4j.Logger; -import javax.inject.Inject; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TimeZone; -import java.util.stream.Collectors; +import com.cloud.agent.api.VgpuTypesInfo; +import com.cloud.api.query.ViewResponseHelper; +import com.cloud.api.query.vo.AccountJoinVO; +import com.cloud.api.query.vo.AsyncJobJoinVO; +import com.cloud.api.query.vo.ControlledViewEntity; +import com.cloud.api.query.vo.DataCenterJoinVO; +import com.cloud.api.query.vo.DiskOfferingJoinVO; +import com.cloud.api.query.vo.DomainRouterJoinVO; +import com.cloud.api.query.vo.EventJoinVO; +import com.cloud.api.query.vo.HostJoinVO; +import com.cloud.api.query.vo.ImageStoreJoinVO; +import com.cloud.api.query.vo.InstanceGroupJoinVO; +import com.cloud.api.query.vo.ProjectAccountJoinVO; +import com.cloud.api.query.vo.ProjectInvitationJoinVO; +import com.cloud.api.query.vo.ProjectJoinVO; +import com.cloud.api.query.vo.ResourceTagJoinVO; +import com.cloud.api.query.vo.SecurityGroupJoinVO; +import com.cloud.api.query.vo.ServiceOfferingJoinVO; +import com.cloud.api.query.vo.StoragePoolJoinVO; +import com.cloud.api.query.vo.TemplateJoinVO; +import com.cloud.api.query.vo.UserAccountJoinVO; +import com.cloud.api.query.vo.UserVmJoinVO; +import com.cloud.api.query.vo.VolumeJoinVO; +import com.cloud.api.response.ApiResponseSerializer; +import com.cloud.capacity.Capacity; +import com.cloud.capacity.CapacityVO; +import com.cloud.capacity.dao.CapacityDaoImpl.SummedCapacity; +import com.cloud.configuration.ConfigurationManager; +import com.cloud.configuration.Resource.ResourceOwnerType; +import com.cloud.configuration.Resource.ResourceType; +import com.cloud.configuration.ResourceCount; +import com.cloud.configuration.ResourceLimit; +import com.cloud.dc.ClusterDetailsDao; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.DataCenter; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.HostPodVO; +import com.cloud.dc.Pod; +import com.cloud.dc.StorageNetworkIpRange; +import com.cloud.dc.Vlan; +import com.cloud.dc.Vlan.VlanType; +import com.cloud.dc.VlanVO; +import com.cloud.domain.Domain; +import com.cloud.domain.DomainVO; +import com.cloud.event.Event; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.gpu.GPU; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.hypervisor.HypervisorCapabilities; +import com.cloud.network.GuestVlan; +import com.cloud.network.IpAddress; +import com.cloud.network.Network; +import com.cloud.network.Network.Capability; +import com.cloud.network.Network.Provider; +import com.cloud.network.Network.Service; +import com.cloud.network.NetworkModel; +import com.cloud.network.NetworkProfile; +import com.cloud.network.Networks.BroadcastDomainType; +import com.cloud.network.Networks.IsolationType; +import com.cloud.network.Networks.TrafficType; +import com.cloud.network.OvsProvider; +import com.cloud.network.PhysicalNetwork; +import com.cloud.network.PhysicalNetworkServiceProvider; +import com.cloud.network.PhysicalNetworkTrafficType; +import com.cloud.network.RemoteAccessVpn; +import com.cloud.network.Site2SiteCustomerGateway; +import com.cloud.network.Site2SiteVpnConnection; +import com.cloud.network.Site2SiteVpnGateway; +import com.cloud.network.VirtualRouterProvider; +import com.cloud.network.VpnUser; +import com.cloud.network.VpnUserVO; +import com.cloud.network.as.AutoScalePolicy; +import com.cloud.network.as.AutoScaleVmGroup; +import com.cloud.network.as.AutoScaleVmProfile; +import com.cloud.network.as.AutoScaleVmProfileVO; +import com.cloud.network.as.Condition; +import com.cloud.network.as.ConditionVO; +import com.cloud.network.as.Counter; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.network.dao.IPAddressVO; +import com.cloud.network.dao.LoadBalancerVO; +import com.cloud.network.dao.NetworkDetailVO; +import com.cloud.network.dao.NetworkDetailsDao; +import com.cloud.network.dao.NetworkVO; +import com.cloud.network.dao.PhysicalNetworkVO; +import com.cloud.network.router.VirtualRouter; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.FirewallRuleVO; +import com.cloud.network.rules.HealthCheckPolicy; +import com.cloud.network.rules.LoadBalancer; +import com.cloud.network.rules.LoadBalancerContainer.Scheme; +import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.rules.PortForwardingRuleVO; +import com.cloud.network.rules.StaticNatRule; +import com.cloud.network.rules.StickinessPolicy; +import com.cloud.network.security.SecurityGroup; +import com.cloud.network.security.SecurityGroupVO; +import com.cloud.network.security.SecurityRule; +import com.cloud.network.security.SecurityRule.SecurityRuleType; +import com.cloud.network.vpc.NetworkACL; +import com.cloud.network.vpc.NetworkACLItem; +import com.cloud.network.vpc.PrivateGateway; +import com.cloud.network.vpc.StaticRoute; +import com.cloud.network.vpc.Vpc; +import com.cloud.network.vpc.VpcOffering; +import com.cloud.offering.DiskOffering; +import com.cloud.offering.NetworkOffering; +import com.cloud.offering.NetworkOffering.Detail; +import com.cloud.offering.ServiceOffering; +import com.cloud.offerings.NetworkOfferingVO; +import com.cloud.org.Cluster; +import com.cloud.projects.Project; +import com.cloud.projects.ProjectAccount; +import com.cloud.projects.ProjectInvitation; +import com.cloud.region.ha.GlobalLoadBalancerRule; +import com.cloud.server.ResourceTag; +import com.cloud.server.ResourceTag.ResourceObjectType; +import com.cloud.service.ServiceOfferingVO; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.GuestOS; +import com.cloud.storage.GuestOSCategoryVO; +import com.cloud.storage.GuestOSHypervisor; +import com.cloud.storage.ImageStore; +import com.cloud.storage.Snapshot; +import com.cloud.storage.SnapshotVO; +import com.cloud.storage.StoragePool; +import com.cloud.storage.Upload; +import com.cloud.storage.UploadVO; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.Volume; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.snapshot.SnapshotPolicy; +import com.cloud.storage.snapshot.SnapshotSchedule; +import com.cloud.tags.dao.ResourceTagDao; +import com.cloud.template.VirtualMachineTemplate; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.SSHKeyPair; +import com.cloud.user.User; +import com.cloud.user.UserAccount; +import com.cloud.uservm.UserVm; +import com.cloud.utils.Pair; +import com.cloud.utils.StringUtils; +import com.cloud.utils.crypt.DBEncryptionUtil; +import com.cloud.utils.db.EntityManager; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.net.Dhcp; +import com.cloud.utils.net.Ip; +import com.cloud.utils.net.NetUtils; +import com.cloud.vm.ConsoleProxyVO; +import com.cloud.vm.InstanceGroup; +import com.cloud.vm.Nic; +import com.cloud.vm.NicExtraDhcpOptionVO; +import com.cloud.vm.NicProfile; +import com.cloud.vm.NicSecondaryIp; +import com.cloud.vm.NicVO; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachine.Type; +import com.cloud.vm.dao.NicExtraDhcpOptionDao; +import com.cloud.vm.dao.NicSecondaryIpVO; +import com.cloud.vm.snapshot.VMSnapshot; public class ApiResponseHelper implements ResponseGenerator { @@ -363,6 +367,8 @@ public class ApiResponseHelper implements ResponseGenerator { private NicExtraDhcpOptionDao _nicExtraDhcpOptionDao; @Inject private IPAddressDao userIpAddressDao; + @Inject + NetworkDetailsDao networkDetailsDao; @Override public UserResponse createUserResponse(User user) { @@ -2118,6 +2124,15 @@ public class ApiResponseHelper implements ResponseGenerator { response.setVlan(vlan); } + // return network details only to Root admin + if (view == ResponseView.Full) { + Map details = new HashMap<>(); + for (NetworkDetailVO detail: networkDetailsDao.listDetails(network.getId())) { + details.put(detail.getName(),detail.getValue()); + } + response.setDetails(details); + } + DataCenter zone = ApiDBUtils.findZoneById(network.getDataCenterId()); if (zone != null) { response.setZoneId(zone.getUuid()); @@ -3360,18 +3375,26 @@ public class ApiResponseHelper implements ResponseGenerator { } } else if (usageRecord.getUsageType() == UsageTypes.IP_ADDRESS) { - //isSourceNAT - usageRecResponse.setSourceNat((usageRecord.getType().equals("SourceNat")) ? true : false); - //isSystem - usageRecResponse.setSystem((usageRecord.getSize() == 1) ? true : false); //IP Address ID IPAddressVO ip = _entityMgr.findByIdIncludingRemoved(IPAddressVO.class, usageRecord.getUsageId().toString()); if (ip != null) { + Long networkId = ip.getAssociatedWithNetworkId(); + if (networkId == null) { + networkId = ip.getSourceNetworkId(); + } + NetworkDetailVO networkDetail = networkDetailsDao.findDetail(networkId, Network.hideIpAddressUsage); + if (networkDetail != null && networkDetail.getValue() != null && networkDetail.getValue().equals("true")) { + // Don't export network usage when admin wants it hidden + return null; + } resourceType = ResourceObjectType.PublicIpAddress; resourceId = ip.getId(); usageRecResponse.setUsageId(ip.getUuid()); } - + //isSourceNAT + usageRecResponse.setSourceNat((usageRecord.getType().equals("SourceNat")) ? true : false); + //isSystem + usageRecResponse.setSystem((usageRecord.getSize() == 1) ? true : false); } else if (usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_SENT || usageRecord.getUsageType() == UsageTypes.NETWORK_BYTES_RECEIVED) { //Device Type resourceType = ResourceObjectType.UserVm; diff --git a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java index 76d55603226..0e52c054ec1 100644 --- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java @@ -45,10 +45,12 @@ import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin; import org.apache.cloudstack.api.command.admin.network.CreateNetworkCmdByAdmin; import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd; import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd; +import org.apache.cloudstack.api.command.admin.network.UpdateNetworkCmdByAdmin; import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; +import org.apache.cloudstack.api.command.user.network.UpdateNetworkCmd; import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; import org.apache.cloudstack.api.response.AcquirePodIpCmdResponse; import org.apache.cloudstack.context.CallContext; @@ -1023,11 +1025,11 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { String networkDomain = cmd.getNetworkDomain(); String vlanId = null; boolean bypassVlanOverlapCheck = false; + boolean hideIpAddressUsage = false; if (cmd instanceof CreateNetworkCmdByAdmin) { vlanId = ((CreateNetworkCmdByAdmin)cmd).getVlan(); - } - if (cmd instanceof CreateNetworkCmdByAdmin) { bypassVlanOverlapCheck = ((CreateNetworkCmdByAdmin)cmd).getBypassVlanOverlapCheck(); + hideIpAddressUsage = ((CreateNetworkCmdByAdmin)cmd).getHideIpAddressUsage(); } String name = cmd.getNetworkName(); @@ -1309,6 +1311,10 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { domainId, isDomainSpecific, subdomainAccess, vpcId, startIPv6, endIPv6, ip6Gateway, ip6Cidr, displayNetwork, aclId, isolatedPvlan, ntwkOff, pNtwk, aclType, owner, cidr, createVlan, externalId); + if (hideIpAddressUsage) { + _networkDetailsDao.persist(new NetworkDetailVO(network.getId(), Network.hideIpAddressUsage, String.valueOf(hideIpAddressUsage), false)); + } + // if the network offering has persistent set to true, implement the network if (ntwkOff.isPersistent()) { try { @@ -1981,8 +1987,21 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { @Override @DB @ActionEvent(eventType = EventTypes.EVENT_NETWORK_UPDATE, eventDescription = "updating network", async = true) - public Network updateGuestNetwork(final long networkId, String name, String displayText, Account callerAccount, User callerUser, String domainSuffix, final Long networkOfferingId, - Boolean changeCidr, String guestVmCidr, Boolean displayNetwork, String customId, boolean updateInSequence, boolean forced) { + public Network updateGuestNetwork(final UpdateNetworkCmd cmd) { + User callerUser = _accountService.getActiveUser(CallContext.current().getCallingUserId()); + Account callerAccount = _accountService.getActiveAccountById(callerUser.getAccountId()); + final long networkId = cmd.getId(); + String name = cmd.getNetworkName(); + String displayText = cmd.getDisplayText(); + String domainSuffix = cmd.getNetworkDomain(); + final Long networkOfferingId = cmd.getNetworkOfferingId(); + Boolean changeCidr = cmd.getChangeCidr(); + String guestVmCidr = cmd.getGuestVmCidr(); + Boolean displayNetwork = cmd.getDisplayNetwork(); + String customId = cmd.getCustomId(); + boolean updateInSequence = cmd.getUpdateInSequence(); + boolean forced = cmd.getForced(); + boolean restartNetwork = false; // verify input parameters @@ -2016,6 +2035,19 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { _accountMgr.checkAccess(callerAccount, null, true, network); + if (cmd instanceof UpdateNetworkCmdByAdmin) { + final Boolean hideIpAddressUsage = ((UpdateNetworkCmdByAdmin) cmd).getHideIpAddressUsage(); + if (hideIpAddressUsage != null) { + final NetworkDetailVO detail = _networkDetailsDao.findDetail(network.getId(), Network.hideIpAddressUsage); + if (detail != null) { + detail.setValue(hideIpAddressUsage.toString()); + _networkDetailsDao.update(detail.getId(), detail); + } else { + _networkDetailsDao.persist(new NetworkDetailVO(network.getId(), Network.hideIpAddressUsage, hideIpAddressUsage.toString(), false)); + } + } + } + if (name != null) { network.setName(name); } diff --git a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java index b3027f23486..e99c2a864cb 100644 --- a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java @@ -24,9 +24,6 @@ import java.util.Map; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin; import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd; @@ -35,9 +32,12 @@ import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementors import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; +import org.apache.cloudstack.api.command.user.network.UpdateNetworkCmd; import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; import org.apache.cloudstack.api.response.AcquirePodIpCmdResponse; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; @@ -250,12 +250,8 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches return null; } - /* (non-Javadoc) - * @see com.cloud.network.NetworkService#updateGuestNetwork(long, java.lang.String, java.lang.String, com.cloud.user.Account, com.cloud.user.User, java.lang.String, java.lang.Long, java.lang.Boolean) - */ @Override - public Network updateGuestNetwork(long networkId, String name, String displayText, Account callerAccount, User callerUser, String domainSuffix, - Long networkOfferingId, Boolean changeCidr, String guestVmCidr, Boolean displayNetwork, String newUUID,boolean updateInSequence, boolean forced) { + public Network updateGuestNetwork(final UpdateNetworkCmd cmd) { // TODO Auto-generated method stub return null; } diff --git a/ui/l10n/en.js b/ui/l10n/en.js index ca3d9cf1478..db269250860 100644 --- a/ui/l10n/en.js +++ b/ui/l10n/en.js @@ -1177,6 +1177,7 @@ var dictionary = { "label.network.device.type":"Network Device Type", "label.network.domain":"Network Domain", "label.network.domain.text":"Network domain", +"label.network.hideipaddressusage":"Hide IP Address Usage", "label.network.id":"Network ID", "label.network.label.display.for.blank.value":"Use default gateway", "label.network.limits":"Network limits", diff --git a/ui/scripts/docs.js b/ui/scripts/docs.js index 9a737469ced..aef5e77efbc 100755 --- a/ui/scripts/docs.js +++ b/ui/scripts/docs.js @@ -506,6 +506,10 @@ cloudStack.docs = { desc: 'If you want to assign a special domain name to this guest VM network, specify the DNS suffix', externalLink: '' }, + helpGuestNetworkHideIpAddressUsage: { + desc: 'If you want the IP address usage records hidden for the network', + externalLink: '' + }, // Add host helpHostZone: { desc: 'The zone where you want to add the host', diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index 995b8415ebc..1a389bbe01c 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -704,7 +704,16 @@ var addGuestNetworkDialog = { networkdomain: { label: 'label.network.domain', docID: 'helpGuestNetworkZoneNetworkDomain' + }, + + hideipaddressusage: { + label: 'label.network.hideipaddressusage', + dependsOn: ['zoneId', 'physicalNetworkId', 'scope'], + isBoolean: true, + isChecked: false, + docID: 'helpGuestNetworkHideIpAddressUsage' } + } }, @@ -795,6 +804,10 @@ var addGuestNetworkDialog = { if (args.data.networkdomain != null && args.data.networkdomain.length > 0){ array1.push("&networkdomain=" + encodeURIComponent(args.data.networkdomain)); } + if (args.data.hideipaddressusage != null && args.data.hideipaddressusage) { + array1.push("&hideipaddressusage=true") + } + $.ajax({ url: createURL("createNetwork" + array1.join("")), dataType: "json",