From 5f8450f28f1272bb2a3b73e3a5c88e717cb6e910 Mon Sep 17 00:00:00 2001 From: dahn Date: Fri, 19 Apr 2024 09:18:41 +0200 Subject: [PATCH 0001/1050] Add a shutdownhook to remove jobs owned by the process (#8896) Co-authored-by: Suresh Kumar Anaparti --- .../java/com/cloud/usage/UsageManagerImpl.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java index dd838f2f3ff..29f8a8decdd 100644 --- a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java @@ -316,6 +316,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna _sanity = _sanityExecutor.scheduleAtFixedRate(new SanityCheck(), 1, _sanityCheckInterval, TimeUnit.DAYS); } + Runtime.getRuntime().addShutdownHook(new AbandonJob()); TransactionLegacy usageTxn = TransactionLegacy.open(TransactionLegacy.USAGE_DB); try { if (_heartbeatLock.lock(3)) { // 3 second timeout @@ -345,9 +346,11 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna if (_sanity != null) { _sanity.cancel(true); } + return true; } + @Override public void run() { (new ManagedContextRunnable() { @@ -2183,4 +2186,17 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna } } } + private class AbandonJob extends Thread { + @Override + public void run() { + s_logger.info("exitting Usage Manager"); + deleteOpenjob(); + } + private void deleteOpenjob() { + UsageJobVO job = _usageJobDao.isOwner(_hostname, _pid); + if (job != null) { + _usageJobDao.remove(job.getId()); + } + } + } } From d4a5459a8300a37712bb0bd60b21bb1baf52ea91 Mon Sep 17 00:00:00 2001 From: Vishesh Date: Fri, 19 Apr 2024 15:01:51 +0530 Subject: [PATCH 0002/1050] UI: Fix missing locale strings for Status widget (#8792) --- ui/src/components/widgets/Status.vue | 29 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/ui/src/components/widgets/Status.vue b/ui/src/components/widgets/Status.vue index 62438820314..73b1a9af930 100644 --- a/ui/src/components/widgets/Status.vue +++ b/ui/src/components/widgets/Status.vue @@ -166,23 +166,24 @@ export default { if (!(state && this.displayText)) { return '' } + let result if (this.$route.path === '/vmsnapshot' || this.$route.path.includes('/vmsnapshot/')) { - return this.$t('message.vmsnapshot.state.' + state.toLowerCase()) + result = this.$t('message.vmsnapshot.state.' + state.toLowerCase()) + } else if (this.$route.path === '/vm' || this.$route.path.includes('/vm/')) { + result = this.$t('message.vm.state.' + state.toLowerCase()) + } else if (this.$route.path === '/volume' || this.$route.path.includes('/volume/')) { + result = this.$t('message.volume.state.' + state.toLowerCase()) + } else if (this.$route.path === '/guestnetwork' || this.$route.path.includes('/guestnetwork/')) { + result = this.$t('message.guestnetwork.state.' + state.toLowerCase()) + } else if (this.$route.path === '/publicip' || this.$route.path.includes('/publicip/')) { + result = this.$t('message.publicip.state.' + state.toLowerCase()) } - if (this.$route.path === '/vm' || this.$route.path.includes('/vm/')) { - return this.$t('message.vm.state.' + state.toLowerCase()) + + if (!result || (result.startsWith('message.') && result.endsWith('.state.' + state.toLowerCase()))) { + // Nothing for snapshots, vpcs, gateways, vnpnconn, vpnuser, kubectl, event, project, account, infra. They're all self explanatory + result = this.$t(state) } - if (this.$route.path === '/volume' || this.$route.path.includes('/volume/')) { - return this.$t('message.volume.state.' + state.toLowerCase()) - } - if (this.$route.path === '/guestnetwork' || this.$route.path.includes('/guestnetwork/')) { - return this.$t('message.guestnetwork.state.' + state.toLowerCase()) - } - if (this.$route.path === '/publicip' || this.$route.path.includes('/publicip/')) { - return this.$t('message.publicip.state.' + state.toLowerCase()) - } - // Nothing for snapshots, vpcs, gateways, vnpnconn, vpnuser, kubectl, event, project, account, infra. They're all self explanatory - return this.$t(state) + return result }, getStyle () { let styles = { display: 'inline-flex' } From 7affbb1dacf709424b33f30a5305c44ea201acd4 Mon Sep 17 00:00:00 2001 From: dahn Date: Fri, 19 Apr 2024 12:23:31 +0200 Subject: [PATCH 0003/1050] protect against null-path (#8915) Co-authored-by: Vladimir Dombrovski Co-authored-by: Vishesh Co-authored-by: Suresh Kumar Anaparti --- .../com/cloud/hypervisor/vmware/resource/VmwareResource.java | 5 ++++- systemvm/debian/etc/logrotate.d/haproxy | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java index b65a7847675..0612ed70510 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -3066,7 +3066,10 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes } private String appendFileType(String path, String fileType) { - if (path.toLowerCase().endsWith(fileType.toLowerCase())) { + if (StringUtils.isBlank(path)) { + throw new CloudRuntimeException("No path given, cannot append filetype " + fileType); + } + if (fileType == null || path.toLowerCase().endsWith(fileType.toLowerCase())) { return path; } diff --git a/systemvm/debian/etc/logrotate.d/haproxy b/systemvm/debian/etc/logrotate.d/haproxy index 464209791a3..a6b72b6f77a 100644 --- a/systemvm/debian/etc/logrotate.d/haproxy +++ b/systemvm/debian/etc/logrotate.d/haproxy @@ -4,6 +4,6 @@ notifempty maxsize 10M postrotate - /bin/kill -HUP `cat /var/run/rsyslog.pid 2> /dev/null` 2> /dev/null || true + /usr/lib/rsyslog/rsyslog-rotate endscript } From e1922da249938157ea9ea01000feb964b5c96381 Mon Sep 17 00:00:00 2001 From: dahn Date: Fri, 19 Apr 2024 14:21:18 +0200 Subject: [PATCH 0004/1050] merge forward error in logger name (#8949) --- usage/src/main/java/com/cloud/usage/UsageManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java index b036bc3c520..4831b6794e4 100644 --- a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java @@ -2247,7 +2247,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna private class AbandonJob extends Thread { @Override public void run() { - s_logger.info("exitting Usage Manager"); + logger.info("exitting Usage Manager"); deleteOpenjob(); } private void deleteOpenjob() { From 8ff2c018cc5b3fc69bcd8756695d04b384e46ab8 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Fri, 19 Apr 2024 15:10:38 +0200 Subject: [PATCH 0005/1050] test: fix test failures in ActionEventInterceptorTest (#8938) * test: fix test failures in ActionEventInterceptorTest ``` Error: Failures: Error: ActionEventInterceptorTest.testInterceptComplete:247 Error: ActionEventInterceptorTest.testInterceptException:261 Error: ActionEventInterceptorTest.testInterceptStartAsync:234 expected: but was: ``` * Update 8938: move CallContext.unregister as well --- .../java/com/cloud/event/ActionEventInterceptorTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 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..109cb585d8e 100644 --- a/server/src/test/java/com/cloud/event/ActionEventInterceptorTest.java +++ b/server/src/test/java/com/cloud/event/ActionEventInterceptorTest.java @@ -172,6 +172,7 @@ public class ActionEventInterceptorTest { account.setId(ACCOUNT_ID); user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN); + CallContext.register(user, account); Mockito.when(accountDao.findById(ACCOUNT_ID)).thenReturn(account); } @@ -197,6 +198,8 @@ public class ActionEventInterceptorTest { utils.init(); + CallContext.unregister(); + componentContextMocked.close(); } @@ -265,7 +268,6 @@ public class ActionEventInterceptorTest { @Test public void testInterceptExceptionResource() throws NoSuchMethodException { - CallContext.register(user, account); Long resourceId = 1L; ApiCommandResourceType resourceType = ApiCommandResourceType.VirtualMachine; CallContext.current().setEventResourceId(resourceId); @@ -282,7 +284,6 @@ public class ActionEventInterceptorTest { Assert.assertEquals(eventVO.getState(), com.cloud.event.Event.State.Completed); Assert.assertEquals(eventVO.getResourceId(), resourceId); Assert.assertEquals(eventVO.getResourceType(), resourceType.toString()); - CallContext.unregister(); } @Test From 5a52ca78ae5e165211c618525613c3d62cfd1b28 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Sat, 20 Apr 2024 00:53:49 +0530 Subject: [PATCH 0006/1050] kvm: export sysinfo for arm64 domains for cloud-init to work (#8940) This fixes a limitation for arm64/aarch64 KVM hosts to correctly export the product name via sysconfig attribute. Without this `cloud-init` doesn't function correctly on arm64 platforms. Signed-off-by: Rohit Yadav --- .../java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java index db179f98642..6d69b2f9664 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtVMDef.java @@ -222,9 +222,7 @@ public class LibvirtVMDef { guestDef.append("\n"); } } - if (_arch == null || !_arch.equals("aarch64")) { - guestDef.append("\n"); - } + guestDef.append("\n"); guestDef.append("\n"); if (iothreads) { guestDef.append(String.format("%s", NUMBER_OF_IOTHREADS)); From 49d244f2513d2c765354e74f6176747b9ac75fe6 Mon Sep 17 00:00:00 2001 From: SadiJr Date: Mon, 22 Apr 2024 04:42:24 -0300 Subject: [PATCH 0007/1050] [Usage] Create VPC billing (#7235) Co-authored-by: SadiJr Co-authored-by: Bryan Lima --- .../main/java/com/cloud/event/EventTypes.java | 4 + .../apache/cloudstack/usage/UsageTypes.java | 2 + .../main/java/com/cloud/usage/UsageVpcVO.java | 130 +++++++++++++++++ .../java/com/cloud/usage/dao/UsageVpcDao.java | 29 ++++ .../com/cloud/usage/dao/UsageVpcDaoImpl.java | 131 ++++++++++++++++++ ...s-between-management-and-usage-context.xml | 1 + ...spring-engine-schema-core-daos-context.xml | 1 + .../META-INF/db/schema-41900to41910.sql | 15 ++ .../presetvariables/PresetVariableHelper.java | 22 +++ .../cloudstack/quota/constant/QuotaTypes.java | 1 + .../apache/cloudstack/quota/dao/VpcDao.java | 23 +++ .../cloudstack/quota/dao/VpcDaoImpl.java | 23 +++ .../PresetVariableHelperTest.java | 1 + .../com/cloud/network/vpc/VpcManagerImpl.java | 8 +- .../com/cloud/usage/UsageManagerImpl.java | 25 ++++ .../cloud/usage/parser/VpcUsageParser.java | 94 +++++++++++++ 16 files changed, 509 insertions(+), 1 deletion(-) create mode 100644 engine/schema/src/main/java/com/cloud/usage/UsageVpcVO.java create mode 100644 engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDao.java create mode 100644 engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java create mode 100644 framework/quota/src/main/java/org/apache/cloudstack/quota/dao/VpcDao.java create mode 100644 framework/quota/src/main/java/org/apache/cloudstack/quota/dao/VpcDaoImpl.java create mode 100644 usage/src/main/java/com/cloud/usage/parser/VpcUsageParser.java diff --git a/api/src/main/java/com/cloud/event/EventTypes.java b/api/src/main/java/com/cloud/event/EventTypes.java index d385fa9ed07..852a109447c 100644 --- a/api/src/main/java/com/cloud/event/EventTypes.java +++ b/api/src/main/java/com/cloud/event/EventTypes.java @@ -1219,4 +1219,8 @@ public class EventTypes { return null; } + + public static boolean isVpcEvent(String eventType) { + return EventTypes.EVENT_VPC_CREATE.equals(eventType) || EventTypes.EVENT_VPC_DELETE.equals(eventType); + } } diff --git a/api/src/main/java/org/apache/cloudstack/usage/UsageTypes.java b/api/src/main/java/org/apache/cloudstack/usage/UsageTypes.java index 5e0f03ff583..78af844c0a8 100644 --- a/api/src/main/java/org/apache/cloudstack/usage/UsageTypes.java +++ b/api/src/main/java/org/apache/cloudstack/usage/UsageTypes.java @@ -46,6 +46,7 @@ public class UsageTypes { public static final int VM_SNAPSHOT_ON_PRIMARY = 27; public static final int BACKUP = 28; public static final int BUCKET = 29; + public static final int VPC = 31; public static List listUsageTypes() { List responseList = new ArrayList(); @@ -72,6 +73,7 @@ public class UsageTypes { responseList.add(new UsageTypeResponse(VM_SNAPSHOT_ON_PRIMARY, "VM Snapshot on primary storage usage")); responseList.add(new UsageTypeResponse(BACKUP, "Backup storage usage")); responseList.add(new UsageTypeResponse(BUCKET, "Bucket storage usage")); + responseList.add(new UsageTypeResponse(VPC, "VPC usage")); return responseList; } } diff --git a/engine/schema/src/main/java/com/cloud/usage/UsageVpcVO.java b/engine/schema/src/main/java/com/cloud/usage/UsageVpcVO.java new file mode 100644 index 00000000000..e676b2bc2e9 --- /dev/null +++ b/engine/schema/src/main/java/com/cloud/usage/UsageVpcVO.java @@ -0,0 +1,130 @@ +// 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. +package com.cloud.usage; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import org.apache.cloudstack.api.InternalIdentity; + +import java.util.Date; + +@Entity +@Table(name = "usage_vpc") +public class UsageVpcVO implements InternalIdentity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "vpc_id") + private long vpcId; + + @Column(name = "zone_id") + private long zoneId; + + @Column(name = "account_id") + private long accountId; + + @Column(name = "domain_id") + private long domainId; + + + @Column(name = "state") + private String state; + + @Column(name = "created") + @Temporal(value = TemporalType.TIMESTAMP) + private Date created = null; + + @Column(name = "removed") + @Temporal(value = TemporalType.TIMESTAMP) + private Date removed = null; + + protected UsageVpcVO(){} + + public UsageVpcVO(long id, long vpcId, long zoneId, long accountId, long domainId, String state, Date created, Date removed) { + this.id = id; + this.vpcId = vpcId; + this.zoneId = zoneId; + this.domainId = domainId; + this.accountId = accountId; + this.state = state; + this.created = created; + this.removed = removed; + } + public UsageVpcVO(long vpcId, long zoneId, long accountId, long domainId, String state, Date created, Date removed) { + this.vpcId = vpcId; + this.zoneId = zoneId; + this.domainId = domainId; + this.accountId = accountId; + this.state = state; + this.created = created; + this.removed = removed; + } + + @Override + public long getId() { + return id; + } + + public long getZoneId() { + return zoneId; + } + + public long getAccountId() { + return accountId; + } + + public long getDomainId() { + return domainId; + } + + public long getVpcId() { + return vpcId; + } + + public void setVpcId(long vpcId) { + this.vpcId = vpcId; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public Date getCreated() { + return created; + } + + public Date getRemoved() { + return removed; + } + + public void setRemoved(Date removed) { + this.removed = removed; + } +} diff --git a/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDao.java b/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDao.java new file mode 100644 index 00000000000..a1514aba4ca --- /dev/null +++ b/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDao.java @@ -0,0 +1,29 @@ +// 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. +package com.cloud.usage.dao; + +import com.cloud.usage.UsageVpcVO; +import com.cloud.utils.db.GenericDao; + +import java.util.Date; +import java.util.List; + +public interface UsageVpcDao extends GenericDao { + void update(UsageVpcVO usage); + void remove(long vpcId, Date removed); + List getUsageRecords(Long accountId, Date startDate, Date endDate); +} diff --git a/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java b/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java new file mode 100644 index 00000000000..a42b96486a5 --- /dev/null +++ b/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java @@ -0,0 +1,131 @@ +// 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. +package com.cloud.usage.dao; + +import com.cloud.network.vpc.Vpc; +import com.cloud.usage.UsageVpcVO; +import com.cloud.utils.DateUtil; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.TransactionLegacy; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; + +@Component +public class UsageVpcDaoImpl extends GenericDaoBase implements UsageVpcDao { + private static final Logger LOGGER = Logger.getLogger(UsageVpcDaoImpl.class); + protected static final String GET_USAGE_RECORDS_BY_ACCOUNT = "SELECT id, vpc_id, zone_id, account_id, domain_id, state, created, removed FROM usage_vpc WHERE " + + " account_id = ? AND ((removed IS NULL AND created <= ?) OR (created BETWEEN ? AND ?) OR (removed BETWEEN ? AND ?) " + + " OR ((created <= ?) AND (removed >= ?)))"; + + @Override + public void update(UsageVpcVO usage) { + TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB); + try { + SearchCriteria sc = this.createSearchCriteria(); + sc.addAnd("vpcId", SearchCriteria.Op.EQ, usage.getVpcId()); + sc.addAnd("created", SearchCriteria.Op.EQ, usage.getCreated()); + UsageVpcVO vo = findOneBy(sc); + if (vo != null) { + vo.setRemoved(usage.getRemoved()); + update(vo.getId(), vo); + } + } catch (final Exception e) { + LOGGER.error(String.format("Error updating usage of VPC due to [%s].", e.getMessage()), e); + txn.rollback(); + } finally { + txn.close(); + } + } + + @Override + public void remove(long vpcId, Date removed) { + TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB); + try { + SearchCriteria sc = this.createSearchCriteria(); + sc.addAnd("vpcId", SearchCriteria.Op.EQ, vpcId); + sc.addAnd("removed", SearchCriteria.Op.NULL); + UsageVpcVO vo = findOneBy(sc); + if (vo != null) { + vo.setRemoved(removed); + vo.setState(Vpc.State.Inactive.name()); + update(vo.getId(), vo); + } + } catch (final Exception e) { + txn.rollback(); + LOGGER.error(String.format("Error updating usage of VPC due to [%s].", e.getMessage()), e); + } finally { + txn.close(); + } + } + + @Override + public List getUsageRecords(Long accountId, Date startDate, Date endDate) { + List usageRecords = new ArrayList<>(); + TransactionLegacy txn = TransactionLegacy.open(TransactionLegacy.USAGE_DB); + PreparedStatement pstmt; + try { + int i = 1; + pstmt = txn.prepareAutoCloseStatement(GET_USAGE_RECORDS_BY_ACCOUNT); + pstmt.setLong(i++, accountId); + + pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), endDate)); + pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), startDate)); + pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), endDate)); + pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), startDate)); + pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), endDate)); + pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), startDate)); + pstmt.setString(i++, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), endDate)); + + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) { + long id = rs.getLong(1); + long vpcId = rs.getLong(2); + long zoneId = rs.getLong(3); + long acctId = rs.getLong(4); + long domId = rs.getLong(5); + String stateTS = rs.getString(6); + Date createdDate = null; + Date removedDate = null; + String createdTS = rs.getString(7); + String removedTS = rs.getString(8); + + if (createdTS != null) { + createdDate = DateUtil.parseDateString(s_gmtTimeZone, createdTS); + } + if (removedTS != null) { + removedDate = DateUtil.parseDateString(s_gmtTimeZone, removedTS); + } + usageRecords.add(new UsageVpcVO(id, vpcId, zoneId, acctId, domId, stateTS, createdDate, removedDate)); + } + } catch (Exception e) { + txn.rollback(); + LOGGER.warn("Error getting VPC usage records", e); + } finally { + txn.close(); + } + + return usageRecords; + } +} diff --git a/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-common-daos-between-management-and-usage-context.xml b/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-common-daos-between-management-and-usage-context.xml index 0c46c5ff934..368d17e831d 100644 --- a/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-common-daos-between-management-and-usage-context.xml +++ b/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-common-daos-between-management-and-usage-context.xml @@ -67,6 +67,7 @@ + diff --git a/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml index 5d958383161..62ef8645a7e 100644 --- a/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml +++ b/engine/schema/src/main/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml @@ -203,6 +203,7 @@ + diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41900to41910.sql b/engine/schema/src/main/resources/META-INF/db/schema-41900to41910.sql index e704d61d70c..358cc9d2979 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41900to41910.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41900to41910.sql @@ -30,3 +30,18 @@ UPDATE cloud_usage.quota_tariff SET usage_unit = 'IOPS', updated_on = NOW() WHERE effective_on = '2010-05-04 00:00:00' AND name IN ('VM_DISK_IO_READ', 'VM_DISK_IO_WRITE'); + +-- PR #7235 - [Usage] Create VPC billing +CREATE TABLE IF NOT EXISTS `cloud_usage`.`usage_vpc` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `vpc_id` bigint(20) unsigned NOT NULL, + `zone_id` bigint(20) unsigned NOT NULL, + `account_id` bigint(20) unsigned NOT NULL, + `domain_id` bigint(20) unsigned NOT NULL, + `state` varchar(100) DEFAULT NULL, + `created` datetime NOT NULL, + `removed` datetime DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB CHARSET=utf8; + +CALL `cloud_usage`.`IDEMPOTENT_ADD_COLUMN`('cloud_usage.cloud_usage', 'state', 'VARCHAR(100) DEFAULT NULL'); diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelper.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelper.java index 9723d3e5899..95d28ac2419 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelper.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelper.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.stream.Collectors; import com.cloud.host.HostTagVO; +import com.cloud.network.vpc.VpcVO; import javax.inject.Inject; import com.cloud.hypervisor.Hypervisor; @@ -37,6 +38,7 @@ import org.apache.cloudstack.backup.dao.BackupOfferingDao; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.quota.constant.QuotaTypes; import org.apache.cloudstack.quota.dao.VmTemplateDao; +import org.apache.cloudstack.quota.dao.VpcDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; @@ -170,6 +172,10 @@ public class PresetVariableHelper { @Inject BackupOfferingDao backupOfferingDao; + @Inject + VpcDao vpcDao; + + protected boolean backupSnapshotAfterTakingSnapshot = SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value(); private List runningAndAllocatedVmUsageTypes = Arrays.asList(UsageTypes.RUNNING_VM, UsageTypes.ALLOCATED_VM); @@ -273,6 +279,7 @@ public class PresetVariableHelper { loadPresetVariableValueForNetworkOffering(usageRecord, value); loadPresetVariableValueForVmSnapshot(usageRecord, value); loadPresetVariableValueForBackup(usageRecord, value); + loadPresetVariableValueForVpc(usageRecord, value); return value; } @@ -689,6 +696,21 @@ public class PresetVariableHelper { return backupOffering; } + protected void loadPresetVariableValueForVpc(UsageVO usageRecord, Value value) { + int usageType = usageRecord.getUsageType(); + if (usageType != QuotaTypes.VPC) { + logNotLoadingMessageInTrace("VPC", usageType); + return; + } + + Long vpcId = usageRecord.getUsageId(); + VpcVO vpc = vpcDao.findByIdIncludingRemoved(vpcId); + validateIfObjectIsNull(vpc, vpcId, "VPC"); + + value.setId(vpc.getUuid()); + value.setName(vpc.getName()); + } + /** * Throws a {@link CloudRuntimeException} if the object is null; */ diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/constant/QuotaTypes.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/constant/QuotaTypes.java index 6f19fa95f1b..0c6ff82a4f5 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/constant/QuotaTypes.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/constant/QuotaTypes.java @@ -56,6 +56,7 @@ public class QuotaTypes extends UsageTypes { quotaTypeList.put(VM_SNAPSHOT_ON_PRIMARY, new QuotaTypes(VM_SNAPSHOT_ON_PRIMARY, "VM_SNAPSHOT_ON_PRIMARY", UsageUnitTypes.GB_MONTH.toString(), "VM Snapshot primary storage usage")); quotaTypeList.put(BACKUP, new QuotaTypes(BACKUP, "BACKUP", UsageUnitTypes.GB_MONTH.toString(), "Backup storage usage")); quotaTypeList.put(BUCKET, new QuotaTypes(BUCKET, "BUCKET", UsageUnitTypes.GB_MONTH.toString(), "Object Store bucket usage")); + quotaTypeList.put(VPC, new QuotaTypes(VPC, "VPC", UsageUnitTypes.COMPUTE_MONTH.toString(), "VPC usage")); quotaTypeMap = Collections.unmodifiableMap(quotaTypeList); } diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/dao/VpcDao.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/dao/VpcDao.java new file mode 100644 index 00000000000..a3ce164ce6a --- /dev/null +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/dao/VpcDao.java @@ -0,0 +1,23 @@ +// 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. +package org.apache.cloudstack.quota.dao; + +import com.cloud.network.vpc.VpcVO; +import com.cloud.utils.db.GenericDao; + +public interface VpcDao extends GenericDao { +} diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/dao/VpcDaoImpl.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/dao/VpcDaoImpl.java new file mode 100644 index 00000000000..10d7c4bd82f --- /dev/null +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/dao/VpcDaoImpl.java @@ -0,0 +1,23 @@ +// 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. +package org.apache.cloudstack.quota.dao; + +import com.cloud.network.vpc.VpcVO; +import com.cloud.utils.db.GenericDaoBase; + +public class VpcDaoImpl extends GenericDaoBase implements VpcDao { +} diff --git a/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java b/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java index b973d1145c3..f7492590196 100644 --- a/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java +++ b/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariableHelperTest.java @@ -471,6 +471,7 @@ public class PresetVariableHelperTest { Mockito.doNothing().when(presetVariableHelperSpy).loadPresetVariableValueForNetworkOffering(Mockito.any(UsageVO.class), Mockito.any(Value.class)); Mockito.doNothing().when(presetVariableHelperSpy).loadPresetVariableValueForVmSnapshot(Mockito.any(UsageVO.class), Mockito.any(Value.class)); Mockito.doNothing().when(presetVariableHelperSpy).loadPresetVariableValueForBackup(Mockito.any(UsageVO.class), Mockito.any(Value.class)); + Mockito.doNothing().when(presetVariableHelperSpy).loadPresetVariableValueForVpc(Mockito.any(UsageVO.class), Mockito.any(Value.class)); Value result = presetVariableHelperSpy.getPresetVariableValue(usageVoMock); diff --git a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java index 341a3b81b42..58098ee3832 100644 --- a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java @@ -37,6 +37,7 @@ import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import com.cloud.event.UsageEventUtils; import javax.annotation.PostConstruct; import javax.inject.Inject; import javax.naming.ConfigurationException; @@ -1147,7 +1148,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis + "and the hyphen ('-'); can't start or end with \"-\""); } - return Transaction.execute(new TransactionCallback() { + VpcVO vpcVO = Transaction.execute(new TransactionCallback() { @Override public VpcVO doInTransaction(final TransactionStatus status) { final VpcVO persistedVpc = vpcDao.persist(vpc, finalizeServicesAndProvidersForVpc(vpc.getZoneId(), vpc.getVpcOfferingId())); @@ -1157,6 +1158,10 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis return persistedVpc; } }); + if (vpcVO != null) { + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VPC_CREATE, vpcVO.getAccountId(), vpcVO.getZoneId(), vpcVO.getId(), vpcVO.getName(), Vpc.class.getName(), vpcVO.getUuid(), vpcVO.isDisplay()); + } + return vpcVO; } private Map> finalizeServicesAndProvidersForVpc(final long zoneId, final long offeringId) { @@ -1255,6 +1260,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis // executed successfully if (vpcDao.remove(vpc.getId())) { s_logger.debug("Vpc " + vpc + " is destroyed successfully"); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VPC_DELETE, vpc.getAccountId(), vpc.getZoneId(), vpc.getId(), vpc.getName(), Vpc.class.getName(), vpc.getUuid(), vpc.isDisplay()); return true; } else { s_logger.warn("Vpc " + vpc + " failed to destroy"); diff --git a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java index f29073a3cb5..250b5859c57 100644 --- a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java @@ -32,6 +32,9 @@ import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import com.cloud.network.vpc.Vpc; +import com.cloud.usage.dao.UsageVpcDao; +import com.cloud.usage.parser.VpcUsageParser; import javax.inject.Inject; import javax.naming.ConfigurationException; import javax.persistence.EntityExistsException; @@ -170,6 +173,9 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna @Inject private BucketStatisticsDao _bucketStatisticsDao; + @Inject + private UsageVpcDao usageVpcDao; + private String _version = null; private final Calendar _jobExecTime = Calendar.getInstance(); private int _aggregationDuration = 0; @@ -1034,6 +1040,10 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna s_logger.debug("Bucket usage successfully parsed? " + parsed + " (for account: " + account.getAccountName() + ", id: " + account.getId() + ")"); } } + parsed = VpcUsageParser.parse(account, currentStartDate, currentEndDate); + if (!parsed) { + s_logger.debug(String.format("VPC usage failed to parse for account [%s].", account)); + } return parsed; } @@ -1068,6 +1078,8 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna createVmSnapshotOnPrimaryEvent(event); } else if (isBackupEvent(eventType)) { createBackupEvent(event); + } else if (EventTypes.isVpcEvent(eventType)) { + handleVpcEvent(event); } } catch (EntityExistsException e) { s_logger.warn(String.format("Failed to create usage event id: %d type: %s due to %s", event.getId(), eventType, e.getMessage()), e); @@ -2113,6 +2125,19 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna } } + private void handleVpcEvent(UsageEventVO event) { + Account account = _accountDao.findByIdIncludingRemoved(event.getAccountId()); + long domainId = account.getDomainId(); + if (EventTypes.EVENT_VPC_DELETE.equals(event.getType())) { + usageVpcDao.remove(event.getResourceId(), event.getCreateDate()); + } else if (EventTypes.EVENT_VPC_CREATE.equals(event.getType())) { + UsageVpcVO usageVPCVO = new UsageVpcVO(event.getResourceId(), event.getZoneId(), event.getAccountId(), domainId, Vpc.State.Enabled.name(), event.getCreateDate(), null); + usageVpcDao.persist(usageVPCVO); + } else { + s_logger.error(String.format("Unknown event type [%s] in VPC event parser. Skipping it.", event.getType())); + } + } + private class Heartbeat extends ManagedContextRunnable { @Override protected void runInContext() { diff --git a/usage/src/main/java/com/cloud/usage/parser/VpcUsageParser.java b/usage/src/main/java/com/cloud/usage/parser/VpcUsageParser.java new file mode 100644 index 00000000000..8fff2efde94 --- /dev/null +++ b/usage/src/main/java/com/cloud/usage/parser/VpcUsageParser.java @@ -0,0 +1,94 @@ +// 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. +package com.cloud.usage.parser; + +import com.cloud.usage.UsageVpcVO; +import com.cloud.usage.dao.UsageDao; +import com.cloud.usage.UsageVO; +import com.cloud.usage.dao.UsageVpcDao; +import com.cloud.user.AccountVO; +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import org.apache.cloudstack.usage.UsageTypes; +import org.springframework.stereotype.Component; + +import java.text.DecimalFormat; +import java.util.Date; +import java.util.List; +import org.apache.log4j.Logger; + +@Component +public class VpcUsageParser { + private static final Logger LOGGER = Logger.getLogger(VpcUsageParser.class.getName()); + + @Inject + private UsageVpcDao vpcDao; + @Inject + private UsageDao usageDao; + + private static UsageDao s_usageDao; + private static UsageVpcDao s_usageVpcDao; + @PostConstruct + void init() { + s_usageDao = usageDao; + s_usageVpcDao = vpcDao; + } + + public static boolean parse(AccountVO account, Date startDate, Date endDate) { + LOGGER.debug(String.format("Parsing all VPC usage events for account [%s].", account.getId())); + if ((endDate == null) || endDate.after(new Date())) { + endDate = new Date(); + } + + final List usageVPCs = s_usageVpcDao.getUsageRecords(account.getId(), startDate, endDate); + if (usageVPCs == null || usageVPCs.isEmpty()) { + LOGGER.debug(String.format("Cannot find any VPC usage for account [%s] in period between [%s] and [%s].", account, startDate, endDate)); + return true; + } + + for (final UsageVpcVO usageVPC : usageVPCs) { + Long zoneId = usageVPC.getZoneId(); + Date createdDate = usageVPC.getCreated(); + Date removedDate = usageVPC.getRemoved(); + if (createdDate.before(startDate)) { + createdDate = startDate; + } + + if (removedDate == null || removedDate.after(endDate)) { + removedDate = endDate; + } + + final long duration = (removedDate.getTime() - createdDate.getTime()) + 1; + final float usage = duration / 1000f / 60f / 60f; + DecimalFormat dFormat = new DecimalFormat("#.######"); + String usageDisplay = dFormat.format(usage); + + long vpcId = usageVPC.getVpcId(); + LOGGER.debug(String.format("Creating VPC usage record with id [%s], usage [%s], startDate [%s], and endDate [%s], for account [%s].", + vpcId, usageDisplay, startDate, endDate, account.getId())); + + String description = String.format("VPC usage for VPC ID: %d", usageVPC.getVpcId()); + UsageVO usageRecord = + new UsageVO(zoneId, account.getAccountId(), account.getDomainId(), description, usageDisplay + " Hrs", + UsageTypes.VPC, (double) usage, null, null, null, null, usageVPC.getVpcId(), + (long)0, null, startDate, endDate); + s_usageDao.persist(usageRecord); + } + + return true; + } +} From 405aac38bc949db8467cc789a0ecfc9b4c55cd15 Mon Sep 17 00:00:00 2001 From: Rene Peinthor Date: Mon, 22 Apr 2024 10:04:05 +0200 Subject: [PATCH 0008/1050] linstor: Only set allow-two-primaries if resource is already in use (#8802) For live migrate we need the allow-two-primaries option, but we don't know exactly if we are called for a migration operation. Now also check if at least any of the resources is in use somewhere and only then set the option. --- .../kvm/storage/LinstorStorageAdaptor.java | 33 +++++++++++++------ .../storage/datastore/util/LinstorUtil.java | 19 +++++++++++ 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java index 9ad8332d0e1..66278f827f7 100644 --- a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java +++ b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java @@ -260,6 +260,28 @@ public class LinstorStorageAdaptor implements StorageAdaptor { } } + /** + * Checks if the given resource is in use by drbd on any host and + * if so set the drbd option allow-two-primaries + * @param api linstor api object + * @param rscName resource name to set allow-two-primaries if in use + * @throws ApiException if any problem connecting to the Linstor controller + */ + private void allow2PrimariesIfInUse(DevelopersApi api, String rscName) throws ApiException { + if (LinstorUtil.isResourceInUse(api, rscName)) { + // allow 2 primaries for live migration, should be removed by disconnect on the other end + ResourceDefinitionModify rdm = new ResourceDefinitionModify(); + Properties props = new Properties(); + props.put("DrbdOptions/Net/allow-two-primaries", "yes"); + rdm.setOverrideProps(props); + ApiCallRcList answers = api.resourceDefinitionModify(rscName, rdm); + if (answers.hasError()) { + s_logger.error("Unable to set 'allow-two-primaries' on " + rscName); + // do not fail here as adding allow-two-primaries property is only a problem while live migrating + } + } + } + @Override public boolean connectPhysicalDisk(String volumePath, KVMStoragePool pool, Map details) { @@ -286,16 +308,7 @@ public class LinstorStorageAdaptor implements StorageAdaptor { try { - // allow 2 primaries for live migration, should be removed by disconnect on the other end - ResourceDefinitionModify rdm = new ResourceDefinitionModify(); - Properties props = new Properties(); - props.put("DrbdOptions/Net/allow-two-primaries", "yes"); - rdm.setOverrideProps(props); - ApiCallRcList answers = api.resourceDefinitionModify(rscName, rdm); - if (answers.hasError()) { - s_logger.error("Unable to set 'allow-two-primaries' on " + rscName); - // do not fail here as adding allow-two-primaries property is only a problem while live migrating - } + allow2PrimariesIfInUse(api, rscName); } catch (ApiException apiEx) { s_logger.error(apiEx); // do not fail here as adding allow-two-primaries property is only a problem while live migrating diff --git a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java index cc85c9834eb..c8544fd3e3e 100644 --- a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java +++ b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/util/LinstorUtil.java @@ -23,6 +23,7 @@ import com.linbit.linstor.api.DevelopersApi; import com.linbit.linstor.api.model.ApiCallRc; import com.linbit.linstor.api.model.ApiCallRcList; import com.linbit.linstor.api.model.ProviderKind; +import com.linbit.linstor.api.model.Resource; import com.linbit.linstor.api.model.ResourceGroup; import com.linbit.linstor.api.model.StoragePool; @@ -90,4 +91,22 @@ public class LinstorUtil { throw new CloudRuntimeException(apiEx); } } + + /** + * Check if any resource of the given name is InUse on any host. + * + * @param api developer api object to use + * @param rscName resource name to check in use state. + * @return True if a resource found that is in use(primary) state, else false. + * @throws ApiException forwards api errors + */ + public static boolean isResourceInUse(DevelopersApi api, String rscName) throws ApiException { + List rscs = api.resourceList(rscName, null, null); + if (rscs != null) { + return rscs.stream() + .anyMatch(rsc -> rsc.getState() != null && Boolean.TRUE.equals(rsc.getState().isInUse())); + } + s_logger.error("isResourceInUse: null returned from resourceList"); + return false; + } } From 0577b0ac8ef99c304216a0212e775f9293d06688 Mon Sep 17 00:00:00 2001 From: dahn Date: Mon, 22 Apr 2024 10:31:48 +0200 Subject: [PATCH 0009/1050] server: add logs to public ip allocation attempt (#8239) --- .../cloud/network/IpAddressManagerImpl.java | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java index 9882ed50353..f55b03a5bf6 100644 --- a/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java +++ b/server/src/main/java/com/cloud/network/IpAddressManagerImpl.java @@ -343,6 +343,9 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage if (possibleAddr.getState() != State.Free) { continue; } + if (s_logger.isDebugEnabled()) { + s_logger.debug(String.format("trying ip address %s", possibleAddr.getAddress())); + } possibleAddr.setSourceNat(sourceNat); possibleAddr.setAllocatedTime(new Date()); possibleAddr.setAllocatedInDomainId(owner.getDomainId()); @@ -357,15 +360,9 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage possibleAddr.setAssociatedWithNetworkId(guestNetworkId); possibleAddr.setVpcId(vpcId); } - if (_ipAddressDao.lockRow(possibleAddr.getId(), true) != null) { - final IPAddressVO userIp = _ipAddressDao.findById(possibleAddr.getId()); - if (userIp.getState() == State.Free) { - possibleAddr.setState(State.Allocating); - if (_ipAddressDao.update(possibleAddr.getId(), possibleAddr)) { - finalAddress = possibleAddr; - break; - } - } + finalAddress = assignIpAddressWithLock(possibleAddr); + if (finalAddress != null) { + break; } } @@ -387,6 +384,29 @@ public class IpAddressManagerImpl extends ManagerBase implements IpAddressManage }); } + private IPAddressVO assignIpAddressWithLock(IPAddressVO possibleAddr) { + IPAddressVO finalAddress = null; + IPAddressVO userIp = _ipAddressDao.acquireInLockTable(possibleAddr.getId()); + if (userIp != null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug(String.format("locked row for ip address %s (id: %s)", possibleAddr.getAddress(), possibleAddr.getUuid())); + } + if (userIp.getState() == State.Free) { + possibleAddr.setState(State.Allocating); + if (_ipAddressDao.update(possibleAddr.getId(), possibleAddr)) { + s_logger.info(String.format("successfully allocated ip address %s", possibleAddr.getAddress())); + finalAddress = possibleAddr; + } + } else { + if (s_logger.isDebugEnabled()) { + s_logger.debug(String.format("locked ip address %s is not free (%s)", possibleAddr.getAddress(), userIp.getState())); + } + } + _ipAddressDao.releaseFromLockTable(possibleAddr.getId()); + } + return finalAddress; + } + @Override public boolean configure(String name, Map params) { // populate providers From 21182dabcd8cdfbb20fc514c549837aa26a4ba45 Mon Sep 17 00:00:00 2001 From: Suresh Kumar Anaparti Date: Mon, 22 Apr 2024 14:05:03 +0530 Subject: [PATCH 0010/1050] Update netty version for compatibility/staying current (#8945) --- services/secondary-storage/server/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/secondary-storage/server/pom.xml b/services/secondary-storage/server/pom.xml index 432486eb8a4..b9e7d419ee3 100644 --- a/services/secondary-storage/server/pom.xml +++ b/services/secondary-storage/server/pom.xml @@ -60,7 +60,7 @@ io.netty netty-all - 4.1.42.Final + 4.1.100.Final compile From c081f60427d63f98f51665f6af5128d47bf92568 Mon Sep 17 00:00:00 2001 From: Vishesh Date: Mon, 22 Apr 2024 22:51:16 +0530 Subject: [PATCH 0011/1050] server: Fix null pointer exception in restore VM (#8930) --- .../main/java/com/cloud/vm/UserVmManagerImpl.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index 566fcb38fc9..6c8aec0da48 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -7699,8 +7699,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } _accountMgr.checkAccess(caller, null, true, vm); + VMTemplateVO template; + if (newTemplateId != null) { + template = _templateDao.findById(newTemplateId); + if (template == null) { + throw new InvalidParameterValueException("Cannot find template with ID " + newTemplateId); + } + } else { + template = _templateDao.findById(vm.getTemplateId()); + if (template == null) { + throw new InvalidParameterValueException("Cannot find template linked with VM"); + } + } DiskOffering diskOffering = rootDiskOfferingId != null ? validateAndGetDiskOffering(rootDiskOfferingId, vm, caller) : null; - VMTemplateVO template = _templateDao.findById(newTemplateId); if (template.getSize() != null) { String rootDiskSize = details.get(VmDetailConstants.ROOT_DISK_SIZE); Long templateSize = template.getSize(); From 6502dde8c33feb43aad989c97960ba8efa3bfd34 Mon Sep 17 00:00:00 2001 From: dahn Date: Tue, 23 Apr 2024 09:31:08 +0200 Subject: [PATCH 0012/1050] field enlarged and db upgrade (#8675) * 4.19 -> 4.19.1 and enlarge url field --- .../com/cloud/upgrade/dao/Upgrade41900to41910.java | 11 ++++++----- .../resources/META-INF/db/schema-41900to41910.sql | 4 ++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41900to41910.java b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41900to41910.java index 5c57fb31fcf..4cdd1c3364d 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41900to41910.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41900to41910.java @@ -16,9 +16,10 @@ // under the License. package com.cloud.upgrade.dao; +import org.apache.log4j.Logger; + import com.cloud.upgrade.SystemVmTemplateRegistration; import com.cloud.utils.exception.CloudRuntimeException; -import org.apache.log4j.Logger; import java.io.InputStream; import java.sql.Connection; @@ -73,6 +74,10 @@ public class Upgrade41900to41910 implements DbUpgrade, DbUpgradeSystemVmTemplate DbUpgradeUtils.addIndexIfNeeded(conn, "vm_stats", "vm_id"); } + private void initSystemVmTemplateRegistration() { + systemVmTemplateRegistration = new SystemVmTemplateRegistration(""); + } + @Override public void updateSystemVmTemplates(Connection conn) { LOG.debug("Updating System Vm template IDs"); @@ -83,8 +88,4 @@ public class Upgrade41900to41910 implements DbUpgrade, DbUpgradeSystemVmTemplate throw new CloudRuntimeException("Failed to find / register SystemVM template(s)"); } } - - private void initSystemVmTemplateRegistration() { - systemVmTemplateRegistration = new SystemVmTemplateRegistration(""); - } } diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41900to41910.sql b/engine/schema/src/main/resources/META-INF/db/schema-41900to41910.sql index 358cc9d2979..de9c62258c8 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41900to41910.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41900to41910.sql @@ -31,6 +31,10 @@ SET usage_unit = 'IOPS', updated_on = NOW() WHERE effective_on = '2010-05-04 00:00:00' AND name IN ('VM_DISK_IO_READ', 'VM_DISK_IO_WRITE'); +-- allow for bigger urls + +ALTER TABLE `cloud`.`vm_template` MODIFY COLUMN `url` VARCHAR(1024) DEFAULT NULL COMMENT 'the url where the template exists externally'; + -- PR #7235 - [Usage] Create VPC billing CREATE TABLE IF NOT EXISTS `cloud_usage`.`usage_vpc` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, From bf9fdaddbd2c0bc631771e333b968bc7b2a23b12 Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Tue, 23 Apr 2024 11:43:08 +0200 Subject: [PATCH 0013/1050] Fix build errors due to log4j 2.x changes --- .../java/com/cloud/upgrade/dao/Upgrade41900to41910.java | 2 -- .../main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java | 8 +++----- usage/src/main/java/com/cloud/usage/UsageManagerImpl.java | 4 ++-- .../main/java/com/cloud/usage/parser/VpcUsageParser.java | 5 +++-- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41900to41910.java b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41900to41910.java index 92616481ac4..4eb8e9bdb2a 100644 --- a/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41900to41910.java +++ b/engine/schema/src/main/java/com/cloud/upgrade/dao/Upgrade41900to41910.java @@ -16,8 +16,6 @@ // under the License. package com.cloud.upgrade.dao; -import org.apache.log4j.Logger; - import com.cloud.upgrade.SystemVmTemplateRegistration; import com.cloud.utils.exception.CloudRuntimeException; diff --git a/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java b/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java index a42b96486a5..45ae845e58f 100644 --- a/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/usage/dao/UsageVpcDaoImpl.java @@ -22,7 +22,6 @@ import com.cloud.utils.DateUtil; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.TransactionLegacy; -import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import java.sql.PreparedStatement; @@ -34,7 +33,6 @@ import java.util.TimeZone; @Component public class UsageVpcDaoImpl extends GenericDaoBase implements UsageVpcDao { - private static final Logger LOGGER = Logger.getLogger(UsageVpcDaoImpl.class); protected static final String GET_USAGE_RECORDS_BY_ACCOUNT = "SELECT id, vpc_id, zone_id, account_id, domain_id, state, created, removed FROM usage_vpc WHERE " + " account_id = ? AND ((removed IS NULL AND created <= ?) OR (created BETWEEN ? AND ?) OR (removed BETWEEN ? AND ?) " + " OR ((created <= ?) AND (removed >= ?)))"; @@ -52,7 +50,7 @@ public class UsageVpcDaoImpl extends GenericDaoBase implements update(vo.getId(), vo); } } catch (final Exception e) { - LOGGER.error(String.format("Error updating usage of VPC due to [%s].", e.getMessage()), e); + logger.error(String.format("Error updating usage of VPC due to [%s].", e.getMessage()), e); txn.rollback(); } finally { txn.close(); @@ -74,7 +72,7 @@ public class UsageVpcDaoImpl extends GenericDaoBase implements } } catch (final Exception e) { txn.rollback(); - LOGGER.error(String.format("Error updating usage of VPC due to [%s].", e.getMessage()), e); + logger.error(String.format("Error updating usage of VPC due to [%s].", e.getMessage()), e); } finally { txn.close(); } @@ -121,7 +119,7 @@ public class UsageVpcDaoImpl extends GenericDaoBase implements } } catch (Exception e) { txn.rollback(); - LOGGER.warn("Error getting VPC usage records", e); + logger.warn("Error getting VPC usage records", e); } finally { txn.close(); } diff --git a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java index 4ace561095b..2b436bb440c 100644 --- a/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/main/java/com/cloud/usage/UsageManagerImpl.java @@ -1045,7 +1045,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna } parsed = VpcUsageParser.parse(account, currentStartDate, currentEndDate); if (!parsed) { - s_logger.debug(String.format("VPC usage failed to parse for account [%s].", account)); + logger.debug(String.format("VPC usage failed to parse for account [%s].", account)); } return parsed; } @@ -2140,7 +2140,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna UsageVpcVO usageVPCVO = new UsageVpcVO(event.getResourceId(), event.getZoneId(), event.getAccountId(), domainId, Vpc.State.Enabled.name(), event.getCreateDate(), null); usageVpcDao.persist(usageVPCVO); } else { - s_logger.error(String.format("Unknown event type [%s] in VPC event parser. Skipping it.", event.getType())); + logger.error(String.format("Unknown event type [%s] in VPC event parser. Skipping it.", event.getType())); } } diff --git a/usage/src/main/java/com/cloud/usage/parser/VpcUsageParser.java b/usage/src/main/java/com/cloud/usage/parser/VpcUsageParser.java index 8fff2efde94..5dcb5d08a6c 100644 --- a/usage/src/main/java/com/cloud/usage/parser/VpcUsageParser.java +++ b/usage/src/main/java/com/cloud/usage/parser/VpcUsageParser.java @@ -24,16 +24,17 @@ import com.cloud.user.AccountVO; import javax.annotation.PostConstruct; import javax.inject.Inject; import org.apache.cloudstack.usage.UsageTypes; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; import org.springframework.stereotype.Component; import java.text.DecimalFormat; import java.util.Date; import java.util.List; -import org.apache.log4j.Logger; @Component public class VpcUsageParser { - private static final Logger LOGGER = Logger.getLogger(VpcUsageParser.class.getName()); + private static final Logger LOGGER = LogManager.getLogger(VpcUsageParser.class.getName()); @Inject private UsageVpcDao vpcDao; From 582249c1f727d5a0050126bdf8fb375464114e6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernardo=20De=20Marco=20Gon=C3=A7alves?= Date: Tue, 23 Apr 2024 06:46:10 -0300 Subject: [PATCH 0014/1050] Fix permission to manipulate VMs and templates settings through UI (#8778) --- ui/src/components/view/DetailSettings.vue | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ui/src/components/view/DetailSettings.vue b/ui/src/components/view/DetailSettings.vue index ba9f61860e4..1581c2daef8 100644 --- a/ui/src/components/view/DetailSettings.vue +++ b/ui/src/components/view/DetailSettings.vue @@ -26,7 +26,7 @@ {{ $t('label.add.setting') }} @@ -96,8 +96,7 @@ + + + +
{{ $t('label.cancel') }} @@ -332,7 +338,8 @@ export default { this.form = reactive({ bootable: true, isextractable: false, - ispublic: false + ispublic: false, + passwordenabled: 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..f718f1c030c 100644 --- a/ui/src/views/image/UpdateISO.vue +++ b/ui/src/views/image/UpdateISO.vue @@ -42,6 +42,12 @@ :placeholder="apiParams.displaytext.description" autoFocus /> + + + + Date: Mon, 6 May 2024 09:05:31 +0200 Subject: [PATCH 0060/1050] linstor: disconnect-disk also search for resource name in Linstor (#9035) disconnectPhysicalDisk(String, KVMStoragePool) seems to calls the plugin with the resource name instead of the device path, so we also have to search for resource names, while cleaning up. --- .../hypervisor/kvm/storage/LinstorStorageAdaptor.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java index b38ab382a42..632b92c80fd 100644 --- a/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java +++ b/plugins/storage/volume/linstor/src/main/java/com/cloud/hypervisor/kvm/storage/LinstorStorageAdaptor.java @@ -341,7 +341,7 @@ public class LinstorStorageAdaptor implements StorageAdaptor { null, null); - optRsc = getResourceByPath(resources, volumePath); + optRsc = getResourceByPathOrName(resources, volumePath); } catch (ApiException apiEx) { // couldn't query linstor controller s_logger.error(apiEx.getBestMessage()); @@ -401,9 +401,10 @@ public class LinstorStorageAdaptor implements StorageAdaptor { return false; } - private Optional getResourceByPath(final List resources, String path) { + private Optional getResourceByPathOrName( + final List resources, String path) { return resources.stream() - .filter(rsc -> rsc.getVolumes().stream() + .filter(rsc -> getLinstorRscName(path).equalsIgnoreCase(rsc.getName()) || rsc.getVolumes().stream() .anyMatch(v -> path.equals(v.getDevicePath()))) .findFirst(); } From f80d20528457838009f1f8195e6476bd8c9c4f27 Mon Sep 17 00:00:00 2001 From: Rene Peinthor Date: Mon, 6 May 2024 11:00:22 +0200 Subject: [PATCH 0061/1050] linstor: Fix volume format and make resource available on copy target (#8811) Linstor primary storage forgot to make sure the volume download/copy target has a Linstor resource available. --- .../LinstorPrimaryDataStoreDriverImpl.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java index 328b3d21d0a..9612781ee4c 100644 --- a/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java +++ b/plugins/storage/volume/linstor/src/main/java/org/apache/cloudstack/storage/datastore/driver/LinstorPrimaryDataStoreDriverImpl.java @@ -102,6 +102,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.datastore.util.LinstorConfigurationManager; import org.apache.cloudstack.storage.datastore.util.LinstorUtil; import org.apache.cloudstack.storage.to.SnapshotObjectTO; +import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.storage.volume.VolumeObject; import org.apache.log4j.Logger; @@ -798,6 +799,15 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver || srcData.getDataStore().getRole() == DataStoreRole.ImageCache); } + private static boolean canCopyVolumeCond(DataObject srcData, DataObject dstData) { + // Volume download from Linstor primary storage + return srcData.getType() == DataObjectType.VOLUME + && (dstData.getType() == DataObjectType.VOLUME || dstData.getType() == DataObjectType.TEMPLATE) + && srcData.getDataStore().getRole() == DataStoreRole.Primary + && (dstData.getDataStore().getRole() == DataStoreRole.Image + || dstData.getDataStore().getRole() == DataStoreRole.ImageCache); + } + @Override public boolean canCopy(DataObject srcData, DataObject dstData) { @@ -814,6 +824,10 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver return storagePoolVO != null && storagePoolVO.getPoolType() == Storage.StoragePoolType.Linstor && tInfo.getSize() != null; + } else if (canCopyVolumeCond(srcData, dstData)) { + VolumeInfo srcVolInfo = (VolumeInfo) srcData; + StoragePoolVO storagePool = _storagePoolDao.findById(srcVolInfo.getPoolId()); + return storagePool.getStorageProviderName().equals(LinstorUtil.PROVIDER_NAME); } return false; } @@ -844,6 +858,9 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver } else if (canCopyTemplateCond(srcData, dstData)) { Answer answer = copyTemplate(srcData, dstData); res = new CopyCommandResult(null, answer); + } else if (canCopyVolumeCond(srcData, dstData)) { + Answer answer = copyVolume(srcData, dstData); + res = new CopyCommandResult(null, answer); } else { Answer answer = new Answer(null, false, "noimpl"); res = new CopyCommandResult(null, answer); @@ -965,6 +982,43 @@ public class LinstorPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver return answer; } + private Answer copyVolume(DataObject srcData, DataObject dstData) { + VolumeInfo srcVolInfo = (VolumeInfo) srcData; + final StoragePoolVO pool = _storagePoolDao.findById(srcVolInfo.getDataStore().getId()); + final DevelopersApi api = LinstorUtil.getLinstorAPI(pool.getHostAddress()); + final String rscName = LinstorUtil.RSC_PREFIX + srcVolInfo.getUuid(); + + VolumeObjectTO to = (VolumeObjectTO) srcVolInfo.getTO(); + // patch source format + // Linstor volumes are stored as RAW, but we can't set the correct format as RAW (we use QCOW2) + // otherwise create template from snapshot won't work, because this operation + // uses the format of the base volume and we backup snapshots as QCOW2 + // https://github.com/apache/cloudstack/pull/8802#issuecomment-2024019927 + to.setFormat(Storage.ImageFormat.RAW); + int nMaxExecutionSeconds = NumbersUtil.parseInt( + _configDao.getValue(Config.CopyVolumeWait.key()), 10800); + CopyCommand cmd = new CopyCommand( + to, + dstData.getTO(), + nMaxExecutionSeconds, + VirtualMachineManager.ExecuteInSequence.value()); + Answer answer; + + try { + Optional optEP = getLinstorEP(api, rscName); + if (optEP.isPresent()) { + answer = optEP.get().sendMessage(cmd); + } + else { + answer = new Answer(cmd, false, "Unable to get matching Linstor endpoint."); + } + } catch (ApiException exc) { + s_logger.error("copy volume failed: ", exc); + throw new CloudRuntimeException(exc.getBestMessage()); + } + return answer; + } + /** * Create a temporary resource from the snapshot to backup, so we can copy the data on a diskless agent * @param api Linstor Developer api object From 87e7c57d08c9ff87aa6c2db621efc620c7318a30 Mon Sep 17 00:00:00 2001 From: Vishesh Date: Tue, 7 May 2024 03:32:36 +0530 Subject: [PATCH 0062/1050] Fixup e2e test_restore_vm (#9025) * Fixup e2e test_restore_vm * Fix template's size attribute * Resolve comments --- test/integration/smoke/test_restore_vm.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/test/integration/smoke/test_restore_vm.py b/test/integration/smoke/test_restore_vm.py index ec0383d17a8..dd33346ed9e 100644 --- a/test/integration/smoke/test_restore_vm.py +++ b/test/integration/smoke/test_restore_vm.py @@ -32,6 +32,7 @@ class TestRestoreVM(cloudstackTestCase): testClient = super(TestRestoreVM, cls).getClsTestClient() cls.apiclient = testClient.getApiClient() cls.services = testClient.getParsedTestDataConfig() + cls._cleanup = [] # Get Zone, Domain and templates cls.domain = get_domain(cls.apiclient) @@ -42,16 +43,21 @@ class TestRestoreVM(cloudstackTestCase): cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.service_offering = ServiceOffering.create(cls.apiclient, cls.services["service_offering"]) + cls._cleanup.append(cls.service_offering) - cls.template_t1 = Template.register(cls.apiclient, cls.services["test_templates"][ + template_t1 = Template.register(cls.apiclient, cls.services["test_templates"][ cls.hypervisor.lower() if cls.hypervisor.lower() != 'simulator' else 'xenserver'], zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower()) + cls._cleanup.append(template_t1) + template_t1.download(cls.apiclient) + cls.template_t1 = Template.list(cls.apiclient, templatefilter='all', id=template_t1.id)[0] - cls.template_t2 = Template.register(cls.apiclient, cls.services["test_templates"][ + template_t2 = Template.register(cls.apiclient, cls.services["test_templates"][ cls.hypervisor.lower() if cls.hypervisor.lower() != 'simulator' else 'xenserver'], zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower()) - - cls._cleanup = [cls.service_offering, cls.template_t1, cls.template_t2] + cls._cleanup.append(template_t2) + template_t2.download(cls.apiclient) + cls.template_t2 = Template.list(cls.apiclient, templatefilter='all', id=template_t2.id)[0] @classmethod def tearDownClass(cls): From 0d1bc7dfd0c6db37a06c69bacca71e81c907929e Mon Sep 17 00:00:00 2001 From: Henrique Sato Date: Tue, 7 May 2024 04:12:49 -0300 Subject: [PATCH 0063/1050] Limit `listRoles` API visibility (#8639) Co-authored-by: Henrique Sato --- .../management/MockAccountManager.java | 5 + .../java/com/cloud/user/AccountManager.java | 2 + .../com/cloud/user/AccountManagerImpl.java | 5 + .../cloudstack/acl/RoleManagerImpl.java | 105 +++++++++--- .../cloud/user/MockAccountManagerImpl.java | 4 + .../cloudstack/acl/RoleManagerImplTest.java | 162 ++++++++++++++---- 6 files changed, 228 insertions(+), 55 deletions(-) diff --git a/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/MockAccountManager.java b/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/MockAccountManager.java index 836bb721329..610f4aa82aa 100644 --- a/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/MockAccountManager.java +++ b/plugins/network-elements/juniper-contrail/src/test/java/org/apache/cloudstack/network/contrail/management/MockAccountManager.java @@ -346,6 +346,11 @@ public class MockAccountManager extends ManagerBase implements AccountManager { return null; } + @Override + public List getApiNameList() { + return null; + } + @Override public boolean deleteUserAccount(long arg0) { // TODO Auto-generated method stub diff --git a/server/src/main/java/com/cloud/user/AccountManager.java b/server/src/main/java/com/cloud/user/AccountManager.java index c95047a6c42..6d2d1db5668 100644 --- a/server/src/main/java/com/cloud/user/AccountManager.java +++ b/server/src/main/java/com/cloud/user/AccountManager.java @@ -195,6 +195,8 @@ public interface AccountManager extends AccountService, Configurable { UserTwoFactorAuthenticator getUserTwoFactorAuthenticator(final Long domainId, final Long userAccountId); void verifyUsingTwoFactorAuthenticationCode(String code, Long domainId, Long userAccountId); + UserTwoFactorAuthenticationSetupResponse setupUserTwoFactorAuthentication(SetupUserTwoFactorAuthenticationCmd cmd); + List getApiNameList(); } diff --git a/server/src/main/java/com/cloud/user/AccountManagerImpl.java b/server/src/main/java/com/cloud/user/AccountManagerImpl.java index a95b660975b..d996b684b25 100644 --- a/server/src/main/java/com/cloud/user/AccountManagerImpl.java +++ b/server/src/main/java/com/cloud/user/AccountManagerImpl.java @@ -425,6 +425,11 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M _querySelectors = querySelectors; } + @Override + public List getApiNameList() { + return apiNameList; + } + @Override public boolean configure(final String name, final Map params) throws ConfigurationException { _systemAccount = _accountDao.findById(Account.ACCOUNT_ID_SYSTEM); diff --git a/server/src/main/java/org/apache/cloudstack/acl/RoleManagerImpl.java b/server/src/main/java/org/apache/cloudstack/acl/RoleManagerImpl.java index 9b6ac0e0279..bab286bb8f9 100644 --- a/server/src/main/java/org/apache/cloudstack/acl/RoleManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/acl/RoleManagerImpl.java @@ -18,9 +18,12 @@ package org.apache.cloudstack.acl; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import javax.inject.Inject; @@ -405,40 +408,98 @@ public class RoleManagerImpl extends ManagerBase implements RoleService, Configu public Pair, Integer> findRolesByName(String name, String keyword, Long startIndex, Long limit) { if (StringUtils.isNotBlank(name) || StringUtils.isNotBlank(keyword)) { Pair, Integer> data = roleDao.findAllByName(name, keyword, startIndex, limit, isCallerRootAdmin()); - int removed = removeRootAdminRolesIfNeeded(data.first()); + int removed = removeRolesIfNeeded(data.first()); return new Pair,Integer>(ListUtils.toListOfInterface(data.first()), Integer.valueOf(data.second() - removed)); } return new Pair, Integer>(new ArrayList(), 0); } /** - * Removes roles of the given list that have the type '{@link RoleType#Admin}' if the user calling the method is not a 'root admin'. - * The actual removal is executed via {@link #removeRootAdminRoles(List)}. Therefore, if the method is called by a 'root admin', we do nothing here. + * Removes roles from the given list if the role has different or more permissions than the user's calling the method role */ - protected int removeRootAdminRolesIfNeeded(List roles) { - if (!isCallerRootAdmin()) { - return removeRootAdminRoles(roles); + protected int removeRolesIfNeeded(List roles) { + if (roles.isEmpty()) { + return 0; } - return 0; + + Long callerRoleId = getCurrentAccount().getRoleId(); + Map callerRolePermissions = getRoleRulesAndPermissions(callerRoleId); + + int count = 0; + Iterator rolesIterator = roles.iterator(); + while (rolesIterator.hasNext()) { + Role role = rolesIterator.next(); + + if (role.getId() == callerRoleId || roleHasPermission(callerRolePermissions, role)) { + continue; + } + + count++; + rolesIterator.remove(); + } + + return count; } /** - * Remove all roles that have the {@link RoleType#Admin}. + * Checks if the role of the caller account has compatible permissions of the specified role. + * For each permission of the role of the caller, the target role needs to contain the same permission. + * + * @param sourceRolePermissions the permissions of the caller role. + * @param targetRole the role that the caller role wants to access. + * @return True if the role can be accessed with the given permissions; false otherwise. */ - protected int removeRootAdminRoles(List roles) { - if (CollectionUtils.isEmpty(roles)) { - return 0; - } - Iterator rolesIterator = roles.iterator(); - int count = 0; - while (rolesIterator.hasNext()) { - Role role = rolesIterator.next(); - if (RoleType.Admin == role.getRoleType()) { - count++; - rolesIterator.remove(); + protected boolean roleHasPermission(Map sourceRolePermissions, Role targetRole) { + Set rulesAlreadyCompared = new HashSet<>(); + for (RolePermission rolePermission : findAllPermissionsBy(targetRole.getId())) { + boolean permissionIsRegex = rolePermission.getRule().getRuleString().contains("*"); + + for (String apiName : accountManager.getApiNameList()) { + if (!rolePermission.getRule().matches(apiName) || rulesAlreadyCompared.contains(apiName)) { + continue; + } + + if (rolePermission.getPermission() == Permission.ALLOW && (!sourceRolePermissions.containsKey(apiName) || sourceRolePermissions.get(apiName) == Permission.DENY)) { + return false; + } + + rulesAlreadyCompared.add(apiName); + + if (!permissionIsRegex) { + break; + } } } - return count; + + return true; + } + + /** + * Given a role ID, returns a {@link Map} containing the API name as the key and the {@link Permission} for the API as the value. + * + * @param roleId ID from role. + */ + public Map getRoleRulesAndPermissions(Long roleId) { + Map roleRulesAndPermissions = new HashMap<>(); + + for (RolePermission rolePermission : findAllPermissionsBy(roleId)) { + boolean permissionIsRegex = rolePermission.getRule().getRuleString().contains("*"); + + for (String apiName : accountManager.getApiNameList()) { + if (!rolePermission.getRule().matches(apiName)) { + continue; + } + + if (!roleRulesAndPermissions.containsKey(apiName)) { + roleRulesAndPermissions.put(apiName, rolePermission.getPermission()); + } + + if (!permissionIsRegex) { + break; + } + } + } + return roleRulesAndPermissions; } @Override @@ -458,14 +519,14 @@ public class RoleManagerImpl extends ManagerBase implements RoleService, Configu @Override public List listRoles() { List roles = roleDao.listAll(); - removeRootAdminRolesIfNeeded(roles); + removeRolesIfNeeded(roles); return ListUtils.toListOfInterface(roles); } @Override public Pair, Integer> listRoles(Long startIndex, Long limit) { Pair, Integer> data = roleDao.listAllRoles(startIndex, limit, isCallerRootAdmin()); - int removed = removeRootAdminRolesIfNeeded(data.first()); + int removed = removeRolesIfNeeded(data.first()); return new Pair,Integer>(ListUtils.toListOfInterface(data.first()), Integer.valueOf(data.second() - removed)); } diff --git a/server/src/test/java/com/cloud/user/MockAccountManagerImpl.java b/server/src/test/java/com/cloud/user/MockAccountManagerImpl.java index fe7748b8581..334e1f33481 100644 --- a/server/src/test/java/com/cloud/user/MockAccountManagerImpl.java +++ b/server/src/test/java/com/cloud/user/MockAccountManagerImpl.java @@ -479,4 +479,8 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco return null; } + @Override + public List getApiNameList() { + return null; + } } diff --git a/server/src/test/java/org/apache/cloudstack/acl/RoleManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/acl/RoleManagerImplTest.java index 2bb46c0deee..e596601325e 100644 --- a/server/src/test/java/org/apache/cloudstack/acl/RoleManagerImplTest.java +++ b/server/src/test/java/org/apache/cloudstack/acl/RoleManagerImplTest.java @@ -20,7 +20,10 @@ package org.apache.cloudstack.acl; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.utils.Pair; + +import org.apache.cloudstack.acl.RolePermissionEntity.Permission; import org.apache.cloudstack.acl.dao.RoleDao; +import org.apache.cloudstack.acl.dao.RolePermissionsDao; import org.apache.commons.collections.CollectionUtils; import org.junit.Assert; import org.junit.Before; @@ -33,7 +36,10 @@ import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; @RunWith(MockitoJUnitRunner.class) public class RoleManagerImplTest { @@ -45,6 +51,22 @@ public class RoleManagerImplTest { private AccountManager accountManagerMock; @Mock private RoleDao roleDaoMock; + @Mock + private RolePermissionsDao rolePermissionsDaoMock; + @Mock + private RolePermission rolePermission1Mock; + @Mock + private RolePermission rolePermission2Mock; + @Mock + private Account callerAccountMock; + @Mock + private Role callerAccountRoleMock; + @Mock + private Role lessPermissionsRoleMock; + @Mock + private Role morePermissionsRoleMock; + @Mock + private Role differentPermissionsRoleMock; @Mock private Account accountMock; @@ -54,6 +76,33 @@ public class RoleManagerImplTest { private RoleVO roleVoMock; private long roleMockId = 1l; + private Map rolePermissions = new HashMap<>(); + + public void setUpRoleVisibilityTests() { + Mockito.doReturn(List.of("api1", "api2", "api3")).when(accountManagerMock).getApiNameList(); + + Mockito.doReturn(1L).when(callerAccountRoleMock).getId(); + Mockito.doReturn(callerAccountMock).when(roleManagerImpl).getCurrentAccount(); + Mockito.doReturn(callerAccountRoleMock.getId()).when(callerAccountMock).getRoleId(); + + Mockito.when(rolePermission1Mock.getRule()).thenReturn(new Rule("api1")); + Mockito.when(rolePermission2Mock.getRule()).thenReturn(new Rule("api2")); + Mockito.doReturn(RolePermissionEntity.Permission.ALLOW).when(rolePermission1Mock).getPermission(); + Mockito.doReturn(RolePermissionEntity.Permission.ALLOW).when(rolePermission2Mock).getPermission(); + + List lessPermissionsRolePermissions = Collections.singletonList(rolePermission1Mock); + Mockito.doReturn(1L).when(lessPermissionsRoleMock).getId(); + Mockito.when(roleManagerImpl.findAllPermissionsBy(1L)).thenReturn(lessPermissionsRolePermissions); + + List morePermissionsRolePermissions = List.of(rolePermission1Mock, rolePermission2Mock); + Mockito.doReturn(2L).when(morePermissionsRoleMock).getId(); + Mockito.when(roleManagerImpl.findAllPermissionsBy(morePermissionsRoleMock.getId())).thenReturn(morePermissionsRolePermissions); + + List differentPermissionsRolePermissions = Collections.singletonList(rolePermission2Mock); + Mockito.doReturn(3L).when(differentPermissionsRoleMock).getId(); + Mockito.when(roleManagerImpl.findAllPermissionsBy(differentPermissionsRoleMock.getId())).thenReturn(differentPermissionsRolePermissions); + } + @Before public void beforeTest() { Mockito.doReturn(accountMockId).when(accountMock).getId(); @@ -168,57 +217,104 @@ public class RoleManagerImplTest { Mockito.doReturn(toBeReturned).when(roleDaoMock).findAllByName(roleName, null, null, null, false); roleManagerImpl.findRolesByName(roleName); - Mockito.verify(roleManagerImpl).removeRootAdminRolesIfNeeded(roles); + Mockito.verify(roleManagerImpl).removeRolesIfNeeded(roles); } @Test - public void removeRootAdminRolesIfNeededTestRootAdmin() { - Mockito.doReturn(accountMock).when(roleManagerImpl).getCurrentAccount(); - Mockito.doReturn(true).when(accountManagerMock).isRootAdmin(accountMockId); - + public void removeRolesIfNeededTestRoleWithMoreAndSamePermissionsKeepRoles() { + setUpRoleVisibilityTests(); List roles = new ArrayList<>(); - roleManagerImpl.removeRootAdminRolesIfNeeded(roles); - Mockito.verify(roleManagerImpl, Mockito.times(0)).removeRootAdminRoles(roles); + List callerAccountRolePermissions = List.of(rolePermission1Mock, rolePermission2Mock); + Mockito.when(roleManagerImpl.findAllPermissionsBy(callerAccountRoleMock.getId())).thenReturn(callerAccountRolePermissions); + + roles.add(callerAccountRoleMock); + roles.add(lessPermissionsRoleMock); + + roleManagerImpl.removeRolesIfNeeded(roles); + + Assert.assertEquals(2, roles.size()); + Assert.assertEquals(callerAccountRoleMock, roles.get(0)); + Assert.assertEquals(lessPermissionsRoleMock, roles.get(1)); } @Test - public void removeRootAdminRolesIfNeededTestNonRootAdminUser() { - Mockito.doReturn(accountMock).when(roleManagerImpl).getCurrentAccount(); - Mockito.doReturn(false).when(accountManagerMock).isRootAdmin(accountMockId); - + public void removeRolesIfNeededTestRoleWithLessPermissionsRemoveRoles() { + setUpRoleVisibilityTests(); List roles = new ArrayList<>(); - roleManagerImpl.removeRootAdminRolesIfNeeded(roles); - Mockito.verify(roleManagerImpl, Mockito.times(1)).removeRootAdminRoles(roles); + List callerAccountRolePermissions = Collections.singletonList(rolePermission1Mock); + Mockito.when(roleManagerImpl.findAllPermissionsBy(callerAccountRoleMock.getId())).thenReturn(callerAccountRolePermissions); + + + roles.add(callerAccountRoleMock); + roles.add(morePermissionsRoleMock); + + roleManagerImpl.removeRolesIfNeeded(roles); + + Assert.assertEquals(1, roles.size()); + Assert.assertEquals(callerAccountRoleMock, roles.get(0)); } @Test - public void removeRootAdminRolesTest() { + public void removeRolesIfNeededTestRoleWithDifferentPermissionsRemoveRoles() { + setUpRoleVisibilityTests(); List roles = new ArrayList<>(); - Role roleRootAdmin = Mockito.mock(Role.class); - Mockito.doReturn(RoleType.Admin).when(roleRootAdmin).getRoleType(); - Role roleDomainAdmin = Mockito.mock(Role.class); - Mockito.doReturn(RoleType.DomainAdmin).when(roleDomainAdmin).getRoleType(); + List callerAccountRolePermissions = Collections.singletonList(rolePermission1Mock); + Mockito.when(roleManagerImpl.findAllPermissionsBy(callerAccountRoleMock.getId())).thenReturn(callerAccountRolePermissions); - Role roleResourceAdmin = Mockito.mock(Role.class); - Mockito.doReturn(RoleType.ResourceAdmin).when(roleResourceAdmin).getRoleType(); + roles.add(callerAccountRoleMock); + roles.add(differentPermissionsRoleMock); - Role roleUser = Mockito.mock(Role.class); - Mockito.doReturn(RoleType.User).when(roleUser).getRoleType(); + roleManagerImpl.removeRolesIfNeeded(roles); - roles.add(roleRootAdmin); - roles.add(roleDomainAdmin); - roles.add(roleResourceAdmin); - roles.add(roleUser); + Assert.assertEquals(1, roles.size()); + Assert.assertEquals(callerAccountRoleMock, roles.get(0)); + } - roleManagerImpl.removeRootAdminRoles(roles); + @Test + public void roleHasPermissionTestRoleWithMoreAndSamePermissionsReturnsTrue() { + setUpRoleVisibilityTests(); + rolePermissions.put("api1", Permission.ALLOW); + rolePermissions.put("api2", Permission.ALLOW); - Assert.assertEquals(3, roles.size()); - Assert.assertEquals(roleDomainAdmin, roles.get(0)); - Assert.assertEquals(roleResourceAdmin, roles.get(1)); - Assert.assertEquals(roleUser, roles.get(2)); + boolean result = roleManagerImpl.roleHasPermission(rolePermissions, lessPermissionsRoleMock); + + Assert.assertTrue(result); + } + + @Test + public void roleHasPermissionTestRoleAllowedApisDoesNotContainRoleToAccessAllowedApiReturnsFalse() { + setUpRoleVisibilityTests(); + rolePermissions.put("api2", Permission.ALLOW); + rolePermissions.put("api3", Permission.ALLOW); + + boolean result = roleManagerImpl.roleHasPermission(rolePermissions, morePermissionsRoleMock); + + Assert.assertFalse(result); + } + + @Test + public void roleHasPermissionTestRolePermissionsDeniedApiContainRoleToAccessAllowedApiReturnsFalse() { + setUpRoleVisibilityTests(); + rolePermissions.put("api1", Permission.ALLOW); + rolePermissions.put("api2", Permission.DENY); + + boolean result = roleManagerImpl.roleHasPermission(rolePermissions, morePermissionsRoleMock); + + Assert.assertFalse(result); + } + + @Test + public void getRolePermissionsTestRoleReturnsRolePermissions() { + setUpRoleVisibilityTests(); + + Map roleRulesAndPermissions = roleManagerImpl.getRoleRulesAndPermissions(morePermissionsRoleMock.getId()); + + Assert.assertEquals(2, roleRulesAndPermissions.size()); + Assert.assertEquals(roleRulesAndPermissions.get("api1"), Permission.ALLOW); + Assert.assertEquals(roleRulesAndPermissions.get("api2"), Permission.ALLOW); } @Test @@ -277,12 +373,12 @@ public class RoleManagerImplTest { roles.add(Mockito.mock(Role.class)); Mockito.doReturn(roles).when(roleDaoMock).listAll(); - Mockito.doReturn(0).when(roleManagerImpl).removeRootAdminRolesIfNeeded(roles); + Mockito.doReturn(0).when(roleManagerImpl).removeRolesIfNeeded(roles); List returnedRoles = roleManagerImpl.listRoles(); Assert.assertEquals(roles.size(), returnedRoles.size()); Mockito.verify(roleDaoMock).listAll(); - Mockito.verify(roleManagerImpl).removeRootAdminRolesIfNeeded(roles); + Mockito.verify(roleManagerImpl).removeRolesIfNeeded(roles); } } From 6b4955affe9f9658eb8128b3b7d18f08a1f05752 Mon Sep 17 00:00:00 2001 From: Vishesh Date: Tue, 7 May 2024 13:27:31 +0530 Subject: [PATCH 0064/1050] 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 0065/1050] 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 0066/1050] 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 7a341942373b777cbea22dd4981444cda67478fb Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Wed, 8 May 2024 13:25:47 +0200 Subject: [PATCH 0067/1050] cleanup: remove test/src-not-used/ (#9007) --- .../cloud/sample/UserCloudAPIExecutor.java | 188 -- .../cloud/test/longrun/BuildGuestNetwork.java | 123 - .../com/cloud/test/longrun/GuestNetwork.java | 107 - .../test/longrun/PerformanceWithAPI.java | 190 -- .../java/com/cloud/test/longrun/User.java | 202 -- .../cloud/test/longrun/VirtualMachine.java | 95 - .../com/cloud/test/regression/ApiCommand.java | 848 ------ .../com/cloud/test/regression/ConfigTest.java | 125 - .../test/regression/DelegatedAdminTest.java | 129 - .../com/cloud/test/regression/Deploy.java | 109 - .../cloud/test/regression/EventsApiTest.java | 176 -- .../java/com/cloud/test/regression/HA.java | 80 - .../test/regression/LoadBalancingTest.java | 142 - .../test/regression/PortForwardingTest.java | 143 - .../com/cloud/test/regression/SanityTest.java | 86 - .../java/com/cloud/test/regression/Test.java | 88 - .../com/cloud/test/regression/TestCase.java | 138 - .../cloud/test/regression/TestCaseEngine.java | 275 -- .../com/cloud/test/regression/VMApiTest.java | 91 - .../java/com/cloud/test/stress/SshTest.java | 90 - .../test/stress/StressTestDirectAttach.java | 1353 ---------- .../cloud/test/stress/TestClientWithAPI.java | 2289 ----------------- .../java/com/cloud/test/stress/WgetTest.java | 150 -- .../test/ui/AbstractSeleniumTestCase.java | 55 - .../com/cloud/test/ui/AddAndDeleteAISO.java | 127 - .../cloud/test/ui/AddAndDeleteATemplate.java | 126 - .../com/cloud/test/ui/UIScenarioTest.java | 86 - .../com/cloud/test/utils/ConsoleProxy.java | 110 - .../com/cloud/test/utils/IpSqlGenerator.java | 89 - .../com/cloud/test/utils/ProxyLoadTemp.java | 112 - .../java/com/cloud/test/utils/SignEC2.java | 143 - .../com/cloud/test/utils/SignRequest.java | 112 - .../cloud/test/utils/SqlDataGenerator.java | 49 - .../java/com/cloud/test/utils/SubmitCert.java | 198 -- .../java/com/cloud/test/utils/TestClient.java | 385 --- .../com/cloud/test/utils/UtilsForTest.java | 210 -- 36 files changed, 9019 deletions(-) delete mode 100644 test/src-not-used/main/java/com/cloud/sample/UserCloudAPIExecutor.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/longrun/BuildGuestNetwork.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/longrun/GuestNetwork.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/longrun/PerformanceWithAPI.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/longrun/User.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/longrun/VirtualMachine.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/regression/ApiCommand.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/regression/ConfigTest.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/regression/DelegatedAdminTest.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/regression/Deploy.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/regression/EventsApiTest.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/regression/HA.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/regression/LoadBalancingTest.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/regression/PortForwardingTest.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/regression/SanityTest.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/regression/Test.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/regression/TestCase.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/regression/TestCaseEngine.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/regression/VMApiTest.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/stress/SshTest.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/stress/StressTestDirectAttach.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/stress/TestClientWithAPI.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/stress/WgetTest.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/ui/AbstractSeleniumTestCase.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteAISO.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteATemplate.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/ui/UIScenarioTest.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/utils/ConsoleProxy.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/utils/IpSqlGenerator.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/utils/ProxyLoadTemp.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/utils/SignEC2.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/utils/SignRequest.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/utils/SqlDataGenerator.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/utils/SubmitCert.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/utils/TestClient.java delete mode 100644 test/src-not-used/main/java/com/cloud/test/utils/UtilsForTest.java diff --git a/test/src-not-used/main/java/com/cloud/sample/UserCloudAPIExecutor.java b/test/src-not-used/main/java/com/cloud/sample/UserCloudAPIExecutor.java deleted file mode 100644 index 6baadb8b035..00000000000 --- a/test/src-not-used/main/java/com/cloud/sample/UserCloudAPIExecutor.java +++ /dev/null @@ -1,188 +0,0 @@ -// 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. -package com.cloud.sample; - -import java.io.FileInputStream; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Properties; -import java.util.StringTokenizer; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; - -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; - -/** - * - * - * - * - * - * - * - * - * - */ - -/** - * Sample CloudStack Management User API Executor. - * - * Prerequisites: - Edit usercloud.properties to include your host, apiUrl, apiKey, and secretKey - Use ./executeUserAPI.sh to - * execute this test class - * - * - */ -public class UserCloudAPIExecutor { - public static void main(String[] args) { - // Host - String host = null; - - // Fully qualified URL with http(s)://host:port - String apiUrl = null; - - // ApiKey and secretKey as given by your CloudStack vendor - String apiKey = null; - String secretKey = null; - - try { - Properties prop = new Properties(); - prop.load(new FileInputStream("usercloud.properties")); - - // host - host = prop.getProperty("host"); - if (host == null) { - System.out.println("Please specify a valid host in the format of http(s)://:/client/api in your usercloud.properties file."); - } - - // apiUrl - apiUrl = prop.getProperty("apiUrl"); - if (apiUrl == null) { - System.out.println("Please specify a valid API URL in the format of command=¶m1=¶m2=... in your usercloud.properties file."); - } - - // apiKey - apiKey = prop.getProperty("apiKey"); - if (apiKey == null) { - System.out.println("Please specify your API Key as provided by your CloudStack vendor in your usercloud.properties file."); - } - - // secretKey - secretKey = prop.getProperty("secretKey"); - if (secretKey == null) { - System.out.println("Please specify your secret Key as provided by your CloudStack vendor in your usercloud.properties file."); - } - - if (apiUrl == null || apiKey == null || secretKey == null) { - return; - } - - System.out.println("Constructing API call to host = '" + host + "' with API command = '" + apiUrl + "' using apiKey = '" + apiKey + "' and secretKey = '" + - secretKey + "'"); - - // Step 1: Make sure your APIKey is URL encoded - String encodedApiKey = URLEncoder.encode(apiKey, "UTF-8"); - - // Step 2: URL encode each parameter value, then sort the parameters and apiKey in - // alphabetical order, and then toLowerCase all the parameters, parameter values and apiKey. - // Please note that if any parameters with a '&' as a value will cause this test client to fail since we are using - // '&' to delimit - // the string - List sortedParams = new ArrayList(); - sortedParams.add("apikey=" + encodedApiKey.toLowerCase()); - StringTokenizer st = new StringTokenizer(apiUrl, "&"); - String url = null; - boolean first = true; - while (st.hasMoreTokens()) { - String paramValue = st.nextToken(); - String param = paramValue.substring(0, paramValue.indexOf("=")); - String value = URLEncoder.encode(paramValue.substring(paramValue.indexOf("=") + 1, paramValue.length()), "UTF-8"); - if (first) { - url = param + "=" + value; - first = false; - } else { - url = url + "&" + param + "=" + value; - } - sortedParams.add(param.toLowerCase() + "=" + value.toLowerCase()); - } - Collections.sort(sortedParams); - - System.out.println("Sorted Parameters: " + sortedParams); - - // Step 3: Construct the sorted URL and sign and URL encode the sorted URL with your secret key - String sortedUrl = null; - first = true; - for (String param : sortedParams) { - if (first) { - sortedUrl = param; - first = false; - } else { - sortedUrl = sortedUrl + "&" + param; - } - } - System.out.println("sorted URL : " + sortedUrl); - String encodedSignature = signRequest(sortedUrl, secretKey); - - // Step 4: Construct the final URL we want to send to the CloudStack Management Server - // Final result should look like: - // http(s)://://client/api?&apiKey=&signature= - String finalUrl = host + "?" + url + "&apiKey=" + apiKey + "&signature=" + encodedSignature; - System.out.println("final URL : " + finalUrl); - - // Step 5: Perform a HTTP GET on this URL to execute the command - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(finalUrl); - int responseCode = client.executeMethod(method); - if (responseCode == 200) { - // SUCCESS! - System.out.println("Successfully executed command"); - } else { - // FAILED! - System.out.println("Unable to execute command with response code: " + responseCode); - } - - } catch (Throwable t) { - System.out.println(t); - } - } - - /** - * 1. Signs a string with a secret key using SHA-1 2. Base64 encode the result 3. URL encode the final result - * - * @param request - * @param key - * @return - */ - public static String signRequest(String request, String key) { - try { - Mac mac = Mac.getInstance("HmacSHA1"); - SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1"); - mac.init(keySpec); - mac.update(request.getBytes()); - byte[] encryptedBytes = mac.doFinal(); - return URLEncoder.encode(Base64.encodeBase64String(encryptedBytes), "UTF-8"); - } catch (Exception ex) { - System.out.println(ex); - } - return null; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/longrun/BuildGuestNetwork.java b/test/src-not-used/main/java/com/cloud/test/longrun/BuildGuestNetwork.java deleted file mode 100644 index 3a823ab9733..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/longrun/BuildGuestNetwork.java +++ /dev/null @@ -1,123 +0,0 @@ -// 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. -package com.cloud.test.longrun; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Random; - -import org.apache.log4j.Logger; - -public class BuildGuestNetwork { - - public static final Logger s_logger = Logger.getLogger(BuildGuestNetwork.class.getClass()); - private static final int ApiPort = 8096; - private static final int DeveloperPort = 8080; - private static final String ApiUrl = "/client/api"; - private static int numVM = 1; - private static long zoneId = -1L; - private static long templateId = 3; - private static long serviceOfferingId = 1; - - public static void main(String[] args) { - - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - String host = "http://localhost"; - int numThreads = 1; - - while (iter.hasNext()) { - String arg = iter.next(); - if (arg.equals("-h")) { - host = "http://" + iter.next(); - } - if (arg.equals("-t")) { - numThreads = Integer.parseInt(iter.next()); - } - if (arg.equals("-n")) { - numVM = Integer.parseInt(iter.next()); - } - if (arg.equals("-z")) { - zoneId = Integer.parseInt(iter.next()); - } - - if (arg.equals("-e")) { - templateId = Integer.parseInt(iter.next()); - } - - if (arg.equals("-s")) { - serviceOfferingId = Integer.parseInt(iter.next()); - } - } - - final String server = host + ":" + ApiPort + "/"; - final String developerServer = host + ":" + DeveloperPort + ApiUrl; - s_logger.info("Starting test in " + numThreads + " thread(s). Each thread is launching " + numVM + " VMs"); - - for (int i = 0; i < numThreads; i++) { - new Thread(new Runnable() { - @Override - public void run() { - try { - - String username = null; - String singlePrivateIp = null; - Random ran = new Random(); - username = Math.abs(ran.nextInt()) + "-user"; - - //Create User - User myUser = new User(username, username, server, developerServer); - try { - myUser.launchUser(); - myUser.registerUser(); - } catch (Exception e) { - s_logger.warn("Error code: ", e); - } - - if (myUser.getUserId() != null) { - s_logger.info("User " + myUser.getUserName() + " was created successfully, starting VM creation"); - //create VMs for the user - for (int i = 0; i < numVM; i++) { - //Create a new VM, add it to the list of user's VMs - VirtualMachine myVM = new VirtualMachine(myUser.getUserId()); - myVM.deployVM(zoneId, serviceOfferingId, templateId, myUser.getDeveloperServer(), myUser.getApiKey(), myUser.getSecretKey()); - myUser.getVirtualMachines().add(myVM); - singlePrivateIp = myVM.getPrivateIp(); - - if (singlePrivateIp != null) { - s_logger.info("VM with private Ip " + singlePrivateIp + " was successfully created"); - } else { - s_logger.info("Problems with VM creation for a user" + myUser.getUserName()); - s_logger.info("Deployment failed"); - break; - } - } - - s_logger.info("Deployment done..." + numVM + " VMs were created."); - } - - } catch (Exception e) { - s_logger.error(e); - } - } - }).start(); - - } - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/longrun/GuestNetwork.java b/test/src-not-used/main/java/com/cloud/test/longrun/GuestNetwork.java deleted file mode 100644 index 226e31ae4cc..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/longrun/GuestNetwork.java +++ /dev/null @@ -1,107 +0,0 @@ -// 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. -package com.cloud.test.longrun; - -import java.util.ArrayList; -import java.util.Random; - -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; - -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.Session; - -public class GuestNetwork implements Runnable { - public static final Logger s_logger = Logger.getLogger(GuestNetwork.class.getClass()); - - private String publicIp; - private ArrayList virtualMachines; - private int retryNum; - - public GuestNetwork(String publicIp, int retryNum) { - this.publicIp = publicIp; - this.retryNum = retryNum; - } - - public ArrayList getVirtualMachines() { - return virtualMachines; - } - - public void setVirtualMachines(ArrayList virtualMachines) { - this.virtualMachines = virtualMachines; - } - - @Override - public void run() { - NDC.push("Following thread has started" + Thread.currentThread().getName()); - int retry = 0; - - //Start copying files between machines in the network - s_logger.info("The size of the array is " + this.virtualMachines.size()); - while (true) { - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt"); - Thread.sleep(120000); - } - for (VirtualMachine vm : this.virtualMachines) { - - s_logger.info("Attempting to SSH into linux host " + this.publicIp + " with retry attempt: " + retry); - Connection conn = new Connection(this.publicIp); - conn.connect(null, 600000, 600000); - - s_logger.info("SSHed successfully into linux host " + this.publicIp); - - boolean isAuthenticated = conn.authenticateWithPassword("root", "password"); - - if (isAuthenticated == false) { - s_logger.info("Authentication failed"); - } - //execute copy command - Session sess = conn.openSession(); - String fileName; - Random ran = new Random(); - fileName = Math.abs(ran.nextInt()) + "-file"; - String copyCommand = new String("./scpScript " + vm.getPrivateIp() + " " + fileName); - s_logger.info("Executing " + copyCommand); - sess.execCommand(copyCommand); - Thread.sleep(120000); - sess.close(); - - //execute wget command - sess = conn.openSession(); - String downloadCommand = - new String("wget http://172.16.0.220/scripts/checkDiskSpace.sh; chmod +x *sh; ./checkDiskSpace.sh; rm -rf checkDiskSpace.sh"); - s_logger.info("Executing " + downloadCommand); - sess.execCommand(downloadCommand); - Thread.sleep(120000); - sess.close(); - - //close the connection - conn.close(); - } - } catch (Exception ex) { - s_logger.error(ex); - retry++; - if (retry == retryNum) { - s_logger.info("Performance Guest Network test failed with error " + ex.getMessage()); - } - } - } - - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/longrun/PerformanceWithAPI.java b/test/src-not-used/main/java/com/cloud/test/longrun/PerformanceWithAPI.java deleted file mode 100644 index f1a3725d01f..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/longrun/PerformanceWithAPI.java +++ /dev/null @@ -1,190 +0,0 @@ -// 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. -package com.cloud.test.longrun; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; - -import com.cloud.test.stress.TestClientWithAPI; - -public class PerformanceWithAPI { - - public static final Logger s_logger = Logger.getLogger(PerformanceWithAPI.class.getClass()); - private static final int Retry = 10; - private static final int ApiPort = 8096; - private static int s_numVM = 2; - private static final long ZoneId = -1L; - private static final long TemplateId = 3; - private static final long ServiceOfferingId = 1; - private static final String ApiUrl = "/client/api"; - private static final int DeveloperPort = 8080; - - public static void main(String[] args) { - - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - String host = "http://localhost"; - int numThreads = 1; - - while (iter.hasNext()) { - String arg = iter.next(); - if (arg.equals("-h")) { - host = "http://" + iter.next(); - } - if (arg.equals("-t")) { - numThreads = Integer.parseInt(iter.next()); - } - if (arg.equals("-n")) { - s_numVM = Integer.parseInt(iter.next()); - } - } - - final String server = host + ":" + ApiPort + "/"; - final String developerServer = host + ":" + DeveloperPort + ApiUrl; - - s_logger.info("Starting test in " + numThreads + " thread(s). Each thread is launching " + s_numVM + " VMs"); - - for (int i = 0; i < numThreads; i++) { - new Thread(new Runnable() { - @Override - public void run() { - try { - - String username = null; - String singlePrivateIp = null; - String singlePublicIp = null; - Random ran = new Random(); - username = Math.abs(ran.nextInt()) + "-user"; - - //Create User - User myUser = new User(username, username, server, developerServer); - try { - myUser.launchUser(); - myUser.registerUser(); - } catch (Exception e) { - s_logger.warn("Error code: ", e); - } - - if (myUser.getUserId() != null) { - s_logger.info("User " + myUser.getUserName() + " was created successfully, starting VM creation"); - //create VMs for the user - for (int i = 0; i < s_numVM; i++) { - //Create a new VM, add it to the list of user's VMs - VirtualMachine myVM = new VirtualMachine(myUser.getUserId()); - myVM.deployVM(ZoneId, ServiceOfferingId, TemplateId, myUser.getDeveloperServer(), myUser.getApiKey(), myUser.getSecretKey()); - myUser.getVirtualMachines().add(myVM); - singlePrivateIp = myVM.getPrivateIp(); - - if (singlePrivateIp != null) { - s_logger.info("VM with private Ip " + singlePrivateIp + " was successfully created"); - } else { - s_logger.info("Problems with VM creation for a user" + myUser.getUserName()); - break; - } - - //get public IP address for the User - myUser.retrievePublicIp(ZoneId); - singlePublicIp = myUser.getPublicIp().get(myUser.getPublicIp().size() - 1); - if (singlePublicIp != null) { - s_logger.info("Successfully got public Ip " + singlePublicIp + " for user " + myUser.getUserName()); - } else { - s_logger.info("Problems with getting public Ip address for user" + myUser.getUserName()); - break; - } - - //create ForwardProxy rules for user's VMs - int responseCode = CreateForwardingRule(myUser, singlePrivateIp, singlePublicIp, "22", "22"); - if (responseCode == 500) - break; - } - - s_logger.info("Deployment successful..." + s_numVM + " VMs were created. Waiting for 5 min before performance test"); - Thread.sleep(300000L); // Wait - - //Start performance test for the user - s_logger.info("Starting performance test for Guest network that has " + myUser.getPublicIp().size() + " public IP addresses"); - for (int j = 0; j < myUser.getPublicIp().size(); j++) { - s_logger.info("Starting test for user which has " + myUser.getVirtualMachines().size() + " vms. Public IP for the user is " + - myUser.getPublicIp().get(j) + " , number of retries is " + Retry + " , private IP address of the machine is" + - myUser.getVirtualMachines().get(j).getPrivateIp()); - GuestNetwork myNetwork = new GuestNetwork(myUser.getPublicIp().get(j), Retry); - myNetwork.setVirtualMachines(myUser.getVirtualMachines()); - new Thread(myNetwork).start(); - } - - } - } catch (Exception e) { - s_logger.error(e); - } - } - }).start(); - - } - } - - private static int CreateForwardingRule(User myUser, String privateIp, String publicIp, String publicPort, String privatePort) throws IOException { - String encodedPrivateIp = URLEncoder.encode("" + privateIp, "UTF-8"); - String encodedPublicIp = URLEncoder.encode("" + publicIp, "UTF-8"); - String encodedPrivatePort = URLEncoder.encode("" + privatePort, "UTF-8"); - String encodedPublicPort = URLEncoder.encode("" + publicPort, "UTF-8"); - String encodedApiKey = URLEncoder.encode(myUser.getApiKey(), "UTF-8"); - int responseCode = 500; - - String requestToSign = - "apiKey=" + encodedApiKey + "&command=createOrUpdateIpForwardingRule&privateIp=" + encodedPrivateIp + "&privatePort=" + encodedPrivatePort + - "&protocol=tcp&publicIp=" + encodedPublicIp + "&publicPort=" + encodedPublicPort; - - requestToSign = requestToSign.toLowerCase(); - s_logger.info("Request to sign is " + requestToSign); - - String signature = TestClientWithAPI.signRequest(requestToSign, myUser.getSecretKey()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - String url = - myUser.getDeveloperServer() + "?command=createOrUpdateIpForwardingRule" + "&publicIp=" + encodedPublicIp + "&publicPort=" + encodedPublicPort + - "&privateIp=" + encodedPrivateIp + "&privatePort=" + encodedPrivatePort + "&protocol=tcp&apiKey=" + encodedApiKey + "&signature=" + encodedSignature; - - s_logger.info("Trying to create IP forwarding rule: " + url); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("create ip forwarding rule response code: " + responseCode); - if (responseCode == 200) { - s_logger.info("The rule is created successfully"); - } else if (responseCode == 500) { - InputStream is = method.getResponseBodyAsStream(); - Map errorInfo = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"errorCode", "description"}); - s_logger.error("create ip forwarding rule (linux) test failed with errorCode: " + errorInfo.get("errorCode") + " and description: " + - errorInfo.get("description")); - } else { - s_logger.error("internal error processing request: " + method.getStatusText()); - } - return responseCode; - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/longrun/User.java b/test/src-not-used/main/java/com/cloud/test/longrun/User.java deleted file mode 100644 index 06234c846ab..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/longrun/User.java +++ /dev/null @@ -1,202 +0,0 @@ -// 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. -package com.cloud.test.longrun; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Map; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpException; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; - -import com.cloud.test.stress.TestClientWithAPI; - -public class User { - public static final Logger s_logger = Logger.getLogger(User.class.getClass()); - - private ArrayList virtualMachines; - private ArrayList publicIp; - private String server; - private String developerServer; - private String userName; - private String userId; - private String apiKey; - private String secretKey; - private String password; - private String encryptedPassword; - - public User(String userName, String password, String server, String developerServer) { - this.server = server; - this.developerServer = developerServer; - this.userName = userName; - this.password = password; - this.virtualMachines = new ArrayList(); - this.publicIp = new ArrayList(); - } - - public ArrayList getVirtualMachines() { - return virtualMachines; - } - - public void setVirtualMachines(ArrayList virtualMachines) { - this.virtualMachines = virtualMachines; - } - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public ArrayList getPublicIp() { - return publicIp; - } - - public void setPublicIp(ArrayList publicIp) { - this.publicIp = publicIp; - } - - public String getServer() { - return server; - } - - public void setServer(String server) { - this.server = server; - } - - public String getUserName() { - return userName; - } - - public void setUserName(String userName) { - this.userName = userName; - } - - public String getApiKey() { - return apiKey; - } - - public void setApiKey(String apiKey) { - this.apiKey = apiKey; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getSecretKey() { - return secretKey; - } - - public void setSecretKey(String secretKey) { - this.secretKey = secretKey; - } - - public String getDeveloperServer() { - return developerServer; - } - - public void setDeveloperServer(String developerServer) { - this.developerServer = developerServer; - } - - public void launchUser() throws IOException { - String encodedUsername = URLEncoder.encode(this.getUserName(), "UTF-8"); - this.encryptedPassword = TestClientWithAPI.createMD5Password(this.getPassword()); - String encodedPassword = URLEncoder.encode(this.encryptedPassword, "UTF-8"); - String url = - this.server + "?command=createUser&username=" + encodedUsername + "&password=" + encodedPassword + - "&firstname=Test&lastname=Test&email=alena@vmops.com&domainId=1"; - String userIdStr = null; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map userIdValues = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"id"}); - userIdStr = userIdValues.get("id"); - if ((userIdStr != null) && (Long.parseLong(userIdStr) != -1)) { - this.setUserId(userIdStr); - } - } - } - - public void retrievePublicIp(long zoneId) throws IOException { - - String encodedApiKey = URLEncoder.encode(this.apiKey, "UTF-8"); - String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); - String requestToSign = "apiKey=" + encodedApiKey + "&command=associateIpAddress" + "&zoneId=" + encodedZoneId; - requestToSign = requestToSign.toLowerCase(); - String signature = TestClientWithAPI.signRequest(requestToSign, this.secretKey); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - String url = this.developerServer + "?command=associateIpAddress" + "&apiKey=" + encodedApiKey + "&zoneId=" + encodedZoneId + "&signature=" + encodedSignature; - - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map values = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"ipaddress"}); - this.getPublicIp().add(values.get("ipaddress")); - s_logger.info("Ip address is " + values.get("ipaddress")); - } else if (responseCode == 500) { - InputStream is = method.getResponseBodyAsStream(); - Map errorInfo = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"errorcode", "description"}); - s_logger.error("associate ip test failed with errorCode: " + errorInfo.get("errorCode") + " and description: " + errorInfo.get("description")); - } else { - s_logger.error("internal error processing request: " + method.getStatusText()); - } - - } - - public void registerUser() throws HttpException, IOException { - - String encodedUsername = URLEncoder.encode(this.userName, "UTF-8"); - String encodedPassword = URLEncoder.encode(this.password, "UTF-8"); - String url = server + "?command=register&username=" + encodedUsername + "&domainid=1"; - s_logger.info("registering: " + this.userName + " with url " + url); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map requestKeyValues = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"apikey", "secretkey"}); - this.setApiKey(requestKeyValues.get("apikey")); - this.setSecretKey(requestKeyValues.get("secretkey")); - } else if (responseCode == 500) { - InputStream is = method.getResponseBodyAsStream(); - Map errorInfo = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"errorcode", "description"}); - s_logger.error("registration failed with errorCode: " + errorInfo.get("errorCode") + " and description: " + errorInfo.get("description")); - } else { - s_logger.error("internal error processing request: " + method.getStatusText()); - } - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/longrun/VirtualMachine.java b/test/src-not-used/main/java/com/cloud/test/longrun/VirtualMachine.java deleted file mode 100644 index eaed0a2bd12..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/longrun/VirtualMachine.java +++ /dev/null @@ -1,95 +0,0 @@ -// 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. -package com.cloud.test.longrun; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URLEncoder; -import java.util.Map; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; - -import com.cloud.test.stress.TestClientWithAPI; - -public class VirtualMachine { - public static final Logger s_logger = Logger.getLogger(VirtualMachine.class.getClass()); - - private String privateIp; - private String userId; - - public VirtualMachine(String userId) { - this.userId = userId; - } - - public String getPrivateIp() { - return privateIp; - } - - public void setPrivateIp(String privateIp) { - this.privateIp = privateIp; - } - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public void deployVM(long zoneId, long serviceOfferingId, long templateId, String server, String apiKey, String secretKey) throws IOException { - - String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); - String encodedServiceOfferingId = URLEncoder.encode("" + serviceOfferingId, "UTF-8"); - String encodedTemplateId = URLEncoder.encode("" + templateId, "UTF-8"); - String encodedApiKey = URLEncoder.encode(apiKey, "UTF-8"); - String requestToSign = - "apiKey=" + encodedApiKey + "&command=deployVirtualMachine&serviceOfferingId=" + encodedServiceOfferingId + "&templateId=" + encodedTemplateId + "&zoneId=" + - encodedZoneId; - - requestToSign = requestToSign.toLowerCase(); - String signature = TestClientWithAPI.signRequest(requestToSign, secretKey); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - String url = - server + "?command=deployVirtualMachine" + "&zoneId=" + encodedZoneId + "&serviceOfferingId=" + encodedServiceOfferingId + "&templateId=" + - encodedTemplateId + "&apiKey=" + encodedApiKey + "&signature=" + encodedSignature; - - s_logger.info("Sending this request to deploy a VM: " + url); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("deploy linux vm response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map values = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"id", "ipaddress"}); - long linuxVMId = Long.parseLong(values.get("id")); - s_logger.info("got linux virtual machine id: " + linuxVMId); - this.setPrivateIp(values.get("ipaddress")); - - } else if (responseCode == 500) { - InputStream is = method.getResponseBodyAsStream(); - Map errorInfo = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"errorcode", "description"}); - s_logger.error("deploy linux vm test failed with errorCode: " + errorInfo.get("errorCode") + " and description: " + errorInfo.get("description")); - } else { - s_logger.error("internal error processing request: " + method.getStatusText()); - } - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/ApiCommand.java b/test/src-not-used/main/java/com/cloud/test/regression/ApiCommand.java deleted file mode 100644 index 9c9fc83bce9..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/ApiCommand.java +++ /dev/null @@ -1,848 +0,0 @@ -// 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. -package com.cloud.test.regression; - -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import java.net.URLEncoder; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Properties; -import java.util.Random; -import java.util.Set; -import java.util.TreeMap; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.cloud.test.utils.UtilsForTest; - -public class ApiCommand { - public static final Logger s_logger = Logger.getLogger(ApiCommand.class.getName()); - - public static enum CommandType { - HTTP, MYSQL, SCRIPT; - } - - public static enum ResponseType { - ERROR, EMPTY; - } - - private Element xmlCommand; - private String commandName; - private String testCaseInfo; - private boolean isUserCommand; - private boolean isAsync = false; - private CommandType commandType; - private ResponseType responseType; - - private TreeMap urlParam; - private HashMap verifyParam = new HashMap();; - private HashMap setParam = new HashMap();; - private int responseCode; - private Element responseBody; - - private String command; - private String host; - private boolean list; - private Element listName; - private Element listId; - private boolean required = false; - private ResultSet result; - - public ApiCommand(Element fstElmnt, HashMap param, HashMap commands) { - this.setXmlCommand(fstElmnt); - this.setCommandName(); - this.setResponseType(); - this.setUserCommand(); - this.setCommandType(); - this.setTestCaseInfo(); - this.setUrlParam(param); - this.setVerifyParam(param); - this.setHost("http://" + param.get("hostip")); - this.setCommand(param); - String async = commands.get(this.getName()); - if (async != null && async.equals("yes")) { - this.isAsync = true; - - } - } - - public Element getXmlCommand() { - return xmlCommand; - } - - public void setXmlCommand(Element xmlCommand) { - this.xmlCommand = xmlCommand; - } - - // ================FOLLOWING METHODS USE INPUT XML FILE=======================// - public void setCommandName() { - NodeList commandName = this.xmlCommand.getElementsByTagName("name"); - Element commandElmnt = (Element)commandName.item(0); - NodeList commandNm = commandElmnt.getChildNodes(); - this.commandName = (commandNm.item(0).getNodeValue()); - } - - public String getName() { - return commandName; - } - - public void setTestCaseInfo() { - this.testCaseInfo = getElementByName("testcase"); - } - - public String getHost() { - return host; - } - - public void setHost(String host) { - this.host = host; - } - - public void setResponseType() { - boolean result = verifyTagValue("error", "true"); - if (result) { - this.responseType = ResponseType.ERROR; - return; - } - result = verifyTagValue("empty", "true"); - if (result) { - this.responseType = ResponseType.EMPTY; - } - } - - public void setResponseType(ResponseType responseType) { - this.responseType = responseType; - } - - public ResponseType getResponseType() { - return responseType; - } - - public void setUserCommand() { - boolean result = verifyTagValue("usercommand", "true"); - this.isUserCommand = result; - } - - public void setCommandType() { - boolean result = verifyTagValue("mysql", "true"); - if (result) { - this.commandType = CommandType.MYSQL; - return; - } - result = verifyTagValue("script", "true"); - if (result) { - this.commandType = CommandType.SCRIPT; - return; - } - this.commandType = CommandType.HTTP; - } - - public CommandType getCommandType() { - return commandType; - } - - public String getTestCaseInfo() { - return testCaseInfo; - } - - public Boolean getRequired() { - return required; - } - - public void setUrlParam(HashMap param) { - this.urlParam = new TreeMap(); - NodeList parameterLst = this.xmlCommand.getElementsByTagName("parameters"); - if (parameterLst != null) { - for (int j = 0; j < parameterLst.getLength(); j++) { - Element parameterElement = (Element)parameterLst.item(j); - NodeList itemLst = parameterElement.getElementsByTagName("item"); - for (int k = 0; k < itemLst.getLength(); k++) { - Node item = itemLst.item(k); - if (item.getNodeType() == Node.ELEMENT_NODE) { - Element itemElement = (Element)item; - NodeList itemName = itemElement.getElementsByTagName("name"); - Element itemNameElement = (Element)itemName.item(0); - - // get value - Element itemValueElement = null; - if ((itemElement.getElementsByTagName("value") != null) && (itemElement.getElementsByTagName("value").getLength() != 0)) { - NodeList itemValue = itemElement.getElementsByTagName("value"); - itemValueElement = (Element)itemValue.item(0); - } - - Element itemParamElement = null; - // getparam - if ((itemElement.getElementsByTagName("param") != null) && (itemElement.getElementsByTagName("param").getLength() != 0)) { - NodeList itemParam = itemElement.getElementsByTagName("param"); - itemParamElement = (Element)itemParam.item(0); - } - - if ((itemElement.getAttribute("getparam").equals("true")) && (itemParamElement != null)) { - this.urlParam.put(itemNameElement.getTextContent(), param.get(itemParamElement.getTextContent())); - } else if (itemValueElement != null) { - this.urlParam.put(itemNameElement.getTextContent(), itemValueElement.getTextContent()); - } else if (itemElement.getAttribute("random").equals("true")) { - Random ran = new Random(); - String randomString = Math.abs(ran.nextInt()) + "-randomName"; - this.urlParam.put(itemNameElement.getTextContent(), randomString); - if ((itemElement.getAttribute("setparam").equals("true")) && (itemParamElement != null)) { - param.put(itemParamElement.getTextContent(), randomString); - } - } else if (itemElement.getAttribute("randomnumber").equals("true")) { - Random ran = new Random(); - Integer randomNumber = Math.abs(ran.nextInt(65535)); - this.urlParam.put(itemNameElement.getTextContent(), randomNumber.toString()); - if ((itemElement.getAttribute("setparam").equals("true")) && (itemParamElement != null)) { - param.put(itemParamElement.getTextContent(), randomNumber.toString()); - } - } - } - } - } - } - } - - // Set command URL - public void setCommand(HashMap param) { - - if (this.getCommandType() == CommandType.SCRIPT) { - String temp = "bash xen/" + this.commandName; - Set c = this.urlParam.entrySet(); - Iterator it = c.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - temp = temp + " -" + key + " " + value; - } catch (Exception ex) { - s_logger.error("Unable to set parameter " + key + " for the command " + this.getName()); - } - } - this.command = temp; - } else if (this.getCommandType() == CommandType.MYSQL) { - String temp = this.commandName + " where "; - Set c = this.urlParam.entrySet(); - Iterator it = c.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - temp = temp + key + "=" + value; - } catch (Exception ex) { - s_logger.error("Unable to set parameter " + key + " for the command " + this.getName()); - } - } - this.command = temp; - s_logger.info("The command is " + this.command); - - } else { - if ((param.get("apikey") == null) || (param.get("secretkey") == null) || (this.isUserCommand == false)) { - String temp = this.host + ":8096/?command=" + this.commandName; - Set c = this.urlParam.entrySet(); - Iterator it = c.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - temp = temp + "&" + key + "=" + URLEncoder.encode(value, "UTF-8"); - } catch (Exception ex) { - s_logger.error("Unable to set parameter " + key + " for the command " + this.getName()); - } - } - this.command = temp; - } else if (isUserCommand == true) { - String apiKey = param.get("apikey"); - String secretKey = param.get("secretkey"); - - String temp = ""; - this.urlParam.put("apikey", apiKey); - this.urlParam.put("command", this.commandName); - - // sort url hash map by key - Set c = this.urlParam.entrySet(); - Iterator it = c.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - temp = temp + key + "=" + URLEncoder.encode(value, "UTF-8") + "&"; - } catch (Exception ex) { - s_logger.error("Unable to set parameter " + value + " for the command " + this.getName()); - } - - } - temp = temp.substring(0, temp.length() - 1); - String requestToSign = temp.toLowerCase(); - String signature = UtilsForTest.signRequest(requestToSign, secretKey); - String encodedSignature = ""; - try { - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - } catch (Exception ex) { - s_logger.error(ex); - } - this.command = this.host + ":8080/client/api/?" + temp + "&signature=" + encodedSignature; - } - } - } - - public void setVerifyParam(HashMap param) { - NodeList returnLst = this.xmlCommand.getElementsByTagName("returnvalue"); - if (returnLst != null) { - for (int m = 0; m < returnLst.getLength(); m++) { - Element returnElement = (Element)returnLst.item(m); - if (returnElement.getAttribute("list").equals("true")) { - this.list = true; - NodeList elementLst = returnElement.getElementsByTagName("element"); - this.listId = (Element)elementLst.item(0); - NodeList elementName = returnElement.getElementsByTagName("name"); - this.listName = (Element)elementName.item(0); - } else { - this.list = false; - } - - NodeList itemLst1 = returnElement.getElementsByTagName("item"); - if (itemLst1 != null) { - for (int n = 0; n < itemLst1.getLength(); n++) { - Node item = itemLst1.item(n); - if (item.getNodeType() == Node.ELEMENT_NODE) { - Element itemElement = (Element)item; - // get parameter name - NodeList itemName = itemElement.getElementsByTagName("name"); - Element itemNameElement = (Element)itemName.item(0); - - // Get parameters for future use - if (itemElement.getAttribute("setparam").equals("true")) { - NodeList itemVariable = itemElement.getElementsByTagName("param"); - Element itemVariableElement = (Element)itemVariable.item(0); - setParam.put(itemVariableElement.getTextContent(), itemNameElement.getTextContent()); - this.required = true; - } else if (itemElement.getAttribute("getparam").equals("true")) { - NodeList itemVariable = itemElement.getElementsByTagName("param"); - Element itemVariableElement = (Element)itemVariable.item(0); - this.verifyParam.put(itemNameElement.getTextContent(), param.get(itemVariableElement.getTextContent())); - } else if ((itemElement.getElementsByTagName("value") != null) && (itemElement.getElementsByTagName("value").getLength() != 0)) { - NodeList itemVariable = itemElement.getElementsByTagName("value"); - Element itemVariableElement = (Element)itemVariable.item(0); - this.verifyParam.put(itemNameElement.getTextContent(), itemVariableElement.getTextContent()); - } else { - this.verifyParam.put(itemNameElement.getTextContent(), "no value"); - } - } - } - } - } - } - } - - public int getResponseCode() { - return responseCode; - } - - // Send api command to the server - public void sendCommand(HttpClient client, Connection conn) { - if (TestCaseEngine.s_printUrl == true) { - s_logger.info("url is " + this.command); - } - - if (this.getCommandType() == CommandType.SCRIPT) { - try { - s_logger.info("Executing command " + this.command); - Runtime rtime = Runtime.getRuntime(); - Process child = rtime.exec(this.command); - Thread.sleep(10000); - int retCode = child.waitFor(); - if (retCode != 0) { - this.responseCode = retCode; - } else { - this.responseCode = 200; - } - - } catch (Exception ex) { - s_logger.error("Unable to execute a command " + this.command, ex); - } - } else if (this.getCommandType() == CommandType.MYSQL) { - try { - Statement stmt = conn.createStatement(); - this.result = stmt.executeQuery(this.command); - this.responseCode = 200; - } catch (Exception ex) { - this.responseCode = 400; - s_logger.error("Unable to execute mysql query " + this.command, ex); - } - } else { - HttpMethod method = new GetMethod(this.command); - try { - this.responseCode = client.executeMethod(method); - - if (this.responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(is); - doc.getDocumentElement().normalize(); - - if (!(this.isAsync)) { - this.responseBody = doc.getDocumentElement(); - } else { - // get async job result - Element jobTag = (Element)doc.getDocumentElement().getElementsByTagName("jobid").item(0); - String jobId = jobTag.getTextContent(); - Element responseBodyAsyncEl = queryAsyncJobResult(jobId); - if (responseBodyAsyncEl == null) { - s_logger.error("Can't get a async result"); - } else { - this.responseBody = responseBodyAsyncEl; - // get status of the job - Element jobStatusTag = (Element)responseBodyAsyncEl.getElementsByTagName("jobstatus").item(0); - String jobStatus = jobStatusTag.getTextContent(); - if (!jobStatus.equals("1")) { // Need to modify with different error codes for jobAsync -// results - // set fake response code by now - this.responseCode = 400; - } - } - } - } - - if (TestCaseEngine.s_printUrl == true) { - s_logger.info("Response code is " + this.responseCode); - } - } catch (Exception ex) { - s_logger.error("Command " + command + " failed with exception " + ex.getMessage()); - } finally { - method.releaseConnection(); - } - } - } - - // verify if response is empty (contains only root element) - public boolean isEmpty() { - boolean result = false; - if (!this.responseBody.hasChildNodes()) - result = true; - return result; - } - - // ================FOLLOWING METHODS USE RETURN XML FILE=======================// - - public boolean setParam(HashMap param) { - if ((this.responseBody == null) && (this.commandType == CommandType.HTTP)) { - s_logger.error("Response body is empty"); - return false; - } - Boolean result = true; - - if (this.getCommandType() == CommandType.MYSQL) { - Set set = this.setParam.entrySet(); - Iterator it = set.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - String itemName = null; - while (this.result.next()) { - itemName = this.result.getString(value); - } - if (itemName != null) { - param.put(key, itemName); - } else { - s_logger.error("Following return parameter is missing: " + value); - result = false; - } - } catch (Exception ex) { - s_logger.error("Unable to set parameter " + value, ex); - } - } - } else if (this.getCommandType() == CommandType.HTTP) { - if (this.list == false) { - Set set = this.setParam.entrySet(); - Iterator it = set.iterator(); - - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - // set parameters needed for the future use - NodeList itemName = this.responseBody.getElementsByTagName(value); - if ((itemName != null) && (itemName.getLength() != 0)) { - for (int i = 0; i < itemName.getLength(); i++) { - Element itemNameElement = (Element)itemName.item(i); - if (itemNameElement.getChildNodes().getLength() <= 1) { - param.put(key, itemNameElement.getTextContent()); - break; - } - } - } else { - s_logger.error("Following return parameter is missing: " + value); - result = false; - } - } - } else { - Set set = this.setParam.entrySet(); - Iterator it = set.iterator(); - NodeList returnLst = this.responseBody.getElementsByTagName(this.listName.getTextContent()); - Node requiredNode = returnLst.item(Integer.parseInt(this.listId.getTextContent())); - - if (requiredNode.getNodeType() == Node.ELEMENT_NODE) { - Element fstElmnt = (Element)requiredNode; - - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - NodeList itemName = fstElmnt.getElementsByTagName(value); - if ((itemName != null) && (itemName.getLength() != 0)) { - Element itemNameElement = (Element)itemName.item(0); - if (itemNameElement.getChildNodes().getLength() <= 1) { - param.put(key, itemNameElement.getTextContent()); - } - } else { - s_logger.error("Following return parameter is missing: " + value); - result = false; - } - } - } - } - } - return result; - } - - public String getUrl() { - return command; - } - - public boolean verifyParam() { - boolean result = true; - if (this.getCommandType() == CommandType.HTTP) { - if (this.list == false) { - Set set = verifyParam.entrySet(); - Iterator it = set.iterator(); - - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - if (value == null) { - s_logger.error("Parameter " + key + " is missing in the list of global parameters"); - return false; - } - - NodeList itemName = this.responseBody.getElementsByTagName(key); - if ((itemName.getLength() != 0) && (itemName != null)) { - Element itemNameElement = (Element)itemName.item(0); - if (itemNameElement.hasChildNodes()) { - continue; - } - if (!(verifyParam.get(key).equals("no value")) && !(itemNameElement.getTextContent().equals(verifyParam.get(key)))) { - s_logger.error("Incorrect value for the following tag: " + key + ". Expected value is " + verifyParam.get(key) + " while actual value is " + - itemNameElement.getTextContent()); - result = false; - } - } else { - s_logger.error("Following xml element is missing in the response: " + key); - result = false; - } - } - } - // for multiple elements - else { - Set set = verifyParam.entrySet(); - Iterator it = set.iterator(); - // get list element specified by id - NodeList returnLst = this.responseBody.getElementsByTagName(this.listName.getTextContent()); - Node requiredNode = returnLst.item(Integer.parseInt(this.listId.getTextContent())); - - if (requiredNode.getNodeType() == Node.ELEMENT_NODE) { - Element fstElmnt = (Element)requiredNode; - - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - if (value == null) { - s_logger.error("Parameter " + key + " is missing in the list of global parameters"); - return false; - } - NodeList itemName = fstElmnt.getElementsByTagName(key); - if ((itemName.getLength() != 0) && (itemName != null)) { - Element itemNameElement = (Element)itemName.item(0); - if (!(verifyParam.get(key).equals("no value")) && !(itemNameElement.getTextContent().equals(verifyParam.get(key)))) { - s_logger.error("Incorrect value for the following tag: " + key + ". Expected value is " + verifyParam.get(key) + - " while actual value is " + itemNameElement.getTextContent()); - result = false; - } - } else { - s_logger.error("Following xml element is missing in the response: " + key); - result = false; - } - } - } - } - } else if (this.getCommandType() == CommandType.MYSQL) { - Set set = verifyParam.entrySet(); - Iterator it = set.iterator(); - - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - if (value == null) { - s_logger.error("Parameter " + key + " is missing in the list of global parameters"); - return false; - } - - String itemName = null; - try { - while (this.result.next()) { - itemName = this.result.getString(key); - } - } catch (Exception ex) { - s_logger.error("Unable to get element from result set " + key); - } - - if (!(value.equals("no value")) && !(itemName.equals(verifyParam.get(key)))) { - s_logger.error("Incorrect value for the following tag: " + key + ". Expected value is " + verifyParam.get(key) + " while actual value is " + itemName); - result = false; - } - } - } - return result; - } - - public static boolean verifyEvents(String fileName, String level, String host, String account) { - boolean result = false; - HashMap expectedEvents = new HashMap(); - HashMap actualEvents = new HashMap(); - String key = ""; - - File file = new File(fileName); - if (file.exists()) { - Properties pro = new Properties(); - try { - // get expected events - FileInputStream in = new FileInputStream(file); - pro.load(in); - Enumeration en = pro.propertyNames(); - while (en.hasMoreElements()) { - key = (String)en.nextElement(); - expectedEvents.put(key, Integer.parseInt(pro.getProperty(key))); - } - - // get actual events - String url = host + "/?command=listEvents&account=" + account + "&level=" + level + "&domainid=1&pagesize=100"; - s_logger.info("Getting events with the following url " + url); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - ArrayList> eventValues = UtilsForTest.parseMulXML(is, new String[] {"event"}); - - for (int i = 0; i < eventValues.size(); i++) { - HashMap element = eventValues.get(i); - if (element.get("level").equals(level)) { - if (actualEvents.containsKey(element.get("type")) == true) { - actualEvents.put(element.get("type"), actualEvents.get(element.get("type")) + 1); - } else { - actualEvents.put(element.get("type"), 1); - } - } - } - } - method.releaseConnection(); - - // compare actual events with expected events - - // compare expected result and actual result - Iterator iterator = expectedEvents.keySet().iterator(); - Integer expected; - Integer actual; - int fail = 0; - while (iterator.hasNext()) { - expected = null; - actual = null; - String type = iterator.next().toString(); - expected = expectedEvents.get(type); - actual = actualEvents.get(type); - if (actual == null) { - s_logger.error("Event of type " + type + " and level " + level + " is missing in the listEvents response. Expected number of these events is " + - expected); - fail++; - } else if (expected.compareTo(actual) != 0) { - fail++; - s_logger.info("Amount of events of " + type + " type and level " + level + " is incorrect. Expected number of these events is " + expected + - ", actual number is " + actual); - } - } - if (fail == 0) { - result = true; - } - } catch (Exception ex) { - s_logger.error(ex); - } - } else { - s_logger.info("File " + fileName + " not found"); - } - return result; - } - - public static boolean verifyEvents(HashMap expectedEvents, String level, String host, String parameters) { - boolean result = false; - HashMap actualEvents = new HashMap(); - try { - // get actual events - String url = host + "/?command=listEvents&" + parameters; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - ArrayList> eventValues = UtilsForTest.parseMulXML(is, new String[] {"event"}); - - for (int i = 0; i < eventValues.size(); i++) { - HashMap element = eventValues.get(i); - if (element.get("level").equals(level)) { - if (actualEvents.containsKey(element.get("type")) == true) { - actualEvents.put(element.get("type"), actualEvents.get(element.get("type")) + 1); - } else { - actualEvents.put(element.get("type"), 1); - } - } - } - } - method.releaseConnection(); - } catch (Exception ex) { - s_logger.error(ex); - } - - // compare actual events with expected events - Iterator iterator = expectedEvents.keySet().iterator(); - Integer expected; - Integer actual; - int fail = 0; - while (iterator.hasNext()) { - expected = null; - actual = null; - String type = iterator.next().toString(); - expected = expectedEvents.get(type); - actual = actualEvents.get(type); - if (actual == null) { - s_logger.error("Event of type " + type + " and level " + level + " is missing in the listEvents response. Expected number of these events is " + expected); - fail++; - } else if (expected.compareTo(actual) != 0) { - fail++; - s_logger.info("Amount of events of " + type + " type and level " + level + " is incorrect. Expected number of these events is " + expected + - ", actual number is " + actual); - } - } - - if (fail == 0) { - result = true; - } - - return result; - } - - public Element queryAsyncJobResult(String jobId) { - Element returnBody = null; - int code = 400; - String resultUrl = this.host + ":8096/?command=queryAsyncJobResult&jobid=" + jobId; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(resultUrl); - while (true) { - try { - code = client.executeMethod(method); - if (code == 200) { - InputStream is = method.getResponseBodyAsStream(); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(is); - doc.getDocumentElement().normalize(); - returnBody = doc.getDocumentElement(); - Element jobStatusTag = (Element)returnBody.getElementsByTagName("jobstatus").item(0); - String jobStatus = jobStatusTag.getTextContent(); - if (jobStatus.equals("0")) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - s_logger.debug("[ignored] interrupted while during async job result query."); - } - } else { - break; - } - method.releaseConnection(); - } else { - s_logger.error("Error during queryJobAsync. Error code is " + code); - this.responseCode = code; - return null; - } - } catch (Exception ex) { - s_logger.error(ex); - } - } - return returnBody; - } - - private String getElementByName(String elementName) { - NodeList commandName = this.xmlCommand.getElementsByTagName(elementName); - if (commandName.getLength() != 0) { - Element commandElmnt = (Element)commandName.item(0); - NodeList commandNm = commandElmnt.getChildNodes(); - return commandNm.item(0).getNodeValue(); - } else { - return null; - } - } - - private boolean verifyTagValue(String elementName, String expectedValue) { - NodeList tag = this.xmlCommand.getElementsByTagName(elementName); - if (tag.getLength() != 0) { - Element commandElmnt = (Element)tag.item(0); - NodeList commandNm = commandElmnt.getChildNodes(); - if (commandNm.item(0).getNodeValue().equals(expectedValue)) { - return true; - } else { - return false; - } - } else { - return false; - } - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/ConfigTest.java b/test/src-not-used/main/java/com/cloud/test/regression/ConfigTest.java deleted file mode 100644 index 8d5c3587a54..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/ConfigTest.java +++ /dev/null @@ -1,125 +0,0 @@ -// 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. -package com.cloud.test.regression; - -import java.util.HashMap; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.Session; - -import com.cloud.test.regression.ApiCommand.ResponseType; - -public class ConfigTest extends TestCase { - public static final Logger s_logger = Logger.getLogger(ConfigTest.class.getName()); - - public ConfigTest() { - this.setClient(); - this.setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - if (api.getName().equals("rebootManagementServer")) { - - s_logger.info("Attempting to SSH into management server " + this.getParam().get("hostip")); - try { - Connection conn = new Connection(this.getParam().get("hostip")); - conn.connect(null, 60000, 60000); - - s_logger.info("SSHed successfully into management server " + this.getParam().get("hostip")); - - boolean isAuthenticated = conn.authenticateWithPassword("root", "password"); - - if (isAuthenticated == false) { - s_logger.info("Authentication failed for root with password"); - return false; - } - - String restartCommand = "service cloud-management restart; service cloud-usage restart"; - Session sess = conn.openSession(); - s_logger.info("Executing : " + restartCommand); - sess.execCommand(restartCommand); - Thread.sleep(120000); - sess.close(); - conn.close(); - - } catch (Exception ex) { - s_logger.error(ex); - return false; - } - } else { - //send a command - api.sendCommand(this.getClient(), null); - - //verify the response of the command - if ((api.getResponseType() == ResponseType.ERROR) && (api.getResponseCode() == 200) && (api.getTestCaseInfo() != null)) { - s_logger.error("Test case " + api.getTestCaseInfo() + - "failed. Command that was supposed to fail, passed. The command was sent with the following url " + api.getUrl()); - error++; - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() == 200)) { - //set parameters for the future use - if (api.setParam(this.getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + - " didn't return parameters needed for the future use. The command was sent with url " + api.getUrl()); - return false; - } else { - //verify parameters - if (api.verifyParam() == false) { - s_logger.error("Command " + api.getName() + " failed. Verification for returned parameters failed. Command was sent with url " + api.getUrl()); - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed. Command was sent with the url " + api.getUrl()); - } - } - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { - s_logger.error("Command " + api.getName() + " failed with an error code " + api.getResponseCode() + " . Command was sent with url " + api.getUrl() + - " Required: " + api.getRequired()); - if (api.getRequired() == true) { - s_logger.info("The command is required for the future use, so exiging"); - return false; - } - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed. Command that was supposed to fail, failed - test passed. Command was sent with url " + - api.getUrl()); - } - } - } - if (error != 0) - return false; - else - return true; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/DelegatedAdminTest.java b/test/src-not-used/main/java/com/cloud/test/regression/DelegatedAdminTest.java deleted file mode 100644 index cad22db07e2..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/DelegatedAdminTest.java +++ /dev/null @@ -1,129 +0,0 @@ -// 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. -package com.cloud.test.regression; - -import java.util.HashMap; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.cloud.test.regression.ApiCommand.ResponseType; - -public class DelegatedAdminTest extends TestCase { - - public static final Logger s_logger = Logger.getLogger(DelegatedAdminTest.class.getName()); - - public DelegatedAdminTest() { - this.setClient(); - this.setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - int error = 0; - - for (Document eachElement : this.getInputFile()) { - - Element rootElement = eachElement.getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - boolean verify = false; - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - if ((eachElement.getElementsByTagName("delegated_admin_verify_part2").getLength() != 0) && !(api.getName().equals("registerUserKeys"))) { - if (api.getName().startsWith("list")) { - - if (this.denyToExecute()) { - api.setResponseType(ResponseType.EMPTY); - } - verify = true; - } - - if (this.denyToExecute()) { - api.setResponseType(ResponseType.ERROR); - } - } - - //send a command - api.sendCommand(this.getClient(), null); - - //verify the response of the command - if ((verify == true) && !(api.getResponseType() == ResponseType.ERROR || api.getResponseType() == ResponseType.EMPTY)) { - s_logger.error("Test case " + api.getTestCaseInfo() + - " failed. Command that was supposed to fail, passed. The command was sent with the following url " + api.getUrl()); - error++; - } else if ((verify == true) && (api.getResponseType() == ResponseType.ERROR || api.getResponseType() == ResponseType.EMPTY)) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - } else if ((api.getResponseType() == ResponseType.ERROR) && (api.getResponseCode() == 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + - " failed. Command that was supposed to fail, passed. The command was sent with the following url " + api.getUrl()); - error++; - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() == 200)) { - //set parameters for the future use - if (api.setParam(this.getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + - " didn't return parameters needed for the future use. The command was sent with url " + api.getUrl()); - return false; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - } - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed with an error code " + api.getResponseCode() + " . Command was sent with url " + - api.getUrl()); - if (api.getRequired() == true) { - s_logger.info("The command is required for the future use, so exiging"); - return false; - } - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - - } - } - } - - if (error != 0) - return false; - else - return true; - } - - public boolean denyToExecute() { - boolean result = true; - Integer level1 = Integer.valueOf(this.getParam().get("domainlevel1")); - Integer level2 = Integer.valueOf(this.getParam().get("domainlevel2")); - String domain1 = this.getParam().get("domainname1"); - String domain2 = this.getParam().get("domainname2"); - - if (this.getParam().get("accounttype2").equals("1")) { - result = false; - } else if ((level2.compareTo(level1) < 0) && (domain1.startsWith(domain2)) && (this.getParam().get("accounttype2").equals("2"))) { - result = false; - } - - return result; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/Deploy.java b/test/src-not-used/main/java/com/cloud/test/regression/Deploy.java deleted file mode 100644 index 716e6277bec..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/Deploy.java +++ /dev/null @@ -1,109 +0,0 @@ -// 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. -package com.cloud.test.regression; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -public class Deploy extends TestCase { - public static final Logger s_logger = Logger.getLogger(Deploy.class.getName()); - - public Deploy() { - this.setClient(); - this.setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - //send a command - api.sendCommand(this.getClient(), null); - - //verify the response of the command - if (api.getResponseCode() != 200) { - error++; - s_logger.error("The command " + api.getUrl() + " failed"); - } else { - s_logger.info("The command " + api.getUrl() + " passsed"); - } - } - if (error != 0) - return false; - else - return true; - } - - public static void main(String[] args) { - - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - String host = null; - String file = null; - - while (iter.hasNext()) { - String arg = iter.next(); - // management server host - if (arg.equals("-h")) { - host = iter.next(); - } - if (arg.equals("-f")) { - file = iter.next(); - } - } - - Deploy deploy = new Deploy(); - - ArrayList inputFile = new ArrayList(); - inputFile.add(file); - deploy.setInputFile(inputFile); - deploy.setTestCaseName("Management server deployment"); - deploy.getParam().put("hostip", host); - deploy.getParam().put("apicommands", "../metadata/func/commands"); - deploy.setCommands(); - - s_logger.info("Starting deployment against host " + host); - - boolean result = deploy.executeTest(); - if (result == false) { - s_logger.error("DEPLOYMENT FAILED"); - System.exit(1); - } else { - s_logger.info("DEPLOYMENT IS SUCCESSFUL"); - } - - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/EventsApiTest.java b/test/src-not-used/main/java/com/cloud/test/regression/EventsApiTest.java deleted file mode 100644 index 6d724c02587..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/EventsApiTest.java +++ /dev/null @@ -1,176 +0,0 @@ -// 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. -package com.cloud.test.regression; - -import java.sql.Statement; -import java.util.HashMap; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.Session; - -import com.cloud.test.regression.ApiCommand.ResponseType; - -public class EventsApiTest extends TestCase { - public static final Logger s_logger = Logger.getLogger(EventsApiTest.class.getName()); - - public EventsApiTest() { - this.setClient(); - this.setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //!!!check if we need to execute mySql command - NodeList commandName = fstElmnt.getElementsByTagName("name"); - Element commandElmnt = (Element)commandName.item(0); - NodeList commandNm = commandElmnt.getChildNodes(); - if (commandNm.item(0).getNodeValue().equals("mysqlupdate")) { - //establish connection to mysql server and execute an update command - NodeList mysqlList = fstElmnt.getElementsByTagName("mysqlcommand"); - for (int j = 0; j < mysqlList.getLength(); j++) { - Element itemVariableElement = (Element)mysqlList.item(j); - - s_logger.info("Executing mysql command " + itemVariableElement.getTextContent()); - try { - Statement st = this.getConn().createStatement(); - st.executeUpdate(itemVariableElement.getTextContent()); - } catch (Exception ex) { - s_logger.error(ex); - return false; - } - } - } - - else if (commandNm.item(0).getNodeValue().equals("agentcommand")) { - //connect to all the agents and execute agent command - NodeList commandList = fstElmnt.getElementsByTagName("commandname"); - Element commandElement = (Element)commandList.item(0); - NodeList ipList = fstElmnt.getElementsByTagName("ip"); - for (int j = 0; j < ipList.getLength(); j++) { - Element itemVariableElement = (Element)ipList.item(j); - - s_logger.info("Attempting to SSH into agent " + itemVariableElement.getTextContent()); - try { - Connection conn = new Connection(itemVariableElement.getTextContent()); - conn.connect(null, 60000, 60000); - - s_logger.info("SSHed successfully into agent " + itemVariableElement.getTextContent()); - - boolean isAuthenticated = conn.authenticateWithPassword("root", "password"); - - if (isAuthenticated == false) { - s_logger.info("Authentication failed for root with password"); - return false; - } - - Session sess = conn.openSession(); - s_logger.info("Executing : " + commandElement.getTextContent()); - sess.execCommand(commandElement.getTextContent()); - Thread.sleep(60000); - sess.close(); - conn.close(); - - } catch (Exception ex) { - s_logger.error(ex); - return false; - } - } - } - - else { - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - //send a command - api.sendCommand(this.getClient(), null); - - //verify the response of the command - if ((api.getResponseType() == ResponseType.ERROR) && (api.getResponseCode() == 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + - " failed. Command that was supposed to fail, passed. The command was sent with the following url " + api.getUrl()); - error++; - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() == 200)) { - //verify if response is suppposed to be empty - if (api.getResponseType() == ResponseType.EMPTY) { - if (api.isEmpty() == true) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed. Empty response was returned as expected. Command was sent with url " + - api.getUrl()); - } else { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Empty response was expected. Command was sent with url " + api.getUrl()); - } - } else { - if (api.isEmpty() != false) - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Non-empty response was expected. Command was sent with url " + api.getUrl()); - else { - //set parameters for the future use - if (api.setParam(this.getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + - " didn't return parameters needed for the future use. The command was sent with url " + api.getUrl()); - return false; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed. Command was sent with the url " + api.getUrl()); - } - } - } - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { - s_logger.error("Command " + api.getName() + " failed with an error code " + api.getResponseCode() + " . Command was sent with url " + api.getUrl()); - if (api.getRequired() == true) { - s_logger.info("The command is required for the future use, so exiging"); - return false; - } - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed. Command that was supposed to fail, failed. Command was sent with url " + api.getUrl()); - - } - } - } - - //verify events with userid parameter - test case 97 - HashMap expectedEvents = new HashMap(); - expectedEvents.put("VM.START", 1); - boolean eventResult = - ApiCommand.verifyEvents(expectedEvents, "INFO", "http://" + this.getParam().get("hostip") + ":8096", "userid=" + this.getParam().get("userid1") + - "&type=VM.START"); - s_logger.info("Test case 97 - listEvent command verification result is " + eventResult); - - //verify error events - eventResult = - ApiCommand.verifyEvents("../metadata/error_events.properties", "ERROR", "http://" + this.getParam().get("hostip") + ":8096", - this.getParam().get("erroruseraccount")); - s_logger.info("listEvent command verification result is " + eventResult); - - if (error != 0) - return false; - else - return true; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/HA.java b/test/src-not-used/main/java/com/cloud/test/regression/HA.java deleted file mode 100644 index 0a17a5b7582..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/HA.java +++ /dev/null @@ -1,80 +0,0 @@ -// 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. -package com.cloud.test.regression; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.cloud.test.regression.ApiCommand.ResponseType; - -public class HA extends TestCase { - - public static final Logger s_logger = Logger.getLogger(HA.class.getName()); - - public HA() { - this.setClient(); - } - - @Override - public boolean executeTest() { - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - //send a command - api.sendCommand(this.getClient(), this.getConn()); - - //verify the response parameters - if ((api.getResponseCode() != 200) && (api.getRequired() == true)) { - s_logger.error("Exiting the test....Command " + api.getName() + " required for the future run, failed with an error code " + api.getResponseCode() + - ". Command was sent with the url " + api.getUrl()); - return false; - } else if ((api.getResponseCode() != 200) && (api.getResponseType() != ResponseType.ERROR)) { - error++; - s_logger.error("Command " + api.getTestCaseInfo() + " failed with an error code " + api.getResponseCode() + " . Command was sent with url " + - api.getUrl()); - } else if ((api.getResponseCode() == 200) && (api.getResponseType() == ResponseType.ERROR)) { - error++; - s_logger.error("Command " + api.getTestCaseInfo() + " which was supposed to failed, passed. The command was sent with url " + api.getUrl()); - } else { - //set parameters for the future use - if (api.setParam(this.getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + " didn't return parameters needed for the future use. Command was sent with url " + - api.getUrl()); - return false; - } - s_logger.info("Command " + api.getTestCaseInfo() + " passed"); - } - } - - if (error != 0) - return false; - else - return true; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/LoadBalancingTest.java b/test/src-not-used/main/java/com/cloud/test/regression/LoadBalancingTest.java deleted file mode 100644 index cdbc5364137..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/LoadBalancingTest.java +++ /dev/null @@ -1,142 +0,0 @@ -// 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. -package com.cloud.test.regression; - -import java.util.HashMap; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.cloud.test.regression.ApiCommand.ResponseType; - -public class LoadBalancingTest extends TestCase { - - public static final Logger s_logger = Logger.getLogger(LoadBalancingTest.class.getName()); - - public LoadBalancingTest() { - this.setClient(); - this.setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - //send a command - api.sendCommand(this.getClient(), null); - - //verify the response of the command - if ((api.getResponseType() == ResponseType.ERROR) && (api.getResponseCode() == 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Command that was supposed to fail, passed. The command was sent with the following url " + - api.getUrl()); - error++; - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() == 200)) { - //verify if response is suppposed to be empty - if (api.getResponseType() == ResponseType.EMPTY) { - if (api.isEmpty() == true) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - } else { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Empty response was expected. Command was sent with url " + api.getUrl()); - } - } else { - if (api.isEmpty() != false) - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Non-empty response was expected. Command was sent with url " + api.getUrl()); - else { - //set parameters for the future use - if (api.setParam(this.getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + - " didn't return parameters needed for the future use. The command was sent with url " + api.getUrl()); - return false; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - } - } - } - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Command was sent with url " + api.getUrl()); - if (api.getRequired() == true) { - s_logger.info("The command is required for the future use, so exiging"); - return false; - } - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - - } - } - -// //Try to create portForwarding rule for all available private/public ports -// ArrayList port = new ArrayList(); -// for (int i=1; i<65536; i++){ -// port.add(Integer.toString(i)); -// } -// -// //try all public ports -// for (String portValue : port) { -// try { -// String url = this.getHost() + ":8096/?command=createOrUpdateLoadBalancerRule&account=" + this.getParam().get("accountname") + "&publicip=" + this.getParam().get("boundaryip") + -// "&privateip=" + this.getParam().get("vmipaddress") + "&privateport=22&protocol=tcp&publicport=" + portValue; -// HttpClient client = new HttpClient(); -// HttpMethod method = new GetMethod(url); -// int responseCode = client.executeMethod(method); -// if (responseCode != 200 ) { -// error++; -// s_logger.error("Can't create LB rule for the public port " + portValue + ". Request was sent with url " + url); -// } -// }catch (Exception ex) { -// s_logger.error(ex); -// } -// } -// -// //try all private ports -// for (String portValue : port) { -// try { -// String url = this.getHost() + ":8096/?command=createOrUpdateLoadBalancerRule&account=" + this.getParam().get("accountname") + "&publicip=" + this.getParam().get("boundaryip") + -// "&privateip=" + this.getParam().get("vmipaddress") + "&publicport=22&protocol=tcp&privateport=" + portValue; -// HttpClient client = new HttpClient(); -// HttpMethod method = new GetMethod(url); -// int responseCode = client.executeMethod(method); -// if (responseCode != 200 ) { -// error++; -// s_logger.error("Can't create LB rule for the private port " + portValue + ". Request was sent with url " + url); -// } -// }catch (Exception ex) { -// s_logger.error(ex); -// } -// } - - if (error != 0) - return false; - else - return true; - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/PortForwardingTest.java b/test/src-not-used/main/java/com/cloud/test/regression/PortForwardingTest.java deleted file mode 100644 index 24415fdc69a..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/PortForwardingTest.java +++ /dev/null @@ -1,143 +0,0 @@ -// 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. -package com.cloud.test.regression; - -import java.util.HashMap; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.cloud.test.regression.ApiCommand.ResponseType; - -public class PortForwardingTest extends TestCase { - public static final Logger s_logger = Logger.getLogger(PortForwardingTest.class.getName()); - - public PortForwardingTest() { - setClient(); - setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - - int error = 0; - Element rootElement = getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, getParam(), getCommands()); - - //send a command - api.sendCommand(getClient(), null); - - //verify the response of the command - if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() == 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Command that was supposed to fail, passed. The command was sent with the following url " + - api.getUrl()); - error++; - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() == 200)) { - //verify if response is suppposed to be empty - if (api.getResponseType() == ResponseType.EMPTY) { - if (api.isEmpty() == true) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - } else { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Empty response was expected. Command was sent with url " + api.getUrl()); - } - } else { - if (api.isEmpty() != false) - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Non-empty response was expected. Command was sent with url " + api.getUrl()); - else { - //set parameters for the future use - if (api.setParam(getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + - " didn't return parameters needed for the future use. The command was sent with url " + api.getUrl()); - return false; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - } - } - } - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed . Command was sent with url " + api.getUrl()); - if (api.getRequired() == true) { - s_logger.info("The command is required for the future use, so exiging"); - return false; - } - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - - } - } - -// //Try to create portForwarding rule for all available private/public ports -// ArrayList port = new ArrayList(); -// for (int i=1; i<65536; i++){ -// port.add(Integer.toString(i)); -// } -// -// //try all public ports -// for (String portValue : port) { -// try { -// s_logger.info("public port is " + portValue); -// String url = this.getHost() + ":8096/?command=createOrUpdateIpForwardingRule&account=" + this.getParam().get("accountname") + "&publicip=" + this.getParam().get("boundaryip") + -// "&privateip=" + this.getParam().get("vmipaddress") + "&privateport=22&protocol=tcp&publicport=" + portValue; -// HttpClient client = new HttpClient(); -// HttpMethod method = new GetMethod(url); -// int responseCode = client.executeMethod(method); -// if (responseCode != 200 ) { -// error++; -// s_logger.error("Can't create portForwarding rule for the public port " + portValue + ". Request was sent with url " + url); -// } -// }catch (Exception ex) { -// s_logger.error(ex); -// } -// } -// -// //try all private ports -// for (String portValue : port) { -// try { -// String url = this.getHost() + ":8096/?command=createOrUpdateIpForwardingRule&account=" + -// this.getParam().get("accountname") + "&publicip=" + this.getParam().get("boundaryip") + -// "&privateip=" + this.getParam().get("vmipaddress") + "&publicport=22&protocol=tcp&privateport=" + portValue; -// HttpClient client = new HttpClient(); -// HttpMethod method = new GetMethod(url); -// int responseCode = client.executeMethod(method); -// if (responseCode != 200 ) { -// error++; -// s_logger.error("Can't create portForwarding rule for the private port " + portValue + ". Request was sent with url " + url); -// } -// }catch (Exception ex) { -// s_logger.error(ex); -// } -// } - - if (error != 0) - return false; - else - return true; - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/SanityTest.java b/test/src-not-used/main/java/com/cloud/test/regression/SanityTest.java deleted file mode 100644 index defb232b5af..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/SanityTest.java +++ /dev/null @@ -1,86 +0,0 @@ -// 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. -package com.cloud.test.regression; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -public class SanityTest extends TestCase { - - public static final Logger s_logger = Logger.getLogger(SanityTest.class.getName()); - - public SanityTest() { - this.setClient(); - } - - @Override - public boolean executeTest() { - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - api.sendCommand(this.getClient(), null); - - //verify the response parameters - if ((api.getResponseCode() != 200) && (api.getRequired() == true)) { - s_logger.error("Exiting the test....Command " + api.getName() + " required for the future run, failed with an error code " + api.getResponseCode() + - ". Command was sent with the url " + api.getUrl()); - return false; - } else if (api.getResponseCode() != 200) { - error++; - s_logger.error("Test " + api.getTestCaseInfo() + " failed with an error code " + api.getResponseCode() + " . Command was sent with url " + api.getUrl()); - } else { - //set parameters for the future use - if (api.setParam(this.getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + " didn't return parameters needed for the future use. Command was sent with url " + - api.getUrl()); - return false; - } - - //verify parameters - if (api.verifyParam() == false) { - s_logger.error("Test " + api.getTestCaseInfo() + " failed. Verification for returned parameters failed. The command was sent with url " + - api.getUrl()); - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test " + api.getTestCaseInfo() + " passed"); - } - } - } - - //verify event - boolean eventResult = - ApiCommand.verifyEvents("../metadata/func/regression_events.properties", "INFO", "http://" + this.getParam().get("hostip") + ":8096", - this.getParam().get("accountname")); - s_logger.info("listEvent command verification result is " + eventResult); - - if (error != 0) - return false; - else - return true; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/Test.java b/test/src-not-used/main/java/com/cloud/test/regression/Test.java deleted file mode 100644 index 5c6b336de9d..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/Test.java +++ /dev/null @@ -1,88 +0,0 @@ -// 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. -package com.cloud.test.regression; - -import java.util.ArrayList; -import java.util.HashMap; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -public class Test extends TestCase { - public static final Logger s_logger = Logger.getLogger(Test.class.getName()); - - public Test() { - this.setClient(); - this.setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - //send a command - api.sendCommand(this.getClient(), null); - - } - - //Try to create portForwarding rule for all available private/public ports - ArrayList port = new ArrayList(); - for (int j = 1; j < 1000; j++) { - port.add(Integer.toString(j)); - } - - //try all public ports - for (String portValue : port) { - try { - s_logger.info("public port is " + portValue); - String url = - "http://" + this.getParam().get("hostip") + ":8096/?command=createNetworkRule&publicPort=" + portValue + - "&privatePort=22&protocol=tcp&isForward=true&securityGroupId=1&account=admin"; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - if (responseCode != 200) { - error++; - s_logger.error("Can't create portForwarding network rule for the public port " + portValue + ". Request was sent with url " + url); - } - } catch (Exception ex) { - s_logger.error(ex); - } - } - - if (error != 0) - return false; - else - return true; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/TestCase.java b/test/src-not-used/main/java/com/cloud/test/regression/TestCase.java deleted file mode 100644 index cb7395c07bf..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/TestCase.java +++ /dev/null @@ -1,138 +0,0 @@ -// 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. -package com.cloud.test.regression; - -import java.io.File; -import java.io.FileInputStream; -import java.sql.Connection; -import java.sql.DriverManager; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Properties; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.log4j.Logger; -import org.w3c.dom.Document; - -public abstract class TestCase { - - public static Logger s_logger = Logger.getLogger(TestCase.class.getName()); - private Connection conn; - private ArrayList inputFile = new ArrayList(); - private HttpClient client; - private String testCaseName; - private HashMap param = new HashMap(); - private HashMap commands = new HashMap(); - - public HashMap getParam() { - return param; - } - - public void setParam(HashMap param) { - this.param = param; - } - - public HashMap getCommands() { - return commands; - } - - public void setCommands() { - File asyncCommands = null; - if (param.get("apicommands") == null) { - s_logger.info("Unable to get the list of commands, exiting"); - System.exit(1); - } else { - asyncCommands = new File(param.get("apicommands")); - } - try { - Properties pro = new Properties(); - FileInputStream in = new FileInputStream(asyncCommands); - pro.load(in); - Enumeration en = pro.propertyNames(); - while (en.hasMoreElements()) { - String key = (String)en.nextElement(); - commands.put(key, pro.getProperty(key)); - } - } catch (Exception ex) { - s_logger.info("Unable to find the file " + param.get("apicommands") + " due to following exception " + ex); - } - - } - - public Connection getConn() { - return conn; - } - - public void setConn(String dbPassword) { - this.conn = null; - try { - Class.forName("com.mysql.jdbc.Driver"); - this.conn = DriverManager.getConnection("jdbc:mysql://" + param.get("db") + "/cloud", "root", dbPassword); - if (!this.conn.isValid(0)) { - s_logger.error("Connection to DB failed to establish"); - } - - } catch (Exception ex) { - s_logger.error(ex); - } - } - - public void setInputFile(ArrayList fileNameInput) { - for (String fileName : fileNameInput) { - File file = new File(fileName); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - Document doc = null; - try { - DocumentBuilder builder = factory.newDocumentBuilder(); - doc = builder.parse(file); - doc.getDocumentElement().normalize(); - } catch (Exception ex) { - s_logger.error("Unable to load " + fileName + " due to ", ex); - } - this.inputFile.add(doc); - } - } - - public ArrayList getInputFile() { - return inputFile; - } - - public void setTestCaseName(String testCaseName) { - this.testCaseName = testCaseName; - } - - public String getTestCaseName() { - return this.testCaseName; - } - - public void setClient() { - HttpClient client = new HttpClient(); - this.client = client; - } - - public HttpClient getClient() { - return this.client; - } - - //abstract methods - public abstract boolean executeTest(); - -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/TestCaseEngine.java b/test/src-not-used/main/java/com/cloud/test/regression/TestCaseEngine.java deleted file mode 100644 index 4207e1786f5..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/TestCaseEngine.java +++ /dev/null @@ -1,275 +0,0 @@ -// 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. -package com.cloud.test.regression; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.apache.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -public class TestCaseEngine { - - public static final Logger s_logger = Logger.getLogger(TestCaseEngine.class.getName()); - public static String s_fileName = "../metadata/adapter.xml"; - public static HashMap s_globalParameters = new HashMap(); - protected static HashMap s_componentMap = new HashMap(); - protected static HashMap> s_inputFile = new HashMap>(); - protected static String s_testCaseName = new String(); - protected static ArrayList s_keys = new ArrayList(); - private static ThreadLocal s_result = new ThreadLocal(); - public static int s_numThreads = 1; - public static boolean s_repeat = false; - public static boolean s_printUrl = false; - public static String s_type = "All"; - public static boolean s_isSanity = false; - public static boolean s_isRegression = false; - private static int s_failure = 0; - - public static void main(String args[]) { - - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - // is stress? - if (arg.equals("-t")) { - s_numThreads = Integer.parseInt(iter.next()); - } - // do you want to print url for all commands? - if (arg.equals("-p")) { - s_printUrl = true; - } - - //type of the test: sanity, regression, all (default) - if (arg.equals("-type")) { - s_type = iter.next(); - } - - if (arg.equals("-repeat")) { - s_repeat = Boolean.valueOf(iter.next()); - } - - if (arg.equals("-filename")) { - s_fileName = iter.next(); - } - } - - if (s_type.equalsIgnoreCase("sanity")) - s_isSanity = true; - else if (s_type.equalsIgnoreCase("regression")) - s_isRegression = true; - - try { - // parse adapter.xml file to get list of tests to execute - File file = new File(s_fileName); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(file); - doc.getDocumentElement().normalize(); - Element root = doc.getDocumentElement(); - - // set global parameters - setGlobalParams(root); - - // populate _componentMap - setComponent(root); - - // set error to 0 by default - - // execute test - for (int i = 0; i < s_numThreads; i++) { - if (s_numThreads > 1) { - s_logger.info("STARTING STRESS TEST IN " + s_numThreads + " THREADS"); - } else { - s_logger.info("STARTING FUNCTIONAL TEST"); - } - new Thread(new Runnable() { - @Override - public void run() { - do { - if (s_numThreads == 1) { - try { - for (String key : s_keys) { - Class c = Class.forName(s_componentMap.get(key)); - TestCase component = (TestCase)c.newInstance(); - executeTest(key, c, component); - } - } catch (Exception ex1) { - s_logger.error(ex1); - } finally { - if (s_failure > 0) { - System.exit(1); - } - } - } else { - Random ran = new Random(); - Integer randomNumber = Math.abs(ran.nextInt(s_keys.size())); - try { - String key = s_keys.get(randomNumber); - Class c = Class.forName(s_componentMap.get(key)); - TestCase component = (TestCase)c.newInstance(); - executeTest(key, c, component); - } catch (Exception e) { - s_logger.error("Error in thread ", e); - } - } - } while (s_repeat); - } - }).start(); - } - - } catch (Exception exc) { - s_logger.error(exc); - } - } - - public static void setGlobalParams(Element rootElement) { - NodeList globalParam = rootElement.getElementsByTagName("globalparam"); - Element parameter = (Element)globalParam.item(0); - NodeList paramLst = parameter.getElementsByTagName("param"); - - for (int i = 0; i < paramLst.getLength(); i++) { - Element paramElement = (Element)paramLst.item(i); - - if (paramElement.getNodeType() == Node.ELEMENT_NODE) { - Element itemElement = paramElement; - NodeList itemName = itemElement.getElementsByTagName("name"); - Element itemNameElement = (Element)itemName.item(0); - NodeList itemVariable = itemElement.getElementsByTagName("variable"); - Element itemVariableElement = (Element)itemVariable.item(0); - s_globalParameters.put(itemVariableElement.getTextContent(), itemNameElement.getTextContent()); - } - } - } - - public static void setComponent(Element rootElement) { - NodeList testLst = rootElement.getElementsByTagName("test"); - for (int j = 0; j < testLst.getLength(); j++) { - Element testElement = (Element)testLst.item(j); - - if (testElement.getNodeType() == Node.ELEMENT_NODE) { - Element itemElement = testElement; - - // get test case name - NodeList testCaseNameList = itemElement.getElementsByTagName("testname"); - if (testCaseNameList != null) { - s_testCaseName = ((Element)testCaseNameList.item(0)).getTextContent(); - } - - if (s_isSanity == true && !s_testCaseName.equals("SANITY TEST")) - continue; - else if (s_isRegression == true && !(s_testCaseName.equals("SANITY TEST") || s_testCaseName.equals("REGRESSION TEST"))) - continue; - - // set class name - NodeList className = itemElement.getElementsByTagName("class"); - if ((className.getLength() == 0) || (className == null)) { - s_componentMap.put(s_testCaseName, "com.cloud.test.regression.VMApiTest"); - } else { - String name = ((Element)className.item(0)).getTextContent(); - s_componentMap.put(s_testCaseName, name); - } - - // set input file name - NodeList inputFileNameLst = itemElement.getElementsByTagName("filename"); - s_inputFile.put(s_testCaseName, new ArrayList()); - for (int k = 0; k < inputFileNameLst.getLength(); k++) { - String inputFileName = ((Element)inputFileNameLst.item(k)).getTextContent(); - s_inputFile.get(s_testCaseName).add(inputFileName); - } - } - } - - //If sanity test required, make sure that SANITY TEST componennt got loaded - if (s_isSanity == true && s_componentMap.size() == 0) { - s_logger.error("FAILURE!!! Failed to load SANITY TEST component. Verify that the test is uncommented in adapter.xml"); - System.exit(1); - } - - if (s_isRegression == true && s_componentMap.size() != 2) { - s_logger.error("FAILURE!!! Failed to load SANITY TEST or REGRESSION TEST components. Verify that these tests are uncommented in adapter.xml"); - System.exit(1); - } - - // put all keys from _componentMap to the ArrayList - Set set = s_componentMap.entrySet(); - Iterator it = set.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - s_keys.add(key); - } - - } - - public static boolean executeTest(String key, Class c, TestCase component) { - boolean finalResult = false; - try { - s_logger.info("Starting \"" + key + "\" test...\n\n"); - - // set global parameters - HashMap updateParam = new HashMap(); - updateParam.putAll(s_globalParameters); - component.setParam(updateParam); - - // set DB ip address - component.setConn(s_globalParameters.get("dbPassword")); - - // set commands list - component.setCommands(); - - // set input file - if (s_inputFile.get(key) != null) { - component.setInputFile(s_inputFile.get(key)); - } - - // set test case name - if (key != null) { - component.setTestCaseName(s_testCaseName); - } - - // execute method - s_result.set(component.executeTest()); - if (s_result.get().toString().equals("false")) { - s_logger.error("FAILURE!!! Test \"" + key + "\" failed\n\n\n"); - s_failure++; - } else { - finalResult = true; - s_logger.info("SUCCESS!!! Test \"" + key + "\" passed\n\n\n"); - } - - } catch (Exception ex) { - s_logger.error("error during test execution ", ex); - } - return finalResult; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/regression/VMApiTest.java b/test/src-not-used/main/java/com/cloud/test/regression/VMApiTest.java deleted file mode 100644 index 28877c59705..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/regression/VMApiTest.java +++ /dev/null @@ -1,91 +0,0 @@ -// 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. -package com.cloud.test.regression; - -import java.util.HashMap; - -import org.apache.log4j.Logger; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.cloud.test.regression.ApiCommand.ResponseType; - -public class VMApiTest extends TestCase { - public static final Logger s_logger = Logger.getLogger(VMApiTest.class.getName()); - - public VMApiTest() { - this.setClient(); - this.setParam(new HashMap()); - } - - @Override - public boolean executeTest() { - int error = 0; - Element rootElement = this.getInputFile().get(0).getDocumentElement(); - NodeList commandLst = rootElement.getElementsByTagName("command"); - - //Analyze each command, send request and build the array list of api commands - for (int i = 0; i < commandLst.getLength(); i++) { - Node fstNode = commandLst.item(i); - Element fstElmnt = (Element)fstNode; - - //new command - ApiCommand api = new ApiCommand(fstElmnt, this.getParam(), this.getCommands()); - - //send a command - api.sendCommand(this.getClient(), this.getConn()); - - //verify the response of the command - if ((api.getResponseType() == ResponseType.ERROR) && (api.getResponseCode() == 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed. Command that was supposed to fail, passed. The command was sent with the following url " + - api.getUrl()); - error++; - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() == 200)) { - //set parameters for the future use - if (api.setParam(this.getParam()) == false) { - s_logger.error("Exiting the test...Command " + api.getName() + " didn't return parameters needed for the future use. The command was sent with url " + - api.getUrl()); - return false; - } - //verify parameters - if (api.verifyParam() == false) { - s_logger.error("Test " + api.getTestCaseInfo() + " failed. Verification for returned parameters failed. The command was sent with url " + - api.getUrl()); - error++; - } else { - s_logger.info("Test " + api.getTestCaseInfo() + " passed"); - } - } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { - s_logger.error("Test case " + api.getTestCaseInfo() + " failed with an error code " + api.getResponseCode() + " . Command was sent with url " + - api.getUrl()); - if (api.getRequired() == true) { - s_logger.info("The command is required for the future use, so exiging"); - return false; - } - error++; - } else if (api.getTestCaseInfo() != null) { - s_logger.info("Test case " + api.getTestCaseInfo() + " passed"); - - } - } - if (error != 0) - return false; - else - return true; - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/stress/SshTest.java b/test/src-not-used/main/java/com/cloud/test/stress/SshTest.java deleted file mode 100644 index a49dbadf1d5..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/stress/SshTest.java +++ /dev/null @@ -1,90 +0,0 @@ -// 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. -package com.cloud.test.stress; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -import org.apache.log4j.Logger; - -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.Session; - -public class SshTest { - - public static final Logger s_logger = Logger.getLogger(SshTest.class.getName()); - public static String host = ""; - public static String password = "password"; - public static String url = "http://google.com"; - - public static void main(String[] args) { - - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - if (arg.equals("-h")) { - host = iter.next(); - } - if (arg.equals("-p")) { - password = iter.next(); - } - - if (arg.equals("-u")) { - url = iter.next(); - } - } - - if (host == null || host.equals("")) { - s_logger.info("Did not receive a host back from test, ignoring ssh test"); - System.exit(2); - } - - if (password == null) { - s_logger.info("Did not receive a password back from test, ignoring ssh test"); - System.exit(2); - } - - try { - s_logger.info("Attempting to SSH into host " + host); - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("User + ssHed successfully into host " + host); - - boolean isAuthenticated = conn.authenticateWithPassword("root", password); - - if (isAuthenticated == false) { - s_logger.info("Authentication failed for root with password" + password); - System.exit(2); - } - - String linuxCommand = "wget " + url; - Session sess = conn.openSession(); - sess.execCommand(linuxCommand); - sess.close(); - conn.close(); - - } catch (Exception e) { - s_logger.error("SSH test fail with error", e); - System.exit(2); - } - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/stress/StressTestDirectAttach.java b/test/src-not-used/main/java/com/cloud/test/stress/StressTestDirectAttach.java deleted file mode 100644 index 5625830b238..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/stress/StressTestDirectAttach.java +++ /dev/null @@ -1,1353 +0,0 @@ -// 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. -package com.cloud.test.stress; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; -import java.net.URLEncoder; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpException; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.trilead.ssh2.ChannelCondition; -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.SCPClient; -import com.trilead.ssh2.Session; - -import com.cloud.utils.exception.CloudRuntimeException; - -public class StressTestDirectAttach { - private static long sleepTime = 180000L; // default 0 - private static boolean cleanUp = true; - public static final Logger s_logger = Logger.getLogger(StressTestDirectAttach.class.getName()); - private static boolean repeat = true; - private static String[] users = null; - private static boolean internet = false; - private static ThreadLocal s_linuxIP = new ThreadLocal(); - private static ThreadLocal s_linuxVmId = new ThreadLocal(); - private static ThreadLocal s_linuxVmId1 = new ThreadLocal(); - private static ThreadLocal s_linuxPassword = new ThreadLocal(); - private static ThreadLocal s_windowsIP = new ThreadLocal(); - private static ThreadLocal s_secretKey = new ThreadLocal(); - private static ThreadLocal s_apiKey = new ThreadLocal(); - private static ThreadLocal s_userId = new ThreadLocal(); - private static ThreadLocal s_account = new ThreadLocal(); - private static ThreadLocal s_domainRouterId = new ThreadLocal(); - private static ThreadLocal s_newVolume = new ThreadLocal(); - private static ThreadLocal s_newVolume1 = new ThreadLocal(); - private static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - private static int usageIterator = 1; - private static int numThreads = 1; - private static int wait = 5000; - private static String accountName = null; - private static String zoneId = "1"; - private static String serviceOfferingId = "13"; - private static String diskOfferingId = "11"; - private static String diskOfferingId1 = "12"; - - private static final int MAX_RETRY_LINUX = 10; - private static final int MAX_RETRY_WIN = 10; - - public static void main(String[] args) { - String host = "http://localhost"; - String port = "8092"; - String devPort = "8080"; - String apiUrl = "/client/api"; - - try { - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - // host - if (arg.equals("-h")) { - host = "http://" + iter.next(); - } - - if (arg.equals("-p")) { - port = iter.next(); - } - if (arg.equals("-dp")) { - devPort = iter.next(); - } - - if (arg.equals("-t")) { - numThreads = Integer.parseInt(iter.next()); - } - - if (arg.equals("-s")) { - sleepTime = Long.parseLong(iter.next()); - } - if (arg.equals("-a")) { - accountName = iter.next(); - } - - if (arg.equals("-c")) { - cleanUp = Boolean.parseBoolean(iter.next()); - if (!cleanUp) - sleepTime = 0L; // no need to wait if we don't ever - // cleanup - } - - if (arg.equals("-r")) { - repeat = Boolean.parseBoolean(iter.next()); - } - - if (arg.equals("-i")) { - internet = Boolean.parseBoolean(iter.next()); - } - - if (arg.equals("-w")) { - wait = Integer.parseInt(iter.next()); - } - - if (arg.equals("-z")) { - zoneId = iter.next(); - } - - if (arg.equals("-so")) { - serviceOfferingId = iter.next(); - } - - } - - final String server = host + ":" + port + "/"; - final String developerServer = host + ":" + devPort + apiUrl; - s_logger.info("Starting test against server: " + server + " with " + numThreads + " thread(s)"); - if (cleanUp) - s_logger.info("Clean up is enabled, each test will wait " + sleepTime + " ms before cleaning up"); - - for (int i = 0; i < numThreads; i++) { - new Thread(new Runnable() { - @Override - public void run() { - do { - String username = null; - try { - long now = System.currentTimeMillis(); - Random ran = new Random(); - username = Math.abs(ran.nextInt()) + "-user"; - NDC.push(username); - - s_logger.info("Starting test for the user " + username); - int response = executeDeployment(server, developerServer, username); - boolean success = false; - String reason = null; - - if (response == 200) { - success = true; - if (internet) { - s_logger.info("Deploy successful...waiting 5 minute before SSH tests"); - Thread.sleep(300000L); // Wait 60 - // seconds so - // the windows VM - // can boot up and do a sys prep. - - s_logger.info("Begin Linux SSH test for account " + s_account.get()); - reason = sshTest(s_linuxIP.get(), s_linuxPassword.get()); - - if (reason == null) { - s_logger.info("Linux SSH test successful for account " + s_account.get()); - } - } - if (reason == null) { - if (internet) { - s_logger.info("Windows SSH test successful for account " + s_account.get()); - } else { - s_logger.info("deploy test successful....now cleaning up"); - if (cleanUp) { - s_logger.info("Waiting " + sleepTime + " ms before cleaning up vms"); - Thread.sleep(sleepTime); - } else { - success = true; - } - } - - if (usageIterator >= numThreads) { - int eventsAndBillingResponseCode = executeEventsAndBilling(server, developerServer); - s_logger.info("events and usage records command finished with response code: " + eventsAndBillingResponseCode); - usageIterator = 1; - - } else { - s_logger.info("Skipping events and usage records for this user: usageIterator " + usageIterator + " and number of Threads " + - numThreads); - usageIterator++; - } - - if ((users == null) && (accountName == null)) { - s_logger.info("Sending cleanup command"); - int cleanupResponseCode = executeCleanup(server, developerServer, username); - s_logger.info("cleanup command finished with response code: " + cleanupResponseCode); - success = (cleanupResponseCode == 200); - } else { - s_logger.info("Sending stop DomR / destroy VM command"); - int stopResponseCode = executeStop(server, developerServer, username); - s_logger.info("stop(destroy) command finished with response code: " + stopResponseCode); - success = (stopResponseCode == 200); - } - - } else { - // Just stop but don't destroy the - // VMs/Routers - s_logger.info("SSH test failed for account " + s_account.get() + "with reason '" + reason + "', stopping VMs"); - int stopResponseCode = executeStop(server, developerServer, username); - s_logger.info("stop command finished with response code: " + stopResponseCode); - success = false; // since the SSH test - // failed, mark the - // whole test as - // failure - } - } else { - // Just stop but don't destroy the - // VMs/Routers - s_logger.info("Deploy test failed with reason '" + reason + "', stopping VMs"); - int stopResponseCode = executeStop(server, developerServer, username); - s_logger.info("stop command finished with response code: " + stopResponseCode); - success = false; // since the deploy test - // failed, mark the - // whole test as failure - } - - if (success) { - s_logger.info("***** Completed test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + " seconds"); - - } else { - s_logger.info("##### FAILED test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + - " seconds with reason : " + reason); - } - s_logger.info("Sleeping for " + wait + " seconds before starting next iteration"); - Thread.sleep(wait); - } catch (Exception e) { - s_logger.warn("Error in thread", e); - try { - int stopResponseCode = executeStop(server, developerServer, username); - s_logger.info("stop response code: " + stopResponseCode); - } catch (Exception e1) { - s_logger.info("[ignored]" - + "error executing stop during stress test: " + e1.getLocalizedMessage()); - } - } finally { - NDC.clear(); - } - } while (repeat); - } - }).start(); - } - } catch (Exception e) { - s_logger.error(e); - } - } - - public static Map> getMultipleValuesFromXML(InputStream is, String[] tagNames) { - Map> returnValues = new HashMap>(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - s_logger.error("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - List valueList = new ArrayList(); - for (int j = 0; j < targetNodes.getLength(); j++) { - Node node = targetNodes.item(j); - valueList.add(node.getTextContent()); - } - returnValues.put(tagNames[i], valueList); - } - } - } catch (Exception ex) { - s_logger.error(ex); - } - return returnValues; - } - - public static Map getSingleValueFromXML(InputStream is, String[] tagNames) { - Map returnValues = new HashMap(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - s_logger.error("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); - } - } - } catch (Exception ex) { - s_logger.error("error processing XML", ex); - } - return returnValues; - } - - public static Map getSingleValueFromXML(Element rootElement, String[] tagNames) { - Map returnValues = new HashMap(); - if (rootElement == null) { - s_logger.error("Root element is null, can't get single value from xml"); - return null; - } - try { - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - s_logger.error("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); - } - } - } catch (Exception ex) { - s_logger.error("error processing XML", ex); - } - return returnValues; - } - - private static List getNonSourceNatIPs(InputStream is) { - List returnValues = new ArrayList(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - NodeList allocatedIpAddrNodes = rootElement.getElementsByTagName("publicipaddress"); - for (int i = 0; i < allocatedIpAddrNodes.getLength(); i++) { - Node allocatedIpAddrNode = allocatedIpAddrNodes.item(i); - NodeList childNodes = allocatedIpAddrNode.getChildNodes(); - String ipAddress = null; - boolean isSourceNat = true; // assume it's source nat until we - // find otherwise - for (int j = 0; j < childNodes.getLength(); j++) { - Node n = childNodes.item(j); - if ("ipaddress".equals(n.getNodeName())) { - ipAddress = n.getTextContent(); - } else if ("issourcenat".equals(n.getNodeName())) { - isSourceNat = Boolean.parseBoolean(n.getTextContent()); - } - } - if ((ipAddress != null) && !isSourceNat) { - returnValues.add(ipAddress); - } - } - } catch (Exception ex) { - s_logger.error(ex); - } - return returnValues; - } - - private static List getSourceNatIPs(InputStream is) { - List returnValues = new ArrayList(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - NodeList allocatedIpAddrNodes = rootElement.getElementsByTagName("publicipaddress"); - for (int i = 0; i < allocatedIpAddrNodes.getLength(); i++) { - Node allocatedIpAddrNode = allocatedIpAddrNodes.item(i); - NodeList childNodes = allocatedIpAddrNode.getChildNodes(); - String ipAddress = null; - boolean isSourceNat = false; // assume it's *not* source nat until we find otherwise - for (int j = 0; j < childNodes.getLength(); j++) { - Node n = childNodes.item(j); - if ("ipaddress".equals(n.getNodeName())) { - ipAddress = n.getTextContent(); - } else if ("issourcenat".equals(n.getNodeName())) { - isSourceNat = Boolean.parseBoolean(n.getTextContent()); - } - } - if ((ipAddress != null) && isSourceNat) { - returnValues.add(ipAddress); - } - } - } catch (Exception ex) { - s_logger.error(ex); - } - return returnValues; - } - - private static String executeRegistration(String server, String username, String password) throws HttpException, IOException { - String url = server + "?command=registerUserKeys&id=" + s_userId.get().toString(); - s_logger.info("registering: " + username); - String returnValue = null; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map requestKeyValues = getSingleValueFromXML(is, new String[] {"apikey", "secretkey"}); - s_apiKey.set(requestKeyValues.get("apikey")); - returnValue = requestKeyValues.get("secretkey"); - } else { - s_logger.error("registration failed with error code: " + responseCode); - } - return returnValue; - } - - private static Integer executeDeployment(String server, String developerServer, String username) throws HttpException, IOException { - // test steps: - // - create user - // - deploy Windows VM - // - deploy Linux VM - // - associate IP address - // - create two IP forwarding rules - // - create load balancer rule - // - list IP forwarding rules - // - list load balancer rules - - // ----------------------------- - // CREATE USER - // ----------------------------- - String encodedUsername = URLEncoder.encode(username, "UTF-8"); - String encryptedPassword = createMD5Password(username); - String encodedPassword = URLEncoder.encode(encryptedPassword, "UTF-8"); - - String url = - server + "?command=createUser&username=" + encodedUsername + "&password=" + encodedPassword + - "&firstname=Test&lastname=Test&email=test@vmops.com&domainId=1&accounttype=0"; - if (accountName != null) { - url = - server + "?command=createUser&username=" + encodedUsername + "&password=" + encodedPassword + - "&firstname=Test&lastname=Test&email=test@vmops.com&domainId=1&accounttype=0&account=" + accountName; - } - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - long userId = -1; - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map userIdValues = getSingleValueFromXML(is, new String[] {"id", "account"}); - String userIdStr = userIdValues.get("id"); - s_logger.info("created user " + username + " with id " + userIdStr); - if (userIdStr != null) { - userId = Long.parseLong(userIdStr); - s_userId.set(userId); - s_account.set(userIdValues.get("account")); - if (userId == -1) { - s_logger.error("create user (" + username + ") failed to retrieve a valid user id, aborting depolyment test"); - return -1; - } - } - } else { - s_logger.error("create user test failed for user " + username + " with error code :" + responseCode); - return responseCode; - } - - s_secretKey.set(executeRegistration(server, username, username)); - - if (s_secretKey.get() == null) { - s_logger.error("FAILED to retrieve secret key during registration, skipping user: " + username); - return -1; - } else { - s_logger.info("got secret key: " + s_secretKey.get()); - s_logger.info("got api key: " + s_apiKey.get()); - } - - // --------------------------------- - // CREATE NETWORK GROUP AND ADD INGRESS RULE TO IT - // --------------------------------- - String networkAccount = null; - if (accountName != null) { - networkAccount = accountName; - } else { - networkAccount = encodedUsername; - } - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String requestToSign = "apikey=" + encodedApiKey + "&command=createSecurityGroup&name=" + encodedUsername; - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - url = developerServer + "?command=createSecurityGroup&name=" + encodedUsername + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map values = getSingleValueFromXML(is, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("Create network rule response code: 401"); - return 401; - } else { - s_logger.info("Create security group response code: " + responseCode); - } - } else { - s_logger.error("Create security group failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - String encodedCidr = URLEncoder.encode("192.168.1.143/32", "UTF-8"); - url = - server + "?command=authorizeSecurityGroupIngress&cidrlist=" + encodedCidr + "&endport=22&" + "securitygroupname=" + encodedUsername + - "&protocol=tcp&startport=22&account=" + networkAccount + "&domainid=1"; - - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("Authorise security group ingress response code: 401"); - return 401; - } else { - s_logger.info("Authorise security group ingress response code: " + responseCode); - } - } else { - s_logger.error("Authorise security group ingress failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // --------------------------------- - // DEPLOY LINUX VM - // --------------------------------- - { - long templateId = 2; - String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); - String encodedServiceOfferingId = URLEncoder.encode("" + serviceOfferingId, "UTF-8"); - String encodedTemplateId = URLEncoder.encode("" + templateId, "UTF-8"); - encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - requestToSign = - "apikey=" + encodedApiKey + "&command=deployVirtualMachine&securitygrouplist=" + encodedUsername + "&serviceofferingid=" + encodedServiceOfferingId + - "&templateid=" + encodedTemplateId + "&zoneid=" + encodedZoneId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - url = - developerServer + "?command=deployVirtualMachine&securitygrouplist=" + encodedUsername + "&zoneid=" + encodedZoneId + "&serviceofferingid=" + - encodedServiceOfferingId + "&templateid=" + encodedTemplateId + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id", "ipaddress"}); - - if ((values.get("ipaddress") == null) || (values.get("id") == null)) { - s_logger.info("deploy linux vm response code: 401"); - return 401; - } else { - s_logger.info("deploy linux vm response code: " + responseCode); - long linuxVMId = Long.parseLong(values.get("id")); - s_logger.info("got linux virtual machine id: " + linuxVMId); - s_linuxVmId.set(values.get("id")); - s_linuxIP.set(values.get("ipaddress")); - s_linuxPassword.set("rs-ccb35ea5"); - } - } else { - s_logger.error("deploy linux vm failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - //Create a new volume - { - url = server + "?command=createVolume&diskofferingid=" + diskOfferingId + "&zoneid=" + zoneId + "&name=newvolume&account=" + s_account.get() + "&domainid=1"; - s_logger.info("Creating volume...."); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("create volume response code: 401"); - return 401; - } else { - s_logger.info("create volume response code: " + responseCode); - String volumeId = values.get("id"); - s_logger.info("got volume id: " + volumeId); - s_newVolume.set(volumeId); - } - } else { - s_logger.error("create volume failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - //attach a new volume to the vm - { - url = server + "?command=attachVolume&id=" + s_newVolume.get() + "&virtualmachineid=" + s_linuxVmId.get(); - s_logger.info("Attaching volume with id " + s_newVolume.get() + " to the vm " + s_linuxVmId.get()); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Attach data volume response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("Attach volume response code: 401"); - return 401; - } else { - s_logger.info("Attach volume response code: " + responseCode); - } - } else { - s_logger.error("Attach volume failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - //DEPLOY SECOND VM, ADD VOLUME TO IT - - // --------------------------------- - // DEPLOY another linux vm - // --------------------------------- - { - long templateId = 2; - String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); - String encodedServiceOfferingId = URLEncoder.encode("" + serviceOfferingId, "UTF-8"); - String encodedTemplateId = URLEncoder.encode("" + templateId, "UTF-8"); - encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - requestToSign = - "apikey=" + encodedApiKey + "&command=deployVirtualMachine&securitygrouplist=" + encodedUsername + "&serviceofferingid=" + encodedServiceOfferingId + - "&templateid=" + encodedTemplateId + "&zoneid=" + encodedZoneId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - url = - developerServer + "?command=deployVirtualMachine&securitygrouplist=" + encodedUsername + "&zoneid=" + encodedZoneId + "&serviceofferingid=" + - encodedServiceOfferingId + "&templateid=" + encodedTemplateId + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id", "ipaddress"}); - - if ((values.get("ipaddress") == null) || (values.get("id") == null)) { - s_logger.info("deploy linux vm response code: 401"); - return 401; - } else { - s_logger.info("deploy linux vm response code: " + responseCode); - long linuxVMId = Long.parseLong(values.get("id")); - s_logger.info("got linux virtual machine id: " + linuxVMId); - s_linuxVmId1.set(values.get("id")); - } - } else { - s_logger.error("deploy linux vm failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - //Create a new volume - { - url = server + "?command=createVolume&diskofferingid=" + diskOfferingId1 + "&zoneid=" + zoneId + "&name=newvolume1&account=" + s_account.get() + "&domainid=1"; - s_logger.info("Creating volume...."); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("create volume response code: 401"); - return 401; - } else { - s_logger.info("create volume response code: " + responseCode); - String volumeId = values.get("id"); - s_logger.info("got volume id: " + volumeId); - s_newVolume1.set(volumeId); - } - } else { - s_logger.error("create volume failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - //attach a new volume to the vm - { - url = server + "?command=attachVolume&id=" + s_newVolume1.get() + "&virtualmachineid=" + s_linuxVmId1.get(); - s_logger.info("Attaching volume with id " + s_newVolume1.get() + " to the vm " + s_linuxVmId1.get()); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Attach data volume response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("Attach volume response code: 401"); - return 401; - } else { - s_logger.info("Attach volume response code: " + responseCode); - } - } else { - s_logger.error("Attach volume failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - return 200; - } - - private static int executeCleanup(String server, String developerServer, String username) throws HttpException, IOException { - // test steps: - // - get user - // - delete user - - // ----------------------------- - // GET USER - // ----------------------------- - String userId = s_userId.get().toString(); - String encodedUserId = URLEncoder.encode(userId, "UTF-8"); - String url = server + "?command=listUsers&id=" + encodedUserId; - s_logger.info("Cleaning up resources for user: " + userId + " with url " + url); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("get user response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map userInfo = getSingleValueFromXML(is, new String[] {"username", "id", "account"}); - if (!username.equals(userInfo.get("username"))) { - s_logger.error("get user failed to retrieve requested user, aborting cleanup test" + ". Following URL was sent: " + url); - return -1; - } - - } else { - s_logger.error("get user failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ----------------------------- - // UPDATE USER - // ----------------------------- - { - url = server + "?command=updateUser&id=" + userId + "&firstname=delete&lastname=me"; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("update user response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"success"}); - s_logger.info("update user..success? " + success.get("success")); - } else { - s_logger.error("update user failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // ----------------------------- - // Execute reboot/stop/start commands for the VMs before deleting the account - made to exercise xen - // ----------------------------- - - //Reboot centos VM - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String requestToSign = "apikey=" + encodedApiKey + "&command=rebootVirtualMachine&id=" + s_linuxVmId.get(); - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=rebootVirtualMachine&id=" + s_linuxVmId.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Reboot VM response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(el, new String[] {"success"}); - s_logger.info("VM was rebooted with the status: " + success.get("success")); - } else { - s_logger.error(" VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - //Stop centos VM - requestToSign = "apikey=" + encodedApiKey + "&command=stopVirtualMachine&id=" + s_linuxVmId.get(); - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=stopVirtualMachine&id=" + s_linuxVmId.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Stop VM response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(el, new String[] {"success"}); - s_logger.info("VM was stopped with the status: " + success.get("success")); - } else { - s_logger.error("Stop VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - //Start centos VM - requestToSign = "apikey=" + encodedApiKey + "&command=startVirtualMachine&id=" + s_linuxVmId.get(); - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=startVirtualMachine&id=" + s_linuxVmId.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Start VM response code: " + responseCode); - - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(el, new String[] {"id"}); - - if (success.get("id") == null) { - s_logger.info("Start linux vm response code: 401"); - return 401; - } else { - s_logger.info("Start vm response code: " + responseCode); - } - - s_logger.info("VM was started with the status: " + success.get("success")); - } else { - s_logger.error("Start VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - -//// // ----------------------------- -//// // DISABLE USER -//// // ----------------------------- -// { -// url = server + "?command=disableUser&id=" + userId; -// client = new HttpClient(); -// method = new GetMethod(url); -// responseCode = client.executeMethod(method); -// s_logger.info("disable user response code: " + responseCode); -// if (responseCode == 200) { -// InputStream input = method.getResponseBodyAsStream(); -// Element el = queryAsyncJobResult(server, input); -// s_logger -// .info("Disabled user successfully"); -// } else { -// s_logger.error("disable user failed with error code: " + responseCode + ". Following URL was sent: " + url); -// return responseCode; -// } -// } - - // ----------------------------- - // DELETE USER - // ----------------------------- - { - url = server + "?command=deleteUser&id=" + userId; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("delete user response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - s_logger.info("Deleted user successfully"); - } else { - s_logger.error("delete user failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - return responseCode; - } - - private static int executeEventsAndBilling(String server, String developerServer) throws HttpException, IOException { - // test steps: - // - get all the events in the system for all users in the system - // - generate all the usage records in the system - // - get all the usage records in the system - - // ----------------------------- - // GET EVENTS - // ----------------------------- - String url = server + "?command=listEvents&page=1&account=" + s_account.get(); - - s_logger.info("Getting events for the account " + s_account.get()); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("get events response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> eventDescriptions = getMultipleValuesFromXML(is, new String[] {"description"}); - List descriptionText = eventDescriptions.get("description"); - if (descriptionText == null) { - s_logger.info("no events retrieved..."); - } else { - for (String text : descriptionText) { - s_logger.info("event: " + text); - } - } - } else { - s_logger.error("list events failed with error code: " + responseCode + ". Following URL was sent: " + url); - - return responseCode; - } - return responseCode; - } - - private static int executeStop(String server, String developerServer, String username) throws HttpException, IOException { - // test steps: - // - get userId for the given username - // - list virtual machines for the user - // - stop all virtual machines - // - get ip addresses for the user - // - release ip addresses - - // ----------------------------- - // GET USER - // ----------------------------- - String userId = s_userId.get().toString(); - String encodedUserId = URLEncoder.encode(userId, "UTF-8"); - - String url = server + "?command=listUsers&id=" + encodedUserId; - s_logger.info("Stopping resources for user: " + username); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("get user response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map userIdValues = getSingleValueFromXML(is, new String[] {"id"}); - String userIdStr = userIdValues.get("id"); - if (userIdStr != null) { - userId = userIdStr; - if (userId == null) { - s_logger.error("get user failed to retrieve a valid user id, aborting depolyment test" + ". Following URL was sent: " + url); - return -1; - } - } - } else { - s_logger.error("get user failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - { - // ---------------------------------- - // LIST VIRTUAL MACHINES - // ---------------------------------- - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String requestToSign = "apikey=" + encodedApiKey + "&command=listVirtualMachines"; - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listVirtualMachines&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - - s_logger.info("Listing all virtual machines for the user with url " + url); - String[] vmIds = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list virtual machines response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> vmIdValues = getMultipleValuesFromXML(is, new String[] {"id"}); - if (vmIdValues.containsKey("id")) { - List vmIdList = vmIdValues.get("id"); - if (vmIdList != null) { - vmIds = new String[vmIdList.size()]; - vmIdList.toArray(vmIds); - String vmIdLogStr = ""; - if ((vmIds != null) && (vmIds.length > 0)) { - vmIdLogStr = vmIds[0]; - for (int i = 1; i < vmIds.length; i++) { - vmIdLogStr = vmIdLogStr + "," + vmIds[i]; - } - } - s_logger.info("got virtual machine ids: " + vmIdLogStr); - } - } - - } else { - s_logger.error("list virtual machines test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // STOP/DESTROY VIRTUAL MACHINES - // ---------------------------------- - if (vmIds != null) { - for (String vmId : vmIds) { - requestToSign = "apikey=" + encodedApiKey + "&command=stopVirtualMachine&id=" + vmId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=stopVirtualMachine&id=" + vmId + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("StopVirtualMachine" + " [" + vmId + "] response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(el, new String[] {"success"}); - s_logger.info("StopVirtualMachine..success? " + success.get("success")); - } else { - s_logger.error("Stop virtual machine test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - } - -// { -// url = server + "?command=deleteUser&id=" + userId; -// client = new HttpClient(); -// method = new GetMethod(url); -// responseCode = client.executeMethod(method); -// s_logger.info("delete user response code: " + responseCode); -// if (responseCode == 200) { -// InputStream input = method.getResponseBodyAsStream(); -// Element el = queryAsyncJobResult(server, input); -// s_logger -// .info("Deleted user successfully"); -// } else { -// s_logger.error("delete user failed with error code: " + responseCode + ". Following URL was sent: " + url); -// return responseCode; -// } -// } - - } - - s_linuxIP.set(""); - s_linuxVmId.set(""); - s_linuxPassword.set(""); - s_windowsIP.set(""); - s_secretKey.set(""); - s_apiKey.set(""); - s_userId.set(Long.parseLong("0")); - s_account.set(""); - s_domainRouterId.set(""); - return responseCode; - } - - public static String signRequest(String request, String key) { - try { - Mac mac = Mac.getInstance("HmacSHA1"); - SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1"); - mac.init(keySpec); - mac.update(request.getBytes()); - byte[] encryptedBytes = mac.doFinal(); - return Base64.encodeBase64String(encryptedBytes); - } catch (Exception ex) { - s_logger.error("unable to sign request", ex); - } - return null; - } - - private static String sshWinTest(String host) { - if (host == null) { - s_logger.info("Did not receive a host back from test, ignoring win ssh test"); - return null; - } - - // We will retry 5 times before quitting - int retry = 1; - - while (true) { - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 300 seconds before next attempt. Account is " + s_account.get()); - Thread.sleep(300000); - } - - s_logger.info("Attempting to SSH into windows host " + host + " with retry attempt: " + retry + " for account " + s_account.get()); - - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("User " + s_account.get() + " ssHed successfully into windows host " + host); - boolean success = false; - boolean isAuthenticated = conn.authenticateWithPassword("Administrator", "password"); - if (isAuthenticated == false) { - return "Authentication failed"; - } else { - s_logger.info("Authentication is successful"); - } - - try { - SCPClient scp = new SCPClient(conn); - scp.put("wget.exe", "wget.exe", "C:\\Users\\Administrator", "0777"); - s_logger.info("Successfully put wget.exe file"); - } catch (Exception ex) { - s_logger.error("Unable to put wget.exe " + ex); - } - - if (conn == null) { - s_logger.error("Connection is null"); - } - Session sess = conn.openSession(); - - s_logger.info("User + " + s_account.get() + " executing : wget http://192.168.1.250/dump.bin"); - sess.execCommand("wget http://192.168.1.250/dump.bin && dir dump.bin"); - - InputStream stdout = sess.getStdout(); - InputStream stderr = sess.getStderr(); - - byte[] buffer = new byte[8192]; - while (true) { - if ((stdout.available() == 0) && (stderr.available() == 0)) { - int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); - - if ((conditions & ChannelCondition.TIMEOUT) != 0) { - s_logger.info("Timeout while waiting for data from peer."); - return null; - } - - if ((conditions & ChannelCondition.EOF) != 0) { - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { - break; - } - } - } - - while (stdout.available() > 0) { - success = true; - int len = stdout.read(buffer); - if (len > 0) // this check is somewhat paranoid - s_logger.info(new String(buffer, 0, len)); - } - - while (stderr.available() > 0) { - /* int len = */stderr.read(buffer); - } - } - sess.close(); - conn.close(); - - if (success) { - Thread.sleep(120000); - return null; - } else { - retry++; - if (retry == MAX_RETRY_WIN) { - return "SSH Windows Network test fail for account " + s_account.get(); - } - } - } catch (Exception e) { - s_logger.error(e); - retry++; - if (retry == MAX_RETRY_WIN) { - return "SSH Windows Network test fail with error " + e.getMessage(); - } - } - } - } - - private static String sshTest(String host, String password) { - int i = 0; - if (host == null) { - s_logger.info("Did not receive a host back from test, ignoring ssh test"); - return null; - } - - if (password == null) { - s_logger.info("Did not receive a password back from test, ignoring ssh test"); - return null; - } - - // We will retry 5 times before quitting - String result = null; - int retry = 0; - - while (true) { - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt. Account is " + s_account.get()); - Thread.sleep(120000); - } - - s_logger.info("Attempting to SSH into linux host " + host + " with retry attempt: " + retry + ". Account is " + s_account.get()); - - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("User + " + s_account.get() + " ssHed successfully into linux host " + host); - - boolean isAuthenticated = conn.authenticateWithPassword("root", password); - - if (isAuthenticated == false) { - s_logger.info("Authentication failed for root with password" + password); - return "Authentication failed"; - - } - - boolean success = false; - String linuxCommand = null; - - if (i % 10 == 0) - linuxCommand = "rm -rf *; wget http://192.168.1.250/dump.bin && ls -al dump.bin"; - else - linuxCommand = "wget http://192.168.1.250/dump.bin && ls -al dump.bin"; - - Session sess = conn.openSession(); - s_logger.info("User " + s_account.get() + " executing : " + linuxCommand); - sess.execCommand(linuxCommand); - - InputStream stdout = sess.getStdout(); - InputStream stderr = sess.getStderr(); - - byte[] buffer = new byte[8192]; - while (true) { - if ((stdout.available() == 0) && (stderr.available() == 0)) { - int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); - - if ((conditions & ChannelCondition.TIMEOUT) != 0) { - s_logger.info("Timeout while waiting for data from peer."); - return null; - } - - if ((conditions & ChannelCondition.EOF) != 0) { - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { - break; - } - } - } - - while (stdout.available() > 0) { - success = true; - int len = stdout.read(buffer); - if (len > 0) // this check is somewhat paranoid - s_logger.info(new String(buffer, 0, len)); - } - - while (stderr.available() > 0) { - /* int len = */stderr.read(buffer); - } - } - - sess.close(); - conn.close(); - - if (!success) { - retry++; - if (retry == MAX_RETRY_LINUX) { - result = "SSH Linux Network test fail"; - } - } - - return result; - } catch (Exception e) { - retry++; - s_logger.error("SSH Linux Network test fail with error"); - if (retry == MAX_RETRY_LINUX) { - return "SSH Linux Network test fail with error " + e.getMessage(); - } - } - i++; - } - } - - public static String createMD5Password(String password) { - MessageDigest md5; - - try { - md5 = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - throw new CloudRuntimeException("Error", e); - } - - md5.reset(); - BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes())); - - // make sure our MD5 hash value is 32 digits long... - StringBuffer sb = new StringBuffer(); - String pwStr = pwInt.toString(16); - int padding = 32 - pwStr.length(); - for (int i = 0; i < padding; i++) { - sb.append('0'); - } - sb.append(pwStr); - return sb.toString(); - } - - public static Element queryAsyncJobResult(String host, InputStream inputStream) { - Element returnBody = null; - - Map values = getSingleValueFromXML(inputStream, new String[] {"jobid"}); - String jobId = values.get("jobid"); - - if (jobId == null) { - s_logger.error("Unable to get a jobId"); - return null; - } - - //s_logger.info("Job id is " + jobId); - String resultUrl = host + "?command=queryAsyncJobResult&jobid=" + jobId; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(resultUrl); - while (true) { - try { - client.executeMethod(method); - //s_logger.info("Method is executed successfully. Following url was sent " + resultUrl); - InputStream is = method.getResponseBodyAsStream(); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(is); - returnBody = doc.getDocumentElement(); - doc.getDocumentElement().normalize(); - Element jobStatusTag = (Element)returnBody.getElementsByTagName("jobstatus").item(0); - String jobStatus = jobStatusTag.getTextContent(); - if (jobStatus.equals("0")) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - s_logger.debug("[ignored] interrupted while during async job result query."); - } - } else { - break; - } - - } catch (Exception ex) { - s_logger.error(ex); - } - } - return returnBody; - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/stress/TestClientWithAPI.java b/test/src-not-used/main/java/com/cloud/test/stress/TestClientWithAPI.java deleted file mode 100644 index 3d43a9440c7..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/stress/TestClientWithAPI.java +++ /dev/null @@ -1,2289 +0,0 @@ -// 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. -package com.cloud.test.stress; - -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; -import java.net.URLEncoder; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpException; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.trilead.ssh2.ChannelCondition; -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.SCPClient; -import com.trilead.ssh2.Session; - -import com.cloud.utils.exception.CloudRuntimeException; - -public class TestClientWithAPI { - private static long sleepTime = 180000L; // default 0 - private static boolean cleanUp = true; - public static final Logger s_logger = Logger.getLogger(TestClientWithAPI.class); - private static boolean repeat = true; - private static int numOfUsers = 0; - private static String[] users = null; - private static boolean internet = false; - private static ThreadLocal s_linuxIP = new ThreadLocal(); - private static ThreadLocal s_linuxIpId = new ThreadLocal(); - private static ThreadLocal s_linuxVmId = new ThreadLocal(); - private static ThreadLocal s_linuxPassword = new ThreadLocal(); - private static ThreadLocal s_windowsIP = new ThreadLocal(); - private static ThreadLocal s_windowsIpId = new ThreadLocal(); - private static ThreadLocal s_windowsVmId = new ThreadLocal(); - private static ThreadLocal s_secretKey = new ThreadLocal(); - private static ThreadLocal s_apiKey = new ThreadLocal(); - private static ThreadLocal s_userId = new ThreadLocal(); - private static ThreadLocal s_accountId = new ThreadLocal(); - private static ThreadLocal s_account = new ThreadLocal(); - private static ThreadLocal s_domainRouterId = new ThreadLocal(); - private static ThreadLocal s_pfGroupId = new ThreadLocal(); - private static ThreadLocal s_windowsLb = new ThreadLocal(); - private static ThreadLocal s_linuxLb = new ThreadLocal(); - private static ThreadLocal s_dataVolume = new ThreadLocal(); - private static ThreadLocal s_rootVolume = new ThreadLocal(); - private static ThreadLocal s_newVolume = new ThreadLocal(); - private static ThreadLocal s_snapshot = new ThreadLocal(); - private static ThreadLocal s_volumeFromSnapshot = new ThreadLocal(); - private static ThreadLocal s_networkId = new ThreadLocal(); - private static ThreadLocal s_publicIpId = new ThreadLocal(); - private static ThreadLocal s_winipfwdid = new ThreadLocal(); - private static ThreadLocal s_linipfwdid = new ThreadLocal(); - private static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - private static int usageIterator = 1; - private static int numThreads = 1; - private static int wait = 5000; - private static String accountName = null; - private static String zoneId = "1"; - private static String snapshotTest = "no"; - private static String serviceOfferingId = "1"; - private static String diskOfferingId = "4"; - private static String networkOfferingId = "6"; - private static String vmPassword = "rs-ccb35ea5"; - private static String downloadUrl = "192.168.1.250/dump.bin"; - - private static final int MAX_RETRY_LINUX = 10; - private static final int MAX_RETRY_WIN = 10; - - public static void main(String[] args) { - String host = "http://localhost"; - String port = "8092"; - String devPort = "8080"; - String apiUrl = "/client/api"; - - try { - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - // host - if (arg.equals("-h")) { - host = "http://" + iter.next(); - } - - if (arg.equals("-p")) { - port = iter.next(); - } - if (arg.equals("-dp")) { - devPort = iter.next(); - } - - if (arg.equals("-t")) { - numThreads = Integer.parseInt(iter.next()); - } - - if (arg.equals("-s")) { - sleepTime = Long.parseLong(iter.next()); - } - if (arg.equals("-a")) { - accountName = iter.next(); - } - - if (arg.equals("-c")) { - cleanUp = Boolean.parseBoolean(iter.next()); - if (!cleanUp) - sleepTime = 0L; // no need to wait if we don't ever - // cleanup - } - - if (arg.equals("-r")) { - repeat = Boolean.parseBoolean(iter.next()); - } - - if (arg.equals("-u")) { - numOfUsers = Integer.parseInt(iter.next()); - } - - if (arg.equals("-i")) { - internet = Boolean.parseBoolean(iter.next()); - } - - if (arg.equals("-w")) { - wait = Integer.parseInt(iter.next()); - } - - if (arg.equals("-z")) { - zoneId = iter.next(); - } - - if (arg.equals("-snapshot")) { - snapshotTest = "yes"; - } - - if (arg.equals("-so")) { - serviceOfferingId = iter.next(); - } - - if (arg.equals("-do")) { - diskOfferingId = iter.next(); - } - - if (arg.equals("-no")) { - networkOfferingId = iter.next(); - } - - if (arg.equals("-pass")) { - vmPassword = iter.next(); - } - - if (arg.equals("-url")) { - downloadUrl = iter.next(); - } - - } - - final String server = host + ":" + port + "/"; - final String developerServer = host + ":" + devPort + apiUrl; - s_logger.info("Starting test against server: " + server + " with " + numThreads + " thread(s)"); - if (cleanUp) - s_logger.info("Clean up is enabled, each test will wait " + sleepTime + " ms before cleaning up"); - - if (numOfUsers > 0) { - s_logger.info("Pre-generating users for test of size : " + numOfUsers); - users = new String[numOfUsers]; - Random ran = new Random(); - for (int i = 0; i < numOfUsers; i++) { - users[i] = Math.abs(ran.nextInt()) + "-user"; - } - } - - for (int i = 0; i < numThreads; i++) { - new Thread(new Runnable() { - @Override - public void run() { - do { - String username = null; - try { - long now = System.currentTimeMillis(); - Random ran = new Random(); - if (users != null) { - username = users[Math.abs(ran.nextInt()) % numOfUsers]; - } else { - username = Math.abs(ran.nextInt()) + "-user"; - } - NDC.push(username); - - s_logger.info("Starting test for the user " + username); - int response = executeDeployment(server, developerServer, username, snapshotTest); - boolean success = false; - String reason = null; - - if (response == 200) { - success = true; - if (internet) { - s_logger.info("Deploy successful...waiting 5 minute before SSH tests"); - Thread.sleep(300000L); // Wait 60 - // seconds so - // the windows VM - // can boot up and do a sys prep. - - if (accountName == null) { - s_logger.info("Begin Linux SSH test for account " + s_account.get()); - reason = sshTest(s_linuxIP.get(), s_linuxPassword.get(), snapshotTest); - } - - if (reason == null) { - s_logger.info("Linux SSH test successful for account " + s_account.get()); - s_logger.info("Begin WindowsSSH test for account " + s_account.get()); - - reason = sshTest(s_linuxIP.get(), s_linuxPassword.get(), snapshotTest); - // reason = sshWinTest(s_windowsIP.get()); - } - - // release the linux IP now... - s_linuxIP.set(null); - // release the Windows IP now - s_windowsIP.set(null); - } - - // sleep for 3 min before getting the latest network stat - // s_logger.info("Sleeping for 5 min before getting the lates network stat for the account"); - // Thread.sleep(300000); - // verify that network stat is correct for the user; if it's not - stop all the resources - // for the user - // if ((reason == null) && (getNetworkStat(server) == false) ) { - // s_logger.error("Stopping all the resources for the account " + s_account.get() + - // " as network stat is incorrect"); - // int stopResponseCode = executeStop( - // server, developerServer, - // username, false); - // s_logger - // .info("stop command finished with response code: " - // + stopResponseCode); - // success = false; // since the SSH test - // - // } else - if (reason == null) { - if (internet) { - s_logger.info("Windows SSH test successful for account " + s_account.get()); - } else { - s_logger.info("deploy test successful....now cleaning up"); - if (cleanUp) { - s_logger.info("Waiting " + sleepTime + " ms before cleaning up vms"); - Thread.sleep(sleepTime); - } else { - success = true; - } - } - - if (usageIterator >= numThreads) { - int eventsAndBillingResponseCode = executeEventsAndBilling(server, developerServer); - s_logger.info("events and usage records command finished with response code: " + eventsAndBillingResponseCode); - usageIterator = 1; - - } else { - s_logger.info("Skipping events and usage records for this user: usageIterator " + usageIterator + " and number of Threads " + - numThreads); - usageIterator++; - } - - if ((users == null) && (accountName == null)) { - s_logger.info("Sending cleanup command"); - int cleanupResponseCode = executeCleanup(server, developerServer, username); - s_logger.info("cleanup command finished with response code: " + cleanupResponseCode); - success = (cleanupResponseCode == 200); - } else { - s_logger.info("Sending stop DomR / destroy VM command"); - int stopResponseCode = executeStop(server, developerServer, username, true); - s_logger.info("stop(destroy) command finished with response code: " + stopResponseCode); - success = (stopResponseCode == 200); - } - - } else { - // Just stop but don't destroy the - // VMs/Routers - s_logger.info("SSH test failed for account " + s_account.get() + "with reason '" + reason + "', stopping VMs"); - int stopResponseCode = executeStop(server, developerServer, username, false); - s_logger.info("stop command finished with response code: " + stopResponseCode); - success = false; // since the SSH test - // failed, mark the - // whole test as - // failure - } - } else { - // Just stop but don't destroy the - // VMs/Routers - s_logger.info("Deploy test failed with reason '" + reason + "', stopping VMs"); - int stopResponseCode = executeStop(server, developerServer, username, true); - s_logger.info("stop command finished with response code: " + stopResponseCode); - success = false; // since the deploy test - // failed, mark the - // whole test as failure - } - - if (success) { - s_logger.info("***** Completed test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + " seconds"); - - } else { - s_logger.info("##### FAILED test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + - " seconds with reason : " + reason); - } - s_logger.info("Sleeping for " + wait + " seconds before starting next iteration"); - Thread.sleep(wait); - } catch (Exception e) { - s_logger.warn("Error in thread", e); - try { - int stopResponseCode = executeStop(server, developerServer, username, true); - s_logger.info("stop response code: " + stopResponseCode); - } catch (Exception e1) { - s_logger.info("[ignored]" - + "error executing stop during api test: " + e1.getLocalizedMessage()); - } - } finally { - NDC.clear(); - } - } while (repeat); - } - }).start(); - } - } catch (Exception e) { - s_logger.error(e); - } - } - - public static Map> getMultipleValuesFromXML(InputStream is, String[] tagNames) { - Map> returnValues = new HashMap>(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - s_logger.error("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - List valueList = new ArrayList(); - for (int j = 0; j < targetNodes.getLength(); j++) { - Node node = targetNodes.item(j); - valueList.add(node.getTextContent()); - } - returnValues.put(tagNames[i], valueList); - } - } - } catch (Exception ex) { - s_logger.error(ex); - } - return returnValues; - } - - public static Map getSingleValueFromXML(InputStream is, String[] tagNames) { - Map returnValues = new HashMap(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - s_logger.error("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); - } - } - } catch (Exception ex) { - s_logger.error("error processing XML", ex); - } - return returnValues; - } - - public static Map getSingleValueFromXML(Element rootElement, String[] tagNames) { - Map returnValues = new HashMap(); - if (rootElement == null) { - s_logger.error("Root element is null, can't get single value from xml"); - return null; - } - try { - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - s_logger.error("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); - } - } - } catch (Exception ex) { - s_logger.error("error processing XML", ex); - } - return returnValues; - } - - private static List getNonSourceNatIPs(InputStream is) { - List returnValues = new ArrayList(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - NodeList allocatedIpAddrNodes = rootElement.getElementsByTagName("publicipaddress"); - for (int i = 0; i < allocatedIpAddrNodes.getLength(); i++) { - Node allocatedIpAddrNode = allocatedIpAddrNodes.item(i); - NodeList childNodes = allocatedIpAddrNode.getChildNodes(); - String ipAddress = null; - boolean isSourceNat = true; // assume it's source nat until we - // find otherwise - for (int j = 0; j < childNodes.getLength(); j++) { - Node n = childNodes.item(j); - if ("id".equals(n.getNodeName())) { - // if ("ipaddress".equals(n.getNodeName())) { - ipAddress = n.getTextContent(); - } else if ("issourcenat".equals(n.getNodeName())) { - isSourceNat = Boolean.parseBoolean(n.getTextContent()); - } - } - if ((ipAddress != null) && !isSourceNat) { - returnValues.add(ipAddress); - } - } - } catch (Exception ex) { - s_logger.error(ex); - } - return returnValues; - } - - private static List getIPs(InputStream is, boolean sourceNat) { - List returnValues = new ArrayList(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - NodeList allocatedIpAddrNodes = rootElement.getElementsByTagName("publicipaddress"); - for (int i = 0; i < allocatedIpAddrNodes.getLength(); i++) { - Node allocatedIpAddrNode = allocatedIpAddrNodes.item(i); - NodeList childNodes = allocatedIpAddrNode.getChildNodes(); - String ipAddress = null; - String ipAddressId = null; - boolean isSourceNat = false; // assume it's *not* source nat until we find otherwise - for (int j = 0; j < childNodes.getLength(); j++) { - Node n = childNodes.item(j); - //Id is being used instead of ipaddress. Changes need to done later to ipaddress variable - if ("id".equals(n.getNodeName())) { - ipAddressId = n.getTextContent(); - } else if ("ipaddress".equals(n.getNodeName())) { - ipAddress = n.getTextContent(); - } else if ("issourcenat".equals(n.getNodeName())) { - isSourceNat = Boolean.parseBoolean(n.getTextContent()); - } - } - if ((ipAddress != null) && isSourceNat == sourceNat) { - returnValues.add(ipAddressId); - returnValues.add(ipAddress); - } - } - } catch (Exception ex) { - s_logger.error(ex); - } - return returnValues; - } - - private static String executeRegistration(String server, String username, String password) throws HttpException, IOException { - String url = server + "?command=registerUserKeys&id=" + s_userId.get().toString(); - s_logger.info("registering: " + username); - String returnValue = null; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map requestKeyValues = getSingleValueFromXML(is, new String[] {"apikey", "secretkey"}); - s_apiKey.set(requestKeyValues.get("apikey")); - returnValue = requestKeyValues.get("secretkey"); - } else { - s_logger.error("registration failed with error code: " + responseCode); - } - return returnValue; - } - - private static Integer executeDeployment(String server, String developerServer, String username, String snapshotTest) throws HttpException, IOException { - // test steps: - // - create user - // - deploy Windows VM - // - deploy Linux VM - // - associate IP address - // - create two IP forwarding rules - // - create load balancer rule - // - list IP forwarding rules - // - list load balancer rules - - // ----------------------------- - // CREATE ACCOUNT - // ----------------------------- - String encodedUsername = URLEncoder.encode(username, "UTF-8"); - String encryptedPassword = createMD5Password(username); - String encodedPassword = URLEncoder.encode(encryptedPassword, "UTF-8"); - - String url = - server + "?command=createAccount&username=" + encodedUsername + "&account=" + encodedUsername + "&password=" + encodedPassword + - "&firstname=Test&lastname=Test&email=test@vmops.com&domainId=1&accounttype=0"; - - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - long accountId = -1; - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map accountValues = getSingleValueFromXML(is, new String[] {"id", "name"}); - String accountIdStr = accountValues.get("id"); - s_logger.info("created account " + username + " with id " + accountIdStr); - if (accountIdStr != null) { - accountId = Long.parseLong(accountIdStr); - s_accountId.set(accountId); - s_account.set(accountValues.get("name")); - if (accountId == -1) { - s_logger.error("create account (" + username + ") failed to retrieve a valid user id, aborting depolyment test"); - return -1; - } - } - } else { - s_logger.error("create account test failed for account " + username + " with error code :" + responseCode + - ", aborting deployment test. The command was sent with url " + url); - return -1; - } - - // LIST JUST CREATED USER TO GET THE USER ID - url = server + "?command=listUsers&username=" + encodedUsername + "&account=" + encodedUsername + "&domainId=1"; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - long userId = -1; - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map userIdValues = getSingleValueFromXML(is, new String[] {"id"}); - String userIdStr = userIdValues.get("id"); - s_logger.info("listed user " + username + " with id " + userIdStr); - if (userIdStr != null) { - userId = Long.parseLong(userIdStr); - s_userId.set(userId); - if (userId == -1) { - s_logger.error("list user by username " + username + ") failed to retrieve a valid user id, aborting depolyment test"); - return -1; - } - } - } else { - s_logger.error("list user test failed for account " + username + " with error code :" + responseCode + - ", aborting deployment test. The command was sent with url " + url); - return -1; - } - - s_secretKey.set(executeRegistration(server, username, username)); - - if (s_secretKey.get() == null) { - s_logger.error("FAILED to retrieve secret key during registration, skipping user: " + username); - return -1; - } else { - s_logger.info("got secret key: " + s_secretKey.get()); - s_logger.info("got api key: " + s_apiKey.get()); - } - - // --------------------------------- - // CREATE VIRTUAL NETWORK - // --------------------------------- - url = - server + "?command=createNetwork&networkofferingid=" + networkOfferingId + "&account=" + encodedUsername + "&domainId=1" + "&zoneId=" + zoneId + - "&name=virtualnetwork-" + encodedUsername + "&displaytext=virtualnetwork-" + encodedUsername; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map networkValues = getSingleValueFromXML(is, new String[] {"id"}); - String networkIdStr = networkValues.get("id"); - s_logger.info("Created virtual network with name virtualnetwork-" + encodedUsername + " and id " + networkIdStr); - if (networkIdStr != null) { - s_networkId.set(networkIdStr); - } - } else { - s_logger.error("Create virtual network failed for account " + username + " with error code :" + responseCode + - ", aborting deployment test. The command was sent with url " + url); - return -1; - } - /* - // --------------------------------- - // CREATE DIRECT NETWORK - // --------------------------------- - url = server + "?command=createNetwork&networkofferingid=" + networkOfferingId_dir + "&account=" + encodedUsername + "&domainId=1" + "&zoneId=" + zoneId + "&name=directnetwork-" + encodedUsername + "&displaytext=directnetwork-" + encodedUsername; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map networkValues = getSingleValueFromXML(is, new String[] { "id" }); - String networkIdStr = networkValues.get("id"); - s_logger.info("Created direct network with name directnetwork-" + encodedUsername + " and id " + networkIdStr); - if (networkIdStr != null) { - s_networkId_dir.set(networkIdStr); - } - } else { - s_logger.error("Create direct network failed for account " + username + " with error code :" + responseCode + ", aborting deployment test. The command was sent with url " + url); - return -1; - } - */ - - // --------------------------------- - // DEPLOY LINUX VM - // --------------------------------- - String linuxVMPrivateIP = null; - { - // long templateId = 3; - long templateId = 4; - String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); - String encodedServiceOfferingId = URLEncoder.encode("" + serviceOfferingId, "UTF-8"); - String encodedTemplateId = URLEncoder.encode("" + templateId, "UTF-8"); - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String encodedNetworkIds = URLEncoder.encode(s_networkId.get() + ",206", "UTF-8"); - String requestToSign = - "apikey=" + encodedApiKey + "&command=deployVirtualMachine&diskofferingid=" + diskOfferingId + "&networkids=" + encodedNetworkIds + - "&serviceofferingid=" + encodedServiceOfferingId + "&templateid=" + encodedTemplateId + "&zoneid=" + encodedZoneId; - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - url = - developerServer + "?command=deployVirtualMachine" + "&zoneid=" + encodedZoneId + "&serviceofferingid=" + encodedServiceOfferingId + "&diskofferingid=" + - diskOfferingId + "&networkids=" + encodedNetworkIds + "&templateid=" + encodedTemplateId + "&apikey=" + encodedApiKey + "&signature=" + - encodedSignature; - - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id", "ipaddress"}); - - if ((values.get("ipaddress") == null) || (values.get("id") == null)) { - s_logger.info("deploy linux vm response code: 401, the command was sent with url " + url); - return 401; - } else { - s_logger.info("deploy linux vm response code: " + responseCode); - long linuxVMId = Long.parseLong(values.get("id")); - s_logger.info("got linux virtual machine id: " + linuxVMId); - s_linuxVmId.set(values.get("id")); - linuxVMPrivateIP = values.get("ipaddress"); - // s_linuxPassword.set(values.get("password")); - s_linuxPassword.set(vmPassword); - s_logger.info("got linux virtual machine password: " + s_linuxPassword.get()); - } - } else { - s_logger.error("deploy linux vm failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - { - // --------------------------------- - // ASSOCIATE IP for windows - // --------------------------------- - String ipAddr = null; - - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String requestToSign = "apikey=" + encodedApiKey + "&command=associateIpAddress" + "&zoneid=" + zoneId; - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=associateIpAddress" + "&apikey=" + encodedApiKey + "&zoneid=" + zoneId + "&signature=" + encodedSignature; - - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - /*Asynchronous Job - Corresponding Changes Made*/ - Element associpel = queryAsyncJobResult(server, is); - Map values = getSingleValueFromXML(associpel, new String[] {"id", "ipaddress"}); - - if ((values.get("ipaddress") == null) || (values.get("id") == null)) { - s_logger.info("associate ip for Windows response code: 401, the command was sent with url " + url); - return 401; - } else { - s_logger.info("Associate IP Address response code: " + responseCode); - long publicIpId = Long.parseLong(values.get("id")); - s_logger.info("Associate IP's Id: " + publicIpId); - s_publicIpId.set(values.get("id")); - } - } else { - s_logger.error("associate ip address for windows vm failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - String encodedPublicIpId = URLEncoder.encode(s_publicIpId.get(), "UTF-8"); - requestToSign = "apikey=" + encodedApiKey + "&command=listPublicIpAddresses" + "&id=" + encodedPublicIpId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listPublicIpAddresses&apikey=" + encodedApiKey + "&id=" + encodedPublicIpId + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("url is " + url); - s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - // InputStream ips = method.getResponseBodyAsStream(); - List ipAddressValues = getIPs(is, false); - // List ipAddressVals = getIPs(is, false, true); - if ((ipAddressValues != null) && !ipAddressValues.isEmpty()) { - s_windowsIpId.set(ipAddressValues.get(0)); - s_windowsIP.set(ipAddressValues.get(1)); - s_logger.info("For Windows, using non-sourceNat IP address ID: " + ipAddressValues.get(0)); - s_logger.info("For Windows, using non-sourceNat IP address: " + ipAddressValues.get(1)); - } - } else { - s_logger.error("list ip addresses failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // --------------------------------- - // Use the SourceNat IP for linux - // --------------------------------- - { - requestToSign = "apikey=" + encodedApiKey + "&command=listPublicIpAddresses"; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listPublicIpAddresses&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("url is " + url); - s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); -// InputStream ips = method.getResponseBodyAsStream(); - List ipAddressValues = getIPs(is, true); -// is = method.getResponseBodyAsStream(); -// List ipAddressVals = getIPs(is, true, true); - if ((ipAddressValues != null) && !ipAddressValues.isEmpty()) { - s_linuxIpId.set(ipAddressValues.get(0)); - s_linuxIP.set(ipAddressValues.get(1)); - s_logger.info("For linux, using sourceNat IP address ID: " + ipAddressValues.get(0)); - s_logger.info("For linux, using sourceNat IP address: " + ipAddressValues.get(1)); - } - } else { - s_logger.error("list ip addresses failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - //-------------------------------------------- - // Enable Static NAT for the Source NAT Ip - //-------------------------------------------- - String encodedSourceNatPublicIpId = URLEncoder.encode(s_linuxIpId.get(), "UTF-8"); - - /* requestToSign = "apikey=" + encodedApiKey + "&command=enableStaticNat"+"&id=" + encodedSourceNatPublicIpId + "&virtualMachineId=" + encodedVmId;; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=enableStaticNat&apikey=" + encodedApiKey + "&signature=" + encodedSignature + "&id=" + encodedSourceNatPublicIpId + "&virtualMachineId=" + encodedVmId; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("url is " + url); - s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] { "success" }); - s_logger.info("Enable Static NAT..success? " + success.get("success")); - } else { - s_logger.error("Enable Static NAT failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - */ - // ------------------------------------------------------------- - // CREATE IP FORWARDING RULE -- Linux VM - // ------------------------------------------------------------- - String encodedVmId = URLEncoder.encode(s_linuxVmId.get(), "UTF-8"); - String encodedIpAddress = URLEncoder.encode(s_linuxIpId.get(), "UTF-8"); - requestToSign = - "apikey=" + encodedApiKey + "&command=createPortForwardingRule&ipaddressid=" + encodedIpAddress + "&privateport=22&protocol=TCP&publicport=22" + - "&virtualmachineid=" + encodedVmId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = - developerServer + "?command=createPortForwardingRule&apikey=" + encodedApiKey + "&ipaddressid=" + encodedIpAddress + - "&privateport=22&protocol=TCP&publicport=22&virtualmachineid=" + encodedVmId + "&signature=" + encodedSignature; - - s_logger.info("Created port forwarding rule with " + url); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - s_logger.info("Port forwarding rule was assigned successfully to Linux VM"); - long ipfwdid = Long.parseLong(values.get("id")); - s_logger.info("got Port Forwarding Rule's Id:" + ipfwdid); - s_linipfwdid.set(values.get("id")); - - } else { - s_logger.error("Port forwarding rule creation failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // Create snapshot recurring policy if needed; otherwise create windows vm - if (snapshotTest.equals("yes")) { - - // list volumes for linux vm - { - url = server + "?command=listVolumes&virtualMachineId=" + s_linuxVmId.get() + "&type=root"; - s_logger.info("Getting rootDisk id of Centos vm"); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("List volumes response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"id"}); - if (success.get("id") == null) { - s_logger.error("Unable to get root volume for linux vm. Followin url was sent: " + url); - } - s_logger.info("Got rootVolume for linux vm with id " + success.get("id")); - s_rootVolume.set(success.get("id")); - } else { - s_logger.error("List volumes for linux vm failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - // Create recurring snapshot policy for linux vm - { - String encodedTimeZone = URLEncoder.encode("America/Los Angeles", "UTF-8"); - url = - server + "?command=createSnapshotPolicy&intervaltype=hourly&schedule=10&maxsnaps=4&volumeid=" + s_rootVolume.get() + "&timezone=" + - encodedTimeZone; - s_logger.info("Creating recurring snapshot policy for linux vm ROOT disk"); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Create recurring snapshot policy for linux vm ROOT disk: " + responseCode); - if (responseCode != 200) { - s_logger.error("Create recurring snapshot policy for linux vm ROOT disk failed with error code: " + responseCode + ". Following URL was sent: " + - url); - return responseCode; - } - } - } else { - // --------------------------------- - // DEPLOY WINDOWS VM - // --------------------------------- - String windowsVMPrivateIP = null; - { - // long templateId = 6; - long templateId = 4; - String encodedZoneId = URLEncoder.encode("" + zoneId, "UTF-8"); - String encodedServiceOfferingId = URLEncoder.encode("" + serviceOfferingId, "UTF-8"); - String encodedTemplateId = URLEncoder.encode("" + templateId, "UTF-8"); - encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String encodedNetworkIds = URLEncoder.encode(s_networkId.get() + ",206", "UTF-8"); - - requestToSign = - "apikey=" + encodedApiKey + "&command=deployVirtualMachine&diskofferingid=" + diskOfferingId + "&networkids=" + encodedNetworkIds + - "&serviceofferingid=" + encodedServiceOfferingId + "&templateid=" + encodedTemplateId + "&zoneid=" + encodedZoneId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = - developerServer + "?command=deployVirtualMachine" + "&zoneid=" + encodedZoneId + "&serviceofferingid=" + encodedServiceOfferingId + - "&diskofferingid=" + diskOfferingId + "&networkids=" + encodedNetworkIds + "&templateid=" + encodedTemplateId + "&apikey=" + encodedApiKey + - "&signature=" + encodedSignature; - - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id", "ipaddress"}); - - if ((values.get("ipaddress") == null) || (values.get("id") == null)) { - s_logger.info("deploy windows vm response code: 401, the command was sent with url " + url); - return 401; - } else { - s_logger.info("deploy windows vm response code: " + responseCode); - windowsVMPrivateIP = values.get("ipaddress"); - long windowsVMId = Long.parseLong(values.get("id")); - s_logger.info("got windows virtual machine id: " + windowsVMId); - s_windowsVmId.set(values.get("id")); - } - } else { - s_logger.error("deploy windows vm failes with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - //-------------------------------------------- - // Enable Static NAT for the Non Source NAT Ip - //-------------------------------------------- - - encodedVmId = URLEncoder.encode(s_windowsVmId.get(), "UTF-8"); - encodedPublicIpId = URLEncoder.encode(s_publicIpId.get(), "UTF-8"); - requestToSign = "apikey=" + encodedApiKey + "&command=enableStaticNat" + "&ipaddressid=" + encodedPublicIpId + "&virtualMachineId=" + encodedVmId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = - developerServer + "?command=enableStaticNat&apikey=" + encodedApiKey + "&ipaddressid=" + encodedPublicIpId + "&signature=" + encodedSignature + - "&virtualMachineId=" + encodedVmId; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("url is " + url); - s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"success"}); - s_logger.info("Enable Static NAT..success? " + success.get("success")); - } else { - s_logger.error("Enable Static NAT failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ------------------------------------------------------------- - // CREATE IP FORWARDING RULE -- Windows VM - // ------------------------------------------------------------- - - // create port forwarding rule for window vm - encodedIpAddress = URLEncoder.encode(s_windowsIpId.get(), "UTF-8"); - //encodedVmId = URLEncoder.encode(s_windowsVmId.get(), "UTF-8"); - - requestToSign = "apikey=" + encodedApiKey + "&command=createIpForwardingRule&endPort=22&ipaddressid=" + encodedIpAddress + "&protocol=TCP&startPort=22"; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = - developerServer + "?command=createIpForwardingRule&apikey=" + encodedApiKey + "&endPort=22&ipaddressid=" + encodedIpAddress + - "&protocol=TCP&signature=" + encodedSignature + "&startPort=22"; - - s_logger.info("Created Ip forwarding rule with " + url); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - s_logger.info("Port forwarding rule was assigned successfully to Windows VM"); - long ipfwdid = Long.parseLong(values.get("id")); - s_logger.info("got Ip Forwarding Rule's Id:" + ipfwdid); - s_winipfwdid.set(values.get("id")); - } else { - s_logger.error("Port forwarding rule creation failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - } - return responseCode; - } - - private static int executeCleanup(String server, String developerServer, String username) throws HttpException, IOException { - // test steps: - // - get user - // - delete user - - // ----------------------------- - // GET USER - // ----------------------------- - String userId = s_userId.get().toString(); - String encodedUserId = URLEncoder.encode(userId, "UTF-8"); - String url = server + "?command=listUsers&id=" + encodedUserId; - s_logger.info("Cleaning up resources for user: " + userId + " with url " + url); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("get user response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map userInfo = getSingleValueFromXML(is, new String[] {"username", "id", "account"}); - if (!username.equals(userInfo.get("username"))) { - s_logger.error("get user failed to retrieve requested user, aborting cleanup test" + ". Following URL was sent: " + url); - return -1; - } - - } else { - s_logger.error("get user failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ----------------------------- - // UPDATE USER - // ----------------------------- - { - url = server + "?command=updateUser&id=" + userId + "&firstname=delete&lastname=me"; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("update user response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"success"}); - s_logger.info("update user..success? " + success.get("success")); - } else { - s_logger.error("update user failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // ----------------------------- - // Detach existin dataVolume, create a new volume, attach it to the vm - // ----------------------------- - { - url = server + "?command=listVolumes&virtualMachineId=" + s_linuxVmId.get() + "&type=dataDisk"; - s_logger.info("Getting dataDisk id of Centos vm"); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("List volumes response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"id"}); - s_logger.info("Got dataDiskVolume with id " + success.get("id")); - s_dataVolume.set(success.get("id")); - } else { - s_logger.error("List volumes failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // Detach volume - { - url = server + "?command=detachVolume&id=" + s_dataVolume.get(); - s_logger.info("Detaching volume with id " + s_dataVolume.get()); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Detach data volume response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - s_logger.info("The volume was detached successfully"); - } else { - s_logger.error("Detach data disk failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // Delete a volume - { - url = server + "?command=deleteVolume&id=" + s_dataVolume.get(); - s_logger.info("Deleting volume with id " + s_dataVolume.get()); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Delete data volume response code: " + responseCode); - if (responseCode == 200) { - s_logger.info("The volume was deleted successfully"); - } else { - s_logger.error("Delete volume failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // Create a new volume - { - url = server + "?command=createVolume&diskofferingid=" + diskOfferingId + "&zoneid=" + zoneId + "&name=newvolume&account=" + s_account.get() + "&domainid=1"; - s_logger.info("Creating volume...."); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("create volume response code: 401"); - return 401; - } else { - s_logger.info("create volume response code: " + responseCode); - long volumeId = Long.parseLong(values.get("id")); - s_logger.info("got volume id: " + volumeId); - s_newVolume.set(values.get("id")); - } - } else { - s_logger.error("create volume failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // attach a new volume to the vm - { - url = server + "?command=attachVolume&id=" + s_newVolume.get() + "&virtualmachineid=" + s_linuxVmId.get(); - s_logger.info("Attaching volume with id " + s_newVolume.get() + " to the vm " + s_linuxVmId.get()); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Attach data volume response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - s_logger.info("The volume was attached successfully"); - } else { - s_logger.error("Attach volume failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // Create a snapshot - // list volumes - { - url = server + "?command=listVolumes&virtualMachineId=" + s_linuxVmId.get() + "&type=root"; - s_logger.info("Getting rootDisk id of Centos vm"); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("List volumes response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"id"}); - if (success.get("id") == null) { - s_logger.error("Unable to get root volume. Followin url was sent: " + url); - } - s_logger.info("Got rootVolume with id " + success.get("id")); - s_rootVolume.set(success.get("id")); - } else { - s_logger.error("List volumes failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // //Create snapshot from root disk volume - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String requestToSign = "apikey=" + encodedApiKey + "&command=createSnapshot&volumeid=" + s_rootVolume.get(); - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=createSnapshot&volumeid=" + s_rootVolume.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Create snapshot response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("create snapshot response code: 401"); - return 401; - } else { - s_logger.info("create snapshot response code: " + responseCode + ". Got snapshot with id " + values.get("id")); - s_snapshot.set(values.get("id")); - } - } else { - s_logger.error("create snapshot failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // Create volume from the snapshot created on the previous step and attach it to the running vm - /* encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - requestToSign = "apikey=" + encodedApiKey + "&command=createVolume&name=" + s_account.get() + "&snapshotid=" + s_snapshot.get(); - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=createVolume&name=" + s_account.get() + "&snapshotid=" + s_snapshot.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Create volume from snapshot response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] { "id" }); - - if (values.get("id") == null) { - s_logger.info("create volume from snapshot response code: 401"); - return 401; - } else { - s_logger.info("create volume from snapshot response code: " + responseCode + ". Got volume with id " + values.get("id") + ". The command was sent with url " + url); - s_volumeFromSnapshot.set(values.get("id")); - } - } else { - s_logger.error("create volume from snapshot failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - { - url = server + "?command=attachVolume&id=" + s_volumeFromSnapshot.get() + "&virtualmachineid=" + s_linuxVmId.get(); - s_logger.info("Attaching volume with id " + s_volumeFromSnapshot.get() + " to the vm " + s_linuxVmId.get()); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Attach volume from snapshot to linux vm response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - s_logger.info("The volume created from snapshot was attached successfully to linux vm"); - } else { - s_logger.error("Attach volume created from snapshot failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - */ - // ----------------------------- - // Execute reboot/stop/start commands for the VMs before deleting the account - made to exercise xen - // ----------------------------- - - // Reboot windows VM - requestToSign = "apikey=" + encodedApiKey + "&command=rebootVirtualMachine&id=" + s_windowsVmId.get(); - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=rebootVirtualMachine&id=" + s_windowsVmId.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Reboot windows Vm response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(el, new String[] {"success"}); - s_logger.info("Windows VM was rebooted with the status: " + success.get("success")); - } else { - s_logger.error("Reboot windows VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // Stop centos VM - requestToSign = "apikey=" + encodedApiKey + "&command=stopVirtualMachine&id=" + s_linuxVmId.get(); - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=stopVirtualMachine&id=" + s_linuxVmId.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Stop linux Vm response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(el, new String[] {"success"}); - s_logger.info("Linux VM was stopped with the status: " + success.get("success")); - } else { - s_logger.error("Stop linux VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // Create private template from root disk volume - requestToSign = - "apikey=" + encodedApiKey + "&command=createTemplate" + "&displaytext=" + s_account.get() + "&name=" + s_account.get() + "&ostypeid=11" + "&snapshotid=" + - s_snapshot.get(); - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = - developerServer + "?command=createTemplate" + "&displaytext=" + s_account.get() + "&name=" + s_account.get() + "&ostypeid=11" + "&snapshotid=" + - s_snapshot.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Create private template response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map values = getSingleValueFromXML(el, new String[] {"id"}); - - if (values.get("id") == null) { - s_logger.info("create private template response code: 401"); - return 401; - } else { - s_logger.info("create private template response code: " + responseCode); - } - } else { - s_logger.error("create private template failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // Start centos VM - requestToSign = "apikey=" + encodedApiKey + "&command=startVirtualMachine&id=" + s_windowsVmId.get(); - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=startVirtualMachine&id=" + s_windowsVmId.get() + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Start linux Vm response code: " + responseCode); - if (responseCode != 200) { - s_logger.error("Start linux VM test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // get domainRouter id - { - url = server + "?command=listRouters&zoneid=" + zoneId + "&account=" + s_account.get() + "&domainid=1"; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("List domain routers response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"id"}); - s_logger.info("Got the domR with id " + success.get("id")); - s_domainRouterId.set(success.get("id")); - } else { - s_logger.error("List domain routers failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // reboot the domain router - { - url = server + "?command=rebootRouter&id=" + s_domainRouterId.get(); - s_logger.info("Rebooting domR with id " + s_domainRouterId.get()); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("Reboot domain router response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - s_logger.info("Domain router was rebooted successfully"); - } else { - s_logger.error("Reboot domain routers failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - - // ----------------------------- - // DELETE ACCOUNT - // ----------------------------- - { - url = server + "?command=deleteAccount&id=" + s_accountId.get(); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("delete account response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - s_logger.info("Deleted account successfully"); - } else { - s_logger.error("delete account failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - return responseCode; - } - - private static int executeEventsAndBilling(String server, String developerServer) throws HttpException, IOException { - // test steps: - // - get all the events in the system for all users in the system - // - generate all the usage records in the system - // - get all the usage records in the system - - // ----------------------------- - // GET EVENTS - // ----------------------------- - String url = server + "?command=listEvents&page=1&pagesize=100&&account=" + s_account.get(); - - s_logger.info("Getting events for the account " + s_account.get()); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("get events response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> eventDescriptions = getMultipleValuesFromXML(is, new String[] {"description"}); - List descriptionText = eventDescriptions.get("description"); - if (descriptionText == null) { - s_logger.info("no events retrieved..."); - } else { - for (String text : descriptionText) { - s_logger.info("event: " + text); - } - } - } else { - s_logger.error("list events failed with error code: " + responseCode + ". Following URL was sent: " + url); - - return responseCode; - } - - // ------------------------------------------------------------------------------------- - // GENERATE USAGE RECORDS (note: typically this is done infrequently) - // ------------------------------------------------------------------------------------- - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); - Date currentDate = new Date(); - String endDate = dateFormat.format(currentDate); - s_logger.info("Generating usage records from September 1st till " + endDate); - url = server + "?command=generateUsageRecords&startdate=2009-09-01&enddate=" + endDate; // generate - // all usage record till today - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("generate usage records response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map successStr = getSingleValueFromXML(is, new String[] {"success"}); - s_logger.info("successfully generated usage records? " + successStr.get("success")); - } else { - s_logger.error("generate usage records failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // Sleeping for a 2 minutes before getting a usage records from the database - try { - Thread.sleep(120000); - } catch (Exception ex) { - s_logger.error(ex); - } - - // -------------------------------- - // GET USAGE RECORDS - // -------------------------------- - url = server + "?command=listUsageRecords&startdate=2009-09-01&enddate=" + endDate + "&account=" + s_account.get() + "&domaindid=1"; - s_logger.info("Getting all usage records with request: " + url); - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("get usage records response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> usageRecValues = getMultipleValuesFromXML(is, new String[] {"description", "usage"}); - if ((usageRecValues.containsKey("description") == true) && (usageRecValues.containsKey("usage") == true)) { - List descriptions = usageRecValues.get("description"); - List usages = usageRecValues.get("usage"); - for (int i = 0; i < descriptions.size(); i++) { - String desc = descriptions.get(i); - String usage = ""; - if (usages != null) { - if (i < usages.size()) { - usage = ", usage: " + usages.get(i); - } - } - s_logger.info("desc: " + desc + usage); - } - } - - } else { - s_logger.error("list usage records failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - return responseCode; - } - - private static boolean getNetworkStat(String server) { - try { - String url = server + "?command=listAccountStatistics&account=" + s_account.get(); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("listAccountStatistics response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map requestKeyValues = getSingleValueFromXML(is, new String[] {"receivedbytes", "sentbytes"}); - int bytesReceived = Integer.parseInt(requestKeyValues.get("receivedbytes")); - int bytesSent = Integer.parseInt(requestKeyValues.get("sentbytes")); - if ((bytesReceived > 100000000) && (bytesSent > 0)) { - s_logger.info("Network stat is correct for account" + s_account.get() + "; bytest received is " + toHumanReadableSize(bytesReceived) + " and bytes sent is " + toHumanReadableSize(bytesSent)); - return true; - } else { - s_logger.error("Incorrect value for bytes received/sent for the account " + s_account.get() + ". We got " + toHumanReadableSize(bytesReceived) + " bytes received; " + - " and " + toHumanReadableSize(bytesSent) + " bytes sent"); - return false; - } - - } else { - s_logger.error("listAccountStatistics failed with error code: " + responseCode + ". Following URL was sent: " + url); - return false; - } - } catch (Exception ex) { - s_logger.error("Exception while sending command listAccountStatistics"); - return false; - } - } - - private static int executeStop(String server, String developerServer, String username, boolean destroy) throws HttpException, IOException { - // test steps: - // - get userId for the given username - // - list virtual machines for the user - // - stop all virtual machines - // - get ip addresses for the user - // - release ip addresses - - // ----------------------------- - // GET USER - // ----------------------------- - String userId = s_userId.get().toString(); - String encodedUserId = URLEncoder.encode(userId, "UTF-8"); - - String url = server + "?command=listUsers&id=" + encodedUserId; - s_logger.info("Stopping resources for user: " + username); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - s_logger.info("get user response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map userIdValues = getSingleValueFromXML(is, new String[] {"id"}); - String userIdStr = userIdValues.get("id"); - if (userIdStr != null) { - userId = userIdStr; - - } else { - s_logger.error("get user failed to retrieve a valid user id, aborting depolyment test" + ". Following URL was sent: " + url); - return -1; - } - } else { - s_logger.error("get user failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - { - // ---------------------------------- - // LIST VIRTUAL MACHINES - // ---------------------------------- - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String requestToSign = "apikey=" + encodedApiKey + "&command=listVirtualMachines"; - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listVirtualMachines&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - - s_logger.info("Listing all virtual machines for the user with url " + url); - String[] vmIds = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list virtual machines response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> vmIdValues = getMultipleValuesFromXML(is, new String[] {"id"}); - if (vmIdValues.containsKey("id")) { - List vmIdList = vmIdValues.get("id"); - if (vmIdList != null) { - vmIds = new String[vmIdList.size()]; - vmIdList.toArray(vmIds); - String vmIdLogStr = ""; - if ((vmIds != null) && (vmIds.length > 0)) { - vmIdLogStr = vmIds[0]; - for (int i = 1; i < vmIds.length; i++) { - vmIdLogStr = vmIdLogStr + "," + vmIds[i]; - } - } - s_logger.info("got virtual machine ids: " + vmIdLogStr); - } - } - - } else { - s_logger.error("list virtual machines test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // LIST USER IP ADDRESSES - // ---------------------------------- - - requestToSign = "apikey=" + encodedApiKey + "&command=listPublicIpAddresses"; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listPublicIpAddresses&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - String[] ipAddresses = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> ipAddressValues = getMultipleValuesFromXML(is, new String[] {"ipaddress"}); - if (ipAddressValues.containsKey("ipaddress")) { - List ipAddressList = ipAddressValues.get("ipaddress"); - if (ipAddressList != null) { - ipAddresses = new String[ipAddressList.size()]; - ipAddressList.toArray(ipAddresses); - String ipAddressLogStr = ""; - if ((ipAddresses != null) && (ipAddresses.length > 0)) { - ipAddressLogStr = ipAddresses[0]; - for (int i = 1; i < ipAddresses.length; i++) { - ipAddressLogStr = ipAddressLogStr + "," + ipAddresses[i]; - } - } - s_logger.info("got IP addresses: " + ipAddressLogStr); - } - } - - } else { - s_logger.error("list user ip addresses failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // LIST ZONES - // ---------------------------------- - - requestToSign = "apikey=" + encodedApiKey + "&command=listZones"; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listZones&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - String[] zoneNames = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list zones response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> zoneNameValues = getMultipleValuesFromXML(is, new String[] {"name"}); - if (zoneNameValues.containsKey("name")) { - List zoneNameList = zoneNameValues.get("name"); - if (zoneNameList != null) { - zoneNames = new String[zoneNameList.size()]; - zoneNameList.toArray(zoneNames); - String zoneNameLogStr = "\n\n"; - if ((zoneNames != null) && (zoneNames.length > 0)) { - zoneNameLogStr += zoneNames[0]; - for (int i = 1; i < zoneNames.length; i++) { - zoneNameLogStr = zoneNameLogStr + "\n" + zoneNames[i]; - } - - } - zoneNameLogStr += "\n\n"; - s_logger.info("got zones names: " + zoneNameLogStr); - } - } - - } else { - s_logger.error("list zones failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // LIST ACCOUNT STATISTICS - // ---------------------------------- - - requestToSign = "apikey=" + encodedApiKey + "&command=listAccounts"; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listAccounts&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - String[] statNames = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("listAccountStatistics response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> statValues = getMultipleValuesFromXML(is, new String[] {"receivedbytes"}); - if (statValues.containsKey("receivedbytes")) { - List statList = statValues.get("receivedbytes"); - if (statList != null) { - statNames = new String[statList.size()]; - statList.toArray(statNames); - String statLogStr = "\n\n"; - if ((statNames != null) && (zoneNames.length > 0)) { - statLogStr += statNames[0]; - for (int i = 1; i < statNames.length; i++) { - statLogStr = statLogStr + "\n" + zoneNames[i]; - } - - } - statLogStr += "\n\n"; - s_logger.info("got accountstatistics: " + statLogStr); - } - } - - } else { - s_logger.error("listAccountStatistics failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // LIST TEMPLATES - // ---------------------------------- - - requestToSign = "apikey=" + encodedApiKey + "&command=listTemplates@templatefilter=self"; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listTemplates&apikey=" + encodedApiKey + "&templatefilter=self&signature=" + encodedSignature; - String[] templateNames = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list templates response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> templateNameValues = getMultipleValuesFromXML(is, new String[] {"name"}); - - if (templateNameValues.containsKey("name")) { - List templateNameList = templateNameValues.get("name"); - if (templateNameList != null) { - templateNames = new String[templateNameList.size()]; - templateNameList.toArray(templateNames); - String templateNameLogStr = "\n\n"; - if ((templateNames != null) && (templateNames.length > 0)) { - templateNameLogStr += templateNames[0]; - for (int i = 1; i < templateNames.length; i++) { - templateNameLogStr = templateNameLogStr + "\n" + templateNames[i]; - } - - } - templateNameLogStr += "\n\n"; - s_logger.info("got template names: " + templateNameLogStr); - } - } - - } else { - s_logger.error("list templates failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // LIST SERVICE OFFERINGS - // ---------------------------------- - - requestToSign = "apikey=" + encodedApiKey + "&command=listServiceOfferings"; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listServiceOfferings&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - String[] serviceOfferingNames = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list service offerings response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> serviceOfferingNameValues = getMultipleValuesFromXML(is, new String[] {"name"}); - - if (serviceOfferingNameValues.containsKey("name")) { - List serviceOfferingNameList = serviceOfferingNameValues.get("name"); - if (serviceOfferingNameList != null) { - serviceOfferingNames = new String[serviceOfferingNameList.size()]; - serviceOfferingNameList.toArray(serviceOfferingNames); - String serviceOfferingNameLogStr = ""; - if ((serviceOfferingNames != null) && (serviceOfferingNames.length > 0)) { - serviceOfferingNameLogStr = serviceOfferingNames[0]; - for (int i = 1; i < serviceOfferingNames.length; i++) { - serviceOfferingNameLogStr = serviceOfferingNameLogStr + ", " + serviceOfferingNames[i]; - } - } - s_logger.info("got service offering names: " + serviceOfferingNameLogStr); - } - } - - } else { - s_logger.error("list service offerings failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // LIST EVENTS - // --------------------------------- - - url = server + "?command=listEvents&page=1&pagesize=100&&account=" + s_account.get(); - String[] eventDescriptions = null; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list events response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map> eventNameValues = getMultipleValuesFromXML(is, new String[] {"description"}); - - if (eventNameValues.containsKey("description")) { - List eventNameList = eventNameValues.get("description"); - if (eventNameList != null) { - eventDescriptions = new String[eventNameList.size()]; - eventNameList.toArray(eventDescriptions); - String eventNameLogStr = "\n\n"; - if ((eventDescriptions != null) && (eventDescriptions.length > 0)) { - eventNameLogStr += eventDescriptions[0]; - for (int i = 1; i < eventDescriptions.length; i++) { - eventNameLogStr = eventNameLogStr + "\n" + eventDescriptions[i]; - } - } - eventNameLogStr += "\n\n"; - s_logger.info("got event descriptions: " + eventNameLogStr); - } - } - } else { - s_logger.error("list events failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ---------------------------------- - // STOP/DESTROY VIRTUAL MACHINES - // ---------------------------------- - if (vmIds != null) { - String cmdName = (destroy ? "destroyVirtualMachine" : "stopVirtualMachine"); - for (String vmId : vmIds) { - requestToSign = "apikey=" + encodedApiKey + "&command=" + cmdName + "&id=" + vmId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=" + cmdName + "&id=" + vmId + "&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info(cmdName + " [" + vmId + "] response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(el, new String[] {"success"}); - s_logger.info(cmdName + "..success? " + success.get("success")); - } else { - s_logger.error(cmdName + "test failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - } - } - - { - String[] ipAddresses = null; - // ----------------------------------------- - // LIST NAT IP ADDRESSES - // ----------------------------------------- - String encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String requestToSign = "apikey=" + encodedApiKey + "&command=listPublicIpAddresses"; - requestToSign = requestToSign.toLowerCase(); - String signature = signRequest(requestToSign, s_secretKey.get()); - String encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=listPublicIpAddresses&apikey=" + encodedApiKey + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); - if (responseCode == 200) { - - InputStream is = method.getResponseBodyAsStream(); - List ipAddressList = getNonSourceNatIPs(is); - ipAddresses = new String[ipAddressList.size()]; - ipAddressList.toArray(ipAddresses); - String ipAddrLogStr = ""; - if ((ipAddresses != null) && (ipAddresses.length > 0)) { - ipAddrLogStr = ipAddresses[0]; - for (int i = 1; i < ipAddresses.length; i++) { - ipAddrLogStr = ipAddrLogStr + "," + ipAddresses[i]; - } - } - s_logger.info("got ip addresses: " + ipAddrLogStr); - - } else { - s_logger.error("list nat ip addresses failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ------------------------------------------------------------- - // Delete IP FORWARDING RULE -- Windows VM - // ------------------------------------------------------------- - String encodedIpFwdId = URLEncoder.encode(s_winipfwdid.get(), "UTF-8"); - - requestToSign = "apikey=" + encodedApiKey + "&command=deleteIpForwardingRule&id=" + encodedIpFwdId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=deleteIpForwardingRule&apikey=" + encodedApiKey + "&id=" + encodedIpFwdId + "&signature=" + encodedSignature; - - s_logger.info("Delete Ip forwarding rule with " + url); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element el = queryAsyncJobResult(server, input); - s_logger.info("IP forwarding rule was successfully deleted"); - - } else { - s_logger.error("IP forwarding rule creation failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - //-------------------------------------------- - // Disable Static NAT for the Source NAT Ip - //-------------------------------------------- - encodedApiKey = URLEncoder.encode(s_apiKey.get(), "UTF-8"); - String encodedPublicIpId = URLEncoder.encode(s_publicIpId.get(), "UTF-8"); - requestToSign = "apikey=" + encodedApiKey + "&command=disableStaticNat" + "&id=" + encodedPublicIpId; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=disableStaticNat&apikey=" + encodedApiKey + "&id=" + encodedPublicIpId + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("url is " + url); - s_logger.info("list ip addresses for user " + userId + " response code: " + responseCode); - if (responseCode == 200) { - InputStream is = method.getResponseBodyAsStream(); - Map success = getSingleValueFromXML(is, new String[] {"success"}); - s_logger.info("Disable Static NAT..success? " + success.get("success")); - } else { - s_logger.error("Disable Static NAT failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - - // ----------------------------------------- - // DISASSOCIATE IP ADDRESSES - // ----------------------------------------- - if (ipAddresses != null) { - for (String ipAddress : ipAddresses) { - requestToSign = "apikey=" + encodedApiKey + "&command=disassociateIpAddress&id=" + ipAddress; - requestToSign = requestToSign.toLowerCase(); - signature = signRequest(requestToSign, s_secretKey.get()); - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - - url = developerServer + "?command=disassociateIpAddress&apikey=" + encodedApiKey + "&id=" + ipAddress + "&signature=" + encodedSignature; - client = new HttpClient(); - method = new GetMethod(url); - responseCode = client.executeMethod(method); - s_logger.info("disassociate ip address [" + userId + "/" + ipAddress + "] response code: " + responseCode); - if (responseCode == 200) { - InputStream input = method.getResponseBodyAsStream(); - Element disassocipel = queryAsyncJobResult(server, input); - Map success = getSingleValueFromXML(disassocipel, new String[] {"success"}); - // Map success = getSingleValueFromXML(input, new String[] { "success" }); - s_logger.info("disassociate ip address..success? " + success.get("success")); - } else { - s_logger.error("disassociate ip address failed with error code: " + responseCode + ". Following URL was sent: " + url); - return responseCode; - } - } - } - } - s_linuxIP.set(""); - s_linuxIpId.set(""); - s_linuxVmId.set(""); - s_linuxPassword.set(""); - s_windowsIP.set(""); - s_windowsIpId.set(""); - s_windowsVmId.set(""); - s_secretKey.set(""); - s_apiKey.set(""); - s_userId.set(Long.parseLong("0")); - s_account.set(""); - s_domainRouterId.set(""); - return responseCode; - } - - public static String signRequest(String request, String key) { - try { - Mac mac = Mac.getInstance("HmacSHA1"); - SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1"); - mac.init(keySpec); - mac.update(request.getBytes()); - byte[] encryptedBytes = mac.doFinal(); - return org.apache.commons.codec.binary.Base64.encodeBase64String(encryptedBytes); - } catch (Exception ex) { - s_logger.error("unable to sign request", ex); - } - return null; - } - - private static String sshWinTest(String host) { - if (host == null) { - s_logger.info("Did not receive a host back from test, ignoring win ssh test"); - return null; - } - - // We will retry 5 times before quitting - int retry = 1; - - while (true) { - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 300 seconds before next attempt. Account is " + s_account.get()); - Thread.sleep(300000); - } - - s_logger.info("Attempting to SSH into windows host " + host + " with retry attempt: " + retry + " for account " + s_account.get()); - - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("User " + s_account.get() + " ssHed successfully into windows host " + host); - boolean success = false; - boolean isAuthenticated = conn.authenticateWithPassword("Administrator", "password"); - if (isAuthenticated == false) { - return "Authentication failed"; - } else { - s_logger.info("Authentication is successful"); - } - - try { - SCPClient scp = new SCPClient(conn); - scp.put("wget.exe", "wget.exe", "C:\\Users\\Administrator", "0777"); - s_logger.info("Successfully put wget.exe file"); - } catch (Exception ex) { - s_logger.error("Unable to put wget.exe " + ex); - } - - if (conn == null) { - s_logger.error("Connection is null"); - } - Session sess = conn.openSession(); - - s_logger.info("User + " + s_account.get() + " executing : wget http://" + downloadUrl); - String downloadCommand = "wget http://" + downloadUrl + " && dir dump.bin"; - sess.execCommand(downloadCommand); - - InputStream stdout = sess.getStdout(); - InputStream stderr = sess.getStderr(); - - byte[] buffer = new byte[8192]; - while (true) { - if ((stdout.available() == 0) && (stderr.available() == 0)) { - int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); - - if ((conditions & ChannelCondition.TIMEOUT) != 0) { - s_logger.info("Timeout while waiting for data from peer."); - return null; - } - - if ((conditions & ChannelCondition.EOF) != 0) { - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { - break; - } - } - } - - while (stdout.available() > 0) { - success = true; - int len = stdout.read(buffer); - if (len > 0) // this check is somewhat paranoid - s_logger.info(new String(buffer, 0, len)); - } - - while (stderr.available() > 0) { - /* int len = */stderr.read(buffer); - } - } - sess.close(); - conn.close(); - - if (success) { - return null; - } else { - retry++; - if (retry == MAX_RETRY_WIN) { - return "SSH Windows Network test fail for account " + s_account.get(); - } - } - } catch (Exception e) { - s_logger.error(e); - retry++; - if (retry == MAX_RETRY_WIN) { - return "SSH Windows Network test fail with error " + e.getMessage(); - } - } - } - } - - private static String sshTest(String host, String password, String snapshotTest) { - int i = 0; - if (host == null) { - s_logger.info("Did not receive a host back from test, ignoring ssh test"); - return null; - } - - if (password == null) { - s_logger.info("Did not receive a password back from test, ignoring ssh test"); - return null; - } - - // We will retry 5 times before quitting - String result = null; - int retry = 0; - - while (true) { - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt. Account is " + s_account.get()); - Thread.sleep(120000); - } - - s_logger.info("Attempting to SSH into linux host " + host + " with retry attempt: " + retry + ". Account is " + s_account.get()); - - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("User + " + s_account.get() + " ssHed successfully into linux host " + host); - - boolean isAuthenticated = conn.authenticateWithPassword("root", password); - - if (isAuthenticated == false) { - s_logger.info("Authentication failed for root with password" + password); - return "Authentication failed"; - - } - - boolean success = false; - String linuxCommand = null; - - if (i % 10 == 0) - linuxCommand = "rm -rf *; wget http://" + downloadUrl + " && ls -al dump.bin"; - else - linuxCommand = "wget http://" + downloadUrl + " && ls -al dump.bin"; - - Session sess = conn.openSession(); - s_logger.info("User " + s_account.get() + " executing : " + linuxCommand); - sess.execCommand(linuxCommand); - - InputStream stdout = sess.getStdout(); - InputStream stderr = sess.getStderr(); - - byte[] buffer = new byte[8192]; - while (true) { - if ((stdout.available() == 0) && (stderr.available() == 0)) { - int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); - - if ((conditions & ChannelCondition.TIMEOUT) != 0) { - s_logger.info("Timeout while waiting for data from peer."); - return null; - } - - if ((conditions & ChannelCondition.EOF) != 0) { - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { - break; - } - } - } - - while (stdout.available() > 0) { - success = true; - int len = stdout.read(buffer); - if (len > 0) // this check is somewhat paranoid - s_logger.info(new String(buffer, 0, len)); - } - - while (stderr.available() > 0) { - /* int len = */stderr.read(buffer); - } - } - - sess.close(); - conn.close(); - - if (!success) { - retry++; - if (retry == MAX_RETRY_LINUX) { - result = "SSH Linux Network test fail"; - } - } - - if (snapshotTest.equals("no")) - return result; - else { - Long sleep = 300000L; - s_logger.info("Sleeping for " + sleep / 1000 / 60 + "minutes before executing next ssh test"); - Thread.sleep(sleep); - } - } catch (Exception e) { - retry++; - s_logger.error("SSH Linux Network test fail with error"); - if ((retry == MAX_RETRY_LINUX) && (snapshotTest.equals("no"))) { - return "SSH Linux Network test fail with error " + e.getMessage(); - } - } - i++; - } - } - - public static String createMD5Password(String password) { - MessageDigest md5; - - try { - md5 = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - throw new CloudRuntimeException("Error", e); - } - - md5.reset(); - BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes())); - - // make sure our MD5 hash value is 32 digits long... - StringBuffer sb = new StringBuffer(); - String pwStr = pwInt.toString(16); - int padding = 32 - pwStr.length(); - for (int i = 0; i < padding; i++) { - sb.append('0'); - } - sb.append(pwStr); - return sb.toString(); - } - - public static Element queryAsyncJobResult(String host, InputStream inputStream) { - Element returnBody = null; - - Map values = getSingleValueFromXML(inputStream, new String[] {"jobid"}); - String jobId = values.get("jobid"); - - if (jobId == null) { - s_logger.error("Unable to get a jobId"); - return null; - } - - // s_logger.info("Job id is " + jobId); - String resultUrl = host + "?command=queryAsyncJobResult&jobid=" + jobId; - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(resultUrl); - while (true) { - try { - client.executeMethod(method); - // s_logger.info("Method is executed successfully. Following url was sent " + resultUrl); - InputStream is = method.getResponseBodyAsStream(); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(is); - returnBody = doc.getDocumentElement(); - doc.getDocumentElement().normalize(); - Element jobStatusTag = (Element)returnBody.getElementsByTagName("jobstatus").item(0); - String jobStatus = jobStatusTag.getTextContent(); - if (jobStatus.equals("0")) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - s_logger.debug("[ignored] interrupted while during async job result query."); - } - } else { - break; - } - - } catch (Exception ex) { - s_logger.error(ex); - } - } - return returnBody; - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/stress/WgetTest.java b/test/src-not-used/main/java/com/cloud/test/stress/WgetTest.java deleted file mode 100644 index 91885568447..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/stress/WgetTest.java +++ /dev/null @@ -1,150 +0,0 @@ -// 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. -package com.cloud.test.stress; - -import java.io.InputStream; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -import org.apache.log4j.Logger; - -import com.trilead.ssh2.ChannelCondition; -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.Session; - -public class WgetTest { - - public static final int MAX_RETRY_LINUX = 1; - public static final Logger s_logger = Logger.getLogger(WgetTest.class.getName()); - public static String host = ""; - public static String password = "rs-ccb35ea5"; - - public static void main(String[] args) { - - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - // host - if (arg.equals("-h")) { - host = iter.next(); - } - //password - - if (arg.equals("-p")) { - password = iter.next(); - } - - } - - int i = 0; - if (host == null || host.equals("")) { - s_logger.info("Did not receive a host back from test, ignoring ssh test"); - System.exit(2); - } - - if (password == null) { - s_logger.info("Did not receive a password back from test, ignoring ssh test"); - System.exit(2); - } - int retry = 0; - - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt"); - Thread.sleep(120000); - } - - s_logger.info("Attempting to SSH into linux host " + host + " with retry attempt: " + retry); - - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("User + ssHed successfully into linux host " + host); - - boolean isAuthenticated = conn.authenticateWithPassword("root", password); - - if (isAuthenticated == false) { - s_logger.info("Authentication failed for root with password" + password); - System.exit(2); - } - - boolean success = false; - String linuxCommand = null; - - if (i % 10 == 0) - linuxCommand = "rm -rf *; wget http://192.168.1.250/dump.bin && ls -al dump.bin"; - else - linuxCommand = "wget http://192.168.1.250/dump.bin && ls -al dump.bin"; - - Session sess = conn.openSession(); - sess.execCommand(linuxCommand); - - InputStream stdout = sess.getStdout(); - InputStream stderr = sess.getStderr(); - - byte[] buffer = new byte[8192]; - while (true) { - if ((stdout.available() == 0) && (stderr.available() == 0)) { - int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); - - if ((conditions & ChannelCondition.TIMEOUT) != 0) { - s_logger.info("Timeout while waiting for data from peer."); - System.exit(2); - } - - if ((conditions & ChannelCondition.EOF) != 0) { - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { - break; - } - } - } - - while (stdout.available() > 0) { - success = true; - int len = stdout.read(buffer); - if (len > 0) // this check is somewhat paranoid - s_logger.info(new String(buffer, 0, len)); - } - - while (stderr.available() > 0) { - /* int len = */stderr.read(buffer); - } - } - - sess.close(); - conn.close(); - - if (!success) { - retry++; - if (retry == MAX_RETRY_LINUX) { - System.exit(2); - } - } - } catch (Exception e) { - retry++; - s_logger.error("SSH Linux Network test fail with error"); - if (retry == MAX_RETRY_LINUX) { - s_logger.error("Ssh test failed"); - System.exit(2); - } - } - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/ui/AbstractSeleniumTestCase.java b/test/src-not-used/main/java/com/cloud/test/ui/AbstractSeleniumTestCase.java deleted file mode 100644 index f9e678e2529..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/ui/AbstractSeleniumTestCase.java +++ /dev/null @@ -1,55 +0,0 @@ -// 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. -package com.cloud.test.ui; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.openqa.selenium.server.RemoteControlConfiguration; -import org.openqa.selenium.server.SeleniumServer; - -import com.thoughtworks.selenium.DefaultSelenium; - -@RunWith(JUnit4.class) -public abstract class AbstractSeleniumTestCase { - protected static DefaultSelenium selenium; - private static SeleniumServer seleniumServer; - - @BeforeClass - public static void setUp() throws Exception { - System.out.println("*** Starting selenium ... ***"); - RemoteControlConfiguration seleniumConfig = new RemoteControlConfiguration(); - seleniumConfig.setPort(4444); - seleniumServer = new SeleniumServer(seleniumConfig); - seleniumServer.start(); - - String host = System.getProperty("myParam", "localhost"); - selenium = createSeleniumClient("http://" + host + ":" + "8080/client/"); - selenium.start(); - System.out.println("*** Started selenium ***"); - } - - @AfterClass - public static void tearDown() throws Exception { - selenium.stop(); - } - - protected static DefaultSelenium createSeleniumClient(String url) throws Exception { - return new DefaultSelenium("localhost", 4444, "*firefox", url); - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteAISO.java b/test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteAISO.java deleted file mode 100644 index 1998ae7c8ef..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteAISO.java +++ /dev/null @@ -1,127 +0,0 @@ -// 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. -package com.cloud.test.ui; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import org.junit.Test; - -import com.thoughtworks.selenium.SeleniumException; - -public class AddAndDeleteAISO extends AbstractSeleniumTestCase { - - @Test - public void testAddAndDeleteISO() throws Exception { - try { - selenium.open("/client/"); - selenium.type("account_username", "admin"); - selenium.type("account_password", "password"); - selenium.click("loginbutton"); - Thread.sleep(3000); - assertTrue(selenium.isTextPresent("admin")); - selenium.click("//div[@id='leftmenu_templates']/div"); - selenium.click("//div[@id='leftmenu_submenu_my_iso']/div/div[2]"); - Thread.sleep(3000); - selenium.click("label"); - - selenium.type("add_iso_name", "abc"); - selenium.type("add_iso_display_text", "abc"); - String iso_url = System.getProperty("add_iso_url", "http://10.91.28.6/ISO/Fedora-11-i386-DVD.iso"); - selenium.type("add_iso_url", iso_url); - String iso_zone = System.getProperty("add_iso_zone", "All Zones"); - selenium.select("add_iso_zone", "label=" + iso_zone); - String iso_os_type = System.getProperty("add_iso_os_type", "Fedora 11"); - selenium.select("add_iso_os_type", "label=" + iso_os_type); - selenium.click("//div[28]/div[11]/button[1]"); - Thread.sleep(3000); - int i = 1; - try { - for (;; i++) { - System.out.println("i= " + i); - selenium.click("//div[" + i + "]/div/div[2]/span/span"); - } - } catch (Exception ex) { - s_logger.info("[ignored]" - + "error during clicking test on iso: " + e.getLocalizedMessage()); - } - - for (int second = 0;; second++) { - if (second >= 60) - fail("timeout"); - try { - if (selenium.isVisible("//div[@id='after_action_info_container_on_top']")) - break; - } catch (Exception e) { - s_logger.info("[ignored]" - + "error during visibility test of iso: " + e.getLocalizedMessage()); - } - Thread.sleep(10000); - } - - assertTrue(selenium.isTextPresent("Adding succeeded")); - Thread.sleep(3000); - int status = 1; - while (!selenium.isTextPresent("Ready")) { - for (int j = 1; j <= i; j++) - - { - if (selenium.isTextPresent("Ready")) { - status = 0; - break; - } - selenium.click("//div[" + j + "]/div/div[2]/span/span"); - } - if (status == 0) { - break; - } else { - selenium.click("//div[@id='leftmenu_submenu_featured_iso']/div/div[2]"); - Thread.sleep(3000); - selenium.click("//div[@id='leftmenu_submenu_my_iso']/div/div[2]"); - Thread.sleep(3000); - } - - } - selenium.click("link=Delete ISO"); - selenium.click("//div[28]/div[11]/button[1]"); - for (int second = 0;; second++) { - if (second >= 60) - fail("timeout"); - try { - if (selenium.isVisible("after_action_info_container_on_top")) - break; - } catch (Exception e) { - s_logger.info("[ignored]" - + "error checking visibility after test completion for iso: " + e.getLocalizedMessage()); - } - Thread.sleep(1000); - } - - assertTrue(selenium.isTextPresent("Delete ISO action succeeded")); - selenium.click("main_logout"); - selenium.waitForPageToLoad("30000"); - assertTrue(selenium.isTextPresent("Welcome to Management Console")); - - } catch (SeleniumException ex) { - - System.err.println(ex.getMessage()); - fail(ex.getMessage()); - - throw ex; - } - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteATemplate.java b/test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteATemplate.java deleted file mode 100644 index 3a3264e9cf1..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteATemplate.java +++ /dev/null @@ -1,126 +0,0 @@ -// 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. -package com.cloud.test.ui; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import org.junit.Test; - -import com.thoughtworks.selenium.SeleniumException; - -public class AddAndDeleteATemplate extends AbstractSeleniumTestCase { - - @Test - public void testAddAndDeleteTemplate() throws Exception { - try { - selenium.open("/client/"); - selenium.type("account_username", "admin"); - selenium.type("account_password", "password"); - selenium.click("loginbutton"); - Thread.sleep(3000); - assertTrue(selenium.isTextPresent("admin")); - selenium.click("//div[@id='leftmenu_templates']/div"); - selenium.click("//div[@id='leftmenu_submenu_my_template']/div/div[2]"); - Thread.sleep(3000); - selenium.click("label"); - selenium.type("add_template_name", "abc"); - selenium.type("add_template_display_text", "abc"); - String template_url = - System.getProperty("add_template_url", "http://10.91.28.6/templates/centos53-x86_64/latest/f59f18fb-ae94-4f97-afd2-f84755767aca.vhd.bz2"); - selenium.type("add_template_url", template_url); - String template_zone = System.getProperty("add_template_zone", "All Zones"); - selenium.select("add_template_zone", "label=" + template_zone); - String template_os_type = System.getProperty("add_template_os_type", "CentOS 5.3 (32-bit)"); - selenium.select("add_template_os_type", "label=" + template_os_type); - selenium.click("//div[28]/div[11]/button[1]"); - Thread.sleep(3000); - int i = 1; - try { - for (;; i++) { - System.out.println("i= " + i); - selenium.click("//div[" + i + "]/div/div[2]/span/span"); - } - } catch (Exception ex) { - s_logger.info("[ignored]" - + "error during clicking test on template: " + ex.getLocalizedMessage()); - } - - for (int second = 0;; second++) { - if (second >= 60) - fail("timeout"); - try { - if (selenium.isVisible("//div[@id='after_action_info_container_on_top']")) - break; - } catch (Exception e) { - s_logger.info("[ignored]" - + "error during visibility test of template: " + e.getLocalizedMessage()); - } - Thread.sleep(10000); - } - - assertTrue(selenium.isTextPresent("Adding succeeded")); - Thread.sleep(3000); - int status = 1; - while (!selenium.isTextPresent("Ready")) { - for (int j = 1; j <= i; j++) - - { - if (selenium.isTextPresent("Ready")) { - status = 0; - break; - } - selenium.click("//div[" + j + "]/div/div[2]/span/span"); - } - if (status == 0) { - break; - } else { - selenium.click("//div[@id='leftmenu_submenu_featured_template']/div/div[2]"); - Thread.sleep(3000); - selenium.click("//div[@id='leftmenu_submenu_my_template']/div/div[2]"); - Thread.sleep(3000); - } - - } - selenium.click("link=Delete Template"); - selenium.click("//div[28]/div[11]/button[1]"); - for (int second = 0;; second++) { - if (second >= 60) - fail("timeout"); - try { - if (selenium.isVisible("after_action_info_container_on_top")) - break; - } catch (Exception e) { - s_logger.info("[ignored]" - + "error checking visibility after test completion for template: " + e.getLocalizedMessage()); - } - Thread.sleep(1000); - } - - assertTrue(selenium.isTextPresent("Delete Template action succeeded")); - selenium.click("main_logout"); - selenium.waitForPageToLoad("30000"); - assertTrue(selenium.isTextPresent("Welcome to Management Console")); - } catch (SeleniumException ex) { - - System.err.println(ex.getMessage()); - fail(ex.getMessage()); - - throw ex; - } - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/ui/UIScenarioTest.java b/test/src-not-used/main/java/com/cloud/test/ui/UIScenarioTest.java deleted file mode 100644 index 8fde7e37ea6..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/ui/UIScenarioTest.java +++ /dev/null @@ -1,86 +0,0 @@ -// 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. -package com.cloud.test.ui; - -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import org.junit.Test; - -import com.thoughtworks.selenium.SeleniumException; - -public class UIScenarioTest extends AbstractSeleniumTestCase { - - @Test - public void testLoginStartStopVMScenario() throws Exception { - try { - selenium.open("/client/"); - selenium.type("account_username", "admin"); - selenium.type("account_password", "password"); - selenium.click("loginbutton"); - Thread.sleep(3000); - assertTrue(selenium.isTextPresent("admin")); - selenium.click("//div[@id='leftmenu_instances']/div"); - selenium.click("//div[@id='leftmenu_instances_stopped_instances']/div/span"); - - Thread.sleep(3000); - selenium.click("//div[@id='midmenu_startvm_link']/div/div[2]"); - selenium.click("//div[39]/div[11]/button[1]"); - - for (int second = 0;; second++) { - if (second >= 60) - fail("timeout"); - try { - if (selenium.isVisible("//div/p[@id='after_action_info']")) - break; - } catch (Exception e) { - s_logger.info("[ignored]" - + "error during visibility test after start vm: " + e.getLocalizedMessage()); - } - Thread.sleep(10000); - } - assertTrue(selenium.isTextPresent("Start Instance action succeeded")); - selenium.click("//div[@id='leftmenu_instances_running_instances']/div/span"); - - Thread.sleep(3000); - selenium.click("//div[@id='midmenu_stopvm_link']/div/div[2]"); - selenium.click("//div[39]/div[11]/button[1]"); - for (int second = 0;; second++) { - if (second >= 60) - fail("timeout"); - try { - if (selenium.isVisible("//div/p[@id='after_action_info']")) - break; - } catch (Exception e) { - s_logger.info("[ignored]" - + "error during visibility test after stop vm: " + e.getLocalizedMessage()); - } - Thread.sleep(10000); - } - - assertTrue(selenium.isTextPresent("Stop Instance action succeeded")); - selenium.click("main_logout"); - selenium.waitForPageToLoad("30000"); - assertTrue(selenium.isTextPresent("Welcome to Management Console")); - - } catch (SeleniumException ex) { - fail(ex.getMessage()); - System.err.println(ex.getMessage()); - throw ex; - } - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/ConsoleProxy.java b/test/src-not-used/main/java/com/cloud/test/utils/ConsoleProxy.java deleted file mode 100644 index 8c10d75a5c1..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/ConsoleProxy.java +++ /dev/null @@ -1,110 +0,0 @@ -// 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. -package com.cloud.test.utils; - -import java.io.BufferedReader; -import java.io.IOException; - -import org.apache.log4j.Logger; - -import com.cloud.utils.script.OutputInterpreter; -import com.cloud.utils.script.Script; - -public class ConsoleProxy implements Runnable { - public static String proxyIp; - private String command; - private int connectionsMade; - private long responseTime; - public static final Logger s_logger = Logger.getLogger(ConsoleProxy.class.getClass()); - - public ConsoleProxy(String port, String sid, String host) { - this.command = "https://" + proxyIp + ".realhostip.com:8000/getscreen?w=100&h=75&host=" + host + "&port=" + port + "&sid=" + sid; - s_logger.info("Command for a console proxy is " + this.command); - this.connectionsMade = 0; - this.responseTime = 0; - } - - public int getConnectionsMade() { - return this.connectionsMade; - } - - public long getResponseTime() { - return this.responseTime; - } - - @Override - public void run() { - while (true) { - - Script myScript = new Script("wget"); - myScript.add(command); - myScript.execute(); - long begin = System.currentTimeMillis(); - WgetInt process = new WgetInt(); - String response = myScript.execute(process); - long end = process.getEnd(); - if (response != null) { - s_logger.info("Content lenght is incorrect: " + response); - } - - long duration = (end - begin); - this.connectionsMade++; - this.responseTime = this.responseTime + duration; - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - s_logger.debug("[ignored] interrupted."); - } - - } - } - - public class WgetInt extends OutputInterpreter { - private long end; - - public long getEnd() { - return end; - } - - public void setEnd(long end) { - this.end = end; - } - - @Override - public String interpret(BufferedReader reader) throws IOException { - // TODO Auto-generated method stub - end = System.currentTimeMillis(); - String status = null; - String line = null; - while ((line = reader.readLine()) != null) { - int index = line.indexOf("Length:"); - if (index == -1) { - continue; - } else { - int index1 = line.indexOf("Length: 1827"); - if (index1 == -1) { - return status; - } else - status = line; - } - - } - return status; - } - - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/IpSqlGenerator.java b/test/src-not-used/main/java/com/cloud/test/utils/IpSqlGenerator.java deleted file mode 100644 index c37d08b86ff..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/IpSqlGenerator.java +++ /dev/null @@ -1,89 +0,0 @@ -// 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. -package com.cloud.test.utils; - -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.util.StringTokenizer; - -public class IpSqlGenerator { - public static void main(String[] args) { - try { - if (args.length != 5) { - System.out.println("Usage -- generate-ip.sh "); - System.out.println("Example -- generate-ip.sh public 192.168.1.1 192.168.1.255 1 1"); - System.out.println(" will generate ips ranging from public ips 192.168.1.1 to 192.168.1.255 for dc 1 and pod 1"); - return; - } - - String type = args[0]; - - StringTokenizer st = new StringTokenizer(args[1], "."); - int ipS1 = Integer.parseInt(st.nextToken()); - int ipS2 = Integer.parseInt(st.nextToken()); - int ipS3 = Integer.parseInt(st.nextToken()); - int ipS4 = Integer.parseInt(st.nextToken()); - - st = new StringTokenizer(args[2], "."); - int ipE1 = Integer.parseInt(st.nextToken()); - int ipE2 = Integer.parseInt(st.nextToken()); - int ipE3 = Integer.parseInt(st.nextToken()); - int ipE4 = Integer.parseInt(st.nextToken()); - - String dcId = args[3]; - String podId = args[4]; - - if (type.equals("private")) { - FileOutputStream fs = new FileOutputStream(new File("private-ips.sql")); - DataOutputStream out = new DataOutputStream(fs); - for (int i = ipS1; i <= ipE1; i++) { - for (int j = ipS2; j <= ipE2; j++) { - for (int k = ipS3; k <= ipE3; k++) { - for (int l = ipS4; l <= ipE4; l++) { - out.writeBytes("INSERT INTO `vmops`.`dc_ip_address_alloc` (ip_address, data_center_id, pod_id) VALUES ('" + i + "." + j + "." + k + "." + - l + "'," + dcId + "," + podId + ");\r\n"); - } - } - } - } - out.writeBytes("\r\n"); - out.flush(); - out.close(); - } else { - FileOutputStream fs = new FileOutputStream(new File("public-ips.sql")); - DataOutputStream out = new DataOutputStream(fs); - for (int i = ipS1; i <= ipE1; i++) { - for (int j = ipS2; j <= ipE2; j++) { - for (int k = ipS3; k <= ipE3; k++) { - for (int l = ipS4; l <= ipE4; l++) { - out.writeBytes("INSERT INTO `vmops`.`user_ip_address` (ip_address, data_center_id) VALUES ('" + i + "." + j + "." + k + "." + l + "'," + - dcId + ");\r\n"); - } - } - } - } - out.writeBytes("\r\n"); - out.flush(); - out.close(); - } - } catch (Exception e) { - s_logger.info("[ignored]" - + "error during ip insert generator: " + e.getLocalizedMessage()); - } - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/ProxyLoadTemp.java b/test/src-not-used/main/java/com/cloud/test/utils/ProxyLoadTemp.java deleted file mode 100644 index f64b7d6b9e9..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/ProxyLoadTemp.java +++ /dev/null @@ -1,112 +0,0 @@ -// 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. -package com.cloud.test.utils; - -import java.io.BufferedReader; -import java.io.FileReader; -import java.util.ArrayList; - -import org.apache.log4j.Logger; - -public class ProxyLoadTemp { - public static final Logger s_logger = Logger.getLogger(ProxyLoadTemp.class.getClass()); - public static int numThreads = 0; - public static ArrayList proxyList = new ArrayList(); - public static long begin; - public static long end; - public static long sum = 0; - - public ProxyLoadTemp() { - } - - public static void main(String[] args) { - begin = System.currentTimeMillis(); - Runtime.getRuntime().addShutdownHook(new ShutdownThread(new ProxyLoadTemp())); - ConsoleProxy.proxyIp = "172-16-1-101"; - - try { - BufferedReader consoleInput = new BufferedReader(new FileReader("console.input")); - boolean eof = false; - s_logger.info("Started reading file"); - while (!eof) { - String line = consoleInput.readLine(); - s_logger.info("Line is " + line); - if (line == null) { - s_logger.info("Line " + numThreads + " is null"); - eof = true; - } else { - String[] result = null; - try { - s_logger.info("Starting parsing line " + line); - result = parseLine(line, "[,]"); - s_logger.info("Line retrieved from the file is " + result[0] + " " + result[1] + " " + result[2]); - ConsoleProxy proxy = new ConsoleProxy(result[0], result[1], result[2]); - proxyList.add(proxy); - new Thread(proxy).start(); - numThreads++; - - } catch (Exception ex) { - s_logger.warn(ex); - } - } - - } - } catch (Exception e) { - s_logger.warn(e); - } - - } - - public static class ShutdownThread extends Thread { - ProxyLoadTemp temp; - - public ShutdownThread(ProxyLoadTemp temp) { - this.temp = temp; - } - - @Override - public void run() { - s_logger.info("Program was running in " + numThreads + " threads"); - - for (int j = 0; j < proxyList.size(); j++) { - long av = 0; - if (proxyList.get(j).getConnectionsMade() != 0) { - av = proxyList.get(j).getResponseTime() / proxyList.get(j).getConnectionsMade(); - } - s_logger.info("Information for " + j + " thread: Number of requests sent is " + proxyList.get(j).getConnectionsMade() + ". Average response time is " + - av + " milliseconds"); - sum = sum + av; - - } - ProxyLoadTemp.end = System.currentTimeMillis(); - s_logger.info("Summary for all" + numThreads + " threads: Average response time is " + sum / numThreads + " milliseconds"); - s_logger.info("Test was running for " + (ProxyLoadTemp.end - ProxyLoadTemp.begin) / 1000 + " seconds"); - } - } - - public static String[] parseLine(String line, String del) throws Exception { - String del1 = del.substring(1, del.length() - 1); - if (line.contains(del1) != true) { - throw new Exception(); - } else { - String[] token = line.split(del); - return token; - } - - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/SignEC2.java b/test/src-not-used/main/java/com/cloud/test/utils/SignEC2.java deleted file mode 100644 index 29e78c16c98..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/SignEC2.java +++ /dev/null @@ -1,143 +0,0 @@ -// 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. -package com.cloud.test.utils; - -import java.io.FileInputStream; -import java.io.IOException; -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.TreeMap; - -import org.apache.log4j.Logger; - -public class SignEC2 { - public static String url; - public static String secretkey; - public static String host; - public static String port; - public static String command; - public static String accessPoint; - public static final Logger s_logger = Logger.getLogger(SignEC2.class.getName()); - - public static void main(String[] args) { - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - - if (arg.equals("-u")) { - url = iter.next(); - } - } - - Properties prop = new Properties(); - try { - prop.load(new FileInputStream("../conf/tool.properties")); - } catch (IOException ex) { - s_logger.error("Error reading from ../conf/tool.properties", ex); - System.exit(2); - } - - host = prop.getProperty("host"); - secretkey = prop.getProperty("secretkey"); - port = prop.getProperty("port"); - - if (host == null) { - s_logger.info("Please set host in tool.properties file"); - System.exit(1); - } - - if (port == null) { - s_logger.info("Please set port in tool.properties file"); - System.exit(1); - } - - if (url == null) { - s_logger.info("Please specify url with -u option"); - System.exit(1); - } - - if (secretkey == null) { - s_logger.info("Please set secretkey in tool.properties file"); - System.exit(1); - } - - if (prop.get("apikey") == null) { - s_logger.info("Please set apikey in tool.properties file"); - System.exit(1); - } - - if (prop.get("accesspoint") == null) { - s_logger.info("Please set apikey in tool.properties file"); - System.exit(1); - } - - TreeMap param = new TreeMap(); - - String req = "GET\n" + host + ":" + prop.getProperty("port") + "\n/" + prop.getProperty("accesspoint") + "\n"; - String temp = ""; - param.put("AWSAccessKeyId", prop.getProperty("apikey")); - param.put("Expires", prop.getProperty("expires")); - param.put("SignatureMethod", "HmacSHA1"); - param.put("SignatureVersion", "2"); - param.put("Version", prop.getProperty("version")); - param.put("id", "1"); - - StringTokenizer str1 = new StringTokenizer(url, "&"); - while (str1.hasMoreTokens()) { - String newEl = str1.nextToken(); - StringTokenizer str2 = new StringTokenizer(newEl, "="); - String name = str2.nextToken(); - String value = str2.nextToken(); - param.put(name, value); - } - - //sort url hash map by key - Set c = param.entrySet(); - Iterator it = c.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - temp = temp + key + "=" + URLEncoder.encode(value, "UTF-8") + "&"; - } catch (Exception ex) { - s_logger.error("Unable to set parameter " + value + " for the command " + param.get("command")); - } - - } - temp = temp.substring(0, temp.length() - 1); - String requestToSign = req + temp; - String signature = UtilsForTest.signRequest(requestToSign, secretkey); - String encodedSignature = ""; - try { - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - } catch (Exception ex) { - s_logger.error(ex); - } - String url = "http://" + host + ":" + prop.getProperty("port") + "/" + prop.getProperty("accesspoint") + "?" + temp + "&Signature=" + encodedSignature; - s_logger.info("Url is " + url); - - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/SignRequest.java b/test/src-not-used/main/java/com/cloud/test/utils/SignRequest.java deleted file mode 100644 index 95fd7b29374..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/SignRequest.java +++ /dev/null @@ -1,112 +0,0 @@ -// 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. -package com.cloud.test.utils; - -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.TreeMap; - -public class SignRequest { - public static String url; - public static String apikey; - public static String secretkey; - public static String command; - - public static void main(String[] args) { - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - if (arg.equals("-a")) { - apikey = iter.next(); - - } - if (arg.equals("-u")) { - url = iter.next(); - } - - if (arg.equals("-s")) { - secretkey = iter.next(); - } - } - - if (url == null) { - System.out.println("Please specify url with -u option. Example: -u \"command=listZones&id=1\""); - System.exit(1); - } - - if (apikey == null) { - System.out.println("Please specify apikey with -a option"); - System.exit(1); - } - - if (secretkey == null) { - System.out.println("Please specify secretkey with -s option"); - System.exit(1); - } - - TreeMap param = new TreeMap(); - - String temp = ""; - param.put("apikey", apikey); - - StringTokenizer str1 = new StringTokenizer(url, "&"); - while (str1.hasMoreTokens()) { - String newEl = str1.nextToken(); - StringTokenizer str2 = new StringTokenizer(newEl, "="); - String name = str2.nextToken(); - String value = str2.nextToken(); - param.put(name, value); - } - - //sort url hash map by key - Set c = param.entrySet(); - Iterator it = c.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - temp = temp + key + "=" + URLEncoder.encode(value, "UTF-8") + "&"; - } catch (Exception ex) { - System.out.println("Unable to set parameter " + value + " for the command " + param.get("command")); - } - - } - temp = temp.substring(0, temp.length() - 1); - String requestToSign = temp.toLowerCase(); - System.out.println("After sorting: " + requestToSign); - String signature = UtilsForTest.signRequest(requestToSign, secretkey); - System.out.println("After Base64 encoding: " + signature); - String encodedSignature = ""; - try { - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - } catch (Exception ex) { - System.out.println(ex); - } - System.out.println("After UTF8 encoding: " + encodedSignature); - String url = temp + "&signature=" + encodedSignature; - System.out.println("After sort and add signature: " + url); - - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/SqlDataGenerator.java b/test/src-not-used/main/java/com/cloud/test/utils/SqlDataGenerator.java deleted file mode 100644 index 8b42b1f1237..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/SqlDataGenerator.java +++ /dev/null @@ -1,49 +0,0 @@ -// 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. -package com.cloud.test.utils; - -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.util.Formatter; - -public class SqlDataGenerator { - public static void main(String[] args) { - try { - FileOutputStream fs = new FileOutputStream(new File("out.txt")); - - DataOutputStream out = new DataOutputStream(fs); - - for (int i = 20; i < 171; i++) { - out.writeBytes("INSERT INTO `vmops`.`dc_ip_address_alloc` (ip_address, data_center_id, pod_id) VALUES ('192.168.2." + i + "',1,1);\r\n"); - } - out.writeBytes("\r\n"); - for (int i = 1; i < 10000; i++) { - StringBuilder imagePath = new StringBuilder(); - Formatter formatter = new Formatter(imagePath); - formatter.format("%04x", i); - out.writeBytes("INSERT INTO `vmops`.`dc_vnet_alloc` (vnet, data_center_id) VALUES ('" + imagePath.toString() + "',1);\r\n"); - } - - out.flush(); - out.close(); - } catch (Exception e) { - s_logger.info("[ignored]" - + "error during sql generation: " + e.getLocalizedMessage()); - } - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/SubmitCert.java b/test/src-not-used/main/java/com/cloud/test/utils/SubmitCert.java deleted file mode 100644 index a130d6728ec..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/SubmitCert.java +++ /dev/null @@ -1,198 +0,0 @@ -// 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. -package com.cloud.test.utils; - -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.FileReader; -import java.io.IOException; -import java.net.URLEncoder; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.StringTokenizer; -import java.util.TreeMap; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; - -public class SubmitCert { - public static String url = "Action=SetCertificate"; - public static String secretKey; - public static String apiKey; - public static String host; - public static String port; - public static String command; - public static String accessPoint; - public static String signatureMethod; - public static String fileName = "tool.properties"; - public static String certFileName; - public static String cert; - public static final Logger s_logger = Logger.getLogger(SubmitCert.class.getName()); - - public static void main(String[] args) { - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - - if (arg.equals("-c")) { - certFileName = iter.next(); - } - - if (arg.equals("-s")) { - secretKey = iter.next(); - } - - if (arg.equals("-a")) { - apiKey = iter.next(); - } - - if (arg.equals("-action")) { - url = "Action=" + iter.next(); - } - } - - Properties prop = new Properties(); - try { - prop.load(new FileInputStream("conf/tool.properties")); - } catch (IOException ex) { - s_logger.error("Error reading from conf/tool.properties", ex); - System.exit(2); - } - - host = prop.getProperty("host"); - port = prop.getProperty("port"); - - if (url.equals("Action=SetCertificate") && certFileName == null) { - s_logger.error("Please set path to certificate (including file name) with -c option"); - System.exit(1); - } - - if (secretKey == null) { - s_logger.error("Please set secretkey with -s option"); - System.exit(1); - } - - if (apiKey == null) { - s_logger.error("Please set apikey with -a option"); - System.exit(1); - } - - if (host == null) { - s_logger.error("Please set host in tool.properties file"); - System.exit(1); - } - - if (port == null) { - s_logger.error("Please set port in tool.properties file"); - System.exit(1); - } - - TreeMap param = new TreeMap(); - - String req = "GET\n" + host + ":" + prop.getProperty("port") + "\n/" + prop.getProperty("accesspoint") + "\n"; - String temp = ""; - - if (certFileName != null) { - cert = readCert(certFileName); - param.put("cert", cert); - } - - param.put("AWSAccessKeyId", apiKey); - param.put("Expires", prop.getProperty("expires")); - param.put("SignatureMethod", prop.getProperty("signaturemethod")); - param.put("SignatureVersion", "2"); - param.put("Version", prop.getProperty("version")); - - StringTokenizer str1 = new StringTokenizer(url, "&"); - while (str1.hasMoreTokens()) { - String newEl = str1.nextToken(); - StringTokenizer str2 = new StringTokenizer(newEl, "="); - String name = str2.nextToken(); - String value = str2.nextToken(); - param.put(name, value); - } - - //sort url hash map by key - Set c = param.entrySet(); - Iterator it = c.iterator(); - while (it.hasNext()) { - Map.Entry me = (Map.Entry)it.next(); - String key = (String)me.getKey(); - String value = (String)me.getValue(); - try { - temp = temp + key + "=" + URLEncoder.encode(value, "UTF-8") + "&"; - } catch (Exception ex) { - s_logger.error("Unable to set parameter " + value + " for the command " + param.get("command"), ex); - } - - } - temp = temp.substring(0, temp.length() - 1); - String requestToSign = req + temp; - String signature = UtilsForTest.signRequest(requestToSign, secretKey); - String encodedSignature = ""; - try { - encodedSignature = URLEncoder.encode(signature, "UTF-8"); - } catch (Exception ex) { - ex.printStackTrace(); - } - - String url = "http://" + host + ":" + prop.getProperty("port") + "/" + prop.getProperty("accesspoint") + "?" + temp + "&Signature=" + encodedSignature; - s_logger.info("Sending request with url: " + url + "\n"); - sendRequest(url); - } - - public static String readCert(String filePath) { - try { - StringBuffer fileData = new StringBuffer(1000); - BufferedReader reader = new BufferedReader(new FileReader(filePath)); - char[] buf = new char[1024]; - int numRead = 0; - while ((numRead = reader.read(buf)) != -1) { - String readData = String.valueOf(buf, 0, numRead); - fileData.append(readData); - buf = new char[1024]; - } - reader.close(); - return fileData.toString(); - } catch (Exception ex) { - s_logger.error(ex); - return null; - } - } - - public static void sendRequest(String url) { - try { - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - String is = method.getResponseBodyAsString(); - s_logger.info("Response code " + responseCode + ": " + is); - } catch (Exception ex) { - ex.printStackTrace(); - } - - } - -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/TestClient.java b/test/src-not-used/main/java/com/cloud/test/utils/TestClient.java deleted file mode 100644 index 20df29147e3..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/TestClient.java +++ /dev/null @@ -1,385 +0,0 @@ -// 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. -package com.cloud.test.utils; - -import java.io.InputStream; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Random; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.GetMethod; -import org.apache.log4j.Logger; -import org.apache.log4j.NDC; - -import com.trilead.ssh2.ChannelCondition; -import com.trilead.ssh2.Connection; -import com.trilead.ssh2.SCPClient; -import com.trilead.ssh2.Session; - -public class TestClient { - private static long sleepTime = 180000L; // default 0 - private static boolean cleanUp = true; - public static final Logger s_logger = Logger.getLogger(TestClient.class.getName()); - private static boolean repeat = true; - private static int numOfUsers = 0; - private static String[] users = null; - private static boolean internet = true; - - private static final int MAX_RETRY_LINUX = 5; - private static final int MAX_RETRY_WIN = 10; - - public static void main(String[] args) { - String host = "http://localhost"; - String port = "8080"; - String testUrl = "/client/test"; - int numThreads = 1; - - try { - // Parameters - List argsList = Arrays.asList(args); - Iterator iter = argsList.iterator(); - while (iter.hasNext()) { - String arg = iter.next(); - // host - if (arg.equals("-h")) { - host = "http://" + iter.next(); - } - - if (arg.equals("-p")) { - port = iter.next(); - } - - if (arg.equals("-t")) { - numThreads = Integer.parseInt(iter.next()); - } - - if (arg.equals("-s")) { - sleepTime = Long.parseLong(iter.next()); - } - - if (arg.equals("-c")) { - cleanUp = Boolean.parseBoolean(iter.next()); - if (!cleanUp) - sleepTime = 0L; // no need to wait if we don't ever cleanup - } - - if (arg.equals("-r")) { - repeat = Boolean.parseBoolean(iter.next()); - } - - if (arg.equals("-u")) { - numOfUsers = Integer.parseInt(iter.next()); - } - - if (arg.equals("-i")) { - internet = Boolean.parseBoolean(iter.next()); - } - } - - final String server = host + ":" + port + testUrl; - s_logger.info("Starting test against server: " + server + " with " + numThreads + " thread(s)"); - if (cleanUp) - s_logger.info("Clean up is enabled, each test will wait " + sleepTime + " ms before cleaning up"); - - if (numOfUsers > 0) { - s_logger.info("Pre-generating users for test of size : " + numOfUsers); - users = new String[numOfUsers]; - Random ran = new Random(); - for (int i = 0; i < numOfUsers; i++) { - users[i] = Math.abs(ran.nextInt()) + "-user"; - } - } - - for (int i = 0; i < numThreads; i++) { - new Thread(new Runnable() { - @Override - public void run() { - do { - String username = null; - try { - long now = System.currentTimeMillis(); - Random ran = new Random(); - if (users != null) { - username = users[Math.abs(ran.nextInt()) % numOfUsers]; - } else { - username = Math.abs(ran.nextInt()) + "-user"; - } - NDC.push(username); - - String url = server + "?email=" + username + "&password=" + username + "&command=deploy"; - s_logger.info("Launching test for user: " + username + " with url: " + url); - HttpClient client = new HttpClient(); - HttpMethod method = new GetMethod(url); - int responseCode = client.executeMethod(method); - boolean success = false; - String reason = null; - if (responseCode == 200) { - if (internet) { - s_logger.info("Deploy successful...waiting 5 minute before SSH tests"); - Thread.sleep(300000L); // Wait 60 seconds so the linux VM can boot up. - - s_logger.info("Begin Linux SSH test"); - reason = sshTest(method.getResponseHeader("linuxIP").getValue()); - - if (reason == null) { - s_logger.info("Linux SSH test successful"); - s_logger.info("Begin Windows SSH test"); - reason = sshWinTest(method.getResponseHeader("windowsIP").getValue()); - } - } - if (reason == null) { - if (internet) { - s_logger.info("Windows SSH test successful"); - } else { - s_logger.info("deploy test successful....now cleaning up"); - if (cleanUp) { - s_logger.info("Waiting " + sleepTime + " ms before cleaning up vms"); - Thread.sleep(sleepTime); - } else { - success = true; - } - } - if (users == null) { - s_logger.info("Sending cleanup command"); - url = server + "?email=" + username + "&password=" + username + "&command=cleanup"; - } else { - s_logger.info("Sending stop DomR / destroy VM command"); - url = server + "?email=" + username + "&password=" + username + "&command=stopDomR"; - } - method = new GetMethod(url); - responseCode = client.executeMethod(method); - if (responseCode == 200) { - success = true; - } else { - reason = method.getStatusText(); - } - } else { - // Just stop but don't destroy the VMs/Routers - s_logger.info("SSH test failed with reason '" + reason + "', stopping VMs"); - url = server + "?email=" + username + "&password=" + username + "&command=stop"; - responseCode = client.executeMethod(new GetMethod(url)); - } - } else { - // Just stop but don't destroy the VMs/Routers - reason = method.getStatusText(); - s_logger.info("Deploy test failed with reason '" + reason + "', stopping VMs"); - url = server + "?email=" + username + "&password=" + username + "&command=stop"; - client.executeMethod(new GetMethod(url)); - } - - if (success) { - s_logger.info("***** Completed test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + " seconds"); - } else { - s_logger.info("##### FAILED test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + - " seconds with reason : " + reason); - } - } catch (Exception e) { - s_logger.warn("Error in thread", e); - try { - HttpClient client = new HttpClient(); - String url = server + "?email=" + username + "&password=" + username + "&command=stop"; - client.executeMethod(new GetMethod(url)); - } catch (Exception e1) { - s_logger.info("[ignored]" - + "error while executing last resort stop attempt: " + e1.getLocalizedMessage()); - } - } finally { - NDC.clear(); - } - } while (repeat); - } - }).start(); - } - } catch (Exception e) { - s_logger.error(e); - } - } - - private static String sshWinTest(String host) { - if (host == null) { - s_logger.info("Did not receive a host back from test, ignoring win ssh test"); - return null; - } - - // We will retry 5 times before quitting - int retry = 0; - - while (true) { - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 300 seconds before next attempt"); - Thread.sleep(300000); - } - - s_logger.info("Attempting to SSH into windows host " + host + " with retry attempt: " + retry); - - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("SSHed successfully into windows host " + host); - boolean success = false; - boolean isAuthenticated = conn.authenticateWithPassword("vmops", "vmops"); - if (isAuthenticated == false) { - return "Authentication failed"; - } - SCPClient scp = new SCPClient(conn); - - scp.put("wget.exe", ""); - - Session sess = conn.openSession(); - s_logger.info("Executing : wget http://172.16.0.220/dump.bin"); - sess.execCommand("wget http://172.16.0.220/dump.bin && dir dump.bin"); - - InputStream stdout = sess.getStdout(); - InputStream stderr = sess.getStderr(); - - byte[] buffer = new byte[8192]; - while (true) { - if ((stdout.available() == 0) && (stderr.available() == 0)) { - int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); - - if ((conditions & ChannelCondition.TIMEOUT) != 0) { - s_logger.info("Timeout while waiting for data from peer."); - return null; - } - - if ((conditions & ChannelCondition.EOF) != 0) { - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { - break; - } - } - } - - while (stdout.available() > 0) { - success = true; - int len = stdout.read(buffer); - if (len > 0) // this check is somewhat paranoid - s_logger.info(new String(buffer, 0, len)); - } - - while (stderr.available() > 0) { - int len = stderr.read(buffer); - } - } - sess.close(); - conn.close(); - - if (success) { - return null; - } else { - retry++; - if (retry == MAX_RETRY_WIN) { - return "SSH Windows Network test fail"; - } - } - } catch (Exception e) { - retry++; - if (retry == MAX_RETRY_WIN) { - return "SSH Windows Network test fail with error " + e.getMessage(); - } - } - } - } - - private static String sshTest(String host) { - if (host == null) { - s_logger.info("Did not receive a host back from test, ignoring ssh test"); - return null; - } - - // We will retry 5 times before quitting - int retry = 0; - - while (true) { - try { - if (retry > 0) { - s_logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt"); - Thread.sleep(120000); - } - - s_logger.info("Attempting to SSH into linux host " + host + " with retry attempt: " + retry); - - Connection conn = new Connection(host); - conn.connect(null, 60000, 60000); - - s_logger.info("SSHed successfully into linux host " + host); - - boolean isAuthenticated = conn.authenticateWithPassword("root", "password"); - - if (isAuthenticated == false) { - return "Authentication failed"; - } - boolean success = false; - Session sess = conn.openSession(); - s_logger.info("Executing : wget http://172.16.0.220/dump.bin"); - sess.execCommand("wget http://172.16.0.220/dump.bin && ls -al dump.bin"); - - InputStream stdout = sess.getStdout(); - InputStream stderr = sess.getStderr(); - - byte[] buffer = new byte[8192]; - while (true) { - if ((stdout.available() == 0) && (stderr.available() == 0)) { - int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); - - if ((conditions & ChannelCondition.TIMEOUT) != 0) { - s_logger.info("Timeout while waiting for data from peer."); - return null; - } - - if ((conditions & ChannelCondition.EOF) != 0) { - if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { - break; - } - } - } - - while (stdout.available() > 0) { - success = true; - int len = stdout.read(buffer); - if (len > 0) // this check is somewhat paranoid - s_logger.info(new String(buffer, 0, len)); - } - - while (stderr.available() > 0) { - int len = stderr.read(buffer); - } - } - - sess.close(); - conn.close(); - - if (success) { - return null; - } else { - retry++; - if (retry == MAX_RETRY_LINUX) { - return "SSH Linux Network test fail"; - } - } - } catch (Exception e) { - retry++; - if (retry == MAX_RETRY_LINUX) { - return "SSH Linux Network test fail with error " + e.getMessage(); - } - } - } - } -} diff --git a/test/src-not-used/main/java/com/cloud/test/utils/UtilsForTest.java b/test/src-not-used/main/java/com/cloud/test/utils/UtilsForTest.java deleted file mode 100644 index 78ba001bb9c..00000000000 --- a/test/src-not-used/main/java/com/cloud/test/utils/UtilsForTest.java +++ /dev/null @@ -1,210 +0,0 @@ -// 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. -package com.cloud.test.utils; - -import java.io.InputStream; -import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import org.apache.commons.codec.binary.Base64; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -import com.cloud.utils.exception.CloudRuntimeException; - -public class UtilsForTest { - - private static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - - public static boolean verifyTags(Map params) { - boolean result = true; - for (String value : params.keySet()) { - if (params.get(value) == null) { - result = false; - } - } - return result; - } - - public static boolean verifyTagValues(Map params, Map pattern) { - boolean result = true; - - if (pattern != null) { - for (String value : pattern.keySet()) { - if (!pattern.get(value).equals(params.get(value))) { - result = false; - System.out.println("Tag " + value + " has " + params.get(value) + " while expected value is: " + pattern.get(value)); - } - } - } - return result; - } - - public static Map parseXML(InputStream is, String[] tagNames) { - Map returnValues = new HashMap(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - System.out.println("no " + tagNames[i] + " tag in the response"); - returnValues.put(tagNames[i], null); - } else { - returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); - } - } - } catch (Exception ex) { - System.out.println("error processing XML"); - ex.printStackTrace(); - } - return returnValues; - } - - public static ArrayList> parseMulXML(InputStream is, String[] tagNames) { - ArrayList> returnValues = new ArrayList>(); - - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - System.out.println("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - for (int j = 0; j < targetNodes.getLength(); j++) { - HashMap valueList = new HashMap(); - Node node = targetNodes.item(j); - //parse child nodes - NodeList child = node.getChildNodes(); - for (int c = 0; c < node.getChildNodes().getLength(); c++) { - child.item(c).getNodeName(); - valueList.put(child.item(c).getNodeName(), child.item(c).getTextContent()); - } - returnValues.add(valueList); - } - - } - } - } catch (Exception ex) { - System.out.println(ex); - } - - return returnValues; - } - - public static String createMD5String(String password) { - MessageDigest md5; - try { - md5 = MessageDigest.getInstance("MD5"); - } catch (NoSuchAlgorithmException e) { - throw new CloudRuntimeException("Error", e); - } - - md5.reset(); - BigInteger pwInt = new BigInteger(1, md5.digest(password.getBytes())); - - // make sure our MD5 hash value is 32 digits long... - StringBuffer sb = new StringBuffer(); - String pwStr = pwInt.toString(16); - int padding = 32 - pwStr.length(); - for (int i = 0; i < padding; i++) { - sb.append('0'); - } - sb.append(pwStr); - return sb.toString(); - } - - public static Map getSingleValueFromXML(InputStream is, String[] tagNames) { - Map returnValues = new HashMap(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - System.out.println("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); - } - } - } catch (Exception ex) { - System.out.println("error processing XML"); - ex.printStackTrace(); - } - return returnValues; - } - - public static Map> getMultipleValuesFromXML(InputStream is, String[] tagNames) { - Map> returnValues = new HashMap>(); - try { - DocumentBuilder docBuilder = factory.newDocumentBuilder(); - Document doc = docBuilder.parse(is); - Element rootElement = doc.getDocumentElement(); - for (int i = 0; i < tagNames.length; i++) { - NodeList targetNodes = rootElement.getElementsByTagName(tagNames[i]); - if (targetNodes.getLength() <= 0) { - System.out.println("no " + tagNames[i] + " tag in XML response...returning null"); - } else { - List valueList = new ArrayList(); - for (int j = 0; j < targetNodes.getLength(); j++) { - Node node = targetNodes.item(j); - valueList.add(node.getTextContent()); - } - returnValues.put(tagNames[i], valueList); - } - } - } catch (Exception ex) { - System.out.println(ex); - } - return returnValues; - } - - public static String signRequest(String request, String key) { - try { - Mac mac = Mac.getInstance("HmacSHA1"); - SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "HmacSHA1"); - mac.init(keySpec); - mac.update(request.getBytes()); - byte[] encryptedBytes = mac.doFinal(); - //System.out.println("HmacSHA1 hash: " + encryptedBytes); - return Base64.encodeBase64String(encryptedBytes); - } catch (Exception ex) { - System.out.println("unable to sign request"); - ex.printStackTrace(); - } - return null; - } - -} From 21af134087a55c044f921b3f6ab64aba83b80071 Mon Sep 17 00:00:00 2001 From: Vishesh Date: Wed, 8 May 2024 20:55:19 +0530 Subject: [PATCH 0068/1050] Fix exceeding of resource limits with powerflex (#9008) * Fix exceeding of resource limits with powerflex * Add e2e tests * Update server/src/main/java/com/cloud/vm/UserVmManagerImpl.java Co-authored-by: Suresh Kumar Anaparti * fixup --------- Co-authored-by: Suresh Kumar Anaparti --- .../com/cloud/user/ResourceLimitService.java | 2 + .../service/VolumeOrchestrationService.java | 3 +- .../api/storage/PrimaryDataStoreDriver.java | 16 +++ .../cloud/vm/VirtualMachineManagerImpl.java | 3 +- .../orchestration/VolumeOrchestrator.java | 50 ++++++- .../driver/ScaleIOPrimaryDataStoreDriver.java | 10 ++ .../ScaleIOPrimaryDataStoreDriverTest.java | 33 +++++ .../ResourceLimitManagerImpl.java | 13 ++ .../cloud/storage/VolumeApiServiceImpl.java | 18 +++ .../java/com/cloud/vm/UserVmManagerImpl.java | 123 +++++++++++------- .../com/cloud/vm/UserVmManagerImplTest.java | 34 +++++ .../vpc/MockResourceLimitManagerImpl.java | 6 + .../component/test_resource_limit_tags.py | 44 +++++++ test/integration/smoke/test_restore_vm.py | 91 +++++++++++-- tools/marvin/marvin/lib/base.py | 20 ++- 15 files changed, 398 insertions(+), 68 deletions(-) diff --git a/api/src/main/java/com/cloud/user/ResourceLimitService.java b/api/src/main/java/com/cloud/user/ResourceLimitService.java index d0aa9f69f84..ba19719ea8d 100644 --- a/api/src/main/java/com/cloud/user/ResourceLimitService.java +++ b/api/src/main/java/com/cloud/user/ResourceLimitService.java @@ -243,6 +243,8 @@ public interface ResourceLimitService { void checkVolumeResourceLimitForDiskOfferingChange(Account owner, Boolean display, Long currentSize, Long newSize, DiskOffering currentOffering, DiskOffering newOffering) throws ResourceAllocationException; + void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException; + void incrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering); void decrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering); diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java index c3525466ce1..7950dda4d68 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.cloud.exception.ResourceAllocationException; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; @@ -126,7 +127,7 @@ public interface VolumeOrchestrationService { void prepareForMigration(VirtualMachineProfile vm, DeployDestination dest); - void prepare(VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException, InsufficientStorageCapacityException, ConcurrentOperationException, StorageAccessException; + void prepare(VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException, InsufficientStorageCapacityException, ConcurrentOperationException, StorageAccessException, ResourceAllocationException; boolean canVmRestartOnAnotherServer(long vmId); diff --git a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java index 2c7d3c60278..dbe67e6cca5 100644 --- a/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java +++ b/engine/api/src/main/java/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreDriver.java @@ -157,4 +157,20 @@ public interface PrimaryDataStoreDriver extends DataStoreDriver { default boolean zoneWideVolumesAvailableWithoutClusterMotion() { return false; } + + /** + * This method returns the actual size required on the pool for a volume. + * + * @param volumeSize + * Size of volume to be created on the store + * @param templateSize + * Size of template, if any, which will be used to create the volume + * @param isEncryptionRequired + * true if volume is encrypted + * + * @return the size required on the pool for the volume + */ + default long getVolumeSizeRequiredOnPool(long volumeSize, Long templateSize, boolean isEncryptionRequired) { + return volumeSize; + } } diff --git a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java index 824b9f5f45d..0613b9586ff 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -52,6 +52,7 @@ import javax.persistence.EntityExistsException; import com.cloud.configuration.Resource; import com.cloud.domain.Domain; import com.cloud.domain.dao.DomainDao; +import com.cloud.exception.ResourceAllocationException; import com.cloud.network.vpc.VpcVO; import com.cloud.network.vpc.dao.VpcDao; import com.cloud.user.dao.AccountDao; @@ -1403,7 +1404,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac logger.warn("unexpected InsufficientCapacityException : {}", e.getScope().getName(), e); } } - } catch (ExecutionException | NoTransitionException e) { + } catch (ExecutionException | NoTransitionException | ResourceAllocationException e) { logger.error("Failed to start instance {}", vm, e); throw new AgentUnavailableException("Unable to start instance due to " + e.getMessage(), destHostId, e); } catch (final StorageAccessException e) { diff --git a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index ff9da6bccc2..a2921452e28 100644 --- a/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/main/java/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -38,6 +38,11 @@ import java.util.stream.Collectors; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.user.AccountManager; import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants.IoDriverPolicy; import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd; @@ -180,6 +185,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } + @Inject + private AccountManager _accountMgr; @Inject EntityManager _entityMgr; @Inject @@ -195,6 +202,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati @Inject protected VolumeDao _volumeDao; @Inject + protected VMTemplateDao _templateDao; + @Inject protected SnapshotDao _snapshotDao; @Inject protected SnapshotDataStoreDao _snapshotDataStoreDao; @@ -1677,7 +1686,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } } - private Pair recreateVolume(VolumeVO vol, VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException, StorageAccessException { + private Pair recreateVolume(VolumeVO vol, VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException, StorageAccessException, ResourceAllocationException { String volToString = getReflectOnlySelectedFields(vol); VolumeVO newVol; @@ -1710,6 +1719,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } logger.debug("Created new volume [{}] from old volume [{}].", newVolToString, volToString); } + updateVolumeSize(destPool, newVol); VolumeInfo volume = volFactory.getVolume(newVol.getId(), destPool); Long templateId = newVol.getTemplateId(); for (int i = 0; i < 2; i++) { @@ -1841,8 +1851,39 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } } + /** + * This method checks if size of volume on the data store would be different. + * If it's different it verifies the resource limits and updates the volume's size + */ + protected void updateVolumeSize(DataStore store, VolumeVO vol) throws ResourceAllocationException { + if (store == null || !(store.getDriver() instanceof PrimaryDataStoreDriver)) { + return; + } + + VMTemplateVO template = vol.getTemplateId() != null ? _templateDao.findById(vol.getTemplateId()) : null; + PrimaryDataStoreDriver driver = (PrimaryDataStoreDriver) store.getDriver(); + long newSize = driver.getVolumeSizeRequiredOnPool(vol.getSize(), + template == null ? null : template.getSize(), + vol.getPassphraseId() != null); + + if (newSize != vol.getSize()) { + DiskOfferingVO diskOffering = diskOfferingDao.findByIdIncludingRemoved(vol.getDiskOfferingId()); + if (newSize > vol.getSize()) { + _resourceLimitMgr.checkPrimaryStorageResourceLimit(_accountMgr.getActiveAccountById(vol.getAccountId()), + vol.isDisplay(), newSize - vol.getSize(), diskOffering); + _resourceLimitMgr.incrementVolumePrimaryStorageResourceCount(vol.getAccountId(), vol.isDisplay(), + newSize - vol.getSize(), diskOffering); + } else { + _resourceLimitMgr.decrementVolumePrimaryStorageResourceCount(vol.getAccountId(), vol.isDisplay(), + vol.getSize() - newSize, diskOffering); + } + vol.setSize(newSize); + _volsDao.persist(vol); + } + } + @Override - public void prepare(VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException, InsufficientStorageCapacityException, ConcurrentOperationException, StorageAccessException { + public void prepare(VirtualMachineProfile vm, DeployDestination dest) throws StorageUnavailableException, InsufficientStorageCapacityException, ConcurrentOperationException, StorageAccessException, ResourceAllocationException { if (dest == null) { String msg = String.format("Unable to prepare volumes for the VM [%s] because DeployDestination is null.", vm.getVirtualMachine()); logger.error(msg); @@ -1865,7 +1906,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati String volToString = getReflectOnlySelectedFields(vol); - store = (PrimaryDataStore)dataStoreMgr.getDataStore(task.pool.getId(), DataStoreRole.Primary); + store = (PrimaryDataStore) dataStoreMgr.getDataStore(task.pool.getId(), DataStoreRole.Primary); // For zone-wide managed storage, it is possible that the VM can be started in another // cluster. In that case, make sure that the volume is in the right access group. @@ -1876,6 +1917,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati long lastClusterId = lastHost == null || lastHost.getClusterId() == null ? -1 : lastHost.getClusterId(); long clusterId = host == null || host.getClusterId() == null ? -1 : host.getClusterId(); + updateVolumeSize(store, (VolumeVO) vol); + if (lastClusterId != clusterId) { if (lastHost != null) { storageMgr.removeStoragePoolFromCluster(lastHost.getId(), vol.get_iScsiName(), store); @@ -1895,6 +1938,7 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati } } else if (task.type == VolumeTaskType.MIGRATE) { store = (PrimaryDataStore) dataStoreMgr.getDataStore(task.pool.getId(), DataStoreRole.Primary); + updateVolumeSize(store, task.volume); vol = migrateVolume(task.volume, store); } else if (task.type == VolumeTaskType.RECREATE) { Pair result = recreateVolume(task.volume, vm, dest); diff --git a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriver.java b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriver.java index 31308a429da..817b263e9b4 100644 --- a/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriver.java +++ b/plugins/storage/volume/scaleio/src/main/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriver.java @@ -1340,6 +1340,16 @@ public class ScaleIOPrimaryDataStoreDriver implements PrimaryDataStoreDriver { } } + @Override + public long getVolumeSizeRequiredOnPool(long volumeSize, Long templateSize, boolean isEncryptionRequired) { + long newSizeInGB = volumeSize / (1024 * 1024 * 1024); + if (templateSize != null && isEncryptionRequired && needsExpansionForEncryptionHeader(templateSize, volumeSize)) { + newSizeInGB = (volumeSize + (1<<30)) / (1024 * 1024 * 1024); + } + long newSizeIn8gbBoundary = (long) (Math.ceil(newSizeInGB / 8.0) * 8.0); + return newSizeIn8gbBoundary * (1024 * 1024 * 1024); + } + @Override public void handleQualityOfServiceForVolumeMigration(VolumeInfo volumeInfo, QualityOfServiceState qualityOfServiceState) { } diff --git a/plugins/storage/volume/scaleio/src/test/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriverTest.java b/plugins/storage/volume/scaleio/src/test/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriverTest.java index de5e4d44c02..b8a799a4e07 100644 --- a/plugins/storage/volume/scaleio/src/test/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriverTest.java +++ b/plugins/storage/volume/scaleio/src/test/java/org/apache/cloudstack/storage/datastore/driver/ScaleIOPrimaryDataStoreDriverTest.java @@ -542,4 +542,37 @@ public class ScaleIOPrimaryDataStoreDriverTest { Assert.assertEquals(false, answer.getResult()); } + + @Test + public void testGetVolumeSizeRequiredOnPool() { + Assert.assertEquals(16L * (1024 * 1024 * 1024), + scaleIOPrimaryDataStoreDriver.getVolumeSizeRequiredOnPool( + 10L * (1024 * 1024 * 1024), + null, + true)); + + Assert.assertEquals(16L * (1024 * 1024 * 1024), + scaleIOPrimaryDataStoreDriver.getVolumeSizeRequiredOnPool( + 10L * (1024 * 1024 * 1024), + null, + false)); + + Assert.assertEquals(16L * (1024 * 1024 * 1024), + scaleIOPrimaryDataStoreDriver.getVolumeSizeRequiredOnPool( + 16L * (1024 * 1024 * 1024), + null, + false)); + + Assert.assertEquals(16L * (1024 * 1024 * 1024), + scaleIOPrimaryDataStoreDriver.getVolumeSizeRequiredOnPool( + 16L * (1024 * 1024 * 1024), + 16L * (1024 * 1024 * 1024), + false)); + + Assert.assertEquals(24L * (1024 * 1024 * 1024), + scaleIOPrimaryDataStoreDriver.getVolumeSizeRequiredOnPool( + 16L * (1024 * 1024 * 1024), + 16L * (1024 * 1024 * 1024), + true)); + } } diff --git a/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index f040b526a6e..4455c472113 100644 --- a/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -1641,6 +1641,19 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim } } + @Override + public void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, DiskOffering diskOffering) throws ResourceAllocationException { + List tags = getResourceLimitStorageTagsForResourceCountOperation(display, diskOffering); + if (CollectionUtils.isEmpty(tags)) { + return; + } + if (size != null) { + for (String tag : tags) { + checkResourceLimitWithTag(owner, ResourceType.primary_storage, tag, size); + } + } + } + @Override public void checkVolumeResourceLimitForDiskOfferingChange(Account owner, Boolean display, Long currentSize, Long newSize, DiskOffering currentOffering, DiskOffering newOffering diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index e79e9b9941d..ac6cdea7e0d 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -1240,6 +1240,16 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic } long currentSize = volume.getSize(); + VolumeInfo volInfo = volFactory.getVolume(volume.getId()); + boolean isEncryptionRequired = volume.getPassphraseId() != null; + if (newDiskOffering != null) { + isEncryptionRequired = newDiskOffering.getEncrypt(); + } + + DataStore dataStore = volInfo.getDataStore(); + if (dataStore != null && dataStore.getDriver() instanceof PrimaryDataStoreDriver) { + newSize = ((PrimaryDataStoreDriver) dataStore.getDriver()).getVolumeSizeRequiredOnPool(newSize, null, isEncryptionRequired); + } validateVolumeResizeWithSize(volume, currentSize, newSize, shrinkOk, diskOffering, newDiskOffering); // Note: The storage plug-in in question should perform validation on the IOPS to check if a sufficient number of IOPS is available to perform @@ -1982,6 +1992,14 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic newMaxIops = updateNewMaxIops[0]; newHypervisorSnapshotReserve = updateNewHypervisorSnapshotReserve[0]; long currentSize = volume.getSize(); + + VolumeInfo volInfo = volFactory.getVolume(volume.getId()); + + DataStore dataStore = volInfo.getDataStore(); + if (dataStore != null && dataStore.getDriver() instanceof PrimaryDataStoreDriver) { + newSize = ((PrimaryDataStoreDriver) dataStore.getDriver()).getVolumeSizeRequiredOnPool(newSize, null, newDiskOffering.getEncrypt()); + } + validateVolumeResizeWithSize(volume, currentSize, newSize, shrinkOk, existingDiskOffering, newDiskOffering); /* If this volume has never been beyond allocated state, short circuit everything and simply update the database. */ diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index c924a124fa1..dce8a21b478 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -7980,7 +7980,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } for (VolumeVO root : rootVols) { - if ( !Volume.State.Allocated.equals(root.getState()) || newTemplateId != null ) { + if ( !Volume.State.Allocated.equals(root.getState()) || newTemplateId != null || diskOffering != null) { _volumeService.validateDestroyVolume(root, caller, Volume.State.Allocated.equals(root.getState()) || expunge, false); final UserVmVO userVm = vm; Pair vmAndNewVol = Transaction.execute(new TransactionCallbackWithException, CloudRuntimeException>() { @@ -8013,7 +8013,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir newVol = volumeMgr.allocateDuplicateVolume(root, diskOffering, null); } - updateVolume(newVol, template, userVm, diskOffering, details); + getRootVolumeSizeForVmRestore(newVol, template, userVm, diskOffering, details, true); volumeMgr.saveVolumeDetails(newVol.getDiskOfferingId(), newVol.getId()); // 1. Save usage event and update resource count for user vm volumes @@ -8112,62 +8112,87 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir } - private void updateVolume(Volume vol, VMTemplateVO template, UserVmVO userVm, DiskOffering diskOffering, Map details) { + Long getRootVolumeSizeForVmRestore(Volume vol, VMTemplateVO template, UserVmVO userVm, DiskOffering diskOffering, Map details, boolean update) { VolumeVO resizedVolume = (VolumeVO) vol; + Long size = null; if (template != null && template.getSize() != null) { UserVmDetailVO vmRootDiskSizeDetail = userVmDetailsDao.findDetail(userVm.getId(), VmDetailConstants.ROOT_DISK_SIZE); if (vmRootDiskSizeDetail == null) { - resizedVolume.setSize(template.getSize()); + size = template.getSize(); } else { long rootDiskSize = Long.parseLong(vmRootDiskSizeDetail.getValue()) * GiB_TO_BYTES; if (template.getSize() >= rootDiskSize) { - resizedVolume.setSize(template.getSize()); - userVmDetailsDao.remove(vmRootDiskSizeDetail.getId()); + size = template.getSize(); + if (update) { + userVmDetailsDao.remove(vmRootDiskSizeDetail.getId()); + } } else { - resizedVolume.setSize(rootDiskSize); + size = rootDiskSize; } } + if (update) { + resizedVolume.setSize(size); + } } if (diskOffering != null) { - resizedVolume.setDiskOfferingId(diskOffering.getId()); + if (update) { + resizedVolume.setDiskOfferingId(diskOffering.getId()); + } + // Size of disk offering should be greater than or equal to the template's size and this should be validated before this if (!diskOffering.isCustomized()) { - resizedVolume.setSize(diskOffering.getDiskSize()); - } - if (diskOffering.getMinIops() != null) { - resizedVolume.setMinIops(diskOffering.getMinIops()); - } - if (diskOffering.getMaxIops() != null) { - resizedVolume.setMaxIops(diskOffering.getMaxIops()); - } - } - - if (MapUtils.isNotEmpty(details)) { - if (StringUtils.isNumeric(details.get(VmDetailConstants.ROOT_DISK_SIZE))) { - Long rootDiskSize = Long.parseLong(details.get(VmDetailConstants.ROOT_DISK_SIZE)) * GiB_TO_BYTES; - resizedVolume.setSize(rootDiskSize); - UserVmDetailVO vmRootDiskSizeDetail = userVmDetailsDao.findDetail(userVm.getId(), VmDetailConstants.ROOT_DISK_SIZE); - if (vmRootDiskSizeDetail != null) { - vmRootDiskSizeDetail.setValue(details.get(VmDetailConstants.ROOT_DISK_SIZE)); - userVmDetailsDao.update(vmRootDiskSizeDetail.getId(), vmRootDiskSizeDetail); - } else { - userVmDetailsDao.persist(new UserVmDetailVO(userVm.getId(), VmDetailConstants.ROOT_DISK_SIZE, - details.get(VmDetailConstants.ROOT_DISK_SIZE), true)); + size = diskOffering.getDiskSize(); + if (update) { + resizedVolume.setSize(diskOffering.getDiskSize()); } } - String minIops = details.get(MIN_IOPS); - String maxIops = details.get(MAX_IOPS); - - if (StringUtils.isNumeric(minIops)) { - resizedVolume.setMinIops(Long.parseLong(minIops)); - } - if (StringUtils.isNumeric(maxIops)) { - resizedVolume.setMinIops(Long.parseLong(maxIops)); + if (update) { + if (diskOffering.getMinIops() != null) { + resizedVolume.setMinIops(diskOffering.getMinIops()); + } + if (diskOffering.getMaxIops() != null) { + resizedVolume.setMaxIops(diskOffering.getMaxIops()); + } } } - _volsDao.update(resizedVolume.getId(), resizedVolume); + + // Size of disk should be greater than or equal to the template's size and this should be validated before this + if (MapUtils.isNotEmpty(details)) { + if (StringUtils.isNumeric(details.get(VmDetailConstants.ROOT_DISK_SIZE))) { + Long rootDiskSize = Long.parseLong(details.get(VmDetailConstants.ROOT_DISK_SIZE)) * GiB_TO_BYTES; + size = rootDiskSize; + if (update) { + resizedVolume.setSize(rootDiskSize); + } + UserVmDetailVO vmRootDiskSizeDetail = userVmDetailsDao.findDetail(userVm.getId(), VmDetailConstants.ROOT_DISK_SIZE); + if (update) { + if (vmRootDiskSizeDetail != null) { + vmRootDiskSizeDetail.setValue(details.get(VmDetailConstants.ROOT_DISK_SIZE)); + userVmDetailsDao.update(vmRootDiskSizeDetail.getId(), vmRootDiskSizeDetail); + } else { + userVmDetailsDao.persist(new UserVmDetailVO(userVm.getId(), VmDetailConstants.ROOT_DISK_SIZE, + details.get(VmDetailConstants.ROOT_DISK_SIZE), true)); + } + } + } + if (update) { + String minIops = details.get(MIN_IOPS); + String maxIops = details.get(MAX_IOPS); + + if (StringUtils.isNumeric(minIops)) { + resizedVolume.setMinIops(Long.parseLong(minIops)); + } + if (StringUtils.isNumeric(maxIops)) { + resizedVolume.setMinIops(Long.parseLong(maxIops)); + } + } + } + if (update) { + _volsDao.update(resizedVolume.getId(), resizedVolume); + } + return size; } private void updateVMDynamicallyScalabilityUsingTemplate(UserVmVO vm, Long newTemplateId) { @@ -8185,7 +8210,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir * @param template template * @throws InvalidParameterValueException if restore is not possible */ - private void checkRestoreVmFromTemplate(UserVmVO vm, VMTemplateVO template, List volumes, DiskOffering newDiskOffering, Map details) throws ResourceAllocationException { + private void checkRestoreVmFromTemplate(UserVmVO vm, VMTemplateVO template, List rootVolumes, DiskOffering newDiskOffering, Map details) throws ResourceAllocationException { TemplateDataStoreVO tmplStore; if (!template.isDirectDownload()) { tmplStore = _templateStoreDao.findByTemplateZoneReady(template.getId(), vm.getDataCenterId()); @@ -8206,17 +8231,15 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir _resourceLimitMgr.checkVmResourceLimitsForTemplateChange(owner, vm.isDisplay(), serviceOffering, currentTemplate, template); } - Long newSize = newDiskOffering != null ? newDiskOffering.getDiskSize() : null; - if (MapUtils.isNotEmpty(details) && StringUtils.isNumeric(details.get(VmDetailConstants.ROOT_DISK_SIZE))) { - newSize = Long.parseLong(details.get(VmDetailConstants.ROOT_DISK_SIZE)) * GiB_TO_BYTES; - } - if (newDiskOffering != null || newSize != null) { - for (Volume vol : volumes) { - if (newDiskOffering != null || !vol.getSize().equals(newSize)) { - DiskOffering currentOffering = _diskOfferingDao.findById(vol.getDiskOfferingId()); - _resourceLimitMgr.checkVolumeResourceLimitForDiskOfferingChange(owner, vol.isDisplay(), - vol.getSize(), newSize, currentOffering, newDiskOffering); - } + for (Volume vol : rootVolumes) { + Long newSize = getRootVolumeSizeForVmRestore(vol, template, vm, newDiskOffering, details, false); + if (newSize == null) { + newSize = vol.getSize(); + } + if (newDiskOffering != null || !vol.getSize().equals(newSize)) { + DiskOffering currentOffering = _diskOfferingDao.findById(vol.getDiskOfferingId()); + _resourceLimitMgr.checkVolumeResourceLimitForDiskOfferingChange(owner, vol.isDisplay(), + vol.getSize(), newSize, currentOffering, newDiskOffering); } } } diff --git a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java index c464af6385b..323a1ed9416 100644 --- a/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java +++ b/server/src/test/java/com/cloud/vm/UserVmManagerImplTest.java @@ -40,6 +40,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import com.cloud.offering.DiskOffering; import org.apache.cloudstack.api.BaseCmd.HTTPMethod; import org.apache.cloudstack.api.command.user.vm.DeployVMCmd; import org.apache.cloudstack.api.command.user.vm.DeployVnfApplianceCmd; @@ -1563,4 +1564,37 @@ public class UserVmManagerImplTest { Assert.fail(e.getMessage()); } } + + @Test + public void testGetRootVolumeSizeForVmRestore() { + VMTemplateVO template = Mockito.mock(VMTemplateVO.class); + Mockito.when(template.getSize()).thenReturn(10L * GiB_TO_BYTES); + UserVmVO userVm = Mockito.mock(UserVmVO.class); + Mockito.when(userVm.getId()).thenReturn(1L); + DiskOffering diskOffering = Mockito.mock(DiskOffering.class); + Mockito.when(diskOffering.isCustomized()).thenReturn(false); + Mockito.when(diskOffering.getDiskSize()).thenReturn(8L * GiB_TO_BYTES); + Map details = new HashMap<>(); + details.put(VmDetailConstants.ROOT_DISK_SIZE, "16"); + UserVmDetailVO vmRootDiskSizeDetail = Mockito.mock(UserVmDetailVO.class); + Mockito.when(vmRootDiskSizeDetail.getValue()).thenReturn("20"); + Mockito.when(userVmDetailsDao.findDetail(1L, VmDetailConstants.ROOT_DISK_SIZE)).thenReturn(vmRootDiskSizeDetail); + Long actualSize = userVmManagerImpl.getRootVolumeSizeForVmRestore(null, template, userVm, diskOffering, details, false); + Assert.assertEquals(16 * GiB_TO_BYTES, actualSize.longValue()); + } + + @Test + public void testGetRootVolumeSizeForVmRestoreNullDiskOfferingAndEmptyDetails() { + VMTemplateVO template = Mockito.mock(VMTemplateVO.class); + Mockito.when(template.getSize()).thenReturn(10L * GiB_TO_BYTES); + UserVmVO userVm = Mockito.mock(UserVmVO.class); + Mockito.when(userVm.getId()).thenReturn(1L); + DiskOffering diskOffering = null; + Map details = new HashMap<>(); + UserVmDetailVO vmRootDiskSizeDetail = Mockito.mock(UserVmDetailVO.class); + Mockito.when(vmRootDiskSizeDetail.getValue()).thenReturn("20"); + Mockito.when(userVmDetailsDao.findDetail(1L, VmDetailConstants.ROOT_DISK_SIZE)).thenReturn(vmRootDiskSizeDetail); + Long actualSize = userVmManagerImpl.getRootVolumeSizeForVmRestore(null, template, userVm, diskOffering, details, false); + Assert.assertEquals(20 * GiB_TO_BYTES, actualSize.longValue()); + } } diff --git a/server/src/test/java/com/cloud/vpc/MockResourceLimitManagerImpl.java b/server/src/test/java/com/cloud/vpc/MockResourceLimitManagerImpl.java index 74e2a7e6545..3f3220d0934 100644 --- a/server/src/test/java/com/cloud/vpc/MockResourceLimitManagerImpl.java +++ b/server/src/test/java/com/cloud/vpc/MockResourceLimitManagerImpl.java @@ -278,6 +278,12 @@ public class MockResourceLimitManagerImpl extends ManagerBase implements Resourc } + @Override + public void checkPrimaryStorageResourceLimit(Account owner, Boolean display, Long size, + DiskOffering diskOffering) { + + } + @Override public void incrementVolumeResourceCount(long accountId, Boolean display, Long size, DiskOffering diskOffering) { diff --git a/test/integration/component/test_resource_limit_tags.py b/test/integration/component/test_resource_limit_tags.py index feb5c7820e2..916abff4db8 100644 --- a/test/integration/component/test_resource_limit_tags.py +++ b/test/integration/component/test_resource_limit_tags.py @@ -28,6 +28,7 @@ from marvin.lib.base import (Host, Domain, Zone, ServiceOffering, + Template, DiskOffering, VirtualMachine, Volume, @@ -56,6 +57,7 @@ class TestResourceLimitTags(cloudstackTestCase): def setUpClass(cls): testClient = super(TestResourceLimitTags, cls).getClsTestClient() cls.apiclient = testClient.getApiClient() + cls.hypervisor = testClient.getHypervisorInfo() cls.services = testClient.getParsedTestDataConfig() # Get Zone, Domain and templates @@ -646,3 +648,45 @@ class TestResourceLimitTags(cloudstackTestCase): expected_usage_total = 2 * expected_usage_total self.assertTrue(usage.total == expected_usage_total, "Usage for %s with tag %s is not matching for target account" % (usage.resourcetypename, usage.tag)) return + + @attr(tags=["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"], required_hardware="false") + def test_13_verify_restore_vm_limit(self): + """Test to verify limits are updated on restoring VM + """ + hypervisor = self.hypervisor.lower() + restore_template_service = self.services["test_templates"][ + hypervisor if hypervisor != 'simulator' else 'xenserver'].copy() + restore_template = Template.register(self.apiclient, restore_template_service, zoneid=self.zone.id, hypervisor=hypervisor, templatetag=self.host_tags[1]) + restore_template.download(self.apiclient) + self.cleanup.append(restore_template) + + self.vm = VirtualMachine.create( + self.userapiclient, + self.services["virtual_machine"], + templateid=restore_template.id, + serviceofferingid=self.host_storage_tagged_compute_offering.id, + mode=self.services["mode"] + ) + self.cleanup.append(self.vm) + old_root_vol = Volume.list(self.userapiclient, virtualmachineid=self.vm.id)[0] + + acc = Account.list( + self.userapiclient, + id=self.account.id + )[0] + tags = [self.host_storage_tagged_compute_offering.hosttags, self.host_storage_tagged_compute_offering.storagetags] + account_usage_before = list(filter(lambda x: x.tag in tags, acc['taggedresources'])) + + self.vm.restore(self.userapiclient, restore_template.id, rootdisksize=16, expunge=True) + acc = Account.list( + self.userapiclient, + id=self.account.id + )[0] + + account_usage_after = list(filter(lambda x: x.tag in tags, acc['taggedresources'])) + for idx, usage in enumerate(account_usage_after): + expected_usage_total = account_usage_before[idx].total + if usage.resourcetype in [10]: + expected_usage_total = expected_usage_total - old_root_vol.size + 16 * 1024 * 1024 * 1024 + self.assertTrue(usage.total == expected_usage_total, "Usage for %s with tag %s is not matching for target account" % (usage.resourcetypename, usage.tag)) + return diff --git a/test/integration/smoke/test_restore_vm.py b/test/integration/smoke/test_restore_vm.py index dd33346ed9e..aac33460da1 100644 --- a/test/integration/smoke/test_restore_vm.py +++ b/test/integration/smoke/test_restore_vm.py @@ -18,7 +18,7 @@ """ # Import Local Modules from marvin.cloudstackTestCase import cloudstackTestCase -from marvin.lib.base import (VirtualMachine, Volume, ServiceOffering, Template) +from marvin.lib.base import (VirtualMachine, Volume, DiskOffering, ServiceOffering, Template) from marvin.lib.common import (get_zone, get_domain) from nose.plugins.attrib import attr @@ -45,16 +45,19 @@ class TestRestoreVM(cloudstackTestCase): cls.service_offering = ServiceOffering.create(cls.apiclient, cls.services["service_offering"]) cls._cleanup.append(cls.service_offering) + cls.disk_offering = DiskOffering.create(cls.apiclient, cls.services["disk_offering"], disksize='8') + cls._cleanup.append(cls.disk_offering) + template_t1 = Template.register(cls.apiclient, cls.services["test_templates"][ cls.hypervisor.lower() if cls.hypervisor.lower() != 'simulator' else 'xenserver'], - zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower()) + zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower()) cls._cleanup.append(template_t1) template_t1.download(cls.apiclient) cls.template_t1 = Template.list(cls.apiclient, templatefilter='all', id=template_t1.id)[0] template_t2 = Template.register(cls.apiclient, cls.services["test_templates"][ cls.hypervisor.lower() if cls.hypervisor.lower() != 'simulator' else 'xenserver'], - zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower()) + zoneid=cls.zone.id, hypervisor=cls.hypervisor.lower()) cls._cleanup.append(template_t2) template_t2.download(cls.apiclient) cls.template_t2 = Template.list(cls.apiclient, templatefilter='all', id=template_t2.id)[0] @@ -74,20 +77,83 @@ class TestRestoreVM(cloudstackTestCase): serviceofferingid=self.service_offering.id) self._cleanup.append(virtual_machine) - root_vol = Volume.list(self.apiclient, virtualmachineid=virtual_machine.id)[0] - self.assertEqual(root_vol.state, 'Ready', "Volume should be in Ready state") - self.assertEqual(root_vol.size, self.template_t1.size, "Size of volume and template should match") + old_root_vol = Volume.list(self.apiclient, virtualmachineid=virtual_machine.id)[0] + self.assertEqual(old_root_vol.state, 'Ready', "Volume should be in Ready state") + self.assertEqual(old_root_vol.size, self.template_t1.size, "Size of volume and template should match") + + virtual_machine.restore(self.apiclient, self.template_t2.id, expunge=True) - virtual_machine.restore(self.apiclient, self.template_t2.id) restored_vm = VirtualMachine.list(self.apiclient, id=virtual_machine.id)[0] self.assertEqual(restored_vm.state, 'Running', "VM should be in a running state") self.assertEqual(restored_vm.templateid, self.template_t2.id, "VM's template after restore is incorrect") + root_vol = Volume.list(self.apiclient, virtualmachineid=restored_vm.id)[0] self.assertEqual(root_vol.state, 'Ready', "Volume should be in Ready state") self.assertEqual(root_vol.size, self.template_t2.size, "Size of volume and template should match") + old_root_vol = Volume.list(self.apiclient, id=old_root_vol.id) + self.assertEqual(old_root_vol, None, "Old volume should be deleted") + @attr(tags=["advanced", "basic"], required_hardware="false") - def test_02_restore_vm_allocated_root(self): + def test_02_restore_vm_with_disk_offering(self): + """Test restore virtual machine + """ + # create a virtual machine + virtual_machine = VirtualMachine.create(self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, + templateid=self.template_t1.id, + serviceofferingid=self.service_offering.id) + self._cleanup.append(virtual_machine) + + old_root_vol = Volume.list(self.apiclient, virtualmachineid=virtual_machine.id)[0] + self.assertEqual(old_root_vol.state, 'Ready', "Volume should be in Ready state") + self.assertEqual(old_root_vol.size, self.template_t1.size, "Size of volume and template should match") + + virtual_machine.restore(self.apiclient, self.template_t2.id, self.disk_offering.id, expunge=True) + + restored_vm = VirtualMachine.list(self.apiclient, id=virtual_machine.id)[0] + self.assertEqual(restored_vm.state, 'Running', "VM should be in a running state") + self.assertEqual(restored_vm.templateid, self.template_t2.id, "VM's template after restore is incorrect") + + root_vol = Volume.list(self.apiclient, virtualmachineid=restored_vm.id)[0] + self.assertEqual(root_vol.diskofferingid, self.disk_offering.id, "Disk offering id should match") + self.assertEqual(root_vol.state, 'Ready', "Volume should be in Ready state") + self.assertEqual(root_vol.size, self.disk_offering.disksize * 1024 * 1024 * 1024, + "Size of volume and disk offering should match") + + old_root_vol = Volume.list(self.apiclient, id=old_root_vol.id) + self.assertEqual(old_root_vol, None, "Old volume should be deleted") + + @attr(tags=["advanced", "basic"], required_hardware="false") + def test_03_restore_vm_with_disk_offering_custom_size(self): + """Test restore virtual machine + """ + # create a virtual machine + virtual_machine = VirtualMachine.create(self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, + templateid=self.template_t1.id, + serviceofferingid=self.service_offering.id) + self._cleanup.append(virtual_machine) + + old_root_vol = Volume.list(self.apiclient, virtualmachineid=virtual_machine.id)[0] + self.assertEqual(old_root_vol.state, 'Ready', "Volume should be in Ready state") + self.assertEqual(old_root_vol.size, self.template_t1.size, "Size of volume and template should match") + + virtual_machine.restore(self.apiclient, self.template_t2.id, self.disk_offering.id, rootdisksize=16) + + restored_vm = VirtualMachine.list(self.apiclient, id=virtual_machine.id)[0] + self.assertEqual(restored_vm.state, 'Running', "VM should be in a running state") + self.assertEqual(restored_vm.templateid, self.template_t2.id, "VM's template after restore is incorrect") + + root_vol = Volume.list(self.apiclient, virtualmachineid=restored_vm.id)[0] + self.assertEqual(root_vol.diskofferingid, self.disk_offering.id, "Disk offering id should match") + self.assertEqual(root_vol.state, 'Ready', "Volume should be in Ready state") + self.assertEqual(root_vol.size, 16 * 1024 * 1024 * 1024, "Size of volume and custom disk size should match") + + old_root_vol = Volume.list(self.apiclient, id=old_root_vol.id)[0] + self.assertEqual(old_root_vol.state, "Destroy", "Old volume should be in Destroy state") + Volume.delete(old_root_vol, self.apiclient) + + @attr(tags=["advanced", "basic"], required_hardware="false") + def test_04_restore_vm_allocated_root(self): """Test restore virtual machine with root disk in allocated state """ # create a virtual machine with allocated root disk by setting startvm=False @@ -96,9 +162,9 @@ class TestRestoreVM(cloudstackTestCase): serviceofferingid=self.service_offering.id, startvm=False) self._cleanup.append(virtual_machine) - root_vol = Volume.list(self.apiclient, virtualmachineid=virtual_machine.id)[0] - self.assertEqual(root_vol.state, 'Allocated', "Volume should be in Allocated state") - self.assertEqual(root_vol.size, self.template_t1.size, "Size of volume and template should match") + old_root_vol = Volume.list(self.apiclient, virtualmachineid=virtual_machine.id)[0] + self.assertEqual(old_root_vol.state, 'Allocated', "Volume should be in Allocated state") + self.assertEqual(old_root_vol.size, self.template_t1.size, "Size of volume and template should match") virtual_machine.restore(self.apiclient, self.template_t2.id) restored_vm = VirtualMachine.list(self.apiclient, id=virtual_machine.id)[0] @@ -112,3 +178,6 @@ class TestRestoreVM(cloudstackTestCase): virtual_machine.start(self.apiclient) root_vol = Volume.list(self.apiclient, virtualmachineid=restored_vm.id)[0] self.assertEqual(root_vol.state, 'Ready', "Volume should be in Ready state") + + old_root_vol = Volume.list(self.apiclient, id=old_root_vol.id) + self.assertEqual(old_root_vol, None, "Old volume should be deleted") diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py index 04d4e6810c4..a855908eb0d 100755 --- a/tools/marvin/marvin/lib/base.py +++ b/tools/marvin/marvin/lib/base.py @@ -776,12 +776,25 @@ class VirtualMachine: if response[0] == FAIL: raise Exception(response[1]) - def restore(self, apiclient, templateid=None): + def restore(self, apiclient, templateid=None, diskofferingid=None, rootdisksize=None, expunge=None, details=None): """Restore the instance""" cmd = restoreVirtualMachine.restoreVirtualMachineCmd() cmd.virtualmachineid = self.id if templateid: cmd.templateid = templateid + if diskofferingid: + cmd.diskofferingid = diskofferingid + if rootdisksize: + cmd.rootdisksize = rootdisksize + if expunge is not None: + cmd.expunge = expunge + if details: + for key, value in list(details.items()): + cmd.details.append({ + 'key': key, + 'value': value + }) + return apiclient.restoreVirtualMachine(cmd) def get_ssh_client( @@ -1457,7 +1470,7 @@ class Template: @classmethod def register(cls, apiclient, services, zoneid=None, account=None, domainid=None, hypervisor=None, - projectid=None, details=None, randomize_name=True): + projectid=None, details=None, randomize_name=True, templatetag=None): """Create template from URL""" # Create template from Virtual machine and Volume ID @@ -1522,6 +1535,9 @@ class Template: if details: cmd.details = details + if templatetag: + cmd.templatetag = templatetag + if "directdownload" in services: cmd.directdownload = services["directdownload"] if "checksum" in services: From c791c138e75649b604d42f56d7d185a34fe30ce3 Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Fri, 10 May 2024 23:41:37 +0530 Subject: [PATCH 0069/1050] ui: change reporting link to Github Discussions (#9023) * ui: change reporting link to Github Discussions Many users are using the footer link to open questions about CloudStack that are usually discussed on the users@ mailing list. This fixes that behaviour by diverting them to Github Discussions which are linked with the user@ ML, smart users can still report actual bugs/issues via the issues tab. Signed-off-by: Rohit Yadav * Update en.json --------- Signed-off-by: Rohit Yadav --- ui/public/locales/en.json | 2 +- ui/src/components/page/GlobalFooter.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index b11a8f864fb..d7e3c51c1ea 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -1613,7 +1613,7 @@ "label.removing": "Removing", "label.replace.acl": "Replace ACL", "label.replace.acl.list": "Replace ACL list", -"label.report.bug": "Report issue", +"label.report.bug": "Ask a question or Report an issue", "label.required": "Required", "label.requireshvm": "HVM", "label.requiresupgrade": "Requires upgrade", diff --git a/ui/src/components/page/GlobalFooter.vue b/ui/src/components/page/GlobalFooter.vue index 86c8948e564..854cecc78ac 100644 --- a/ui/src/components/page/GlobalFooter.vue +++ b/ui/src/components/page/GlobalFooter.vue @@ -23,7 +23,7 @@
CloudStack {{ $store.getters.features.cloudstackversion }} - + {{ $t('label.report.bug') }} From f0df8d7831ae13f8ef8411dfbaae12041e4590bc Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 20 May 2024 14:45:01 +0530 Subject: [PATCH 0070/1050] 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 0071/1050] 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 5f73172bcbe975e4ef416e525dc95bad63fa6d3a Mon Sep 17 00:00:00 2001 From: Wei Zhou Date: Wed, 22 May 2024 14:11:51 +0200 Subject: [PATCH 0072/1050] Fix failure test with ConfigKeyScheduledExecutionWrapperTest (#9103) --- .../config/ConfigKeyScheduledExecutionWrapperTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/framework/config/src/test/java/org/apache/cloudstack/framework/config/ConfigKeyScheduledExecutionWrapperTest.java b/framework/config/src/test/java/org/apache/cloudstack/framework/config/ConfigKeyScheduledExecutionWrapperTest.java index fbb4dc24fca..0eb2f6286ca 100644 --- a/framework/config/src/test/java/org/apache/cloudstack/framework/config/ConfigKeyScheduledExecutionWrapperTest.java +++ b/framework/config/src/test/java/org/apache/cloudstack/framework/config/ConfigKeyScheduledExecutionWrapperTest.java @@ -20,6 +20,7 @@ import com.cloud.utils.concurrency.NamedThreadFactory; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import java.util.concurrent.Executors; @@ -58,8 +59,8 @@ public class ConfigKeyScheduledExecutionWrapperTest { @Test(expected = IllegalArgumentException.class) public void invalidConfigKeyTest() { TestRunnable runnable = new TestRunnable(); - ConfigKey configKey = new ConfigKey<>(String.class, "test", "test", "test", "test", true, - ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.CSV, null); + ConfigKey configKey = Mockito.mock(ConfigKey.class); + when(configKey.value()).thenReturn("test"); ConfigKeyScheduledExecutionWrapper runner = new ConfigKeyScheduledExecutionWrapper(executorService, runnable, configKey, TimeUnit.SECONDS); } From 2a63483b4c5f234fa441cb5a5477aa59c9e196ee Mon Sep 17 00:00:00 2001 From: Rohit Yadav Date: Wed, 22 May 2024 20:20:15 +0530 Subject: [PATCH 0073/1050] framework/config: make logic in ::value() defensive (#9108) This adds a NPE check on the s_depot.global() which can cause NPE in case of unit tests, where s_depot is not null but the underlying config dao is null (not mocked or initialised) via `s_depot.global()` becomes null. This reverts commit 5f73172bcbe975e4ef416e525dc95bad63fa6d3a. Signed-off-by: Rohit Yadav --- .../org/apache/cloudstack/framework/config/ConfigKey.java | 2 +- .../config/ConfigKeyScheduledExecutionWrapperTest.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java b/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java index df93f78fa83..46923de3c7c 100644 --- a/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java +++ b/framework/config/src/main/java/org/apache/cloudstack/framework/config/ConfigKey.java @@ -211,7 +211,7 @@ public class ConfigKey { public T value() { if (_value == null || isDynamic()) { - ConfigurationVO vo = s_depot != null ? s_depot.global().findById(key()) : null; + ConfigurationVO vo = (s_depot != null && s_depot.global() != null) ? s_depot.global().findById(key()) : null; final String value = (vo != null && vo.getValue() != null) ? vo.getValue() : defaultValue(); _value = ((value == null) ? (T)defaultValue() : valueOf(value)); } diff --git a/framework/config/src/test/java/org/apache/cloudstack/framework/config/ConfigKeyScheduledExecutionWrapperTest.java b/framework/config/src/test/java/org/apache/cloudstack/framework/config/ConfigKeyScheduledExecutionWrapperTest.java index 0eb2f6286ca..fbb4dc24fca 100644 --- a/framework/config/src/test/java/org/apache/cloudstack/framework/config/ConfigKeyScheduledExecutionWrapperTest.java +++ b/framework/config/src/test/java/org/apache/cloudstack/framework/config/ConfigKeyScheduledExecutionWrapperTest.java @@ -20,7 +20,6 @@ import com.cloud.utils.concurrency.NamedThreadFactory; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import java.util.concurrent.Executors; @@ -59,8 +58,8 @@ public class ConfigKeyScheduledExecutionWrapperTest { @Test(expected = IllegalArgumentException.class) public void invalidConfigKeyTest() { TestRunnable runnable = new TestRunnable(); - ConfigKey configKey = Mockito.mock(ConfigKey.class); - when(configKey.value()).thenReturn("test"); + ConfigKey configKey = new ConfigKey<>(String.class, "test", "test", "test", "test", true, + ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.CSV, null); ConfigKeyScheduledExecutionWrapper runner = new ConfigKeyScheduledExecutionWrapper(executorService, runnable, configKey, TimeUnit.SECONDS); } From c6762f1a41d8076b26a36cb4123c5538decf93fa Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 23 May 2024 16:04:32 +0530 Subject: [PATCH 0074/1050] 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 0075/1050] 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 0076/1050] 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 0077/1050] 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 0078/1050] 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 0079/1050] 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 0080/1050] 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 0081/1050] 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 0082/1050] 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 0083/1050] 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 0084/1050] 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 @@ - - + - + - + - + - + - + - + - + - +