diff --git a/server/src/main/java/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java b/server/src/main/java/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java index e76c52b9ebf0..094f81607fe3 100644 --- a/server/src/main/java/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java +++ b/server/src/main/java/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java @@ -23,10 +23,11 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.cloudstack.annotation.AnnotationService; -import org.apache.cloudstack.annotation.dao.AnnotationDao; +import org.apache.commons.collections.CollectionUtils; import org.springframework.stereotype.Component; +import org.apache.cloudstack.annotation.AnnotationService; +import org.apache.cloudstack.annotation.dao.AnnotationDao; import org.apache.cloudstack.api.command.user.vpn.CreateVpnConnectionCmd; import org.apache.cloudstack.api.command.user.vpn.CreateVpnCustomerGatewayCmd; import org.apache.cloudstack.api.command.user.vpn.CreateVpnGatewayCmd; @@ -45,7 +46,6 @@ import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Site2SiteCustomerGateway; @@ -106,7 +106,6 @@ public class Site2SiteVpnManagerImpl extends ManagerBase implements Site2SiteVpn @Inject private AnnotationDao annotationDao; - String _name; int _connLimit; int _subnetsLimit; @@ -253,7 +252,7 @@ public Site2SiteCustomerGateway createCustomerGateway(CreateVpnCustomerGatewayCm @Override @ActionEvent(eventType = EventTypes.EVENT_S2S_VPN_CONNECTION_CREATE, eventDescription = "creating s2s vpn connection", create = true) - public Site2SiteVpnConnection createVpnConnection(CreateVpnConnectionCmd cmd) throws NetworkRuleConflictException { + public Site2SiteVpnConnection createVpnConnection(CreateVpnConnectionCmd cmd) { Account caller = CallContext.current().getCallingAccount(); Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); @@ -261,27 +260,15 @@ public Site2SiteVpnConnection createVpnConnection(CreateVpnConnectionCmd cmd) th _accountMgr.checkAccess(caller, null, false, owner); Long customerGatewayId = cmd.getCustomerGatewayId(); - Site2SiteCustomerGateway customerGateway = _customerGatewayDao.findById(customerGatewayId); - if (customerGateway == null) { - throw new InvalidParameterValueException("Unable to found specified Site to Site VPN customer gateway " + customerGatewayId + " !"); - } - _accountMgr.checkAccess(caller, null, false, customerGateway); + Site2SiteCustomerGateway customerGateway = getAndValidateSite2SiteCustomerGateway(customerGatewayId, caller); Long vpnGatewayId = cmd.getVpnGatewayId(); - Site2SiteVpnGateway vpnGateway = _vpnGatewayDao.findById(vpnGatewayId); - if (vpnGateway == null) { - throw new InvalidParameterValueException("Unable to found specified Site to Site VPN gateway " + vpnGatewayId + " !"); - } - _accountMgr.checkAccess(caller, null, false, vpnGateway); + Site2SiteVpnGateway vpnGateway = getAndValidateSite2SiteVpnGateway(vpnGatewayId, caller); - if (customerGateway.getAccountId() != vpnGateway.getAccountId() || customerGateway.getDomainId() != vpnGateway.getDomainId()) { - throw new InvalidParameterValueException("VPN connection can only be esitablished between same account's VPN gateway and customer gateway!"); - } + validateVpnConnectionOfTheRightAccount(customerGateway, vpnGateway); + validateVpnConnectionDoesntExist(vpnGatewayId, customerGatewayId); + validatePrerequisiteVpnGateway(vpnGateway); - if (_vpnConnectionDao.findByVpnGatewayIdAndCustomerGatewayId(vpnGatewayId, customerGatewayId) != null) { - throw new InvalidParameterValueException("The vpn connection with customer gateway id " + customerGatewayId + " and vpn gateway id " + vpnGatewayId + - " already existed!"); - } String[] cidrList = customerGateway.getGuestCidrList().split(","); // Remote sub nets cannot overlap VPC's sub net @@ -324,13 +311,51 @@ public Site2SiteVpnConnection createVpnConnection(CreateVpnConnectionCmd cmd) th return conn; } + private Site2SiteCustomerGateway getAndValidateSite2SiteCustomerGateway(Long customerGatewayId, Account caller) { + Site2SiteCustomerGateway customerGateway = _customerGatewayDao.findById(customerGatewayId); + if (customerGateway == null) { + throw new InvalidParameterValueException(String.format("Unable to find specified Site to Site VPN customer gateway %s !", customerGatewayId)); + } + _accountMgr.checkAccess(caller, null, false, customerGateway); + return customerGateway; + } + + private Site2SiteVpnGateway getAndValidateSite2SiteVpnGateway(Long vpnGatewayId, Account caller) { + Site2SiteVpnGateway vpnGateway = _vpnGatewayDao.findById(vpnGatewayId); + if (vpnGateway == null) { + throw new InvalidParameterValueException(String.format("Unable to find specified Site to Site VPN gateway %s !", vpnGatewayId)); + } + _accountMgr.checkAccess(caller, null, false, vpnGateway); + return vpnGateway; + } + + private void validateVpnConnectionOfTheRightAccount(Site2SiteCustomerGateway customerGateway, Site2SiteVpnGateway vpnGateway) { + if (customerGateway.getAccountId() != vpnGateway.getAccountId() || customerGateway.getDomainId() != vpnGateway.getDomainId()) { + throw new InvalidParameterValueException("VPN connection can only be established between same account's VPN gateway and customer gateway!"); + } + } + + private void validateVpnConnectionDoesntExist(Long vpnGatewayId, Long customerGatewayId) { + if (_vpnConnectionDao.findByVpnGatewayIdAndCustomerGatewayId(vpnGatewayId, customerGatewayId) != null) { + throw new InvalidParameterValueException("The vpn connection with customer gateway id " + customerGatewayId + " and vpn gateway id " + vpnGatewayId + + " already existed!"); + } + } + + private void validatePrerequisiteVpnGateway(Site2SiteVpnGateway vpnGateway) { + // check if gateway has been defined on the VPC + if (_vpnGatewayDao.findByVpcId(vpnGateway.getVpcId()) == null) { + throw new InvalidParameterValueException("we can not create a VPN connection for a VPC that does not have a VPN gateway defined"); + } + } + @Override @DB @ActionEvent(eventType = EventTypes.EVENT_S2S_VPN_CONNECTION_CREATE, eventDescription = "starting s2s vpn connection", async = true) public Site2SiteVpnConnection startVpnConnection(long id) throws ResourceUnavailableException { Site2SiteVpnConnectionVO conn = _vpnConnectionDao.acquireInLockTable(id); if (conn == null) { - throw new CloudRuntimeException("Unable to acquire lock on " + conn); + throw new CloudRuntimeException("Unable to acquire lock for starting of VPN connection with ID " + id); } try { if (conn.getState() != State.Pending && conn.getState() != State.Disconnected) { @@ -380,11 +405,7 @@ public boolean deleteCustomerGateway(DeleteVpnCustomerGatewayCmd cmd) { Account caller = CallContext.current().getCallingAccount(); Long id = cmd.getId(); - Site2SiteCustomerGateway customerGateway = _customerGatewayDao.findById(id); - if (customerGateway == null) { - throw new InvalidParameterValueException("Fail to find customer gateway with " + id + " !"); - } - _accountMgr.checkAccess(caller, null, false, customerGateway); + Site2SiteCustomerGateway customerGateway = getAndValidateSite2SiteCustomerGateway(id, caller); return doDeleteCustomerGateway(customerGateway); } @@ -392,7 +413,7 @@ public boolean deleteCustomerGateway(DeleteVpnCustomerGatewayCmd cmd) { protected boolean doDeleteCustomerGateway(Site2SiteCustomerGateway gw) { long id = gw.getId(); List vpnConnections = _vpnConnectionDao.listByCustomerGatewayId(id); - if (vpnConnections != null && vpnConnections.size() != 0) { + if (!CollectionUtils.isEmpty(vpnConnections)) { throw new InvalidParameterValueException("Unable to delete VPN customer gateway with id " + id + " because there is still related VPN connections!"); } annotationDao.removeByEntityType(AnnotationService.EntityType.VPN_CUSTOMER_GATEWAY.name(), gw.getUuid()); @@ -402,7 +423,7 @@ protected boolean doDeleteCustomerGateway(Site2SiteCustomerGateway gw) { protected void doDeleteVpnGateway(Site2SiteVpnGateway gw) { List conns = _vpnConnectionDao.listByVpnGatewayId(gw.getId()); - if (conns != null && conns.size() != 0) { + if (!CollectionUtils.isEmpty(conns)) { throw new InvalidParameterValueException("Unable to delete VPN gateway " + gw.getId() + " because there is still related VPN connections!"); } _vpnGatewayDao.remove(gw.getId()); @@ -415,12 +436,7 @@ public boolean deleteVpnGateway(DeleteVpnGatewayCmd cmd) { Account caller = CallContext.current().getCallingAccount(); Long id = cmd.getId(); - Site2SiteVpnGateway vpnGateway = _vpnGatewayDao.findById(id); - if (vpnGateway == null) { - throw new InvalidParameterValueException("Fail to find vpn gateway with " + id + " !"); - } - - _accountMgr.checkAccess(caller, null, false, vpnGateway); + Site2SiteVpnGateway vpnGateway = getAndValidateSite2SiteVpnGateway(id, caller); doDeleteVpnGateway(vpnGateway); return true; @@ -576,7 +592,7 @@ public boolean deleteVpnConnection(DeleteVpnConnectionCmd cmd) throws ResourceUn private void stopVpnConnection(Long id) throws ResourceUnavailableException { Site2SiteVpnConnectionVO conn = _vpnConnectionDao.acquireInLockTable(id); if (conn == null) { - throw new CloudRuntimeException("Unable to acquire lock on " + conn); + throw new CloudRuntimeException("Unable to acquire lock for stopping of VPN connection with ID " + id); } try { if (conn.getState() == State.Pending) { @@ -637,10 +653,9 @@ public Pair, Integer> searchForCustomer String keyword = cmd.getKeyword(); Account caller = CallContext.current().getCallingAccount(); - List permittedAccounts = new ArrayList(); + List permittedAccounts = new ArrayList<>(); - Ternary domainIdRecursiveListProject = new Ternary(domainId, isRecursive, null); + Ternary domainIdRecursiveListProject = new Ternary<>(domainId, isRecursive, null); _accountMgr.buildACLSearchParameters(caller, id, accountName, cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, listAll, false); domainId = domainIdRecursiveListProject.first(); isRecursive = domainIdRecursiveListProject.second(); @@ -665,7 +680,7 @@ public Pair, Integer> searchForCustomer } Pair, Integer> result = _customerGatewayDao.searchAndCount(sc, searchFilter); - return new Pair, Integer>(result.first(), result.second()); + return new Pair<>(result.first(), result.second()); } @Override @@ -682,10 +697,9 @@ public Pair, Integer> searchForVpnGateways(L long pageSizeVal = cmd.getPageSizeVal(); Account caller = CallContext.current().getCallingAccount(); - List permittedAccounts = new ArrayList(); + List permittedAccounts = new ArrayList<>(); - Ternary domainIdRecursiveListProject = new Ternary(domainId, isRecursive, null); + Ternary domainIdRecursiveListProject = new Ternary<>(domainId, isRecursive, null); _accountMgr.buildACLSearchParameters(caller, id, accountName, cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, listAll, false); domainId = domainIdRecursiveListProject.first(); isRecursive = domainIdRecursiveListProject.second(); @@ -715,7 +729,7 @@ public Pair, Integer> searchForVpnGateways(L } Pair, Integer> result = _vpnGatewayDao.searchAndCount(sc, searchFilter); - return new Pair, Integer>(result.first(), result.second()); + return new Pair<>(result.first(), result.second()); } @Override @@ -732,10 +746,9 @@ public Pair, Integer> searchForVpnConnect long pageSizeVal = cmd.getPageSizeVal(); Account caller = CallContext.current().getCallingAccount(); - List permittedAccounts = new ArrayList(); + List permittedAccounts = new ArrayList<>(); - Ternary domainIdRecursiveListProject = new Ternary(domainId, isRecursive, null); + Ternary domainIdRecursiveListProject = new Ternary<>(domainId, isRecursive, null); _accountMgr.buildACLSearchParameters(caller, id, accountName, cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, listAll, false); domainId = domainIdRecursiveListProject.first(); isRecursive = domainIdRecursiveListProject.second(); @@ -769,7 +782,7 @@ public Pair, Integer> searchForVpnConnect } Pair, Integer> result = _vpnConnectionDao.searchAndCount(sc, searchFilter); - return new Pair, Integer>(result.first(), result.second()); + return new Pair<>(result.first(), result.second()); } @Override @@ -816,7 +829,7 @@ public void markDisconnectVpnConnByVpc(long vpcId) { @Override public List getConnectionsForRouter(DomainRouterVO router) { - List conns = new ArrayList(); + List conns = new ArrayList<>(); // One router for one VPC Long vpcId = router.getVpcId(); if (router.getVpcId() == null) { @@ -829,7 +842,6 @@ public List getConnectionsForRouter(DomainRouterVO rou @Override public boolean deleteCustomerGatewayByAccount(long accountId) { boolean result = true; - ; List gws = _customerGatewayDao.listByAccountId(accountId); for (Site2SiteCustomerGatewayVO gw : gws) { result = result & doDeleteCustomerGateway(gw); diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java index cbde58dc7211..87b3dd3cbd92 100644 --- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java +++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java @@ -4859,7 +4859,7 @@ public Pair, Integer> listUserDatas(final ListUserDataC sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); - sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); + sb.and("keyword", sb.entity().getName(), SearchCriteria.Op.LIKE); final SearchCriteria sc = sb.create(); _accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria); @@ -4872,7 +4872,7 @@ public Pair, Integer> listUserDatas(final ListUserDataC } if (keyword != null) { - sc.setParameters("name", "%" + keyword + "%"); + sc.setParameters("keyword", "%" + keyword + "%"); } final Pair, Integer> result = userDataDao.searchAndCount(sc, searchFilter); diff --git a/ui/src/views/compute/EditVM.vue b/ui/src/views/compute/EditVM.vue index 87e6d96d6c6b..f2d679ee4445 100644 --- a/ui/src/views/compute/EditVM.vue +++ b/ui/src/views/compute/EditVM.vue @@ -84,7 +84,7 @@ }" :options="groups.opts" /> - + @@ -150,6 +150,7 @@ export default { return { serviceOffering: {}, template: {}, + userDataEnabled: false, securityGroupsEnabled: false, dynamicScalingVmConfig: false, loading: false, @@ -297,15 +298,37 @@ export default { return decodedData.toString('utf-8') }, fetchUserData () { - const params = { - id: this.resource.id, - userdata: true + let networkId + this.resource.nic.forEach(nic => { + if (nic.isdefault) { + networkId = nic.networkid + } + }) + if (!networkId) { + return + } + const listNetworkParams = { + id: networkId, + listall: true } + api(`listNetworks`, listNetworkParams).then(json => { + json.listnetworksresponse.network[0].service.forEach(service => { + if (service.name === 'UserData') { + this.userDataEnabled = true - api('listVirtualMachines', params).then(json => { - this.form.userdata = this.decodeUserData(json.listvirtualmachinesresponse.virtualmachine[0].userdata || '') + const listVmParams = { + id: this.resource.id, + userdata: true, + listall: true + } + api('listVirtualMachines', listVmParams).then(json => { + this.form.userdata = atob(json.listvirtualmachinesresponse.virtualmachine[0].userdata || '') + }) + } + }) }) }, + handleSubmit () { this.formRef.value.validate().then(() => { const values = toRaw(this.form) diff --git a/ui/src/views/network/VpcTab.vue b/ui/src/views/network/VpcTab.vue index 452d3934dafb..9090654b1833 100644 --- a/ui/src/views/network/VpcTab.vue +++ b/ui/src/views/network/VpcTab.vue @@ -800,12 +800,12 @@ export default { this.formRef.value.validate().then(() => { const values = toRaw(this.form) - - api('createVpnConnection', { - s2svpngatewayid: this.vpnGateways[0].id, + const params = { + s2svpngatewayid: this.vpnGateways[0] ? this.vpnGateways[0].id : null, s2scustomergatewayid: values.vpncustomergateway, passive: values.passive ? values.passive : false - }).then(response => { + } + api('createVpnConnection', params).then(response => { this.$pollJob({ jobId: response.createvpnconnectionresponse.jobid, title: this.$t('label.vpn.connection'),