Merge branch '4.19'

This commit is contained in:
Daan Hoogland 2024-05-23 12:34:04 +02:00
commit b38f1364e6
9 changed files with 62 additions and 25 deletions

View File

@ -20,6 +20,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import com.cloud.dc.VlanVO;
import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.impl.ConfigurationSubGroupVO; import org.apache.cloudstack.framework.config.impl.ConfigurationSubGroupVO;
@ -189,7 +190,7 @@ public interface ConfigurationManager {
* @param caller * @param caller
* @return success/failure * @return success/failure
*/ */
boolean deleteVlanAndPublicIpRange(long userId, long vlanDbId, Account caller); VlanVO deleteVlanAndPublicIpRange(long userId, long vlanDbId, Account caller);
void checkZoneAccess(Account caller, DataCenter zone); void checkZoneAccess(Account caller, DataCenter zone);

View File

@ -259,6 +259,8 @@ import com.cloud.vm.dao.VMInstanceDao;
import com.googlecode.ipv6.IPv6Address; import com.googlecode.ipv6.IPv6Address;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import static com.cloud.configuration.ConfigurationManager.MESSAGE_DELETE_VLAN_IP_RANGE_EVENT;
/** /**
* NetworkManagerImpl implements NetworkManager. * NetworkManagerImpl implements NetworkManager.
*/ */
@ -3324,17 +3326,17 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
final NetworkVO networkFinal = network; final NetworkVO networkFinal = network;
try { try {
Transaction.execute(new TransactionCallbackNoReturn() { final List<VlanVO> deletedVlanRangeToPublish = Transaction.execute(new TransactionCallback<List<VlanVO>>() {
@Override @Override
public void doInTransactionWithoutResult(final TransactionStatus status) { public List<VlanVO> doInTransaction(TransactionStatus status) {
final NetworkGuru guru = AdapterBase.getAdapterByName(networkGurus, networkFinal.getGuruName()); final NetworkGuru guru = AdapterBase.getAdapterByName(networkGurus, networkFinal.getGuruName());
if (!guru.trash(networkFinal, _networkOfferingDao.findById(networkFinal.getNetworkOfferingId()))) { if (!guru.trash(networkFinal, _networkOfferingDao.findById(networkFinal.getNetworkOfferingId()))) {
throw new CloudRuntimeException("Failed to trash network."); throw new CloudRuntimeException("Failed to trash network.");
} }
Pair<Boolean, List<VlanVO>> deletedVlans = deleteVlansInNetwork(networkFinal, context.getCaller().getId(), callerAccount);
if (!deleteVlansInNetwork(networkFinal, context.getCaller().getId(), callerAccount)) { if (!deletedVlans.first()) {
logger.warn("Failed to delete network {}; was unable to cleanup corresponding ip ranges", networkFinal); logger.warn("Failed to delete network " + networkFinal + "; was unable to cleanup corresponding ip ranges");
throw new CloudRuntimeException("Failed to delete network " + networkFinal + "; was unable to cleanup corresponding ip ranges"); throw new CloudRuntimeException("Failed to delete network " + networkFinal + "; was unable to cleanup corresponding ip ranges");
} else { } else {
// commit transaction only when ips and vlans for the network are released successfully // commit transaction only when ips and vlans for the network are released successfully
@ -3367,8 +3369,10 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
_resourceLimitMgr.decrementResourceCount(networkFinal.getAccountId(), ResourceType.network, networkFinal.getDisplayNetwork()); _resourceLimitMgr.decrementResourceCount(networkFinal.getAccountId(), ResourceType.network, networkFinal.getDisplayNetwork());
} }
} }
return deletedVlans.second();
} }
}); });
publishDeletedVlanRanges(deletedVlanRangeToPublish);
if (_networksDao.findById(network.getId()) == null) { if (_networksDao.findById(network.getId()) == null) {
// remove its related ACL permission // remove its related ACL permission
final Pair<Class<?>, Long> networkMsg = new Pair<Class<?>, Long>(Network.class, networkFinal.getId()); final Pair<Class<?>, Long> networkMsg = new Pair<Class<?>, Long>(Network.class, networkFinal.getId());
@ -3386,6 +3390,14 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
return success; return success;
} }
private void publishDeletedVlanRanges(List<VlanVO> deletedVlanRangeToPublish) {
if (CollectionUtils.isNotEmpty(deletedVlanRangeToPublish)) {
for (VlanVO vlan : deletedVlanRangeToPublish) {
_messageBus.publish(_name, MESSAGE_DELETE_VLAN_IP_RANGE_EVENT, PublishScope.LOCAL, vlan);
}
}
}
@Override @Override
public boolean resourceCountNeedsUpdate(final NetworkOffering ntwkOff, final ACLType aclType) { public boolean resourceCountNeedsUpdate(final NetworkOffering ntwkOff, final ACLType aclType) {
//Update resource count only for Isolated account specific non-system networks //Update resource count only for Isolated account specific non-system networks
@ -3393,15 +3405,19 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
return updateResourceCount; return updateResourceCount;
} }
protected boolean deleteVlansInNetwork(final NetworkVO network, final long userId, final Account callerAccount) { protected Pair<Boolean, List<VlanVO>> deleteVlansInNetwork(final NetworkVO network, final long userId, final Account callerAccount) {
final long networkId = network.getId(); final long networkId = network.getId();
//cleanup Public vlans //cleanup Public vlans
final List<VlanVO> publicVlans = _vlanDao.listVlansByNetworkId(networkId); final List<VlanVO> publicVlans = _vlanDao.listVlansByNetworkId(networkId);
List<VlanVO> deletedPublicVlanRange = new ArrayList<>();
boolean result = true; boolean result = true;
for (final VlanVO vlan : publicVlans) { for (final VlanVO vlan : publicVlans) {
if (!_configMgr.deleteVlanAndPublicIpRange(userId, vlan.getId(), callerAccount)) { VlanVO vlanRange = _configMgr.deleteVlanAndPublicIpRange(userId, vlan.getId(), callerAccount);
logger.warn("Failed to delete vlan {});", vlan.getId()); if (vlanRange == null) {
logger.warn("Failed to delete vlan " + vlan.getId() + ");");
result = false; result = false;
} else {
deletedPublicVlanRange.add(vlanRange);
} }
} }
@ -3421,7 +3437,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
_dcDao.releaseVnet(BroadcastDomainType.getValue(network.getBroadcastUri()), network.getDataCenterId(), _dcDao.releaseVnet(BroadcastDomainType.getValue(network.getBroadcastUri()), network.getDataCenterId(),
network.getPhysicalNetworkId(), network.getAccountId(), network.getReservationId()); network.getPhysicalNetworkId(), network.getAccountId(), network.getReservationId());
} }
return result; return new Pair<>(result, deletedPublicVlanRange);
} }
public class NetworkGarbageCollector extends ManagedContextRunnable { public class NetworkGarbageCollector extends ManagedContextRunnable {

View File

@ -5362,7 +5362,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
@Override @Override
@DB @DB
public boolean deleteVlanAndPublicIpRange(final long userId, final long vlanDbId, final Account caller) { public VlanVO deleteVlanAndPublicIpRange(final long userId, final long vlanDbId, final Account caller) {
VlanVO vlanRange = _vlanDao.findById(vlanDbId); VlanVO vlanRange = _vlanDao.findById(vlanDbId);
if (vlanRange == null) { if (vlanRange == null) {
throw new InvalidParameterValueException("Please specify a valid IP range id."); throw new InvalidParameterValueException("Please specify a valid IP range id.");
@ -5468,9 +5468,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
} }
}); });
messageBus.publish(_name, MESSAGE_DELETE_VLAN_IP_RANGE_EVENT, PublishScope.LOCAL, vlanRange); return vlanRange;
return true;
} }
@Override @Override
@ -5976,7 +5974,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
throw new InvalidParameterValueException("Please specify a valid IP range id."); throw new InvalidParameterValueException("Please specify a valid IP range id.");
} }
return deleteVlanAndPublicIpRange(CallContext.current().getCallingUserId(), vlanDbId, CallContext.current().getCallingAccount()); return deleteAndPublishVlanAndPublicIpRange(CallContext.current().getCallingUserId(), vlanDbId, CallContext.current().getCallingAccount());
}
private boolean deleteAndPublishVlanAndPublicIpRange(final long userId, final long vlanDbId, final Account caller) {
VlanVO deletedVlan = deleteVlanAndPublicIpRange(userId, vlanDbId, caller);
if (deletedVlan != null) {
messageBus.publish(_name, MESSAGE_DELETE_VLAN_IP_RANGE_EVENT, PublishScope.LOCAL, deletedVlan);
return true;
}
return false;
} }
@Override @Override

View File

@ -8044,7 +8044,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
// Detach, destroy and create the usage event for the old root volume. // Detach, destroy and create the usage event for the old root volume.
_volsDao.detachVolume(root.getId()); _volsDao.detachVolume(root.getId());
_volumeService.destroyVolume(root.getId(), caller, Volume.State.Allocated.equals(root.getState()) || expunge, false); destroyVolumeInContext(vm, Volume.State.Allocated.equals(root.getState()) || expunge, root);
if (currentTemplate.getId() != template.getId() && VirtualMachine.Type.User.equals(vm.type) && !VirtualMachineManager.ResourceCountRunningVMsonly.value()) { if (currentTemplate.getId() != template.getId() && VirtualMachine.Type.User.equals(vm.type) && !VirtualMachineManager.ResourceCountRunningVMsonly.value()) {
ServiceOfferingVO serviceOffering = serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); ServiceOfferingVO serviceOffering = serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId());

View File

@ -26,6 +26,7 @@ import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO; import com.cloud.dc.HostPodVO;
import com.cloud.dc.Pod; import com.cloud.dc.Pod;
import com.cloud.dc.Vlan; import com.cloud.dc.Vlan;
import com.cloud.dc.VlanVO;
import com.cloud.domain.Domain; import com.cloud.domain.Domain;
import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientCapacityException;
@ -515,9 +516,9 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu
* @see com.cloud.configuration.ConfigurationManager#deleteVlanAndPublicIpRange(long, long, com.cloud.user.Account) * @see com.cloud.configuration.ConfigurationManager#deleteVlanAndPublicIpRange(long, long, com.cloud.user.Account)
*/ */
@Override @Override
public boolean deleteVlanAndPublicIpRange(long userId, long vlanDbId, Account caller) { public VlanVO deleteVlanAndPublicIpRange(long userId, long vlanDbId, Account caller) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
return false; return null;
} }
/* (non-Javadoc) /* (non-Javadoc)

View File

@ -116,6 +116,7 @@ class TestEventsResource(cloudstackTestCase):
self.services["domain"], self.services["domain"],
parentdomainid=self.domain.id parentdomainid=self.domain.id
) )
self.cleanup.append(domain1)
self.services["domainid"] = domain1.id self.services["domainid"] = domain1.id
account = Account.create( account = Account.create(
@ -123,6 +124,7 @@ class TestEventsResource(cloudstackTestCase):
self.services["account"], self.services["account"],
domainid=domain1.id domainid=domain1.id
) )
self.cleanup.append(account)
account_network = Network.create( account_network = Network.create(
self.apiclient, self.apiclient,
@ -130,6 +132,7 @@ class TestEventsResource(cloudstackTestCase):
account.name, account.name,
account.domainid account.domainid
) )
self.cleanup.append(account_network)
virtual_machine = VirtualMachine.create( virtual_machine = VirtualMachine.create(
self.apiclient, self.apiclient,
self.services, self.services,
@ -138,6 +141,7 @@ class TestEventsResource(cloudstackTestCase):
networkids=account_network.id, networkids=account_network.id,
serviceofferingid=self.service_offering.id serviceofferingid=self.service_offering.id
) )
self.cleanup.append(virtual_machine)
volume = Volume.create( volume = Volume.create(
self.apiclient, self.apiclient,
self.services, self.services,
@ -146,6 +150,7 @@ class TestEventsResource(cloudstackTestCase):
domainid=account.domainid, domainid=account.domainid,
diskofferingid=self.disk_offering.id diskofferingid=self.disk_offering.id
) )
self.cleanup.append(volume)
virtual_machine.attach_volume( virtual_machine.attach_volume(
self.apiclient, self.apiclient,
volume volume
@ -157,15 +162,20 @@ class TestEventsResource(cloudstackTestCase):
time.sleep(self.services["sleep"]) time.sleep(self.services["sleep"])
virtual_machine.detach_volume(self.apiclient, volume) virtual_machine.detach_volume(self.apiclient, volume)
volume.delete(self.apiclient) volume.delete(self.apiclient)
self.cleanup.remove(volume)
ts = str(time.time()) ts = str(time.time())
virtual_machine.update(self.apiclient, displayname=ts) virtual_machine.update(self.apiclient, displayname=ts)
virtual_machine.delete(self.apiclient) virtual_machine.delete(self.apiclient)
self.cleanup.remove(virtual_machine)
account_network.update(self.apiclient, name=account_network.name + ts) account_network.update(self.apiclient, name=account_network.name + ts)
account_network.delete(self.apiclient) account_network.delete(self.apiclient)
self.cleanup.remove(account_network)
account.update(self.apiclient, newname=account.name + ts) account.update(self.apiclient, newname=account.name + ts)
account.disable(self.apiclient) account.disable(self.apiclient)
account.delete(self.apiclient) account.delete(self.apiclient)
self.cleanup.remove(account)
domain1.delete(self.apiclient) domain1.delete(self.apiclient)
self.cleanup.remove(domain1)
cmd = listEvents.listEventsCmd() cmd = listEvents.listEventsCmd()
cmd.startdate = start_time cmd.startdate = start_time
@ -185,8 +195,9 @@ class TestEventsResource(cloudstackTestCase):
for event in events: for event in events:
if event.type.startswith("VM.") or (event.type.startswith("NETWORK.") and not event.type.startswith("NETWORK.ELEMENT")) or event.type.startswith("VOLUME.") or event.type.startswith("ACCOUNT.") or event.type.startswith("DOMAIN.") or event.type.startswith("TEMPLATE."): if event.type.startswith("VM.") or (event.type.startswith("NETWORK.") and not event.type.startswith("NETWORK.ELEMENT")) or event.type.startswith("VOLUME.") or event.type.startswith("ACCOUNT.") or event.type.startswith("DOMAIN.") or event.type.startswith("TEMPLATE."):
if event.resourceid is None or event.resourcetype is None: if event.resourceid is None or event.resourcetype is None:
self.debug("Failed event:: %s" % json.dumps(event, indent=2)) event_json = json.dumps(event.__dict__, indent=2)
self.fail("resourceid or resourcetype for the event not found!") self.debug("Failed event:: %s" % event_json)
self.fail("resourceid or resourcetype not found for the event: %s" % event_json)
else: else:
self.debug("Event %s at %s:: Resource Type: %s, Resource ID: %s" % (event.type, event.created, event.resourcetype, event.resourceid)) self.debug("Event %s at %s:: Resource Type: %s, Resource ID: %s" % (event.type, event.created, event.resourcetype, event.resourceid))

View File

@ -626,7 +626,7 @@ export default {
name: 'autoscalevmgroup', name: 'autoscalevmgroup',
title: 'label.autoscale.vm.groups', title: 'label.autoscale.vm.groups',
icon: 'fullscreen-outlined', icon: 'fullscreen-outlined',
docHelp: 'adminguide/autoscale_without_netscaler.html', docHelp: 'adminguide/autoscale_with_virtual_router.html',
resourceType: 'AutoScaleVmGroup', resourceType: 'AutoScaleVmGroup',
permission: ['listAutoScaleVmGroups'], permission: ['listAutoScaleVmGroups'],
columns: (store) => { columns: (store) => {

View File

@ -177,7 +177,8 @@ export default {
isdynamicallyscalable: this.resource.isdynamicallyscalable, isdynamicallyscalable: this.resource.isdynamicallyscalable,
group: this.resource.group, group: this.resource.group,
securitygroupids: this.resource.securitygroup.map(x => x.id), securitygroupids: this.resource.securitygroup.map(x => x.id),
userdata: '' userdata: '',
haenable: this.resource.haenable
}) })
this.rules = reactive({}) this.rules = reactive({})
}, },

View File

@ -202,7 +202,7 @@
<a-progress <a-progress
status="active" status="active"
:percent="parseFloat(getPercentUsed(entity[usageType + 'total'], entity[usageType + 'limit']))" :percent="parseFloat(getPercentUsed(entity[usageType + 'total'], entity[usageType + 'limit']))"
:format="p => resource[item + 'limit'] !== '-1' && resource[item + 'limit'] !== 'Unlimited' ? p.toFixed(0) + '%' : ''" :format="p => entity[usageType + 'limit'] !== '-1' && entity[usageType + 'limit'] !== 'Unlimited' ? p.toFixed(0) + '%' : ''"
stroke-color="#52c41a" stroke-color="#52c41a"
size="small" size="small"
/> />
@ -238,7 +238,7 @@
<a-progress <a-progress
status="active" status="active"
:percent="parseFloat(getPercentUsed(entity[usageType + 'total'], entity[usageType + 'limit']))" :percent="parseFloat(getPercentUsed(entity[usageType + 'total'], entity[usageType + 'limit']))"
:format="p => resource[item + 'limit'] !== '-1' && resource[item + 'limit'] !== 'Unlimited' ? p.toFixed(0) + '%' : ''" :format="p => entity[usageType + 'limit'] !== '-1' && entity[usageType + 'limit'] !== 'Unlimited' ? p.toFixed(0) + '%' : ''"
stroke-color="#52c41a" stroke-color="#52c41a"
size="small" size="small"
/> />
@ -274,7 +274,7 @@
<a-progress <a-progress
status="active" status="active"
:percent="parseFloat(getPercentUsed(entity[usageType + 'total'], entity[usageType + 'limit']))" :percent="parseFloat(getPercentUsed(entity[usageType + 'total'], entity[usageType + 'limit']))"
:format="p => resource[item + 'limit'] !== '-1' && resource[item + 'limit'] !== 'Unlimited' ? p.toFixed(0) + '%' : ''" :format="p => entity[usageType + 'limit'] !== '-1' && entity[usageType + 'limit'] !== 'Unlimited' ? p.toFixed(0) + '%' : ''"
stroke-color="#52c41a" stroke-color="#52c41a"
size="small" size="small"
/> />