Skip to content

Commit 0bab0db

Browse files
GaOrtigaLopez
andauthored
Introducing concept of domain VPCs (#7153)
Co-authored-by: Gabriel Ortiga Fernandes <gabriel.fernandes@scclouds.com.br> Co-authored-by: Lopez <rodrigo@scclouds.com.br>
1 parent a738204 commit 0bab0db

File tree

12 files changed

+85
-63
lines changed

12 files changed

+85
-63
lines changed

api/src/main/java/org/apache/cloudstack/api/command/user/network/ListNetworksCmd.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,11 @@ public void execute() {
235235
private void updateNetworkResponse(List<NetworkResponse> response) {
236236
for (NetworkResponse networkResponse : response) {
237237
ResourceIcon resourceIcon = resourceIconManager.getByResourceTypeAndUuid(ResourceTag.ResourceObjectType.Network, networkResponse.getId());
238-
if (resourceIcon == null) {
238+
if (resourceIcon == null && networkResponse.getVpcId() != null) {
239239
resourceIcon = resourceIconManager.getByResourceTypeAndUuid(ResourceTag.ResourceObjectType.Vpc, networkResponse.getVpcId());
240-
if (resourceIcon == null) {
241-
continue;
242-
}
240+
}
241+
if (resourceIcon == null) {
242+
continue;
243243
}
244244
ResourceIconResponse iconResponse = _responseGenerator.createResourceIconResponse(resourceIcon);
245245
networkResponse.setResourceIconResponse(iconResponse);

engine/schema/src/main/java/com/cloud/vm/dao/UserVmDao.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,5 @@ public interface UserVmDao extends GenericDao<UserVmVO, Long> {
103103

104104
List<UserVmVO> findByUserDataId(long userdataId);
105105

106+
List<UserVmVO> listByIds(List<Long> ids);
106107
}

engine/schema/src/main/java/com/cloud/vm/dao/UserVmDaoImpl.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
7171
protected SearchBuilder<UserVmVO> RunningSearch;
7272
protected SearchBuilder<UserVmVO> StateChangeSearch;
7373
protected SearchBuilder<UserVmVO> AccountHostSearch;
74+
protected SearchBuilder<UserVmVO> IdsSearch;
7475

7576
protected SearchBuilder<UserVmVO> DestroySearch;
7677
protected SearchBuilder<UserVmVO> AccountDataCenterVirtualSearch;
@@ -135,6 +136,10 @@ void init() {
135136
AccountSearch.and("account", AccountSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
136137
AccountSearch.done();
137138

139+
IdsSearch = createSearchBuilder();
140+
IdsSearch.and("ids", IdsSearch.entity().getId(), SearchCriteria.Op.IN);
141+
IdsSearch.done();
142+
138143
HostSearch = createSearchBuilder();
139144
HostSearch.and("host", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ);
140145
HostSearch.done();
@@ -778,4 +783,11 @@ public List<UserVmVO> findByUserDataId(long userdataId) {
778783
sc.setParameters("userDataId", userdataId);
779784
return listBy(sc);
780785
}
786+
787+
@Override
788+
public List<UserVmVO> listByIds(List<Long> ids) {
789+
SearchCriteria<UserVmVO> sc = IdsSearch.create();
790+
sc.setParameters("ids", ids.toArray());
791+
return listBy(sc);
792+
}
781793
}

server/src/main/java/com/cloud/api/ApiResponseHelper.java

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.util.Map;
3434
import java.util.Set;
3535
import java.util.TimeZone;
36+
import java.util.function.Consumer;
3637
import java.util.stream.Collectors;
3738

3839
import javax.inject.Inject;
@@ -1019,13 +1020,9 @@ public IPAddressResponse createIPAddressResponse(ResponseView view, IpAddress ip
10191020
}
10201021
}
10211022

1022-
if (ipAddr.getVpcId() != null) {
1023-
Vpc vpc = ApiDBUtils.findVpcById(ipAddr.getVpcId());
1024-
if (vpc != null) {
1025-
ipResponse.setVpcId(vpc.getUuid());
1026-
ipResponse.setVpcName(vpc.getName());
1027-
}
1028-
}
1023+
1024+
setVpcIdInResponse(ipAddr.getVpcId(), ipResponse::setVpcId, ipResponse::setVpcName);
1025+
10291026

10301027
// Network id the ip is associated with (if associated networkId is
10311028
// null, try to get this information from vlan)
@@ -1095,6 +1092,22 @@ public IPAddressResponse createIPAddressResponse(ResponseView view, IpAddress ip
10951092
return ipResponse;
10961093
}
10971094

1095+
1096+
private void setVpcIdInResponse(Long vpcId, Consumer<String> vpcUuidSetter, Consumer<String> vpcNameSetter) {
1097+
if (vpcId != null) {
1098+
Vpc vpc = ApiDBUtils.findVpcById(vpcId);
1099+
if (vpc != null) {
1100+
try {
1101+
_accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, false, vpc);
1102+
vpcUuidSetter.accept(vpc.getUuid());
1103+
} catch (PermissionDeniedException e) {
1104+
s_logger.debug("Not setting the vpcId to the response because the caller does not have access to the VPC");
1105+
}
1106+
vpcNameSetter.accept(vpc.getName());
1107+
}
1108+
}
1109+
}
1110+
10981111
private void showVmInfoForSharedNetworks(boolean forVirtualNetworks, IpAddress ipAddr, IPAddressResponse ipResponse) {
10991112
if (!forVirtualNetworks) {
11001113
NicVO nic = ApiDBUtils.findByIp4AddressAndNetworkId(ipAddr.getAddress().toString(), ipAddr.getNetworkId());
@@ -2565,13 +2578,9 @@ public NetworkResponse createNetworkResponse(ResponseView view, Network network)
25652578
}
25662579

25672580
response.setSpecifyIpRanges(network.getSpecifyIpRanges());
2568-
if (network.getVpcId() != null) {
2569-
Vpc vpc = ApiDBUtils.findVpcById(network.getVpcId());
2570-
if (vpc != null) {
2571-
response.setVpcId(vpc.getUuid());
2572-
response.setVpcName(vpc.getName());
2573-
}
2574-
}
2581+
2582+
2583+
setVpcIdInResponse(network.getVpcId(), response::setVpcId, response::setVpcName);
25752584

25762585
setResponseAssociatedNetworkInformation(response, network.getId());
25772586

server/src/main/java/com/cloud/network/IpAddressManagerImpl.java

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,15 +1471,7 @@ public IPAddressVO associateIPToGuestNetwork(long ipId, long networkId, boolean
14711471
throw new InvalidParameterValueException("Ip address can be associated to the network with trafficType " + TrafficType.Guest);
14721472
}
14731473

1474-
// Check that network belongs to IP owner - skip this check
1475-
// - if zone is basic zone as there is just one guest network,
1476-
// - if shared network in Advanced zone
1477-
// - and it belongs to the system
1478-
if (network.getAccountId() != owner.getId()) {
1479-
if (zone.getNetworkType() != NetworkType.Basic && !(zone.getNetworkType() == NetworkType.Advanced && network.getGuestType() == Network.GuestType.Shared)) {
1480-
throw new InvalidParameterValueException("The owner of the network is not the same as owner of the IP");
1481-
}
1482-
}
1474+
validateNetworkAndIpOwnership(owner, ipToAssoc, network, zone);
14831475

14841476
if (zone.getNetworkType() == NetworkType.Advanced) {
14851477
// In Advance zone allow to do IP assoc only for Isolated networks with source nat service enabled
@@ -1543,6 +1535,21 @@ public IPAddressVO associateIPToGuestNetwork(long ipId, long networkId, boolean
15431535
}
15441536
}
15451537

1538+
/**
1539+
* Check that network belongs to IP owner - skip this check
1540+
* - if the IP belongs to the same VPC as the network
1541+
* - if zone is basic zone as there is just one guest network,
1542+
* - if shared network in Advanced zone
1543+
* - and it belongs to the system
1544+
*/
1545+
private static void validateNetworkAndIpOwnership(Account owner, IPAddressVO ipToAssoc, Network network, DataCenter zone) {
1546+
if (network.getAccountId() != owner.getId()) {
1547+
if (!network.getVpcId().equals(ipToAssoc.getVpcId()) && zone.getNetworkType() == NetworkType.Advanced && network.getGuestType() != GuestType.Shared) {
1548+
throw new InvalidParameterValueException("The owner of the network is not the same as owner of the IP");
1549+
}
1550+
}
1551+
}
1552+
15461553
/**
15471554
* Prevents associating an IP address to an allocated (unimplemented network) network, throws an Exception otherwise
15481555
* @param owner Used to check if the user belongs to the Network
@@ -1625,15 +1632,7 @@ public IPAddressVO disassociatePortableIPToGuestNetwork(long ipId, long networkI
16251632

16261633
DataCenter zone = _entityMgr.findById(DataCenter.class, network.getDataCenterId());
16271634

1628-
// Check that network belongs to IP owner - skip this check
1629-
// - if zone is basic zone as there is just one guest network,
1630-
// - if shared network in Advanced zone
1631-
// - and it belongs to the system
1632-
if (network.getAccountId() != owner.getId()) {
1633-
if (zone.getNetworkType() != NetworkType.Basic && !(zone.getNetworkType() == NetworkType.Advanced && network.getGuestType() == Network.GuestType.Shared)) {
1634-
throw new InvalidParameterValueException("The owner of the network is not the same as owner of the IP");
1635-
}
1636-
}
1635+
validateNetworkAndIpOwnership(owner, ipToAssoc, network, zone);
16371636

16381637
// Check if IP has any services (rules) associated in the network
16391638
List<PublicIpAddress> ipList = new ArrayList<PublicIpAddress>();

server/src/main/java/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2351,7 +2351,7 @@ public Pair<List<? extends UserVm>, List<String>> listLoadBalancerInstances(List
23512351
}
23522352
}
23532353

2354-
List<UserVmVO> userVms = _vmDao.listVirtualNetworkInstancesByAcctAndNetwork(loadBalancer.getAccountId(), loadBalancer.getNetworkId());
2354+
List<UserVmVO> userVms = _vmDao.listByIds(appliedInstanceIdList);
23552355

23562356
for (UserVmVO userVm : userVms) {
23572357
// if the VM is destroyed, being expunged, in an error state, or in

server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1855,10 +1855,8 @@ public void doInTransactionWithoutResult(final TransactionStatus status) {
18551855
}
18561856
}
18571857

1858-
// 4) vpc and network should belong to the same owner
1859-
if (vpc.getAccountId() != networkOwner.getId()) {
1860-
throw new InvalidParameterValueException("Vpc " + vpc + " owner is different from the network owner " + networkOwner);
1861-
}
1858+
// 4) Vpc's account should be able to access network owner's account
1859+
CheckAccountsAccess(vpc, networkOwner);
18621860

18631861
// 5) network domain should be the same as VPC's
18641862
if (!networkDomain.equalsIgnoreCase(vpc.getNetworkDomain())) {
@@ -1877,6 +1875,17 @@ public void doInTransactionWithoutResult(final TransactionStatus status) {
18771875
});
18781876
}
18791877

1878+
private void CheckAccountsAccess(Vpc vpc, Account networkAccount) {
1879+
Account vpcaccount = _accountMgr.getAccount(vpc.getAccountId());
1880+
try {
1881+
_accountMgr.checkAccess(vpcaccount, null, false, networkAccount);
1882+
}
1883+
catch (PermissionDeniedException e) {
1884+
s_logger.error(e.getMessage());
1885+
throw new InvalidParameterValueException(String.format("VPC owner does not have access to account [%s].", networkAccount.getAccountName()));
1886+
}
1887+
}
1888+
18801889
public List<VpcProvider> getVpcElements() {
18811890
if (vpcElements == null) {
18821891
vpcElements = new ArrayList<VpcProvider>();
@@ -2879,11 +2888,11 @@ public IpAddress associateIPToVpc(final long ipId, final long vpcId) throws Reso
28792888
}
28802889

28812890
// check permissions
2882-
_accountMgr.checkAccess(caller, null, true, owner, vpc);
2891+
_accountMgr.checkAccess(caller, null, false, owner, vpc);
28832892

28842893
s_logger.debug("Associating ip " + ipToAssoc + " to vpc " + vpc);
28852894

2886-
final boolean isSourceNatFinal = isSrcNatIpRequired(vpc.getVpcOfferingId()) && getExistingSourceNatInVpc(owner.getId(), vpcId) == null;
2895+
final boolean isSourceNatFinal = isSrcNatIpRequired(vpc.getVpcOfferingId()) && getExistingSourceNatInVpc(vpc.getAccountId(), vpcId) == null;
28872896
Transaction.execute(new TransactionCallbackNoReturn() {
28882897
@Override
28892898
public void doInTransactionWithoutResult(final TransactionStatus status) {

ui/src/components/view/ListView.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,10 @@
216216
<router-link :to="{ path: '/guestnetwork/' + record.associatednetworkid }">{{ text }}</router-link>
217217
</template>
218218
<template v-if="column.key === 'vpcname'">
219-
<router-link :to="{ path: '/vpc/' + record.vpcid }">{{ text }}</router-link>
219+
<a v-if="record.vpcid">
220+
<router-link :to="{ path: '/vpc/' + record.vpcid }">{{ text }}</router-link>
221+
</a>
222+
<span v-else>{{ text }}</span>
220223
</template>
221224
<template v-if="column.key === 'hostname'">
222225
<router-link v-if="record.hostid" :to="{ path: '/host/' + record.hostid }">{{ text }}</router-link>

ui/src/config/section/network.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,15 @@ export default {
6060
}, {
6161
name: 'egress.rules',
6262
component: shallowRef(defineAsyncComponent(() => import('@/views/network/EgressRulesTab.vue'))),
63-
show: (record, route, user) => { return record.type === 'Isolated' && !('vpcid' in record) && 'listEgressFirewallRules' in store.getters.apis && (['Admin', 'DomainAdmin'].includes(user.roletype) || record.account === user.account || record.projectid) }
63+
show: (record, route, user) => { return record.type === 'Isolated' && !('vpcname' in record) && 'listEgressFirewallRules' in store.getters.apis && (['Admin', 'DomainAdmin'].includes(user.roletype) || record.account === user.account || record.projectid) }
6464
}, {
6565
name: 'ip.v6.firewall',
6666
component: shallowRef(defineAsyncComponent(() => import('@/views/network/Ipv6FirewallRulesTab.vue'))),
6767
show: (record, route, user) => { return record.type === 'Isolated' && ['IPv6', 'DualStack'].includes(record.internetprotocol) && !('vpcid' in record) && 'listIpv6FirewallRules' in store.getters.apis && (['Admin', 'DomainAdmin'].includes(user.roletype) || record.account === user.account || record.projectid) }
6868
}, {
6969
name: 'public.ip.addresses',
7070
component: shallowRef(defineAsyncComponent(() => import('@/views/network/IpAddressesTab.vue'))),
71-
show: (record, route, user) => { return 'listPublicIpAddresses' in store.getters.apis && (record.type === 'Shared' || (record.type === 'Isolated' && !('vpcid' in record) && (['Admin', 'DomainAdmin'].includes(user.roletype) || record.account === user.account || record.projectid))) }
71+
show: (record, route, user) => { return 'listPublicIpAddresses' in store.getters.apis && (record.type === 'Shared' || (record.type === 'Isolated' && !('vpcname' in record) && (['Admin', 'DomainAdmin'].includes(user.roletype) || record.account === user.account || record.projectid))) }
7272
}, {
7373
name: 'virtual.routers',
7474
component: shallowRef(defineAsyncComponent(() => import('@/views/network/RoutersTab.vue'))),

ui/src/views/network/EnableStaticNat.vue

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,6 @@ export default {
191191
pageSize: this.pageSize,
192192
listAll: true,
193193
networkid: this.resource.associatednetworkid,
194-
account: this.resource.account,
195-
domainid: this.resource.domainid,
196194
keyword: this.searchQuery
197195
}).then(response => {
198196
this.vmCount = response.listvirtualmachinesresponse.count
@@ -210,8 +208,6 @@ export default {
210208
pageSize: this.pageSize,
211209
listAll: true,
212210
networkid: e,
213-
account: this.resource.account,
214-
domainid: this.resource.domainid,
215211
vpcid: this.resource.vpcid,
216212
keyword: this.searchQuery
217213
}).then(response => {
@@ -250,8 +246,7 @@ export default {
250246
this.loading = true
251247
api('listNetworks', {
252248
vpcid: this.resource.vpcid,
253-
domainid: this.resource.domainid,
254-
account: this.resource.account,
249+
isrecursive: true,
255250
supportedservices: 'StaticNat'
256251
}).then(response => {
257252
this.networksList = response.listnetworksresponse.network

0 commit comments

Comments
 (0)