From 6b4955affe9f9658eb8128b3b7d18f08a1f05752 Mon Sep 17 00:00:00 2001 From: Vishesh Date: Tue, 7 May 2024 13:27:31 +0530 Subject: [PATCH 01/25] Fix message publish in transaction (#8980) * Fix message publish in transaction * Resolve comments --- .../configuration/ConfigurationManager.java | 3 +- .../orchestration/NetworkOrchestrator.java | 30 ++++++++++++++----- .../ConfigurationManagerImpl.java | 17 +++++++---- .../vpc/MockConfigurationManagerImpl.java | 5 ++-- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java b/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java index 0232d07b8be..728511ba8d5 100644 --- a/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java +++ b/engine/components-api/src/main/java/com/cloud/configuration/ConfigurationManager.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.cloud.dc.VlanVO; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.impl.ConfigurationSubGroupVO; @@ -189,7 +190,7 @@ public interface ConfigurationManager { * @param caller TODO * @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); diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index c49a0fd09b1..09500051df6 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -255,6 +255,8 @@ import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; import com.googlecode.ipv6.IPv6Address; +import static com.cloud.configuration.ConfigurationManager.MESSAGE_DELETE_VLAN_IP_RANGE_EVENT; + /** * NetworkManagerImpl implements NetworkManager. */ @@ -3298,16 +3300,16 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra final NetworkVO networkFinal = network; try { - Transaction.execute(new TransactionCallbackNoReturn() { + final List deletedVlanRangeToPublish = Transaction.execute(new TransactionCallback>() { @Override - public void doInTransactionWithoutResult(final TransactionStatus status) { + public List doInTransaction(TransactionStatus status) { final NetworkGuru guru = AdapterBase.getAdapterByName(networkGurus, networkFinal.getGuruName()); if (!guru.trash(networkFinal, _networkOfferingDao.findById(networkFinal.getNetworkOfferingId()))) { throw new CloudRuntimeException("Failed to trash network."); } - - if (!deleteVlansInNetwork(networkFinal, context.getCaller().getId(), callerAccount)) { + Pair> deletedVlans = deleteVlansInNetwork(networkFinal, context.getCaller().getId(), callerAccount); + if (!deletedVlans.first()) { s_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"); } else { @@ -3341,8 +3343,10 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra _resourceLimitMgr.decrementResourceCount(networkFinal.getAccountId(), ResourceType.network, networkFinal.getDisplayNetwork()); } } + return deletedVlans.second(); } }); + publishDeletedVlanRanges(deletedVlanRangeToPublish); if (_networksDao.findById(network.getId()) == null) { // remove its related ACL permission final Pair, Long> networkMsg = new Pair, Long>(Network.class, networkFinal.getId()); @@ -3360,6 +3364,14 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra return success; } + private void publishDeletedVlanRanges(List deletedVlanRangeToPublish) { + if (CollectionUtils.isNotEmpty(deletedVlanRangeToPublish)) { + for (VlanVO vlan : deletedVlanRangeToPublish) { + _messageBus.publish(_name, MESSAGE_DELETE_VLAN_IP_RANGE_EVENT, PublishScope.LOCAL, vlan); + } + } + } + @Override public boolean resourceCountNeedsUpdate(final NetworkOffering ntwkOff, final ACLType aclType) { //Update resource count only for Isolated account specific non-system networks @@ -3367,15 +3379,19 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra return updateResourceCount; } - protected boolean deleteVlansInNetwork(final NetworkVO network, final long userId, final Account callerAccount) { + protected Pair> deleteVlansInNetwork(final NetworkVO network, final long userId, final Account callerAccount) { final long networkId = network.getId(); //cleanup Public vlans final List publicVlans = _vlanDao.listVlansByNetworkId(networkId); + List deletedPublicVlanRange = new ArrayList<>(); boolean result = true; for (final VlanVO vlan : publicVlans) { - if (!_configMgr.deleteVlanAndPublicIpRange(userId, vlan.getId(), callerAccount)) { + VlanVO vlanRange = _configMgr.deleteVlanAndPublicIpRange(userId, vlan.getId(), callerAccount); + if (vlanRange == null) { s_logger.warn("Failed to delete vlan " + vlan.getId() + ");"); result = false; + } else { + deletedPublicVlanRange.add(vlanRange); } } @@ -3395,7 +3411,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra _dcDao.releaseVnet(BroadcastDomainType.getValue(network.getBroadcastUri()), network.getDataCenterId(), network.getPhysicalNetworkId(), network.getAccountId(), network.getReservationId()); } - return result; + return new Pair<>(result, deletedPublicVlanRange); } public class NetworkGarbageCollector extends ManagedContextRunnable { diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index 18355a47fe1..b59c8d018ee 100644 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -5348,7 +5348,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override @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); if (vlanRange == null) { throw new InvalidParameterValueException("Please specify a valid IP range id."); @@ -5454,9 +5454,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } }); - messageBus.publish(_name, MESSAGE_DELETE_VLAN_IP_RANGE_EVENT, PublishScope.LOCAL, vlanRange); - - return true; + return vlanRange; } @Override @@ -5962,7 +5960,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati 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 diff --git a/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java b/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java index 8c6e73fcf70..eb314b7cb5d 100644 --- a/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java +++ b/server/src/test/java/com/cloud/vpc/MockConfigurationManagerImpl.java @@ -26,6 +26,7 @@ import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; import com.cloud.dc.Pod; import com.cloud.dc.Vlan; +import com.cloud.dc.VlanVO; import com.cloud.domain.Domain; import com.cloud.exception.ConcurrentOperationException; 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) */ @Override - public boolean deleteVlanAndPublicIpRange(long userId, long vlanDbId, Account caller) { + public VlanVO deleteVlanAndPublicIpRange(long userId, long vlanDbId, Account caller) { // TODO Auto-generated method stub - return false; + return null; } /* (non-Javadoc) From a0f87187da1ef922755833d348775308dc0d3d72 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 7 May 2024 16:07:14 +0530 Subject: [PATCH 02/25] ui: fix documentation link for VM autoscaling (#9044) Existing link directs to an older documentation. Signed-off-by: Abhishek Kumar --- ui/src/config/section/compute.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js index 7a0644ba98f..ba3a21e1539 100644 --- a/ui/src/config/section/compute.js +++ b/ui/src/config/section/compute.js @@ -626,7 +626,7 @@ export default { name: 'autoscalevmgroup', title: 'label.autoscale.vm.groups', icon: 'fullscreen-outlined', - docHelp: 'adminguide/autoscale_without_netscaler.html', + docHelp: 'adminguide/autoscale_with_virtual_router.html', resourceType: 'AutoScaleVmGroup', permission: ['listAutoScaleVmGroups'], columns: (store) => { From ea9a0f4adf81b92abd7eddc4a6be57a131ef001b Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 8 May 2024 11:52:53 +0530 Subject: [PATCH 03/25] ui: fix haenable in edit vm form (#9049) Fixes #8150 Signed-off-by: Abhishek Kumar --- ui/src/views/compute/EditVM.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/src/views/compute/EditVM.vue b/ui/src/views/compute/EditVM.vue index 3601901252b..550c4645ed6 100644 --- a/ui/src/views/compute/EditVM.vue +++ b/ui/src/views/compute/EditVM.vue @@ -177,7 +177,8 @@ export default { isdynamicallyscalable: this.resource.isdynamicallyscalable, group: this.resource.group, securitygroupids: this.resource.securitygroup.map(x => x.id), - userdata: '' + userdata: '', + haenable: this.resource.haenable }) this.rules = reactive({}) }, From f0df8d7831ae13f8ef8411dfbaae12041e4590bc Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 20 May 2024 14:45:01 +0530 Subject: [PATCH 04/25] ui: fix limit format (#9060) An undefined variable `item` was used. Signed-off-by: Abhishek Kumar --- ui/src/views/dashboard/UsageDashboard.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/src/views/dashboard/UsageDashboard.vue b/ui/src/views/dashboard/UsageDashboard.vue index e9edd0cfb6e..fe835cbd0d0 100644 --- a/ui/src/views/dashboard/UsageDashboard.vue +++ b/ui/src/views/dashboard/UsageDashboard.vue @@ -202,7 +202,7 @@ @@ -238,7 +238,7 @@ @@ -274,7 +274,7 @@ From 33659fdf06911f6427ea3b81cb0d377e47d3b973 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Wed, 22 May 2024 14:32:14 +0530 Subject: [PATCH 05/25] server,test: fix resourceid for VOLUME.DETROY in restore VM (#9032) Signed-off-by: Abhishek Kumar --- .../main/java/com/cloud/vm/UserVmManagerImpl.java | 2 +- test/integration/smoke/test_events_resource.py | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 4283b44e171..3c172051463 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -7909,7 +7909,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir // Detach, destroy and create the usage event for the old root volume. _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); // For VMware hypervisor since the old root volume is replaced by the new root volume, force expunge old root volume if it has been created in storage if (vm.getHypervisorType() == HypervisorType.VMware) { diff --git a/test/integration/smoke/test_events_resource.py b/test/integration/smoke/test_events_resource.py index 660cbd37bce..79443110950 100644 --- a/test/integration/smoke/test_events_resource.py +++ b/test/integration/smoke/test_events_resource.py @@ -116,6 +116,7 @@ class TestEventsResource(cloudstackTestCase): self.services["domain"], parentdomainid=self.domain.id ) + self.cleanup.append(domain1) self.services["domainid"] = domain1.id account = Account.create( @@ -123,6 +124,7 @@ class TestEventsResource(cloudstackTestCase): self.services["account"], domainid=domain1.id ) + self.cleanup.append(account) account_network = Network.create( self.apiclient, @@ -130,6 +132,7 @@ class TestEventsResource(cloudstackTestCase): account.name, account.domainid ) + self.cleanup.append(account_network) virtual_machine = VirtualMachine.create( self.apiclient, self.services, @@ -138,6 +141,7 @@ class TestEventsResource(cloudstackTestCase): networkids=account_network.id, serviceofferingid=self.service_offering.id ) + self.cleanup.append(virtual_machine) volume = Volume.create( self.apiclient, self.services, @@ -146,6 +150,7 @@ class TestEventsResource(cloudstackTestCase): domainid=account.domainid, diskofferingid=self.disk_offering.id ) + self.cleanup.append(volume) virtual_machine.attach_volume( self.apiclient, volume @@ -157,15 +162,20 @@ class TestEventsResource(cloudstackTestCase): time.sleep(self.services["sleep"]) virtual_machine.detach_volume(self.apiclient, volume) volume.delete(self.apiclient) + self.cleanup.remove(volume) ts = str(time.time()) virtual_machine.update(self.apiclient, displayname=ts) virtual_machine.delete(self.apiclient) + self.cleanup.remove(virtual_machine) account_network.update(self.apiclient, name=account_network.name + ts) account_network.delete(self.apiclient) + self.cleanup.remove(account_network) account.update(self.apiclient, newname=account.name + ts) account.disable(self.apiclient) account.delete(self.apiclient) + self.cleanup.remove(account) domain1.delete(self.apiclient) + self.cleanup.remove(domain1) cmd = listEvents.listEventsCmd() cmd.startdate = start_time @@ -185,8 +195,9 @@ class TestEventsResource(cloudstackTestCase): 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.resourceid is None or event.resourcetype is None: - self.debug("Failed event:: %s" % json.dumps(event, indent=2)) - self.fail("resourceid or resourcetype for the event not found!") + event_json = json.dumps(event.__dict__, indent=2) + self.debug("Failed event:: %s" % event_json) + self.fail("resourceid or resourcetype not found for the event: %s" % event_json) else: self.debug("Event %s at %s:: Resource Type: %s, Resource ID: %s" % (event.type, event.created, event.resourcetype, event.resourceid)) From c6762f1a41d8076b26a36cb4123c5538decf93fa Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 23 May 2024 16:04:32 +0530 Subject: [PATCH 06/25] ui: fix projectrolepermissions listing with description (#9091) Signed-off-by: Abhishek Kumar --- ui/src/views/project/iam/ProjectRolePermissionTab.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/views/project/iam/ProjectRolePermissionTab.vue b/ui/src/views/project/iam/ProjectRolePermissionTab.vue index 7b24098a5e9..dd628d780e6 100644 --- a/ui/src/views/project/iam/ProjectRolePermissionTab.vue +++ b/ui/src/views/project/iam/ProjectRolePermissionTab.vue @@ -78,7 +78,7 @@
{{ $t('message.no.description') }} From daf6b9d1030188bb129e44e2cdd7a4f65a2bbb0f Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 24 May 2024 21:09:52 +0530 Subject: [PATCH 07/25] api,ui: vm template format, fix vm info link (#9094) --- .../apache/cloudstack/api/ApiConstants.java | 1 + .../api/response/UserVmResponse.java | 12 ++++++ .../META-INF/db/views/cloud.user_vm_view.sql | 1 + .../api/query/dao/UserVmJoinDaoImpl.java | 1 + .../com/cloud/api/query/vo/UserVmJoinVO.java | 8 ++++ .../api/query/dao/UserVmJoinDaoImplTest.java | 38 ++++++++++--------- ui/src/components/view/InfoCard.vue | 2 +- 7 files changed, 44 insertions(+), 19 deletions(-) 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 b5fab14ccb6..7565b679e58 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -448,6 +448,7 @@ public class ApiConstants { public static final String TEMPLATE_IDS = "templateids"; public static final String TEMPLATE_NAME = "templatename"; public static final String TEMPLATE_TYPE = "templatetype"; + public static final String TEMPLATE_FORMAT = "templateformat"; public static final String TIMEOUT = "timeout"; public static final String TIMEZONE = "timezone"; public static final String TIMEZONEOFFSET = "timezoneoffset"; diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java index 763265e109d..5a0ea77a4e7 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java @@ -137,6 +137,10 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co @Param(description = "the type of the template for the virtual machine", since = "4.19.0") private String templateType; + @SerializedName(ApiConstants.TEMPLATE_FORMAT) + @Param(description = "the format of the template for the virtual machine", since = "4.19.1") + private String templateFormat; + @SerializedName("templatedisplaytext") @Param(description = " an alternate display text of the template for the virtual machine") private String templateDisplayText; @@ -1076,6 +1080,14 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co this.templateType = templateType; } + public String getTemplateFormat() { + return templateFormat; + } + + public void setTemplateFormat(String templateFormat) { + this.templateFormat = templateFormat; + } + public List getVnfNics() { return vnfNics; } diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.user_vm_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.user_vm_view.sql index 7a057dc0330..25f95709721 100644 --- a/engine/schema/src/main/resources/META-INF/db/views/cloud.user_vm_view.sql +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.user_vm_view.sql @@ -74,6 +74,7 @@ SELECT `vm_template`.`uuid` AS `template_uuid`, `vm_template`.`name` AS `template_name`, `vm_template`.`type` AS `template_type`, + `vm_template`.`format` AS `template_format`, `vm_template`.`display_text` AS `template_display_text`, `vm_template`.`enable_password` AS `password_enabled`, `iso`.`id` AS `iso_id`, diff --git a/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java index e5cc9ee7234..828cafd7d50 100644 --- a/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/UserVmJoinDaoImpl.java @@ -198,6 +198,7 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation { @@ -109,6 +110,7 @@ public class UserVmJoinDaoImplTest extends GenericDaoBaseWithTagInformationBaseT Mockito.when(userVmMock.getId()).thenReturn(vmId); Mockito.when(userVmMock.getTemplateId()).thenReturn(templateId); Mockito.when(userVmMock.getTemplateType()).thenReturn(Storage.TemplateType.VNF); + Mockito.when(userVmMock.getTemplateFormat()).thenReturn(Storage.ImageFormat.OVA); Mockito.when(caller.getId()).thenReturn(2L); Mockito.when(accountMgr.isRootAdmin(nullable(Long.class))).thenReturn(true); diff --git a/ui/src/components/view/InfoCard.vue b/ui/src/components/view/InfoCard.vue index 66c878da0f8..a4fa1191d13 100644 --- a/ui/src/components/view/InfoCard.vue +++ b/ui/src/components/view/InfoCard.vue @@ -524,7 +524,7 @@
- {{ resource.templatedisplaytext || resource.templatename || resource.templateid }} + {{ resource.templatedisplaytext || resource.templatename || resource.templateid }}
From e817e04343a3c91696625211b59d916125366fc1 Mon Sep 17 00:00:00 2001 From: Hans Rakers Date: Fri, 24 May 2024 17:41:02 +0200 Subject: [PATCH 08/25] Fix typo keyparis -> keypairs in InvalidParameterValueException (#9100) --- server/src/main/java/com/cloud/vm/UserVmManagerImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index a5a8f07546b..a03aeac9967 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -1012,7 +1012,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } if (cmd.getNames() == null || cmd.getNames().isEmpty()) { - throw new InvalidParameterValueException("'keypair' or 'keyparis' must be specified"); + throw new InvalidParameterValueException("'keypair' or 'keypairs' must be specified"); } String keypairnames = ""; @@ -1021,7 +1021,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir pairs = _sshKeyPairDao.findByNames(owner.getAccountId(), owner.getDomainId(), cmd.getNames()); if (pairs == null || pairs.size() != cmd.getNames().size()) { - throw new InvalidParameterValueException("Not all specified keyparis exist"); + throw new InvalidParameterValueException("Not all specified keypairs exist"); } sshPublicKeys = pairs.stream().map(p -> p.getPublicKey()).collect(Collectors.joining("\n")); keypairnames = String.join(",", cmd.getNames()); @@ -4209,7 +4209,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir if (!sshKeyPairs.isEmpty()) { List pairs = _sshKeyPairDao.findByNames(owner.getAccountId(), owner.getDomainId(), sshKeyPairs); if (pairs == null || pairs.size() != sshKeyPairs.size()) { - throw new InvalidParameterValueException("Not all specified keyparis exist"); + throw new InvalidParameterValueException("Not all specified keypairs exist"); } sshPublicKeys = pairs.stream().map(p -> p.getPublicKey()).collect(Collectors.joining("\n")); From 2d4d370be802e4363326932b8741e0bd6743ff5e Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 24 May 2024 21:18:27 +0530 Subject: [PATCH 09/25] ui: support isdynamicallyscalable param for iso (#9092) Register/List/Update iso APIs already support isdynamicallyscalable parama. This PR makes them available in the UI. Signed-off-by: Abhishek Kumar --- ui/src/config/section/image.js | 2 +- ui/src/views/image/RegisterOrUploadIso.vue | 59 +++++++++++++--------- ui/src/views/image/UpdateISO.vue | 8 ++- 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/ui/src/config/section/image.js b/ui/src/config/section/image.js index 7a5d52d1b89..aa21b262037 100644 --- a/ui/src/config/section/image.js +++ b/ui/src/config/section/image.js @@ -231,7 +231,7 @@ export default { } return fields }, - details: ['name', 'id', 'displaytext', 'checksum', 'ostypename', 'size', 'bootable', 'isready', 'directdownload', 'isextractable', 'ispublic', 'isfeatured', 'crosszones', 'account', 'domain', 'created', 'userdatadetails', 'userdatapolicy', 'url'], + details: ['name', 'id', 'displaytext', 'checksum', 'ostypename', 'size', 'bootable', 'isready', 'directdownload', 'isextractable', 'ispublic', 'isfeatured', 'isdynamicallyscalable', 'crosszones', 'account', 'domain', 'created', 'userdatadetails', 'userdatapolicy', 'url'], searchFilters: () => { var filters = ['name', 'zoneid', 'tags'] if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { diff --git a/ui/src/views/image/RegisterOrUploadIso.vue b/ui/src/views/image/RegisterOrUploadIso.vue index 1a461ee6bf6..f27676b8e7f 100644 --- a/ui/src/views/image/RegisterOrUploadIso.vue +++ b/ui/src/views/image/RegisterOrUploadIso.vue @@ -227,29 +227,39 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + +
{{ $t('label.cancel') }} @@ -332,7 +342,8 @@ export default { this.form = reactive({ bootable: true, isextractable: false, - ispublic: false + ispublic: false, + isdynamicallyscalable: false }) this.rules = reactive({ url: [{ required: true, message: this.$t('label.upload.iso.from.local') }], diff --git a/ui/src/views/image/UpdateISO.vue b/ui/src/views/image/UpdateISO.vue index 4d7140df165..92386823c16 100644 --- a/ui/src/views/image/UpdateISO.vue +++ b/ui/src/views/image/UpdateISO.vue @@ -61,6 +61,12 @@ + + + + @@ -162,7 +168,7 @@ export default { displaytext: [{ required: true, message: this.$t('message.error.required.input') }], ostypeid: [{ required: true, message: this.$t('message.error.select') }] }) - const resourceFields = ['name', 'displaytext', 'ostypeid', 'userdataid', 'userdatapolicy'] + const resourceFields = ['name', 'displaytext', 'ostypeid', 'isdynamicallyscalable', 'userdataid', 'userdatapolicy'] for (var field of resourceFields) { var fieldValue = this.resource[field] From 57e67afdf0da26c35f754ba55f4b8ecf401172fc Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 27 May 2024 13:47:44 +0530 Subject: [PATCH 10/25] api,server: list autoscalevmgroups with keyword (#9046) Fixes #9042 Signed-off-by: Abhishek Kumar --- .../main/java/com/cloud/network/as/AutoScaleManagerImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java b/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java index c10ff89fa3d..468f238a0c5 100644 --- a/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java +++ b/server/src/main/java/com/cloud/network/as/AutoScaleManagerImpl.java @@ -1174,6 +1174,7 @@ public class AutoScaleManagerImpl extends ManagerBase implements AutoScaleManage Long profileId = cmd.getProfileId(); Long zoneId = cmd.getZoneId(); Boolean forDisplay = cmd.getDisplay(); + String keyword = cmd.getKeyword(); SearchWrapper searchWrapper = new SearchWrapper<>(autoScaleVmGroupDao, AutoScaleVmGroupVO.class, cmd, cmd.getId()); SearchBuilder sb = searchWrapper.getSearchBuilder(); @@ -1184,6 +1185,7 @@ public class AutoScaleManagerImpl extends ManagerBase implements AutoScaleManage sb.and("profileId", sb.entity().getProfileId(), SearchCriteria.Op.EQ); sb.and("zoneId", sb.entity().getZoneId(), SearchCriteria.Op.EQ); sb.and("display", sb.entity().isDisplay(), SearchCriteria.Op.EQ); + sb.and("keyword", sb.entity().getName(), SearchCriteria.Op.LIKE); if (policyId != null) { SearchBuilder asVmGroupPolicySearch = autoScaleVmGroupPolicyMapDao.createSearchBuilder(); @@ -1213,6 +1215,9 @@ public class AutoScaleManagerImpl extends ManagerBase implements AutoScaleManage if (forDisplay != null) { sc.setParameters("display", forDisplay); } + if (StringUtils.isNotBlank(keyword)) { + sc.setParameters("keyword", "%" + keyword + "%"); + } return searchWrapper.search(); } From 371ce12abeffa82511cf06d55d6dc548763251c2 Mon Sep 17 00:00:00 2001 From: Fabricio Duarte Date: Mon, 27 May 2024 12:06:52 -0300 Subject: [PATCH 11/25] Normalize dates in Usage and Quota APIs (#8243) * Normalize dates in Usage and Quota APIs * Apply Daan's sugestions Co-authored-by: dahn * Restore removed sinces * Add missing space * Change param descriptions for quotaBalance and quotaStatement * Apply Daniel's suggestions Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com> --------- Co-authored-by: dahn Co-authored-by: Daniel Augusto Veronezi Salvador <38945620+GutoVeronezi@users.noreply.github.com> --- .../apache/cloudstack/api/ApiConstants.java | 8 +++ .../admin/usage/ListUsageRecordsCmd.java | 20 +++--- .../api/response/UsageRecordResponse.java | 11 ++-- .../api/command/QuotaBalanceCmd.java | 6 +- .../api/command/QuotaStatementCmd.java | 6 +- .../api/command/QuotaTariffCreateCmd.java | 8 +-- .../api/command/QuotaTariffListCmd.java | 10 +-- .../api/command/QuotaTariffUpdateCmd.java | 4 +- .../response/QuotaResponseBuilderImpl.java | 22 +++---- .../api/response/QuotaTariffResponse.java | 48 +++----------- .../apache/cloudstack/quota/QuotaService.java | 2 - .../cloudstack/quota/QuotaServiceImpl.java | 62 ++++--------------- .../QuotaResponseBuilderImplTest.java | 7 +-- .../quota/QuotaServiceImplTest.java | 10 --- .../java/com/cloud/api/ApiResponseHelper.java | 4 +- .../com/cloud/usage/UsageServiceImpl.java | 38 ++---------- 16 files changed, 79 insertions(+), 187 deletions(-) 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 892903d17ac..4115d440d78 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -1142,6 +1142,14 @@ public class ApiConstants { } } + public static final String PARAMETER_DESCRIPTION_START_DATE_POSSIBLE_FORMATS = "The recommended format is \"yyyy-MM-dd'T'HH:mm:ssZ\" (e.g.: \"2023-01-01T12:00:00+0100\"); " + + "however, the following formats are also accepted: \"yyyy-MM-dd HH:mm:ss\" (e.g.: \"2023-01-01 12:00:00\") and \"yyyy-MM-dd\" (e.g.: \"2023-01-01\" - if the time is not " + + "added, it will be interpreted as \"00:00:00\"). If the recommended format is not used, the date will be considered in the server timezone."; + + public static final String PARAMETER_DESCRIPTION_END_DATE_POSSIBLE_FORMATS = "The recommended format is \"yyyy-MM-dd'T'HH:mm:ssZ\" (e.g.: \"2023-01-01T12:00:00+0100\"); " + + "however, the following formats are also accepted: \"yyyy-MM-dd HH:mm:ss\" (e.g.: \"2023-01-01 12:00:00\") and \"yyyy-MM-dd\" (e.g.: \"2023-01-01\" - if the time is not " + + "added, it will be interpreted as \"23:59:59\"). If the recommended format is not used, the date will be considered in the server timezone."; + public enum BootType { UEFI, BIOS; 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 3cb148c2af0..9ce1fcb2bc9 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 @@ -53,16 +53,12 @@ public class ListUsageRecordsCmd extends BaseListCmd { @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "List usage records for the specified domain.") private Long domainId; - @Parameter(name = ApiConstants.END_DATE, - type = CommandType.DATE, - required = true, - description = "End date range for usage record query (use format \"yyyy-MM-dd\" or the new format \"yyyy-MM-dd HH:mm:ss\", e.g. startDate=2015-01-01 or startdate=2015-01-01 10:30:00).") + @Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, required = true, description = "End date range for usage record query. " + + ApiConstants.PARAMETER_DESCRIPTION_END_DATE_POSSIBLE_FORMATS) private Date endDate; - @Parameter(name = ApiConstants.START_DATE, - type = CommandType.DATE, - required = true, - description = "Start date range for usage record query (use format \"yyyy-MM-dd\" or the new format \"yyyy-MM-dd HH:mm:ss\", e.g. startDate=2015-01-01 or startdate=2015-01-01 11:00:00).") + @Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, required = true, description = "Start date range for usage record query. " + + ApiConstants.PARAMETER_DESCRIPTION_START_DATE_POSSIBLE_FORMATS) private Date startDate; @Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "List usage records for the specified account") @@ -137,11 +133,11 @@ public class ListUsageRecordsCmd extends BaseListCmd { } public void setEndDate(Date endDate) { - this.endDate = endDate == null ? null : new Date(endDate.getTime()); + this.endDate = endDate; } public void setStartDate(Date startDate) { - this.startDate = startDate == null ? null : new Date(startDate.getTime()); + this.startDate = startDate; } public void setAccountId(Long accountId) { @@ -167,8 +163,8 @@ public class ListUsageRecordsCmd extends BaseListCmd { @Override public void execute() { Pair, Integer> usageRecords = _usageService.getUsageRecords(this); - ListResponse response = new ListResponse(); - List usageResponses = new ArrayList(); + ListResponse response = new ListResponse<>(); + List usageResponses = new ArrayList<>(); Map> resourceTagResponseMap = null; if (usageRecords != null) { //read the resource tags details for all the resources in usage data and store in Map diff --git a/api/src/main/java/org/apache/cloudstack/api/response/UsageRecordResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/UsageRecordResponse.java index 7bcb1afd2d2..4522315b499 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/UsageRecordResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/UsageRecordResponse.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.api.response; +import java.util.Date; import java.util.LinkedHashSet; import java.util.Set; @@ -133,11 +134,11 @@ public class UsageRecordResponse extends BaseResponseWithTagInformation implemen @SerializedName(ApiConstants.START_DATE) @Param(description = "start date of the usage record") - private String startDate; + private Date startDate; @SerializedName(ApiConstants.END_DATE) @Param(description = "end date of the usage record") - private String endDate; + private Date endDate; @SerializedName("issourcenat") @Param(description = "True if the IPAddress is source NAT") @@ -160,7 +161,7 @@ public class UsageRecordResponse extends BaseResponseWithTagInformation implemen private String vpcId; public UsageRecordResponse() { - tags = new LinkedHashSet(); + tags = new LinkedHashSet<>(); } public void setTags(Set tags) { @@ -245,11 +246,11 @@ public class UsageRecordResponse extends BaseResponseWithTagInformation implemen this.size = size; } - public void setStartDate(String startDate) { + public void setStartDate(Date startDate) { this.startDate = startDate; } - public void setEndDate(String endDate) { + public void setEndDate(Date endDate) { this.endDate = endDate; } diff --git a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaBalanceCmd.java b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaBalanceCmd.java index 53d82fae604..218e3c2b2f9 100644 --- a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaBalanceCmd.java +++ b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaBalanceCmd.java @@ -43,10 +43,12 @@ public class QuotaBalanceCmd extends BaseCmd { @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, description = "If domain Id is given and the caller is domain admin then the statement is generated for domain.") private Long domainId; - @Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, description = "End date range for quota query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-03.") + @Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, description = "End of the period of the Quota balance." + + ApiConstants.PARAMETER_DESCRIPTION_END_DATE_POSSIBLE_FORMATS) private Date endDate; - @Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, description = "Start date range quota query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-01.") + @Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, description = "Start of the period of the Quota balance. " + + ApiConstants.PARAMETER_DESCRIPTION_START_DATE_POSSIBLE_FORMATS) private Date startDate; @Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, description = "List usage records for the specified account") diff --git a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaStatementCmd.java b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaStatementCmd.java index cc02ed31d2d..4fb33f79672 100644 --- a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaStatementCmd.java +++ b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaStatementCmd.java @@ -45,10 +45,12 @@ public class QuotaStatementCmd extends BaseCmd { @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, description = "Optional, If domain Id is given and the caller is domain admin then the statement is generated for domain.") private Long domainId; - @Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, required = true, description = "End date range for quota query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-03.") + @Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, required = true, description = "End of the period of the Quota statement. " + + ApiConstants.PARAMETER_DESCRIPTION_END_DATE_POSSIBLE_FORMATS) private Date endDate; - @Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, required = true, description = "Start date range quota query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-01.") + @Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, required = true, description = "Start of the period of the Quota statement. " + + ApiConstants.PARAMETER_DESCRIPTION_START_DATE_POSSIBLE_FORMATS) private Date startDate; @Parameter(name = ApiConstants.TYPE, type = CommandType.INTEGER, description = "List quota usage records for the specified usage type") diff --git a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaTariffCreateCmd.java b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaTariffCreateCmd.java index ef9ffc23d13..b9406754b31 100644 --- a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaTariffCreateCmd.java +++ b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaTariffCreateCmd.java @@ -60,12 +60,12 @@ public class QuotaTariffCreateCmd extends BaseCmd { "value will be applied.", length = 65535) private String activationRule; - @Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, description = "The effective start date on/after which the quota tariff is effective. Use yyyy-MM-dd as" - + " the date format, e.g. startDate=2009-06-03. Inform null to use the current date.") + @Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, description = "The effective start date on/after which the quota tariff is effective. Inform null to " + + "use the current date. " + ApiConstants.PARAMETER_DESCRIPTION_START_DATE_POSSIBLE_FORMATS) private Date startDate; - @Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, description = "The end date of the quota tariff. Use yyyy-MM-dd as the date format, e.g." - + " endDate=2009-06-03.") + @Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, description = "The end date of the quota tariff. If not informed, the tariff will be valid indefinitely. " + + ApiConstants.PARAMETER_DESCRIPTION_END_DATE_POSSIBLE_FORMATS) private Date endDate; @Override diff --git a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaTariffListCmd.java b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaTariffListCmd.java index c47fdbfa1d8..b4e8c868e40 100644 --- a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaTariffListCmd.java +++ b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaTariffListCmd.java @@ -44,18 +44,18 @@ public class QuotaTariffListCmd extends BaseListCmd { @Parameter(name = ApiConstants.USAGE_TYPE, type = CommandType.INTEGER, description = "Usage type of the resource") private Integer usageType; - @Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, description = "The start date of the quota tariff. Use yyyy-MM-dd as the date format, " - + "e.g. startDate=2009-06-03.") + @Parameter(name = ApiConstants.START_DATE, type = CommandType.DATE, description = "The start date of the quota tariff. " + + ApiConstants.PARAMETER_DESCRIPTION_START_DATE_POSSIBLE_FORMATS) private Date effectiveDate; - @Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, description = "The end date of the quota tariff. Use yyyy-MM-dd as the date format, e.g. " - + "endDate=2021-11-03.", since = "4.18.0.0") + @Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, description = "The end date of the quota tariff. " + + ApiConstants.PARAMETER_DESCRIPTION_END_DATE_POSSIBLE_FORMATS, since = "4.18.0.0") private Date endDate; @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "The name of the quota tariff.", since = "4.18.0.0") private String name; - @Parameter(name = ApiConstants.LIST_ALL, type = CommandType.BOOLEAN, description = "False will list only not removed quota tariffs. If set to True, we will " + @Parameter(name = ApiConstants.LIST_ALL, type = CommandType.BOOLEAN, description = "False will list only not removed quota tariffs. If set to true, we will " + "list all, including the removed ones. The default is false.", since = "4.18.0.0") private boolean listAll = false; diff --git a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaTariffUpdateCmd.java b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaTariffUpdateCmd.java index 175500604d6..4fc1f08da88 100644 --- a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaTariffUpdateCmd.java +++ b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/command/QuotaTariffUpdateCmd.java @@ -52,8 +52,8 @@ public class QuotaTariffUpdateCmd extends BaseCmd { "Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-03.") private Date startDate; - @Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, description = "The end date of the quota tariff. Use yyyy-MM-dd as the date format, e.g." - + " endDate=2009-06-03.", since = "4.18.0.0") + @Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, description = "The end date of the quota tariff. " + + ApiConstants.PARAMETER_DESCRIPTION_END_DATE_POSSIBLE_FORMATS, since = "4.18.0.0") private Date endDate; @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "Quota tariff's name", length = 65535, since = "4.18.0.0") diff --git a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java index 94897b410f4..94f821828ab 100644 --- a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java +++ b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java @@ -134,7 +134,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { response.setName(tariff.getName()); response.setEndDate(tariff.getEndDate()); response.setDescription(tariff.getDescription()); - response.setUuid(tariff.getUuid()); + response.setId(tariff.getUuid()); response.setRemoved(tariff.getRemoved()); return response; } @@ -376,8 +376,8 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { @Override public Pair, Integer> listQuotaTariffPlans(final QuotaTariffListCmd cmd) { - Date startDate = _quotaService.computeAdjustedTime(cmd.getEffectiveDate()); - Date endDate = _quotaService.computeAdjustedTime(cmd.getEndDate()); + Date startDate = cmd.getEffectiveDate(); + Date endDate = cmd.getEndDate(); Integer usageType = cmd.getUsageType(); String name = cmd.getName(); boolean listAll = cmd.isListAll(); @@ -395,10 +395,10 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { public QuotaTariffVO updateQuotaTariffPlan(QuotaTariffUpdateCmd cmd) { String name = cmd.getName(); Double value = cmd.getValue(); - Date endDate = _quotaService.computeAdjustedTime(cmd.getEndDate()); + Date endDate = cmd.getEndDate(); String description = cmd.getDescription(); String activationRule = cmd.getActivationRule(); - Date now = _quotaService.computeAdjustedTime(new Date()); + Date now = new Date(); warnQuotaTariffUpdateDeprecatedFields(cmd); @@ -488,7 +488,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { endDate, startDate)); } - Date now = _quotaService.computeAdjustedTime(new Date()); + Date now = new Date(); if (endDate.compareTo(now) < 0) { throw new InvalidParameterValueException(String.format("The quota tariff's end date [%s] cannot be less than now [%s].", endDate, now)); @@ -499,7 +499,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { @Override public QuotaCreditsResponse addQuotaCredits(Long accountId, Long domainId, Double amount, Long updatedBy, Boolean enforce) { - Date despositedOn = _quotaService.computeAdjustedTime(new Date()); + Date despositedOn = new Date(); QuotaBalanceVO qb = _quotaBalanceDao.findLaterBalanceEntry(accountId, domainId, despositedOn); if (qb != null) { @@ -643,8 +643,8 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { int usageType = cmd.getUsageType(); Date startDate = cmd.getStartDate(); Date now = new Date(); - startDate = _quotaService.computeAdjustedTime(startDate == null ? now : startDate); - Date endDate = _quotaService.computeAdjustedTime(cmd.getEndDate()); + startDate = startDate == null ? now : startDate; + Date endDate = cmd.getEndDate(); Double value = cmd.getValue(); String description = cmd.getDescription(); String activationRule = cmd.getActivationRule(); @@ -675,10 +675,8 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Quota tariff with the provided UUID does not exist."); } - quotaTariff.setRemoved(_quotaService.computeAdjustedTime(new Date())); - + quotaTariff.setRemoved(new Date()); CallContext.current().setEventResourceId(quotaTariff.getId()); - return _quotaTariffDao.updateQuotaTariff(quotaTariff); } diff --git a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaTariffResponse.java b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaTariffResponse.java index ce4c5953641..cec3634c76d 100644 --- a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaTariffResponse.java +++ b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaTariffResponse.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.api.response; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import java.math.BigDecimal; @@ -74,9 +75,9 @@ public class QuotaTariffResponse extends BaseResponse { @Param(description = "description") private String description; - @SerializedName("uuid") - @Param(description = "uuid") - private String uuid; + @SerializedName(ApiConstants.ID) + @Param(description = "the ID of the tariff") + private String id; @SerializedName("removed") @Param(description = "when the quota tariff was removed") @@ -87,15 +88,6 @@ public class QuotaTariffResponse extends BaseResponse { this.setObjectName("quotatariff"); } - public QuotaTariffResponse(final int usageType) { - super(); - this.usageType = usageType; - } - - public String getUsageName() { - return usageName; - } - public void setUsageName(String usageName) { this.usageName = usageName; } @@ -108,18 +100,10 @@ public class QuotaTariffResponse extends BaseResponse { this.usageType = usageType; } - public String getUsageUnit() { - return usageUnit; - } - public void setUsageUnit(String usageUnit) { this.usageUnit = usageUnit; } - public String getUsageDiscriminator() { - return usageDiscriminator; - } - public void setUsageDiscriminator(String usageDiscriminator) { this.usageDiscriminator = usageDiscriminator; } @@ -132,26 +116,14 @@ public class QuotaTariffResponse extends BaseResponse { this.tariffValue = tariffValue; } - public String getUsageTypeDescription() { - return usageTypeDescription; - } - public void setUsageTypeDescription(String usageTypeDescription) { this.usageTypeDescription = usageTypeDescription; } - public Date getEffectiveOn() { - return effectiveOn; - } - public void setEffectiveOn(Date effectiveOn) { this.effectiveOn = effectiveOn; } - public String getCurrency() { - return currency; - } - public void setCurrency(String currency) { this.currency = currency; } @@ -188,16 +160,12 @@ public class QuotaTariffResponse extends BaseResponse { this.description = description; } - public String getUuid() { - return uuid; + public String getId() { + return id; } - public void setUuid(String uuid) { - this.uuid = uuid; - } - - public Date getRemoved() { - return removed; + public void setId(String id) { + this.id = id; } public void setRemoved(Date removed) { diff --git a/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaService.java b/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaService.java index fe634715d89..8f3c34982c0 100644 --- a/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaService.java +++ b/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaService.java @@ -32,8 +32,6 @@ public interface QuotaService extends PluggableService { List findQuotaBalanceVO(Long accountId, String accountName, Long domainId, Date startDate, Date endDate); - Date computeAdjustedTime(Date date); - void setLockAccount(Long accountId, Boolean state); void setMinBalance(Long accountId, Double balance); diff --git a/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaServiceImpl.java b/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaServiceImpl.java index da3f50b165a..4bc41233096 100644 --- a/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaServiceImpl.java +++ b/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaServiceImpl.java @@ -18,7 +18,6 @@ package org.apache.cloudstack.quota; import java.math.BigDecimal; import java.util.ArrayList; -import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Map; @@ -165,36 +164,32 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi if (endDate == null) { // adjust start date to end of day as there is no end date - Date adjustedStartDate = computeAdjustedTime(_respBldr.startOfNextDay(startDate)); + startDate = _respBldr.startOfNextDay(startDate); if (logger.isDebugEnabled()) { - logger.debug("getQuotaBalance1: Getting quota balance records for account: " + accountId + ", domainId: " + domainId + ", on or before " + adjustedStartDate); + logger.debug("getQuotaBalance1: Getting quota balance records for account: " + accountId + ", domainId: " + domainId + ", on or before " + startDate); } - List qbrecords = _quotaBalanceDao.lastQuotaBalanceVO(accountId, domainId, adjustedStartDate); + List qbrecords = _quotaBalanceDao.lastQuotaBalanceVO(accountId, domainId, startDate); if (logger.isDebugEnabled()) { logger.debug("Found records size=" + qbrecords.size()); } if (qbrecords.isEmpty()) { - logger.info("Incorrect Date there are no quota records before this date " + adjustedStartDate); + logger.info("Incorrect Date there are no quota records before this date " + startDate); return qbrecords; } else { return qbrecords; } } else { - Date adjustedStartDate = computeAdjustedTime(startDate); - if (endDate.after(_respBldr.startOfNextDay())) { - throw new InvalidParameterValueException("Incorrect Date Range. End date:" + endDate + " should not be in future. "); - } else if (startDate.before(endDate)) { - Date adjustedEndDate = computeAdjustedTime(endDate); + if (startDate.before(endDate)) { if (logger.isDebugEnabled()) { - logger.debug("getQuotaBalance2: Getting quota balance records for account: " + accountId + ", domainId: " + domainId + ", between " + adjustedStartDate - + " and " + adjustedEndDate); + logger.debug("getQuotaBalance2: Getting quota balance records for account: " + accountId + ", domainId: " + domainId + ", between " + startDate + + " and " + endDate); } - List qbrecords = _quotaBalanceDao.findQuotaBalance(accountId, domainId, adjustedStartDate, adjustedEndDate); + List qbrecords = _quotaBalanceDao.findQuotaBalance(accountId, domainId, startDate, endDate); if (logger.isDebugEnabled()) { logger.debug("getQuotaBalance3: Found records size=" + qbrecords.size()); } if (qbrecords.isEmpty()) { - logger.info("There are no quota records between these dates start date " + adjustedStartDate + " and end date:" + endDate); + logger.info("There are no quota records between these dates start date " + startDate + " and end date:" + endDate); return qbrecords; } else { return qbrecords; @@ -230,44 +225,11 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi if (startDate.after(endDate)) { throw new InvalidParameterValueException("Incorrect Date Range. Start date: " + startDate + " is after end date:" + endDate); } - if (endDate.after(_respBldr.startOfNextDay())) { - throw new InvalidParameterValueException("Incorrect Date Range. End date:" + endDate + " should not be in future. "); - } - Date adjustedEndDate = computeAdjustedTime(endDate); - Date adjustedStartDate = computeAdjustedTime(startDate); - if (logger.isDebugEnabled()) { - logger.debug("Getting quota records for account: " + accountId + ", domainId: " + domainId + ", between " + adjustedStartDate + " and " + adjustedEndDate); - } - return _quotaUsageDao.findQuotaUsage(accountId, domainId, usageType, adjustedStartDate, adjustedEndDate); - } - @Override - public Date computeAdjustedTime(final Date date) { - if (date == null) { - return null; - } + logger.debug("Getting quota records of type [{}] for account [{}] in domain [{}], between [{}] and [{}].", + usageType, accountId, domainId, startDate, endDate); - Calendar cal = Calendar.getInstance(); - cal.setTime(date); - TimeZone localTZ = cal.getTimeZone(); - int timezoneOffset = cal.get(Calendar.ZONE_OFFSET); - if (localTZ.inDaylightTime(date)) { - timezoneOffset += (60 * 60 * 1000); - } - cal.add(Calendar.MILLISECOND, timezoneOffset); - - Date newTime = cal.getTime(); - - Calendar calTS = Calendar.getInstance(_usageTimezone); - calTS.setTime(newTime); - timezoneOffset = calTS.get(Calendar.ZONE_OFFSET); - if (_usageTimezone.inDaylightTime(date)) { - timezoneOffset += (60 * 60 * 1000); - } - - calTS.add(Calendar.MILLISECOND, -1 * timezoneOffset); - - return calTS.getTime(); + return _quotaUsageDao.findQuotaUsage(accountId, domainId, usageType, startDate, endDate); } @Override diff --git a/plugins/database/quota/src/test/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImplTest.java b/plugins/database/quota/src/test/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImplTest.java index 899ce649fce..664863a1b90 100644 --- a/plugins/database/quota/src/test/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImplTest.java +++ b/plugins/database/quota/src/test/java/org/apache/cloudstack/api/response/QuotaResponseBuilderImplTest.java @@ -177,7 +177,6 @@ public class QuotaResponseBuilderImplTest extends TestCase { Mockito.when(quotaCreditsDaoMock.saveCredits(Mockito.any(QuotaCreditsVO.class))).thenReturn(credit); Mockito.when(quotaBalanceDaoMock.lastQuotaBalance(Mockito.anyLong(), Mockito.anyLong(), Mockito.any(Date.class))).thenReturn(new BigDecimal(111)); - Mockito.when(quotaServiceMock.computeAdjustedTime(Mockito.any(Date.class))).thenReturn(new Date()); AccountVO account = new AccountVO(); account.setState(Account.State.LOCKED); @@ -245,7 +244,6 @@ public class QuotaResponseBuilderImplTest extends TestCase { entry.setCreditBalance(new BigDecimal(100)); quotaBalance.add(entry); quotaBalance.add(entry); - Mockito.lenient().when(quotaServiceMock.computeAdjustedTime(Mockito.any(Date.class))).thenReturn(new Date()); QuotaBalanceResponse resp = quotaResponseBuilderSpy.createQuotaLastBalanceResponse(quotaBalance, null); assertTrue(resp.getStartQuota().compareTo(new BigDecimal(200)) == 0); } @@ -326,16 +324,14 @@ public class QuotaResponseBuilderImplTest extends TestCase { Date startDate = DateUtils.addDays(date, -100); Date endDate = DateUtils.addDays(new Date(), -1); - Mockito.doReturn(date).when(quotaServiceMock).computeAdjustedTime(Mockito.any(Date.class)); quotaResponseBuilderSpy.validateEndDateOnCreatingNewQuotaTariff(quotaTariffVoMock, startDate, endDate); } @Test public void validateEndDateOnCreatingNewQuotaTariffTestSetValidEndDate() { Date startDate = DateUtils.addDays(date, -100); - Date endDate = date; + Date endDate = DateUtils.addMilliseconds(new Date(), 1); - Mockito.doReturn(DateUtils.addDays(date, -10)).when(quotaServiceMock).computeAdjustedTime(Mockito.any(Date.class)); quotaResponseBuilderSpy.validateEndDateOnCreatingNewQuotaTariff(quotaTariffVoMock, startDate, endDate); Mockito.verify(quotaTariffVoMock).setEndDate(Mockito.any(Date.class)); } @@ -387,7 +383,6 @@ public class QuotaResponseBuilderImplTest extends TestCase { public void deleteQuotaTariffTestUpdateRemoved() { Mockito.doReturn(quotaTariffVoMock).when(quotaTariffDaoMock).findByUuid(Mockito.anyString()); Mockito.doReturn(true).when(quotaTariffDaoMock).updateQuotaTariff(Mockito.any(QuotaTariffVO.class)); - Mockito.doReturn(new Date()).when(quotaServiceMock).computeAdjustedTime(Mockito.any(Date.class)); Assert.assertTrue(quotaResponseBuilderSpy.deleteQuotaTariff("")); diff --git a/plugins/database/quota/src/test/java/org/apache/cloudstack/quota/QuotaServiceImplTest.java b/plugins/database/quota/src/test/java/org/apache/cloudstack/quota/QuotaServiceImplTest.java index fa58c35ea5d..19e756d1d97 100644 --- a/plugins/database/quota/src/test/java/org/apache/cloudstack/quota/QuotaServiceImplTest.java +++ b/plugins/database/quota/src/test/java/org/apache/cloudstack/quota/QuotaServiceImplTest.java @@ -30,7 +30,6 @@ import org.apache.cloudstack.quota.dao.QuotaUsageDao; import org.apache.cloudstack.quota.vo.QuotaAccountVO; import org.apache.cloudstack.quota.vo.QuotaBalanceVO; import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -102,13 +101,6 @@ public class QuotaServiceImplTest extends TestCase { quotaService.configure("randomName", null); } - @Test - public void testComputeAdjustedTime() { - DateTime now = new DateTime(DateTimeZone.UTC); - DateTime result = new DateTime(quotaService.computeAdjustedTime(now.toDate())); - // FIXME: fix this test - } - @Test public void testFindQuotaBalanceVO() { final long accountId = 2L; @@ -123,7 +115,6 @@ public class QuotaServiceImplTest extends TestCase { qb.setAccountId(accountId); records.add(qb); - Mockito.when(respBldr.startOfNextDay()).thenReturn(endDate); Mockito.when(respBldr.startOfNextDay(Mockito.any(Date.class))).thenReturn(startDate); Mockito.when(quotaBalanceDao.findQuotaBalance(Mockito.eq(accountId), Mockito.eq(domainId), Mockito.any(Date.class), Mockito.any(Date.class))).thenReturn(records); Mockito.when(quotaBalanceDao.lastQuotaBalanceVO(Mockito.eq(accountId), Mockito.eq(domainId), Mockito.any(Date.class))).thenReturn(records); @@ -142,7 +133,6 @@ public class QuotaServiceImplTest extends TestCase { final Date startDate = new DateTime().minusDays(2).toDate(); final Date endDate = new Date(); - Mockito.when(respBldr.startOfNextDay()).thenReturn(endDate); quotaService.getQuotaUsage(accountId, accountName, domainId, QuotaTypes.IP_ADDRESS, startDate, endDate); Mockito.verify(quotaUsageDao, Mockito.times(1)).findQuotaUsage(Mockito.eq(accountId), Mockito.eq(domainId), Mockito.eq(QuotaTypes.IP_ADDRESS), Mockito.any(Date.class), Mockito.any(Date.class)); } diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index b665257bb2a..5a580cb86e4 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -4374,10 +4374,10 @@ public class ApiResponseHelper implements ResponseGenerator { } if (usageRecord.getStartDate() != null) { - usageRecResponse.setStartDate(getDateStringInternal(usageRecord.getStartDate())); + usageRecResponse.setStartDate(usageRecord.getStartDate()); } if (usageRecord.getEndDate() != null) { - usageRecResponse.setEndDate(getDateStringInternal(usageRecord.getEndDate())); + usageRecResponse.setEndDate(usageRecord.getEndDate()); } return usageRecResponse; diff --git a/server/src/main/java/com/cloud/usage/UsageServiceImpl.java b/server/src/main/java/com/cloud/usage/UsageServiceImpl.java index 3398e3ba571..170ef1fdbbc 100644 --- a/server/src/main/java/com/cloud/usage/UsageServiceImpl.java +++ b/server/src/main/java/com/cloud/usage/UsageServiceImpl.java @@ -206,14 +206,10 @@ public class UsageServiceImpl extends ManagerBase implements UsageService, Manag if (startDate.after(endDate)) { throw new InvalidParameterValueException("Incorrect Date Range. Start date: " + startDate + " is after end date:" + endDate); } - TimeZone usageTZ = getUsageTimezone(); - Date adjustedStartDate = computeAdjustedTime(startDate, usageTZ); - Date adjustedEndDate = computeAdjustedTime(endDate, usageTZ); logger.debug("Getting usage records for account ID [{}], domain ID [{}] between [{}] and [{}] using page size [{}] and start index [{}].", - accountId, domainId, DateUtil.displayDateInTimezone(_usageTimezone, adjustedStartDate), - DateUtil.displayDateInTimezone(_usageTimezone, adjustedEndDate), cmd.getPageSizeVal(), - cmd.getStartIndex()); + accountId, domainId, DateUtil.displayDateInTimezone(_usageTimezone, startDate), DateUtil.displayDateInTimezone(_usageTimezone, endDate), + cmd.getPageSizeVal(), cmd.getStartIndex()); Filter usageFilter = new Filter(UsageVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal()); @@ -338,9 +334,9 @@ public class UsageServiceImpl extends ManagerBase implements UsageService, Manag // Filter out hidden usages sc.addAnd("isHidden", SearchCriteria.Op.EQ, false); - if ((adjustedStartDate != null) && (adjustedEndDate != null) && adjustedStartDate.before(adjustedEndDate)) { - sc.addAnd("startDate", SearchCriteria.Op.BETWEEN, adjustedStartDate, adjustedEndDate); - sc.addAnd("endDate", SearchCriteria.Op.BETWEEN, adjustedStartDate, adjustedEndDate); + if ((startDate != null) && (endDate != null) && startDate.before(endDate)) { + sc.addAnd("startDate", SearchCriteria.Op.BETWEEN, startDate, endDate); + sc.addAnd("endDate", SearchCriteria.Op.BETWEEN, startDate, endDate); } else { return new Pair, Integer>(new ArrayList(), new Integer(0)); // return an empty list if we fail to validate the dates } @@ -490,30 +486,6 @@ public class UsageServiceImpl extends ManagerBase implements UsageService, Manag return true; } - private Date computeAdjustedTime(Date initialDate, TimeZone targetTZ) { - Calendar cal = Calendar.getInstance(); - cal.setTime(initialDate); - TimeZone localTZ = cal.getTimeZone(); - int timezoneOffset = cal.get(Calendar.ZONE_OFFSET); - if (localTZ.inDaylightTime(initialDate)) { - timezoneOffset += (60 * 60 * 1000); - } - cal.add(Calendar.MILLISECOND, timezoneOffset); - - Date newTime = cal.getTime(); - - Calendar calTS = Calendar.getInstance(targetTZ); - calTS.setTime(newTime); - timezoneOffset = calTS.get(Calendar.ZONE_OFFSET); - if (targetTZ.inDaylightTime(initialDate)) { - timezoneOffset += (60 * 60 * 1000); - } - - calTS.add(Calendar.MILLISECOND, -1 * timezoneOffset); - - return calTS.getTime(); - } - @Override public List listUsageTypes() { return UsageTypes.listUsageTypes(); From ad66edf6e6522fd816252367fd1f447308bfe5e2 Mon Sep 17 00:00:00 2001 From: Vishesh Date: Tue, 28 May 2024 11:08:59 +0530 Subject: [PATCH 12/25] UI: Add search filters (#9068) --- ui/public/locales/en.json | 6 + ui/src/components/view/SearchView.vue | 287 +++++++++++++++++- ui/src/config/section/account.js | 1 + ui/src/config/section/compute.js | 6 +- ui/src/config/section/config.js | 2 + ui/src/config/section/image.js | 1 + ui/src/config/section/infra.js | 2 +- ui/src/config/section/infra/clusters.js | 1 + ui/src/config/section/infra/hosts.js | 1 + ui/src/config/section/infra/pods.js | 1 + .../config/section/infra/primaryStorages.js | 1 + .../config/section/infra/secondaryStorages.js | 1 + ui/src/config/section/infra/systemVms.js | 1 + ui/src/config/section/infra/zones.js | 1 + ui/src/config/section/network.js | 2 +- ui/src/config/section/offering.js | 6 + ui/src/config/section/role.js | 1 + 17 files changed, 316 insertions(+), 5 deletions(-) diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 1f6a2057c49..89abfe5981f 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -708,6 +708,7 @@ "label.destnetworkuuid": "Network", "label.destport": "Destination Ports", "label.destroy": "Destroy", +"label.destroying": "Destroying", "label.destroyed": "Destroyed", "label.destroy.router": "Destroy router", "label.deststartport": "Destination Start Port", @@ -931,6 +932,7 @@ "label.fwdeviceid": "ID", "label.fwdevicestate": "Status", "label.gateway": "Gateway", +"label.global": "Global", "label.global.settings": "Global Settings", "label.globo.dns": "GloboDNS", "label.globo.dns.configuration": "GloboDNS configuration", @@ -1343,6 +1345,7 @@ "label.min_balance": "Min balance", "label.mincpunumber": "Min CPU cores", "label.minimum": "Minimum", +"label.minimumsemanticversion": "Minimum semantic version", "label.miniops": "Min IOPS", "label.minmaxiops": "Min IOPS / Max IOPS", "label.minmembers": "Min members", @@ -1682,6 +1685,7 @@ "label.reboot": "Reboot", "label.receivedbytes": "Bytes received", "label.recover.vm": "Recover Instance", +"label.recovering": "Recovering", "label.redirect": "Redirect to:", "label.redirecturi": "Redirect URI", "label.redundantrouter": "Redundant router", @@ -1824,6 +1828,7 @@ "label.scaledown.policy": "ScaleDown policy", "label.scaleup.policies": "ScaleUp policies", "label.scaleup.policy": "ScaleUp policy", +"label.scaling": "Scaling", "label.schedule": "Schedule", "label.schedule.add": "Add schedule", "label.scheduled.backups": "Scheduled backups", @@ -2188,6 +2193,7 @@ "label.update.vmware.datacenter": "Update VMWare datacenter", "label.updating": "Updating", "label.upgrade.router.newer.template": "Upgrade router to use newer Template", +"label.upgrading": "Upgrading", "label.upload": "Upload", "label.upload.description": "Path to upload objects at", "label.upload.path": "Upload path", diff --git a/ui/src/components/view/SearchView.vue b/ui/src/components/view/SearchView.vue index 7a2154ad426..43f07c7456b 100644 --- a/ui/src/components/view/SearchView.vue +++ b/ui/src/components/view/SearchView.vue @@ -79,7 +79,7 @@ - + @@ -268,6 +268,9 @@ export default { if (item === 'domainid' && !('listDomains' in this.$store.getters.apis)) { return true } + if (item === 'account' && !('listAccounts' in this.$store.getters.apis)) { + return true + } if (item === 'account' && !('addAccountToProject' in this.$store.getters.apis || 'createAccount' in this.$store.getters.apis)) { return true } @@ -280,7 +283,10 @@ export default { if (item === 'groupid' && !('listInstanceGroups' in this.$store.getters.apis)) { return true } - if (['zoneid', 'domainid', 'imagestoreid', 'storageid', 'state', 'level', 'clusterid', 'podid', 'groupid', 'entitytype', 'type'].includes(item)) { + if (['zoneid', 'domainid', 'imagestoreid', 'storageid', 'state', 'account', 'hypervisor', 'level', + 'clusterid', 'podid', 'groupid', 'entitytype', 'accounttype', 'systemvmtype', 'scope', 'provider', + 'type'].includes(item) + ) { type = 'list' } else if (item === 'tags') { type = 'tag' @@ -305,6 +311,11 @@ export default { this.fields[typeIndex].loading = true this.fields[typeIndex].opts = this.fetchGuestNetworkTypes() this.fields[typeIndex].loading = false + } else if (this.$route.path === '/role' || this.$route.path.includes('/role/')) { + const typeIndex = this.fields.findIndex(item => item.name === 'type') + this.fields[typeIndex].loading = true + this.fields[typeIndex].opts = this.fetchRoleTypes() + this.fields[typeIndex].loading = false } } @@ -329,6 +340,34 @@ export default { this.fields[entityTypeIndex].loading = false } + if (arrayField.includes('accounttype')) { + const accountTypeIndex = this.fields.findIndex(item => item.name === 'accounttype') + this.fields[accountTypeIndex].loading = true + this.fields[accountTypeIndex].opts = this.fetchAccountTypes() + this.fields[accountTypeIndex].loading = false + } + + if (arrayField.includes('systemvmtype')) { + const systemVmTypeIndex = this.fields.findIndex(item => item.name === 'systemvmtype') + this.fields[systemVmTypeIndex].loading = true + this.fields[systemVmTypeIndex].opts = this.fetchSystemVmTypes() + this.fields[systemVmTypeIndex].loading = false + } + + if (arrayField.includes('scope')) { + const scopeIndex = this.fields.findIndex(item => item.name === 'scope') + this.fields[scopeIndex].loading = true + this.fields[scopeIndex].opts = this.fetchStoragePoolScope() + this.fields[scopeIndex].loading = false + } + + if (arrayField.includes('provider')) { + const providerIndex = this.fields.findIndex(item => item.name === 'provider') + this.fields[providerIndex].loading = true + this.fields[providerIndex].opts = this.fetchImageStoreProviders() + this.fields[providerIndex].loading = false + } + if (arrayField.includes('resourcetype')) { const resourceTypeIndex = this.fields.findIndex(item => item.name === 'resourcetype') this.fields[resourceTypeIndex].loading = true @@ -351,6 +390,8 @@ export default { let typeIndex = -1 let zoneIndex = -1 let domainIndex = -1 + let accountIndex = -1 + let hypervisorIndex = -1 let imageStoreIndex = -1 let storageIndex = -1 let podIndex = -1 @@ -362,6 +403,10 @@ export default { typeIndex = this.fields.findIndex(item => item.name === 'type') this.fields[typeIndex].loading = true promises.push(await this.fetchAlertTypes()) + } else if (this.$route.path === '/affinitygroup') { + typeIndex = this.fields.findIndex(item => item.name === 'type') + this.fields[typeIndex].loading = true + promises.push(await this.fetchAffinityGroupTypes()) } } @@ -377,6 +422,18 @@ export default { promises.push(await this.fetchDomains(searchKeyword)) } + if (arrayField.includes('account')) { + accountIndex = this.fields.findIndex(item => item.name === 'account') + this.fields[accountIndex].loading = true + promises.push(await this.fetchAccounts(searchKeyword)) + } + + if (arrayField.includes('hypervisor')) { + hypervisorIndex = this.fields.findIndex(item => item.name === 'hypervisor') + this.fields[hypervisorIndex].loading = true + promises.push(await this.fetchHypervisors()) + } + if (arrayField.includes('imagestoreid')) { imageStoreIndex = this.fields.findIndex(item => item.name === 'imagestoreid') this.fields[imageStoreIndex].loading = true @@ -426,6 +483,18 @@ export default { this.fields[domainIndex].opts = this.sortArray(domain[0].data, 'path') } } + if (accountIndex > -1) { + const account = response.filter(item => item.type === 'account') + if (account && account.length > 0) { + this.fields[accountIndex].opts = this.sortArray(account[0].data, 'name') + } + } + if (hypervisorIndex > -1) { + const hypervisor = response.filter(item => item.type === 'hypervisor') + if (hypervisor && hypervisor.length > 0) { + this.fields[hypervisorIndex].opts = this.sortArray(hypervisor[0].data, 'name') + } + } if (imageStoreIndex > -1) { const imageStore = response.filter(item => item.type === 'imagestoreid') if (imageStore && imageStore.length > 0) { @@ -539,6 +608,32 @@ export default { }) }) }, + fetchAccounts (searchKeyword) { + return new Promise((resolve, reject) => { + api('listAccounts', { listAll: true, showicon: true, keyword: searchKeyword }).then(json => { + const account = json.listaccountsresponse.account + resolve({ + type: 'account', + data: account + }) + }).catch(error => { + reject(error.response.headers['x-description']) + }) + }) + }, + fetchHypervisors () { + return new Promise((resolve, reject) => { + api('listHypervisors').then(json => { + const hypervisor = json.listhypervisorsresponse.hypervisor.map(a => { return { id: a.name, name: a.name } }) + resolve({ + type: 'hypervisor', + data: hypervisor + }) + }).catch(error => { + reject(error.response.headers['x-description']) + }) + }) + }, fetchImageStores (searchKeyword) { return new Promise((resolve, reject) => { api('listImageStores', { listAll: true, showicon: true, keyword: searchKeyword }).then(json => { @@ -627,6 +722,41 @@ export default { }) } }, + fetchAffinityGroupTypes () { + if (this.alertTypes.length > 0) { + return new Promise((resolve, reject) => { + resolve({ + type: 'type', + data: this.alertTypes + }) + }) + } else { + return new Promise((resolve, reject) => { + api('listAffinityGroupTypes').then(json => { + const alerttypes = json.listaffinitygrouptypesresponse.affinityGroupType.map(a => { + let name = a.type + if (a.type === 'host anti-affinity') { + name = 'host anti-affinity (Strict)' + } else if (a.type === 'host affinity') { + name = 'host affinity (Strict)' + } else if (a.type === 'non-strict host anti-affinity') { + name = 'host anti-affinity (Non-Strict)' + } else if (a.type === 'non-strict host affinity') { + name = 'host affinity (Non-Strict)' + } + return { id: a.type, name: name } + }) + this.alertTypes = alerttypes + resolve({ + type: 'type', + data: alerttypes + }) + }).catch(error => { + reject(error.response.headers['x-description']) + }) + }) + } + }, fetchGuestNetworkTypes () { const types = [] if (this.apiName.indexOf('listNetworks') > -1) { @@ -645,6 +775,108 @@ export default { } return types }, + fetchAccountTypes () { + const types = [] + if (this.apiName.indexOf('listAccounts') > -1) { + types.push({ + id: '1', + name: 'Admin' + }) + types.push({ + id: '2', + name: 'DomainAdmin' + }) + types.push({ + id: '3', + name: 'User' + }) + } + return types + }, + fetchSystemVmTypes () { + const types = [] + if (this.apiName.indexOf('listSystemVms') > -1) { + types.push({ + id: 'consoleproxy', + name: 'label.console.proxy.vm' + }) + types.push({ + id: 'secondarystoragevm', + name: 'label.secondary.storage.vm' + }) + } + return types + }, + fetchStoragePoolScope () { + const types = [] + if (this.apiName.indexOf('listStoragePools') > -1) { + types.push({ + id: 'HOST', + name: 'label.hostname' + }) + types.push({ + id: 'CLUSTER', + name: 'label.cluster' + }) + types.push({ + id: 'ZONE', + name: 'label.zone' + }) + types.push({ + id: 'REGION', + name: 'label.region' + }) + types.push({ + id: 'GLOBAL', + name: 'label.global' + }) + } + return types + }, + fetchImageStoreProviders () { + const types = [] + if (this.apiName.indexOf('listImageStores') > -1) { + types.push({ + id: 'NFS', + name: 'NFS' + }) + types.push({ + id: 'SMB/CIFS', + name: 'SMB/CIFS' + }) + types.push({ + id: 'S3', + name: 'S3' + }) + types.push({ + id: 'Swift', + name: 'Swift' + }) + } + return types + }, + fetchRoleTypes () { + const types = [] + if (this.apiName.indexOf('listRoles') > -1) { + types.push({ + id: 'Admin', + name: 'Admin' + }) + types.push({ + id: 'ResourceAdmin', + name: 'ResourceAdmin' + }) + types.push({ + id: 'DomainAdmin', + name: 'DomainAdmin' + }) + types.push({ + id: 'User', + name: 'User' + }) + } + return types + }, fetchState () { if (this.apiName.includes('listVolumes')) { return [ @@ -673,6 +905,57 @@ export default { name: 'label.migrating' } ] + } else if (this.apiName.includes('listKubernetesClusters')) { + return [ + { + id: 'Created', + name: 'label.created' + }, + { + id: 'Starting', + name: 'label.starting' + }, + { + id: 'Running', + name: 'label.running' + }, + { + id: 'Stopping', + name: 'label.stopping' + }, + { + id: 'Stopped', + name: 'label.stopped' + }, + { + id: 'Scaling', + name: 'label.scaling' + }, + { + id: 'Upgrading', + name: 'label.upgrading' + }, + { + id: 'Alert', + name: 'label.alert' + }, + { + id: 'Recovering', + name: 'label.recovering' + }, + { + id: 'Destroyed', + name: 'label.destroyed' + }, + { + id: 'Destroying', + name: 'label.destroying' + }, + { + id: 'Error', + name: 'label.error' + } + ] } return [] }, diff --git a/ui/src/config/section/account.js b/ui/src/config/section/account.js index 92897a33b12..a35b2b9d5f0 100644 --- a/ui/src/config/section/account.js +++ b/ui/src/config/section/account.js @@ -24,6 +24,7 @@ export default { icon: 'team-outlined', docHelp: 'adminguide/accounts.html', permission: ['listAccounts'], + searchFilters: ['name', 'accounttype', 'domainid'], columns: ['name', 'state', 'rolename', 'roletype', 'domainpath'], details: ['name', 'id', 'rolename', 'roletype', 'domainpath', 'networkdomain', 'iptotal', 'vmtotal', 'volumetotal', 'receivedbytes', 'sentbytes', 'created'], related: [{ diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js index ba3a21e1539..969402a694c 100644 --- a/ui/src/config/section/compute.js +++ b/ui/src/config/section/compute.js @@ -520,6 +520,7 @@ export default { title: 'label.kubernetes', icon: ['fa-solid', 'fa-dharmachakra'], docHelp: 'plugins/cloudstack-kubernetes-service.html', + searchFilters: ['name', 'domainid', 'account', 'state'], permission: ['listKubernetesClusters'], columns: (store) => { var fields = ['name', 'state', 'clustertype', 'size', 'cpunumber', 'memory', 'kubernetesversionname'] @@ -629,6 +630,7 @@ export default { docHelp: 'adminguide/autoscale_with_virtual_router.html', resourceType: 'AutoScaleVmGroup', permission: ['listAutoScaleVmGroups'], + searchFilters: ['name', 'zoneid', 'domainid', 'account'], columns: (store) => { var fields = ['name', 'state', 'associatednetworkname', 'publicip', 'publicport', 'privateport', 'minmembers', 'maxmembers', 'availablevirtualmachinecount', 'account'] if (store.listAllProjects) { @@ -739,7 +741,7 @@ export default { docHelp: 'adminguide/virtual_machines.html#changing-the-vm-name-os-or-group', resourceType: 'VMInstanceGroup', permission: ['listInstanceGroups'], - + searchFilters: ['name', 'zoneid', 'domainid', 'account'], columns: (store) => { var fields = ['name', 'account'] if (store.listAllProjects) { @@ -797,6 +799,7 @@ export default { icon: 'key-outlined', docHelp: 'adminguide/virtual_machines.html#using-ssh-keys-for-authentication', permission: ['listSSHKeyPairs'], + searchFilters: ['name', 'domainid', 'account', 'fingerprint'], columns: () => { var fields = ['name', 'fingerprint'] if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { @@ -957,6 +960,7 @@ export default { icon: 'swap-outlined', docHelp: 'adminguide/virtual_machines.html#affinity-groups', permission: ['listAffinityGroups'], + searchFilters: ['name', 'zoneid', 'domainid', 'account', 'type'], columns: () => { var fields = ['name', 'type', 'description'] if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { diff --git a/ui/src/config/section/config.js b/ui/src/config/section/config.js index 6fa33e3ed31..aa108b5b1fa 100644 --- a/ui/src/config/section/config.js +++ b/ui/src/config/section/config.js @@ -37,6 +37,7 @@ export default { icon: 'team-outlined', docHelp: 'adminguide/accounts.html#using-an-ldap-server-for-user-authentication', permission: ['listLdapConfigurations'], + searchFilters: ['domainid', 'hostname', 'port'], columns: ['hostname', 'port', 'domainid'], details: ['hostname', 'port', 'domainid'], actions: [ @@ -118,6 +119,7 @@ export default { icon: 'database-outlined', docHelp: 'adminguide/hosts.html?highlight=Hypervisor%20capabilities#hypervisor-capabilities', permission: ['listHypervisorCapabilities'], + searchFilters: ['hypervisor'], columns: ['hypervisor', 'hypervisorversion', 'maxguestslimit', 'maxhostspercluster'], details: ['hypervisor', 'hypervisorversion', 'maxguestslimit', 'maxdatavolumeslimit', 'maxhostspercluster', 'securitygroupenabled', 'storagemotionenabled'], actions: [ diff --git a/ui/src/config/section/image.js b/ui/src/config/section/image.js index aa21b262037..6f0bd5e9322 100644 --- a/ui/src/config/section/image.js +++ b/ui/src/config/section/image.js @@ -367,6 +367,7 @@ export default { icon: ['fa-solid', 'fa-dharmachakra'], docHelp: 'plugins/cloudstack-kubernetes-service.html#kubernetes-supported-versions', permission: ['listKubernetesSupportedVersions'], + searchFilters: ['zoneid', 'minimumsemanticversion'], columns: ['name', 'state', 'semanticversion', 'isostate', 'mincpunumber', 'minmemory', 'zonename'], details: ['name', 'semanticversion', 'supportsautoscaling', 'zoneid', 'zonename', 'isoid', 'isoname', 'isostate', 'mincpunumber', 'minmemory', 'supportsha', 'state', 'created'], actions: [ diff --git a/ui/src/config/section/infra.js b/ui/src/config/section/infra.js index 5b3b38a68e5..cb91d4d7b04 100644 --- a/ui/src/config/section/infra.js +++ b/ui/src/config/section/infra.js @@ -79,7 +79,7 @@ export default { permission: ['listAlerts'], columns: ['name', 'description', 'type', 'sent'], details: ['name', 'id', 'type', 'sent', 'description'], - searchFilters: ['type'], + searchFilters: ['name', 'type'], actions: [ { api: 'archiveAlerts', diff --git a/ui/src/config/section/infra/clusters.js b/ui/src/config/section/infra/clusters.js index ab8bea6b79d..8b2f37d5b7b 100644 --- a/ui/src/config/section/infra/clusters.js +++ b/ui/src/config/section/infra/clusters.js @@ -24,6 +24,7 @@ export default { icon: 'cluster-outlined', docHelp: 'conceptsandterminology/concepts.html#about-clusters', permission: ['listClustersMetrics'], + searchFilters: ['name', 'zoneid', 'podid', 'hypervisor'], columns: () => { const fields = ['name', 'state', 'allocationstate', 'clustertype', 'hypervisortype', 'hosts'] const metricsFields = ['cpuused', 'cpumaxdeviation', 'cpuallocated', 'cputotal', 'memoryused', 'memorymaxdeviation', 'memoryallocated', 'memorytotal', 'drsimbalance'] diff --git a/ui/src/config/section/infra/hosts.js b/ui/src/config/section/infra/hosts.js index d92f4af21e6..329b77fe2d7 100644 --- a/ui/src/config/section/infra/hosts.js +++ b/ui/src/config/section/infra/hosts.js @@ -24,6 +24,7 @@ export default { icon: 'database-outlined', docHelp: 'conceptsandterminology/concepts.html#about-hosts', permission: ['listHostsMetrics'], + searchFilters: ['name', 'zoneid', 'podid', 'clusterid', 'hypervisor'], resourceType: 'Host', filters: () => { const filters = ['enabled', 'disabled', 'maintenance', 'up', 'down', 'alert'] diff --git a/ui/src/config/section/infra/pods.js b/ui/src/config/section/infra/pods.js index eff62e0a4a2..595b35f4fb9 100644 --- a/ui/src/config/section/infra/pods.js +++ b/ui/src/config/section/infra/pods.js @@ -24,6 +24,7 @@ export default { icon: 'appstore-outlined', docHelp: 'conceptsandterminology/concepts.html#about-pods', permission: ['listPods'], + searchFilters: ['name', 'zoneid'], columns: ['name', 'allocationstate', 'gateway', 'netmask', 'zonename'], details: ['name', 'id', 'allocationstate', 'netmask', 'gateway', 'zonename'], related: [{ diff --git a/ui/src/config/section/infra/primaryStorages.js b/ui/src/config/section/infra/primaryStorages.js index f222edeaf70..74624b3e888 100644 --- a/ui/src/config/section/infra/primaryStorages.js +++ b/ui/src/config/section/infra/primaryStorages.js @@ -24,6 +24,7 @@ export default { icon: 'hdd-outlined', docHelp: 'adminguide/storage.html#primary-storage', permission: ['listStoragePoolsMetrics'], + searchFilters: ['name', 'zoneid', 'podid', 'clusterid', 'ipaddress', 'path', 'scope'], columns: () => { const fields = ['name', 'state', 'ipaddress', 'scope', 'type', 'path'] const metricsFields = ['disksizeusedgb', 'disksizetotalgb', 'disksizeallocatedgb', 'disksizeunallocatedgb'] diff --git a/ui/src/config/section/infra/secondaryStorages.js b/ui/src/config/section/infra/secondaryStorages.js index 774c233c446..53fa546d934 100644 --- a/ui/src/config/section/infra/secondaryStorages.js +++ b/ui/src/config/section/infra/secondaryStorages.js @@ -24,6 +24,7 @@ export default { icon: 'picture-outlined', docHelp: 'adminguide/storage.html#secondary-storage', permission: ['listImageStores'], + searchFilters: ['name', 'zoneid', 'provider'], columns: () => { var fields = ['name', 'url', 'protocol', 'scope', 'zonename'] if (store.getters.apis.listImageStores.params.filter(x => x.name === 'readonly').length > 0) { diff --git a/ui/src/config/section/infra/systemVms.js b/ui/src/config/section/infra/systemVms.js index 68a27f73a52..3ecd17f95ca 100644 --- a/ui/src/config/section/infra/systemVms.js +++ b/ui/src/config/section/infra/systemVms.js @@ -24,6 +24,7 @@ export default { icon: 'thunderbolt-outlined', docHelp: 'adminguide/systemvm.html', permission: ['listSystemVms'], + searchFilters: ['name', 'zoneid', 'podid', 'hostid', 'systemvmtype', 'storageid'], columns: ['name', 'state', 'agentstate', 'systemvmtype', 'publicip', 'privateip', 'linklocalip', 'version', 'hostname', 'zonename'], details: ['name', 'id', 'agentstate', 'systemvmtype', 'publicip', 'privateip', 'linklocalip', 'gateway', 'hostname', 'version', 'zonename', 'created', 'activeviewersessions', 'isdynamicallyscalable', 'hostcontrolstate'], resourceType: 'SystemVm', diff --git a/ui/src/config/section/infra/zones.js b/ui/src/config/section/infra/zones.js index b2768f77343..929add5210d 100644 --- a/ui/src/config/section/infra/zones.js +++ b/ui/src/config/section/infra/zones.js @@ -24,6 +24,7 @@ export default { icon: 'global-outlined', docHelp: 'conceptsandterminology/concepts.html#about-zones', permission: ['listZonesMetrics'], + searchFilters: ['name', 'domainid', 'tags'], columns: () => { const fields = ['name', 'allocationstate', 'type', 'networktype', 'clusters'] const metricsFields = ['cpuused', 'cpumaxdeviation', 'cpuallocated', 'cputotal', 'memoryused', 'memorymaxdeviation', 'memoryallocated', 'memorytotal'] diff --git a/ui/src/config/section/network.js b/ui/src/config/section/network.js index 3d5241feb59..65abdd6bec8 100644 --- a/ui/src/config/section/network.js +++ b/ui/src/config/section/network.js @@ -748,6 +748,7 @@ export default { icon: 'environment-outlined', docHelp: 'adminguide/networking_and_traffic.html#reserving-public-ip-addresses-and-vlans-for-accounts', permission: ['listPublicIpAddresses'], + searchFilters: ['ipaddress', 'zoneid', 'account', 'domainid', 'vlanid', 'tags'], resourceType: 'PublicIpAddress', columns: () => { var fields = ['ipaddress', 'state', 'associatednetworkname', 'vpcname', 'virtualmachinename', 'allocated', 'account'] @@ -921,7 +922,6 @@ export default { name: 's2svpn', title: 'label.site.to.site.vpn', icon: 'lock-outlined', - hidden: true, permission: ['listVpnGateways'], columns: ['publicip', 'account', 'domain'], details: ['publicip', 'account', 'domain'], diff --git a/ui/src/config/section/offering.js b/ui/src/config/section/offering.js index 3e99f602d91..b97b1a0cb2c 100644 --- a/ui/src/config/section/offering.js +++ b/ui/src/config/section/offering.js @@ -29,6 +29,7 @@ export default { docHelp: 'adminguide/service_offerings.html#compute-and-disk-service-offerings', icon: 'cloud-outlined', permission: ['listServiceOfferings'], + searchFilters: ['name', 'zoneid', 'domainid', 'cpunumber', 'cpuspeed', 'memory'], params: () => { var params = {} if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { @@ -132,6 +133,7 @@ export default { icon: 'setting-outlined', docHelp: 'adminguide/service_offerings.html#system-service-offerings', permission: ['listServiceOfferings', 'listInfrastructure'], + searchFilters: ['name', 'zoneid', 'domainid', 'cpunumber', 'cpuspeed', 'memory'], params: { issystem: 'true', isrecursive: 'true' }, columns: ['name', 'state', 'systemvmtype', 'cpunumber', 'cpuspeed', 'memory', 'storagetype', 'order'], filters: ['active', 'inactive'], @@ -208,6 +210,7 @@ export default { icon: 'hdd-outlined', docHelp: 'adminguide/service_offerings.html#compute-and-disk-service-offerings', permission: ['listDiskOfferings'], + searchFilters: ['name', 'zoneid', 'domainid', 'storageid'], params: () => { var params = {} if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) { @@ -307,6 +310,7 @@ export default { icon: 'cloud-upload-outlined', docHelp: 'adminguide/virtual_machines.html#backup-offerings', permission: ['listBackupOfferings'], + searchFilters: ['zoneid'], columns: ['name', 'description', 'zonename'], details: ['name', 'id', 'description', 'externalid', 'zone', 'allowuserdrivenbackups', 'created'], related: [{ @@ -360,6 +364,7 @@ export default { icon: 'wifi-outlined', docHelp: 'adminguide/networking.html#network-offerings', permission: ['listNetworkOfferings'], + searchFilters: ['name', 'zoneid', 'domainid', 'tags'], columns: ['name', 'state', 'guestiptype', 'traffictype', 'networkrate', 'domain', 'zone', 'order'], details: ['name', 'id', 'displaytext', 'guestiptype', 'traffictype', 'internetprotocol', 'networkrate', 'ispersistent', 'egressdefaultpolicy', 'availability', 'conservemode', 'specifyvlan', 'specifyipranges', 'supportspublicaccess', 'supportsstrechedl2subnet', 'service', 'tags', 'domain', 'zone'], resourceType: 'NetworkOffering', @@ -458,6 +463,7 @@ export default { icon: 'deployment-unit-outlined', docHelp: 'plugins/nuage-plugin.html?#vpc-offerings', permission: ['listVPCOfferings'], + searchFilters: ['name', 'zoneid', 'domainid'], resourceType: 'VpcOffering', columns: ['name', 'state', 'displaytext', 'domain', 'zone', 'order'], details: ['name', 'id', 'displaytext', 'internetprotocol', 'distributedvpcrouter', 'tags', 'service', 'domain', 'zone', 'created'], diff --git a/ui/src/config/section/role.js b/ui/src/config/section/role.js index 3823d633b18..c842b2f68f1 100644 --- a/ui/src/config/section/role.js +++ b/ui/src/config/section/role.js @@ -24,6 +24,7 @@ export default { icon: 'idcard-outlined', docHelp: 'adminguide/accounts.html#roles', permission: ['listRoles', 'listRolePermissions'], + searchFilters: ['name', 'type'], columns: ['name', 'type', 'description'], details: ['name', 'id', 'type', 'description', 'ispublic'], tabs: [{ From c563fda081952b579272097c99d88bc1178c1e62 Mon Sep 17 00:00:00 2001 From: John Bampton Date: Tue, 28 May 2024 15:40:15 +1000 Subject: [PATCH 13/25] Add two more `pre-commit` hooks (#9077) https://github.com/pre-commit/pre-commit-hooks?tab=readme-ov-file#detect-aws-credentials https://github.com/pre-commit/pre-commit-hooks?tab=readme-ov-file#forbid-submodules --- .pre-commit-config.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9004ed9daee..4a5cc3ae716 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -36,6 +36,8 @@ repos: - id: check-vcs-permalinks #- id: check-yaml - id: destroyed-symlinks + - id: detect-aws-credentials + args: [--allow-missing-credentials] - id: detect-private-key exclude: > (?x) @@ -53,6 +55,7 @@ repos: - id: end-of-file-fixer exclude: \.vhd$ #- id: fix-byte-order-marker + - id: forbid-submodules - id: mixed-line-ending exclude: \.(cs|xml)$ # - id: trailing-whitespace From e159a593f1297189d0fe29484e0b8dd45d72bc34 Mon Sep 17 00:00:00 2001 From: John Bampton Date: Tue, 28 May 2024 15:40:52 +1000 Subject: [PATCH 14/25] Add `markdownlint` with `pre-commit` (#9078) https://github.com/DavidAnson/markdownlint/tree/main?tab=readme-ov-file#rules--aliases https://github.com/igorshubovych/markdownlint-cli?tab=readme-ov-file#use-with-pre-commit --- .github/linters/.markdown-lint.yml | 100 +++++++++++++++++++++++++++++ .pre-commit-config.yaml | 9 +++ 2 files changed, 109 insertions(+) create mode 100644 .github/linters/.markdown-lint.yml diff --git a/.github/linters/.markdown-lint.yml b/.github/linters/.markdown-lint.yml new file mode 100644 index 00000000000..df1b1a2825e --- /dev/null +++ b/.github/linters/.markdown-lint.yml @@ -0,0 +1,100 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# MD001/heading-increment Heading levels should only increment by one level at a time +MD001: false + +# MD003/heading-style Heading style +MD003: false + +# MD004/ul-style Unordered list style +MD004: false + +# MD007/ul-indent Unordered list indentation +MD007: false + +# MD009/no-trailing-spaces Trailing spaces +MD009: false + +# MD010/no-hard-tabs Hard tabs +MD010: false + +# MD012/no-multiple-blanks Multiple consecutive blank lines +MD012: false + +# MD013/line-length Line length +MD013: false + +# MD014/commands-show-output Dollar signs used before commands without showing output +MD014: false + +# MD018/no-missing-space-atx No space after hash on atx style heading +MD018: false + +# MD019/no-multiple-space-atx Multiple spaces after hash on atx style heading +MD019: false + +# MD022/blanks-around-headings Headings should be surrounded by blank lines +MD022: false + +# MD023/heading-start-left Headings must start at the beginning of the line +MD023: false + +# MD024/no-duplicate-heading Multiple headings with the same content +MD024: false + +# MD025/single-title/single-h1 Multiple top-level headings in the same document +MD025: false + +# MD026/no-trailing-punctuation Trailing punctuation in heading +MD026: false + +# MD028/no-blanks-blockquote Blank line inside blockquote +MD028: false + +# MD029/ol-prefix Ordered list item prefix +MD029: false + +# MD031/blanks-around-fences Fenced code blocks should be surrounded by blank lines +MD031: false + +# MD032/blanks-around-lists Lists should be surrounded by blank lines +MD032: false + +# MD033/no-inline-html Inline HTML +MD033: false + +# MD034/no-bare-urls Bare URL used +MD034: false + +# MD036/no-emphasis-as-heading Emphasis used instead of a heading +MD036: false + +# MD037/no-space-in-emphasis Spaces inside emphasis markers +MD037: false + +# MD040/fenced-code-language Fenced code blocks should have a language specified +MD040: false + +# MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading +MD041: false + +# MD046/code-block-style Code block style +MD046: false + +# MD052/reference-links-images Reference links and images should use a label that is defined +MD052: false diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4a5cc3ae716..73775aeb36c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -75,3 +75,12 @@ repos: ^scripts/vm/hypervisor/xenserver/vmopspremium$| ^setup/bindir/cloud-setup-encryption\.in$| ^venv/.*$ + - repo: https://github.com/igorshubovych/markdownlint-cli + rev: v0.40.0 + hooks: + - id: markdownlint + name: run markdownlint + description: check Markdown files with markdownlint + args: [--config=.github/linters/.markdown-lint.yml] + types: [markdown] + files: \.(md|mdown|markdown)$ From 40c5d353773933c841296da6d9fe775bc96089e7 Mon Sep 17 00:00:00 2001 From: John Bampton Date: Tue, 28 May 2024 15:41:20 +1000 Subject: [PATCH 15/25] Fix spelling in docs, logs, exception messages etc (#9076) --- .../com/cloud/network/NetworkServiceImpl.java | 50 +++++++++---------- .../com/cloud/user/AccountManagerImpl.java | 2 +- .../opt/cloud/templates/conntrackd.conf.templ | 2 +- .../maint/testpath_disable_enable_zone.py | 2 +- .../component/test_acl_sharednetwork.py | 2 +- ...cl_sharednetwork_deployVM-impersonation.py | 2 +- .../component/test_advancedsg_networks.py | 2 +- .../component/test_project_limits.py | 2 +- .../component/test_resource_limits.py | 2 +- .../component/test_snapshots_improvement.py | 2 +- .../smoke/test_attach_multiple_volumes.py | 2 +- ...test_enable_account_settings_for_domain.py | 4 +- tools/ngui/static/js/lib/angular.js | 4 +- 13 files changed, 39 insertions(+), 39 deletions(-) diff --git a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java index 1314d7dd574..e618c17d3cf 100644 --- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java @@ -540,7 +540,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C } protected boolean canIpUsedForNonConserveService(PublicIp ip, Service service) { - // If it's non-conserve mode, then the new ip should not be used by any other services + // If it's non-conserve mode, then the new IP should not be used by any other services List ipList = new ArrayList(); ipList.add(ip); Map> ipToServices = getIpToServices(ipList, false, false); @@ -549,7 +549,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C if (services == null || services.isEmpty()) { return true; } - // Since it's non-conserve mode, only one service should used for IP + // Since it's non-conserve mode, only one service should be used for IP if (services.size() != 1) { throw new InvalidParameterException("There are multiple services used ip " + ip.getAddress() + "."); } @@ -920,7 +920,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C ip6addr = ipv6AddrMgr.allocateGuestIpv6(network, ipv6Address); } } else if (network.getGuestType() == Network.GuestType.Shared) { - //for basic zone, need to provide the podId to ensure proper ip alloation + //for basic zone, need to provide the podId to ensure proper IP allocation Long podId = null; DataCenter dc = _dcDao.findById(network.getDataCenterId()); @@ -951,7 +951,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C } if (!StringUtils.isAllBlank(ipaddr, ip6addr)) { - // we got the ip addr so up the nics table and secodary ip + // we got the IP addr so up the nics table and secondary IP final String ip4AddrFinal = ipaddr; final String ip6AddrFinal = ip6addr; long id = Transaction.execute(new TransactionCallback() { @@ -1016,7 +1016,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C List ipList = _nicSecondaryIpDao.listByNicId(nicId); boolean lastIp = false; if (ipList.size() == 1) { - // this is the last secondary ip to nic + // this is the last secondary IP to NIC lastIp = true; } @@ -1027,7 +1027,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C logger.debug("Calling secondary ip " + secIpVO.getIp4Address() + " release "); if (dc.getNetworkType() == NetworkType.Advanced && network.getGuestType() == Network.GuestType.Isolated) { - //check PF or static NAT is configured on this ip address + //check PF or static NAT is configured on this IP address String secondaryIp = secIpVO.getIp4Address(); List fwRulesList = _firewallDao.listByNetworkAndPurpose(network.getId(), Purpose.PortForwarding); @@ -1039,7 +1039,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C } } } - //check if the secondary ip associated with any static nat rule + //check if the secondary IP associated with any static nat rule IPAddressVO publicIpVO = _ipAddressDao.findByIpAndNetworkId(secIpVO.getNetworkId(), secondaryIp); if (publicIpVO != null) { logger.debug("VM nic IP " + secondaryIp + " is associated with the static NAT rule public IP address id " + publicIpVO.getId()); @@ -1290,7 +1290,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C throw new IllegalArgumentException("only ip addresses that belong to a virtual network may be disassociated."); } - // don't allow releasing system ip address + // don't allow releasing system IP address if (ipVO.getSystem()) { throwInvalidIdException("Can't release system IP address with specified id", ipVO.getUuid(), "systemIpAddrId"); } @@ -1729,7 +1729,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C domainId, isDomainSpecific, subdomainAccess, vpcId, startIPv6, endIPv6, ip6Gateway, ip6Cidr, displayNetwork, aclId, secondaryVlanId, privateVlanType, ntwkOff, pNtwk, aclType, owner, cidr, createVlan, externalId, routerIPv4, routerIPv6, associatedNetwork, ip4Dns1, ip4Dns2, ip6Dns1, ip6Dns2, interfaceMTUs); - // retrieve, acquire and associate the correct ip adresses + // retrieve, acquire and associate the correct IP addresses checkAndSetRouterSourceNatIp(owner, cmd, network); if (hideIpAddressUsage) { @@ -1787,7 +1787,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C if (! userIps.isEmpty()) { try { _ipAddrMgr.updateSourceNatIpAddress(requestedIp, userIps); - } catch (Exception e) { // pokemon execption from transaction + } catch (Exception e) { // pokemon exception from transaction String msg = String.format("Update of source NAT ip to %s for network \"%s\"/%s failed due to %s", requestedIp.getAddress().addr(), network.getName(), network.getUuid(), e.getLocalizedMessage()); logger.error(msg); @@ -1806,7 +1806,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C } else { logger.info(String.format("updating network %s to have source NAT ip %s", cmd.getNetworkName(), sourceNatIp)); } - // check if the address is already aqcuired for this network + // check if the address is already acquired for this network IPAddressVO requestedIp = _ipAddressDao.findByIp(sourceNatIp); if (requestedIp == null || requestedIp.getAssociatedWithNetworkId() == null || ! requestedIp.getAssociatedWithNetworkId().equals(network.getId())) { logger.warn(String.format("Source NAT IP %s is not associated with network %s/%s. It cannot be used as source NAT IP.", @@ -1815,7 +1815,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C } // check if it is the current source NAT address if (requestedIp.isSourceNat()) { - logger.info(String.format("IP address %s is allready the source Nat address. Not updating!", sourceNatIp)); + logger.info(String.format("IP address %s is already the source Nat address. Not updating!", sourceNatIp)); return null; } return requestedIp; @@ -3051,7 +3051,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C // network offering and domain suffix can be updated for Isolated networks only in 3.0 if ((networkOfferingId != null || domainSuffix != null) && network.getGuestType() != GuestType.Isolated) { - throw new InvalidParameterValueException("NetworkOffering and domain suffix upgrade can be perfomed for Isolated networks only"); + throw new InvalidParameterValueException("NetworkOffering and domain suffix upgrade can be performed for Isolated networks only"); } boolean networkOfferingChanged = false; @@ -3953,7 +3953,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C return false; } - // Check all ips + // Check all IPs List userIps = _ipAddressDao.listByAssociatedNetwork(network.getId(), null); List publicIps = new ArrayList(); if (userIps != null && !userIps.isEmpty()) { @@ -4103,10 +4103,10 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C // add security group provider to the physical network addDefaultSecurityGroupProviderToPhysicalNetwork(pNetwork.getId()); - // add VPCVirtualRouter as the defualt network service provider + // add VPCVirtualRouter as the default network service provider addDefaultVpcVirtualRouterToPhysicalNetwork(pNetwork.getId()); - // add baremetal as the defualt network service provider + // add baremetal as the default network service provider addDefaultBaremetalProvidersToPhysicalNetwork(pNetwork.getId()); //Add Internal Load Balancer element as a default network service provider @@ -4187,7 +4187,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C } // If tags are null, then check if there are any other networks with null tags - // of the same traffic type. If so then dont update the tags + // of the same traffic type. If so then don't update the tags if (tags != null && tags.size() == 0) { checkForPhysicalNetworksWithoutTag(network); } @@ -4272,7 +4272,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C vnetsInDb.addAll(tempVnets); } - //sorting the vnets in Db to generate a comma separated list of the vnet string. + //sorting the vnets in Db to generate a comma separated list of the vnet string. if (vnetsInDb.size() != 0) { commaSeparatedStringOfVnetRanges = generateVnetString(new ArrayList(vnetsInDb)); } @@ -4316,7 +4316,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C // for GRE phynets allow up to 32bits // TODO: Not happy about this test. - // What about guru-like objects for physical networs? + // What about guru-like objects for physical networks? logger.debug("ISOLATION METHODS:" + network.getIsolationMethods()); // Java does not have unsigned types... if (network.getIsolationMethods().contains("GRE")) { @@ -5070,7 +5070,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C } if (enabledServices != null) { - // check if services can be turned of + // check if services can be turned off if (!element.canEnableIndividualServices()) { throw new InvalidParameterValueException("Cannot update set of Services for this Service Provider '" + provider.getProviderName() + "'"); } @@ -5228,7 +5228,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C } // Check if there are more than 1 physical network with null tags in same traffic type. - // If so then dont allow to add traffic type. + // If so then don't allow to add traffic type. List tags = network.getTags(); if (CollectionUtils.isEmpty(tags)) { checkForPhysicalNetworksWithoutTag(network, trafficType); @@ -5578,14 +5578,14 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C Network network = _networksDao.findById(networkId); if (network == null) { - // release the acquired IP addrress before throwing the exception + // release the acquired IP address before throwing the exception // else it will always be in allocating state releaseIpAddress(ipId); throw new InvalidParameterValueException("Invalid network id is given"); } if (network.getVpcId() != null) { - // release the acquired IP addrress before throwing the exception + // release the acquired IP address before throwing the exception // else it will always be in allocating state releaseIpAddress(ipId); throw new InvalidParameterValueException("Can't assign ip to the network directly when network belongs" + " to VPC.Specify vpcId to associate ip address to VPC"); @@ -5622,7 +5622,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C } // VALIDATE IP INFO - // if end ip is not specified, default it to startIp + // if end IP is not specified, default it to startIp if (!NetUtils.isValidIp4(startIp)) { throw new InvalidParameterValueException("Invalid format for the ip address parameter"); } @@ -5646,7 +5646,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C URI uri = BroadcastDomainType.fromString(broadcastUriString); uriString = uri.toString(); BroadcastDomainType tiep = BroadcastDomainType.getSchemeValue(uri); - // numeric vlan or vlan uri are ok for now + // numeric vlan or vlan URI are ok for now // TODO make a test for any supported scheme if (!(tiep == BroadcastDomainType.Vlan || tiep == BroadcastDomainType.Lswitch)) { throw new InvalidParameterValueException("unsupported type of broadcastUri specified: " + broadcastUriString); diff --git a/server/src/main/java/com/cloud/user/AccountManagerImpl.java b/server/src/main/java/com/cloud/user/AccountManagerImpl.java index d996b684b25..d1894b8fc47 100644 --- a/server/src/main/java/com/cloud/user/AccountManagerImpl.java +++ b/server/src/main/java/com/cloud/user/AccountManagerImpl.java @@ -863,7 +863,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M _messageBus.publish(_name, MESSAGE_REMOVE_ACCOUNT_EVENT, PublishScope.LOCAL, accountId); } - // delete all vm groups belonging to accont + // delete all vm groups belonging to account List groups = _vmGroupDao.listByAccountId(accountId); for (InstanceGroupVO group : groups) { if (!_vmMgr.deleteVmGroup(group.getId())) { diff --git a/systemvm/debian/opt/cloud/templates/conntrackd.conf.templ b/systemvm/debian/opt/cloud/templates/conntrackd.conf.templ index 9443db24743..3f64da4064b 100644 --- a/systemvm/debian/opt/cloud/templates/conntrackd.conf.templ +++ b/systemvm/debian/opt/cloud/templates/conntrackd.conf.templ @@ -22,7 +22,7 @@ Sync { # # Size of the resend queue (in objects). This is the maximum # number of objects that can be stored waiting to be confirmed - # via acknoledgment. If you keep this value low, the daemon + # via acknowledgment. If you keep this value low, the daemon # will have less chances to recover state-changes under message # omission. On the other hand, if you keep this value high, # the daemon will consume more memory to store dead objects. diff --git a/test/integration/component/maint/testpath_disable_enable_zone.py b/test/integration/component/maint/testpath_disable_enable_zone.py index 216161f1c6b..63642c0fd25 100644 --- a/test/integration/component/maint/testpath_disable_enable_zone.py +++ b/test/integration/component/maint/testpath_disable_enable_zone.py @@ -1273,7 +1273,7 @@ class TestDisableEnableCluster(cloudstackTestCase): self.assertEqual(len(exception_list), 0, - "Check if vm's are accesible" + "Check if vm's are accessible" ) # non-admin user should fail to create vm, snap, temp etc diff --git a/test/integration/component/test_acl_sharednetwork.py b/test/integration/component/test_acl_sharednetwork.py index 42f4a899e12..52209a378ab 100644 --- a/test/integration/component/test_acl_sharednetwork.py +++ b/test/integration/component/test_acl_sharednetwork.py @@ -949,7 +949,7 @@ class TestSharedNetwork(cloudstackTestCase): Validate that any other user in same domain is NOT allowed to deploy VM in a shared network created with scope="account" for an account """ - # deploy VM as user under the same domain but belonging to a different account from the acount that has a shared network with scope=account + # deploy VM as user under the same domain but belonging to a different account from the account that has a shared network with scope=account self.apiclient.connection.apiKey = self.user_d111b_apikey self.apiclient.connection.securityKey = self.user_d111b_secretkey diff --git a/test/integration/component/test_acl_sharednetwork_deployVM-impersonation.py b/test/integration/component/test_acl_sharednetwork_deployVM-impersonation.py index 36b71defadb..609af80b66c 100644 --- a/test/integration/component/test_acl_sharednetwork_deployVM-impersonation.py +++ b/test/integration/component/test_acl_sharednetwork_deployVM-impersonation.py @@ -1613,7 +1613,7 @@ class TestSharedNetworkImpersonation(cloudstackTestCase): Valiate that Domain admin is NOT able to deploy a VM for user in the same domain but belonging to a different account in a shared network with scope=account """ - # Deploy VM as user in a domain under the same domain but different account from the acount that has a shared network with scope=account + # Deploy VM as user in a domain under the same domain but different account from the account that has a shared network with scope=account self.apiclient.connection.apiKey = self.user_d1_apikey self.apiclient.connection.securityKey = self.user_d1_secretkey self.vmdata["name"] = self.acldata["vmD111B"]["name"] + "-shared-scope-domain-withsubdomainaccess-domain-admin" diff --git a/test/integration/component/test_advancedsg_networks.py b/test/integration/component/test_advancedsg_networks.py index 4b3b8a32fa1..60567ae82fd 100644 --- a/test/integration/component/test_advancedsg_networks.py +++ b/test/integration/component/test_advancedsg_networks.py @@ -611,7 +611,7 @@ class TestNetworksInAdvancedSG(cloudstackTestCase): with same subnet and vlan""" # Steps, - # 1. create two different accouts + # 1. create two different accounts # 2. create account specific shared networks in both accounts with same subnet and vlan id # Validations, diff --git a/test/integration/component/test_project_limits.py b/test/integration/component/test_project_limits.py index 87bbcf70784..74c231e6b8e 100644 --- a/test/integration/component/test_project_limits.py +++ b/test/integration/component/test_project_limits.py @@ -1066,7 +1066,7 @@ class TestMaxProjectNetworks(cloudstackTestCase): # Steps for validation # 1. Fetch max.account.networks from configurations - # 2. Create an account. Create account more that max.accout.network + # 2. Create an account. Create account more that max.account.network # 3. Create network should fail self.debug("Creating project with '%s' as admin" % diff --git a/test/integration/component/test_resource_limits.py b/test/integration/component/test_resource_limits.py index e2efc4344a9..25518257a33 100644 --- a/test/integration/component/test_resource_limits.py +++ b/test/integration/component/test_resource_limits.py @@ -1435,7 +1435,7 @@ class TestMaxAccountNetworks(cloudstackTestCase): # Steps for validation # 1. Fetch max.account.networks from configurations - # 2. Create an account. Create account more that max.accout.network + # 2. Create an account. Create account more that max.account.network # 3. Create network should fail config = Configurations.list( diff --git a/test/integration/component/test_snapshots_improvement.py b/test/integration/component/test_snapshots_improvement.py index c95d8205ee7..fde81025bca 100644 --- a/test/integration/component/test_snapshots_improvement.py +++ b/test/integration/component/test_snapshots_improvement.py @@ -542,7 +542,7 @@ class TestCreateSnapshot(cloudstackTestCase): def verify_Snapshots(self): try: - self.debug("Listing snapshots for accout : %s" % self.account.name) + self.debug("Listing snapshots for account : %s" % self.account.name) snapshots = self.get_Snapshots_For_Account( self.account.name, self.account.domainid) diff --git a/test/integration/smoke/test_attach_multiple_volumes.py b/test/integration/smoke/test_attach_multiple_volumes.py index 939764dc010..81199bcfdfa 100644 --- a/test/integration/smoke/test_attach_multiple_volumes.py +++ b/test/integration/smoke/test_attach_multiple_volumes.py @@ -211,7 +211,7 @@ class TestMultipleVolumeAttach(cloudstackTestCase): clusterid = host.clusterid storage_pools = StoragePool.list(self.apiClient, clusterid=clusterid) if len(storage_pools) < 2: - self.skipTest("at least two accesible primary storage pools needed for the vm to perform this test") + self.skipTest("at least two accessible primary storage pools needed for the vm to perform this test") return storage_pools diff --git a/test/integration/smoke/test_enable_account_settings_for_domain.py b/test/integration/smoke/test_enable_account_settings_for_domain.py index 09550ed1e27..fea80ee1297 100644 --- a/test/integration/smoke/test_enable_account_settings_for_domain.py +++ b/test/integration/smoke/test_enable_account_settings_for_domain.py @@ -391,7 +391,7 @@ class TestDedicatePublicIPRange(cloudstackTestCase): # (8) change domain setting (3) to original +30 # (9) list domain settings with name=(3), value should be same as (8) # (10) list account settings with name=(3), value should be same as (9)=(8) - # (11) change acount setting (3) to original +50 + # (11) change account setting (3) to original +50 # (12) list account settings with name=(3), value should be same as (10) """ @@ -484,7 +484,7 @@ class TestDedicatePublicIPRange(cloudstackTestCase): account_value = int(configs[0].value) self.assertEqual(new_domain_value, account_value, "Account setting is not equal to new value of global setting") - # (11) change acount setting (3) to original +50 + # (11) change account setting (3) to original +50 new_account_value = account_value + 50 Configurations.update( self.apiclient, diff --git a/tools/ngui/static/js/lib/angular.js b/tools/ngui/static/js/lib/angular.js index e960afe36d7..74e036b6c90 100644 --- a/tools/ngui/static/js/lib/angular.js +++ b/tools/ngui/static/js/lib/angular.js @@ -6428,11 +6428,11 @@ function setter(obj, path, setValue) { } /** - * Return the value accesible from the object by path. Any undefined traversals are ignored + * Return the value accessible from the object by path. Any undefined traversals are ignored * @param {Object} obj starting object * @param {string} path path to traverse * @param {boolean=true} bindFnToScope - * @returns value as accesbile by path + * @returns value as accessible by path */ //TODO(misko): this function needs to be removed function getter(obj, path, bindFnToScope) { From 283a4853aadd7ff7b44d50e4e879e394363daebd Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Tue, 28 May 2024 12:07:44 +0530 Subject: [PATCH 16/25] ui: fix create network access in deploy vm wizard (#9117) Fixes #9115 Signed-off-by: Abhishek Kumar --- ui/public/locales/en.json | 3 ++- ui/src/views/compute/DeployVM.vue | 2 +- ui/src/views/compute/wizard/NetworkSelection.vue | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 89abfe5981f..a913435dfc7 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -3029,7 +3029,8 @@ "message.network.offering.promiscuous.mode": "Applicable for guest Networks on VMware hypervisor only.\nReject - The switch drops any outbound frame from a virtual machine adapter with a source MAC address that is different from the one in the .vmx configuration file.\nAccept - The switch does not perform filtering, and permits all outbound frames.\nNone - Default to value from global setting.", "message.network.removenic": "Please confirm that want to remove this NIC, which will also remove the associated Network from the Instance.", "message.network.secondaryip": "Please confirm that you would like to acquire a new secondary IP for this NIC. \n NOTE: You need to manually configure the newly-acquired secondary IP inside the virtual machine.", -"message.network.selection": "Choose one or more Networks to attach the Instance to. A new Network can also be created here.", +"message.network.selection": "Choose one or more Networks to attach the Instance to.", +"message.network.selection.new.network": "A new Network can also be created here.", "message.network.updateip": "Please confirm that you would like to change the IP address for this NIC on the Instance.", "message.network.usage.info.data.points": "Each data point represents the difference in data traffic since the last data point.", "message.network.usage.info.sum.of.vnics": "The Network usage shown is made up of the sum of data traffic from all the vNICs in the Instance.", diff --git a/ui/src/views/compute/DeployVM.vue b/ui/src/views/compute/DeployVM.vue index ef4118959ea..95919461644 100644 --- a/ui/src/views/compute/DeployVM.vue +++ b/ui/src/views/compute/DeployVM.vue @@ -392,7 +392,7 @@