From c71ab9598e3634ec4a6816d65befb3f60523c32a Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 12 Jul 2024 18:40:55 +0530 Subject: [PATCH 01/10] test: refactor ActionEventInterceptorTest to prevent failures (#9384) Try to intercept test calss methods in new CallContext to prevent getting any leftover data during assertions. Signed-off-by: Abhishek Kumar --- .../event/ActionEventInterceptorTest.java | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/server/src/test/java/com/cloud/event/ActionEventInterceptorTest.java b/server/src/test/java/com/cloud/event/ActionEventInterceptorTest.java index 9211ce16759..35b39dc3d53 100644 --- a/server/src/test/java/com/cloud/event/ActionEventInterceptorTest.java +++ b/server/src/test/java/com/cloud/event/ActionEventInterceptorTest.java @@ -140,6 +140,7 @@ public class ActionEventInterceptorTest { } utils.init(); + CallContext.register(user, account); } /** @@ -152,6 +153,7 @@ public class ActionEventInterceptorTest { Mockito.when(configDao.getValue(Config.PublishActionEvent.key())).thenReturn("true"); componentContextMocked = Mockito.mockStatic(ComponentContext.class); Mockito.when(ComponentContext.getComponent(EventBus.class)).thenReturn(eventBus); + persistedEvents = new ArrayList<>(); //Needed for persist to actually set an ID that can be returned from the ActionEventUtils //methods. @@ -198,6 +200,7 @@ public class ActionEventInterceptorTest { utils.init(); componentContextMocked.close(); + CallContext.unregister(); } @Test @@ -228,11 +231,11 @@ public class ActionEventInterceptorTest { Object event = actionEventInterceptor.interceptStart(m, tester); Assert.assertNull(event); - Assert.assertEquals(persistedEvents.size(), 1); + Assert.assertEquals(1, persistedEvents.size()); EventVO eventVO = persistedEvents.get(0); - Assert.assertEquals(eventVO.getType(), EventTypes.EVENT_VM_START); - Assert.assertEquals(eventVO.getDescription(), "Starting VM"); - Assert.assertEquals(eventVO.getState(), com.cloud.event.Event.State.Started); + Assert.assertEquals(EventTypes.EVENT_VM_START, eventVO.getType()); + Assert.assertEquals(eventDescription, eventVO.getDescription()); + Assert.assertEquals(com.cloud.event.Event.State.Started, eventVO.getState()); } @Test @@ -241,12 +244,12 @@ public class ActionEventInterceptorTest { Method m = tester.getClass().getMethod("testMethod"); actionEventInterceptor.interceptComplete(m, tester, null); - Assert.assertEquals(persistedEvents.size(), 1); + Assert.assertEquals(1, persistedEvents.size()); EventVO eventVO = persistedEvents.get(0); - Assert.assertEquals(eventVO.getType(), eventType); + Assert.assertEquals(eventType, eventVO.getType()); Assert.assertTrue(eventVO.getDescription().endsWith(eventDescription)); - Assert.assertEquals(eventVO.getLevel(), EventVO.LEVEL_INFO); - Assert.assertEquals(eventVO.getState(), com.cloud.event.Event.State.Completed); + Assert.assertEquals(EventVO.LEVEL_INFO, eventVO.getLevel()); + Assert.assertEquals(com.cloud.event.Event.State.Completed, eventVO.getState()); } @Test @@ -255,17 +258,16 @@ public class ActionEventInterceptorTest { Method m = tester.getClass().getMethod("testMethod"); actionEventInterceptor.interceptException(m, tester, null); - Assert.assertEquals(persistedEvents.size(), 1); + Assert.assertEquals(1, persistedEvents.size()); EventVO eventVO = persistedEvents.get(0); - Assert.assertEquals(eventVO.getType(), eventType); + Assert.assertEquals(eventType, eventVO.getType()); Assert.assertTrue(eventVO.getDescription().endsWith(eventDescription)); - Assert.assertEquals(eventVO.getLevel(), EventVO.LEVEL_ERROR); - Assert.assertEquals(eventVO.getState(), com.cloud.event.Event.State.Completed); + Assert.assertEquals(EventVO.LEVEL_ERROR, eventVO.getLevel()); + Assert.assertEquals(com.cloud.event.Event.State.Completed, eventVO.getState()); } @Test public void testInterceptExceptionResource() throws NoSuchMethodException { - CallContext.register(user, account); Long resourceId = 1L; ApiCommandResourceType resourceType = ApiCommandResourceType.VirtualMachine; CallContext.current().setEventResourceId(resourceId); @@ -274,15 +276,14 @@ public class ActionEventInterceptorTest { Method m = tester.getClass().getMethod("testMethod"); actionEventInterceptor.interceptException(m, tester, null); - Assert.assertEquals(persistedEvents.size(), 1); + Assert.assertEquals(1, persistedEvents.size()); EventVO eventVO = persistedEvents.get(0); - Assert.assertEquals(eventVO.getType(), eventType); + Assert.assertEquals(eventType, eventVO.getType()); Assert.assertTrue(eventVO.getDescription().endsWith(eventDescription)); - Assert.assertEquals(eventVO.getLevel(), EventVO.LEVEL_ERROR); - Assert.assertEquals(eventVO.getState(), com.cloud.event.Event.State.Completed); - Assert.assertEquals(eventVO.getResourceId(), resourceId); - Assert.assertEquals(eventVO.getResourceType(), resourceType.toString()); - CallContext.unregister(); + Assert.assertEquals(EventVO.LEVEL_ERROR, eventVO.getLevel()); + Assert.assertEquals(com.cloud.event.Event.State.Completed, eventVO.getState()); + Assert.assertEquals(resourceId, eventVO.getResourceId()); + Assert.assertEquals(resourceType.toString(), eventVO.getResourceType()); } @Test From d9f77b841c5c19d92bea82caf65e9adbf18fbe00 Mon Sep 17 00:00:00 2001 From: Suresh Kumar Anaparti Date: Sun, 14 Jul 2024 14:50:26 +0530 Subject: [PATCH 02/10] Ignore non-managed pools for storage pool access preparation (#9376) --- .../src/main/java/com/cloud/storage/StorageManagerImpl.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java index 74b19b61fd4..73b9ac8960d 100644 --- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java @@ -2788,14 +2788,10 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C @Override public boolean canHostPrepareStoragePoolAccess(Host host, StoragePool pool) { - if (host == null || pool == null) { + if (host == null || pool == null || !pool.isManaged()) { return false; } - if (!pool.isManaged()) { - return true; - } - DataStoreProvider storeProvider = _dataStoreProviderMgr.getDataStoreProvider(pool.getStorageProviderName()); DataStoreDriver storeDriver = storeProvider.getDataStoreDriver(); return storeDriver instanceof PrimaryDataStoreDriver && ((PrimaryDataStoreDriver)storeDriver).canHostPrepareStoragePoolAccess(host, pool); From 22ef08154dc89ccce27121578cabfa3b5030220d Mon Sep 17 00:00:00 2001 From: Vishesh Date: Sun, 14 Jul 2024 14:58:36 +0530 Subject: [PATCH 03/10] Switch back to CLOUD_DB after purging usage records (#9367) --- .../com/cloud/usage/dao/UsageDaoImpl.java | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/usage/dao/UsageDaoImpl.java b/engine/schema/src/main/java/com/cloud/usage/dao/UsageDaoImpl.java index 4553ed822b4..038d17a85a3 100644 --- a/engine/schema/src/main/java/com/cloud/usage/dao/UsageDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/usage/dao/UsageDaoImpl.java @@ -28,6 +28,7 @@ import com.cloud.utils.db.QueryBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; import com.cloud.utils.db.TransactionCallback; +import com.cloud.utils.db.TransactionCallbackNoReturn; import com.cloud.utils.db.TransactionLegacy; import com.cloud.utils.db.TransactionStatus; import com.cloud.utils.exception.CloudRuntimeException; @@ -469,21 +470,25 @@ public class UsageDaoImpl extends GenericDaoBase implements Usage @Override public void removeOldUsageRecords(int days) { - String sql = DELETE_ALL_BY_INTERVAL; - TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB); - PreparedStatement pstmt = null; - try { - txn.start(); - pstmt = txn.prepareAutoCloseStatement(sql); - pstmt.setLong(1, days); - pstmt.executeUpdate(); - txn.commit(); - } catch (Exception ex) { - txn.rollback(); - s_logger.error("error removing old cloud_usage records for interval: " + days); - } finally { - txn.close(); - } + Transaction.execute(TransactionLegacy.USAGE_DB, new TransactionCallbackNoReturn() { + @Override + public void doInTransactionWithoutResult(TransactionStatus status) { + TransactionLegacy txn = TransactionLegacy.currentTxn(); + PreparedStatement pstmt = null; + try { + txn.start(); + pstmt = txn.prepareAutoCloseStatement(DELETE_ALL_BY_INTERVAL); + pstmt.setLong(1, days); + pstmt.executeUpdate(); + txn.commit(); + } catch (Exception ex) { + txn.rollback(); + s_logger.error("error removing old cloud_usage records for interval: " + days); + } finally { + txn.close(); + } + } + }); } public UsageVO persistUsage(final UsageVO usage) { From 877c4d9a64b11ec1a692d5afd1cad9f6d17dab75 Mon Sep 17 00:00:00 2001 From: Suresh Kumar Anaparti Date: Mon, 15 Jul 2024 00:56:23 +0530 Subject: [PATCH 04/10] LibvirtOvsFetchInterfaceCommandWrapperTest fix (test fails in mac) - skip it if no interfaces with eth and wl (#9382) * test fix (fails in mac) - skip it if no interfaces with eth and wl * review comments --- .../LibvirtOvsFetchInterfaceCommandWrapperTest.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtOvsFetchInterfaceCommandWrapperTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtOvsFetchInterfaceCommandWrapperTest.java index fbc9c2bcb4b..b0df5519467 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtOvsFetchInterfaceCommandWrapperTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtOvsFetchInterfaceCommandWrapperTest.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.UUID; import org.junit.Assert; +import org.junit.Assume; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Spy; @@ -51,8 +52,7 @@ public class LibvirtOvsFetchInterfaceCommandWrapperTest { while(interfaces.hasMoreElements()) { NetworkInterface networkInterface = interfaces.nextElement(); if (networkInterface.getInetAddresses().hasMoreElements() && - (networkInterface.getName().startsWith("eth") || - networkInterface.getName().startsWith("wl"))) { + networkInterface.getName().matches("^(eth|wl|en).*")) { interfaceName = networkInterface.getName(); Enumeration addresses = networkInterface.getInetAddresses(); while(addresses.hasMoreElements()) { @@ -62,9 +62,13 @@ public class LibvirtOvsFetchInterfaceCommandWrapperTest { break; }; } + if (StringUtils.isNotBlank(interfaceName) && StringUtils.isNotBlank(ipAddress)) { + break; + } } } } catch (SocketException ignored) {} + Assume.assumeTrue(StringUtils.isNotBlank(interfaceName)); Ternary result = null; try { result = wrapper.getInterfaceDetails(interfaceName); From 50586a948165a995a64e1bfe40e2ee6e6fb4c595 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 15 Jul 2024 09:44:39 +0530 Subject: [PATCH 05/10] UI assorted fixes (#9381) * config.json: make configuration names consistent with other Makes login related config param to be consistent with the original `loginFooter`. Group them together. Signed-off-by: Rohit Yadav * ui: assorted UI fixes and copy console URL fix This brings in related buttons across some infra views and new columns which are missing. Also fixes the copy console URL issue on some browsers. Signed-off-by: Rohit Yadav --------- Signed-off-by: Rohit Yadav --- ui/public/config.json | 4 ++-- ui/public/index.html | 4 ++-- ui/public/locales/en.json | 1 + ui/src/components/view/InfoCard.vue | 12 ---------- ui/src/components/widgets/Console.vue | 9 +------ ui/src/config/section/account.js | 24 +++++++++++++++++++ ui/src/config/section/domain.js | 16 +++++++++++++ ui/src/config/section/infra/hosts.js | 2 +- .../config/section/infra/managementServers.js | 4 ++-- 9 files changed, 49 insertions(+), 27 deletions(-) diff --git a/ui/public/config.json b/ui/public/config.json index 57d120aed5e..639ed4f97f1 100644 --- a/ui/public/config.json +++ b/ui/public/config.json @@ -10,12 +10,12 @@ "docBase": "http://docs.cloudstack.apache.org/en/latest", "appTitle": "CloudStack", "footer": "Licensed under the Apache License, Version 2.0.", + "loginTitle": "CloudStack", + "loginFavicon": "assets/logo.svg", "loginFooter": "", "logo": "assets/logo.svg", "minilogo": "assets/mini-logo.svg", "banner": "assets/banner.svg", - "loginPageTitle": "CloudStack", - "loginPageFavicon": "assets/logo.svg", "error": { "403": "assets/403.png", "404": "assets/404.png", diff --git a/ui/public/index.html b/ui/public/index.html index 1a09e46a4e0..0e6521418cb 100644 --- a/ui/public/index.html +++ b/ui/public/index.html @@ -58,8 +58,8 @@ fetch('./config.json') .then(response => response.json()) .then(data => { - document.getElementById("favicon").setAttribute("href", data.loginPageFavicon); - document.getElementById("title").innerHTML = data.loginPageTitle; + document.getElementById("favicon").setAttribute("href", data.loginFavicon); + document.getElementById("title").innerHTML = data.loginTitle; }).catch((err) => {}); diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index c5d87d208b4..3931dae598f 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -1891,6 +1891,7 @@ "label.service.connectivity.distributedroutercapabilitycheckbox": "Distributed router", "label.service.connectivity.regionlevelvpccapabilitycheckbox": "Region level VPC", "label.service.group": "Service group", +"label.serviceip": "Service IP", "label.service.lb.elasticlbcheckbox": "Elastic LB", "label.service.lb.inlinemodedropdown": "Mode", "label.service.lb.lbisolationdropdown": "LB isolation", diff --git a/ui/src/components/view/InfoCard.vue b/ui/src/components/view/InfoCard.vue index 6a0329ada8f..bb6726d75f1 100644 --- a/ui/src/components/view/InfoCard.vue +++ b/ui/src/components/view/InfoCard.vue @@ -104,18 +104,6 @@ v-if="resource.id" /> - - - - diff --git a/ui/src/components/widgets/Console.vue b/ui/src/components/widgets/Console.vue index ae0a034de02..6c16c7546a7 100644 --- a/ui/src/components/widgets/Console.vue +++ b/ui/src/components/widgets/Console.vue @@ -56,17 +56,10 @@ export default { this.url = (json && json.createconsoleendpointresponse) ? json.createconsoleendpointresponse.consoleendpoint.url : '#/exception/404' if (json.createconsoleendpointresponse.consoleendpoint.success) { if (this.copyUrlToClipboard) { + this.$copyText(this.url) this.$message.success({ content: this.$t('label.copied.clipboard') }) - const hiddenElement = document.createElement('textarea') - hiddenElement.value = this.url - document.body.appendChild(hiddenElement) - hiddenElement.focus() - hiddenElement.select() - - document.execCommand('copy') - document.body.removeChild(hiddenElement) } else { window.open(this.url, '_blank') } diff --git a/ui/src/config/section/account.js b/ui/src/config/section/account.js index a35b2b9d5f0..28c0e3f556d 100644 --- a/ui/src/config/section/account.js +++ b/ui/src/config/section/account.js @@ -31,6 +31,30 @@ export default { name: 'accountuser', title: 'label.users', param: 'account' + }, { + name: 'vm', + title: 'label.vms', + param: 'account' + }, { + name: 'volume', + title: 'label.volumes', + param: 'account' + }, { + name: 'guestnetwork', + title: 'label.networks', + param: 'account' + }, { + name: 'ssh', + title: 'label.sshkeypairs', + param: 'account' + }, { + name: 'userdata', + title: 'label.userdata', + param: 'account' + }, { + name: 'template', + title: 'label.templates', + param: 'account' }], filters: () => { const filters = ['enabled', 'disabled', 'locked'] diff --git a/ui/src/config/section/domain.js b/ui/src/config/section/domain.js index a8648b10f76..e6807f06278 100644 --- a/ui/src/config/section/domain.js +++ b/ui/src/config/section/domain.js @@ -32,6 +32,22 @@ export default { name: 'account', title: 'label.accounts', param: 'domainid' + }, { + name: 'vm', + title: 'label.vms', + param: 'domainid' + }, { + name: 'volume', + title: 'label.volumes', + param: 'domainid' + }, { + name: 'guestnetwork', + title: 'label.networks', + param: 'domainid' + }, { + name: 'template', + title: 'label.templates', + param: 'domainid' }], tabs: [ { diff --git a/ui/src/config/section/infra/hosts.js b/ui/src/config/section/infra/hosts.js index 81ca0c917b2..de42762c274 100644 --- a/ui/src/config/section/infra/hosts.js +++ b/ui/src/config/section/infra/hosts.js @@ -32,7 +32,7 @@ export default { }, params: { type: 'routing' }, columns: () => { - const fields = ['name', 'state', 'resourcestate', 'ipaddress', 'hypervisor', 'instances', 'powerstate'] + const fields = ['name', 'state', 'resourcestate', 'ipaddress', 'hypervisor', 'instances', 'powerstate', 'version'] const metricsFields = ['cpunumber', 'cputotalghz', 'cpuusedghz', 'cpuallocatedghz', 'memorytotalgb', 'memoryusedgb', 'memoryallocatedgb', 'networkread', 'networkwrite'] if (store.getters.metrics) { fields.push(...metricsFields) diff --git a/ui/src/config/section/infra/managementServers.js b/ui/src/config/section/infra/managementServers.js index d1dfa6df70d..cda19ef7cd5 100644 --- a/ui/src/config/section/infra/managementServers.js +++ b/ui/src/config/section/infra/managementServers.js @@ -26,8 +26,8 @@ export default { permission: ['listManagementServersMetrics'], resourceType: 'ManagementServer', columns: () => { - const fields = ['name', 'state', 'version'] - const metricsFields = ['collectiontime', 'availableprocessors', 'cpuload', 'heapmemoryused', 'agentcount'] + const fields = ['name', 'state', 'serviceip', 'version', 'osdistribution', 'agentcount'] + const metricsFields = ['collectiontime', 'availableprocessors', 'cpuload', 'heapmemoryused'] if (store.getters.metrics) { fields.push(...metricsFields) } From 2cfb541a1d7875d1beb25b2199303683d472ddcd Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Mon, 15 Jul 2024 09:45:28 +0530 Subject: [PATCH 06/10] saml: purge token after first response and improve setting description (#9377) * saml: purge token after first response and improve setting description This improves the description of a saml signature checking global setting, and purges the SAML token upon handling the first SAML response. Signed-off-by: Rohit Yadav * fix failing unit test Signed-off-by: Rohit Yadav --------- Signed-off-by: Rohit Yadav --- .../SAML2LoginAPIAuthenticatorCmd.java | 1 + .../cloudstack/saml/SAML2AuthManager.java | 19 ++++++++++--------- .../cloudstack/saml/SAML2AuthManagerImpl.java | 7 +++++++ .../SAML2LoginAPIAuthenticatorCmdTest.java | 4 ++-- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmd.java b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmd.java index fd4da7a59b2..332e0602784 100644 --- a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmd.java +++ b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmd.java @@ -228,6 +228,7 @@ public class SAML2LoginAPIAuthenticatorCmd extends BaseCmd implements APIAuthent "Received SAML response for a SSO request that we may not have made or has expired, please try logging in again", params, responseType)); } + samlAuthManager.purgeToken(token); // Set IdpId for this session session.setAttribute(SAMLPluginConstants.SAML_IDPID, issuer.getValue()); diff --git a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManager.java b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManager.java index 27f17cee6b1..3a4030f9c0d 100644 --- a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManager.java +++ b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManager.java @@ -71,16 +71,17 @@ public interface SAML2AuthManager extends PluggableAPIAuthenticator, PluggableSe "SAML2 IDP Metadata refresh interval in seconds, minimum value is set to 300", true); ConfigKey SAMLCheckSignature = new ConfigKey("Advanced", Boolean.class, "saml2.check.signature", "true", - "Whether SAML2 signature must be checked, when enforced and when the SAML response does not have a signature would lead to login exception", true); + "When enabled (default and recommended), SAML2 signature checks are enforced and lack of signature in the SAML SSO response will cause login exception. Disabling this is not advisable but provided for backward compatibility for users who are able to accept the risks.", false); - public SAMLProviderMetadata getSPMetadata(); - public SAMLProviderMetadata getIdPMetadata(String entityId); - public Collection getAllIdPMetadata(); + SAMLProviderMetadata getSPMetadata(); + SAMLProviderMetadata getIdPMetadata(String entityId); + Collection getAllIdPMetadata(); - public boolean isUserAuthorized(Long userId, String entityId); - public boolean authorizeUser(Long userId, String entityId, boolean enable); + boolean isUserAuthorized(Long userId, String entityId); + boolean authorizeUser(Long userId, String entityId, boolean enable); - public void saveToken(String authnId, String domain, String entity); - public SAMLTokenVO getToken(String authnId); - public void expireTokens(); + void saveToken(String authnId, String domain, String entity); + SAMLTokenVO getToken(String authnId); + void purgeToken(SAMLTokenVO token); + void expireTokens(); } diff --git a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java index 3ecebf4d185..dfa76414fb7 100644 --- a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java +++ b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java @@ -487,6 +487,13 @@ public class SAML2AuthManagerImpl extends AdapterBase implements SAML2AuthManage return _samlTokenDao.findByUuid(authnId); } + @Override + public void purgeToken(SAMLTokenVO token) { + if (token != null) { + _samlTokenDao.remove(token.getId()); + } + } + @Override public void expireTokens() { _samlTokenDao.expireTokens(); diff --git a/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java b/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java index ebdc5be8fe9..48a3139052d 100644 --- a/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java +++ b/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java @@ -279,7 +279,7 @@ public class SAML2LoginAPIAuthenticatorCmdTest { @Test public void testFailOnSAMLSignatureCheckWhenFalse() throws NoSuchFieldException, IllegalAccessException { - overrideDefaultConfigValue(SAML2AuthManager.SAMLCheckSignature, "_defaultValue", "false"); + overrideDefaultConfigValue(SAML2AuthManager.SAMLCheckSignature, "_value", false); SAML2LoginAPIAuthenticatorCmd cmd = new SAML2LoginAPIAuthenticatorCmd(); try { cmd.checkAndFailOnMissingSAMLSignature(null); @@ -290,7 +290,7 @@ public class SAML2LoginAPIAuthenticatorCmdTest { @Test(expected = ServerApiException.class) public void testFailOnSAMLSignatureCheckWhenTrue() throws NoSuchFieldException, IllegalAccessException { - overrideDefaultConfigValue(SAML2AuthManager.SAMLCheckSignature, "_defaultValue", "true"); + overrideDefaultConfigValue(SAML2AuthManager.SAMLCheckSignature, "_value", true); SAML2LoginAPIAuthenticatorCmd cmd = new SAML2LoginAPIAuthenticatorCmd(); cmd.checkAndFailOnMissingSAMLSignature(null); } From 6a8494be3be37c58f2b9ff1fb8f8d76d186cc987 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 15 Jul 2024 09:46:29 +0530 Subject: [PATCH 07/10] engine-schema,cks: fix finding non removed network vms (#9339) Fixes #9331 Only those VMs should be considered network VM which have a NIC entry that is not marked removed. Signed-off-by: Abhishek Kumar --- .../schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java index e41c706a9cb..a1bd25c2fbc 100755 --- a/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -856,6 +856,7 @@ public class VMInstanceDaoImpl extends GenericDaoBase implem SearchBuilder nicSearch = nicDao.createSearchBuilder(); nicSearch.and("networkId", nicSearch.entity().getNetworkId(), SearchCriteria.Op.EQ); + nicSearch.and("removed", nicSearch.entity().getRemoved(), SearchCriteria.Op.NULL); NetworkTypeSearch = createSearchBuilder(); NetworkTypeSearch.and("types", NetworkTypeSearch.entity().getType(), SearchCriteria.Op.IN); From 7db83db3dd9b1d85f3a30e4807e1353d572a69cb Mon Sep 17 00:00:00 2001 From: Fabricio Duarte Date: Sat, 13 Jul 2024 16:32:19 -0300 Subject: [PATCH 08/10] Fix radio buttons in instance migration pop-up (#8836) --- ui/src/views/compute/MigrateVMStorage.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/views/compute/MigrateVMStorage.vue b/ui/src/views/compute/MigrateVMStorage.vue index a67e7a5244f..139ff856a2a 100644 --- a/ui/src/views/compute/MigrateVMStorage.vue +++ b/ui/src/views/compute/MigrateVMStorage.vue @@ -24,7 +24,7 @@ {{ $t('label.migrate.instance.single.storage') }} From 21c98af13de80a8e09284013aafdc6f450db8298 Mon Sep 17 00:00:00 2001 From: Vishesh Date: Mon, 15 Jul 2024 15:53:00 +0530 Subject: [PATCH 09/10] Fix backup offering buttons for instances in data view (#9391) --- 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 270d16831d6..4c5a61e3bdc 100644 --- a/ui/src/config/section/compute.js +++ b/ui/src/config/section/compute.js @@ -32,7 +32,7 @@ export default { getApiToCall: () => store.getters.metrics ? 'listVirtualMachinesMetrics' : 'listVirtualMachines', resourceType: 'UserVm', params: () => { - var params = { details: 'group,nics,secgrp,tmpl,servoff,diskoff,iso,volume,affgrp' } + var params = { details: 'group,nics,secgrp,tmpl,servoff,diskoff,iso,volume,affgrp,backoff' } if (store.getters.metrics) { params = { details: 'all,stats' } } From 8a00e25de9123794ab96baf0af799678e336d934 Mon Sep 17 00:00:00 2001 From: Suresh Kumar Anaparti Date: Mon, 15 Jul 2024 17:03:59 +0530 Subject: [PATCH 10/10] Fix list backups after backup vm is expunged (#9392) --- .../cloudstack/api/command/user/backup/ListBackupsCmd.java | 3 +++ api/src/main/java/org/apache/cloudstack/backup/Backup.java | 1 + .../main/java/org/apache/cloudstack/backup/BackupVO.java | 1 + .../org/apache/cloudstack/backup/dao/BackupDaoImpl.java | 6 +++++- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java index 8597d97278c..57a1de2f105 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java @@ -36,6 +36,7 @@ import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.backup.Backup; import org.apache.cloudstack.backup.BackupManager; import org.apache.cloudstack.context.CallContext; +import org.apache.log4j.Logger; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; @@ -49,6 +50,7 @@ import com.cloud.utils.Pair; responseObject = BackupResponse.class, since = "4.14.0", authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class ListBackupsCmd extends BaseListProjectAndAccountResourcesCmd { + private static final Logger s_logger = Logger.getLogger(ListBackupsCmd.class); @Inject private BackupManager backupManager; @@ -116,6 +118,7 @@ public class ListBackupsCmd extends BaseListProjectAndAccountResourcesCmd { Pair, Integer> result = backupManager.listBackups(this); setupResponseBackupList(result.first(), result.second()); } catch (Exception e) { + s_logger.debug("Exception while listing backups", e); throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); } } diff --git a/api/src/main/java/org/apache/cloudstack/backup/Backup.java b/api/src/main/java/org/apache/cloudstack/backup/Backup.java index 75c7ab4cca5..0a5c8634927 100644 --- a/api/src/main/java/org/apache/cloudstack/backup/Backup.java +++ b/api/src/main/java/org/apache/cloudstack/backup/Backup.java @@ -132,6 +132,7 @@ public interface Backup extends ControlledEntity, InternalIdentity, Identity { } long getVmId(); + long getBackupOfferingId(); String getExternalId(); String getType(); String getDate(); diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java index 2ecbfd56460..76127da26e2 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java @@ -155,6 +155,7 @@ public class BackupVO implements Backup { this.status = status; } + @Override public long getBackupOfferingId() { return backupOfferingId; } diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java index fefbb68ae77..8628fe8e01b 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java @@ -145,7 +145,11 @@ public class BackupDaoImpl extends GenericDaoBase implements Bac AccountVO account = accountDao.findByIdIncludingRemoved(vm.getAccountId()); DomainVO domain = domainDao.findByIdIncludingRemoved(vm.getDomainId()); DataCenterVO zone = dataCenterDao.findByIdIncludingRemoved(vm.getDataCenterId()); - BackupOffering offering = backupOfferingDao.findByIdIncludingRemoved(vm.getBackupOfferingId()); + Long offeringId = vm.getBackupOfferingId(); + if (offeringId == null) { + offeringId = backup.getBackupOfferingId(); + } + BackupOffering offering = backupOfferingDao.findByIdIncludingRemoved(offeringId); BackupResponse response = new BackupResponse(); response.setId(backup.getUuid());