This is an automated email from the ASF dual-hosted git repository.
weizhou pushed a commit to branch 4.18
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.18 by this push:
new 8dc5fdd067d server: fix cannot get systemvm ips in dedicated ranges
(#7144)
8dc5fdd067d is described below
commit 8dc5fdd067d555e3fdb04704627bca043b766174
Author: Wei Zhou <[email protected]>
AuthorDate: Fri Aug 25 11:36:39 2023 +0200
server: fix cannot get systemvm ips in dedicated ranges (#7144)
This fixes #6698
---
.../main/java/com/cloud/api/ApiResponseHelper.java | 2 +-
.../configuration/ConfigurationManagerImpl.java | 8 +-
.../com/cloud/network/IpAddressManagerImpl.java | 265 +++++++++++----------
test/integration/smoke/test_public_ip_range.py | 3 +-
ui/public/locales/en.json | 1 +
ui/src/views/infra/network/IpRangesTabPublic.vue | 6 +-
6 files changed, 146 insertions(+), 139 deletions(-)
diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java
b/server/src/main/java/com/cloud/api/ApiResponseHelper.java
index 05aee6b6ccb..17c465d40ce 100644
--- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java
@@ -901,7 +901,7 @@ public class ApiResponseHelper implements ResponseGenerator
{
Long networkId = vlan.getNetworkId();
if (networkId != null) {
Network network = _ntwkModel.getNetwork(networkId);
- if (network != null) {
+ if (network != null &&
TrafficType.Guest.equals(network.getTrafficType())) {
Long accountId = network.getAccountId();
populateAccount(vlanResponse, accountId);
populateDomain(vlanResponse,
ApiDBUtils.findAccountById(accountId).getDomainId());
diff --git
a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
index 737cdc769f6..455a964b8d7 100644
--- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -5397,10 +5397,11 @@ public class ConfigurationManagerImpl extends
ManagerBase implements Configurati
// Check if any of the Public IP addresses is allocated to another
// account
- boolean forSystemVms = false;
final List<IPAddressVO> ips =
_publicIpAddressDao.listByVlanId(vlanDbId);
for (final IPAddressVO ip : ips) {
- forSystemVms = ip.isForSystemVms();
+ if (ip.isForSystemVms()) {
+ throw new InvalidParameterValueException(ip.getAddress() + "
Public IP address in range is dedicated to system vms ");
+ }
final Long allocatedToAccountId = ip.getAllocatedToAccountId();
if (allocatedToAccountId != null) {
if (vlanOwner != null && allocatedToAccountId !=
vlanOwner.getId()) {
@@ -5425,7 +5426,7 @@ public class ConfigurationManagerImpl extends ManagerBase
implements Configurati
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NET_IP_ASSIGN,
vlanOwner.getId(), ip.getDataCenterId(), ip.getId(),
ip.getAddress().toString(), ip.isSourceNat(),
vlan.getVlanType().toString(), ip.getSystem(),
usageHidden, ip.getClass().getName(), ip.getUuid());
}
- } else if (domain != null && !forSystemVms) {
+ } else if (domain != null) {
// Create an DomainVlanMapVO entry
DomainVlanMapVO domainVlanMapVO = new
DomainVlanMapVO(domain.getId(), vlan.getId());
_domainVlanMapDao.persist(domainVlanMapVO);
@@ -7250,7 +7251,6 @@ public class ConfigurationManagerImpl extends ManagerBase
implements Configurati
@Override
public Domain getVlanDomain(long vlanId) {
Vlan vlan = _vlanDao.findById(vlanId);
- Long domainId = null;
// if vlan is Virtual Domain specific, get vlan information from the
// accountVlanMap; otherwise get account information
diff --git a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java
b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java
index bb5371ed271..9882ed50353 100644
--- a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java
+++ b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java
@@ -334,19 +334,10 @@ public class IpAddressManagerImpl extends ManagerBase
implements IpAddressManage
@DB
private IPAddressVO assignAndAllocateIpAddressEntry(final Account owner,
final VlanType vlanUse, final Long guestNetworkId,
final boolean
sourceNat, final boolean allocate, final boolean isSystem,
- final Long vpcId,
final Boolean displayIp, final boolean fetchFromDedicatedRange,
+ final Long vpcId,
final Boolean displayIp,
final
List<IPAddressVO> addressVOS) throws CloudRuntimeException {
return
Transaction.execute((TransactionCallbackWithException<IPAddressVO,
CloudRuntimeException>) status -> {
IPAddressVO finalAddress = null;
- if (!fetchFromDedicatedRange &&
VlanType.VirtualNetwork.equals(vlanUse)) {
- // Check that the maximum number of public IPs for the given
accountId will not be exceeded
- try {
- _resourceLimitMgr.checkResourceLimit(owner,
ResourceType.public_ip);
- } catch (ResourceAllocationException ex) {
- s_logger.warn("Failed to allocate resource of type " +
ex.getResourceType() + " for account " + owner);
- throw new AccountLimitException("Maximum number of public
IP addresses for account: " + owner.getAccountName() + " has been exceeded.");
- }
- }
for (IPAddressVO possibleAddr : addressVOS) {
if (possibleAddr.getState() != State.Free) {
@@ -826,6 +817,10 @@ public class IpAddressManagerImpl extends ManagerBase
implements IpAddressManage
throws InsufficientAddressCapacityException {
List<IPAddressVO> addrs = listAvailablePublicIps(dcId, podId,
vlanDbIds, owner, vlanUse, guestNetworkId, sourceNat, assign, allocate,
requestedIp, requestedGateway, isSystem, vpcId, displayIp, forSystemVms, true);
IPAddressVO addr = addrs.get(0);
+ if (assign) {
+ addr = assignAndAllocateIpAddressEntry(owner, vlanUse,
guestNetworkId, sourceNat, allocate,
+ isSystem,vpcId, displayIp, addrs);
+ }
if (vlanUse == VlanType.VirtualNetwork) {
_firewallMgr.addSystemFirewallRules(addr, owner);
}
@@ -837,128 +832,99 @@ public class IpAddressManagerImpl extends ManagerBase
implements IpAddressManage
public List<IPAddressVO> listAvailablePublicIps(final long dcId, final
Long podId, final List<Long> vlanDbIds, final Account owner, final VlanType
vlanUse, final Long guestNetworkId,
final boolean sourceNat,
final boolean assign, final boolean allocate, final String requestedIp, final
String requestedGateway, final boolean isSystem,
final Long vpcId, final
Boolean displayIp, final boolean forSystemVms, final boolean lockOneRow) throws
InsufficientAddressCapacityException {
- return Transaction.execute(new
TransactionCallbackWithException<List<IPAddressVO>,
InsufficientAddressCapacityException>() {
- @Override
- public List<IPAddressVO> doInTransaction(TransactionStatus status)
throws InsufficientAddressCapacityException {
- StringBuilder errorMessage = new StringBuilder("Unable to get
ip address in ");
- boolean fetchFromDedicatedRange = false;
- List<Long> dedicatedVlanDbIds = new ArrayList<Long>();
- List<Long> nonDedicatedVlanDbIds = new ArrayList<Long>();
- DataCenter zone = _entityMgr.findById(DataCenter.class, dcId);
-
- SearchCriteria<IPAddressVO> sc = null;
- if (podId != null) {
- sc = AssignIpAddressFromPodVlanSearch.create();
- sc.setJoinParameters("podVlanMapSB", "podId", podId);
- errorMessage.append(" pod id=" + podId);
- } else {
- sc = AssignIpAddressSearch.create();
- errorMessage.append(" zone id=" + dcId);
- }
- // If owner has dedicated Public IP ranges, fetch IP from the
dedicated range
- // Otherwise fetch IP from the system pool
- Network network = _networksDao.findById(guestNetworkId);
- //Checking if network is null in the case of system VM's. At
the time of allocation of IP address to systemVm, no network is present.
- if(network == null || !(network.getGuestType() ==
GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced)) {
- List<AccountVlanMapVO> maps =
_accountVlanMapDao.listAccountVlanMapsByAccount(owner.getId());
- for (AccountVlanMapVO map : maps) {
- if (vlanDbIds == null ||
vlanDbIds.contains(map.getVlanDbId()))
- dedicatedVlanDbIds.add(map.getVlanDbId());
- }
- }
- List<DomainVlanMapVO> domainMaps =
_domainVlanMapDao.listDomainVlanMapsByDomain(owner.getDomainId());
- for (DomainVlanMapVO map : domainMaps) {
- if (vlanDbIds == null ||
vlanDbIds.contains(map.getVlanDbId()))
- dedicatedVlanDbIds.add(map.getVlanDbId());
- }
- List<VlanVO> nonDedicatedVlans =
_vlanDao.listZoneWideNonDedicatedVlans(dcId);
- for (VlanVO nonDedicatedVlan : nonDedicatedVlans) {
- if (vlanDbIds == null ||
vlanDbIds.contains(nonDedicatedVlan.getId()))
- nonDedicatedVlanDbIds.add(nonDedicatedVlan.getId());
- }
-
- if (vlanUse == VlanType.VirtualNetwork) {
- if (!dedicatedVlanDbIds.isEmpty()) {
- fetchFromDedicatedRange = true;
- sc.setParameters("vlanId",
dedicatedVlanDbIds.toArray());
- errorMessage.append(", vlanId id=" +
Arrays.toString(dedicatedVlanDbIds.toArray()));
- } else if (!nonDedicatedVlanDbIds.isEmpty()) {
- sc.setParameters("vlanId",
nonDedicatedVlanDbIds.toArray());
- errorMessage.append(", vlanId id=" +
Arrays.toString(nonDedicatedVlanDbIds.toArray()));
- } else {
- if (podId != null) {
- InsufficientAddressCapacityException ex = new
InsufficientAddressCapacityException("Insufficient address capacity",
Pod.class, podId);
-
ex.addProxyObject(ApiDBUtils.findPodById(podId).getUuid());
- throw ex;
- }
- s_logger.warn(errorMessage.toString());
- InsufficientAddressCapacityException ex = new
InsufficientAddressCapacityException("Insufficient address capacity",
DataCenter.class, dcId);
-
ex.addProxyObject(ApiDBUtils.findZoneById(dcId).getUuid());
- throw ex;
- }
- }
+ StringBuilder errorMessage = new StringBuilder("Unable to get ip
address in ");
+ boolean fetchFromDedicatedRange = false;
+ List<Long> dedicatedVlanDbIds = new ArrayList<Long>();
+ List<Long> nonDedicatedVlanDbIds = new ArrayList<Long>();
+ DataCenter zone = _entityMgr.findById(DataCenter.class, dcId);
+
+ SearchCriteria<IPAddressVO> sc = null;
+ if (podId != null) {
+ sc = AssignIpAddressFromPodVlanSearch.create();
+ sc.setJoinParameters("podVlanMapSB", "podId", podId);
+ errorMessage.append(" pod id=" + podId);
+ } else {
+ sc = AssignIpAddressSearch.create();
+ errorMessage.append(" zone id=" + dcId);
+ }
- sc.setParameters("dc", dcId);
+ sc.setParameters("dc", dcId);
- // for direct network take ip addresses only from the vlans
belonging to the network
- if (vlanUse == VlanType.DirectAttached) {
- sc.setJoinParameters("vlan", "networkId", guestNetworkId);
- errorMessage.append(", network id=" + guestNetworkId);
- }
- if (requestedGateway != null) {
- sc.setJoinParameters("vlan", "vlanGateway",
requestedGateway);
- errorMessage.append(", requested gateway=" +
requestedGateway);
- }
- sc.setJoinParameters("vlan", "type", vlanUse);
- String routerIpAddress = null;
- if (network != null) {
- NetworkDetailVO routerIpDetail =
_networkDetailsDao.findDetail(network.getId(), ApiConstants.ROUTER_IP);
- routerIpAddress = routerIpDetail != null ?
routerIpDetail.getValue() : null;
- }
- if (requestedIp != null) {
- sc.addAnd("address", SearchCriteria.Op.EQ, requestedIp);
- errorMessage.append(": requested ip " + requestedIp + " is
not available");
- } else if (routerIpAddress != null) {
- sc.addAnd("address", Op.NEQ, routerIpAddress);
- }
+ // for direct network take ip addresses only from the vlans belonging
to the network
+ if (vlanUse == VlanType.DirectAttached) {
+ sc.setJoinParameters("vlan", "networkId", guestNetworkId);
+ errorMessage.append(", network id=" + guestNetworkId);
+ }
+ if (requestedGateway != null) {
+ sc.setJoinParameters("vlan", "vlanGateway", requestedGateway);
+ errorMessage.append(", requested gateway=" + requestedGateway);
+ }
+ sc.setJoinParameters("vlan", "type", vlanUse);
- boolean ascOrder = ! forSystemVms;
- Filter filter = new Filter(IPAddressVO.class, "forSystemVms",
ascOrder, 0l, 1l);
- if (SystemVmPublicIpReservationModeStrictness.value()) {
- sc.setParameters("forSystemVms", forSystemVms);
- }
+ Network network = _networksDao.findById(guestNetworkId);
+ String routerIpAddress = null;
+ if (network != null) {
+ NetworkDetailVO routerIpDetail =
_networkDetailsDao.findDetail(network.getId(), ApiConstants.ROUTER_IP);
+ routerIpAddress = routerIpDetail != null ?
routerIpDetail.getValue() : null;
+ }
+ if (requestedIp != null) {
+ sc.addAnd("address", SearchCriteria.Op.EQ, requestedIp);
+ errorMessage.append(": requested ip " + requestedIp + " is not
available");
+ } else if (routerIpAddress != null) {
+ sc.addAnd("address", Op.NEQ, routerIpAddress);
+ }
- filter.addOrderBy(IPAddressVO.class,"vlanId", true);
+ boolean ascOrder = ! forSystemVms;
+ Filter filter = new Filter(IPAddressVO.class, "forSystemVms",
ascOrder, 0l, 1l);
- List<IPAddressVO> addrs;
+ filter.addOrderBy(IPAddressVO.class,"vlanId", true);
- if (lockOneRow) {
- addrs = _ipAddressDao.lockRows(sc, filter, true);
- } else {
- addrs = new ArrayList<>(_ipAddressDao.search(sc, null));
- }
+ List<IPAddressVO> addrs = new ArrayList<>();
- // If all the dedicated IPs of the owner are in use fetch an
IP from the system pool
- if ((!lockOneRow || (lockOneRow && addrs.size() == 0)) &&
fetchFromDedicatedRange && vlanUse == VlanType.VirtualNetwork) {
- // Verify if account is allowed to acquire IPs from the
system
- boolean useSystemIps =
UseSystemPublicIps.valueIn(owner.getId());
- if (useSystemIps && !nonDedicatedVlanDbIds.isEmpty()) {
- fetchFromDedicatedRange = false;
- sc.setParameters("vlanId",
nonDedicatedVlanDbIds.toArray());
- errorMessage.append(", vlanId id=" +
Arrays.toString(nonDedicatedVlanDbIds.toArray()));
- if (lockOneRow) {
- addrs = _ipAddressDao.lockRows(sc, filter, true);
- } else {
- addrs.addAll(_ipAddressDao.search(sc, null));
- }
- }
+ if (forSystemVms) {
+ // Get Public IPs for system vms in dedicated ranges
+ sc.setParameters("forSystemVms", true);
+ if (lockOneRow) {
+ addrs = _ipAddressDao.lockRows(sc, filter, true);
+ } else {
+ addrs = new ArrayList<>(_ipAddressDao.search(sc, null));
+ }
+ }
+ if ((!lockOneRow || (lockOneRow && CollectionUtils.isEmpty(addrs))) &&
+ !(forSystemVms &&
SystemVmPublicIpReservationModeStrictness.value())) {
+ sc.setParameters("forSystemVms", false);
+ // If owner has dedicated Public IP ranges, fetch IP from the
dedicated range
+ // Otherwise fetch IP from the system pool
+ // Checking if network is null in the case of system VM's. At the
time of allocation of IP address to systemVm, no network is present.
+ if (network == null || !(network.getGuestType() ==
GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced)) {
+ List<AccountVlanMapVO> maps =
_accountVlanMapDao.listAccountVlanMapsByAccount(owner.getId());
+ for (AccountVlanMapVO map : maps) {
+ if (vlanDbIds == null ||
vlanDbIds.contains(map.getVlanDbId()))
+ dedicatedVlanDbIds.add(map.getVlanDbId());
}
-
- if (lockOneRow && addrs.size() == 0) {
+ }
+ List<DomainVlanMapVO> domainMaps =
_domainVlanMapDao.listDomainVlanMapsByDomain(owner.getDomainId());
+ for (DomainVlanMapVO map : domainMaps) {
+ if (vlanDbIds == null || vlanDbIds.contains(map.getVlanDbId()))
+ dedicatedVlanDbIds.add(map.getVlanDbId());
+ }
+ List<VlanVO> nonDedicatedVlans =
_vlanDao.listZoneWideNonDedicatedVlans(dcId);
+ for (VlanVO nonDedicatedVlan : nonDedicatedVlans) {
+ if (vlanDbIds == null ||
vlanDbIds.contains(nonDedicatedVlan.getId()))
+ nonDedicatedVlanDbIds.add(nonDedicatedVlan.getId());
+ }
+ if (vlanUse == VlanType.VirtualNetwork) {
+ if (!dedicatedVlanDbIds.isEmpty()) {
+ fetchFromDedicatedRange = true;
+ sc.setParameters("vlanId", dedicatedVlanDbIds.toArray());
+ errorMessage.append(", vlanId id=" +
Arrays.toString(dedicatedVlanDbIds.toArray()));
+ } else if (!nonDedicatedVlanDbIds.isEmpty()) {
+ sc.setParameters("vlanId",
nonDedicatedVlanDbIds.toArray());
+ errorMessage.append(", vlanId id=" +
Arrays.toString(nonDedicatedVlanDbIds.toArray()));
+ } else {
if (podId != null) {
InsufficientAddressCapacityException ex = new
InsufficientAddressCapacityException("Insufficient address capacity",
Pod.class, podId);
- // for now, we hardcode the table names, but we should
ideally do a lookup for the tablename from the VO object.
ex.addProxyObject(ApiDBUtils.findPodById(podId).getUuid());
throw ex;
}
@@ -967,17 +933,58 @@ public class IpAddressManagerImpl extends ManagerBase
implements IpAddressManage
ex.addProxyObject(ApiDBUtils.findZoneById(dcId).getUuid());
throw ex;
}
+ }
+ if (lockOneRow) {
+ addrs = _ipAddressDao.lockRows(sc, filter, true);
+ } else {
+ addrs = new ArrayList<>(_ipAddressDao.search(sc, null));
+ }
- if (lockOneRow) {
- assert (addrs.size() == 1) : "Return size is incorrect: "
+ addrs.size();
- }
- if (assign) {
- assignAndAllocateIpAddressEntry(owner, vlanUse,
guestNetworkId, sourceNat, allocate,
- isSystem,vpcId, displayIp,
fetchFromDedicatedRange, addrs);
+ // If all the dedicated IPs of the owner are in use fetch an IP
from the system pool
+ if ((!lockOneRow || (lockOneRow && addrs.size() == 0)) &&
fetchFromDedicatedRange && vlanUse == VlanType.VirtualNetwork) {
+ // Verify if account is allowed to acquire IPs from the system
+ boolean useSystemIps =
UseSystemPublicIps.valueIn(owner.getId());
+ if (useSystemIps && !nonDedicatedVlanDbIds.isEmpty()) {
+ fetchFromDedicatedRange = false;
+ sc.setParameters("vlanId",
nonDedicatedVlanDbIds.toArray());
+ errorMessage.append(", vlanId id=" +
Arrays.toString(nonDedicatedVlanDbIds.toArray()));
+ if (lockOneRow) {
+ addrs = _ipAddressDao.lockRows(sc, filter, true);
+ } else {
+ addrs.addAll(_ipAddressDao.search(sc, null));
+ }
}
- return addrs;
}
- });
+ }
+
+ if (lockOneRow && addrs.size() == 0) {
+ if (podId != null) {
+ InsufficientAddressCapacityException ex = new
InsufficientAddressCapacityException("Insufficient address capacity",
Pod.class, podId);
+ // for now, we hardcode the table names, but we should ideally
do a lookup for the tablename from the VO object.
+ ex.addProxyObject(ApiDBUtils.findPodById(podId).getUuid());
+ throw ex;
+ }
+ s_logger.warn(errorMessage.toString());
+ InsufficientAddressCapacityException ex = new
InsufficientAddressCapacityException("Insufficient address capacity",
DataCenter.class, dcId);
+ ex.addProxyObject(ApiDBUtils.findZoneById(dcId).getUuid());
+ throw ex;
+ }
+
+ if (lockOneRow) {
+ assert (addrs.size() == 1) : "Return size is incorrect: " +
addrs.size();
+ }
+
+ if (assign && !fetchFromDedicatedRange &&
VlanType.VirtualNetwork.equals(vlanUse)) {
+ // Check that the maximum number of public IPs for the given
accountId will not be exceeded
+ try {
+ _resourceLimitMgr.checkResourceLimit(owner,
ResourceType.public_ip);
+ } catch (ResourceAllocationException ex) {
+ s_logger.warn("Failed to allocate resource of type " +
ex.getResourceType() + " for account " + owner);
+ throw new AccountLimitException("Maximum number of public IP
addresses for account: " + owner.getAccountName() + " has been exceeded.");
+ }
+ }
+
+ return addrs;
}
@DB
diff --git a/test/integration/smoke/test_public_ip_range.py
b/test/integration/smoke/test_public_ip_range.py
index 69baf5f2fc2..19edc4c164f 100644
--- a/test/integration/smoke/test_public_ip_range.py
+++ b/test/integration/smoke/test_public_ip_range.py
@@ -128,9 +128,8 @@ class TestDedicatePublicIPRange(cloudstackTestCase):
id=self.public_ip_range.vlan.id
)
public_ip_response = list_public_ip_range_response[0]
- self.assertEqual(
+ self.assertIsNone(
public_ip_response.account,
- "system",
"Check account name is system account in
listVlanIpRanges"
)
return
diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json
index 1469170ae01..528ea521c53 100644
--- a/ui/public/locales/en.json
+++ b/ui/public/locales/en.json
@@ -1901,6 +1901,7 @@
"label.suspend.project": "Suspend project",
"label.switch.type": "Switch type",
"label.sync.storage": "Sync storage pool",
+"label.system.ip.pool": "System Pool",
"label.system.offering": "System offering",
"label.system.offerings": "System offerings",
"label.system.service.offering": "System service offering",
diff --git a/ui/src/views/infra/network/IpRangesTabPublic.vue
b/ui/src/views/infra/network/IpRangesTabPublic.vue
index 247a8faf0d4..d7f743fda13 100644
--- a/ui/src/views/infra/network/IpRangesTabPublic.vue
+++ b/ui/src/views/infra/network/IpRangesTabPublic.vue
@@ -47,21 +47,21 @@
{{ record.endip || record.endipv6 }}
</template>
<template #account="{record}" v-if="!basicGuestNetwork">
- <a-button @click="() => handleOpenAccountModal(record)">{{
`[${record.domain}] ${record.account === undefined ? '' : record.account}`
}}</a-button>
+ <a-button @click="() => handleOpenAccountModal(record)">{{
record.domain === undefined ? `${$t('label.system.ip.pool')}` : `[
${record.domain}] ${record.account === undefined ? '' : record.account}`
}}</a-button>
</template>
<template #actions="{record}">
<div
class="actions"
style="text-align: right" >
<tooltip-button
- v-if="record.account === 'system' && !basicGuestNetwork &&
record.gateway && !record.ip6gateway"
+ v-if="!record.domain && !basicGuestNetwork && record.gateway &&
!record.ip6gateway"
tooltipPlacement="bottom"
:tooltip="$t('label.add.account')"
icon="user-add-outlined"
@onClick="() => handleOpenAddAccountModal(record)"
:disabled="!('dedicatePublicIpRange' in $store.getters.apis)" />
<tooltip-button
- v-if="record.account !== 'system' && !basicGuestNetwork"
+ v-if="record.domain && !basicGuestNetwork"
tooltipPlacement="bottom"
:tooltip="$t('label.release.account')"
icon="user-delete-outlined"