diff --git a/.asf.yaml b/.asf.yaml index 8c1a5d51fdf1..dabefa1eb544 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -58,7 +58,10 @@ github: - gpordeus - hsato03 - bernardodemarco +<<<<<<< HEAD +======= - abh1sar +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 protected_branches: ~ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51c0b006c4a7..f34a350b9e9e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -86,8 +86,12 @@ jobs: smoke/test_migration smoke/test_multipleips_per_nic smoke/test_nested_virtualization +<<<<<<< HEAD + smoke/test_set_sourcenat", +======= smoke/test_set_sourcenat smoke/test_webhook_lifecycle", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "smoke/test_network smoke/test_network_acl smoke/test_network_ipv6 diff --git a/agent/conf/cloudstack-agent.logrotate.in b/agent/conf/cloudstack-agent.logrotate.in index 9f22b4bab868..cab7bfa12f40 100644 --- a/agent/conf/cloudstack-agent.logrotate.in +++ b/agent/conf/cloudstack-agent.logrotate.in @@ -15,13 +15,20 @@ # specific language governing permissions and limitations # under the License. +<<<<<<< HEAD +/var/log/cloudstack/agent/security_group.log /var/log/cloudstack/agent/resizevolume.log /var/log/cloudstack/agent/rolling-maintenance.log { +======= /var/log/cloudstack/agent/security_group.log /var/log/cloudstack/agent/resizevolume.log /var/log/cloudstack/agent/rolling-maintenance.log /var/log/cloudstack/agent/agent.out /var/log/cloudstack/agent/agent.err { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 copytruncate daily rotate 5 compress missingok size 10M +<<<<<<< HEAD +======= dateext dateformat -%Y-%m-%d +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/agent/conf/log4j-cloud.xml.in b/agent/conf/log4j-cloud.xml.in index 29c1d5ee6415..222c013fbfdc 100644 --- a/agent/conf/log4j-cloud.xml.in +++ b/agent/conf/log4j-cloud.xml.in @@ -38,7 +38,11 @@ under the License. +<<<<<<< HEAD + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 diff --git a/agent/src/test/java/com/cloud/agent/AgentShellTest.java b/agent/src/test/java/com/cloud/agent/AgentShellTest.java index 4126692546f2..ef6ebe51c6b1 100644 --- a/agent/src/test/java/com/cloud/agent/AgentShellTest.java +++ b/agent/src/test/java/com/cloud/agent/AgentShellTest.java @@ -350,6 +350,8 @@ public void setHostTestValueIsNullPropertyDoesNotStartAndEndWithAtSignSetHosts() Mockito.verify(agentShellSpy).setHosts(expected); } +<<<<<<< HEAD +======= @Test public void updateAndGetConnectedHost() { @@ -362,4 +364,5 @@ public void updateAndGetConnectedHost() { Assert.assertEquals(expected, shell.getConnectedHost()); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/api/src/main/java/com/cloud/event/EventTypes.java b/api/src/main/java/com/cloud/event/EventTypes.java index 689676290b36..c26acb021edb 100644 --- a/api/src/main/java/com/cloud/event/EventTypes.java +++ b/api/src/main/java/com/cloud/event/EventTypes.java @@ -29,9 +29,15 @@ import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.config.Configuration; import org.apache.cloudstack.ha.HAConfig; +<<<<<<< HEAD +import org.apache.cloudstack.storage.object.Bucket; +import org.apache.cloudstack.storage.object.ObjectStore; +import org.apache.cloudstack.quota.QuotaTariff; +======= import org.apache.cloudstack.quota.QuotaTariff; import org.apache.cloudstack.storage.object.Bucket; import org.apache.cloudstack.storage.object.ObjectStore; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.usage.Usage; import org.apache.cloudstack.vm.schedule.VMSchedule; @@ -1229,8 +1235,11 @@ public static Class getEntityClassForEvent(String eventName) { public static boolean isVpcEvent(String eventType) { return EventTypes.EVENT_VPC_CREATE.equals(eventType) || EventTypes.EVENT_VPC_DELETE.equals(eventType); } +<<<<<<< HEAD +======= public static void addEntityEventDetail(String event, Class clazz) { entityEventDetails.put(event, clazz); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterHelper.java b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterHelper.java new file mode 100644 index 000000000000..e160227749db --- /dev/null +++ b/api/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterHelper.java @@ -0,0 +1,26 @@ +// 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.kubernetes.cluster; + +import com.cloud.utils.component.Adapter; +import org.apache.cloudstack.acl.ControlledEntity; + +public interface KubernetesClusterHelper extends Adapter { + + ControlledEntity findByUuid(String uuid); + ControlledEntity findByVmId(long vmId); +} diff --git a/api/src/main/java/com/cloud/network/NetworkService.java b/api/src/main/java/com/cloud/network/NetworkService.java index b8dd464b3655..97a7f40132e3 100644 --- a/api/src/main/java/com/cloud/network/NetworkService.java +++ b/api/src/main/java/com/cloud/network/NetworkService.java @@ -20,7 +20,10 @@ import java.util.Map; import com.cloud.dc.DataCenter; +<<<<<<< HEAD +======= import org.apache.cloudstack.acl.ControlledEntity; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.command.admin.address.ReleasePodIpCmdByAdmin; import org.apache.cloudstack.api.command.admin.network.DedicateGuestVlanRangeCmd; import org.apache.cloudstack.api.command.admin.network.ListDedicatedGuestVlanRangesCmd; @@ -103,10 +106,13 @@ IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long ne Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException; +<<<<<<< HEAD +======= Network createGuestNetwork(long networkOfferingId, String name, String displayText, Account owner, PhysicalNetwork physicalNetwork, long zoneId, ControlledEntity.ACLType aclType) throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Pair, Integer> searchForNetworks(ListNetworksCmd cmd); boolean deleteNetwork(long networkId, boolean forced); diff --git a/api/src/main/java/com/cloud/network/vpc/VpcService.java b/api/src/main/java/com/cloud/network/vpc/VpcService.java index 0f0d29f4082c..ae3a8c4f65f0 100644 --- a/api/src/main/java/com/cloud/network/vpc/VpcService.java +++ b/api/src/main/java/com/cloud/network/vpc/VpcService.java @@ -132,8 +132,11 @@ Pair, Integer> listVpcs(Long id, String vpcName, String disp */ boolean startVpc(long vpcId, boolean destroyOnFailure) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; +<<<<<<< HEAD +======= void startVpc(CreateVPCCmd cmd) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 /** * Shuts down the VPC which includes shutting down all VPC provider and rules cleanup on the backend * diff --git a/api/src/main/java/com/cloud/user/ResourceLimitService.java b/api/src/main/java/com/cloud/user/ResourceLimitService.java index 3b30b8fc4a57..ae975e550ee6 100644 --- a/api/src/main/java/com/cloud/user/ResourceLimitService.java +++ b/api/src/main/java/com/cloud/user/ResourceLimitService.java @@ -38,10 +38,14 @@ public interface ResourceLimitService { static final ConfigKey MaxProjectSecondaryStorage = new ConfigKey<>("Project Defaults", Long.class, "max.project.secondary.storage", "400", "The default maximum secondary storage space (in GiB) that can be used for a project", false); static final ConfigKey ResourceCountCheckInterval = new ConfigKey<>("Advanced", Long.class, "resourcecount.check.interval", "300", +<<<<<<< HEAD + "Time (in seconds) to wait before running resource recalculation and fixing task. Default is 300 seconds, Setting this to 0 disables execution of the task", true); +======= "Time (in seconds) to wait before running resource recalculation and fixing tasks like stale resource reservation cleanup" + ". Default is 300 seconds, Setting this to 0 disables execution of the task", true); static final ConfigKey ResourceReservationCleanupDelay = new ConfigKey<>("Advanced", Long.class, "resource.reservation.cleanup.delay", "3600", "Time (in seconds) after which a resource reservation gets deleted. Default is 3600 seconds, Setting this to 0 disables execution of the task", true); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 static final ConfigKey ResourceLimitHostTags = new ConfigKey<>("Advanced", String.class, "resource.limit.host.tags", "", "A comma-separated list of tags for host resource limits", true); static final ConfigKey ResourceLimitStorageTags = new ConfigKey<>("Advanced", String.class, "resource.limit.storage.tags", "", diff --git a/api/src/main/java/com/cloud/uservm/UserVm.java b/api/src/main/java/com/cloud/uservm/UserVm.java index 9035d2903c9a..5e32fbb370fb 100644 --- a/api/src/main/java/com/cloud/uservm/UserVm.java +++ b/api/src/main/java/com/cloud/uservm/UserVm.java @@ -48,6 +48,9 @@ public interface UserVm extends VirtualMachine, ControlledEntity { void setAccountId(long accountId); public boolean isDisplayVm(); +<<<<<<< HEAD +======= String getUserVmType(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/api/src/main/java/com/cloud/vm/UserVmService.java b/api/src/main/java/com/cloud/vm/UserVmService.java index a30c4491f9dd..4e0eb1690e08 100644 --- a/api/src/main/java/com/cloud/vm/UserVmService.java +++ b/api/src/main/java/com/cloud/vm/UserVmService.java @@ -45,7 +45,10 @@ import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.ManagementServerException; +<<<<<<< HEAD +======= import com.cloud.exception.OperationTimedoutException; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.StorageUnavailableException; @@ -67,7 +70,14 @@ public interface UserVmService { /** * Destroys one virtual machine * +<<<<<<< HEAD + * @param userId + * the id of the user performing the action + * @param vmId + * the id of the virtual machine. +======= * @param cmd the API Command Object containg the parameters to use for this service action +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 * @throws ConcurrentOperationException * @throws ResourceUnavailableException */ @@ -110,8 +120,11 @@ UserVm startVirtualMachine(StartVMCmd cmd) throws StorageUnavailableException, E UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ResourceAllocationException; +<<<<<<< HEAD +======= void startVirtualMachine(UserVm vm) throws OperationTimedoutException, ResourceUnavailableException, InsufficientCapacityException; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException; /** @@ -148,6 +161,17 @@ UserVm startVirtualMachine(StartVMCmd cmd) throws StorageUnavailableException, E * Creates a Basic Zone User VM in the database and returns the VM to the * caller. * +<<<<<<< HEAD + * + * + * @param sshKeyPair + * - name of the ssh key pair used to login to the virtual + * machine + * @param cpuSpeed + * @param memory + * @param cpuNumber +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 * @param zone * - availability zone for the virtual machine * @param serviceOffering @@ -223,6 +247,12 @@ UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering s * Creates a User VM in Advanced Zone (Security Group feature is enabled) in * the database and returns the VM to the caller. * +<<<<<<< HEAD + * + * + * @param type +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 * @param zone * - availability zone for the virtual machine * @param serviceOffering @@ -298,6 +328,17 @@ UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOfferin * Creates a User VM in Advanced Zone (Security Group feature is disabled) * in the database and returns the VM to the caller. * +<<<<<<< HEAD + * + * + * @param sshKeyPair + * - name of the ssh key pair used to login to the virtual + * machine + * @param cpuSpeed + * @param memory + * @param cpuNumber +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 * @param zone * - availability zone for the virtual machine * @param serviceOffering diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java b/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java index 938936765167..ab6966c8f223 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiCommandResourceType.java @@ -17,9 +17,13 @@ package org.apache.cloudstack.api; import java.util.ArrayList; +<<<<<<< HEAD +import java.util.List; +======= import java.util.HashMap; import java.util.List; import java.util.Map; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.region.PortableIp; import org.apache.commons.collections.CollectionUtils; @@ -83,6 +87,12 @@ public enum ApiCommandResourceType { ManagementServer(org.apache.cloudstack.management.ManagementServerHost.class), ObjectStore(org.apache.cloudstack.storage.object.ObjectStore.class), Bucket(org.apache.cloudstack.storage.object.Bucket.class), +<<<<<<< HEAD + QuotaTariff(org.apache.cloudstack.quota.QuotaTariff.class); + + private final Class clazz; + +======= QuotaTariff(org.apache.cloudstack.quota.QuotaTariff.class), KubernetesCluster(null), KubernetesSupportedVersion(null); @@ -91,14 +101,18 @@ public enum ApiCommandResourceType { static final Map> additionalClassMappings = new HashMap<>(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private ApiCommandResourceType(Class clazz) { this.clazz = clazz; } public Class getAssociatedClass() { +<<<<<<< HEAD +======= if (this.clazz == null && additionalClassMappings.containsKey(this)) { return additionalClassMappings.get(this); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return this.clazz; } @@ -128,8 +142,11 @@ public static ApiCommandResourceType fromString(String value) { } return null; } +<<<<<<< HEAD +======= public static void setClassMapping(ApiCommandResourceType type, Class clazz) { additionalClassMappings.put(type, clazz); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } 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 54c0227de9fa..48a7d4e62015 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -175,8 +175,11 @@ public class ApiConstants { public static final String END_IPV6 = "endipv6"; public static final String END_PORT = "endport"; public static final String ENTRY_TIME = "entrytime"; +<<<<<<< HEAD +======= public static final String EVENT_ID = "eventid"; public static final String EVENT_TYPE = "eventtype"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public static final String EXPIRES = "expires"; public static final String EXTRA_CONFIG = "extraconfig"; public static final String EXTRA_DHCP_OPTION = "extradhcpoption"; @@ -211,7 +214,10 @@ public class ApiConstants { public static final String HA_PROVIDER = "haprovider"; public static final String HA_STATE = "hastate"; public static final String HEALTH = "health"; +<<<<<<< HEAD +======= public static final String HEADERS = "headers"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public static final String HIDE_IP_ADDRESS_USAGE = "hideipaddressusage"; public static final String HOST_ID = "hostid"; public static final String HOST_IDS = "hostids"; @@ -266,7 +272,10 @@ public class ApiConstants { public static final String IS_CLEANUP_REQUIRED = "iscleanuprequired"; public static final String IS_DYNAMIC = "isdynamic"; public static final String IS_EDGE = "isedge"; +<<<<<<< HEAD +======= public static final String IS_ENCRYPTED = "isencrypted"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public static final String IS_EXTRACTABLE = "isextractable"; public static final String IS_FEATURED = "isfeatured"; public static final String IS_IMPLICIT = "isimplicit"; @@ -285,7 +294,10 @@ public class ApiConstants { public static final String JOB_STATUS = "jobstatus"; public static final String KEEPALIVE_ENABLED = "keepaliveenabled"; public static final String KERNEL_VERSION = "kernelversion"; +<<<<<<< HEAD +======= public static final String KEY = "key"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public static final String LABEL = "label"; public static final String LASTNAME = "lastname"; public static final String LAST_BOOT = "lastboottime"; @@ -360,7 +372,10 @@ public class ApiConstants { public static final String SSHKEY_ENABLED = "sshkeyenabled"; public static final String PATH = "path"; public static final String PAYLOAD = "payload"; +<<<<<<< HEAD +======= public static final String PAYLOAD_URL = "payloadurl"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public static final String POD_ID = "podid"; public static final String POD_NAME = "podname"; public static final String POD_IDS = "podids"; @@ -406,9 +421,17 @@ public class ApiConstants { public static final String QUERY_FILTER = "queryfilter"; public static final String SCHEDULE = "schedule"; public static final String SCOPE = "scope"; +<<<<<<< HEAD + public static final String SECRET_KEY = "usersecretkey"; + public static final String SECONDARY_IP = "secondaryip"; + public static final String SINCE = "since"; + public static final String KEY = "key"; + public static final String SEARCH_BASE = "searchbase"; +======= public static final String SEARCH_BASE = "searchbase"; public static final String SECONDARY_IP = "secondaryip"; public static final String SECRET_KEY = "secretkey"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public static final String SECURITY_GROUP_IDS = "securitygroupids"; public static final String SECURITY_GROUP_NAMES = "securitygroupnames"; public static final String SECURITY_GROUP_NAME = "securitygroupname"; @@ -426,7 +449,10 @@ public class ApiConstants { public static final String SHOW_UNIQUE = "showunique"; public static final String SIGNATURE = "signature"; public static final String SIGNATURE_VERSION = "signatureversion"; +<<<<<<< HEAD +======= public static final String SINCE = "since"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public static final String SIZE = "size"; public static final String SNAPSHOT = "snapshot"; public static final String SNAPSHOT_ID = "snapshotid"; @@ -434,7 +460,12 @@ public class ApiConstants { public static final String SNAPSHOT_TYPE = "snapshottype"; public static final String SNAPSHOT_QUIESCEVM = "quiescevm"; public static final String SOURCE_ZONE_ID = "sourcezoneid"; +<<<<<<< HEAD + public static final String SUITABLE_FOR_VM = "suitableforvirtualmachine"; + public static final String SUPPORTS_STORAGE_SNAPSHOT = "supportsstoragesnapshot"; +======= public static final String SSL_VERIFICATION = "sslverification"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public static final String START_DATE = "startdate"; public static final String START_ID = "startid"; public static final String START_IP = "startip"; @@ -453,9 +484,12 @@ public class ApiConstants { public static final String SYSTEM_VM_TYPE = "systemvmtype"; public static final String TAGS = "tags"; public static final String STORAGE_TAGS = "storagetags"; +<<<<<<< HEAD +======= public static final String SUCCESS = "success"; public static final String SUITABLE_FOR_VM = "suitableforvirtualmachine"; public static final String SUPPORTS_STORAGE_SNAPSHOT = "supportsstoragesnapshot"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public static final String TARGET_IQN = "targetiqn"; public static final String TEMPLATE_FILTER = "templatefilter"; public static final String TEMPLATE_ID = "templateid"; @@ -489,7 +523,10 @@ public class ApiConstants { public static final String USERNAME = "username"; public static final String USER_CONFIGURABLE = "userconfigurable"; public static final String USER_SECURITY_GROUP_LIST = "usersecuritygrouplist"; +<<<<<<< HEAD +======= public static final String USER_SECRET_KEY = "usersecretkey"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public static final String USE_VIRTUAL_NETWORK = "usevirtualnetwork"; public static final String UPDATE_IN_SEQUENCE = "updateinsequence"; public static final String VALUE = "value"; @@ -569,7 +606,10 @@ public class ApiConstants { public static final String ALLOCATION_STATE = "allocationstate"; public static final String MANAGED_STATE = "managedstate"; public static final String MANAGEMENT_SERVER_ID = "managementserverid"; +<<<<<<< HEAD +======= public static final String MANAGEMENT_SERVER_NAME = "managementservername"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public static final String STORAGE = "storage"; public static final String STORAGE_ID = "storageid"; public static final String PING_STORAGE_SERVER_IP = "pingstorageserverip"; @@ -1130,9 +1170,12 @@ public class ApiConstants { public static final String PARAMETER_DESCRIPTION_IS_TAG_A_RULE = "Whether the informed tag is a JS interpretable rule or not."; +<<<<<<< HEAD +======= public static final String WEBHOOK_ID = "webhookid"; public static final String WEBHOOK_NAME = "webhookname"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 /** * This enum specifies IO Drivers, each option controls specific policies on I/O. * Qemu guests support "threads" and "native" options Since 0.8.8 ; "io_uring" is supported Since 6.3.0 (QEMU 5.0). diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java index 4dfa76bb9dbe..82b803ea91df 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java @@ -54,11 +54,15 @@ public class CreateServiceOfferingCmd extends BaseCmd { @Parameter(name = ApiConstants.CPU_NUMBER, type = CommandType.INTEGER, required = false, description = "the CPU number of the service offering") private Integer cpuNumber; +<<<<<<< HEAD + @Parameter(name = ApiConstants.CPU_SPEED, type = CommandType.INTEGER, required = false, description = "the CPU speed of the service offering in MHz.") +======= @Parameter(name = ApiConstants.CPU_SPEED, type = CommandType.INTEGER, required = false, description = "For VMware and Xen based hypervisors this is the CPU speed of the service offering in MHz.\n" + "For the KVM hypervisor," + " the values of the parameters cpuSpeed and cpuNumber will be used to calculate the `shares` value. This value is used by the KVM hypervisor to calculate how much time" + " the VM will have access to the host's CPU. The `shares` value does not have a unit, and its purpose is being a weight value for the host to compare between its guest" + " VMs. For more information, see https://libvirt.org/formatdomain.html#cpu-tuning.") +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private Integer cpuSpeed; @Parameter(name = ApiConstants.DISPLAY_TEXT, type = CommandType.STRING, description = "The display text of the service offering, defaults to 'name'.") diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java index c9e1e934152d..62b935d9bdb7 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java @@ -66,7 +66,11 @@ public class UpdateUserCmd extends BaseCmd { @Parameter(name = ApiConstants.CURRENT_PASSWORD, type = CommandType.STRING, description = "Current password that was being used by the user. You must inform the current password when updating the password.", acceptedOnAdminPort = false) private String currentPassword; +<<<<<<< HEAD + @Parameter(name = ApiConstants.SECRET_KEY, type = CommandType.STRING, description = "The secret key for the user. Must be specified with userApiKey") +======= @Parameter(name = ApiConstants.USER_SECRET_KEY, type = CommandType.STRING, description = "The secret key for the user. Must be specified with userApiKey") +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private String secretKey; @Parameter(name = ApiConstants.TIMEZONE, diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java index 49c6ee605c8c..98cd6ebf26f8 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java @@ -34,11 +34,16 @@ import com.cloud.configuration.ResourceCount; import com.cloud.user.Account; +<<<<<<< HEAD +@APICommand(name = "updateResourceCount", description = "Recalculate and update resource count for an account or domain.", responseObject = ResourceCountResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +======= @APICommand(name = "updateResourceCount", description = "Recalculate and update resource count for an account or domain. " + "This also executes some cleanup tasks before calculating resource counts.", responseObject = ResourceCountResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public class UpdateResourceCountCmd extends BaseCmd { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMScheduleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMScheduleCmd.java index 5811eb1abfc5..d751eb09be72 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMScheduleCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMScheduleCmd.java @@ -68,7 +68,11 @@ public class CreateVMScheduleCmd extends BaseCmd { @Parameter(name = ApiConstants.ACTION, type = CommandType.STRING, required = true, +<<<<<<< HEAD + description = "Action to take on the VM (start/stop/restart/force_stop/force_reboot).") +======= description = "Action to take on the VM (start/stop/reboot/force_stop/force_reboot).") +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private String action; @Parameter(name = ApiConstants.START_DATE, diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java index 50e1798112d2..f7e9f2cc9ddb 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java @@ -16,10 +16,16 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; +<<<<<<< HEAD +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; +======= import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Set; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.affinity.AffinityGroupResponse; @@ -46,7 +52,10 @@ import org.apache.cloudstack.api.response.VpcResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.commons.lang3.BooleanUtils; +<<<<<<< HEAD +======= import org.apache.commons.collections.CollectionUtils; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.exception.InvalidParameterValueException; import com.cloud.server.ResourceIcon; @@ -58,6 +67,10 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements UserCmd { +<<<<<<< HEAD + private static final String s_name = "listvirtualmachinesresponse"; +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -97,8 +110,12 @@ public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements collectionType = CommandType.STRING, description = "comma separated list of vm details requested, " + "value can be a list of [all, group, nics, stats, secgrp, tmpl, servoff, diskoff, backoff, iso, volume, min, affgrp]." +<<<<<<< HEAD + + " If no parameter is passed in, the details will be defaulted to all") +======= + " When no parameters are passed, all the details are returned if list.vm.default.details.stats is true (default)," + " otherwise when list.vm.default.details.stats is false the API response will exclude the stats details.") +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private List viewDetails; @Parameter(name = ApiConstants.TEMPLATE_ID, type = CommandType.UUID, entityType = TemplateResponse.class, description = "list vms by template") @@ -239,6 +256,24 @@ public Long getAutoScaleVmGroupId() { return autoScaleVmGroupId; } +<<<<<<< HEAD + public EnumSet getDetails() throws InvalidParameterValueException { + EnumSet dv; + if (viewDetails == null || viewDetails.size() <= 0) { + dv = EnumSet.of(VMDetails.all); + } else { + try { + ArrayList dc = new ArrayList(); + for (String detail : viewDetails) { + dc.add(VMDetails.valueOf(detail)); + } + dv = EnumSet.copyOf(dc); + } catch (IllegalArgumentException e) { + throw new InvalidParameterValueException("The details parameter contains a non permitted value. The allowed values are " + EnumSet.allOf(VMDetails.class)); + } + } + return dv; +======= protected boolean isViewDetailsEmpty() { return CollectionUtils.isEmpty(viewDetails); } @@ -265,6 +300,7 @@ public EnumSet getDetails() throws InvalidParameterValueException { } catch (IllegalArgumentException e) { throw new InvalidParameterValueException("The details parameter contains a non permitted value. The allowed values are " + EnumSet.allOf(VMDetails.class)); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } @Override @@ -287,6 +323,13 @@ public Boolean getVnf() { ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// +<<<<<<< HEAD + @Override + public String getCommandName() { + return s_name; + } +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Override public ApiCommandResourceType getApiResourceType() { diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java index a1024a988981..59f6345c67ef 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java @@ -31,7 +31,10 @@ import org.apache.cloudstack.api.response.HostResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.PodResponse; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.response.ServiceOfferingResponse; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.VolumeResponse; @@ -81,12 +84,15 @@ public class ListVolumesCmd extends BaseListRetrieveOnlyResourceCountCmd impleme RoleType.Admin}) private String storageId; +<<<<<<< HEAD +======= @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, type = CommandType.UUID, entityType = ServiceOfferingResponse.class, description = "list volumes by disk offering of a service offering. If both service offering and " + "disk offering are passed, service offering is ignored", since = "4.19.1") private Long serviceOfferingId; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Parameter(name = ApiConstants.DISK_OFFERING_ID, type = CommandType.UUID, entityType = DiskOfferingResponse.class, description = "list volumes by disk offering", since = "4.4") private Long diskOfferingId; @@ -101,9 +107,12 @@ public class ListVolumesCmd extends BaseListRetrieveOnlyResourceCountCmd impleme @Parameter(name = ApiConstants.STATE, type = CommandType.STRING, description = "state of the volume. Possible values are: Ready, Allocated, Destroy, Expunging, Expunged.") private String state; +<<<<<<< HEAD +======= @Parameter(name = ApiConstants.IS_ENCRYPTED, type = CommandType.BOOLEAN, description = "list only volumes that are encrypted", since = "4.19.1", authorized = { RoleType.Admin }) private Boolean encrypted; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -128,10 +137,13 @@ public Long getPodId() { return podId; } +<<<<<<< HEAD +======= public Long getServiceOfferingId() { return serviceOfferingId; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public Long getDiskOfferingId() { return diskOfferingId; } @@ -165,10 +177,13 @@ public String getState() { return state; } +<<<<<<< HEAD +======= public Boolean isEncrypted() { return encrypted; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java index 89a65f8c27cc..9cca20815cad 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java @@ -208,7 +208,15 @@ public void create() throws ResourceAllocationException { public void execute() { Vpc vpc = null; try { +<<<<<<< HEAD + if (isStart()) { + _vpcService.startVpc(getEntityId(), true); + } else { + logger.debug("Not starting VPC as " + ApiConstants.START + "=false was passed to the API"); + } +======= _vpcService.startVpc(this); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 vpc = _entityMgr.findById(Vpc.class, getEntityId()); } catch (ResourceUnavailableException ex) { logger.warn("Exception: ", ex); diff --git a/api/src/main/java/org/apache/cloudstack/api/response/BucketResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/BucketResponse.java index a1cce6e43d7a..478b45a3bf9c 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/BucketResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/BucketResponse.java @@ -98,7 +98,11 @@ public class BucketResponse extends BaseResponseWithTagInformation implements Co @Param(description = "Bucket Access Key") private String accessKey; +<<<<<<< HEAD + @SerializedName(ApiConstants.SECRET_KEY) +======= @SerializedName(ApiConstants.USER_SECRET_KEY) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Param(description = "Bucket Secret Key") private String secretKey; 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 8deae7d80d3e..4af94f1a80b3 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 @@ -37,7 +37,10 @@ import com.cloud.uservm.UserVm; import com.cloud.vm.VirtualMachine; import com.google.gson.annotations.SerializedName; +<<<<<<< HEAD +======= import org.apache.commons.collections.CollectionUtils; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @SuppressWarnings("unused") @EntityReference(value = {VirtualMachine.class, UserVm.class, VirtualRouter.class}) @@ -274,10 +277,13 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co @Param(description = "the hypervisor on which the template runs") private String hypervisor; +<<<<<<< HEAD +======= @SerializedName(ApiConstants.IP_ADDRESS) @Param(description = "the VM's primary IP address") private String ipAddress; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @SerializedName(ApiConstants.PUBLIC_IP_ID) @Param(description = "public IP address id associated with vm via Static nat rule") private String publicIpId; @@ -632,10 +638,13 @@ public String getHypervisor() { return hypervisor; } +<<<<<<< HEAD +======= public String getIpAddress() { return ipAddress; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public String getPublicIpId() { return publicIpId; } @@ -872,6 +881,8 @@ public void setForVirtualNetwork(Boolean forVirtualNetwork) { public void setNics(Set nics) { this.nics = nics; +<<<<<<< HEAD +======= setIpAddress(nics); } @@ -879,6 +890,7 @@ public void setIpAddress(final Set nics) { if (CollectionUtils.isNotEmpty(nics)) { this.ipAddress = nics.iterator().next().getIpaddress(); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } public void addNic(NicResponse nic) { diff --git a/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java index 726c9adf8a3c..cb50dda8bd63 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/VolumeResponse.java @@ -290,6 +290,15 @@ public class VolumeResponse extends BaseResponseWithTagInformation implements Co private String externalUuid; @SerializedName(ApiConstants.VOLUME_CHECK_RESULT) +<<<<<<< HEAD + @Param(description = "details for the volume check result, they may vary for different hypervisors, since = 4.19.1") + private Map volumeCheckResult; + + @SerializedName(ApiConstants.VOLUME_REPAIR_RESULT) + @Param(description = "details for the volume repair result, they may vary for different hypervisors, since = 4.19.1") + private Map volumeRepairResult; + +======= @Param(description = "details for the volume check result, they may vary for different hypervisors", since = "4.19.1") private Map volumeCheckResult; @@ -301,6 +310,7 @@ public class VolumeResponse extends BaseResponseWithTagInformation implements Co @Param(description = "the format of the disk encryption if applicable", since = "4.19.1") private String encryptionFormat; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public String getPath() { return path; } @@ -846,8 +856,11 @@ public Map getVolumeRepairResult() { public void setVolumeRepairResult(Map volumeRepairResult) { this.volumeRepairResult = volumeRepairResult; } +<<<<<<< HEAD +======= public void setEncryptionFormat(String encryptionFormat) { this.encryptionFormat = encryptionFormat; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/api/src/main/java/org/apache/cloudstack/query/QueryService.java b/api/src/main/java/org/apache/cloudstack/query/QueryService.java index 4c53314aef59..bdc1660cc791 100644 --- a/api/src/main/java/org/apache/cloudstack/query/QueryService.java +++ b/api/src/main/java/org/apache/cloudstack/query/QueryService.java @@ -125,9 +125,12 @@ public interface QueryService { static final ConfigKey SharePublicTemplatesWithOtherDomains = new ConfigKey<>("Advanced", Boolean.class, "share.public.templates.with.other.domains", "true", "If false, templates of this domain will not show up in the list templates of other domains.", true, ConfigKey.Scope.Domain); +<<<<<<< HEAD +======= ConfigKey ReturnVmStatsOnVmList = new ConfigKey<>("Advanced", Boolean.class, "list.vm.default.details.stats", "true", "Determines whether VM stats should be returned when details are not explicitly specified in listVirtualMachines API request. When false, details default to [group, nics, secgrp, tmpl, servoff, diskoff, backoff, iso, volume, min, affgrp]. When true, all details are returned including 'stats'.", true, ConfigKey.Scope.Global); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ListResponse searchForUsers(ListUsersCmd cmd) throws PermissionDeniedException; ListResponse searchForUsers(Long domainId, boolean recursive) throws PermissionDeniedException; diff --git a/api/src/main/java/org/apache/cloudstack/user/ResourceReservation.java b/api/src/main/java/org/apache/cloudstack/user/ResourceReservation.java index d49120d44919..7dff18f21c40 100644 --- a/api/src/main/java/org/apache/cloudstack/user/ResourceReservation.java +++ b/api/src/main/java/org/apache/cloudstack/user/ResourceReservation.java @@ -22,8 +22,11 @@ import com.cloud.configuration.Resource; +<<<<<<< HEAD +======= import java.util.Date; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 /** * an interface defining an {code}AutoClosable{code} reservation object */ @@ -41,6 +44,9 @@ String getTag(); Long getReservedAmount(); +<<<<<<< HEAD +======= Date getCreated(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/api/src/test/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmdTest.java b/api/src/test/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmdTest.java index a28e9e9fd04f..6252c9346b34 100644 --- a/api/src/test/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmdTest.java +++ b/api/src/test/java/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmdTest.java @@ -167,16 +167,28 @@ public void testCreate() throws ResourceAllocationException { @Test public void testExecute() throws ResourceUnavailableException, InsufficientCapacityException { +<<<<<<< HEAD + ReflectionTestUtils.setField(cmd, "start", true); +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Vpc vpc = Mockito.mock(Vpc.class); VpcResponse response = Mockito.mock(VpcResponse.class); ReflectionTestUtils.setField(cmd, "id", 1L); responseGenerator = Mockito.mock(ResponseGenerator.class); +<<<<<<< HEAD + Mockito.when(_vpcService.startVpc(1L, true)).thenReturn(true); +======= Mockito.doNothing().when(_vpcService).startVpc(cmd); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Mockito.when(_entityMgr.findById(Mockito.eq(Vpc.class), Mockito.any(Long.class))).thenReturn(vpc); cmd._responseGenerator = responseGenerator; Mockito.when(responseGenerator.createVpcResponse(ResponseObject.ResponseView.Restricted, vpc)).thenReturn(response); cmd.execute(); +<<<<<<< HEAD + Mockito.verify(_vpcService, Mockito.times(1)).startVpc(Mockito.anyLong(), Mockito.anyBoolean()); +======= Mockito.verify(_vpcService, Mockito.times(1)).startVpc(cmd); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } diff --git a/client/conf/log4j-cloud.xml.in b/client/conf/log4j-cloud.xml.in index 148ccbfbb41b..a0a7ae9b8c1b 100755 --- a/client/conf/log4j-cloud.xml.in +++ b/client/conf/log4j-cloud.xml.in @@ -69,7 +69,11 @@ under the License. +<<<<<<< HEAD + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 diff --git a/client/pom.xml b/client/pom.xml index 23e0f1886bdb..5f38a0c146a1 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -440,11 +440,14 @@ org.apache.cloudstack +<<<<<<< HEAD +======= cloud-mom-webhook ${project.version} org.apache.cloudstack +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 cloud-framework-agent-lb ${project.version} diff --git a/core/src/main/java/org/apache/cloudstack/storage/to/VolumeObjectTO.java b/core/src/main/java/org/apache/cloudstack/storage/to/VolumeObjectTO.java index 6514038ac623..83c019030a0e 100644 --- a/core/src/main/java/org/apache/cloudstack/storage/to/VolumeObjectTO.java +++ b/core/src/main/java/org/apache/cloudstack/storage/to/VolumeObjectTO.java @@ -39,7 +39,10 @@ public class VolumeObjectTO extends DownloadableObjectTO implements DataTO { private DataStoreTO dataStore; private String name; private Long size; +<<<<<<< HEAD +======= private Long usableSize; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private String path; private Long volumeId; private String vmName; @@ -162,10 +165,13 @@ public Long getSize() { return size; } +<<<<<<< HEAD +======= public Long getUsableSize() { return usableSize; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Override public DataObjectType getObjectType() { return DataObjectType.VOLUME; @@ -183,10 +189,13 @@ public void setSize(long size) { this.size = size; } +<<<<<<< HEAD +======= public void setUsableSize(Long usableSize) { this.usableSize = usableSize; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public void setPath(String path) { this.path = path; } diff --git a/core/src/main/resources/META-INF/cloudstack/core/spring-core-registry-core-context.xml b/core/src/main/resources/META-INF/cloudstack/core/spring-core-registry-core-context.xml index 732f36534d2d..b32d52b05ae1 100644 --- a/core/src/main/resources/META-INF/cloudstack/core/spring-core-registry-core-context.xml +++ b/core/src/main/resources/META-INF/cloudstack/core/spring-core-registry-core-context.xml @@ -288,10 +288,17 @@ + + + +======= class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry"> +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @@ -339,7 +346,11 @@ class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry"> +<<<<<<< HEAD + >>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 class="org.apache.cloudstack.spring.lifecycle.registry.ExtensionRegistry"> @@ -358,9 +369,12 @@ +<<<<<<< HEAD +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 diff --git a/core/src/main/resources/META-INF/cloudstack/kubernetes/spring-core-lifecycle-kubernetes-context-inheritable.xml b/core/src/main/resources/META-INF/cloudstack/kubernetes/spring-core-lifecycle-kubernetes-context-inheritable.xml index 96a9a634bae8..299acdc11f5f 100644 --- a/core/src/main/resources/META-INF/cloudstack/kubernetes/spring-core-lifecycle-kubernetes-context-inheritable.xml +++ b/core/src/main/resources/META-INF/cloudstack/kubernetes/spring-core-lifecycle-kubernetes-context-inheritable.xml @@ -25,8 +25,13 @@ > +<<<<<<< HEAD + + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 diff --git a/debian/rules b/debian/rules index b52803702724..9c5beba9c8e6 100755 --- a/debian/rules +++ b/debian/rules @@ -103,8 +103,11 @@ override_dh_auto_install: install -m0644 packaging/systemd/$(PACKAGE)-management.service debian/$(PACKAGE)-management/lib/systemd/system/$(PACKAGE)-management.service install -m0644 packaging/systemd/$(PACKAGE)-management.default $(DESTDIR)/$(SYSCONFDIR)/default/$(PACKAGE)-management +<<<<<<< HEAD +======= install -D -m0644 server/target/conf/cloudstack-management.logrotate $(DESTDIR)/$(SYSCONFDIR)/logrotate.d/cloudstack-management +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 # cloudstack-ui mkdir $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/ui mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-ui @@ -161,8 +164,11 @@ override_dh_auto_install: install -m0644 packaging/systemd/$(PACKAGE)-usage.service debian/$(PACKAGE)-usage/lib/systemd/system/$(PACKAGE)-usage.service install -m0644 packaging/systemd/$(PACKAGE)-usage.default $(DESTDIR)/$(SYSCONFDIR)/default/$(PACKAGE)-usage +<<<<<<< HEAD +======= install -D -m0644 usage/target/transformed/cloudstack-usage.logrotate $(DESTDIR)/$(SYSCONFDIR)/logrotate.d/cloudstack-usage +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 # cloudstack-marvin mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-marvin cp tools/marvin/dist/Marvin-*.tar.gz $(DESTDIR)/usr/share/$(PACKAGE)-marvin/ diff --git a/engine/components-api/src/main/java/com/cloud/alert/AlertManager.java b/engine/components-api/src/main/java/com/cloud/alert/AlertManager.java index 3d4e6579f7ca..f6d683775121 100644 --- a/engine/components-api/src/main/java/com/cloud/alert/AlertManager.java +++ b/engine/components-api/src/main/java/com/cloud/alert/AlertManager.java @@ -38,10 +38,15 @@ public interface AlertManager extends Manager, AlertService { public static final ConfigKey AlertSmtpUseStartTLS = new ConfigKey("Advanced", Boolean.class, "alert.smtp.useStartTLS", "false", "If set to true and if we enable security via alert.smtp.useAuth, this will enable StartTLS to secure the connection.", true); +<<<<<<< HEAD + public static final ConfigKey AlertSmtpEnabledSecurityProtocols = new ConfigKey("Advanced", String.class, "alert.smtp.enabledSecurityProtocols", "", + "White-space separated security protocols; ex: \"TLSv1 TLSv1.1\". Supported protocols: SSLv2Hello, SSLv3, TLSv1, TLSv1.1 and TLSv1.2", true); +======= public static final ConfigKey AlertSmtpUseAuth = new ConfigKey<>(ConfigKey.CATEGORY_ALERT, Boolean.class, "alert.smtp.useAuth", "false", "If true, use SMTP authentication when sending emails.", false, ConfigKey.Scope.ManagementServer); public static final ConfigKey AlertSmtpEnabledSecurityProtocols = new ConfigKey(ConfigKey.CATEGORY_ADVANCED, String.class, "alert.smtp.enabledSecurityProtocols", "", "White-space separated security protocols; ex: \"TLSv1 TLSv1.1\". Supported protocols: SSLv2Hello, SSLv3, TLSv1, TLSv1.1 and TLSv1.2", true, ConfigKey.Kind.WhitespaceSeparatedListWithOptions, "SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2"); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public static final ConfigKey Ipv6SubnetCapacityThreshold = new ConfigKey("Advanced", Double.class, "zone.virtualnetwork.ipv6subnet.capacity.notificationthreshold", diff --git a/engine/components-api/src/main/java/com/cloud/event/UsageEventUtils.java b/engine/components-api/src/main/java/com/cloud/event/UsageEventUtils.java index 51d0846fafbc..c8c13b8eae40 100644 --- a/engine/components-api/src/main/java/com/cloud/event/UsageEventUtils.java +++ b/engine/components-api/src/main/java/com/cloud/event/UsageEventUtils.java @@ -25,6 +25,17 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; +<<<<<<< HEAD +import org.apache.commons.collections.MapUtils; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; + +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.framework.events.Event; +import org.apache.cloudstack.framework.events.EventBus; +import org.apache.cloudstack.framework.events.EventBusException; +======= import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.events.Event; import org.apache.cloudstack.framework.events.EventBus; @@ -33,6 +44,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.NoSuchBeanDefinitionException; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.DataCenterDao; @@ -49,7 +61,10 @@ public class UsageEventUtils { protected static Logger LOGGER = LogManager.getLogger(UsageEventUtils.class); protected static EventBus s_eventBus = null; protected static ConfigurationDao s_configDao; +<<<<<<< HEAD +======= private static EventDistributor eventDistributor; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Inject UsageEventDao usageEventDao; @@ -207,9 +222,15 @@ private static void publishUsageEvent(String usageEventType, Long accountId, Lon if( !configValue) return; try { +<<<<<<< HEAD + s_eventBus = ComponentContext.getComponent(EventBus.class); + } catch (NoSuchBeanDefinitionException nbe) { + return; // no provider is configured to provide events bus, so just return +======= eventDistributor = ComponentContext.getComponent(EventDistributor.class); } catch (NoSuchBeanDefinitionException nbe) { return; // no provider is configured to provide events distributor, so just return +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } Account account = s_accountDao.findById(accountId); @@ -238,7 +259,15 @@ private static void publishUsageEvent(String usageEventType, Long accountId, Lon event.setDescription(eventDescription); +<<<<<<< HEAD + try { + s_eventBus.publish(event); + } catch (EventBusException e) { + LOGGER.warn("Failed to publish usage event on the event bus."); + } +======= eventDistributor.publish(event); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } static final String Name = "management-server"; diff --git a/engine/components-api/src/main/java/com/cloud/network/NetworkStateListener.java b/engine/components-api/src/main/java/com/cloud/network/NetworkStateListener.java index 107e177ef579..a01ba243c39a 100644 --- a/engine/components-api/src/main/java/com/cloud/network/NetworkStateListener.java +++ b/engine/components-api/src/main/java/com/cloud/network/NetworkStateListener.java @@ -25,9 +25,17 @@ import javax.inject.Inject; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +<<<<<<< HEAD +import org.apache.cloudstack.framework.events.EventBus; +import org.apache.cloudstack.framework.events.EventBusException; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +======= import org.apache.cloudstack.framework.events.EventDistributor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.event.EventCategory; import com.cloud.network.Network.Event; @@ -41,7 +49,11 @@ public class NetworkStateListener implements StateListener>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 protected Logger logger = LogManager.getLogger(getClass()); @@ -49,10 +61,13 @@ public NetworkStateListener(ConfigurationDao configDao) { _configDao = configDao; } +<<<<<<< HEAD +======= public void setEventDistributor(EventDistributor eventDistributor) { this.eventDistributor = eventDistributor; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Override public boolean preStateTransitionEvent(State oldState, Event event, State newState, Network vo, boolean status, Object opaque) { pubishOnEventBus(event.name(), "preStateTransitionEvent", vo, oldState, newState); @@ -68,20 +83,37 @@ public boolean postStateTransitionEvent(StateMachine2.Transition t return true; } +<<<<<<< HEAD + private void pubishOnEventBus(String event, String status, Network vo, State oldState, State newState) { + +======= private void pubishOnEventBus(String event, String status, Network vo, State oldState, State newState) { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 String configKey = "publish.resource.state.events"; String value = _configDao.getValue(configKey); boolean configValue = Boolean.parseBoolean(value); if(!configValue) return; +<<<<<<< HEAD + try { + s_eventBus = ComponentContext.getComponent(EventBus.class); + } catch (NoSuchBeanDefinitionException nbe) { + return; // no provider is configured to provide events bus, so just return +======= if (eventDistributor == null) { setEventDistributor(ComponentContext.getComponent(EventDistributor.class)); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } String resourceName = getEntityFromClassName(Network.class.getName()); org.apache.cloudstack.framework.events.Event eventMsg = +<<<<<<< HEAD + new org.apache.cloudstack.framework.events.Event("management-server", EventCategory.RESOURCE_STATE_CHANGE_EVENT.getName(), event, resourceName, vo.getUuid()); + Map eventDescription = new HashMap(); +======= new org.apache.cloudstack.framework.events.Event("management-server", EventCategory.RESOURCE_STATE_CHANGE_EVENT.getName(), event, resourceName, vo.getUuid()); Map eventDescription = new HashMap<>(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 eventDescription.put("resource", resourceName); eventDescription.put("id", vo.getUuid()); eventDescription.put("old-state", oldState.name()); @@ -91,8 +123,16 @@ private void pubishOnEventBus(String event, String status, Network vo, State old eventDescription.put("eventDateTime", eventDate); eventMsg.setDescription(eventDescription); +<<<<<<< HEAD + try { + s_eventBus.publish(eventMsg); + } catch (EventBusException e) { + logger.warn("Failed to publish state change event on the event bus."); + } +======= eventDistributor.publish(eventMsg); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } private String getEntityFromClassName(String entityClassName) { 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 4772a5ad92de..8f1a37a2bf4d 100755 --- a/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java @@ -1077,10 +1077,13 @@ protected void checkAndAttemptMigrateVmAcrossCluster(final VMInstanceVO vm, fina return; } Host lastHost = _hostDao.findById(vm.getLastHostId()); +<<<<<<< HEAD +======= if (lastHost == null) { logger.warn("Could not find last host with id [{}], skipping migrate VM [{}] across cluster check." , vm.getLastHostId(), vm.getUuid()); return; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (destinationClusterId.equals(lastHost.getClusterId())) { return; } @@ -3011,7 +3014,11 @@ protected void createStoragePoolMappingsForVolumes(VirtualMachineProfile profile executeManagedStorageChecksWhenTargetStoragePoolNotProvided(targetHost, currentPool, volume); if (ScopeType.HOST.equals(currentPool.getScope()) || isStorageCrossClusterMigration(plan.getClusterId(), currentPool)) { createVolumeToStoragePoolMappingIfPossible(profile, plan, volumeToPoolObjectMap, volume, currentPool); +<<<<<<< HEAD + } else if (shouldMapVolume(profile, volume, currentPool)){ +======= } else if (shouldMapVolume(profile, currentPool)){ +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 volumeToPoolObjectMap.put(volume, currentPool); } } @@ -3023,10 +3030,18 @@ protected void createStoragePoolMappingsForVolumes(VirtualMachineProfile profile * Some context: VMware migration workflow requires all volumes to be mapped (even if volume stays on its current pool); * however, this is not necessary/desirable for the KVM flow. */ +<<<<<<< HEAD + protected boolean shouldMapVolume(VirtualMachineProfile profile, Volume volume, StoragePoolVO currentPool) { + boolean isManaged = currentPool.isManaged(); + boolean isNotKvm = HypervisorType.KVM != profile.getHypervisorType(); + boolean isNotDatadisk = Type.DATADISK != volume.getVolumeType(); + return isNotKvm || isNotDatadisk || isManaged; +======= protected boolean shouldMapVolume(VirtualMachineProfile profile, StoragePoolVO currentPool) { boolean isManaged = currentPool.isManaged(); boolean isNotKvm = HypervisorType.KVM != profile.getHypervisorType(); return isNotKvm || isManaged; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } /** 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 c6d156d470b4..28e6e115e434 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 @@ -1185,9 +1185,14 @@ public VolumeVO doInTransaction(TransactionStatus status) { logger.error("Unable to destroy existing volume [{}] due to [{}].", volumeToString, e.getMessage()); } // In case of VMware VM will continue to use the old root disk until expunged, so force expunge old root disk +<<<<<<< HEAD + if (vm.getHypervisorType() == HypervisorType.VMware) { + logger.info("Trying to expunge volume [{}] from primary data storage.", volumeToString); +======= // For system VM we do not need volume entry in Destroy state if (vm.getHypervisorType() == HypervisorType.VMware || vm.getType().isUsedBySystem()) { logger.info(String.format("Trying to expunge volume [%s] from primary data storage.", volumeToString)); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 AsyncCallFuture future = volService.expungeVolumeAsync(volFactory.getVolume(existingVolume.getId())); try { future.get(); diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java index 7ef7fd44b244..d573996cd69a 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDao.java @@ -112,8 +112,12 @@ public interface VolumeDao extends GenericDao, StateDao>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 * @return total Primary Storage space (in bytes) used */ long primaryStorageUsedForAccount(long accountId, List virtualRouters); diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java index 2e68dcae3c57..cb995f0ee3e6 100644 --- a/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java +++ b/engine/schema/src/main/java/com/cloud/storage/dao/VolumeDaoImpl.java @@ -81,6 +81,10 @@ public class VolumeDaoImpl extends GenericDaoBase implements Vol @Inject ResourceTagDao _tagsDao; +<<<<<<< HEAD + protected static final String SELECT_VM_SQL = "SELECT DISTINCT instance_id from volumes v where v.host_id = ? and v.mirror_state = ?"; +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 // need to account for zone-wide primary storage where storage_pool has // null-value pod and cluster, where hypervisor information is stored in // storage_pool diff --git a/engine/schema/src/main/java/com/cloud/vm/UserVmVO.java b/engine/schema/src/main/java/com/cloud/vm/UserVmVO.java index ce3a9a84a34f..f266f7017127 100644 --- a/engine/schema/src/main/java/com/cloud/vm/UserVmVO.java +++ b/engine/schema/src/main/java/com/cloud/vm/UserVmVO.java @@ -148,7 +148,10 @@ public boolean isUpdateParameters() { return updateParameters; } +<<<<<<< HEAD +======= @Override +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public String getUserVmType() { return userVmType; } diff --git a/engine/schema/src/main/java/org/apache/cloudstack/reservation/ReservationVO.java b/engine/schema/src/main/java/org/apache/cloudstack/reservation/ReservationVO.java index df0ede6821ad..734c6b5f58a9 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/reservation/ReservationVO.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/reservation/ReservationVO.java @@ -25,14 +25,20 @@ import javax.persistence.Id; import javax.persistence.Table; +<<<<<<< HEAD +======= import com.cloud.utils.db.GenericDao; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.user.ResourceReservation; import com.cloud.configuration.Resource; import com.cloud.utils.exception.CloudRuntimeException; +<<<<<<< HEAD +======= import org.apache.cloudstack.utils.identity.ManagementServerNode; import java.util.Date; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Entity @Table(name = "resource_reservation") @@ -61,12 +67,15 @@ public class ReservationVO implements ResourceReservation { @Column(name = "amount") long amount; +<<<<<<< HEAD +======= @Column(name = "mgmt_server_id") Long managementServerId; @Column(name = GenericDao.CREATED_COLUMN) private Date created; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 protected ReservationVO() { } @@ -79,7 +88,10 @@ public ReservationVO(Long accountId, Long domainId, Resource.ResourceType resour this.resourceType = resourceType; this.tag = tag; this.amount = delta; +<<<<<<< HEAD +======= this.managementServerId = ManagementServerNode.getManagementServerId(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } public ReservationVO(Long accountId, Long domainId, Resource.ResourceType resourceType, Long delta) { @@ -125,6 +137,8 @@ public void setResourceId(long resourceId) { this.resourceId = resourceId; } +<<<<<<< HEAD +======= @Override public Date getCreated() { return created; @@ -137,4 +151,5 @@ public void setCreated(Date created) { public Long getManagementServerId() { return managementServerId; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/engine/schema/src/main/java/org/apache/cloudstack/reservation/dao/ReservationDao.java b/engine/schema/src/main/java/org/apache/cloudstack/reservation/dao/ReservationDao.java index d6d494f61f92..c64334a25969 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/reservation/dao/ReservationDao.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/reservation/dao/ReservationDao.java @@ -23,17 +23,26 @@ import com.cloud.configuration.Resource; import com.cloud.utils.db.GenericDao; +<<<<<<< HEAD +======= import java.util.Date; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import java.util.List; public interface ReservationDao extends GenericDao { long getAccountReservation(Long account, Resource.ResourceType resourceType, String tag); long getDomainReservation(Long domain, Resource.ResourceType resourceType, String tag); void setResourceId(Resource.ResourceType type, Long resourceId); +<<<<<<< HEAD + List getResourceIds(long accountId, Resource.ResourceType type); + List getReservationsForAccount(long accountId, Resource.ResourceType type, String tag); + void removeByIds(List reservationIds); +======= List getReservationsForAccount(long accountId, Resource.ResourceType type, String tag); void removeByIds(List reservationIds); int removeByMsId(long managementServerId); int removeStaleReservations(Long accountId, Resource.ResourceType resourceType, String tag, Date createdBefore); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/engine/schema/src/main/java/org/apache/cloudstack/reservation/dao/ReservationDaoImpl.java b/engine/schema/src/main/java/org/apache/cloudstack/reservation/dao/ReservationDaoImpl.java index 3b17f4e4294e..858b1d184d93 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/reservation/dao/ReservationDaoImpl.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/reservation/dao/ReservationDaoImpl.java @@ -18,8 +18,13 @@ // package org.apache.cloudstack.reservation.dao; +<<<<<<< HEAD +import java.util.List; +import java.util.stream.Collectors; +======= import java.util.Date; import java.util.List; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.reservation.ReservationVO; @@ -42,8 +47,11 @@ public class ReservationDaoImpl extends GenericDaoBase impl private static final String ACCOUNT_ID = "accountId"; private static final String DOMAIN_ID = "domainId"; private static final String IDS = "ids"; +<<<<<<< HEAD +======= private static final String MS_ID = "managementServerId"; private static final String CREATED = "created"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private final SearchBuilder listResourceByAccountAndTypeSearch; private final SearchBuilder listAccountAndTypeSearch; private final SearchBuilder listAccountAndTypeAndNoTagSearch; @@ -52,7 +60,10 @@ public class ReservationDaoImpl extends GenericDaoBase impl private final SearchBuilder listDomainAndTypeAndNoTagSearch; private final SearchBuilder listResourceByAccountAndTypeAndNoTagSearch; private final SearchBuilder listIdsSearch; +<<<<<<< HEAD +======= private final SearchBuilder listMsIdSearch; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public ReservationDaoImpl() { @@ -74,14 +85,20 @@ public ReservationDaoImpl() { listAccountAndTypeSearch.and(ACCOUNT_ID, listAccountAndTypeSearch.entity().getAccountId(), SearchCriteria.Op.EQ); listAccountAndTypeSearch.and(RESOURCE_TYPE, listAccountAndTypeSearch.entity().getResourceType(), SearchCriteria.Op.EQ); listAccountAndTypeSearch.and(RESOURCE_TAG, listAccountAndTypeSearch.entity().getTag(), SearchCriteria.Op.EQ); +<<<<<<< HEAD +======= listAccountAndTypeSearch.and(CREATED, listAccountAndTypeSearch.entity().getCreated(), SearchCriteria.Op.LT); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 listAccountAndTypeSearch.done(); listAccountAndTypeAndNoTagSearch = createSearchBuilder(); listAccountAndTypeAndNoTagSearch.and(ACCOUNT_ID, listAccountAndTypeAndNoTagSearch.entity().getAccountId(), SearchCriteria.Op.EQ); listAccountAndTypeAndNoTagSearch.and(RESOURCE_TYPE, listAccountAndTypeAndNoTagSearch.entity().getResourceType(), SearchCriteria.Op.EQ); listAccountAndTypeAndNoTagSearch.and(RESOURCE_TAG, listAccountAndTypeAndNoTagSearch.entity().getTag(), SearchCriteria.Op.NULL); +<<<<<<< HEAD +======= listAccountAndTypeAndNoTagSearch.and(CREATED, listAccountAndTypeAndNoTagSearch.entity().getCreated(), SearchCriteria.Op.LT); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 listAccountAndTypeAndNoTagSearch.done(); listDomainAndTypeSearch = createSearchBuilder(); @@ -99,15 +116,27 @@ public ReservationDaoImpl() { listIdsSearch = createSearchBuilder(); listIdsSearch.and(IDS, listIdsSearch.entity().getId(), SearchCriteria.Op.IN); listIdsSearch.done(); +<<<<<<< HEAD +======= listMsIdSearch = createSearchBuilder(); listMsIdSearch.and(MS_ID, listMsIdSearch.entity().getManagementServerId(), SearchCriteria.Op.EQ); listMsIdSearch.done(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } @Override public long getAccountReservation(Long accountId, Resource.ResourceType resourceType, String tag) { long total = 0; +<<<<<<< HEAD + SearchCriteria sc = tag == null ? + listAccountAndTypeAndNoTagSearch.create() : listAccountAndTypeSearch.create(); + sc.setParameters(ACCOUNT_ID, accountId); + sc.setParameters(RESOURCE_TYPE, resourceType); + if (tag != null) { + sc.setParameters(RESOURCE_TAG, tag); + } +======= SearchCriteria sc; if (tag == null) { sc = listAccountAndTypeAndNoTagSearch.create(); @@ -117,6 +146,7 @@ public long getAccountReservation(Long accountId, Resource.ResourceType resource } sc.setParameters(ACCOUNT_ID, accountId); sc.setParameters(RESOURCE_TYPE, resourceType); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 List reservations = listBy(sc); for (ReservationVO reservation : reservations) { total += reservation.getReservedAmount(); @@ -127,6 +157,15 @@ public long getAccountReservation(Long accountId, Resource.ResourceType resource @Override public long getDomainReservation(Long domainId, Resource.ResourceType resourceType, String tag) { long total = 0; +<<<<<<< HEAD + SearchCriteria sc = tag == null ? + listDomainAndTypeAndNoTagSearch.create() : listDomainAndTypeSearch.create(); + sc.setParameters(DOMAIN_ID, domainId); + sc.setParameters(RESOURCE_TYPE, resourceType); + if (tag != null) { + sc.setParameters(RESOURCE_TAG, tag); + } +======= SearchCriteria sc; if (tag == null) { sc = listDomainAndTypeAndNoTagSearch.create(); @@ -136,6 +175,7 @@ public long getDomainReservation(Long domainId, Resource.ResourceType resourceTy } sc.setParameters(DOMAIN_ID, domainId); sc.setParameters(RESOURCE_TYPE, resourceType); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 List reservations = listBy(sc); for (ReservationVO reservation : reservations) { total += reservation.getReservedAmount(); @@ -163,6 +203,24 @@ public void setResourceId(Resource.ResourceType type, Long resourceId) { } @Override +<<<<<<< HEAD + public List getResourceIds(long accountId, Resource.ResourceType type) { + SearchCriteria sc = listResourceByAccountAndTypeSearch.create(); + sc.setParameters(ACCOUNT_ID, accountId); + sc.setParameters(RESOURCE_TYPE, type); + return listBy(sc).stream().map(ReservationVO::getResourceId).collect(Collectors.toList()); + } + + @Override + public List getReservationsForAccount(long accountId, Resource.ResourceType type, String tag) { + SearchCriteria sc = tag == null ? + listResourceByAccountAndTypeAndNoTagSearch.create() : listResourceByAccountAndTypeSearch.create(); + sc.setParameters(ACCOUNT_ID, accountId); + sc.setParameters(RESOURCE_TYPE, type); + if (tag != null) { + sc.setParameters(RESOURCE_TAG, tag); + } +======= public List getReservationsForAccount(long accountId, Resource.ResourceType type, String tag) { SearchCriteria sc; if (tag == null) { @@ -173,6 +231,7 @@ public List getReservationsForAccount(long accountId, Resource.Re } sc.setParameters(ACCOUNT_ID, accountId); sc.setParameters(RESOURCE_TYPE, type); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return listBy(sc); } @@ -184,6 +243,8 @@ public void removeByIds(List reservationIds) { remove(sc); } } +<<<<<<< HEAD +======= @Override public int removeByMsId(long managementServerId) { @@ -208,4 +269,5 @@ public int removeStaleReservations(Long accountId, Resource.ResourceType resourc return remove(sc); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ImageStoreDaoImpl.java b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ImageStoreDaoImpl.java index 21c5dc76d96c..33c668f9182b 100644 --- a/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ImageStoreDaoImpl.java +++ b/engine/schema/src/main/java/org/apache/cloudstack/storage/datastore/db/ImageStoreDaoImpl.java @@ -130,7 +130,11 @@ public List findByZone(ZoneScope scope, Boolean readonly) { } if (scope.getScopeId() != null) { SearchCriteria scc = createSearchCriteria(); +<<<<<<< HEAD + scc.addOr("scope", SearchCriteria.Op.EQ, ScopeType.REGION); +======= scc.addOr("scope", SearchCriteria.Op.EQ, ScopeType.ZONE); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 scc.addOr("dcId", SearchCriteria.Op.EQ, scope.getScopeId()); sc.addAnd("scope", SearchCriteria.Op.SC, scc); } diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41900to41910-cleanup.sql b/engine/schema/src/main/resources/META-INF/db/schema-41900to41910-cleanup.sql index 2d57db2b778e..27fdc84c2660 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41900to41910-cleanup.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41900to41910-cleanup.sql @@ -18,7 +18,10 @@ --; -- Schema upgrade cleanup from 4.19.0.0 to 4.19.1.0 --; +<<<<<<< HEAD +======= -- List VMs response optimisation, don't sum during API handling UPDATE cloud.configuration set value='false' where name='vm.stats.increment.metrics'; DELETE from cloud.configuration where name='vm.stats.increment.metrics.in.memory'; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 diff --git a/engine/schema/src/main/resources/META-INF/db/schema-41910to42000.sql b/engine/schema/src/main/resources/META-INF/db/schema-41910to42000.sql index 295ad147a993..1066a14cdfc9 100644 --- a/engine/schema/src/main/resources/META-INF/db/schema-41910to42000.sql +++ b/engine/schema/src/main/resources/META-INF/db/schema-41910to42000.sql @@ -23,6 +23,17 @@ CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.resource_limit', 'tag', 'varchar(64) DEFAULT NULL COMMENT "tag for the limit" '); CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.resource_count', 'tag', 'varchar(64) DEFAULT NULL COMMENT "tag for the resource count" '); CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.resource_reservation', 'tag', 'varchar(64) DEFAULT NULL COMMENT "tag for the resource reservation" '); +<<<<<<< HEAD +ALTER TABLE `resource_count` +DROP INDEX `i_resource_count__type_accountId`, +DROP INDEX `i_resource_count__type_domaintId`, +ADD UNIQUE INDEX `i_resource_count__type_tag_accountId` (`type`,`tag`,`account_id`), +ADD UNIQUE INDEX `i_resource_count__type_tag_domaintId` (`type`,`tag`,`domain_id`); + + +ALTER TABLE `cloud`.`resource_reservation` + ADD COLUMN `resource_id` bigint unsigned NULL; +======= CALL `cloud`.`IDEMPOTENT_DROP_INDEX`('i_resource_count__type_accountId', 'cloud.resource_count'); CALL `cloud`.`IDEMPOTENT_DROP_INDEX`('i_resource_count__type_domaintId', 'cloud.resource_count'); @@ -37,16 +48,20 @@ BEGIN CALL `cloud`.`IDEMPOTENT_ADD_UNIQUE_INDEX`('cloud.resource_count', 'i_resource_count__type_tag_accountId', '(type, tag, account_id)'); CALL `cloud`.`IDEMPOTENT_ADD_UNIQUE_INDEX`('cloud.resource_count', 'i_resource_count__type_tag_domainId', '(type, tag, domain_id)'); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ALTER TABLE `cloud`.`resource_reservation` MODIFY COLUMN `amount` bigint NOT NULL; +<<<<<<< HEAD +======= CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.resource_reservation', 'resource_id', 'bigint unsigned NULL COMMENT "id of the resource" '); CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.resource_reservation', 'mgmt_server_id', 'bigint unsigned NULL COMMENT "management server id" '); CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.resource_reservation', 'created', 'datetime DEFAULT NULL COMMENT "date when the reservation was created" '); UPDATE `cloud`.`resource_reservation` SET `created` = now() WHERE created IS NULL; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 -- Update Default System offering for Router to 512MiB UPDATE `cloud`.`service_offering` SET ram_size = 512 WHERE unique_name IN ("Cloud.Com-SoftwareRouter", "Cloud.Com-SoftwareRouter-Local", @@ -81,6 +96,10 @@ CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.network_offerings','nsx_mode', 'varc CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','for_nsx', 'int(1) unsigned DEFAULT "0" COMMENT "is nsx enabled for the resource"'); CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','nsx_mode', 'varchar(32) COMMENT "mode in which the network would route traffic"'); +<<<<<<< HEAD + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 -- Create table to persist quota email template configurations CREATE TABLE IF NOT EXISTS `cloud_usage`.`quota_email_configuration`( `account_id` int(11) NOT NULL, @@ -92,6 +111,8 @@ CREATE TABLE IF NOT EXISTS `cloud_usage`.`quota_email_configuration`( -- Add `is_implicit` column to `host_tags` table CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.host_tags', 'is_implicit', 'int(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT "If host tag is implicit or explicit" '); +<<<<<<< HEAD +======= -- Webhooks feature DROP TABLE IF EXISTS `cloud`.`webhook`; @@ -150,3 +171,4 @@ SET WHERE name IN ("quota.usage.smtp.useStartTLS", "quota.usage.smtp.useAuth", "alert.smtp.useAuth", "project.smtp.useAuth") AND value NOT IN ("true", "y", "t", "1", "on", "yes"); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 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 62294ed5d890..121891fd1752 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 @@ -196,7 +196,11 @@ FROM LEFT JOIN `networks` ON ((`nics`.`network_id` = `networks`.`id`))) LEFT JOIN `vpc` ON (((`networks`.`vpc_id` = `vpc`.`id`) AND ISNULL(`vpc`.`removed`)))) +<<<<<<< HEAD + LEFT JOIN `user_ip_address` ON ((`user_ip_address`.`vm_id` = `vm_instance`.`id`))) +======= LEFT JOIN `user_ip_address` FORCE INDEX(`fk_user_ip_address__vm_id`) ON ((`user_ip_address`.`vm_id` = `vm_instance`.`id`))) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 LEFT JOIN `user_vm_details` `ssh_details` ON (((`ssh_details`.`vm_id` = `vm_instance`.`id`) AND (`ssh_details`.`name` = 'SSH.KeyPairNames')))) LEFT JOIN `resource_tags` ON (((`resource_tags`.`resource_id` = `vm_instance`.`id`) diff --git a/engine/schema/src/main/resources/META-INF/db/views/cloud.volume_view.sql b/engine/schema/src/main/resources/META-INF/db/views/cloud.volume_view.sql index 950dcddf4c71..7855c22c89fc 100644 --- a/engine/schema/src/main/resources/META-INF/db/views/cloud.volume_view.sql +++ b/engine/schema/src/main/resources/META-INF/db/views/cloud.volume_view.sql @@ -39,7 +39,10 @@ SELECT `volumes`.`path` AS `path`, `volumes`.`chain_info` AS `chain_info`, `volumes`.`external_uuid` AS `external_uuid`, +<<<<<<< HEAD +======= `volumes`.`encrypt_format` AS `encrypt_format`, +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 `account`.`id` AS `account_id`, `account`.`uuid` AS `account_uuid`, `account`.`account_name` AS `account_name`, 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 fa570e0e8fbe..de4f49fe69fd 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 @@ -41,7 +41,11 @@ public enum Scope { } public enum Kind { +<<<<<<< HEAD + CSV, Order, Select +======= CSV, Order, Select, WhitespaceSeparatedListWithOptions +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } private final String _category; @@ -136,10 +140,13 @@ public ConfigKey(String category, Class type, String name, String defaultValu this(type, name, category, defaultValue, description, isDynamic, Scope.Global, null); } +<<<<<<< HEAD +======= public ConfigKey(String category, Class type, String name, String defaultValue, String description, boolean isDynamic, Kind kind, String options) { this(type, name, category, defaultValue, description, isDynamic, Scope.Global, null, null, null, null, null, kind, options); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public ConfigKey(String category, Class type, String name, String defaultValue, String description, boolean isDynamic, String parent) { this(type, name, category, defaultValue, description, isDynamic, Scope.Global, null, null, parent, null, null, null, null); } diff --git a/framework/events/src/main/java/org/apache/cloudstack/framework/events/Event.java b/framework/events/src/main/java/org/apache/cloudstack/framework/events/Event.java index 7a14f385fa15..7ea6692abe89 100644 --- a/framework/events/src/main/java/org/apache/cloudstack/framework/events/Event.java +++ b/framework/events/src/main/java/org/apache/cloudstack/framework/events/Event.java @@ -20,6 +20,11 @@ package org.apache.cloudstack.framework.events; import com.google.gson.Gson; +<<<<<<< HEAD + +public class Event { + +======= import com.google.gson.annotations.Expose; public class Event { @@ -28,12 +33,22 @@ public class Event { Long eventId; @Expose(serialize = false, deserialize = false) String eventUuid; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 String eventCategory; String eventType; String eventSource; String resourceType; String resourceUUID; String description; +<<<<<<< HEAD + + public Event(String eventSource, String eventCategory, String eventType, String resourceType, String resourceUUID) { + this.eventCategory = eventCategory; + this.eventType = eventType; + this.eventSource = eventSource; + this.resourceType = resourceType; + this.resourceUUID = resourceUUID; +======= @Expose(serialize = false, deserialize = false) Long resourceAccountId; @Expose(serialize = false, deserialize = false) @@ -63,6 +78,7 @@ public String getEventUuid() { public void setEventUuid(String eventUuid) { this.eventUuid = eventUuid; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } public String getEventCategory() { @@ -95,7 +111,11 @@ public String getDescription() { public void setDescription(Object message) { Gson gson = new Gson(); +<<<<<<< HEAD + this.description = gson.toJson(message).toString(); +======= this.description = gson.toJson(message); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } public void setDescription(String description) { @@ -117,6 +137,8 @@ public void setResourceUUID(String uuid) { public String getResourceUUID() { return resourceUUID; } +<<<<<<< HEAD +======= public Long getResourceAccountId() { return resourceAccountId; @@ -141,4 +163,5 @@ public Long getResourceDomainId() { public void setResourceDomainId(Long resourceDomainId) { this.resourceDomainId = resourceDomainId; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/framework/events/src/main/java/org/apache/cloudstack/framework/events/EventBus.java b/framework/events/src/main/java/org/apache/cloudstack/framework/events/EventBus.java index 6cd6256ce81d..5ec1bd77bd69 100644 --- a/framework/events/src/main/java/org/apache/cloudstack/framework/events/EventBus.java +++ b/framework/events/src/main/java/org/apache/cloudstack/framework/events/EventBus.java @@ -27,8 +27,11 @@ */ public interface EventBus { +<<<<<<< HEAD +======= String getName(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 /** * publish an event on to the event bus * diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Account.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Account.java index 37c90ab0bcd9..e2e29e3f4954 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Account.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Account.java @@ -17,9 +17,13 @@ package org.apache.cloudstack.quota.activationrule.presetvariables; +<<<<<<< HEAD +public class Account extends GenericPresetVariable{ +======= public class Account extends GenericPresetVariable { @PresetVariableDefinition(description = "Role of the account. This field will not exist if the account is a project.") +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private Role role; public Role getRole() { diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/BackupOffering.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/BackupOffering.java index d8457d294ec3..00c56ae28d7d 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/BackupOffering.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/BackupOffering.java @@ -20,7 +20,10 @@ package org.apache.cloudstack.quota.activationrule.presetvariables; public class BackupOffering extends GenericPresetVariable { +<<<<<<< HEAD +======= @PresetVariableDefinition(description = "External ID of the backup offering that generated the backup.") +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private String externalId; public String getExternalId() { diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/ComputeOffering.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/ComputeOffering.java index 1d294276d470..d5443ada3225 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/ComputeOffering.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/ComputeOffering.java @@ -18,7 +18,10 @@ package org.apache.cloudstack.quota.activationrule.presetvariables; public class ComputeOffering extends GenericPresetVariable { +<<<<<<< HEAD +======= @PresetVariableDefinition(description = "A boolean informing if the compute offering is customized or not.") +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private boolean customized; public boolean isCustomized() { diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/ComputingResources.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/ComputingResources.java index 9c86d2d6e0c9..322096b64087 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/ComputingResources.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/ComputingResources.java @@ -21,6 +21,10 @@ import org.apache.commons.lang3.builder.ToStringStyle; public class ComputingResources { +<<<<<<< HEAD + private Integer memory; + private Integer cpuNumber; +======= @PresetVariableDefinition(description = "Current VM's memory (in MiB).") private Integer memory; @@ -28,6 +32,7 @@ public class ComputingResources { private Integer cpuNumber; @PresetVariableDefinition(description = "Current VM's CPU speed (in MHz).") +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private Integer cpuSpeed; public Integer getMemory() { diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Domain.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Domain.java index 6d83da4cd8fb..f0d4dc127091 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Domain.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Domain.java @@ -18,7 +18,10 @@ package org.apache.cloudstack.quota.activationrule.presetvariables; public class Domain extends GenericPresetVariable { +<<<<<<< HEAD +======= @PresetVariableDefinition(description = "Path of the domain owner of the resource.") +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private String path; public String getPath() { diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/GenericPresetVariable.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/GenericPresetVariable.java index f59f23abdc15..a34c1eacd7c3 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/GenericPresetVariable.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/GenericPresetVariable.java @@ -23,12 +23,17 @@ import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils; public class GenericPresetVariable { +<<<<<<< HEAD + private String id; + private String name; +======= @PresetVariableDefinition(description = "ID of the resource.") private String id; @PresetVariableDefinition(description = "Name of the resource.") private String name; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 protected transient Set fieldNamesToIncludeInToString = new HashSet<>(); public String getId() { diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Host.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Host.java index 4a0fd2f5a078..cbe4e0e06848 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Host.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Host.java @@ -20,10 +20,15 @@ import java.util.List; public class Host extends GenericPresetVariable { +<<<<<<< HEAD + private List tags; + +======= @PresetVariableDefinition(description = "List of tags of the host where the VM is running (i.e.: [\"a\", \"b\"]).") private List tags; @PresetVariableDefinition(description = "Whether the tag is a rule interpreted in JavaScript.") +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private Boolean isTagARule; public List getTags() { diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariables.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariables.java index b27bf589c167..c328c984803f 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariables.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/PresetVariables.java @@ -19,6 +19,13 @@ public class PresetVariables { +<<<<<<< HEAD + private Account account; + private Domain domain; + private GenericPresetVariable project; + private String resourceType; + private Value value; +======= @PresetVariableDefinition(description = "Account owner of the resource.") private Account account; @@ -35,6 +42,7 @@ public class PresetVariables { private Value value; @PresetVariableDefinition(description = "Zone where the resource is.") +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private GenericPresetVariable zone; public Account getAccount() { diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Role.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Role.java index 3f953b3a4ff8..9bc0d103d4b6 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Role.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Role.java @@ -20,7 +20,10 @@ import org.apache.cloudstack.acl.RoleType; public class Role extends GenericPresetVariable { +<<<<<<< HEAD +======= @PresetVariableDefinition(description = "Role type of the resource's owner.") +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private RoleType type; public RoleType getType() { diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Storage.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Storage.java index 9b6cfb310922..a56101c31871 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Storage.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Storage.java @@ -22,6 +22,11 @@ import com.cloud.storage.ScopeType; public class Storage extends GenericPresetVariable { +<<<<<<< HEAD + private List tags; + + private Boolean isTagARule; +======= @PresetVariableDefinition(description = "List of string representing the tags of the storage where the volume is (i.e.: [\"a\", \"b\"]).") private List tags; @@ -29,6 +34,7 @@ public class Storage extends GenericPresetVariable { private Boolean isTagARule; @PresetVariableDefinition(description = "Scope of the storage where the volume is. Values can be: ZONE, CLUSTER or HOST. Applicable only for primary storages.") +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private ScopeType scope; public List getTags() { diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Value.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Value.java index d87146d8798e..fae00d2f4dd5 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Value.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/activationrule/presetvariables/Value.java @@ -23,6 +23,27 @@ import com.cloud.storage.Snapshot; import com.cloud.storage.Storage.ProvisioningType; import com.cloud.vm.snapshot.VMSnapshot; +<<<<<<< HEAD + +public class Value extends GenericPresetVariable { + private Host host; + private String osName; + private List accountResources; + private Map tags; + private String tag; + private Long size; + private Long virtualSize; + private ProvisioningType provisioningType; + private Snapshot.Type snapshotType; + private VMSnapshot.Type vmSnapshotType; + private ComputeOffering computeOffering; + private GenericPresetVariable template; + private GenericPresetVariable diskOffering; + private Storage storage; + private ComputingResources computingResources; + private BackupOffering backupOffering; + private String hypervisorType; +======= import org.apache.cloudstack.quota.constant.QuotaTypes; public class Value extends GenericPresetVariable { @@ -92,6 +113,7 @@ public class Value extends GenericPresetVariable { private String hypervisorType; @PresetVariableDefinition(description = "The volume format. Values can be: RAW, VHD, VHDX, OVA and QCOW2.", supportedTypes = {QuotaTypes.VOLUME, QuotaTypes.VOLUME_SECONDARY}) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private String volumeFormat; private String state; diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/constant/QuotaConfig.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/constant/QuotaConfig.java index 81b4643eb450..df5fd3c8dc5d 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/constant/QuotaConfig.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/constant/QuotaConfig.java @@ -48,16 +48,26 @@ public interface QuotaConfig { public static final ConfigKey QuotaSmtpPort = new ConfigKey("Advanced", String.class, "quota.usage.smtp.port", "", "Quota SMTP port.", true); +<<<<<<< HEAD + public static final ConfigKey QuotaSmtpAuthType = new ConfigKey("Advanced", String.class, "quota.usage.smtp.useAuth", "", +======= public static final ConfigKey QuotaSmtpAuthType = new ConfigKey("Advanced", Boolean.class, "quota.usage.smtp.useAuth", "false", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "If true, use secure SMTP authentication when sending emails.", true); public static final ConfigKey QuotaSmtpSender = new ConfigKey("Advanced", String.class, "quota.usage.smtp.sender", "", "Sender of quota alert email (will be in the From header of the email).", true); public static final ConfigKey QuotaSmtpEnabledSecurityProtocols = new ConfigKey("Advanced", String.class, "quota.usage.smtp.enabledSecurityProtocols", "", +<<<<<<< HEAD + "White-space separated security protocols; ex: \"TLSv1 TLSv1.1\". Supported protocols: SSLv2Hello, SSLv3, TLSv1, TLSv1.1 and TLSv1.2.", true); + + public static final ConfigKey QuotaSmtpUseStartTLS = new ConfigKey("Advanced", String.class, "quota.usage.smtp.useStartTLS", "false", +======= "White-space separated security protocols; ex: \"TLSv1 TLSv1.1\". Supported protocols: SSLv2Hello, SSLv3, TLSv1, TLSv1.1 and TLSv1.2.", true, ConfigKey.Kind.WhitespaceSeparatedListWithOptions, "SSLv2Hello,SSLv3,TLSv1,TLSv1.1,TLSv1.2"); public static final ConfigKey QuotaSmtpUseStartTLS = new ConfigKey("Advanced", Boolean.class, "quota.usage.smtp.useStartTLS", "false", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "If set to true and if we enable security via quota.usage.smtp.useAuth, this will enable StartTLS to secure the connection.", true); public static final ConfigKey QuotaActivationRuleTimeout = new ConfigKey<>("Advanced", Long.class, "quota.activationrule.timeout", "2000", "The maximum runtime," 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 947183577a88..0ed77429440f 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 @@ -22,7 +22,10 @@ import org.apache.cloudstack.usage.UsageTypes; import org.apache.cloudstack.usage.UsageUnitTypes; +<<<<<<< HEAD +======= import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public class QuotaTypes extends UsageTypes { private final Integer quotaType; @@ -101,6 +104,8 @@ static public String getDescription(int quotaType) { } return null; } +<<<<<<< HEAD +======= static public QuotaTypes getQuotaType(int quotaType) { return quotaTypeMap.get(quotaType); @@ -110,4 +115,5 @@ static public QuotaTypes getQuotaType(int quotaType) { public String toString() { return ReflectionToStringBuilderUtils.reflectOnlySelectedFields(this, "quotaType", "quotaName"); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/ValueTest.java b/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/ValueTest.java index bad33da88367..6128081a76e7 100644 --- a/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/ValueTest.java +++ b/framework/quota/src/test/java/org/apache/cloudstack/quota/activationrule/presetvariables/ValueTest.java @@ -26,6 +26,8 @@ public class ValueTest { @Test +<<<<<<< HEAD +======= public void setIdTestAddFieldIdToCollection() { Value variable = new Value(); variable.setId(null); @@ -40,6 +42,7 @@ public void setNameTestAddFieldNameToCollection() { } @Test +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public void setHostTestAddFieldHostToCollection() { Value variable = new Value(); variable.setHost(null); diff --git a/packaging/centos7/cloud.spec b/packaging/centos7/cloud.spec index 80b8443e09b9..f6d37be0f10c 100644 --- a/packaging/centos7/cloud.spec +++ b/packaging/centos7/cloud.spec @@ -314,7 +314,10 @@ install -D packaging/systemd/cloudstack-management.default ${RPM_BUILD_ROOT}%{_s install -D server/target/conf/cloudstack-sudoers ${RPM_BUILD_ROOT}%{_sysconfdir}/sudoers.d/%{name}-management touch ${RPM_BUILD_ROOT}%{_localstatedir}/run/%{name}-management.pid #install -D server/target/conf/cloudstack-catalina.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-catalina +<<<<<<< HEAD +======= install -D server/target/conf/cloudstack-management.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-management +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 # SystemVM template mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/templates/systemvm @@ -379,7 +382,10 @@ cp client/target/lib/mysql*jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-usage/lib/ install -D packaging/systemd/cloudstack-usage.service ${RPM_BUILD_ROOT}%{_unitdir}/%{name}-usage.service install -D packaging/systemd/cloudstack-usage.default ${RPM_BUILD_ROOT}%{_sysconfdir}/default/%{name}-usage mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/usage/ +<<<<<<< HEAD +======= install -D usage/target/transformed/cloudstack-usage.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-usage +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 # CLI cp -r cloud-cli/cloudtool ${RPM_BUILD_ROOT}%{python_sitearch}/ @@ -625,7 +631,10 @@ pip3 install --upgrade urllib3 %{_defaultdocdir}/%{name}-management-%{version}/LICENSE %{_defaultdocdir}/%{name}-management-%{version}/NOTICE #%attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name}-catalina +<<<<<<< HEAD +======= %config(noreplace) %attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name}-management +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 %{_datadir}/%{name}-management/setup/wheel/*.whl %files agent @@ -673,7 +682,10 @@ pip3 install --upgrade urllib3 %files usage %attr(0644,root,root) %{_unitdir}/%{name}-usage.service %config(noreplace) %{_sysconfdir}/default/%{name}-usage +<<<<<<< HEAD +======= %config(noreplace) %attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name}-usage +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 %attr(0644,root,root) %{_datadir}/%{name}-usage/*.jar %attr(0644,root,root) %{_datadir}/%{name}-usage/lib/*.jar %dir %attr(0770,root,cloud) %{_localstatedir}/log/%{name}/usage diff --git a/packaging/centos8/cloud.spec b/packaging/centos8/cloud.spec index ebb7af125830..e64cd315d7d8 100644 --- a/packaging/centos8/cloud.spec +++ b/packaging/centos8/cloud.spec @@ -296,7 +296,10 @@ install -D packaging/systemd/cloudstack-management.default ${RPM_BUILD_ROOT}%{_s install -D server/target/conf/cloudstack-sudoers ${RPM_BUILD_ROOT}%{_sysconfdir}/sudoers.d/%{name}-management touch ${RPM_BUILD_ROOT}%{_localstatedir}/run/%{name}-management.pid #install -D server/target/conf/cloudstack-catalina.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-catalina +<<<<<<< HEAD +======= install -D server/target/conf/cloudstack-management.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-management +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 # SystemVM template mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/templates/systemvm @@ -361,7 +364,10 @@ cp client/target/lib/mysql*jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-usage/lib/ install -D packaging/systemd/cloudstack-usage.service ${RPM_BUILD_ROOT}%{_unitdir}/%{name}-usage.service install -D packaging/systemd/cloudstack-usage.default ${RPM_BUILD_ROOT}%{_sysconfdir}/default/%{name}-usage mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/usage/ +<<<<<<< HEAD +======= install -D usage/target/transformed/cloudstack-usage.logrotate ${RPM_BUILD_ROOT}%{_sysconfdir}/logrotate.d/%{name}-usage +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 # Marvin mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-marvin @@ -579,7 +585,10 @@ pip3 install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz %config(noreplace) %{_sysconfdir}/%{name}/management/log4j2.xml %config(noreplace) %{_sysconfdir}/%{name}/management/environment.properties %config(noreplace) %{_sysconfdir}/%{name}/management/java.security.ciphers +<<<<<<< HEAD +======= %config(noreplace) %attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name}-management +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 %attr(0644,root,root) %{_unitdir}/%{name}-management.service %attr(0755,cloud,cloud) %{_localstatedir}/run/%{name}-management.pid %attr(0755,root,root) %{_bindir}/%{name}-setup-management @@ -651,7 +660,10 @@ pip3 install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz %files usage %attr(0644,root,root) %{_unitdir}/%{name}-usage.service %config(noreplace) %{_sysconfdir}/default/%{name}-usage +<<<<<<< HEAD +======= %config(noreplace) %attr(0644,root,root) %{_sysconfdir}/logrotate.d/%{name}-usage +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 %attr(0644,root,root) %{_datadir}/%{name}-usage/*.jar %attr(0644,root,root) %{_datadir}/%{name}-usage/lib/*.jar %dir %attr(0770,root,cloud) %{_localstatedir}/log/%{name}/usage diff --git a/packaging/systemd/cloudstack-agent.service b/packaging/systemd/cloudstack-agent.service index 5e2e5db0b210..be8643a8591b 100644 --- a/packaging/systemd/cloudstack-agent.service +++ b/packaging/systemd/cloudstack-agent.service @@ -31,8 +31,11 @@ EnvironmentFile=/etc/default/cloudstack-agent ExecStart=/usr/bin/java $JAVA_OPTS $JAVA_DEBUG -cp $CLASSPATH $JAVA_CLASS Restart=always RestartSec=10s +<<<<<<< HEAD +======= StandardOutput=append:/var/log/cloudstack/agent/agent.out StandardError=append:/var/log/cloudstack/agent/agent.err +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 [Install] WantedBy=multi-user.target diff --git a/packaging/systemd/cloudstack-management.service b/packaging/systemd/cloudstack-management.service index 55780af7a5c6..5c96771d6322 100644 --- a/packaging/systemd/cloudstack-management.service +++ b/packaging/systemd/cloudstack-management.service @@ -35,8 +35,11 @@ EnvironmentFile=/etc/default/cloudstack-management WorkingDirectory=/var/log/cloudstack/management PIDFile=/var/run/cloudstack-management.pid ExecStart=/usr/bin/java $JAVA_DEBUG $JAVA_OPTS -cp $CLASSPATH $BOOTSTRAP_CLASS +<<<<<<< HEAD +======= StandardOutput=append:/var/log/cloudstack/management/management-server.out StandardError=append:/var/log/cloudstack/management/management-server.err +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 [Install] WantedBy=multi-user.target diff --git a/packaging/systemd/cloudstack-usage.service b/packaging/systemd/cloudstack-usage.service index bf5bd2a189b9..95ae70eee228 100644 --- a/packaging/systemd/cloudstack-usage.service +++ b/packaging/systemd/cloudstack-usage.service @@ -35,8 +35,11 @@ Environment=JAVA_PID=$$ ExecStart=/bin/sh -ec '/usr/bin/java -Dpid=${JAVA_PID} $JAVA_OPTS $JAVA_DEBUG -cp $CLASSPATH $JAVA_CLASS' Restart=always RestartSec=10s +<<<<<<< HEAD +======= StandardOutput=append:/var/log/cloudstack/usage/usage.out StandardError=append:/var/log/cloudstack/usage/usage.err +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 [Install] WantedBy=multi-user.target diff --git a/plugins/api/discovery/src/main/java/org/apache/cloudstack/api/response/ApiDiscoveryResponse.java b/plugins/api/discovery/src/main/java/org/apache/cloudstack/api/response/ApiDiscoveryResponse.java index 81a9df750cbe..d69a652c347f 100644 --- a/plugins/api/discovery/src/main/java/org/apache/cloudstack/api/response/ApiDiscoveryResponse.java +++ b/plugins/api/discovery/src/main/java/org/apache/cloudstack/api/response/ApiDiscoveryResponse.java @@ -16,6 +16,15 @@ // under the License. package org.apache.cloudstack.api.response; +<<<<<<< HEAD +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.util.HashSet; +import java.util.Set; +======= import java.util.HashSet; import java.util.Set; @@ -24,6 +33,7 @@ import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @SuppressWarnings("unused") public class ApiDiscoveryResponse extends BaseResponse { @@ -65,6 +75,8 @@ public ApiDiscoveryResponse() { isAsync = false; } +<<<<<<< HEAD +======= public ApiDiscoveryResponse(ApiDiscoveryResponse another) { this.name = another.getName(); this.description = another.getDescription(); @@ -77,6 +89,7 @@ public ApiDiscoveryResponse(ApiDiscoveryResponse another) { this.setObjectName(another.getObjectName()); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public void setName(String name) { this.name = name; } @@ -136,8 +149,11 @@ public void addApiResponse(ApiResponseResponse apiResponse) { public Set getApiResponse() { return apiResponse; } +<<<<<<< HEAD +======= public String getType() { return type; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/plugins/api/discovery/src/main/java/org/apache/cloudstack/api/response/ApiParameterResponse.java b/plugins/api/discovery/src/main/java/org/apache/cloudstack/api/response/ApiParameterResponse.java index 75f0aacd5046..ea99ee23db1c 100644 --- a/plugins/api/discovery/src/main/java/org/apache/cloudstack/api/response/ApiParameterResponse.java +++ b/plugins/api/discovery/src/main/java/org/apache/cloudstack/api/response/ApiParameterResponse.java @@ -16,14 +16,22 @@ // under the License. package org.apache.cloudstack.api.response; +<<<<<<< HEAD +import com.google.gson.annotations.SerializedName; + +======= import java.util.List; import org.apache.cloudstack.acl.RoleType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import com.cloud.serializer.Param; +<<<<<<< HEAD +======= import com.google.gson.annotations.SerializedName; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public class ApiParameterResponse extends BaseResponse { @SerializedName(ApiConstants.NAME) @@ -54,8 +62,11 @@ public class ApiParameterResponse extends BaseResponse { @Param(description = "comma separated related apis to get the parameter") private String related; +<<<<<<< HEAD +======= private transient List authorizedRoleTypes = null; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public ApiParameterResponse() { } @@ -91,6 +102,8 @@ public void setRelated(String related) { this.related = related; } +<<<<<<< HEAD +======= public void setAuthorizedRoleTypes(List authorizedRoleTypes) { this.authorizedRoleTypes = authorizedRoleTypes; } @@ -98,4 +111,5 @@ public void setAuthorizedRoleTypes(List authorizedRoleTypes) { public List getAuthorizedRoleTypes() { return authorizedRoleTypes; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/plugins/api/discovery/src/main/java/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java b/plugins/api/discovery/src/main/java/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java index 452b95cf2c05..7de21a7d5acb 100644 --- a/plugins/api/discovery/src/main/java/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java +++ b/plugins/api/discovery/src/main/java/org/apache/cloudstack/discovery/ApiDiscoveryServiceImpl.java @@ -18,10 +18,15 @@ import java.lang.reflect.Field; import java.util.ArrayList; +<<<<<<< HEAD +import java.util.HashMap; +import java.util.HashSet; +======= import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -30,22 +35,34 @@ import javax.inject.Inject; import org.apache.cloudstack.acl.APIChecker; +<<<<<<< HEAD +======= import org.apache.cloudstack.acl.Role; import org.apache.cloudstack.acl.RoleService; import org.apache.cloudstack.acl.RoleType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.BaseAsyncCreateCmd; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.Parameter; +<<<<<<< HEAD +import org.apache.cloudstack.acl.Role; +import org.apache.cloudstack.acl.RoleService; +import org.apache.cloudstack.acl.RoleType; +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.command.user.discovery.ListApisCmd; import org.apache.cloudstack.api.response.ApiDiscoveryResponse; import org.apache.cloudstack.api.response.ApiParameterResponse; import org.apache.cloudstack.api.response.ApiResponseResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils; +<<<<<<< HEAD +======= import org.apache.commons.collections.CollectionUtils; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.commons.lang3.StringUtils; import org.reflections.ReflectionUtils; import org.springframework.stereotype.Component; @@ -218,9 +235,12 @@ private ApiDiscoveryResponse getCmdRequestMap(Class cmdClass, APICommand apiC paramResponse.setSince(parameterAnnotation.since()); } paramResponse.setRelated(parameterAnnotation.entityType()[0].getName()); +<<<<<<< HEAD +======= if (parameterAnnotation.authorized() != null) { paramResponse.setAuthorizedRoleTypes(Arrays.asList(parameterAnnotation.authorized())); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 response.addParam(paramResponse); } } @@ -253,7 +273,10 @@ public ListResponse listApis(User user, String name) { if (user == null) return null; +<<<<<<< HEAD +======= Account account = accountService.getAccount(user.getAccountId()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (name != null) { if (!s_apiNameDiscoveryResponseMap.containsKey(name)) @@ -267,9 +290,16 @@ public ListResponse listApis(User user, String name) { return null; } } +<<<<<<< HEAD + responseList.add(s_apiNameDiscoveryResponseMap.get(name)); + + } else { + Account account = accountService.getAccount(user.getAccountId()); +======= responseList.add(getApiDiscoveryResponseWithAccessibleParams(name, account)); } else { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (account == null) { throw new PermissionDeniedException(String.format("The account with id [%s] for user [%s] is null.", user.getAccountId(), user)); } @@ -290,13 +320,19 @@ public ListResponse listApis(User user, String name) { } for (String apiName: apisAllowed) { +<<<<<<< HEAD + responseList.add(s_apiNameDiscoveryResponseMap.get(apiName)); +======= responseList.add(getApiDiscoveryResponseWithAccessibleParams(apiName, account)); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } response.setResponses(responseList); return response; } +<<<<<<< HEAD +======= private static ApiDiscoveryResponse getApiDiscoveryResponseWithAccessibleParams(String name, Account account) { if (Account.Type.ADMIN.equals(account.getType())) { return s_apiNameDiscoveryResponseMap.get(name); @@ -317,6 +353,7 @@ private static ApiDiscoveryResponse getApiDiscoveryResponseWithAccessibleParams( return apiDiscoveryResponse; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Override public List> getCommands() { List> cmdList = new ArrayList>(); diff --git a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilder.java b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilder.java index ecbb809b60bd..1a0fed4a0631 100644 --- a/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilder.java +++ b/plugins/database/quota/src/main/java/org/apache/cloudstack/api/response/QuotaResponseBuilder.java @@ -20,7 +20,10 @@ import org.apache.cloudstack.api.command.QuotaConfigureEmailCmd; import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd; import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.command.QuotaPresetVariablesListCmd; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.command.QuotaStatementCmd; import org.apache.cloudstack.api.command.QuotaTariffCreateCmd; import org.apache.cloudstack.api.command.QuotaTariffListCmd; @@ -73,6 +76,8 @@ public interface QuotaResponseBuilder { boolean deleteQuotaTariff(String quotaTariffUuid); +<<<<<<< HEAD +======= /** * Lists the preset variables for the usage type informed in the command. * @param cmd used to retrieve the Quota usage type parameter. @@ -80,6 +85,7 @@ public interface QuotaResponseBuilder { */ List listQuotaPresetVariables(QuotaPresetVariablesListCmd cmd); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Pair configureQuotaEmail(QuotaConfigureEmailCmd cmd); QuotaConfigureEmailResponse createQuotaConfigureEmailResponse(QuotaEmailConfigurationVO quotaEmailConfigurationVO, Double minBalance, long accountId); 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 7b5667ac13db..d9c090c1c820 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 @@ -16,15 +16,21 @@ //under the License. package org.apache.cloudstack.api.response; +<<<<<<< HEAD +======= import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.time.ZoneId; import java.util.ArrayList; +<<<<<<< HEAD +======= import java.util.Arrays; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import java.util.Calendar; import java.util.Collection; import java.util.Collections; @@ -35,7 +41,10 @@ import java.util.List; import java.util.ListIterator; import java.util.function.Consumer; +<<<<<<< HEAD +======= import java.util.stream.Collectors; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import javax.inject.Inject; @@ -46,7 +55,10 @@ import org.apache.cloudstack.api.command.QuotaConfigureEmailCmd; import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd; import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.command.QuotaPresetVariablesListCmd; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.command.QuotaStatementCmd; import org.apache.cloudstack.api.command.QuotaTariffCreateCmd; import org.apache.cloudstack.api.command.QuotaTariffListCmd; @@ -56,11 +68,14 @@ import org.apache.cloudstack.quota.QuotaManagerImpl; import org.apache.cloudstack.quota.QuotaService; import org.apache.cloudstack.quota.QuotaStatement; +<<<<<<< HEAD +======= import org.apache.cloudstack.quota.activationrule.presetvariables.ComputingResources; import org.apache.cloudstack.quota.activationrule.presetvariables.GenericPresetVariable; import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariableDefinition; import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariables; import org.apache.cloudstack.quota.activationrule.presetvariables.Value; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.quota.constant.QuotaConfig; import org.apache.cloudstack.quota.constant.QuotaTypes; import org.apache.cloudstack.quota.dao.QuotaAccountDao; @@ -78,8 +93,11 @@ import org.apache.cloudstack.quota.vo.QuotaTariffVO; import org.apache.cloudstack.quota.vo.QuotaUsageVO; import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils; +<<<<<<< HEAD +======= import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.reflect.FieldUtils; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.springframework.stereotype.Component; @@ -132,8 +150,11 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { @Inject private QuotaEmailConfigurationDao quotaEmailConfigurationDao; +<<<<<<< HEAD +======= private final Class[] assignableClasses = {GenericPresetVariable.class, ComputingResources.class}; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Override public QuotaTariffResponse createQuotaTariffResponse(QuotaTariffVO tariff) { final QuotaTariffResponse response = new QuotaTariffResponse(); @@ -696,6 +717,8 @@ public boolean deleteQuotaTariff(String quotaTariffUuid) { } @Override +<<<<<<< HEAD +======= public List listQuotaPresetVariables(QuotaPresetVariablesListCmd cmd) { List response; List> variables = new ArrayList<>(); @@ -809,6 +832,7 @@ public QuotaPresetVariablesItemResponse createPresetVariablesItemResponse(Pair>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public Pair configureQuotaEmail(QuotaConfigureEmailCmd cmd) { validateQuotaConfigureEmailCmdParameters(cmd); 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 17fa7bd8425e..fa0b8be04fcf 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 @@ -33,7 +33,10 @@ import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd; import org.apache.cloudstack.api.command.QuotaEnabledCmd; import org.apache.cloudstack.api.command.QuotaListEmailConfigurationCmd; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.command.QuotaPresetVariablesListCmd; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.command.QuotaStatementCmd; import org.apache.cloudstack.api.command.QuotaSummaryCmd; import org.apache.cloudstack.api.command.QuotaTariffCreateCmd; @@ -120,7 +123,10 @@ public List> getCommands() { cmdList.add(QuotaTariffDeleteCmd.class); cmdList.add(QuotaConfigureEmailCmd.class); cmdList.add(QuotaListEmailConfigurationCmd.class); +<<<<<<< HEAD +======= cmdList.add(QuotaPresetVariablesListCmd.class); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return cmdList; } 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 6bca4ea85bb3..6e734a899750 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 @@ -29,7 +29,10 @@ import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; +<<<<<<< HEAD +======= import com.cloud.utils.Pair; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.QuotaConfigureEmailCmd; import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd; @@ -37,9 +40,12 @@ import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.quota.QuotaService; import org.apache.cloudstack.quota.QuotaStatement; +<<<<<<< HEAD +======= import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariableDefinition; import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariables; import org.apache.cloudstack.quota.activationrule.presetvariables.Value; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.quota.constant.QuotaConfig; import org.apache.cloudstack.quota.constant.QuotaTypes; import org.apache.cloudstack.quota.dao.QuotaAccountDao; @@ -423,6 +429,8 @@ public void getQuotaSummaryResponseTestAccountIsNotNullQuotaIsEnabledShouldRetur assertTrue(quotaSummaryResponse.getQuotaEnabled()); } +<<<<<<< HEAD +======= @Test public void filterSupportedTypesTestReturnWhenQuotaTypeDoesNotMatch() throws NoSuchFieldException { List> variables = new ArrayList<>(); @@ -463,6 +471,7 @@ public void filterSupportedTypesTestCallRecursiveMethodWhenIsGenericPresetVariab Mockito.verify(quotaResponseBuilderSpy, Mockito.atLeastOnce()).addAllPresetVariables(Mockito.any(), Mockito.any(QuotaTypes.class), Mockito.anyList(), Mockito.anyString()); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Test (expected = InvalidParameterValueException.class) public void validateQuotaConfigureEmailCmdParametersTestNullQuotaAccount() { @@ -486,6 +495,10 @@ public void validateQuotaConfigureEmailCmdParametersTestEnableNullAndTemplateNam quotaResponseBuilderSpy.validateQuotaConfigureEmailCmdParameters(quotaConfigureEmailCmdMock); } +<<<<<<< HEAD + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Test public void validateQuotaConfigureEmailCmdParametersTestNullTemplateName() { Mockito.doReturn(quotaAccountVOMock).when(quotaAccountDaoMock).findByIdQuotaAccount(Mockito.any()); diff --git a/plugins/event-bus/inmemory/src/main/java/org/apache/cloudstack/mom/inmemory/InMemoryEventBus.java b/plugins/event-bus/inmemory/src/main/java/org/apache/cloudstack/mom/inmemory/InMemoryEventBus.java index 0c00c0639fd9..4f4b8cfc9d42 100644 --- a/plugins/event-bus/inmemory/src/main/java/org/apache/cloudstack/mom/inmemory/InMemoryEventBus.java +++ b/plugins/event-bus/inmemory/src/main/java/org/apache/cloudstack/mom/inmemory/InMemoryEventBus.java @@ -60,8 +60,11 @@ public UUID subscribe(EventTopic topic, EventSubscriber subscriber) throws Event if (subscriber == null || topic == null) { throw new EventBusException("Invalid EventSubscriber/EventTopic object passed."); } +<<<<<<< HEAD +======= logger.debug("subscribing '{}' to events of type '{}' from '{}'", subscriber.toString(), topic.getEventType(), topic.getEventSource()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 UUID subscriberId = UUID.randomUUID(); subscribers.put(subscriberId, new Pair(topic, subscriber)); @@ -70,7 +73,10 @@ public UUID subscribe(EventTopic topic, EventSubscriber subscriber) throws Event @Override public void unsubscribe(UUID subscriberId, EventSubscriber subscriber) throws EventBusException { +<<<<<<< HEAD +======= logger.debug("unsubscribing '{}'", subscriberId); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (subscriberId == null) { throw new EventBusException("Cannot unregister a null subscriberId."); } @@ -88,9 +94,13 @@ public void unsubscribe(UUID subscriberId, EventSubscriber subscriber) throws Ev @Override public void publish(Event event) throws EventBusException { +<<<<<<< HEAD + if (subscribers == null || subscribers.isEmpty()) { +======= logger.trace("publish '{}'", event.getDescription()); if (subscribers == null || subscribers.isEmpty()) { logger.trace("no subscribers, no publish"); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return; // no subscriber to publish to, so just return } diff --git a/plugins/event-bus/kafka/src/main/java/org/apache/cloudstack/mom/kafka/KafkaEventBus.java b/plugins/event-bus/kafka/src/main/java/org/apache/cloudstack/mom/kafka/KafkaEventBus.java index f2589d2d7d09..2590d805bea4 100644 --- a/plugins/event-bus/kafka/src/main/java/org/apache/cloudstack/mom/kafka/KafkaEventBus.java +++ b/plugins/event-bus/kafka/src/main/java/org/apache/cloudstack/mom/kafka/KafkaEventBus.java @@ -87,23 +87,34 @@ public void setName(String name) { @Override public UUID subscribe(EventTopic topic, EventSubscriber subscriber) throws EventBusException { +<<<<<<< HEAD +======= logger.debug("subscribing '{}' to events of type '{}' from '{}'", subscriber.toString(), topic.getEventType(), topic.getEventSource()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 /* NOOP */ return UUID.randomUUID(); } @Override public void unsubscribe(UUID subscriberId, EventSubscriber subscriber) throws EventBusException { +<<<<<<< HEAD +======= logger.debug("unsubscribing '{}'", subscriberId); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 /* NOOP */ } @Override public void publish(Event event) throws EventBusException { +<<<<<<< HEAD + ProducerRecord record = new ProducerRecord(_topic, event.getResourceUUID(), event.getDescription()); + _producer.send(record); +======= logger.trace("publish '{}'", event.getDescription()); ProducerRecord newRecord = new ProducerRecord<>(_topic, event.getResourceUUID(), event.getDescription()); _producer.send(newRecord); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } @Override diff --git a/plugins/event-bus/rabbitmq/src/main/java/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java b/plugins/event-bus/rabbitmq/src/main/java/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java index e8067e75b406..bff6edf5398a 100644 --- a/plugins/event-bus/rabbitmq/src/main/java/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java +++ b/plugins/event-bus/rabbitmq/src/main/java/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java @@ -185,12 +185,19 @@ public static void setRetryInterval(Integer retryInterval) { */ @Override public UUID subscribe(EventTopic topic, EventSubscriber subscriber) throws EventBusException { +<<<<<<< HEAD + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (subscriber == null || topic == null) { throw new EventBusException("Invalid EventSubscriber/EventTopic object passed."); } +<<<<<<< HEAD +======= logger.debug("subscribing '{}' to events of type '{}' from '{}'", subscriber.toString(), topic.getEventType(), topic.getEventSource()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 // create a UUID, that will be used for managing subscriptions and also used as queue name // for on the queue used for the subscriber on the AMQP broker UUID queueId = UUID.randomUUID(); @@ -251,7 +258,10 @@ public void handleDelivery(String queueName, Envelope envelope, AMQP.BasicProper @Override public void unsubscribe(UUID subscriberId, EventSubscriber subscriber) throws EventBusException { +<<<<<<< HEAD +======= logger.debug("unsubscribing '{}'", subscriberId); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 try { String classname = subscriber.getClass().getName(); String queueName = UUID.nameUUIDFromBytes(classname.getBytes()).toString(); @@ -267,7 +277,10 @@ public void unsubscribe(UUID subscriberId, EventSubscriber subscriber) throws Ev // publish event on to the exchange created on AMQP server @Override public void publish(Event event) throws EventBusException { +<<<<<<< HEAD +======= logger.trace("publish '{}'", event.getDescription()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 String routingKey = createRoutingKey(event); String eventDescription = event.getDescription(); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetRemoteVmsCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetRemoteVmsCommandWrapper.java index a9da4a50452a..d6bdebf7eda1 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetRemoteVmsCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetRemoteVmsCommandWrapper.java @@ -47,7 +47,13 @@ public final class LibvirtGetRemoteVmsCommandWrapper extends CommandWrapper>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 HashMap unmanagedInstances = new HashMap<>(); try { Connect conn = LibvirtConnection.getConnection(hypervisorURI); @@ -56,20 +62,38 @@ public Answer execute(final GetRemoteVmsCommand command, final LibvirtComputingR final Domain domain = libvirtComputingResource.getDomain(conn, name); final DomainInfo.DomainState ps = domain.getInfo().state; +<<<<<<< HEAD + + final VirtualMachine.PowerState state = libvirtComputingResource.convertToPowerState(ps); + + logger.debug("VM " + domain.getName() + ": powerstate = " + ps + "; vm state=" + state.toString()); +======= final VirtualMachine.PowerState state = libvirtComputingResource.convertToPowerState(ps); logger.debug("VM " + domain.getName() + " - powerstate: " + ps + ", state: " + state.toString()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (state == VirtualMachine.PowerState.PowerOff) { try { UnmanagedInstanceTO instance = getUnmanagedInstance(libvirtComputingResource, domain, conn); unmanagedInstances.put(instance.getName(), instance); } catch (Exception e) { +<<<<<<< HEAD + logger.error("Error while fetching instance details", e); +======= logger.error("Couldn't fetch VM " + domain.getName() + " details, due to: " + e.getMessage(), e); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } domain.free(); } +<<<<<<< HEAD + logger.debug("Found Vms: "+ unmanagedInstances.size()); + return new GetRemoteVmsAnswer(command, "", unmanagedInstances); + } catch (final LibvirtException e) { + logger.error("Error while listing stopped Vms on remote host: "+ e.getMessage()); + return new Answer(command, false, result); +======= logger.debug("Found " + unmanagedInstances.size() + " stopped VMs on host " + command.getRemoteIp()); return new GetRemoteVmsAnswer(command, "", unmanagedInstances); } catch (final LibvirtException e) { @@ -78,6 +102,7 @@ public Answer execute(final GetRemoteVmsCommand command, final LibvirtComputingR return new Answer(command, false, "Unable to connect to remote host " + command.getRemoteIp() + ", please check the libvirtd tcp connectivity and retry"); } return new Answer(command, false, "Unable to list stopped VMs on remote host " + command.getRemoteIp() + ", due to: " + e.getMessage()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } @@ -103,8 +128,13 @@ private UnmanagedInstanceTO getUnmanagedInstance(LibvirtComputingResource libvir return instance; } catch (Exception e) { +<<<<<<< HEAD + logger.debug("Unable to retrieve unmanaged instance info. ", e); + throw new CloudRuntimeException("Unable to retrieve unmanaged instance info. " + e.getMessage()); +======= logger.debug("Unable to retrieve unmanaged instance info, due to: " + e.getMessage(), e); throw new CloudRuntimeException("Unable to retrieve unmanaged instance info, due to: " + e.getMessage()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } @@ -116,6 +146,10 @@ private UnmanagedInstanceTO.PowerState getPowerState(VirtualMachine.PowerState v return UnmanagedInstanceTO.PowerState.PowerOff; default: return UnmanagedInstanceTO.PowerState.PowerUnknown; +<<<<<<< HEAD + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } @@ -162,6 +196,10 @@ private List getUnmanagedInstanceDisks(List>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Pair sourceHostPath = getSourceHostPath(libvirtComputingResource, diskDef.getSourcePath()); if (sourceHostPath != null) { disk.setDatastoreHost(sourceHostPath.first()); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java index e15a32876927..bfe99db8a927 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapper.java @@ -67,7 +67,10 @@ import com.cloud.agent.api.MigrateAnswer; import com.cloud.agent.api.MigrateCommand; import com.cloud.agent.api.MigrateCommand.MigrateDiskInfo; +<<<<<<< HEAD +======= import com.cloud.agent.api.to.DataTO; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.DpdkTO; import com.cloud.agent.api.to.VirtualMachineTO; @@ -91,7 +94,10 @@ public final class LibvirtMigrateCommandWrapper extends CommandWrapper>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 protected String createMigrationURI(final String destinationIp, final LibvirtComputingResource libvirtComputingResource) { if (StringUtils.isEmpty(destinationIp)) { @@ -166,7 +172,10 @@ Use VIR_DOMAIN_XML_SECURE (value = 1) prior to v1.0.0. String vncPassword = org.apache.commons.lang3.StringUtils.truncate(to.getVncPassword(), 8); xmlDesc = replaceIpForVNCInDescFileAndNormalizePassword(xmlDesc, target, vncPassword, vmName); +<<<<<<< HEAD +======= // Replace Config Drive ISO path +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 String oldIsoVolumePath = getOldVolumePath(disks, vmName); String newIsoVolumePath = getNewVolumePathIfDatastoreHasChanged(libvirtComputingResource, conn, to); if (newIsoVolumePath != null && !newIsoVolumePath.equals(oldIsoVolumePath)) { @@ -176,6 +185,8 @@ Use VIR_DOMAIN_XML_SECURE (value = 1) prior to v1.0.0. logger.debug(String.format("Replaced disk mount point [%s] with [%s] in VM [%s] XML configuration. New XML configuration is [%s].", oldIsoVolumePath, newIsoVolumePath, vmName, xmlDesc)); } } +<<<<<<< HEAD +======= // Replace CDROM ISO path String oldCdromIsoPath = getOldVolumePathForCdrom(disks, vmName); @@ -184,6 +195,7 @@ Use VIR_DOMAIN_XML_SECURE (value = 1) prior to v1.0.0. xmlDesc = replaceCdromIsoPath(xmlDesc, vmName, oldCdromIsoPath, newCdromIsoPath); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 // delete the metadata of vm snapshots before migration vmsnapshots = libvirtComputingResource.cleanVMSnapshotMetadata(dm); @@ -712,6 +724,8 @@ private String getNewVolumePathIfDatastoreHasChanged(LibvirtComputingResource li return newIsoVolumePath; } +<<<<<<< HEAD +======= private String getOldVolumePathForCdrom(List disks, String vmName) { String oldIsoVolumePath = null; for (DiskDef disk : disks) { @@ -787,6 +801,7 @@ protected String replaceCdromIsoPath(String xmlDesc, String vmName, String oldIs return getXml(doc); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private String getPathFromSourceText(Set paths, String sourceText) { if (paths != null && StringUtils.isNotBlank(sourceText)) { for (String path : paths) { diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateVolumeCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateVolumeCommandWrapper.java index cd5ce031e64e..4cc6e7cf91e8 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateVolumeCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateVolumeCommandWrapper.java @@ -140,6 +140,10 @@ protected MigrateVolumeAnswer migratePowerFlexVolume(final MigrateVolumeCommand logger.info(String.format("Block copy has started for the volume %s : %s ", destDiskLabel, srcPath)); return checkBlockJobStatus(command, dm, destDiskLabel, srcPath, destPath, libvirtComputingResource, conn, srcSecretUUID); +<<<<<<< HEAD + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } catch (Exception e) { String msg = "Migrate volume failed due to " + e.toString(); logger.warn(msg, e); @@ -165,6 +169,19 @@ protected MigrateVolumeAnswer migratePowerFlexVolume(final MigrateVolumeCommand protected MigrateVolumeAnswer checkBlockJobStatus(MigrateVolumeCommand command, Domain dm, String diskLabel, String srcPath, String destPath, LibvirtComputingResource libvirtComputingResource, Connect conn, String srcSecretUUID) throws LibvirtException { int timeBetweenTries = 1000; // Try more frequently (every sec) and return early if disk is found int waitTimeInSec = command.getWait(); +<<<<<<< HEAD + while (waitTimeInSec > 0) { + DomainBlockJobInfo blockJobInfo = dm.getBlockJobInfo(diskLabel, 0); + if (blockJobInfo != null) { + logger.debug(String.format("Volume %s : %s block copy progress: %s%% current value:%s end value:%s", diskLabel, srcPath, (blockJobInfo.end == 0)? 0 : 100*(blockJobInfo.cur / (double) blockJobInfo.end), blockJobInfo.cur, blockJobInfo.end)); + if (blockJobInfo.cur == blockJobInfo.end) { + logger.info(String.format("Block copy completed for the volume %s : %s", diskLabel, srcPath)); + dm.blockJobAbort(diskLabel, Domain.BlockJobAbortFlags.PIVOT); + if (StringUtils.isNotEmpty(srcSecretUUID)) { + libvirtComputingResource.removeLibvirtVolumeSecret(conn, srcSecretUUID); + } + break; +======= double blockCopyProgress = 0; while (waitTimeInSec > 0) { DomainBlockJobInfo blockJobInfo = dm.getBlockJobInfo(diskLabel, 0); @@ -186,6 +203,7 @@ protected MigrateVolumeAnswer checkBlockJobStatus(MigrateVolumeCommand command, logger.warn(msg); return new MigrateVolumeAnswer(command, false, msg, null); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } else { logger.info("Failed to get the block copy status, trying to abort the job"); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePool.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePool.java index 674799c0bbe3..a69b0184e472 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePool.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStoragePool.java @@ -38,9 +38,12 @@ public interface KVMStoragePool { public static final long HeartBeatUpdateRetrySleep = AgentPropertiesFileHandler.getPropertyValue(AgentProperties.KVM_HEARTBEAT_UPDATE_RETRY_SLEEP); public static final long HeartBeatCheckerTimeout = AgentPropertiesFileHandler.getPropertyValue(AgentProperties.KVM_HEARTBEAT_CHECKER_TIMEOUT); +<<<<<<< HEAD +======= public default KVMPhysicalDisk createPhysicalDisk(String volumeUuid, PhysicalDiskFormat format, Storage.ProvisioningType provisioningType, long size, Long usableSize, byte[] passphrase) { return createPhysicalDisk(volumeUuid, format, provisioningType, size, passphrase); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public KVMPhysicalDisk createPhysicalDisk(String volumeUuid, PhysicalDiskFormat format, Storage.ProvisioningType provisioningType, long size, byte[] passphrase); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java index b9671c872d13..44ed3e54e751 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java @@ -1633,7 +1633,11 @@ public Answer createVolume(final CreateObjectCommand cmd) { } } else { vol = primaryPool.createPhysicalDisk(volume.getUuid(), format, +<<<<<<< HEAD + volume.getProvisioningType(), disksize, volume.getPassphrase()); +======= volume.getProvisioningType(), disksize, volume.getUsableSize(), volume.getPassphrase()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } final VolumeObjectTO newVol = new VolumeObjectTO(); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java index b80accd60181..2e680dab1db9 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java @@ -848,7 +848,11 @@ private KVMPhysicalDisk createPhysicalDiskByQemuImg(String name, KVMStoragePool destFile.setFormat(format); destFile.setSize(size); Map options = new HashMap(); +<<<<<<< HEAD + if (pool.getType() == StoragePoolType.NetworkFilesystem){ +======= if (List.of(StoragePoolType.NetworkFilesystem, StoragePoolType.Filesystem).contains(pool.getType())) { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 options.put("preallocation", QemuImg.PreallocationType.getPreallocationType(provisioningType).toString()); } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptor.java index 1b660671b41f..e59b7dad6899 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptor.java @@ -154,11 +154,14 @@ public boolean deleteStoragePool(String uuid) { return MapStorageUuidToStoragePool.remove(uuid) != null; } +<<<<<<< HEAD +======= @Override public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, QemuImg.PhysicalDiskFormat format, Storage.ProvisioningType provisioningType, long size, byte[] passphrase) { return createPhysicalDisk(name, pool, format, provisioningType, size, null, passphrase); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 /** * ScaleIO doesn't need to communicate with the hypervisor normally to create a volume. This is used only to prepare a ScaleIO data disk for encryption. * Thin encrypted volumes are provisioned in QCOW2 format, which insulates the guest from zeroes/unallocated blocks in the block device that would @@ -168,12 +171,19 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, Qemu * @param format disk format * @param provisioningType provisioning type * @param size disk size +<<<<<<< HEAD +======= * @param usableSize usage disk size +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 * @param passphrase passphrase * @return the disk object */ @Override +<<<<<<< HEAD + public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, QemuImg.PhysicalDiskFormat format, Storage.ProvisioningType provisioningType, long size, byte[] passphrase) { +======= public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, QemuImg.PhysicalDiskFormat format, Storage.ProvisioningType provisioningType, long size, Long usableSize, byte[] passphrase) { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (passphrase == null || passphrase.length == 0) { return null; } @@ -191,12 +201,16 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, Qemu QemuImg qemuImg = new QemuImg(0, true, false); Map options = new HashMap<>(); List qemuObjects = new ArrayList<>(); +<<<<<<< HEAD + long formattedSize = getUsableBytesFromRawBytes(disk.getSize()); +======= long formattedSize; if (usableSize != null && usableSize > 0) { formattedSize = usableSize; } else { formattedSize = getUsableBytesFromRawBytes(disk.getSize()); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 options.put("preallocation", QemuImg.PreallocationType.Metadata.toString()); qemuObjects.add(QemuObject.prepareSecretForQemuImg(disk.getFormat(), disk.getQemuEncryptFormat(), keyFile.toString(), "sec0", options)); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStoragePool.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStoragePool.java index 77f21910da6c..d2630b3a6725 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStoragePool.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStoragePool.java @@ -73,11 +73,14 @@ private void addSDCDetails() { } @Override +<<<<<<< HEAD +======= public KVMPhysicalDisk createPhysicalDisk(String volumeUuid, QemuImg.PhysicalDiskFormat format, Storage.ProvisioningType provisioningType, long size, Long usableSize, byte[] passphrase) { return this.storageAdaptor.createPhysicalDisk(volumeUuid, this, format, provisioningType, size, usableSize, passphrase); } @Override +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public KVMPhysicalDisk createPhysicalDisk(String volumeUuid, QemuImg.PhysicalDiskFormat format, Storage.ProvisioningType provisioningType, long size, byte[] passphrase) { return this.storageAdaptor.createPhysicalDisk(volumeUuid, this, format, provisioningType, size, passphrase); } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/StorageAdaptor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/StorageAdaptor.java index 6d58dccb5d1e..a892131df6fa 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/StorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/StorageAdaptor.java @@ -41,11 +41,14 @@ public interface StorageAdaptor { public boolean deleteStoragePool(String uuid); +<<<<<<< HEAD +======= public default KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, PhysicalDiskFormat format, Storage.ProvisioningType provisioningType, long size, Long usableSize, byte[] passphrase) { return createPhysicalDisk(name, pool, format, provisioningType, size, passphrase); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, PhysicalDiskFormat format, Storage.ProvisioningType provisioningType, long size, byte[] passphrase); @@ -57,6 +60,10 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, public boolean disconnectPhysicalDisk(Map volumeToDisconnect); +<<<<<<< HEAD + // given local path to file/device (per Libvirt XML), 1) check that device is + // handled by your adaptor, return false if not. 2) clean up device, return true +======= /** * Given local path to file/device (per Libvirt XML), * 1) Make sure to check that device is handled by your adaptor, return false if not. @@ -68,6 +75,7 @@ public KVMPhysicalDisk createPhysicalDisk(String name, KVMStoragePool pool, * @param localPath path for the file/device from the disk definition per Libvirt XML. * @return true if the operation is successful; false if the operation fails or the adapter fails to handle the path. */ +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public boolean disconnectPhysicalDiskByPath(String localPath); public boolean deletePhysicalDisk(String uuid, KVMStoragePool pool, Storage.ImageFormat format); diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapperTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapperTest.java index b9316c6c042e..ad9077fdd8d7 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapperTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtConvertInstanceCommandWrapperTest.java @@ -214,7 +214,10 @@ public void testGetUnmanagedInstanceDisks() { LibvirtDomainXMLParser parser = Mockito.mock(LibvirtDomainXMLParser.class); Mockito.when(parser.getDisks()).thenReturn(List.of(diskDef)); +<<<<<<< HEAD +======= Mockito.doReturn(new Pair(null, null)).when(convertInstanceCommandWrapper).getNfsStoragePoolHostAndPath(destinationPool); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 List unmanagedInstanceDisks = convertInstanceCommandWrapper.getUnmanagedInstanceDisks(disks, parser); Assert.assertEquals(1, unmanagedInstanceDisks.size()); diff --git a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java index 3c5e54e2ba89..15fe64e481dd 100644 --- a/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java +++ b/plugins/hypervisors/kvm/src/test/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtMigrateCommandWrapperTest.java @@ -132,7 +132,10 @@ public class LibvirtMigrateCommandWrapperTest { " \n" + " \n" + " \n" + +<<<<<<< HEAD +======= " \n" + +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 " \n" + " \n" + " \n" + @@ -250,7 +253,10 @@ public class LibvirtMigrateCommandWrapperTest { " \n" + " \n" + " \n" + +<<<<<<< HEAD +======= " \n" + +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 " \n" + " \n" + " \n" + @@ -1009,6 +1015,8 @@ public void getMigrateStorageDeviceLabelsTestFindPathAndLabels() { assertTrue(result.containsAll(Arrays.asList("vda", "vdb"))); } +<<<<<<< HEAD +======= @Test public void replaceCdromIsoPathTest() throws ParserConfigurationException, IOException, TransformerException, SAXException { @@ -1019,4 +1027,5 @@ public void replaceCdromIsoPathTest() throws ParserConfigurationException, IOExc Assert.assertTrue(finalXml.contains(newIsoVolumePath)); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java index 7be0dd5862fe..67df6330ba10 100644 --- a/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java +++ b/plugins/hypervisors/vmware/src/main/java/com/cloud/storage/resource/VmwareStorageProcessor.java @@ -948,7 +948,11 @@ private String createVMAndFolderWithVMName(VmwareContext context, VmwareHypervis dsMo.moveDatastoreFile(vmwareLayoutFilePair[i], dcMo.getMor(), dsMo.getMor(), legacyCloudStackLayoutFilePair[i], dcMo.getMor(), true); } +<<<<<<< HEAD + logger.info("detach disks from volume-wrapper VM and destroy" + vmdkName); +======= logger.info("detach disks from volume-wrapper VM and destroy {}", vmdkName); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 vmMo.detachAllDisksAndDestroy(); String srcFile = dsMo.getDatastorePath(vmdkName, true); diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterHelperImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterHelperImpl.java new file mode 100644 index 000000000000..60bd81c7c5a5 --- /dev/null +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterHelperImpl.java @@ -0,0 +1,61 @@ +// 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.kubernetes.cluster; + +import com.cloud.kubernetes.cluster.dao.KubernetesClusterDao; +import com.cloud.kubernetes.cluster.dao.KubernetesClusterVmMapDao; +import com.cloud.utils.component.AdapterBase; +import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.framework.config.ConfigKey; +import org.apache.cloudstack.framework.config.Configurable; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.util.Objects; + +@Component +public class KubernetesClusterHelperImpl extends AdapterBase implements KubernetesClusterHelper, Configurable { + + @Inject + private KubernetesClusterDao kubernetesClusterDao; + @Inject + private KubernetesClusterVmMapDao kubernetesClusterVmMapDao; + + @Override + public ControlledEntity findByUuid(String uuid) { + return kubernetesClusterDao.findByUuid(uuid); + } + + @Override + public ControlledEntity findByVmId(long vmId) { + KubernetesClusterVmMapVO clusterVmMapVO = kubernetesClusterVmMapDao.getClusterMapFromVmId(vmId); + if (Objects.isNull(clusterVmMapVO)) { + return null; + } + return kubernetesClusterDao.findById(clusterVmMapVO.getClusterId()); + } + + @Override + public String getConfigComponentName() { + return KubernetesClusterHelper.class.getSimpleName(); + } + + @Override + public ConfigKey[] getConfigKeys() { + return new ConfigKey[]{}; + } +} diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java index 151344575dcc..9397a9acb859 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java @@ -40,11 +40,19 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +<<<<<<< HEAD +import com.cloud.uservm.UserVm; +import com.cloud.vm.UserVmService; +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.annotation.AnnotationService; import org.apache.cloudstack.annotation.dao.AnnotationDao; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.ApiCommandResourceType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants.VMDetails; import org.apache.cloudstack.api.BaseCmd; @@ -89,7 +97,10 @@ import com.cloud.dc.dao.DataCenterDao; import com.cloud.deploy.DeployDestination; import com.cloud.domain.Domain; +<<<<<<< HEAD +======= import com.cloud.event.ActionEvent; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InsufficientServerCapacityException; @@ -157,7 +168,10 @@ import com.cloud.user.UserVO; import com.cloud.user.dao.SSHKeyPairDao; import com.cloud.user.dao.UserDao; +<<<<<<< HEAD +======= import com.cloud.uservm.UserVm; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.utils.Pair; import com.cloud.utils.Ternary; import com.cloud.utils.component.ComponentContext; @@ -175,7 +189,10 @@ import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.StateMachine2; import com.cloud.utils.net.NetUtils; +<<<<<<< HEAD +======= import com.cloud.vm.UserVmService; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.VMInstanceDao; @@ -517,7 +534,13 @@ private DeployDestination plan(final long nodesCount, final DataCenter zone, fin logger.debug(String.format("Checking host ID: %s for capacity already reserved %d", hostVO.getUuid(), reserved)); } if (capacityManager.checkIfHostHasCapacity(hostVO.getId(), cpu_requested * reserved, ram_requested * reserved, false, cpuOvercommitRatio, memoryOvercommitRatio, true)) { +<<<<<<< HEAD + if (logger.isDebugEnabled()) { + logger.debug(String.format("Found host ID: %s for with enough capacity, CPU=%d RAM=%s", hostVO.getUuid(), cpu_requested * reserved, toHumanReadableSize(ram_requested * reserved))); + } +======= logger.debug("Found host ID == '{}' to have enough capacity, CPU={} RAM={}", hostVO.getUuid(), cpu_requested * reserved, toHumanReadableSize(ram_requested * reserved)); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 hostEntry.setValue(new Pair(hostVO, reserved)); suitable_host_found = true; planCluster = cluster; @@ -866,6 +889,15 @@ private Network getKubernetesClusterNetworkIfMissing(final String clusterName, f logger.info(String.format("Creating network for account ID: %s from the network offering ID: %s as part of Kubernetes cluster: %s deployment process", owner.getUuid(), networkOffering.getUuid(), clusterName)); } +<<<<<<< HEAD + try { + network = networkMgr.createGuestNetwork(networkOffering.getId(), clusterName + "-network", owner.getAccountName() + "-network", + null, null, null, false, null, owner, null, physicalNetwork, zone.getId(), + ControlledEntity.ACLType.Account, null, null, null, null, true, null, + null, null, null, null, null, null, null, null, null); + } catch (ConcurrentOperationException | InsufficientCapacityException | ResourceAllocationException e) { + logAndThrow(Level.ERROR, String.format("Unable to create network for the Kubernetes cluster: %s", clusterName)); +======= CallContext networkContext = CallContext.register(CallContext.current(), ApiCommandResourceType.Network); try { network = networkService.createGuestNetwork(networkOffering.getId(), clusterName + "-network", @@ -875,6 +907,7 @@ private Network getKubernetesClusterNetworkIfMissing(final String clusterName, f logAndThrow(Level.ERROR, String.format("Unable to create network for the Kubernetes cluster: %s", clusterName)); } finally { CallContext.unregister(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } return network; @@ -1143,8 +1176,11 @@ protected boolean stateTransitTo(long kubernetesClusterId, KubernetesCluster.Eve } @Override +<<<<<<< HEAD +======= @ActionEvent(eventType = KubernetesClusterEventTypes.EVENT_KUBERNETES_CLUSTER_CREATE, eventDescription = "creating Kubernetes cluster", create = true) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public KubernetesCluster createUnmanagedKubernetesCluster(CreateKubernetesClusterCmd cmd) throws CloudRuntimeException { if (!KubernetesServiceEnabled.value()) { logAndThrow(Level.ERROR, "Kubernetes Service plugin is disabled"); @@ -1191,13 +1227,19 @@ public KubernetesClusterVO doInTransaction(TransactionStatus status) { if (logger.isInfoEnabled()) { logger.info(String.format("Kubernetes cluster with name: %s and ID: %s has been created", cluster.getName(), cluster.getUuid())); } +<<<<<<< HEAD +======= CallContext.current().putContextParameter(KubernetesCluster.class, cluster.getUuid()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return cluster; } @Override +<<<<<<< HEAD +======= @ActionEvent(eventType = KubernetesClusterEventTypes.EVENT_KUBERNETES_CLUSTER_CREATE, eventDescription = "creating Kubernetes cluster", create = true) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public KubernetesCluster createManagedKubernetesCluster(CreateKubernetesClusterCmd cmd) throws CloudRuntimeException { if (!KubernetesServiceEnabled.value()) { logAndThrow(Level.ERROR, "Kubernetes Service plugin is disabled"); @@ -1254,7 +1296,10 @@ public KubernetesClusterVO doInTransaction(TransactionStatus status) { if (logger.isInfoEnabled()) { logger.info(String.format("Kubernetes cluster name: %s and ID: %s has been created", cluster.getName(), cluster.getUuid())); } +<<<<<<< HEAD +======= CallContext.current().putContextParameter(KubernetesCluster.class, cluster.getUuid()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return cluster; } @@ -1281,6 +1326,8 @@ private SecurityGroup getOrCreateSecurityGroupForAccount(Account owner) { return securityGroup; } +<<<<<<< HEAD +======= @Override @ActionEvent(eventType = KubernetesClusterEventTypes.EVENT_KUBERNETES_CLUSTER_CREATE, eventDescription = "creating Kubernetes cluster", async = true) @@ -1321,17 +1368,36 @@ public void startKubernetesCluster(StartKubernetesClusterCmd cmd) throws CloudRu } } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 /** * Start operation can be performed at two different life stages of Kubernetes cluster. First when a freshly created cluster * in which case there are no resources provisioned for the Kubernetes cluster. So during start all the resources * are provisioned from scratch. Second kind of start, happens on Stopped Kubernetes cluster, in which all resources * are provisioned (like volumes, nics, networks etc). It just that VM's are not in running state. So just * start the VM's (which can possibly implicitly start the network also). +<<<<<<< HEAD + * @param kubernetesClusterId +======= * @param kubernetesCluster +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 * @param onCreate * @return * @throws CloudRuntimeException */ +<<<<<<< HEAD + + @Override + public boolean startKubernetesCluster(long kubernetesClusterId, boolean onCreate) throws CloudRuntimeException { + if (!KubernetesServiceEnabled.value()) { + logAndThrow(Level.ERROR, "Kubernetes Service plugin is disabled"); + } + final KubernetesClusterVO kubernetesCluster = kubernetesClusterDao.findById(kubernetesClusterId); + if (kubernetesCluster == null) { + throw new InvalidParameterValueException("Failed to find Kubernetes cluster with given ID"); + } + if (kubernetesCluster.getRemoved() != null) { + throw new InvalidParameterValueException(String.format("Kubernetes cluster : %s is already deleted", kubernetesCluster.getName())); +======= public boolean startKubernetesCluster(KubernetesClusterVO kubernetesCluster, boolean onCreate) throws CloudRuntimeException { if (!KubernetesServiceEnabled.value()) { logAndThrow(Level.ERROR, "Kubernetes Service plugin is disabled"); @@ -1339,6 +1405,7 @@ public boolean startKubernetesCluster(KubernetesClusterVO kubernetesCluster, boo if (kubernetesCluster.getRemoved() != null) { throw new InvalidParameterValueException(String.format("Kubernetes cluster : %s is already deleted", kubernetesCluster.getName())); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } accountManager.checkAccess(CallContext.current().getCallingAccount(), SecurityChecker.AccessType.OperateEntry, false, kubernetesCluster); if (kubernetesCluster.getState().equals(KubernetesCluster.State.Running)) { @@ -1396,8 +1463,11 @@ private String[] getServiceUserKeys(KubernetesClusterVO kubernetesCluster) { } @Override +<<<<<<< HEAD +======= @ActionEvent(eventType = KubernetesClusterEventTypes.EVENT_KUBERNETES_CLUSTER_STOP, eventDescription = "stopping Kubernetes cluster", async = true) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public boolean stopKubernetesCluster(StopKubernetesClusterCmd cmd) throws CloudRuntimeException { long kubernetesClusterId = cmd.getId(); if (!KubernetesServiceEnabled.value()) { @@ -1432,8 +1502,11 @@ public boolean stopKubernetesCluster(StopKubernetesClusterCmd cmd) throws CloudR } @Override +<<<<<<< HEAD +======= @ActionEvent(eventType = KubernetesClusterEventTypes.EVENT_KUBERNETES_CLUSTER_DELETE, eventDescription = "deleting Kubernetes cluster", async = true) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public boolean deleteKubernetesCluster(DeleteKubernetesClusterCmd cmd) throws CloudRuntimeException { if (!KubernetesServiceEnabled.value()) { logAndThrow(Level.ERROR, "Kubernetes Service plugin is disabled"); @@ -1536,6 +1609,15 @@ public ListResponse listKubernetesClusters(ListKubern if (clusterType != null) { sc.setParameters("cluster_type", clusterType); } +<<<<<<< HEAD + List kubernetesClusters = kubernetesClusterDao.search(sc, searchFilter); + for (KubernetesClusterVO cluster : kubernetesClusters) { + KubernetesClusterResponse clusterResponse = createKubernetesClusterResponse(cluster.getId()); + responsesList.add(clusterResponse); + } + ListResponse response = new ListResponse(); + response.setResponses(responsesList); +======= Pair, Integer> kubernetesClustersAndCount = kubernetesClusterDao.searchAndCount(sc, searchFilter); for (KubernetesClusterVO cluster : kubernetesClustersAndCount.first()) { KubernetesClusterResponse clusterResponse = createKubernetesClusterResponse(cluster.getId()); @@ -1543,6 +1625,7 @@ public ListResponse listKubernetesClusters(ListKubern } ListResponse response = new ListResponse<>(); response.setResponses(responsesList, kubernetesClustersAndCount.second()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return response; } @@ -1576,8 +1659,11 @@ public KubernetesClusterConfigResponse getKubernetesClusterConfig(GetKubernetesC } @Override +<<<<<<< HEAD +======= @ActionEvent(eventType = KubernetesClusterEventTypes.EVENT_KUBERNETES_CLUSTER_SCALE, eventDescription = "scaling Kubernetes cluster", async = true) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public boolean scaleKubernetesCluster(ScaleKubernetesClusterCmd cmd) throws CloudRuntimeException { if (!KubernetesServiceEnabled.value()) { logAndThrow(Level.ERROR, "Kubernetes Service plugin is disabled"); @@ -1585,6 +1671,18 @@ public boolean scaleKubernetesCluster(ScaleKubernetesClusterCmd cmd) throws Clou validateKubernetesClusterScaleParameters(cmd); KubernetesClusterVO kubernetesCluster = kubernetesClusterDao.findById(cmd.getId()); +<<<<<<< HEAD + String[] keys = getServiceUserKeys(kubernetesCluster); + KubernetesClusterScaleWorker scaleWorker = + new KubernetesClusterScaleWorker(kubernetesClusterDao.findById(cmd.getId()), + serviceOfferingDao.findById(cmd.getServiceOfferingId()), + cmd.getClusterSize(), + cmd.getNodeIds(), + cmd.isAutoscalingEnabled(), + cmd.getMinSize(), + cmd.getMaxSize(), + this); +======= final Long clusterSize = cmd.getClusterSize(); if (clusterSize != null) { CallContext.current().setEventDetails(String.format("Kubernetes cluster ID: %s scaling from size: %d to %d", @@ -1600,14 +1698,18 @@ public boolean scaleKubernetesCluster(ScaleKubernetesClusterCmd cmd) throws Clou cmd.getMinSize(), cmd.getMaxSize(), this); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 scaleWorker.setKeys(keys); scaleWorker = ComponentContext.inject(scaleWorker); return scaleWorker.scaleCluster(); } @Override +<<<<<<< HEAD +======= @ActionEvent(eventType = KubernetesClusterEventTypes.EVENT_KUBERNETES_CLUSTER_UPGRADE, eventDescription = "upgrading Kubernetes cluster", async = true) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public boolean upgradeKubernetesCluster(UpgradeKubernetesClusterCmd cmd) throws CloudRuntimeException { if (!KubernetesServiceEnabled.value()) { logAndThrow(Level.ERROR, "Kubernetes Service plugin is disabled"); diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterService.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterService.java index 6acc876493ef..2f0a29491184 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterService.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterService.java @@ -23,7 +23,10 @@ import org.apache.cloudstack.api.command.user.kubernetes.cluster.ListKubernetesClustersCmd; import org.apache.cloudstack.api.command.user.kubernetes.cluster.RemoveVirtualMachinesFromKubernetesClusterCmd; import org.apache.cloudstack.api.command.user.kubernetes.cluster.ScaleKubernetesClusterCmd; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.command.user.kubernetes.cluster.StartKubernetesClusterCmd; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.command.user.kubernetes.cluster.StopKubernetesClusterCmd; import org.apache.cloudstack.api.command.user.kubernetes.cluster.UpgradeKubernetesClusterCmd; import org.apache.cloudstack.api.response.KubernetesClusterConfigResponse; @@ -99,9 +102,13 @@ public interface KubernetesClusterService extends PluggableService, Configurable KubernetesCluster createManagedKubernetesCluster(CreateKubernetesClusterCmd cmd) throws CloudRuntimeException; +<<<<<<< HEAD + boolean startKubernetesCluster(long kubernetesClusterId, boolean onCreate) throws CloudRuntimeException; +======= void startKubernetesCluster(CreateKubernetesClusterCmd cmd) throws CloudRuntimeException; void startKubernetesCluster(StartKubernetesClusterCmd cmd) throws CloudRuntimeException; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 boolean stopKubernetesCluster(StopKubernetesClusterCmd cmd) throws CloudRuntimeException; diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java index 0ef3ee96d328..3deeebe3858a 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterActionWorker.java @@ -34,11 +34,17 @@ import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; +<<<<<<< HEAD +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.ca.CAManager; +import org.apache.cloudstack.config.ApiServiceConfiguration; +======= import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.ca.CAManager; import org.apache.cloudstack.config.ApiServiceConfiguration; import org.apache.cloudstack.context.CallContext; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.commons.collections.CollectionUtils; @@ -94,7 +100,11 @@ import com.cloud.vm.UserVmDetailVO; import com.cloud.vm.UserVmService; import com.cloud.vm.UserVmVO; +<<<<<<< HEAD +import com.cloud.vm.VirtualMachineManager; +======= import com.cloud.vm.VirtualMachine; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.vm.VmDetailConstants; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.UserVmDetailsDao; @@ -152,6 +162,11 @@ public class KubernetesClusterActionWorker { @Inject protected VlanDao vlanDao; @Inject +<<<<<<< HEAD + protected VirtualMachineManager itMgr; + @Inject +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 protected LaunchPermissionDao launchPermissionDao; @Inject public ProjectService projectService; @@ -475,8 +490,11 @@ protected void attachIsoKubernetesVMs(List clusterVMs, final KubernetesS } for (UserVm vm : clusterVMs) { +<<<<<<< HEAD +======= CallContext vmContext = CallContext.register(CallContext.current(), ApiCommandResourceType.VirtualMachine); vmContext.putContextParameter(VirtualMachine.class, vm.getUuid()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 try { templateService.attachIso(iso.getId(), vm.getId(), true); if (logger.isInfoEnabled()) { @@ -484,8 +502,11 @@ protected void attachIsoKubernetesVMs(List clusterVMs, final KubernetesS } } catch (CloudRuntimeException ex) { logTransitStateAndThrow(Level.ERROR, String.format("Failed to attach binaries ISO for VM : %s in the Kubernetes cluster name: %s", vm.getDisplayName(), kubernetesCluster.getName()), kubernetesCluster.getId(), failedEvent, ex); +<<<<<<< HEAD +======= } finally { CallContext.unregister(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } } @@ -497,14 +518,20 @@ protected void attachIsoKubernetesVMs(List clusterVMs) throws CloudRunti protected void detachIsoKubernetesVMs(List clusterVMs) { for (UserVm vm : clusterVMs) { boolean result = false; +<<<<<<< HEAD +======= CallContext vmContext = CallContext.register(CallContext.current(), ApiCommandResourceType.VirtualMachine); vmContext.putContextParameter(VirtualMachine.class, vm.getUuid()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 try { result = templateService.detachIso(vm.getId(), true); } catch (CloudRuntimeException ex) { logger.warn(String.format("Failed to detach binaries ISO from VM : %s in the Kubernetes cluster : %s ", vm.getDisplayName(), kubernetesCluster.getName()), ex); +<<<<<<< HEAD +======= } finally { CallContext.unregister(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } if (result) { if (logger.isInfoEnabled()) { diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterDestroyWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterDestroyWorker.java index 047d32f1f9fa..f34a12e1aa33 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterDestroyWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterDestroyWorker.java @@ -25,7 +25,10 @@ import org.apache.cloudstack.annotation.AnnotationService; import org.apache.cloudstack.annotation.dao.AnnotationDao; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.ApiCommandResourceType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.context.CallContext; import org.apache.commons.collections.CollectionUtils; @@ -94,9 +97,12 @@ private boolean destroyClusterVMs() { if (userVM == null || userVM.isRemoved()) { continue; } +<<<<<<< HEAD +======= CallContext vmContext = CallContext.register(CallContext.current(), ApiCommandResourceType.VirtualMachine); vmContext.setEventResourceId(vmID); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 try { UserVm vm = userVmService.destroyVm(vmID, true); if (!userVmManager.expunge(userVM)) { @@ -110,8 +116,11 @@ private boolean destroyClusterVMs() { } catch (ResourceUnavailableException | ConcurrentOperationException e) { logger.warn(String.format("Failed to destroy VM : %s part of the Kubernetes cluster : %s cleanup. Moving on with destroying remaining resources provisioned for the Kubernetes cluster", userVM.getDisplayName(), kubernetesCluster.getName()), e); return false; +<<<<<<< HEAD +======= } finally { CallContext.unregister(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java index d75076eb3d38..dfaadd7b13e4 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterResourceModifierActionWorker.java @@ -31,13 +31,23 @@ import javax.inject.Inject; +<<<<<<< HEAD +import com.cloud.offering.NetworkOffering; +import com.cloud.offerings.dao.NetworkOfferingDao; +======= import org.apache.cloudstack.api.ApiCommandResourceType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.command.user.firewall.CreateFirewallRuleCmd; import org.apache.cloudstack.api.command.user.network.CreateNetworkACLCmd; +<<<<<<< HEAD +import org.apache.cloudstack.api.command.user.vm.StartVMCmd; +import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; +======= import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; import org.apache.cloudstack.context.CallContext; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.commons.codec.binary.Base64; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -85,9 +95,13 @@ import com.cloud.network.vpc.NetworkACLItemDao; import com.cloud.network.vpc.NetworkACLItemVO; import com.cloud.network.vpc.NetworkACLService; +<<<<<<< HEAD +import com.cloud.offering.ServiceOffering; +======= import com.cloud.offering.NetworkOffering; import com.cloud.offering.ServiceOffering; import com.cloud.offerings.dao.NetworkOfferingDao; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.resource.ResourceManager; import com.cloud.storage.Volume; import com.cloud.storage.VolumeApiService; @@ -264,7 +278,13 @@ protected DeployDestination plan(final long nodesCount, final DataCenter zone, f logger.debug(String.format("Checking host : %s for capacity already reserved %d", h.getName(), reserved)); } if (capacityManager.checkIfHostHasCapacity(h.getId(), cpu_requested * reserved, ram_requested * reserved, false, cpuOvercommitRatio, memoryOvercommitRatio, true)) { +<<<<<<< HEAD + if (logger.isDebugEnabled()) { + logger.debug(String.format("Found host : %s for with enough capacity, CPU=%d RAM=%s", h.getName(), cpu_requested * reserved, toHumanReadableSize(ram_requested * reserved))); + } +======= logger.debug("Found host {} with enough capacity: CPU={} RAM={}", h.getName(), cpu_requested * reserved, toHumanReadableSize(ram_requested * reserved)); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 hostEntry.setValue(new Pair(h, reserved)); suitable_host_found = true; break; @@ -324,6 +344,20 @@ protected void resizeNodeVolume(final UserVm vm) throws ManagementServerExceptio } protected void startKubernetesVM(final UserVm vm) throws ManagementServerException { +<<<<<<< HEAD + try { + StartVMCmd startVm = new StartVMCmd(); + startVm = ComponentContext.inject(startVm); + Field f = startVm.getClass().getDeclaredField("id"); + f.setAccessible(true); + f.set(startVm, vm.getId()); + itMgr.advanceStart(vm.getUuid(), null, null); + if (logger.isInfoEnabled()) { + logger.info(String.format("Started VM : %s in the Kubernetes cluster : %s", vm.getDisplayName(), kubernetesCluster.getName())); + } + } catch (IllegalAccessException | NoSuchFieldException | OperationTimedoutException | ResourceUnavailableException | InsufficientCapacityException ex) { + throw new ManagementServerException(String.format("Failed to start VM in the Kubernetes cluster : %s", kubernetesCluster.getName()), ex); +======= CallContext vmContext = null; if (!ApiCommandResourceType.VirtualMachine.equals(CallContext.current().getEventResourceType())); { vmContext = CallContext.register(CallContext.current(), ApiCommandResourceType.VirtualMachine); @@ -337,6 +371,7 @@ protected void startKubernetesVM(final UserVm vm) throws ManagementServerExcepti if (vmContext != null) { CallContext.unregister(); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } UserVm startVm = userVmDao.findById(vm.getId()); @@ -349,6 +384,21 @@ protected List provisionKubernetesClusterNodeVms(final long nodeCount, f ResourceUnavailableException, InsufficientCapacityException { List nodes = new ArrayList<>(); for (int i = offset + 1; i <= nodeCount; i++) { +<<<<<<< HEAD + UserVm vm = createKubernetesNode(publicIpAddress); + addKubernetesClusterVm(kubernetesCluster.getId(), vm.getId(), false); + if (kubernetesCluster.getNodeRootDiskSize() > 0) { + resizeNodeVolume(vm); + } + startKubernetesVM(vm); + vm = userVmDao.findById(vm.getId()); + if (vm == null) { + throw new ManagementServerException(String.format("Failed to provision worker VM for Kubernetes cluster : %s" , kubernetesCluster.getName())); + } + nodes.add(vm); + if (logger.isInfoEnabled()) { + logger.info(String.format("Provisioned node VM : %s in to the Kubernetes cluster : %s", vm.getDisplayName(), kubernetesCluster.getName())); +======= CallContext vmContext = CallContext.register(CallContext.current(), ApiCommandResourceType.VirtualMachine); try { UserVm vm = createKubernetesNode(publicIpAddress); @@ -366,6 +416,7 @@ protected List provisionKubernetesClusterNodeVms(final long nodeCount, f logger.info("Provisioned node VM : {} in to the Kubernetes cluster : {}", vm.getDisplayName(), kubernetesCluster.getName()); } finally { CallContext.unregister(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } return nodes; @@ -636,7 +687,10 @@ protected void provisionLoadBalancerRule(final IpAddress publicIp, final Network protected void createFirewallRules(IpAddress publicIp, List clusterVMIds, boolean apiRule) throws ManagementServerException { // Firewall rule for SSH access on each node VM +<<<<<<< HEAD +======= CallContext.register(CallContext.current(), null); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 try { int endPort = CLUSTER_NODES_DEFAULT_START_SSH_PORT + clusterVMIds.size() - 1; provisionFirewallRules(publicIp, owner, CLUSTER_NODES_DEFAULT_START_SSH_PORT, endPort); @@ -645,14 +699,20 @@ protected void createFirewallRules(IpAddress publicIp, List clusterVMIds, } } catch (NoSuchFieldException | IllegalAccessException | ResourceUnavailableException | NetworkRuleConflictException e) { throw new ManagementServerException(String.format("Failed to provision firewall rules for SSH access for the Kubernetes cluster : %s", kubernetesCluster.getName()), e); +<<<<<<< HEAD +======= } finally { CallContext.unregister(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } if (!apiRule) { return; } // Firewall rule for API access for control node VMs +<<<<<<< HEAD +======= CallContext.register(CallContext.current(), null); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 try { provisionFirewallRules(publicIp, owner, CLUSTER_API_PORT, CLUSTER_API_PORT); if (logger.isInfoEnabled()) { @@ -661,8 +721,11 @@ protected void createFirewallRules(IpAddress publicIp, List clusterVMIds, } } catch (NoSuchFieldException | IllegalAccessException | ResourceUnavailableException | NetworkRuleConflictException e) { throw new ManagementServerException(String.format("Failed to provision firewall rules for API access for the Kubernetes cluster : %s", kubernetesCluster.getName()), e); +<<<<<<< HEAD +======= } finally { CallContext.unregister(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } @@ -703,7 +766,10 @@ protected void createVpcTierAclRules(Network network) throws ManagementServerExc return; } // ACL rule for API access for control node VMs +<<<<<<< HEAD +======= CallContext.register(CallContext.current(), null); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 try { provisionVpcTierAllowPortACLRule(network, CLUSTER_API_PORT, CLUSTER_API_PORT); if (logger.isInfoEnabled()) { @@ -712,10 +778,14 @@ protected void createVpcTierAclRules(Network network) throws ManagementServerExc } } catch (NoSuchFieldException | IllegalAccessException | ResourceUnavailableException | InvalidParameterValueException | PermissionDeniedException e) { throw new ManagementServerException(String.format("Failed to provision firewall rules for API access for the Kubernetes cluster : %s", kubernetesCluster.getName()), e); +<<<<<<< HEAD + } +======= } finally { CallContext.unregister(); } CallContext.register(CallContext.current(), null); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 try { provisionVpcTierAllowPortACLRule(network, DEFAULT_SSH_PORT, DEFAULT_SSH_PORT); if (logger.isInfoEnabled()) { @@ -724,8 +794,11 @@ protected void createVpcTierAclRules(Network network) throws ManagementServerExc } } catch (NoSuchFieldException | IllegalAccessException | ResourceUnavailableException | InvalidParameterValueException | PermissionDeniedException e) { throw new ManagementServerException(String.format("Failed to provision firewall rules for API access for the Kubernetes cluster : %s", kubernetesCluster.getName()), e); +<<<<<<< HEAD +======= } finally { CallContext.unregister(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java index f5ac553733d6..84429b4a70df 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterScaleWorker.java @@ -26,9 +26,13 @@ import javax.inject.Inject; +<<<<<<< HEAD +import org.apache.cloudstack.api.InternalIdentity; +======= import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.context.CallContext; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -320,9 +324,12 @@ private void removeNodesFromCluster(List vmMaps) throw if (!removeKubernetesClusterNode(publicIpAddress, sshPort, userVM, 3, 30000)) { logTransitStateAndThrow(Level.ERROR, String.format("Scaling failed for Kubernetes cluster : %s, failed to remove Kubernetes node: %s running on VM : %s", kubernetesCluster.getName(), userVM.getHostName(), userVM.getDisplayName()), kubernetesCluster.getId(), KubernetesCluster.Event.OperationFailed); } +<<<<<<< HEAD +======= CallContext vmContext = CallContext.register(CallContext.current(), ApiCommandResourceType.VirtualMachine); vmContext.setEventResourceId(userVM.getId()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 try { UserVm vm = userVmService.destroyVm(userVM.getId(), true); if (!userVmManager.expunge(userVM)) { @@ -332,8 +339,11 @@ private void removeNodesFromCluster(List vmMaps) throw } catch (ResourceUnavailableException e) { logTransitStateAndThrow(Level.ERROR, String.format("Scaling Kubernetes cluster %s failed, unable to remove VM ID: %s", kubernetesCluster.getName() , userVM.getDisplayName()), kubernetesCluster.getId(), KubernetesCluster.Event.OperationFailed, e); +<<<<<<< HEAD +======= } finally { CallContext.unregister(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } kubernetesClusterVmMapDao.expunge(vmMapVO.getId()); if (System.currentTimeMillis() > scaleTimeoutTime) { @@ -445,10 +455,17 @@ public boolean scaleCluster() throws CloudRuntimeException { if (existingServiceOffering == null) { logAndThrow(Level.ERROR, String.format("Scaling Kubernetes cluster : %s failed, service offering for the Kubernetes cluster not found!", kubernetesCluster.getName())); } +<<<<<<< HEAD + final boolean autscalingChanged = isAutoscalingChanged(); + final boolean serviceOfferingScalingNeeded = serviceOffering != null && serviceOffering.getId() != existingServiceOffering.getId(); + + if (autscalingChanged) { +======= final boolean autoscalingChanged = isAutoscalingChanged(); final boolean serviceOfferingScalingNeeded = serviceOffering != null && serviceOffering.getId() != existingServiceOffering.getId(); if (autoscalingChanged) { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 boolean autoScaled = autoscaleCluster(this.isAutoscalingEnabled, minSize, maxSize); if (autoScaled && serviceOfferingScalingNeeded) { scaleKubernetesClusterOffering(); diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java index b2fbbd31f6ba..391435811847 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStartWorker.java @@ -533,7 +533,11 @@ public boolean startKubernetesClusterOnCreate() { } attachIsoKubernetesVMs(clusterVMs); if (!KubernetesClusterUtil.isKubernetesClusterControlVmRunning(kubernetesCluster, publicIpAddress, publicIpSshPort.second(), startTimeoutTime)) { +<<<<<<< HEAD + String msg = String.format("Failed to setup Kubernetes cluster : %s in usable state as unable to access control node VMs of the cluster", kubernetesCluster.getName()); +======= String msg = String.format("Failed to setup Kubernetes cluster : %s is not in usable state as the system is unable to access control node VMs of the cluster", kubernetesCluster.getName()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (kubernetesCluster.getControlNodeCount() > 1 && Network.GuestType.Shared.equals(network.getGuestType())) { msg = String.format("%s. Make sure external load-balancer has port forwarding rules for SSH access on ports %d-%d and API access on port %d", msg, diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStopWorker.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStopWorker.java index 60802d12e729..432d35ab404f 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStopWorker.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/actionworkers/KubernetesClusterStopWorker.java @@ -20,8 +20,11 @@ import java.util.List; import org.apache.logging.log4j.Level; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.context.CallContext; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.exception.ConcurrentOperationException; import com.cloud.kubernetes.cluster.KubernetesCluster; @@ -46,15 +49,21 @@ public boolean stop() throws CloudRuntimeException { if (vm == null) { logTransitStateAndThrow(Level.ERROR, String.format("Failed to find all VMs in Kubernetes cluster : %s", kubernetesCluster.getName()), kubernetesCluster.getId(), KubernetesCluster.Event.OperationFailed); } +<<<<<<< HEAD +======= CallContext vmContext = CallContext.register(CallContext.current(), ApiCommandResourceType.VirtualMachine); vmContext.setEventResourceId(vm.getId()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 try { userVmService.stopVirtualMachine(vm.getId(), false); } catch (ConcurrentOperationException ex) { logger.warn(String.format("Failed to stop VM : %s in Kubernetes cluster : %s", vm.getDisplayName(), kubernetesCluster.getName()), ex); +<<<<<<< HEAD +======= } finally { CallContext.unregister(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } for (final UserVm userVm : clusterVMs) { diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/dao/KubernetesClusterVmMapDao.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/dao/KubernetesClusterVmMapDao.java index eaeccd09f801..5c986fc147b2 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/dao/KubernetesClusterVmMapDao.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/dao/KubernetesClusterVmMapDao.java @@ -30,6 +30,9 @@ public interface KubernetesClusterVmMapDao extends GenericDao vmIds); public int removeByClusterId(long clusterId); +<<<<<<< HEAD +======= KubernetesClusterVmMapVO findByVmId(long vmId); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/dao/KubernetesClusterVmMapDaoImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/dao/KubernetesClusterVmMapDaoImpl.java index 5e465848e1c1..7143d75999f0 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/dao/KubernetesClusterVmMapDaoImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/dao/KubernetesClusterVmMapDaoImpl.java @@ -81,6 +81,8 @@ public int removeByClusterId(long clusterId) { sc.setParameters("clusterId", clusterId); return remove(sc); } +<<<<<<< HEAD +======= @Override public KubernetesClusterVmMapVO findByVmId(long vmId) { @@ -91,4 +93,5 @@ public KubernetesClusterVmMapVO findByVmId(long vmId) { sc.setParameters("vmId", vmId); return findOneBy(sc); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterUtil.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterUtil.java index 7a3268014fdb..88cafb9f93cf 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterUtil.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/utils/KubernetesClusterUtil.java @@ -266,11 +266,21 @@ public static boolean isKubernetesClusterControlVmRunning(final KubernetesCluste socket.connect(new InetSocketAddress(ipAddress, port), 10000); controlVmRunning = true; } catch (IOException e) { +<<<<<<< HEAD + if (LOGGER.isInfoEnabled()) { + LOGGER.info(String.format("Waiting for Kubernetes cluster : %s control node VMs to be accessible", kubernetesCluster.getName())); + } + try { + Thread.sleep(10000); + } catch (InterruptedException ex) { + LOGGER.warn(String.format("Error while waiting for Kubernetes cluster : %s control node VMs to be accessible", kubernetesCluster.getName()), ex); +======= LOGGER.info("Waiting for Kubernetes cluster : {} control node VMs to be accessible", kubernetesCluster.getName()); try { Thread.sleep(10000); } catch (InterruptedException ex) { LOGGER.warn("Error while waiting for Kubernetes cluster : {} control node VMs to be accessible", kubernetesCluster.getName(), ex); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } } diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java index ba2b4288d480..667c4302b36d 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java +++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/version/KubernetesVersionManagerImpl.java @@ -22,7 +22,10 @@ import javax.inject.Inject; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.ApiCommandResourceType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.command.admin.kubernetes.version.AddKubernetesSupportedVersionCmd; import org.apache.cloudstack.api.command.admin.kubernetes.version.DeleteKubernetesSupportedVersionCmd; @@ -32,7 +35,10 @@ import org.apache.cloudstack.api.command.user.kubernetes.version.ListKubernetesSupportedVersionsCmd; import org.apache.cloudstack.api.response.KubernetesSupportedVersionResponse; import org.apache.cloudstack.api.response.ListResponse; +<<<<<<< HEAD +======= import org.apache.cloudstack.context.CallContext; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.commons.lang3.StringUtils; import com.cloud.api.query.dao.TemplateJoinDao; @@ -53,7 +59,10 @@ import com.cloud.template.TemplateApiService; import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.AccountManager; +<<<<<<< HEAD +======= import com.cloud.utils.Pair; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.utils.component.ComponentContext; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.Filter; @@ -82,6 +91,8 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne public static final String MINIMUN_AUTOSCALER_SUPPORTED_VERSION = "1.15.0"; +<<<<<<< HEAD +======= protected void updateTemplateDetailsInKubernetesSupportedVersionResponse( final KubernetesSupportedVersion kubernetesSupportedVersion, KubernetesSupportedVersionResponse response) { TemplateJoinVO template = templateJoinDao.findById(kubernetesSupportedVersion.getIsoId()); @@ -96,6 +107,7 @@ protected void updateTemplateDetailsInKubernetesSupportedVersionResponse( response.setDirectDownload(template.isDirectDownload()); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private KubernetesSupportedVersionResponse createKubernetesSupportedVersionResponse(final KubernetesSupportedVersion kubernetesSupportedVersion) { KubernetesSupportedVersionResponse response = new KubernetesSupportedVersionResponse(); response.setObjectName("kubernetessupportedversion"); @@ -115,19 +127,39 @@ private KubernetesSupportedVersionResponse createKubernetesSupportedVersionRespo response.setSupportsHA(compareSemanticVersions(kubernetesSupportedVersion.getSemanticVersion(), KubernetesClusterService.MIN_KUBERNETES_VERSION_HA_SUPPORT)>=0); response.setSupportsAutoscaling(versionSupportsAutoscaling(kubernetesSupportedVersion)); +<<<<<<< HEAD + TemplateJoinVO template = templateJoinDao.findById(kubernetesSupportedVersion.getIsoId()); + if (template != null) { + response.setIsoId(template.getUuid()); + response.setIsoName(template.getName()); + if (template.getState() != null) { + response.setIsoState(template.getState().toString()); + } + response.setDirectDownload(template.isDirectDownload()); + } +======= updateTemplateDetailsInKubernetesSupportedVersionResponse(kubernetesSupportedVersion, response); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 response.setCreated(kubernetesSupportedVersion.getCreated()); return response; } +<<<<<<< HEAD + private ListResponse createKubernetesSupportedVersionListResponse(List versions) { +======= private ListResponse createKubernetesSupportedVersionListResponse( List versions, Integer count) { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 List responseList = new ArrayList<>(); for (KubernetesSupportedVersionVO version : versions) { responseList.add(createKubernetesSupportedVersionResponse(version)); } ListResponse response = new ListResponse<>(); +<<<<<<< HEAD + response.setResponses(responseList); +======= response.setResponses(responseList, count); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return response; } @@ -161,7 +193,10 @@ private List filterKubernetesSupportedVersions(Li private VirtualMachineTemplate registerKubernetesVersionIso(final Long zoneId, final String versionName, final String isoUrl, final String isoChecksum, final boolean directDownload) throws IllegalAccessException, NoSuchFieldException, IllegalArgumentException, ResourceAllocationException { +<<<<<<< HEAD +======= CallContext.register(CallContext.current(), ApiCommandResourceType.Iso); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 String isoName = String.format("%s-Kubernetes-Binaries-ISO", versionName); RegisterIsoCmd registerIsoCmd = new RegisterIsoCmd(); registerIsoCmd = ComponentContext.inject(registerIsoCmd); @@ -179,15 +214,25 @@ private VirtualMachineTemplate registerKubernetesVersionIso(final Long zoneId, f registerIsoCmd.setDirectDownload(directDownload); registerIsoCmd.setAccountName(accountManager.getSystemAccount().getAccountName()); registerIsoCmd.setDomainId(accountManager.getSystemAccount().getDomainId()); +<<<<<<< HEAD + return templateService.registerIso(registerIsoCmd); +======= try { return templateService.registerIso(registerIsoCmd); } finally { CallContext.unregister(); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } private void deleteKubernetesVersionIso(long templateId) throws IllegalAccessException, NoSuchFieldException, IllegalArgumentException { +<<<<<<< HEAD + DeleteIsoCmd deleteIsoCmd = new DeleteIsoCmd(); + deleteIsoCmd = ComponentContext.inject(deleteIsoCmd); + deleteIsoCmd.setId(templateId); + templateService.deleteIso(deleteIsoCmd); +======= CallContext isoContext = CallContext.register(CallContext.current(), ApiCommandResourceType.Iso); isoContext.setEventResourceId(templateId); DeleteIsoCmd deleteIsoCmd = new DeleteIsoCmd(); @@ -198,6 +243,7 @@ private void deleteKubernetesVersionIso(long templateId) throws IllegalAccessExc } finally { CallContext.unregister(); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } public static int compareSemanticVersions(String v1, String v2) throws IllegalArgumentException { @@ -293,6 +339,16 @@ public ListResponse listKubernetesSupportedV if(keyword != null){ sc.setParameters("keyword", "%" + keyword + "%"); } +<<<<<<< HEAD + List versions = kubernetesSupportedVersionDao.search(sc, searchFilter); + versions = filterKubernetesSupportedVersions(versions, minimumSemanticVersion); + + return createKubernetesSupportedVersionListResponse(versions); + } + + @Override + @ActionEvent(eventType = KubernetesVersionEventTypes.EVENT_KUBERNETES_VERSION_ADD, eventDescription = "Adding Kubernetes supported version") +======= Pair, Integer> versionsAndCount = kubernetesSupportedVersionDao.searchAndCount(sc, searchFilter); List versions = @@ -304,6 +360,7 @@ public ListResponse listKubernetesSupportedV @Override @ActionEvent(eventType = KubernetesVersionEventTypes.EVENT_KUBERNETES_VERSION_ADD, eventDescription = "Adding Kubernetes supported version") +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public KubernetesSupportedVersionResponse addKubernetesSupportedVersion(final AddKubernetesSupportedVersionCmd cmd) { if (!KubernetesClusterService.KubernetesServiceEnabled.value()) { throw new CloudRuntimeException("Kubernetes Service plugin is disabled"); @@ -355,14 +412,21 @@ public KubernetesSupportedVersionResponse addKubernetesSupportedVersion(final Ad KubernetesSupportedVersionVO supportedVersionVO = new KubernetesSupportedVersionVO(name, semanticVersion, template.getId(), zoneId, minimumCpu, minimumRamSize); supportedVersionVO = kubernetesSupportedVersionDao.persist(supportedVersionVO); +<<<<<<< HEAD +======= CallContext.current().putContextParameter(KubernetesSupportedVersion.class, supportedVersionVO.getUuid()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return createKubernetesSupportedVersionResponse(supportedVersionVO); } @Override +<<<<<<< HEAD + @ActionEvent(eventType = KubernetesVersionEventTypes.EVENT_KUBERNETES_VERSION_DELETE, eventDescription = "Deleting Kubernetes supported version", async = true) +======= @ActionEvent(eventType = KubernetesVersionEventTypes.EVENT_KUBERNETES_VERSION_DELETE, eventDescription = "deleting Kubernetes supported version", async = true) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public boolean deleteKubernetesSupportedVersion(final DeleteKubernetesSupportedVersionCmd cmd) { if (!KubernetesClusterService.KubernetesServiceEnabled.value()) { throw new CloudRuntimeException("Kubernetes Service plugin is disabled"); @@ -393,8 +457,12 @@ public boolean deleteKubernetesSupportedVersion(final DeleteKubernetesSupportedV } @Override +<<<<<<< HEAD + @ActionEvent(eventType = KubernetesVersionEventTypes.EVENT_KUBERNETES_VERSION_UPDATE, eventDescription = "Updating Kubernetes supported version") +======= @ActionEvent(eventType = KubernetesVersionEventTypes.EVENT_KUBERNETES_VERSION_UPDATE, eventDescription = "Updating Kubernetes supported version") +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public KubernetesSupportedVersionResponse updateKubernetesSupportedVersion(final UpdateKubernetesSupportedVersionCmd cmd) { if (!KubernetesClusterService.KubernetesServiceEnabled.value()) { throw new CloudRuntimeException("Kubernetes Service plugin is disabled"); diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/admin/kubernetes/version/AddKubernetesSupportedVersionCmd.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/admin/kubernetes/version/AddKubernetesSupportedVersionCmd.java index 139b79a182a1..c986d4be2715 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/admin/kubernetes/version/AddKubernetesSupportedVersionCmd.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/admin/kubernetes/version/AddKubernetesSupportedVersionCmd.java @@ -21,7 +21,10 @@ import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.ApiCommandResourceType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; @@ -135,11 +138,14 @@ public long getEntityOwnerId() { return CallContext.current().getCallingAccountId(); } +<<<<<<< HEAD +======= @Override public ApiCommandResourceType getApiResourceType() { return ApiCommandResourceType.KubernetesSupportedVersion; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/admin/kubernetes/version/DeleteKubernetesSupportedVersionCmd.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/admin/kubernetes/version/DeleteKubernetesSupportedVersionCmd.java index a7799a33f188..676295e623fc 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/admin/kubernetes/version/DeleteKubernetesSupportedVersionCmd.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/admin/kubernetes/version/DeleteKubernetesSupportedVersionCmd.java @@ -21,7 +21,10 @@ import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.ApiCommandResourceType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -86,11 +89,14 @@ public String getEventDescription() { return description; } +<<<<<<< HEAD +======= @Override public ApiCommandResourceType getApiResourceType() { return ApiCommandResourceType.KubernetesSupportedVersion; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/admin/kubernetes/version/UpdateKubernetesSupportedVersionCmd.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/admin/kubernetes/version/UpdateKubernetesSupportedVersionCmd.java index 990b6a936b70..306602e0e685 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/admin/kubernetes/version/UpdateKubernetesSupportedVersionCmd.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/admin/kubernetes/version/UpdateKubernetesSupportedVersionCmd.java @@ -21,7 +21,10 @@ import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.ApiCommandResourceType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; @@ -30,7 +33,10 @@ import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.admin.AdminCmd; import org.apache.cloudstack.api.response.KubernetesSupportedVersionResponse; +<<<<<<< HEAD +======= import org.apache.cloudstack.context.CallContext; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.exception.ConcurrentOperationException; import com.cloud.kubernetes.version.KubernetesSupportedVersion; @@ -75,6 +81,9 @@ public String getState() { @Override public long getEntityOwnerId() { +<<<<<<< HEAD + return 0; +======= return CallContext.current().getCallingAccountId(); } @@ -86,6 +95,7 @@ public ApiCommandResourceType getApiResourceType() { @Override public Long getApiResourceId() { return getId(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } ///////////////////////////////////////////////////// diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java index 56d7b0c5838e..0837cbc875cf 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/CreateKubernetesClusterCmd.java @@ -272,23 +272,42 @@ public String getCreateEventType() { @Override public String getCreateEventDescription() { +<<<<<<< HEAD + return "creating Kubernetes cluster"; +======= return "Creating Kubernetes cluster"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } @Override public String getEventDescription() { +<<<<<<< HEAD + return "Creating Kubernetes cluster. Cluster Id: " + getEntityId(); +======= return "Creating Kubernetes cluster Id: " + getEntityId(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } @Override public ApiCommandResourceType getApiResourceType() { +<<<<<<< HEAD + return ApiCommandResourceType.VirtualMachine; +======= return ApiCommandResourceType.KubernetesCluster; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } @Override public void execute() { try { +<<<<<<< HEAD + if (KubernetesCluster.ClusterType.valueOf(getClusterType()) == KubernetesCluster.ClusterType.CloudManaged + && !kubernetesClusterService.startKubernetesCluster(getEntityId(), true)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to start Kubernetes cluster"); + } +======= kubernetesClusterService.startKubernetesCluster(this); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 KubernetesClusterResponse response = kubernetesClusterService.createKubernetesClusterResponse(getEntityId()); response.setResponseName(getCommandName()); setResponseObject(response); diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/DeleteKubernetesClusterCmd.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/DeleteKubernetesClusterCmd.java index 2ce8151c0631..78102ef0621f 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/DeleteKubernetesClusterCmd.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/DeleteKubernetesClusterCmd.java @@ -20,7 +20,10 @@ import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.ApiCommandResourceType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -114,6 +117,8 @@ public String getEventType() { } @Override +<<<<<<< HEAD +======= public ApiCommandResourceType getApiResourceType() { return ApiCommandResourceType.KubernetesCluster; } @@ -124,6 +129,7 @@ public Long getApiResourceId() { } @Override +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public String getEventDescription() { String description = "Deleting Kubernetes cluster"; KubernetesCluster cluster = _entityMgr.findById(KubernetesCluster.class, getId()); diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/RemoveVirtualMachinesFromKubernetesClusterCmd.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/RemoveVirtualMachinesFromKubernetesClusterCmd.java index 5c87f01862f3..ae9c55c5eab2 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/RemoveVirtualMachinesFromKubernetesClusterCmd.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/RemoveVirtualMachinesFromKubernetesClusterCmd.java @@ -20,7 +20,10 @@ import com.cloud.utils.exception.CloudRuntimeException; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.ApiCommandResourceType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; @@ -85,11 +88,14 @@ public long getEntityOwnerId() { } @Override +<<<<<<< HEAD +======= public ApiCommandResourceType getApiResourceType() { return ApiCommandResourceType.KubernetesCluster; } @Override +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public void execute() throws ServerApiException { try { List responseList = kubernetesClusterService.removeVmsFromCluster(this); diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/ScaleKubernetesClusterCmd.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/ScaleKubernetesClusterCmd.java index ee3566564e41..3afbde802c00 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/ScaleKubernetesClusterCmd.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/ScaleKubernetesClusterCmd.java @@ -24,7 +24,10 @@ import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.ApiCommandResourceType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -145,11 +148,14 @@ public long getEntityOwnerId() { return CallContext.current().getCallingAccount().getId(); } +<<<<<<< HEAD +======= @Override public ApiCommandResourceType getApiResourceType() { return ApiCommandResourceType.KubernetesCluster; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/StartKubernetesClusterCmd.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/StartKubernetesClusterCmd.java index bfe00ca27b28..1cbeaecc58ef 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/StartKubernetesClusterCmd.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/StartKubernetesClusterCmd.java @@ -20,7 +20,10 @@ import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.ApiCommandResourceType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -86,20 +89,49 @@ public long getEntityOwnerId() { return CallContext.current().getCallingAccount().getId(); } +<<<<<<< HEAD +======= @Override public ApiCommandResourceType getApiResourceType() { return ApiCommandResourceType.KubernetesCluster; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// +<<<<<<< HEAD + public KubernetesCluster validateRequest() { + if (getId() == null || getId() < 1L) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Invalid Kubernetes cluster ID provided"); + } + final KubernetesCluster kubernetesCluster = kubernetesClusterService.findById(getId()); + if (kubernetesCluster == null) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Given Kubernetes cluster was not found"); + } + if (!kubernetesClusterService.isCommandSupported(kubernetesCluster, getActualCommandName())) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, + String.format("Start kubernetes cluster is not supported for an externally managed cluster (%s)", kubernetesCluster.getName())); + } + return kubernetesCluster; + } + + @Override + public void execute() throws ServerApiException, ConcurrentOperationException { + final KubernetesCluster kubernetesCluster = validateRequest(); + try { + if (!kubernetesClusterService.startKubernetesCluster(kubernetesCluster.getId(), false)) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Failed to start Kubernetes cluster ID: %d", getId())); + } + final KubernetesClusterResponse response = kubernetesClusterService.createKubernetesClusterResponse(kubernetesCluster.getId()); +======= @Override public void execute() throws ServerApiException, ConcurrentOperationException { try { kubernetesClusterService.startKubernetesCluster(this); final KubernetesClusterResponse response = kubernetesClusterService.createKubernetesClusterResponse(getId()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 response.setResponseName(getCommandName()); setResponseObject(response); } catch (CloudRuntimeException ex) { diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/StopKubernetesClusterCmd.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/StopKubernetesClusterCmd.java index 23d6878cf729..bc4b7f88552e 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/StopKubernetesClusterCmd.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/StopKubernetesClusterCmd.java @@ -20,7 +20,10 @@ import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.ApiCommandResourceType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -87,11 +90,14 @@ public long getEntityOwnerId() { return CallContext.current().getCallingAccount().getId(); } +<<<<<<< HEAD +======= @Override public ApiCommandResourceType getApiResourceType() { return ApiCommandResourceType.KubernetesCluster; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/UpgradeKubernetesClusterCmd.java b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/UpgradeKubernetesClusterCmd.java index a3f2e0576459..e05cfcce660d 100644 --- a/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/UpgradeKubernetesClusterCmd.java +++ b/plugins/integrations/kubernetes-service/src/main/java/org/apache/cloudstack/api/command/user/kubernetes/cluster/UpgradeKubernetesClusterCmd.java @@ -21,7 +21,10 @@ import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; +<<<<<<< HEAD +======= import org.apache.cloudstack.api.ApiCommandResourceType; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -97,11 +100,14 @@ public long getEntityOwnerId() { return CallContext.current().getCallingAccount().getId(); } +<<<<<<< HEAD +======= @Override public ApiCommandResourceType getApiResourceType() { return ApiCommandResourceType.KubernetesCluster; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/plugins/integrations/kubernetes-service/src/main/resources/META-INF/cloudstack/kubernetes-service/spring-kubernetes-service-context.xml b/plugins/integrations/kubernetes-service/src/main/resources/META-INF/cloudstack/kubernetes-service/spring-kubernetes-service-context.xml index 9d236eed26cd..177484bfb77e 100644 --- a/plugins/integrations/kubernetes-service/src/main/resources/META-INF/cloudstack/kubernetes-service/spring-kubernetes-service-context.xml +++ b/plugins/integrations/kubernetes-service/src/main/resources/META-INF/cloudstack/kubernetes-service/spring-kubernetes-service-context.xml @@ -34,8 +34,13 @@ +<<<<<<< HEAD + + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 diff --git a/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionServiceTest.java b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionServiceTest.java index f7e816596c26..77cecf89e185 100644 --- a/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionServiceTest.java +++ b/plugins/integrations/kubernetes-service/src/test/java/com/cloud/kubernetes/version/KubernetesVersionServiceTest.java @@ -35,7 +35,10 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; import org.apache.cloudstack.framework.config.ConfigKey; +<<<<<<< HEAD +======= import org.apache.commons.collections.CollectionUtils; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -67,7 +70,10 @@ import com.cloud.user.AccountVO; import com.cloud.user.User; import com.cloud.user.UserVO; +<<<<<<< HEAD +======= import com.cloud.utils.Pair; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.utils.component.ComponentContext; import com.cloud.utils.db.Filter; import com.cloud.utils.db.SearchBuilder; @@ -144,6 +150,16 @@ public void listKubernetesSupportedVersionsTest() { when(versionVO.getSemanticVersion()).thenReturn(KubernetesVersionService.MIN_KUBERNETES_VERSION); versionVOs.add(versionVO); when(kubernetesSupportedVersionDao.findById(Mockito.anyLong())).thenReturn(versionVO); +<<<<<<< HEAD + when(kubernetesSupportedVersionDao.search(Mockito.any(SearchCriteria.class), Mockito.any(Filter.class))).thenReturn(versionVOs); + ListResponse response = + kubernetesVersionService.listKubernetesSupportedVersions( + cmd); + Assert.assertNotNull(response); + Assert.assertEquals(Integer.valueOf(1), response.getCount()); + Assert.assertEquals(1, response.getResponses().size()); + Assert.assertEquals(KubernetesVersionService.MIN_KUBERNETES_VERSION, response.getResponses().get(0).getSemanticVersion()); +======= when(kubernetesSupportedVersionDao.searchAndCount(Mockito.any(SearchCriteria.class), Mockito.any(Filter.class))).thenReturn(new Pair<>(versionVOs, versionVOs.size())); ListResponse versionsResponse = @@ -151,6 +167,7 @@ public void listKubernetesSupportedVersionsTest() { Assert.assertEquals(versionVOs.size(), versionsResponse.getCount().intValue()); Assert.assertTrue(CollectionUtils.isNotEmpty(versionsResponse.getResponses())); Assert.assertEquals(versionVOs.size(), versionsResponse.getResponses().size()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } @Test(expected = InvalidParameterValueException.class) @@ -215,12 +232,18 @@ public void addKubernetesSupportedVersionIsoUrlTest() throws ResourceAllocationE when(cmd.getMinimumRamSize()).thenReturn(KubernetesClusterService.MIN_KUBERNETES_CLUSTER_NODE_RAM_SIZE); Account systemAccount = new AccountVO("system", 1L, "", Account.Type.ADMIN, "uuid"); when(accountManager.getSystemAccount()).thenReturn(systemAccount); +<<<<<<< HEAD + try (MockedStatic mockedComponentContext = Mockito.mockStatic(ComponentContext.class)) { + mockedComponentContext.when(() -> ComponentContext.inject(Mockito.any(RegisterIsoCmd.class))).thenReturn( + new RegisterIsoCmd()); +======= CallContext callContext = Mockito.mock(CallContext.class); try (MockedStatic mockedComponentContext = Mockito.mockStatic(ComponentContext.class); MockedStatic mockedCallContext = Mockito.mockStatic(CallContext.class)) { mockedComponentContext.when(() -> ComponentContext.inject(Mockito.any(RegisterIsoCmd.class))).thenReturn( new RegisterIsoCmd()); mockedCallContext.when(CallContext::current).thenReturn(callContext); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 when(templateService.registerIso(Mockito.any(RegisterIsoCmd.class))).thenReturn( Mockito.mock(VirtualMachineTemplate.class)); diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVMsMetricsCmd.java b/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVMsMetricsCmd.java index f5b2ee5bda78..9fb4b32b39a8 100644 --- a/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVMsMetricsCmd.java +++ b/plugins/metrics/src/main/java/org/apache/cloudstack/api/ListVMsMetricsCmd.java @@ -17,12 +17,18 @@ package org.apache.cloudstack.api; +<<<<<<< HEAD +======= import java.util.EnumSet; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import java.util.List; import javax.inject.Inject; +<<<<<<< HEAD +======= import com.cloud.exception.InvalidParameterValueException; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.command.user.UserCmd; import org.apache.cloudstack.api.command.user.vm.ListVMsCmd; @@ -44,21 +50,34 @@ * although most of it is not suitable/useful for the API purpose. * */ +<<<<<<< HEAD +@APICommand(name = ListVMsMetricsCmd.APINAME, description = "Lists VM metrics", responseObject = VmMetricsResponse.class, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, responseView = ResponseObject.ResponseView.Restricted, + since = "4.9.3", authorized = {RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) +public class ListVMsMetricsCmd extends ListVMsCmd implements UserCmd { + public static final String APINAME = "listVirtualMachinesMetrics"; +======= @APICommand(name = "listVirtualMachinesMetrics", description = "Lists VM metrics", responseObject = VmMetricsResponse.class, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, responseView = ResponseObject.ResponseView.Restricted, since = "4.9.3", authorized = {RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User}) public class ListVMsMetricsCmd extends ListVMsCmd implements UserCmd { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Inject private MetricsService metricsService; @Override +<<<<<<< HEAD + public String getCommandName() { + return APINAME.toLowerCase() + BaseCmd.RESPONSE_SUFFIX; +======= public EnumSet getDetails() throws InvalidParameterValueException { if (isViewDetailsEmpty()) { return EnumSet.of(ApiConstants.VMDetails.all); } return super.getDetails(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } @Override diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java index 6025a41d69cb..6fae2479fe8e 100644 --- a/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java +++ b/plugins/metrics/src/main/java/org/apache/cloudstack/metrics/MetricsServiceImpl.java @@ -617,6 +617,10 @@ public List listVmMetrics(List vmResponses) { } metricsResponse.setHasAnnotation(vmResponse.hasAnnotation()); +<<<<<<< HEAD + metricsResponse.setIpAddress(vmResponse.getNics()); +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 metricsResponse.setCpuTotal(vmResponse.getCpuNumber(), vmResponse.getCpuSpeed()); metricsResponse.setMemTotal(vmResponse.getMemory()); metricsResponse.setNetworkRead(vmResponse.getNetworkKbsRead()); diff --git a/plugins/metrics/src/main/java/org/apache/cloudstack/response/VmMetricsResponse.java b/plugins/metrics/src/main/java/org/apache/cloudstack/response/VmMetricsResponse.java index 7e5db7939db9..60cfd614210d 100644 --- a/plugins/metrics/src/main/java/org/apache/cloudstack/response/VmMetricsResponse.java +++ b/plugins/metrics/src/main/java/org/apache/cloudstack/response/VmMetricsResponse.java @@ -17,13 +17,26 @@ package org.apache.cloudstack.response; +<<<<<<< HEAD +import java.util.Set; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.response.NicResponse; +======= import org.apache.cloudstack.api.ApiConstants; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.api.response.UserVmResponse; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; public class VmMetricsResponse extends UserVmResponse { +<<<<<<< HEAD + @SerializedName(ApiConstants.IP_ADDRESS) + @Param(description = "the VM's primary IP address") + private String ipAddress; +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @SerializedName("cputotal") @Param(description = "the total cpu capacity in Ghz") @@ -53,6 +66,14 @@ public class VmMetricsResponse extends UserVmResponse { @Param(description = "the total disk iops") private Long diskIopsTotal; +<<<<<<< HEAD + public void setIpAddress(final Set nics) { + if (nics != null && nics.size() > 0) { + this.ipAddress = nics.iterator().next().getIpaddress(); + } + } +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public void setCpuTotal(final Integer cpuNumber, final Integer cpuSpeed) { if (cpuNumber != null && cpuSpeed != null) { diff --git a/plugins/metrics/src/test/java/org/apache/cloudstack/response/HostMetricsResponseTest.java b/plugins/metrics/src/test/java/org/apache/cloudstack/response/HostMetricsResponseTest.java index d81d6f6dadbf..3221df445e67 100644 --- a/plugins/metrics/src/test/java/org/apache/cloudstack/response/HostMetricsResponseTest.java +++ b/plugins/metrics/src/test/java/org/apache/cloudstack/response/HostMetricsResponseTest.java @@ -56,6 +56,8 @@ public void testSetCpuAllocatedWithValidCpu() { Assert.assertEquals(expected, hostResponse.getCpuAllocatedGhz()); } +<<<<<<< HEAD +======= @Test public void testSetCpuAllocatedWithNullCpu() { String expected = null; @@ -79,4 +81,5 @@ public void testSetCpuAllocatedWithNullCpuSpeed() { hostResponse.setCpuAllocated(String.format("50%s25%%", decimalSeparator), 10, null); Assert.assertEquals(expected, hostResponse.getCpuAllocatedGhz()); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/plugins/network-elements/juniper-contrail/src/main/java/org/apache/cloudstack/network/contrail/management/EventUtils.java b/plugins/network-elements/juniper-contrail/src/main/java/org/apache/cloudstack/network/contrail/management/EventUtils.java index d47bf6eceeb0..19ec52bb6fa4 100644 --- a/plugins/network-elements/juniper-contrail/src/main/java/org/apache/cloudstack/network/contrail/management/EventUtils.java +++ b/plugins/network-elements/juniper-contrail/src/main/java/org/apache/cloudstack/network/contrail/management/EventUtils.java @@ -18,6 +18,23 @@ package org.apache.cloudstack.network.contrail.management; import java.lang.reflect.Method; +<<<<<<< HEAD +import java.util.HashMap; +import java.util.Map; +import java.util.ArrayList; +import java.util.List; + +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.stereotype.Component; + +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.framework.events.EventBus; +import org.apache.cloudstack.framework.events.EventBusException; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +======= import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -31,6 +48,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.stereotype.Component; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.event.ActionEvent; import com.cloud.event.ActionEvents; @@ -41,20 +59,30 @@ import com.cloud.utils.component.ComponentContext; import com.cloud.utils.component.ComponentMethodInterceptor; +<<<<<<< HEAD +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Component public class EventUtils { protected static Logger LOGGER = LogManager.getLogger(EventUtils.class); +<<<<<<< HEAD + protected static EventBus s_eventBus = null; +======= private static EventDistributor eventDistributor; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public EventUtils() { } +<<<<<<< HEAD +======= public static void setEventDistributor(EventDistributor eventDistributorImpl) { eventDistributor = eventDistributorImpl; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private static void publishOnMessageBus(String eventCategory, String eventType, String details, Event.State state) { if (state != com.cloud.event.Event.State.Completed) { @@ -62,7 +90,11 @@ private static void publishOnMessageBus(String eventCategory, String eventType, } try { +<<<<<<< HEAD + s_eventBus = ComponentContext.getComponent(EventBus.class); +======= setEventDistributor(ComponentContext.getComponent(EventDistributor.class)); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } catch (NoSuchBeanDefinitionException nbe) { return; // no provider is configured to provide events bus, so just return } @@ -70,12 +102,26 @@ private static void publishOnMessageBus(String eventCategory, String eventType, org.apache.cloudstack.framework.events.Event event = new org.apache.cloudstack.framework.events.Event(ManagementService.Name, eventCategory, eventType, EventTypes.getEntityForEvent(eventType), null); +<<<<<<< HEAD + Map eventDescription = new HashMap(); +======= Map eventDescription = new HashMap<>(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 eventDescription.put("event", eventType); eventDescription.put("status", state.toString()); eventDescription.put("details", details); event.setDescription(eventDescription); +<<<<<<< HEAD + try { + s_eventBus.publish(event); + } catch (EventBusException evx) { + String errMsg = "Failed to publish contrail event."; + LOGGER.warn(errMsg, evx); + } + +======= eventDistributor.publish(event); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } public static class EventInterceptor implements ComponentMethodInterceptor, MethodInterceptor { @@ -116,7 +162,11 @@ public Object invoke(MethodInvocation invocation) throws Throwable { } protected List getActionEvents(Method m) { +<<<<<<< HEAD + List result = new ArrayList(); +======= List result = new ArrayList<>(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ActionEvents events = m.getAnnotation(ActionEvents.class); diff --git a/plugins/pom.xml b/plugins/pom.xml index 279067e2c97f..e5b03869ea19 100755 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -79,7 +79,10 @@ event-bus/inmemory event-bus/kafka event-bus/rabbitmq +<<<<<<< HEAD +======= event-bus/webhook +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ha-planners/skip-heurestics 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 97b813669a6b..556c6b8791a9 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 @@ -135,12 +135,33 @@ public KVMPhysicalDisk getPhysicalDisk(String name, KVMStoragePool pool) List volumeDefs = api.volumeDefinitionList(rscName, null, null); final long size = volumeDefs.isEmpty() ? 0 : volumeDefs.get(0).getSizeKib() * 1024; +<<<<<<< HEAD + List resources = api.viewResources( + Collections.emptyList(), + Collections.singletonList(rscName), + Collections.emptyList(), + null, + null, + null); + if (!resources.isEmpty() && !resources.get(0).getVolumes().isEmpty()) { + final String devPath = resources.get(0).getVolumes().get(0).getDevicePath(); + final KVMPhysicalDisk kvmDisk = new KVMPhysicalDisk(devPath, name, pool); + kvmDisk.setFormat(QemuImg.PhysicalDiskFormat.RAW); + kvmDisk.setSize(size); + kvmDisk.setVirtualSize(size); + return kvmDisk; + } else { + logger.error("Linstor: viewResources didn't return resources or volumes for " + rscName); + throw new CloudRuntimeException("Linstor: viewResources didn't return resources or volumes."); + } +======= final String devicePath = LinstorUtil.getDevicePath(api, rscName); final KVMPhysicalDisk kvmDisk = new KVMPhysicalDisk(devicePath, name, pool); kvmDisk.setFormat(QemuImg.PhysicalDiskFormat.RAW); kvmDisk.setSize(size); kvmDisk.setVirtualSize(size); return kvmDisk; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } catch (ApiException apiEx) { logger.error(apiEx); throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx); 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 3d09fce8bab4..1f8966f9a039 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 @@ -29,6 +29,10 @@ import com.linbit.linstor.api.model.ResourceDefinitionModify; import com.linbit.linstor.api.model.ResourceGroupSpawn; import com.linbit.linstor.api.model.ResourceMakeAvailable; +<<<<<<< HEAD +import com.linbit.linstor.api.model.ResourceWithVolumes; +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.linbit.linstor.api.model.Snapshot; import com.linbit.linstor.api.model.SnapshotRestore; import com.linbit.linstor.api.model.VolumeDefinition; @@ -100,7 +104,10 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.datastore.util.LinstorConfigurationManager; import org.apache.cloudstack.storage.datastore.util.LinstorUtil; +<<<<<<< HEAD +======= import org.apache.cloudstack.storage.snapshot.SnapshotObject; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.storage.to.SnapshotObjectTO; import org.apache.cloudstack.storage.to.VolumeObjectTO; import org.apache.cloudstack.storage.volume.VolumeObject; @@ -232,7 +239,11 @@ private void deleteSnapshot(@Nonnull DataStore dataStore, @Nonnull String rscDef try { +<<<<<<< HEAD + ApiCallRcList answers = linstorApi.resourceSnapshotDelete(rscDefName, snapshotName); +======= ApiCallRcList answers = linstorApi.resourceSnapshotDelete(rscDefName, snapshotName, Collections.emptyList()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (answers.hasError()) { for (ApiCallRc answer : answers) @@ -343,6 +354,28 @@ private String checkLinstorAnswers(@Nonnull ApiCallRcList answers) { return answers.stream().filter(ApiCallRc::isError).findFirst().map(ApiCallRc::getMessage).orElse(null); } +<<<<<<< HEAD + private String getDeviceName(DevelopersApi linstorApi, String rscName) throws ApiException { + List resources = linstorApi.viewResources( + Collections.emptyList(), + Collections.singletonList(rscName), + Collections.emptyList(), + null, + null, + null); + if (!resources.isEmpty() && !resources.get(0).getVolumes().isEmpty()) + { + logger.info("Linstor: Created drbd device: " + resources.get(0).getVolumes().get(0).getDevicePath()); + return resources.get(0).getVolumes().get(0).getDevicePath(); + } else + { + logger.error("Linstor: viewResources didn't return resources or volumes."); + throw new CloudRuntimeException("Linstor: viewResources didn't return resources or volumes."); + } + } + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private void applyQoSSettings(StoragePoolVO storagePool, DevelopersApi api, String rscName, Long maxIops) throws ApiException { @@ -428,7 +461,11 @@ private String createResourceBase( applyAuxProps(api, rscName, volName, vmName); +<<<<<<< HEAD + return getDeviceName(api, rscName); +======= return LinstorUtil.getDevicePath(api, rscName); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } catch (ApiException apiEx) { logger.error("Linstor: ApiEx - " + apiEx.getMessage()); @@ -448,7 +485,11 @@ private String createResource(VolumeInfo vol, StoragePoolVO storagePoolVO) { { applyQoSSettings(storagePoolVO, linstorApi, rscName, vol.getMaxIops()); +<<<<<<< HEAD + return deviceName; +======= return LinstorUtil.getDevicePath(linstorApi, rscName); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } catch (ApiException apiEx) { logger.error("Linstor: ApiEx - " + apiEx.getMessage()); @@ -500,7 +541,11 @@ private String cloneResource(long csCloneId, VolumeInfo volumeInfo, StoragePoolV applyAuxProps(linstorApi, rscName, volumeInfo.getName(), volumeInfo.getAttachedVmName()); applyQoSSettings(storagePoolVO, linstorApi, rscName, volumeInfo.getMaxIops()); +<<<<<<< HEAD + return getDeviceName(linstorApi, rscName); +======= return LinstorUtil.getDevicePath(linstorApi, rscName); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } catch (ApiException apiEx) { logger.error("Linstor: ApiEx - " + apiEx.getMessage()); throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx); @@ -552,7 +597,11 @@ private String createResourceFromSnapshot(long csSnapshotId, String rscName, Sto applyAuxProps(linstorApi, rscName, volumeVO.getName(), null); applyQoSSettings(storagePoolVO, linstorApi, rscName, volumeVO.getMaxIops()); +<<<<<<< HEAD + return getDeviceName(linstorApi, rscName); +======= return LinstorUtil.getDevicePath(linstorApi, rscName); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } catch (ApiException apiEx) { logger.error("Linstor: ApiEx - " + apiEx.getMessage()); throw new CloudRuntimeException(apiEx.getBestMessage(), apiEx); @@ -921,7 +970,11 @@ private String restoreResourceFromSnapshot( api.resourceSnapshotRestore(rscName, snapshotName, sr); +<<<<<<< HEAD + return getDeviceName(api, restoredName); +======= return LinstorUtil.getDevicePath(api, restoredName); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } private Answer copyTemplate(DataObject srcData, DataObject dstData) { @@ -1005,13 +1058,24 @@ private Answer copyVolume(DataObject srcData, DataObject dstData) { * @param api Linstor Developer api object * @param pool StoragePool this resource resides on * @param rscName rscName of the snapshotted resource +<<<<<<< HEAD + * @param snapshotInfo snapshot info of the snapshot +======= * @param snapshotName Name of the snapshot to copy from * @param snapshotObject snapshot object of the origCmd, so the path can be modified +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 * @param origCmd original LinstorBackupSnapshotCommand that needs to have a patched path * @return answer from agent operation * @throws ApiException if any Linstor api operation fails */ private Answer copyFromTemporaryResource( +<<<<<<< HEAD + DevelopersApi api, StoragePoolVO pool, String rscName, SnapshotInfo snapshotInfo, CopyCommand origCmd) + throws ApiException { + Answer answer; + String restoreName = rscName + "-rst"; + String snapshotName = LinstorUtil.RSC_PREFIX + snapshotInfo.getUuid(); +======= DevelopersApi api, StoragePoolVO pool, String rscName, @@ -1021,13 +1085,20 @@ private Answer copyFromTemporaryResource( throws ApiException { Answer answer; String restoreName = rscName + "-rst"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 String devName = restoreResourceFromSnapshot(api, pool, rscName, snapshotName, restoreName); Optional optEPAny = getLinstorEP(api, restoreName); if (optEPAny.isPresent()) { // patch the src device path to the temporary linstor resource +<<<<<<< HEAD + SnapshotObjectTO soTO = (SnapshotObjectTO)snapshotInfo.getTO(); + soTO.setPath(devName); + origCmd.setSrcTO(soTO); +======= snapshotObject.setPath(devName); origCmd.setSrcTO(snapshotObject.getTO()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 answer = optEPAny.get().sendMessage(origCmd); } else{ answer = new Answer(origCmd, false, "Unable to get matching Linstor endpoint."); @@ -1037,6 +1108,8 @@ private Answer copyFromTemporaryResource( return answer; } +<<<<<<< HEAD +======= /** * vmsnapshots don't have our typical snapshot path set * instead the path is the internal snapshot name e.g.: {vm}_VS_{datestr} @@ -1060,13 +1133,19 @@ private String setCorrectSnapshotPath(DevelopersApi api, String rscName, Snapsho return originalPath; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 protected Answer copySnapshot(DataObject srcData, DataObject destData) { String value = _configDao.getValue(Config.BackupSnapshotWait.toString()); int _backupsnapshotwait = NumbersUtil.parseInt( value, Integer.parseInt(Config.BackupSnapshotWait.getDefaultValue())); +<<<<<<< HEAD + SnapshotInfo snapshotInfo = (SnapshotInfo)srcData; + Boolean snapshotFullBackup = snapshotInfo.getFullBackup(); +======= SnapshotObject snapshotObject = (SnapshotObject)srcData; Boolean snapshotFullBackup = snapshotObject.getFullBackup(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 final StoragePoolVO pool = _storagePoolDao.findById(srcData.getDataStore().getId()); final DevelopersApi api = LinstorUtil.getLinstorAPI(pool.getHostAddress()); boolean fullSnapshot = true; @@ -1077,6 +1156,13 @@ protected Answer copySnapshot(DataObject srcData, DataObject destData) { options.put("fullSnapshot", fullSnapshot + ""); options.put(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.key(), String.valueOf(SnapshotInfo.BackupSnapshotAfterTakingSnapshot.value())); +<<<<<<< HEAD + options.put("volumeSize", snapshotInfo.getBaseVolume().getSize() + ""); + + try { + CopyCommand cmd = new LinstorBackupSnapshotCommand( + srcData.getTO(), +======= options.put("volumeSize", snapshotObject.getBaseVolume().getSize() + ""); try { @@ -1085,22 +1171,35 @@ protected Answer copySnapshot(DataObject srcData, DataObject destData) { CopyCommand cmd = new LinstorBackupSnapshotCommand( snapshotObject.getTO(), +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 destData.getTO(), _backupsnapshotwait, VirtualMachineManager.ExecuteInSequence.value()); cmd.setOptions(options); +<<<<<<< HEAD + String rscName = LinstorUtil.RSC_PREFIX + snapshotInfo.getBaseVolume().getUuid(); +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Optional optEP = getDiskfullEP(api, rscName); Answer answer; if (optEP.isPresent()) { answer = optEP.get().sendMessage(cmd); } else { logger.debug("No diskfull endpoint found to copy image, creating diskless endpoint"); +<<<<<<< HEAD + answer = copyFromTemporaryResource(api, pool, rscName, snapshotInfo, cmd); + } + return answer; + } catch (Exception e) { + logger.debug("copy snapshot failed: ", e); +======= answer = copyFromTemporaryResource(api, pool, rscName, snapshotName, snapshotObject, cmd); } return answer; } catch (Exception e) { logger.debug("copy snapshot failed, please cleanup snapshot manually: ", e); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 throw new CloudRuntimeException(e.toString()); } 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 bdb999459586..37b923f8c452 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 @@ -113,8 +113,12 @@ public static List getLinstorNodeNames(@Nonnull DevelopersApi api) throw Collections.singletonList(storagePoolName), Collections.emptyList(), null, +<<<<<<< HEAD + null +======= null, true +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ); return sps != null ? sps : Collections.emptyList(); } @@ -168,8 +172,12 @@ public static List getRscGroupStoragePools(DevelopersApi api, Strin rscGrps.get(0).getSelectFilter().getStoragePoolList(), null, null, +<<<<<<< HEAD + null +======= null, true +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ); } @@ -205,6 +213,8 @@ public static boolean isResourceInUse(DevelopersApi api, String rscName) throws LOGGER.error("isResourceInUse: null returned from resourceList"); return false; } +<<<<<<< HEAD +======= /** * Try to get the device path for the given resource name. @@ -238,4 +248,5 @@ public static String getDevicePath(DevelopersApi api, String rscName) throws Api LOGGER.error(errMsg); throw new CloudRuntimeException("Linstor: " + errMsg); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/plugins/storage/volume/linstor/src/main/resources/META-INF/cloudstack/storage-volume-linstor/spring-storage-volume-linstor-context.xml b/plugins/storage/volume/linstor/src/main/resources/META-INF/cloudstack/storage-volume-linstor/spring-storage-volume-linstor-context.xml index a900323ede53..d11f749351e3 100644 --- a/plugins/storage/volume/linstor/src/main/resources/META-INF/cloudstack/storage-volume-linstor/spring-storage-volume-linstor-context.xml +++ b/plugins/storage/volume/linstor/src/main/resources/META-INF/cloudstack/storage-volume-linstor/spring-storage-volume-linstor-context.xml @@ -29,8 +29,11 @@ +<<<<<<< HEAD +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 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 8397334d0dd1..7d307de789cb 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 @@ -66,8 +66,11 @@ import org.apache.logging.log4j.LogManager; import com.cloud.agent.api.Answer; +<<<<<<< HEAD +======= import com.cloud.agent.api.GetVolumeStatAnswer; import com.cloud.agent.api.GetVolumeStatCommand; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.agent.api.storage.MigrateVolumeCommand; import com.cloud.agent.api.storage.ResizeVolumeCommand; import com.cloud.agent.api.to.DataObjectType; @@ -493,10 +496,17 @@ public void revertSnapshot(SnapshotInfo snapshot, SnapshotInfo snapshotOnPrimary } public CreateObjectAnswer createVolume(VolumeInfo volumeInfo, long storagePoolId) { +<<<<<<< HEAD + return createVolume(volumeInfo, storagePoolId, false); + } + + public CreateObjectAnswer createVolume(VolumeInfo volumeInfo, long storagePoolId, boolean migrationInvolved) { +======= return createVolume(volumeInfo, storagePoolId, false, null); } public CreateObjectAnswer createVolume(VolumeInfo volumeInfo, long storagePoolId, boolean migrationInvolved, Long usageSize) { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 logger.debug("Creating PowerFlex volume"); StoragePoolVO storagePool = storagePoolDao.findById(storagePoolId); @@ -546,9 +556,12 @@ public CreateObjectAnswer createVolume(VolumeInfo volumeInfo, long storagePoolId VolumeObjectTO prepVolume = (VolumeObjectTO) createdObject.getTO(); prepVolume.setPath(volumePath); prepVolume.setUuid(volumePath); +<<<<<<< HEAD +======= if (usageSize != null) { prepVolume.setUsableSize(usageSize); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 CreateObjectCommand cmd = new CreateObjectCommand(prepVolume); EndPoint ep = selector.select(volumeInfo, true); if (ep == null) { @@ -851,8 +864,12 @@ public Answer liveMigrateVolume(DataObject srcData, DataObject destData) { // Volume migration across different PowerFlex/ScaleIO clusters final long srcVolumeId = srcData.getId(); DataStore srcStore = srcData.getDataStore(); +<<<<<<< HEAD + Map srcDetails = getVolumeDetails((VolumeInfo) srcData, srcStore); +======= VolumeInfo srcVolumeInfo = (VolumeInfo) srcData; Map srcDetails = getVolumeDetails(srcVolumeInfo, srcStore); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 DataStore destStore = destData.getDataStore(); final long destPoolId = destStore.getId(); @@ -864,6 +881,10 @@ public Answer liveMigrateVolume(DataObject srcData, DataObject destData) { EndPoint ep = RemoteHostEndPoint.getHypervisorHostEndPoint(host); Answer answer = null; +<<<<<<< HEAD + try { + CreateObjectAnswer createAnswer = createVolume((VolumeInfo) destData, destStore.getId(), true); +======= Long srcVolumeUsableSize = null; try { GetVolumeStatCommand statCmd = new GetVolumeStatCommand(srcVolumeInfo.getPath(), srcVolumeInfo.getStoragePoolType(), srcStore.getUuid()); @@ -875,6 +896,7 @@ public Answer liveMigrateVolume(DataObject srcData, DataObject destData) { } CreateObjectAnswer createAnswer = createVolume((VolumeInfo) destData, destStore.getId(), true, srcVolumeUsableSize); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 destVolumePath = createAnswer.getData().getPath(); destVolTO.setPath(destVolumePath); 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 4979fd1fa0aa..39b7bf5efb99 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 @@ -20,10 +20,14 @@ package org.apache.cloudstack.storage.datastore.driver; import com.cloud.agent.api.Answer; +<<<<<<< HEAD +import com.cloud.agent.api.storage.MigrateVolumeAnswer; +======= import com.cloud.agent.api.GetVolumeStatAnswer; import com.cloud.agent.api.GetVolumeStatCommand; import com.cloud.agent.api.storage.MigrateVolumeAnswer; import com.cloud.agent.api.storage.MigrateVolumeCommand; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.agent.api.to.DataTO; import com.cloud.agent.api.to.DiskTO; import com.cloud.configuration.Config; @@ -208,15 +212,25 @@ public void testMigrateVolumeWithinSameScaleIOClusterSuccess() throws Exception RemoteHostEndPoint ep = Mockito.mock(RemoteHostEndPoint.class); remoteHostEndPointMock.when(() -> RemoteHostEndPoint.getHypervisorHostEndPoint(host)).thenReturn(ep); +<<<<<<< HEAD + DataTO dataTO = Mockito.mock(DataTO.class); + CreateObjectAnswer createAnswer = new CreateObjectAnswer(dataTO); + doReturn(createAnswer).when(scaleIOPrimaryDataStoreDriver).createVolume(destData, 2L, true); +======= long volumeVirtualSize = 68673077248L; DataTO dataTO = Mockito.mock(DataTO.class); CreateObjectAnswer createAnswer = new CreateObjectAnswer(dataTO); doReturn(createAnswer).when(scaleIOPrimaryDataStoreDriver).createVolume(destData, 2L, true, volumeVirtualSize); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 when(dataTO.getPath()).thenReturn("bec0ba7700000007:vol-11-6aef-10ee"); doReturn(true).when(scaleIOPrimaryDataStoreDriver) .grantAccess(any(), any(), any()); when(configDao.getValue(Config.MigrateWait.key())).thenReturn("3600"); +<<<<<<< HEAD + MigrateVolumeAnswer migrateVolumeAnswer = Mockito.mock(MigrateVolumeAnswer.class); + when(ep.sendMessage(any())).thenReturn(migrateVolumeAnswer); +======= GetVolumeStatAnswer getVolumeStatAnswer = Mockito.mock(GetVolumeStatAnswer.class); when(ep.sendMessage(any(GetVolumeStatCommand.class))).thenReturn(getVolumeStatAnswer); @@ -225,6 +239,7 @@ public void testMigrateVolumeWithinSameScaleIOClusterSuccess() throws Exception MigrateVolumeAnswer migrateVolumeAnswer = Mockito.mock(MigrateVolumeAnswer.class); when(ep.sendMessage(any(MigrateVolumeCommand.class))).thenReturn(migrateVolumeAnswer); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 when(migrateVolumeAnswer.getResult()).thenReturn(true); Mockito.doNothing().when(scaleIOPrimaryDataStoreDriver) @@ -261,6 +276,18 @@ public void testMigrateVolumeWithinSameScaleIOClusterFailure() throws Exception DataTO dataTO = Mockito.mock(DataTO.class); CreateObjectAnswer createAnswer = new CreateObjectAnswer(dataTO); +<<<<<<< HEAD + doReturn(createAnswer).when(scaleIOPrimaryDataStoreDriver).createVolume(destData, 2L, true); + when(dataTO.getPath()).thenReturn("bec0ba7700000007:vol-11-6aef-10ee"); + doReturn(true).when(scaleIOPrimaryDataStoreDriver) + .grantAccess(any(), any(), any()); + + when(configDao.getValue(Config.MigrateWait.key())).thenReturn("3600"); + MigrateVolumeAnswer migrateVolumeAnswer = Mockito.mock(MigrateVolumeAnswer.class); + when(ep.sendMessage(any())).thenReturn(migrateVolumeAnswer); + when(migrateVolumeAnswer.getResult()).thenReturn(false); + Mockito.doNothing().when(scaleIOPrimaryDataStoreDriver) +======= Mockito.lenient().doReturn(createAnswer).when(scaleIOPrimaryDataStoreDriver).createVolume(destData, 2L, true, null); Mockito.lenient().when(dataTO.getPath()).thenReturn("bec0ba7700000007:vol-11-6aef-10ee"); Mockito.lenient().doReturn(true).when(scaleIOPrimaryDataStoreDriver) @@ -276,6 +303,7 @@ public void testMigrateVolumeWithinSameScaleIOClusterFailure() throws Exception when(ep.sendMessage(any())).thenReturn(migrateVolumeAnswer); Mockito.lenient().when(migrateVolumeAnswer.getResult()).thenReturn(false); Mockito.lenient().doNothing().when(scaleIOPrimaryDataStoreDriver) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 .revertBlockCopyVolumeOperations(any(), any(), any(), any()); Answer answer = scaleIOPrimaryDataStoreDriver.liveMigrateVolume(srcData, destData); diff --git a/plugins/user-authenticators/oauth2/pom.xml b/plugins/user-authenticators/oauth2/pom.xml index 5a1e49874a89..72fa061685da 100644 --- a/plugins/user-authenticators/oauth2/pom.xml +++ b/plugins/user-authenticators/oauth2/pom.xml @@ -59,5 +59,10 @@ 1.20.0 compile + + org.keycloak + keycloak-admin-client + 24.0.0 + diff --git a/plugins/user-authenticators/oauth2/src/main/java/org/apache/cloudstack/oauth2/OAuth2UserAuthenticator.java b/plugins/user-authenticators/oauth2/src/main/java/org/apache/cloudstack/oauth2/OAuth2UserAuthenticator.java index a59d1fc919b7..b68c2d9339de 100644 --- a/plugins/user-authenticators/oauth2/src/main/java/org/apache/cloudstack/oauth2/OAuth2UserAuthenticator.java +++ b/plugins/user-authenticators/oauth2/src/main/java/org/apache/cloudstack/oauth2/OAuth2UserAuthenticator.java @@ -31,6 +31,17 @@ import javax.inject.Inject; import java.util.Map; +<<<<<<< HEAD +public class OAuth2UserAuthenticator extends AdapterBase implements UserAuthenticator { + + @Inject + private UserAccountDao _userAccountDao; + @Inject + private UserDao _userDao; + + @Inject + private OAuth2AuthManager _userOAuth2mgr; +======= import static org.apache.cloudstack.oauth2.OAuth2AuthManager.OAuth2IsPluginEnabled; public class OAuth2UserAuthenticator extends AdapterBase implements UserAuthenticator { @@ -42,6 +53,7 @@ public class OAuth2UserAuthenticator extends AdapterBase implements UserAuthenti @Inject private OAuth2AuthManager userOAuth2mgr; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Override public Pair authenticate(String username, String password, Long domainId, Map requestParameters) { @@ -49,6 +61,9 @@ public Pair authenticate(String username, logger.debug("Trying OAuth2 auth for user: " + username); } +<<<<<<< HEAD + final UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId); +======= if (!isOAuthPluginEnabled()) { logger.debug("OAuth2 plugin is disabled"); return new Pair(false, null); @@ -58,11 +73,16 @@ public Pair authenticate(String username, } final UserAccount userAccount = userAccountDao.getUserAccount(username, domainId); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (userAccount == null) { logger.debug("Unable to find user with " + username + " in domain " + domainId + ", or user source is not OAUTH2"); return new Pair(false, null); } else { +<<<<<<< HEAD + User user = _userDao.getUser(userAccount.getId()); +======= User user = userDao.getUser(userAccount.getId()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 final String[] provider = (String[])requestParameters.get(ApiConstants.PROVIDER); final String[] emailArray = (String[])requestParameters.get(ApiConstants.EMAIL); final String[] secretCodeArray = (String[])requestParameters.get(ApiConstants.SECRET_CODE); @@ -70,7 +90,11 @@ public Pair authenticate(String username, String email = ((emailArray == null) ? null : emailArray[0]); String secretCode = ((secretCodeArray == null) ? null : secretCodeArray[0]); +<<<<<<< HEAD + UserOAuth2Authenticator authenticator = _userOAuth2mgr.getUserOAuth2AuthenticationProvider(oauthProvider); +======= UserOAuth2Authenticator authenticator = userOAuth2mgr.getUserOAuth2AuthenticationProvider(oauthProvider); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (user != null && authenticator.verifyUser(email, secretCode)) { return new Pair(true, null); } @@ -83,8 +107,11 @@ public Pair authenticate(String username, public String encode(String password) { return null; } +<<<<<<< HEAD +======= protected boolean isOAuthPluginEnabled() { return OAuth2IsPluginEnabled.value(); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/plugins/user-authenticators/oauth2/src/main/java/org/apache/cloudstack/oauth2/keycloak/KeycloakOAuth2Provider.java b/plugins/user-authenticators/oauth2/src/main/java/org/apache/cloudstack/oauth2/keycloak/KeycloakOAuth2Provider.java new file mode 100644 index 000000000000..13664598a5f9 --- /dev/null +++ b/plugins/user-authenticators/oauth2/src/main/java/org/apache/cloudstack/oauth2/keycloak/KeycloakOAuth2Provider.java @@ -0,0 +1,153 @@ +<<<<<<< HEAD +// 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. + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 +package org.apache.cloudstack.oauth2.keycloak; + +import com.cloud.exception.CloudAuthenticationException; +import com.cloud.utils.component.AdapterBase; +import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.auth.UserOAuth2Authenticator; +import org.apache.cloudstack.oauth2.dao.OauthProviderDao; +import org.apache.cloudstack.oauth2.vo.OauthProviderVO; +import org.apache.commons.lang3.StringUtils; +import org.keycloak.OAuth2Constants; +import org.keycloak.admin.client.Keycloak; +<<<<<<< HEAD +import org.keycloak.admin.client.resource.RealmResource; +import org.keycloak.admin.client.resource.UserResource; +import org.keycloak.representations.AccessTokenResponse; + +import javax.inject.Inject; +import java.util.HashMap; +import java.util.Map; +======= +import org.keycloak.admin.client.KeycloakBuilder; +import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.representations.AccessTokenResponse; + +import javax.inject.Inject; +import java.util.List; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 + +public class KeycloakOAuth2Provider extends AdapterBase implements UserOAuth2Authenticator { + + protected String accessToken = null; + protected String refreshToken = null; + + @Inject + OauthProviderDao _oauthProviderDao; + + @Override + public String getName() { + return "keycloak"; + } + + @Override + public String getDescription() { + return "Keycloak OAuth2 Provider Plugin"; + } + + @Override + public boolean verifyUser(String email, String secretCode) { + if (StringUtils.isAnyEmpty(email, secretCode)) { + throw new CloudAuthenticationException("Either email or secret code should not be null/empty"); + } + + OauthProviderVO providerVO = _oauthProviderDao.findByProvider(getName()); + if (providerVO == null) { + throw new CloudAuthenticationException("Keycloak provider is not registered, so user cannot be verified"); + } + + String verifiedEmail = verifyCodeAndFetchEmail(secretCode); + if (verifiedEmail == null || !email.equals(verifiedEmail)) { + throw new CloudRuntimeException("Unable to verify the email address with the provided secret"); + } + clearAccessAndRefreshTokens(); + + return true; + } + + @Override + public String verifyCodeAndFetchEmail(String secretCode) { + OauthProviderVO keycloakProvider = _oauthProviderDao.findByProvider(getName()); + String clientId = keycloakProvider.getClientId(); +<<<<<<< HEAD + String secret = keycloakProvider.getSecretKey(); + String authServerUrl = keycloakProvider.getAuthServerUrl(); + String realm = keycloakProvider.getRealm(); + + Keycloak keycloak = Keycloak.getInstance(authServerUrl, realm, clientId, secret, OAuth2Constants.CLIENT_CREDENTIALS); +======= + String clientSecret = keycloakProvider.getSecretKey(); + String redirectUri = keycloakProvider.getRedirectUri(); + String authServerUrl = keycloakProvider.getAuthenticationUri(); + + Keycloak keycloak = KeycloakBuilder.builder() + .serverUrl(authServerUrl) + .realm(keycloakProvider.getProviderName()) + .clientId(clientId) + .clientSecret(clientSecret) + .grantType(OAuth2Constants.AUTHORIZATION_CODE) + .redirectUri(redirectUri) + .code(secretCode) + .build(); + +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 + AccessTokenResponse tokenResponse = keycloak.tokenManager().getAccessToken(); + + accessToken = tokenResponse.getToken(); + refreshToken = tokenResponse.getRefreshToken(); + +<<<<<<< HEAD + RealmResource realmResource = keycloak.realm(realm); + UserResource userResource = realmResource.users().get(tokenResponse.getSubject()); + + Map attributes = new HashMap<>(); + try { + attributes = userResource.toRepresentation().getAttributes(); + } catch (Exception e) { + throw new CloudRuntimeException(String.format("Failed to fetch the email address with the provided secret: %s", e.getMessage())); + } + + return (String) attributes.get("email"); +======= + List users = keycloak.realm(keycloakProvider.getProviderName()).users().search("", 0, 1); + if (users.isEmpty()) { + throw new CloudRuntimeException("No user found with the provided secret"); + } + + return users.get(0).getEmail(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 + } + + protected void clearAccessAndRefreshTokens() { + accessToken = null; + refreshToken = null; + } + + @Override + public String getUserEmailAddress() throws CloudRuntimeException { + return null; + } +} +<<<<<<< HEAD +======= + +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 diff --git a/plugins/user-authenticators/oauth2/src/test/java/org/apache/cloudstack/oauth2/OAuth2UserAuthenticatorTest.java b/plugins/user-authenticators/oauth2/src/test/java/org/apache/cloudstack/oauth2/OAuth2UserAuthenticatorTest.java index d1c1889ba999..f0241d12bfbc 100644 --- a/plugins/user-authenticators/oauth2/src/test/java/org/apache/cloudstack/oauth2/OAuth2UserAuthenticatorTest.java +++ b/plugins/user-authenticators/oauth2/src/test/java/org/apache/cloudstack/oauth2/OAuth2UserAuthenticatorTest.java @@ -27,29 +27,42 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; +<<<<<<< HEAD +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +======= import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import java.util.HashMap; import java.util.Map; import static org.junit.Assert.assertEquals; +<<<<<<< HEAD +======= import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +<<<<<<< HEAD + +======= import static org.mockito.Mockito.doReturn; @RunWith(MockitoJUnitRunner.class) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public class OAuth2UserAuthenticatorTest { @Mock @@ -62,14 +75,22 @@ public class OAuth2UserAuthenticatorTest { private OAuth2AuthManager userOAuth2mgr; @InjectMocks +<<<<<<< HEAD + private OAuth2UserAuthenticator authenticator; + +======= @Spy private OAuth2UserAuthenticator authenticator; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private AutoCloseable closeable; @Before public void setUp() { closeable = MockitoAnnotations.openMocks(this); +<<<<<<< HEAD +======= doReturn(true).when(authenticator).isOAuthPluginEnabled(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } @After @@ -77,7 +98,10 @@ public void tearDown() throws Exception { closeable.close(); } +<<<<<<< HEAD +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Test public void testAuthenticateWithValidCredentials() { String username = "testuser"; @@ -102,13 +126,22 @@ public void testAuthenticateWithValidCredentials() { Pair result = authenticator.authenticate(username, null, domainId, requestParameters); +<<<<<<< HEAD +======= assertTrue(result.first()); assertNull(result.second()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 verify(userAccountDao).getUserAccount(username, domainId); verify(userDao).getUser(userAccount.getId()); verify(userOAuth2mgr).getUserOAuth2AuthenticationProvider(provider[0]); verify(userOAuth2Authenticator).verifyUser(email[0], secretCode[0]); +<<<<<<< HEAD + + assertEquals(true, result.first().booleanValue()); + assertEquals(null, result.second()); +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } @Test @@ -124,7 +157,11 @@ public void testAuthenticateWithInvalidCredentials() { UserOAuth2Authenticator userOAuth2Authenticator = mock(UserOAuth2Authenticator.class); when(userAccountDao.getUserAccount(username, domainId)).thenReturn(userAccount); +<<<<<<< HEAD + when(userDao.getUser(userAccount.getId())).thenReturn( user); +======= when(userDao.getUser(userAccount.getId())).thenReturn(user); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 when(userOAuth2mgr.getUserOAuth2AuthenticationProvider(provider[0])).thenReturn(userOAuth2Authenticator); when(userOAuth2Authenticator.verifyUser(email[0], secretCode[0])).thenReturn(false); @@ -135,13 +172,22 @@ public void testAuthenticateWithInvalidCredentials() { Pair result = authenticator.authenticate(username, null, domainId, requestParameters); +<<<<<<< HEAD +======= assertFalse(result.first()); assertEquals(OAuth2UserAuthenticator.ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT, result.second()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 verify(userAccountDao).getUserAccount(username, domainId); verify(userDao).getUser(userAccount.getId()); verify(userOAuth2mgr).getUserOAuth2AuthenticationProvider(provider[0]); verify(userOAuth2Authenticator).verifyUser(email[0], secretCode[0]); +<<<<<<< HEAD + + assertEquals(false, result.first().booleanValue()); + assertEquals(OAuth2UserAuthenticator.ActionOnFailedAuthentication.INCREMENT_INCORRECT_LOGIN_ATTEMPT_COUNT, result.second()); +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } @Test @@ -161,11 +207,20 @@ public void testAuthenticateWithInvalidUserAccount() { Pair result = authenticator.authenticate(username, null, domainId, requestParameters); +<<<<<<< HEAD + verify(userAccountDao).getUserAccount(username, domainId); + verify(userDao, never()).getUser(anyLong()); + verify(userOAuth2mgr, never()).getUserOAuth2AuthenticationProvider(anyString()); + + assertEquals(false, result.first().booleanValue()); + assertEquals(null, result.second()); +======= assertFalse(result.first()); assertNull(result.second()); verify(userAccountDao).getUserAccount(username, domainId); verify(userDao, never()).getUser(anyLong()); verify(userOAuth2mgr, never()).getUserOAuth2AuthenticationProvider(anyString()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } diff --git a/plugins/user-authenticators/oauth2/src/test/java/org/apache/cloudstack/oauth2/keycloak/KeycloakOAuth2ProviderTest.java b/plugins/user-authenticators/oauth2/src/test/java/org/apache/cloudstack/oauth2/keycloak/KeycloakOAuth2ProviderTest.java new file mode 100644 index 000000000000..3a8e4135caff --- /dev/null +++ b/plugins/user-authenticators/oauth2/src/test/java/org/apache/cloudstack/oauth2/keycloak/KeycloakOAuth2ProviderTest.java @@ -0,0 +1,166 @@ +// 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.oauth2.keycloak; + +import com.cloud.exception.CloudAuthenticationException; +import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.cloudstack.oauth2.dao.OauthProviderDao; +import org.apache.cloudstack.oauth2.vo.OauthProviderVO; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.keycloak.admin.client.Keycloak; +import org.keycloak.admin.client.resource.RealmResource; +import org.keycloak.admin.client.resource.UserResource; +import org.keycloak.representations.AccessTokenResponse; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +public class KeycloakOAuth2ProviderTest { + + @Mock + private OauthProviderDao _oauthProviderDao; + + @Spy + @InjectMocks + private KeycloakOAuth2Provider _keycloakOAuth2Provider; + + private AutoCloseable closeable; + + @Before + public void setUp() { + closeable = MockitoAnnotations.openMocks(this); + } + + @After + public void tearDown() throws Exception { + closeable.close(); + } + + @Test(expected = CloudAuthenticationException.class) + public void testVerifyUserWithNullEmail() { + _keycloakOAuth2Provider.verifyUser(null, "secretCode"); + } + + @Test(expected = CloudAuthenticationException.class) + public void testVerifyUserWithNullSecretCode() { + _keycloakOAuth2Provider.verifyUser("email@example.com", null); + } + + @Test(expected = CloudAuthenticationException.class) + public void testVerifyUserWithUnregisteredProvider() { + when(_oauthProviderDao.findByProvider(anyString())).thenReturn(null); + _keycloakOAuth2Provider.verifyUser("email@example.com", "secretCode"); + } + + @Test(expected = CloudRuntimeException.class) + public void testVerifyUserWithInvalidSecretCode() { + OauthProviderVO providerVO = mock(OauthProviderVO.class); + when(_oauthProviderDao.findByProvider(anyString())).thenReturn(providerVO); + when(providerVO.getClientId()).thenReturn("testClientId"); + when(providerVO.getSecretKey()).thenReturn("testSecretKey"); + when(providerVO.getAuthServerUrl()).thenReturn("http://localhost:8080/auth"); + when(providerVO.getRealm()).thenReturn("testRealm"); + + Keycloak keycloak = mock(Keycloak.class); + when(Keycloak.getInstance(anyString(), anyString(), anyString(), anyString(), anyString())).thenReturn(keycloak); + + AccessTokenResponse tokenResponse = mock(AccessTokenResponse.class); + when(keycloak.tokenManager().getAccessToken()).thenReturn(tokenResponse); + + RealmResource realmResource = mock(RealmResource.class); + when(keycloak.realm(anyString())).thenReturn(realmResource); + + UserResource userResource = mock(UserResource.class); + when(realmResource.users().get(anyString())).thenReturn(userResource); + + Map attributes = new HashMap<>(); + attributes.put("email", null); + when(userResource.toRepresentation().getAttributes()).thenReturn(attributes); + + _keycloakOAuth2Provider.verifyUser("email@example.com", "secretCode"); + } + + @Test(expected = CloudRuntimeException.class) + public void testVerifyUserWithMismatchedEmail() { + OauthProviderVO providerVO = mock(OauthProviderVO.class); + when(_oauthProviderDao.findByProvider(anyString())).thenReturn(providerVO); + when(providerVO.getClientId()).thenReturn("testClientId"); + when(providerVO.getSecretKey()).thenReturn("testSecretKey"); + when(providerVO.getAuthServerUrl()).thenReturn("http://localhost:8080/auth"); + when(providerVO.getRealm()).thenReturn("testRealm"); + + Keycloak keycloak = mock(Keycloak.class); + when(Keycloak.getInstance(anyString(), anyString(), anyString(), anyString(), anyString())).thenReturn(keycloak); + + AccessTokenResponse tokenResponse = mock(AccessTokenResponse.class); + when(keycloak.tokenManager().getAccessToken()).thenReturn(tokenResponse); + + RealmResource realmResource = mock(RealmResource.class); + when(keycloak.realm(anyString())).thenReturn(realmResource); + + UserResource userResource = mock(UserResource.class); + when(realmResource.users().get(anyString())).thenReturn(userResource); + + Map attributes = new HashMap<>(); + attributes.put("email", "otheremail@example.com"); + when(userResource.toRepresentation().getAttributes()).thenReturn(attributes); + + _keycloakOAuth2Provider.verifyUser("email@example.com", "secretCode"); + } + + @Test + public void testVerifyUserEmail() { + OauthProviderVO providerVO = mock(OauthProviderVO.class); + when(_oauthProviderDao.findByProvider(anyString())).thenReturn(providerVO); + when(providerVO.getClientId()).thenReturn("testClientId"); + when(providerVO.getSecretKey()).thenReturn("testSecretKey"); + when(providerVO.getAuthServerUrl()).thenReturn("http://localhost:8080/auth"); + when(providerVO.getRealm()).thenReturn("testRealm"); + + Keycloak keycloak = mock(Keycloak.class); + when(Keycloak.getInstance(anyString(), anyString(), anyString(), anyString(), anyString())).thenReturn(keycloak); + + AccessTokenResponse tokenResponse = mock(AccessTokenResponse.class); + when(keycloak.tokenManager().getAccessToken()).thenReturn(tokenResponse); + + RealmResource realmResource = mock(RealmResource.class); + when(keycloak.realm(anyString())).thenReturn(realmResource); + + UserResource userResource = mock(UserResource.class); + when(realmResource.users().get(anyString())).thenReturn(userResource); + + Map attributes = new HashMap<>(); + attributes.put("email", "email@example.com"); + when(userResource.toRepresentation().getAttributes()).thenReturn(attributes); + + boolean result = _keycloakOAuth2Provider.verifyUser("email@example.com", "secretCode"); + + assertTrue(result); + assertNull(_keycloakOAuth2Provider.accessToken); + } +} diff --git a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmd.java b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmd.java index 6741a0b40685..e514e6f7c33e 100644 --- a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmd.java +++ b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmd.java @@ -142,6 +142,8 @@ public Response processSAMLResponse(String responseMessage) { return responseObject; } +<<<<<<< HEAD +======= protected void checkAndFailOnMissingSAMLSignature(Signature signature) { if (signature == null && SAML2AuthManager.SAMLCheckSignature.value()) { logger.error("Failing SAML login due to missing signature in the SAML response and signature check is enforced. " + @@ -150,6 +152,7 @@ protected void checkAndFailOnMissingSAMLSignature(Signature signature) { } } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Override public String authenticate(final String command, final Map params, final HttpSession session, final InetAddress remoteAddress, final String responseType, final StringBuilder auditTrailSb, final HttpServletRequest req, final HttpServletResponse resp) throws ServerApiException { try { @@ -231,7 +234,10 @@ public String authenticate(final String command, final Map par session.setAttribute(SAMLPluginConstants.SAML_IDPID, issuer.getValue()); Signature sig = processedSAMLResponse.getSignature(); +<<<<<<< HEAD +======= checkAndFailOnMissingSAMLSignature(sig); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (idpMetadata.getSigningCertificate() != null && sig != null) { BasicX509Credential credential = new BasicX509Credential(); credential.setEntityCertificate(idpMetadata.getSigningCertificate()); @@ -245,8 +251,14 @@ public String authenticate(final String command, final Map par params, responseType)); } } +<<<<<<< HEAD + if (username == null) { + username = SAMLUtils.getValueFromAssertions(processedSAMLResponse.getAssertions(), SAML2AuthManager.SAMLUserAttributeName.value()); + } +======= username = SAMLUtils.getValueFromAssertions(processedSAMLResponse.getAssertions(), SAML2AuthManager.SAMLUserAttributeName.value()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 for (Assertion assertion: processedSAMLResponse.getAssertions()) { if (assertion!= null && assertion.getSubject() != null && assertion.getSubject().getNameID() != null) { @@ -278,7 +290,10 @@ public String authenticate(final String command, final Map par continue; } Signature encSig = assertion.getSignature(); +<<<<<<< HEAD +======= checkAndFailOnMissingSAMLSignature(encSig); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (idpMetadata.getSigningCertificate() != null && encSig != null) { BasicX509Credential sigCredential = new BasicX509Credential(); sigCredential.setEntityCertificate(idpMetadata.getSigningCertificate()); diff --git a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManager.java b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManager.java index a5dae36581c6..1d5d8ad47b72 100644 --- a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManager.java +++ b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManager.java @@ -25,6 +25,53 @@ public interface SAML2AuthManager extends PluggableAPIAuthenticator, PluggableService { +<<<<<<< HEAD + public static final ConfigKey SAMLIsPluginEnabled = new ConfigKey("Advanced", Boolean.class, "saml2.enabled", "false", + "Indicates whether SAML SSO plugin is enabled or not", true); + + public static final ConfigKey SAMLServiceProviderID = new ConfigKey("Advanced", String.class, "saml2.sp.id", "org.apache.cloudstack", + "SAML2 Service Provider Identifier String", true); + + public static final ConfigKey SAMLServiceProviderContactPersonName = new ConfigKey("Advanced", String.class, "saml2.sp.contact.person", "CloudStack Developers", + "SAML2 Service Provider Contact Person Name", true); + + public static final ConfigKey SAMLServiceProviderContactEmail = new ConfigKey("Advanced", String.class, "saml2.sp.contact.email", "dev@cloudstack.apache.org", + "SAML2 Service Provider Contact Email Address", true); + + public static final ConfigKey SAMLServiceProviderOrgName = new ConfigKey("Advanced", String.class, "saml2.sp.org.name", "Apache CloudStack", + "SAML2 Service Provider Organization Name", true); + + public static final ConfigKey SAMLServiceProviderOrgUrl = new ConfigKey("Advanced", String.class, "saml2.sp.org.url", "http://cloudstack.apache.org", + "SAML2 Service Provider Organization URL", true); + + public static final ConfigKey SAMLServiceProviderSingleSignOnURL = new ConfigKey("Advanced", String.class, "saml2.sp.sso.url", "http://localhost:8080/client/api?command=samlSso", + "SAML2 CloudStack Service Provider Single Sign On URL", true); + + public static final ConfigKey SAMLServiceProviderSingleLogOutURL = new ConfigKey("Advanced", String.class, "saml2.sp.slo.url", "http://localhost:8080/client/", + "SAML2 CloudStack Service Provider Single Log Out URL", true); + + public static final ConfigKey SAMLCloudStackRedirectionUrl = new ConfigKey("Advanced", String.class, "saml2.redirect.url", "http://localhost:8080/client", + "The CloudStack UI url the SSO should redirected to when successful", true); + + public static final ConfigKey SAMLUserAttributeName = new ConfigKey("Advanced", String.class, "saml2.user.attribute", "uid", + "Attribute name to be looked for in SAML response that will contain the username", true); + + public static final ConfigKey SAMLIdentityProviderMetadataURL = new ConfigKey("Advanced", String.class, "saml2.idp.metadata.url", "https://openidp.feide.no/simplesaml/saml2/idp/metadata.php", + "SAML2 Identity Provider Metadata XML Url", true); + + public static final ConfigKey SAMLDefaultIdentityProviderId = new ConfigKey("Advanced", String.class, "saml2.default.idpid", "https://openidp.feide.no", + "The default IdP entity ID to use only in case of multiple IdPs", true); + + public static final ConfigKey SAMLSignatureAlgorithm = new ConfigKey<>(String.class, "saml2.sigalg", "Advanced", "SHA1", + "The algorithm to use to when signing a SAML request. Default is SHA1, allowed algorithms: SHA1, SHA256, SHA384, SHA512", true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.Select, "SHA1,SHA256,SHA384,SHA512"); + + public static final ConfigKey SAMLAppendDomainSuffix = new ConfigKey("Advanced", Boolean.class, "saml2.append.idpdomain", "false", + "If enabled, create account/user dialog with SAML SSO enabled will append the IdP domain to the user or account name in the UI dialog", true); + + public static final ConfigKey SAMLTimeout = new ConfigKey("Advanced", Integer.class, "saml2.timeout", "1800", + "SAML2 IDP Metadata refresh interval in seconds, minimum value is set to 300", true); + +======= ConfigKey SAMLIsPluginEnabled = new ConfigKey("Advanced", Boolean.class, "saml2.enabled", "false", "Indicates whether SAML SSO plugin is enabled or not", true); @@ -73,6 +120,7 @@ public interface SAML2AuthManager extends PluggableAPIAuthenticator, PluggableSe ConfigKey SAMLCheckSignature = new ConfigKey("Advanced", Boolean.class, "saml2.check.signature", "false", "Whether SAML2 signature must be checked, when enforced and when the SAML response does not have a signature would lead to login exception", true); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public SAMLProviderMetadata getSPMetadata(); public SAMLProviderMetadata getIdPMetadata(String entityId); public Collection getAllIdPMetadata(); diff --git a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java index c4bd696003b8..e7291b6b4779 100644 --- a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java +++ b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/saml/SAML2AuthManagerImpl.java @@ -533,6 +533,10 @@ public ConfigKey[] getConfigKeys() { SAMLServiceProviderSingleSignOnURL, SAMLServiceProviderSingleLogOutURL, SAMLCloudStackRedirectionUrl, SAMLUserAttributeName, SAMLIdentityProviderMetadataURL, SAMLDefaultIdentityProviderId, +<<<<<<< HEAD + SAMLSignatureAlgorithm, SAMLAppendDomainSuffix, SAMLTimeout}; +======= SAMLSignatureAlgorithm, SAMLAppendDomainSuffix, SAMLTimeout, SAMLCheckSignature}; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } diff --git a/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java b/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java index ebdc5be8fe9e..00e9167c7b08 100644 --- a/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java +++ b/plugins/user-authenticators/saml2/src/test/java/org/apache/cloudstack/api/command/SAML2LoginAPIAuthenticatorCmdTest.java @@ -271,6 +271,8 @@ public void whenFailToAuthenticateThrowExceptionOrRedirectToUrlTestSaml2FailedLo verifyTestWhenFailToAuthenticateThrowExceptionOrRedirectToUrl(false, hasThrownServerApiException, 0, 0); } +<<<<<<< HEAD +======= private void overrideDefaultConfigValue(final ConfigKey configKey, final String name, final Object o) throws IllegalAccessException, NoSuchFieldException { Field f = ConfigKey.class.getDeclaredField(name); f.setAccessible(true); @@ -295,6 +297,7 @@ public void testFailOnSAMLSignatureCheckWhenTrue() throws NoSuchFieldException, cmd.checkAndFailOnMissingSAMLSignature(null); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private UserAccountVO configureTestWhenFailToAuthenticateThrowExceptionOrRedirectToUrl(String entity, String configurationValue, Boolean isUserAuthorized) throws IOException { Mockito.when(samlAuthManager.isUserAuthorized(nullable(Long.class), nullable(String.class))).thenReturn(isUserAuthorized); diff --git a/pom.xml b/pom.xml index 24247f50050f..ef4d3ab5526c 100644 --- a/pom.xml +++ b/pom.xml @@ -171,7 +171,11 @@ 10.1 2.6.6 0.6.0 +<<<<<<< HEAD + 0.3.0 +======= 0.5.1 +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 0.10.2 3.4.4_1 4.0.1 diff --git a/server/conf/log4j-cloud.xml.in b/server/conf/log4j-cloud.xml.in index 5d1d3162bc41..15a4dfc8d013 100755 --- a/server/conf/log4j-cloud.xml.in +++ b/server/conf/log4j-cloud.xml.in @@ -67,7 +67,11 @@ under the License. +<<<<<<< HEAD + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 diff --git a/server/src/main/java/com/cloud/alert/AlertManagerImpl.java b/server/src/main/java/com/cloud/alert/AlertManagerImpl.java index 4c4f08f12bd7..60aba6a00006 100644 --- a/server/src/main/java/com/cloud/alert/AlertManagerImpl.java +++ b/server/src/main/java/com/cloud/alert/AlertManagerImpl.java @@ -800,7 +800,11 @@ public String getConfigComponentName() { @Override public ConfigKey[] getConfigKeys() { return new ConfigKey[] {CPUCapacityThreshold, MemoryCapacityThreshold, StorageAllocatedCapacityThreshold, StorageCapacityThreshold, AlertSmtpEnabledSecurityProtocols, +<<<<<<< HEAD + AlertSmtpUseStartTLS, Ipv6SubnetCapacityThreshold}; +======= AlertSmtpUseStartTLS, Ipv6SubnetCapacityThreshold, AlertSmtpUseAuth}; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } @Override diff --git a/server/src/main/java/com/cloud/api/ApiResponseHelper.java b/server/src/main/java/com/cloud/api/ApiResponseHelper.java index 3d87347291cc..a5a0ebac4e35 100644 --- a/server/src/main/java/com/cloud/api/ApiResponseHelper.java +++ b/server/src/main/java/com/cloud/api/ApiResponseHelper.java @@ -1004,12 +1004,15 @@ private void addSystemVmInfoToIpResponse(NicVO nic, IPAddressResponse ipResponse if (!isAdmin) { return; } +<<<<<<< HEAD +======= try { nic.getInstanceId(); } catch (NullPointerException ex) { return; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 VirtualMachine vm = ApiDBUtils.findVMInstanceById(nic.getInstanceId()); if (vm == null) { return; diff --git a/server/src/main/java/com/cloud/api/ApiServer.java b/server/src/main/java/com/cloud/api/ApiServer.java index 6a03b23bcd23..42b43806fcc6 100644 --- a/server/src/main/java/com/cloud/api/ApiServer.java +++ b/server/src/main/java/com/cloud/api/ApiServer.java @@ -95,7 +95,12 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; +<<<<<<< HEAD +import org.apache.cloudstack.framework.events.EventBus; +import org.apache.cloudstack.framework.events.EventBusException; +======= import org.apache.cloudstack.framework.events.EventDistributor; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.framework.jobs.AsyncJob; import org.apache.cloudstack.framework.jobs.AsyncJobManager; import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO; @@ -131,9 +136,16 @@ import org.apache.http.protocol.ResponseContent; import org.apache.http.protocol.ResponseDate; import org.apache.http.protocol.ResponseServer; +<<<<<<< HEAD +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +======= import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.bouncycastle.jce.provider.BouncyCastleProvider; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.springframework.stereotype.Component; import com.cloud.api.dispatch.DispatchChainFactory; @@ -195,6 +207,13 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer private static final String CONTROL_CHARACTERS = "[\000-\011\013-\014\016-\037\177]"; @Inject +<<<<<<< HEAD + private ApiDispatcher dispatcher; + @Inject + private DispatchChainFactory dispatchChainFactory; + @Inject + private AccountManager accountMgr; +======= private AccountManager accountMgr; @Inject private APIAuthenticationManager authManager; @@ -204,16 +223,29 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer private AsyncJobManager asyncMgr; @Inject private DispatchChainFactory dispatchChainFactory; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Inject private DomainManager domainMgr; @Inject private DomainDao domainDao; @Inject +<<<<<<< HEAD + private UUIDManager uuidMgr; + @Inject + private AsyncJobManager asyncMgr; + @Inject + private EntityManager entityMgr; + @Inject + private APIAuthenticationManager authManager; + @Inject + private ProjectDao projectDao; +======= private EntityManager entityMgr; @Inject private ProjectDao projectDao; @Inject private UUIDManager uuidMgr; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private List pluggableServices; @@ -222,7 +254,10 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer @Inject private ApiAsyncJobDispatcher asyncDispatcher; +<<<<<<< HEAD +======= private EventDistributor eventDistributor = null; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private static int s_workerCount = 0; private static Map>> s_apiNameCmdClassMap = new HashMap>>(); @@ -310,10 +345,13 @@ public boolean configure(final String name, final Map params) th return true; } +<<<<<<< HEAD +======= public void setEventDistributor(EventDistributor eventDistributor) { this.eventDistributor = eventDistributor; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @MessageHandler(topic = AsyncJob.Topics.JOB_EVENT_PUBLISH) public void handleAsyncJobPublishEvent(String subject, String senderAddress, Object args) { assert (args != null); @@ -325,8 +363,17 @@ public void handleAsyncJobPublishEvent(String subject, String senderAddress, Obj if (logger.isTraceEnabled()) logger.trace("Handle asyjob publish event " + jobEvent); +<<<<<<< HEAD + + EventBus eventBus = null; + try { + eventBus = ComponentContext.getComponent(EventBus.class); + } catch (NoSuchBeanDefinitionException nbe) { + return; // no provider is configured to provide events bus, so just return +======= if (eventDistributor == null) { setEventDistributor(ComponentContext.getComponent(EventDistributor.class)); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } if (!job.getDispatcher().equalsIgnoreCase("ApiAsyncJobDispatcher")) { @@ -339,7 +386,11 @@ public void handleAsyncJobPublishEvent(String subject, String senderAddress, Obj // Get the event type from the cmdInfo json string String info = job.getCmdInfo(); String cmdEventType = "unknown"; +<<<<<<< HEAD + Map cmdInfoObj = new HashMap(); +======= Map cmdInfoObj = new HashMap<>(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (info != null) { Type type = new TypeToken>(){}.getType(); Map cmdInfo = ApiGsonHelper.getBuilder().create().fromJson(info, type); @@ -367,7 +418,11 @@ public void handleAsyncJobPublishEvent(String subject, String senderAddress, Obj org.apache.cloudstack.framework.events.Event event = new org.apache.cloudstack.framework.events.Event("management-server", EventCategory.ASYNC_JOB_CHANGE_EVENT.getName(), jobEvent, instanceType, instanceUuid); +<<<<<<< HEAD + Map eventDescription = new HashMap(); +======= Map eventDescription = new HashMap<>(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 eventDescription.put("command", job.getCmd()); eventDescription.put("user", userJobOwner.getUuid()); eventDescription.put("account", jobOwner.getUuid()); @@ -388,7 +443,17 @@ public void handleAsyncJobPublishEvent(String subject, String senderAddress, Obj eventDescription.put("domainname", domain.getName()); } event.setDescription(eventDescription); +<<<<<<< HEAD + + try { + eventBus.publish(event); + } catch (EventBusException evx) { + String errMsg = "Failed to publish async job event on the event bus."; + logger.warn(errMsg, evx); + } +======= eventDistributor.publish(event); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } @Override diff --git a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java index 6ccf128d537f..0c82251396f2 100644 --- a/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/main/java/com/cloud/api/query/QueryManagerImpl.java @@ -2397,7 +2397,11 @@ private Pair, Integer> searchForVolumesInternal(ListVolumesCm private Pair, Integer> searchForVolumeIdsAndCount(ListVolumesCmd cmd) { Account caller = CallContext.current().getCallingAccount(); +<<<<<<< HEAD + List permittedAccounts = new ArrayList(); +======= List permittedAccounts = new ArrayList<>(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Long id = cmd.getId(); Long vmInstanceId = cmd.getVirtualMachineId(); @@ -2407,8 +2411,12 @@ private Pair, Integer> searchForVolumeIdsAndCount(ListVolumesCmd cmd) Map tags = cmd.getTags(); String storageId = cmd.getStorageId(); Long clusterId = cmd.getClusterId(); +<<<<<<< HEAD + Long diskOffId = cmd.getDiskOfferingId(); +======= Long serviceOfferingId = cmd.getServiceOfferingId(); Long diskOfferingId = cmd.getDiskOfferingId(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Boolean display = cmd.getDisplay(); String state = cmd.getState(); boolean shouldListSystemVms = shouldListSystemVms(cmd, caller.getId()); @@ -2418,6 +2426,9 @@ private Pair, Integer> searchForVolumeIdsAndCount(ListVolumesCmd cmd) List ids = getIdsListFromCmd(cmd.getId(), cmd.getIds()); +<<<<<<< HEAD + Ternary domainIdRecursiveListProject = new Ternary(cmd.getDomainId(), cmd.isRecursive(), null); +======= if (diskOfferingId == null && serviceOfferingId != null) { ServiceOfferingVO serviceOffering = _srvOfferingDao.findById(serviceOfferingId); if (serviceOffering != null) { @@ -2426,6 +2437,7 @@ private Pair, Integer> searchForVolumeIdsAndCount(ListVolumesCmd cmd) } Ternary domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(), cmd.isRecursive(), null); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false); Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); @@ -2445,6 +2457,8 @@ private Pair, Integer> searchForVolumeIdsAndCount(ListVolumesCmd cmd) volumeSearchBuilder.and("uuid", volumeSearchBuilder.entity().getUuid(), SearchCriteria.Op.NNULL); volumeSearchBuilder.and("instanceId", volumeSearchBuilder.entity().getInstanceId(), SearchCriteria.Op.EQ); volumeSearchBuilder.and("dataCenterId", volumeSearchBuilder.entity().getDataCenterId(), SearchCriteria.Op.EQ); +<<<<<<< HEAD +======= if (cmd.isEncrypted() != null) { if (cmd.isEncrypted()) { volumeSearchBuilder.and("encryptFormat", volumeSearchBuilder.entity().getEncryptFormat(), SearchCriteria.Op.NNULL); @@ -2452,6 +2466,7 @@ private Pair, Integer> searchForVolumeIdsAndCount(ListVolumesCmd cmd) volumeSearchBuilder.and("encryptFormat", volumeSearchBuilder.entity().getEncryptFormat(), SearchCriteria.Op.NULL); } } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (keyword != null) { volumeSearchBuilder.and().op("keywordName", volumeSearchBuilder.entity().getName(), SearchCriteria.Op.LIKE); @@ -2555,8 +2570,13 @@ private Pair, Integer> searchForVolumeIdsAndCount(ListVolumesCmd cmd) } } +<<<<<<< HEAD + if (diskOffId != null) { + sc.setParameters("diskOfferingId", diskOffId); +======= if (diskOfferingId != null) { sc.setParameters("diskOfferingId", diskOfferingId); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } if (id != null) { @@ -4683,12 +4703,17 @@ private Pair, Integer> templateChecks(boolean isIso, List scc = _templateJoinDao.createSearchCriteria(); scc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); scc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%"); sc.addAnd("name", SearchCriteria.Op.SC, scc); } if (name != null) { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 sc.addAnd("name", SearchCriteria.Op.EQ, name); } @@ -5737,6 +5762,10 @@ public String getConfigComponentName() { @Override public ConfigKey[] getConfigKeys() { return new ConfigKey[] {AllowUserViewDestroyedVM, UserVMDeniedDetails, UserVMReadOnlyDetails, SortKeyAscending, +<<<<<<< HEAD + AllowUserViewAllDomainAccounts, SharePublicTemplatesWithOtherDomains}; +======= AllowUserViewAllDomainAccounts, SharePublicTemplatesWithOtherDomains, ReturnVmStatsOnVmList}; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } diff --git a/server/src/main/java/com/cloud/api/query/ViewResponseHelper.java b/server/src/main/java/com/cloud/api/query/ViewResponseHelper.java index 06bfbadda7ac..5e760fc09468 100644 --- a/server/src/main/java/com/cloud/api/query/ViewResponseHelper.java +++ b/server/src/main/java/com/cloud/api/query/ViewResponseHelper.java @@ -167,7 +167,10 @@ public static List createUserVmResponse(ResponseView view, Strin // update nics, securitygroups, tags, affinitygroups for 1 to many mapping fields userVmData = ApiDBUtils.fillVmDetails(view, userVmData, userVm); } +<<<<<<< HEAD +======= userVmData.setIpAddress(userVmData.getNics()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 vmDataList.put(userVm.getId(), userVmData); } return new ArrayList(vmDataList.values()); diff --git a/server/src/main/java/com/cloud/api/query/dao/VolumeJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/VolumeJoinDaoImpl.java index abd5eca3389d..2663b5dfdda2 100644 --- a/server/src/main/java/com/cloud/api/query/dao/VolumeJoinDaoImpl.java +++ b/server/src/main/java/com/cloud/api/query/dao/VolumeJoinDaoImpl.java @@ -178,7 +178,10 @@ public VolumeResponse newVolumeResponse(ResponseView view, VolumeJoinVO volume) if (view == ResponseView.Full) { volResponse.setPath(volume.getPath()); +<<<<<<< HEAD +======= volResponse.setEncryptionFormat(volume.getEncryptionFormat()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } // populate owner. @@ -277,7 +280,10 @@ public VolumeResponse newVolumeResponse(ResponseView view, VolumeJoinVO volume) volResponse.setObjectName("volume"); volResponse.setExternalUuid(volume.getExternalUuid()); +<<<<<<< HEAD +======= volResponse.setEncryptionFormat(volume.getEncryptionFormat()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return volResponse; } diff --git a/server/src/main/java/com/cloud/api/query/vo/VolumeJoinVO.java b/server/src/main/java/com/cloud/api/query/vo/VolumeJoinVO.java index 79f558a3ef50..a38a0dc76873 100644 --- a/server/src/main/java/com/cloud/api/query/vo/VolumeJoinVO.java +++ b/server/src/main/java/com/cloud/api/query/vo/VolumeJoinVO.java @@ -277,9 +277,12 @@ public class VolumeJoinVO extends BaseViewWithTagInformationVO implements Contro @Column(name = "external_uuid") private String externalUuid = null; +<<<<<<< HEAD +======= @Column(name = "encrypt_format") private String encryptionFormat = null; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public VolumeJoinVO() { } @@ -615,12 +618,19 @@ public void setExternalUuid(String externalUuid) { this.externalUuid = externalUuid; } +<<<<<<< HEAD +======= public String getEncryptionFormat() { return encryptionFormat; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Override public Class getEntityType() { return Volume.class; } +<<<<<<< HEAD + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/server/src/main/java/com/cloud/configuration/Config.java b/server/src/main/java/com/cloud/configuration/Config.java index 675e0ee56448..a0c23ef54364 100644 --- a/server/src/main/java/com/cloud/configuration/Config.java +++ b/server/src/main/java/com/cloud/configuration/Config.java @@ -78,6 +78,10 @@ public enum Config { "30000", "Socket I/O timeout value in milliseconds. -1 for infinite timeout.", null), +<<<<<<< HEAD + AlertSMTPUseAuth("Alert", ManagementServer.class, String.class, "alert.smtp.useAuth", null, "If true, use SMTP authentication when sending emails.", null), +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 AlertSMTPUsername( "Alert", ManagementServer.class, @@ -1546,6 +1550,17 @@ public enum Config { "Password for SMTP authentication (applies only if project.smtp.useAuth is true)", null), ProjectSMTPPort("Project Defaults", ManagementServer.class, Integer.class, "project.smtp.port", "465", "Port the SMTP server is listening on", null), +<<<<<<< HEAD + ProjectSMTPUseAuth( + "Project Defaults", + ManagementServer.class, + String.class, + "project.smtp.useAuth", + null, + "If true, use SMTP authentication when sending emails", + null), +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ProjectSMTPUsername( "Project Defaults", ManagementServer.class, diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java index e6f1eb018ce5..4b0897ec416c 100644 --- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java @@ -3280,9 +3280,16 @@ protected ServiceOfferingVO createServiceOffering(final long userId, final boole DiskOfferingVO diskOffering = null; if (diskOfferingId == null) { +<<<<<<< HEAD + diskOffering = createDiskOfferingInternal(userId, isSystem, vmType, + name, cpu, ramSize, speed, displayText, typedProvisioningType, localStorageRequired, + offerHA, limitResourceUse, volatileVm, tags, domainIds, zoneIds, hostTag, + networkRate, deploymentPlanner, details, rootDiskSizeInGiB, isCustomizedIops, minIops, maxIops, +======= diskOffering = createDiskOfferingInternal( name, displayText, typedProvisioningType, localStorageRequired, tags, details, rootDiskSizeInGiB, isCustomizedIops, minIops, maxIops, +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 bytesReadRate, bytesReadRateMax, bytesReadRateMaxLength, bytesWriteRate, bytesWriteRateMax, bytesWriteRateMaxLength, iopsReadRate, iopsReadRateMax, iopsReadRateMaxLength, @@ -3290,10 +3297,13 @@ protected ServiceOfferingVO createServiceOffering(final long userId, final boole hypervisorSnapshotReserve, cacheMode, storagePolicyID, encryptRoot); } else { diskOffering = _diskOfferingDao.findById(diskOfferingId); +<<<<<<< HEAD +======= String diskStoragePolicyId = diskOfferingDetailsDao.getDetail(diskOfferingId, ApiConstants.STORAGE_POLICY); if (storagePolicyID != null && diskStoragePolicyId != null) { throw new InvalidParameterValueException("Storage policy cannot be defined on both compute and disk offering"); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } if (diskOffering != null) { serviceOffering.setDiskOfferingId(diskOffering.getId()); @@ -3333,8 +3343,15 @@ public void validateExtraConfigInServiceOfferingDetail(String detailName) { } } +<<<<<<< HEAD + private DiskOfferingVO createDiskOfferingInternal(final long userId, final boolean isSystem, final VirtualMachine.Type vmType, + final String name, final Integer cpu, final Integer ramSize, final Integer speed, final String displayText, final ProvisioningType typedProvisioningType, final boolean localStorageRequired, + final boolean offerHA, final boolean limitResourceUse, final boolean volatileVm, String tags, final List domainIds, List zoneIds, final String hostTag, + final Integer networkRate, final String deploymentPlanner, final Map details, Long rootDiskSizeInGiB, final Boolean isCustomizedIops, Long minIops, Long maxIops, +======= private DiskOfferingVO createDiskOfferingInternal(final String name, final String displayText, final ProvisioningType typedProvisioningType, final boolean localStorageRequired, String tags, final Map details, Long rootDiskSizeInGiB, final Boolean isCustomizedIops, Long minIops, Long maxIops, +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Long bytesReadRate, Long bytesReadRateMax, Long bytesReadRateMaxLength, Long bytesWriteRate, Long bytesWriteRateMax, Long bytesWriteRateMaxLength, Long iopsReadRate, Long iopsReadRateMax, Long iopsReadRateMaxLength, @@ -3395,8 +3412,13 @@ private DiskOfferingVO createDiskOfferingInternal(final String name, final Strin diskOffering.setHypervisorSnapshotReserve(hypervisorSnapshotReserve); if ((diskOffering = _diskOfferingDao.persist(diskOffering)) != null) { +<<<<<<< HEAD + if (details != null && !details.isEmpty()) { + List diskDetailsVO = new ArrayList(); +======= if ((details != null && !details.isEmpty()) || (storagePolicyID != null)) { List diskDetailsVO = new ArrayList<>(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 // Support disk offering details for below parameters if (details.containsKey(Volume.BANDWIDTH_LIMIT_IN_MBPS)) { diskDetailsVO.add(new DiskOfferingDetailVO(diskOffering.getId(), Volume.BANDWIDTH_LIMIT_IN_MBPS, details.get(Volume.BANDWIDTH_LIMIT_IN_MBPS), false)); @@ -3404,11 +3426,14 @@ private DiskOfferingVO createDiskOfferingInternal(final String name, final Strin if (details.containsKey(Volume.IOPS_LIMIT)) { diskDetailsVO.add(new DiskOfferingDetailVO(diskOffering.getId(), Volume.IOPS_LIMIT, details.get(Volume.IOPS_LIMIT), false)); } +<<<<<<< HEAD +======= if (storagePolicyID != null) { diskDetailsVO.add(new DiskOfferingDetailVO(diskOffering.getId(), ApiConstants.STORAGE_POLICY, String.valueOf(storagePolicyID), false)); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (!diskDetailsVO.isEmpty()) { diskOfferingDetailsDao.saveDetails(diskDetailsVO); } diff --git a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java index 22670c52449b..a3aa2d007db2 100644 --- a/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/main/java/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -458,9 +458,16 @@ private DeployDestination deployInVmLastHost(VirtualMachineProfile vmProfile, De DeploymentPlanner planner, VirtualMachine vm, DataCenter dc, ServiceOffering offering, int cpuRequested, long ramRequested, boolean volumesRequireEncryption) throws InsufficientServerCapacityException { HostVO host = _hostDao.findById(vm.getLastHostId()); +<<<<<<< HEAD + _hostDao.loadHostTags(host); + _hostDao.loadDetails(host); + + if (canUseLastHost(host, avoids, plan, vm, offering, volumesRequireEncryption)) { +======= if (canUseLastHost(host, avoids, plan, vm, offering, volumesRequireEncryption)) { _hostDao.loadHostTags(host); _hostDao.loadDetails(host); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (host.getStatus() != Status.Up) { logger.debug("Cannot deploy VM [{}] to the last host [{}] because this host is not in UP state or is not enabled. Host current status [{}] and resource status [{}].", vm.getUuid(), host.getUuid(), host.getState().name(), host.getResourceState()); diff --git a/server/src/main/java/com/cloud/event/ActionEventInterceptor.java b/server/src/main/java/com/cloud/event/ActionEventInterceptor.java index ee025c825f50..b1d3a3e86097 100644 --- a/server/src/main/java/com/cloud/event/ActionEventInterceptor.java +++ b/server/src/main/java/com/cloud/event/ActionEventInterceptor.java @@ -70,7 +70,11 @@ public Object interceptStart(Method method, Object target) { if (async) { CallContext ctx = CallContext.current(); +<<<<<<< HEAD + String eventDescription = getEventDescription(actionEvent, ctx); +======= String eventDescription = getEventDescription(actionEvent, ctx, true); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Long eventResourceId = getEventResourceId(actionEvent, ctx); String eventResourceType = getEventResourceType(actionEvent, ctx); String eventType = getEventType(actionEvent, ctx); @@ -183,11 +187,25 @@ protected String getEventType(ActionEvent actionEvent, CallContext ctx) { return type == null ? actionEvent.eventType() : type; } +<<<<<<< HEAD + protected String getEventDescription(ActionEvent actionEvent, CallContext ctx) { +======= protected String getEventDescription(ActionEvent actionEvent, CallContext ctx, boolean capitalizeFirstLetter) { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 String eventDescription = ctx.getEventDescription(); if (eventDescription == null) { eventDescription = actionEvent.eventDescription(); } +<<<<<<< HEAD + + if (ctx.getEventDetails() != null) { + eventDescription += ". " + ctx.getEventDetails(); + } + + return eventDescription; + } + +======= if (ctx.getEventDetails() != null) { eventDescription += ". " + ctx.getEventDetails(); } @@ -201,6 +219,7 @@ protected String getEventDescription(ActionEvent actionEvent, CallContext ctx) { return getEventDescription(actionEvent, ctx, false); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 protected Long getEventResourceId(ActionEvent actionEvent, CallContext ctx) { Long resourceId = ctx.getEventResourceId(); if (resourceId != null) { diff --git a/server/src/main/java/com/cloud/event/ActionEventUtils.java b/server/src/main/java/com/cloud/event/ActionEventUtils.java index d625aaca466f..3ca3cadbbe7c 100644 --- a/server/src/main/java/com/cloud/event/ActionEventUtils.java +++ b/server/src/main/java/com/cloud/event/ActionEventUtils.java @@ -32,11 +32,20 @@ import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +<<<<<<< HEAD +import org.apache.cloudstack.framework.events.EventBus; +import org.apache.cloudstack.framework.events.EventBusException; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +======= import org.apache.cloudstack.framework.events.EventDistributor; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.springframework.beans.factory.NoSuchBeanDefinitionException; import com.cloud.configuration.Config; @@ -62,7 +71,11 @@ public class ActionEventUtils { private static AccountDao s_accountDao; private static ProjectDao s_projectDao; protected static UserDao s_userDao; +<<<<<<< HEAD + protected static EventBus s_eventBus = null; +======= private static EventDistributor eventDistributor; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 protected static EntityManager s_entityMgr; protected static ConfigurationDao s_configDao; @@ -100,10 +113,15 @@ void init() { public static Long onActionEvent(Long userId, Long accountId, Long domainId, String type, String description, Long resourceId, String resourceType) { Ternary resourceDetails = getResourceDetails(resourceId, resourceType, type); +<<<<<<< HEAD + publishOnEventBus(userId, accountId, EventCategory.ACTION_EVENT.getName(), type, com.cloud.event.Event.State.Completed, description, resourceDetails.second(), resourceDetails.third()); + Event event = persistActionEvent(userId, accountId, domainId, null, type, Event.State.Completed, true, description, resourceDetails.first(), resourceDetails.third(), null); +======= Event event = persistActionEvent(userId, accountId, domainId, null, type, Event.State.Completed, true, description, resourceDetails.first(), resourceDetails.third(), null); publishOnEventBus(event, userId, accountId, domainId, EventCategory.ACTION_EVENT.getName(), type, com.cloud.event.Event.State.Completed, description, resourceDetails.second(), resourceDetails.third()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return event.getId(); } @@ -112,10 +130,15 @@ public static Long onActionEvent(Long userId, Long accountId, Long domainId, Str */ public static Long onScheduledActionEvent(Long userId, Long accountId, String type, String description, Long resourceId, String resourceType, boolean eventDisplayEnabled, long startEventId) { Ternary resourceDetails = getResourceDetails(resourceId, resourceType, type); +<<<<<<< HEAD + publishOnEventBus(userId, accountId, EventCategory.ACTION_EVENT.getName(), type, com.cloud.event.Event.State.Scheduled, description, resourceDetails.second(), resourceDetails.third()); + Event event = persistActionEvent(userId, accountId, null, null, type, Event.State.Scheduled, eventDisplayEnabled, description, resourceDetails.first(), resourceDetails.third(), startEventId); +======= Event event = persistActionEvent(userId, accountId, null, null, type, Event.State.Scheduled, eventDisplayEnabled, description, resourceDetails.first(), resourceDetails.third(), startEventId); publishOnEventBus(event, userId, accountId, EventCategory.ACTION_EVENT.getName(), type, com.cloud.event.Event.State.Scheduled, description, resourceDetails.second(), resourceDetails.third()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return event.getId(); } @@ -139,10 +162,15 @@ public static void onStartedActionEventFromContext(String eventType, String even */ public static Long onStartedActionEvent(Long userId, Long accountId, String type, String description, Long resourceId, String resourceType, boolean eventDisplayEnabled, long startEventId) { Ternary resourceDetails = getResourceDetails(resourceId, resourceType, type); +<<<<<<< HEAD + publishOnEventBus(userId, accountId, EventCategory.ACTION_EVENT.getName(), type, com.cloud.event.Event.State.Started, description, resourceDetails.second(), resourceDetails.third()); + Event event = persistActionEvent(userId, accountId, null, null, type, Event.State.Started, eventDisplayEnabled, description, resourceDetails.first(), resourceDetails.third(), startEventId); +======= Event event = persistActionEvent(userId, accountId, null, null, type, Event.State.Started, eventDisplayEnabled, description, resourceDetails.first(), resourceDetails.third(), startEventId); publishOnEventBus(event, userId, accountId, EventCategory.ACTION_EVENT.getName(), type, com.cloud.event.Event.State.Started, description, resourceDetails.second(), resourceDetails.third()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return event.getId(); } @@ -153,20 +181,30 @@ public static Long onCompletedActionEvent(Long userId, Long accountId, String le public static Long onCompletedActionEvent(Long userId, Long accountId, String level, String type, boolean eventDisplayEnabled, String description, Long resourceId, String resourceType, long startEventId) { Ternary resourceDetails = getResourceDetails(resourceId, resourceType, type); +<<<<<<< HEAD + publishOnEventBus(userId, accountId, EventCategory.ACTION_EVENT.getName(), type, com.cloud.event.Event.State.Completed, description, resourceDetails.second(), resourceDetails.third()); + Event event = persistActionEvent(userId, accountId, null, level, type, Event.State.Completed, eventDisplayEnabled, description, resourceDetails.first(), resourceDetails.third(), startEventId); +======= Event event = persistActionEvent(userId, accountId, null, level, type, Event.State.Completed, eventDisplayEnabled, description, resourceDetails.first(), resourceDetails.third(), startEventId); publishOnEventBus(event, userId, accountId, EventCategory.ACTION_EVENT.getName(), type, com.cloud.event.Event.State.Completed, description, resourceDetails.second(), resourceDetails.third()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return event.getId(); } public static Long onCreatedActionEvent(Long userId, Long accountId, String level, String type, boolean eventDisplayEnabled, String description, Long resourceId, String resourceType) { Ternary resourceDetails = getResourceDetails(resourceId, resourceType, type); +<<<<<<< HEAD + publishOnEventBus(userId, accountId, EventCategory.ACTION_EVENT.getName(), type, com.cloud.event.Event.State.Created, description, resourceDetails.second(), resourceDetails.third()); + Event event = persistActionEvent(userId, accountId, null, level, type, Event.State.Created, eventDisplayEnabled, description, resourceDetails.first(), resourceDetails.third(), null); +======= Event event = persistActionEvent(userId, accountId, null, level, type, Event.State.Created, eventDisplayEnabled, description, resourceDetails.first(), resourceDetails.third(), null); publishOnEventBus(event, userId, accountId, EventCategory.ACTION_EVENT.getName(), type, com.cloud.event.Event.State.Created, description, resourceDetails.second(), resourceDetails.third()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return event.getId(); } @@ -202,25 +240,38 @@ private static Event persistActionEvent(Long userId, Long accountId, Long domain return event; } +<<<<<<< HEAD + private static void publishOnEventBus(long userId, long accountId, String eventCategory, String eventType, Event.State state, String description, String resourceUuid, String resourceType) { +======= private static void publishOnEventBus(Event eventRecord, long userId, long accountId, Long domainId, String eventCategory, String eventType, Event.State state, String description, String resourceUuid, String resourceType) { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 String configKey = Config.PublishActionEvent.key(); String value = s_configDao.getValue(configKey); boolean configValue = Boolean.parseBoolean(value); if(!configValue) return; +<<<<<<< HEAD + try { + s_eventBus = ComponentContext.getComponent(EventBus.class); +======= try { eventDistributor = ComponentContext.getComponent(EventDistributor.class); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } catch (NoSuchBeanDefinitionException nbe) { return; // no provider is configured to provide events bus, so just return } org.apache.cloudstack.framework.events.Event event = +<<<<<<< HEAD + new org.apache.cloudstack.framework.events.Event(ManagementService.Name, eventCategory, eventType, resourceType, resourceUuid); +======= new org.apache.cloudstack.framework.events.Event(ManagementService.Name, eventCategory, eventType, resourceType, resourceUuid); event.setEventId(eventRecord.getId()); event.setEventUuid(eventRecord.getUuid()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Map eventDescription = new HashMap(); Project project = s_projectDao.findByProjectAccountId(accountId); @@ -233,9 +284,12 @@ private static void publishOnEventBus(Event eventRecord, long userId, long accou return; if (project != null) eventDescription.put("project", project.getUuid()); +<<<<<<< HEAD +======= event.setResourceAccountId(accountId); event.setResourceAccountUuid(account.getUuid()); event.setResourceDomainId(domainId == null ? account.getDomainId() : domainId); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 eventDescription.put("user", user.getUuid()); eventDescription.put("account", account.getUuid()); eventDescription.put("event", eventType); @@ -251,6 +305,13 @@ private static void publishOnEventBus(Event eventRecord, long userId, long accou event.setDescription(eventDescription); +<<<<<<< HEAD + try { + s_eventBus.publish(event); + } catch (EventBusException e) { + LOGGER.warn("Failed to publish action event on the event bus."); + } +======= eventDistributor.publish(event); } @@ -258,6 +319,7 @@ private static void publishOnEventBus(Event event, long userId, long accountId, String eventType, Event.State state, String description, String resourceUuid, String resourceType) { publishOnEventBus(event, userId, accountId, null, eventCategory, eventType, state, description, resourceUuid, resourceType); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } private static Ternary getResourceDetailsUsingEntityClassAndContext(Class entityClass, ApiCommandResourceType resourceType) { diff --git a/server/src/main/java/com/cloud/event/AlertGenerator.java b/server/src/main/java/com/cloud/event/AlertGenerator.java index f1b23e873082..5f01cb504aed 100644 --- a/server/src/main/java/com/cloud/event/AlertGenerator.java +++ b/server/src/main/java/com/cloud/event/AlertGenerator.java @@ -25,6 +25,17 @@ import javax.annotation.PostConstruct; import javax.inject.Inject; +<<<<<<< HEAD +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.stereotype.Component; + +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.framework.events.EventBus; +import org.apache.cloudstack.framework.events.EventBusException; + +======= import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.events.EventDistributor; import org.apache.logging.log4j.LogManager; @@ -32,6 +43,7 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.stereotype.Component; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.configuration.Config; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; @@ -46,8 +58,13 @@ public class AlertGenerator { protected static Logger LOGGER = LogManager.getLogger(AlertGenerator.class); private static DataCenterDao s_dcDao; private static HostPodDao s_podDao; +<<<<<<< HEAD + protected static EventBus s_eventBus = null; + protected static ConfigurationDao s_configDao; +======= protected static ConfigurationDao s_configDao; protected static EventDistributor eventDistributor; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Inject DataCenterDao dcDao; @@ -74,9 +91,15 @@ public static void publishAlertOnEventBus(String alertType, long dataCenterId, L if(!configValue) return; try { +<<<<<<< HEAD + s_eventBus = ComponentContext.getComponent(EventBus.class); + } catch (NoSuchBeanDefinitionException nbe) { + return; // no provider is configured to provide events bus, so just return +======= eventDistributor = ComponentContext.getComponent(EventDistributor.class); } catch (NoSuchBeanDefinitionException nbe) { return; // no provider is configured to provide events distributor, so just return +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } org.apache.cloudstack.framework.events.Event event = @@ -105,6 +128,14 @@ public static void publishAlertOnEventBus(String alertType, long dataCenterId, L event.setDescription(eventDescription); +<<<<<<< HEAD + try { + s_eventBus.publish(event); + } catch (EventBusException e) { + LOGGER.warn("Failed to publish alert on the event bus."); + } +======= eventDistributor.publish(event); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } diff --git a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java index 0a55f75bbbd5..e435e3a693b3 100644 --- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java @@ -205,7 +205,10 @@ import com.cloud.projects.ProjectManager; import com.cloud.server.ResourceTag; import com.cloud.server.ResourceTag.ResourceObjectType; +<<<<<<< HEAD +======= import com.cloud.service.ServiceOfferingVO; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.tags.ResourceTagVO; import com.cloud.tags.dao.ResourceTagDao; import com.cloud.user.Account; @@ -261,6 +264,10 @@ import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; import com.googlecode.ipv6.IPv6Address; +<<<<<<< HEAD +import com.cloud.service.ServiceOfferingVO; +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 /** * NetworkServiceImpl implements NetworkService. @@ -1756,6 +1763,8 @@ private void validateNetworkCreationSupported(long zoneId, String zoneName, Gues } } +<<<<<<< HEAD +======= @Override @DB @ActionEvent(eventType = EventTypes.EVENT_NETWORK_CREATE, eventDescription = "creating network") @@ -1768,6 +1777,7 @@ public Network createGuestNetwork(long networkOfferingId, String name, String di null, null, null, null, null, null, null, null, null); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 void checkAndSetRouterSourceNatIp(Account owner, CreateNetworkCmd cmd, Network network) throws InsufficientAddressCapacityException, ResourceAllocationException { String sourceNatIp = cmd.getSourceNatIP(); if (sourceNatIp == null) { 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 7114bbbd90d0..076c0b801136 100644 --- a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java @@ -1780,6 +1780,8 @@ public boolean startVpc(final long vpcId, final boolean destroyOnFailure) throws return result; } +<<<<<<< HEAD +======= @Override @ActionEvent(eventType = EventTypes.EVENT_VPC_CREATE, eventDescription = "creating vpc", async = true) @@ -1791,6 +1793,7 @@ public void startVpc(final CreateVPCCmd cmd) throws ConcurrentOperationException startVpc(cmd.getEntityId(), true); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 protected boolean startVpc(final Vpc vpc, final DeployDestination dest, final ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { // deploy provider diff --git a/server/src/main/java/com/cloud/projects/ProjectManager.java b/server/src/main/java/com/cloud/projects/ProjectManager.java index 123284955fa9..0733cd3d97e1 100644 --- a/server/src/main/java/com/cloud/projects/ProjectManager.java +++ b/server/src/main/java/com/cloud/projects/ProjectManager.java @@ -22,6 +22,13 @@ import org.apache.cloudstack.framework.config.ConfigKey; public interface ProjectManager extends ProjectService { +<<<<<<< HEAD + public static final ConfigKey ProjectSmtpUseStartTLS = new ConfigKey("Advanced", Boolean.class, "project.smtp.useStartTLS", "false", + "If set to true and if we enable security via project.smtp.useAuth, this will enable StartTLS to secure the connection.", true); + + public static final ConfigKey ProjectSmtpEnabledSecurityProtocols = new ConfigKey("Advanced", String.class, "project.smtp.enabledSecurityProtocols", "", + "White-space separated security protocols; ex: \"TLSv1 TLSv1.1\". Supported protocols: SSLv2Hello, SSLv3, TLSv1, TLSv1.1 and TLSv1.2", true); +======= public static final ConfigKey ProjectSmtpUseStartTLS = new ConfigKey(ConfigKey.CATEGORY_ADVANCED, Boolean.class, "project.smtp.useStartTLS", "false", "If set to true and if we enable security via project.smtp.useAuth, this will enable StartTLS to secure the connection.", true); @@ -30,6 +37,7 @@ public interface ProjectManager extends ProjectService { public static final ConfigKey ProjectSmtpUseAuth = new ConfigKey<>(ConfigKey.CATEGORY_ADVANCED, Boolean.class, "project.smtp.useAuth", "false", "If true, use SMTP authentication when sending emails", false, ConfigKey.Scope.ManagementServer); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 boolean canAccessProjectAccount(Account caller, long accountId); diff --git a/server/src/main/java/com/cloud/projects/ProjectManagerImpl.java b/server/src/main/java/com/cloud/projects/ProjectManagerImpl.java index fb0adda9baf2..141b713175d5 100644 --- a/server/src/main/java/com/cloud/projects/ProjectManagerImpl.java +++ b/server/src/main/java/com/cloud/projects/ProjectManagerImpl.java @@ -18,7 +18,10 @@ import java.io.UnsupportedEncodingException; import java.security.SecureRandom; +<<<<<<< HEAD +======= import java.util.ArrayList; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import java.util.HashSet; import java.util.List; import java.util.Map; @@ -36,7 +39,10 @@ import javax.mail.MessagingException; import javax.naming.ConfigurationException; +<<<<<<< HEAD +======= import org.apache.cloudstack.acl.ControlledEntity; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.acl.ProjectRole; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.acl.dao.ProjectRoleDao; @@ -50,9 +56,13 @@ import org.apache.cloudstack.utils.mailing.MailAddress; import org.apache.cloudstack.utils.mailing.SMTPMailProperties; import org.apache.cloudstack.utils.mailing.SMTPMailSender; +<<<<<<< HEAD +import org.apache.commons.lang3.BooleanUtils; +======= import org.apache.cloudstack.webhook.WebhookHelper; import org.apache.commons.lang3.BooleanUtils; import org.springframework.beans.factory.NoSuchBeanDefinitionException; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.springframework.stereotype.Component; import com.cloud.api.ApiDBUtils; @@ -93,7 +103,10 @@ import com.cloud.user.User; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserDao; +<<<<<<< HEAD +======= import com.cloud.utils.component.ComponentContext; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; @@ -168,6 +181,8 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager, C private String senderAddress; protected SMTPMailSender mailSender; +<<<<<<< HEAD +======= protected List listWebhooksForProject(Project project) { List webhooks = new ArrayList<>(); try { @@ -179,6 +194,7 @@ protected List listWebhooksForProject(Project projec return webhooks; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Override public boolean configure(final String name, final Map params) throws ConfigurationException { @@ -355,9 +371,14 @@ public boolean deleteProject(long projectId, Boolean isCleanup) { List volumes = _volumeDao.findDetachedByAccount(project.getProjectAccountId()); List networks = _networkDao.listByOwner(project.getProjectAccountId()); List vpcs = _vpcMgr.getVpcsForAccount(project.getProjectAccountId()); +<<<<<<< HEAD + + Optional message = Stream.of(userTemplates, vmSnapshots, vms, volumes, networks, vpcs) +======= List webhooks = listWebhooksForProject(project); Optional message = Stream.of(userTemplates, vmSnapshots, vms, volumes, networks, vpcs, webhooks) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 .filter(entity -> !entity.isEmpty()) .map(entity -> entity.size() + " " + entity.get(0).getEntityType().getSimpleName() + " to clean up") .findFirst(); @@ -1451,7 +1472,11 @@ public String getConfigComponentName() { @Override public ConfigKey[] getConfigKeys() { +<<<<<<< HEAD + return new ConfigKey[] {ProjectSmtpEnabledSecurityProtocols, ProjectSmtpUseStartTLS}; +======= return new ConfigKey[] {ProjectSmtpEnabledSecurityProtocols, ProjectSmtpUseStartTLS, ProjectSmtpUseAuth}; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } protected void updateProjectNameAndDisplayText(final ProjectVO project, String name, String displayText) { diff --git a/server/src/main/java/com/cloud/resourcelimit/CheckedReservation.java b/server/src/main/java/com/cloud/resourcelimit/CheckedReservation.java index d66e1eb912ad..172800b4b59c 100644 --- a/server/src/main/java/com/cloud/resourcelimit/CheckedReservation.java +++ b/server/src/main/java/com/cloud/resourcelimit/CheckedReservation.java @@ -62,6 +62,14 @@ public static String getResourceReservationContextParameterKey(final ResourceTyp return String.format("%s-%s", ResourceReservation.class.getSimpleName(), type.getName()); } +<<<<<<< HEAD + protected void checkLimitAndPersistReservations(Account account, ResourceType resourceType, Long resourceId, List resourceLimitTags, Long amount) throws ResourceAllocationException { + checkLimitAndPersistReservation(account, resourceType, resourceId, null, amount); + if (CollectionUtils.isNotEmpty(resourceLimitTags)) { + for (String tag : resourceLimitTags) { + checkLimitAndPersistReservation(account, resourceType, resourceId, tag, amount); + } +======= private void removeAllReservations() { if (CollectionUtils.isEmpty(reservations)) { return; @@ -84,6 +92,7 @@ protected void checkLimitAndPersistReservations(Account account, ResourceType re } catch (ResourceAllocationException rae) { removeAllReservations(); throw rae; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } @@ -163,7 +172,18 @@ protected void setQuotaLimitLock(GlobalLock quotaLimitLock) { @Override public void close() throws Exception { +<<<<<<< HEAD + if (CollectionUtils.isEmpty(reservations)) { + return; + } + CallContext.current().removeContextParameter(getContextParameterKey()); + for (ResourceReservation reservation : reservations) { + reservationDao.remove(reservation.getId()); + } + reservations = null; +======= removeAllReservations(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } public Account getAccount() { diff --git a/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index 435604d83ba5..b4a29fc697d2 100644 --- a/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/main/java/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -20,7 +20,10 @@ import java.util.ArrayList; import java.util.Arrays; +<<<<<<< HEAD +======= import java.util.Date; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -220,6 +223,10 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws CloudR }); } +<<<<<<< HEAD + @Override + public boolean start() { +======= private void cleanupResourceReservationsForMs() { int reservationsRemoved = reservationDao.removeByMsId(ManagementServerNode.getManagementServerId()); if (reservationsRemoved > 0) { @@ -230,6 +237,7 @@ private void cleanupResourceReservationsForMs() { @Override public boolean start() { cleanupResourceReservationsForMs(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (ResourceCountCheckInterval.value() >= 0) { ConfigKeyScheduledExecutionWrapper runner = new ConfigKeyScheduledExecutionWrapper(_rcExecutor, new ResourceCountCheckTask(), ResourceCountCheckInterval, TimeUnit.SECONDS); runner.start(); @@ -239,10 +247,13 @@ public boolean start() { @Override public boolean stop() { +<<<<<<< HEAD +======= if (_rcExecutor != null) { _rcExecutor.shutdown(); } cleanupResourceReservationsForMs(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return true; } @@ -1213,6 +1224,10 @@ protected long recalculateDomainResourceCount(final long domainId, final Resourc }); } +<<<<<<< HEAD + @DB + protected long recalculateAccountResourceCount(final long accountId, final ResourceType type, String tag) { +======= protected void cleanupStaleResourceReservations(final long accountId, final ResourceType type, String tag) { Long delay = ResourceReservationCleanupDelay.value(); if (delay == null || delay <= 0) { @@ -1229,6 +1244,7 @@ protected void cleanupStaleResourceReservations(final long accountId, final Reso @DB protected long recalculateAccountResourceCount(final long accountId, final ResourceType type, String tag) { cleanupStaleResourceReservations(accountId, type, tag); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 final Long newCount; if (type == Resource.ResourceType.user_vm) { newCount = calculateVmCountForAccount(accountId, tag); @@ -2133,7 +2149,10 @@ public String getConfigComponentName() { public ConfigKey[] getConfigKeys() { return new ConfigKey[] { ResourceCountCheckInterval, +<<<<<<< HEAD +======= ResourceReservationCleanupDelay, +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 MaxAccountSecondaryStorage, MaxProjectSecondaryStorage, ResourceLimitHostTags, diff --git a/server/src/main/java/com/cloud/server/StatsCollector.java b/server/src/main/java/com/cloud/server/StatsCollector.java index 2c8b79500bac..f3cfdb9dc79d 100644 --- a/server/src/main/java/com/cloud/server/StatsCollector.java +++ b/server/src/main/java/com/cloud/server/StatsCollector.java @@ -276,9 +276,18 @@ public String toString() { private static final ConfigKey statsOutputUri = new ConfigKey<>("Advanced", String.class, "stats.output.uri", "", "URI to send StatsCollector statistics to. The collector is defined on the URI scheme. Example: graphite://graphite-hostaddress:port or influxdb://influxdb-hostaddress/dbname. Note that the port is optional, if not added the default port for the respective collector (graphite or influxdb) will be used. Additionally, the database name '/dbname' is also optional; default db name is 'cloudstack'. You must create and configure the database if using influxdb.", true); +<<<<<<< HEAD + protected static ConfigKey vmStatsIncrementMetrics = new ConfigKey<>("Advanced", Boolean.class, "vm.stats.increment.metrics", "true", + "When set to 'true', VM metrics(NetworkReadKBs, NetworkWriteKBs, DiskWriteKBs, DiskReadKBs, DiskReadIOs and DiskWriteIOs) that are collected from the hypervisor are summed before being returned." + + "On the other hand, when set to 'false', the VM metrics API will just display the latest metrics collected.", true); + private static final ConfigKey VM_STATS_INCREMENT_METRICS_IN_MEMORY = new ConfigKey<>("Advanced", Boolean.class, "vm.stats.increment.metrics.in.memory", "true", + "When set to 'true', VM metrics(NetworkReadKBs, NetworkWriteKBs, DiskWriteKBs, DiskReadKBs, DiskReadIOs and DiskWriteIOs) that are collected from the hypervisor are summed and stored in memory. " + + "On the other hand, when set to 'false', the VM metrics API will just display the latest metrics collected.", true); +======= protected static ConfigKey vmStatsIncrementMetrics = new ConfigKey<>("Advanced", Boolean.class, "vm.stats.increment.metrics", "false", "When set to 'true', VM metrics(NetworkReadKBs, NetworkWriteKBs, DiskWriteKBs, DiskReadKBs, DiskReadIOs and DiskWriteIOs) that are collected from the hypervisor are summed before being returned." + "On the other hand, when set to 'false', the VM metrics API will just display the latest metrics collected.", true); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 protected static ConfigKey vmStatsMaxRetentionTime = new ConfigKey<>("Advanced", Integer.class, "vm.stats.max.retention.time", "720", "The maximum time (in minutes) for keeping VM stats records in the database. The VM stats cleanup process will be disabled if this is set to 0 or less than 0.", true); @@ -2126,6 +2135,10 @@ public String getConfigComponentName() { public ConfigKey[] getConfigKeys() { return new ConfigKey[] {vmDiskStatsInterval, vmDiskStatsIntervalMin, vmNetworkStatsInterval, vmNetworkStatsIntervalMin, StatsTimeout, statsOutputUri, vmStatsIncrementMetrics, vmStatsMaxRetentionTime, vmStatsCollectUserVMOnly, vmDiskStatsRetentionEnabled, vmDiskStatsMaxRetentionTime, +<<<<<<< HEAD + VM_STATS_INCREMENT_METRICS_IN_MEMORY, +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 MANAGEMENT_SERVER_STATUS_COLLECTION_INTERVAL, DATABASE_SERVER_STATUS_COLLECTION_INTERVAL, DATABASE_SERVER_LOAD_HISTORY_RETENTION_NUMBER}; diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java index f3f0c5dc7e4a..00522d9c2c42 100644 --- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java @@ -1921,8 +1921,11 @@ public String getPrimaryStorageNameLabel(VolumeVO volume) { @Override @DB +<<<<<<< HEAD +======= @ActionEvent(eventType = EventTypes.EVENT_MAINTENANCE_PREPARE_PRIMARY_STORAGE, eventDescription = "preparing storage pool for maintenance", async = true) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public PrimaryDataStoreInfo preparePrimaryStorageForMaintenance(Long primaryStorageId) throws ResourceUnavailableException, InsufficientCapacityException { StoragePoolVO primaryStorage = null; primaryStorage = _storagePoolDao.findById(primaryStorageId); @@ -1991,8 +1994,11 @@ public void doInTransactionWithoutResult(TransactionStatus status) { @Override @DB +<<<<<<< HEAD +======= @ActionEvent(eventType = EventTypes.EVENT_MAINTENANCE_CANCEL_PRIMARY_STORAGE, eventDescription = "canceling maintenance for primary storage pool", async = true) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public PrimaryDataStoreInfo cancelPrimaryStorageForMaintenance(CancelPrimaryStorageMaintenanceCmd cmd) throws ResourceUnavailableException { Long primaryStorageId = cmd.getId(); StoragePoolVO primaryStorage = null; @@ -2897,9 +2903,24 @@ public boolean isStoragePoolCompliantWithStoragePolicy(List> answers = new ArrayList>(); for (Pair volumeDiskProfilePair : volumes) { +<<<<<<< HEAD + String storagePolicyId = null; + Volume volume = volumeDiskProfilePair.first(); + DiskProfile diskProfile = volumeDiskProfilePair.second(); + if (volume.getVolumeType() == Type.ROOT) { + Long vmId = volume.getInstanceId(); + if (vmId != null) { + VMInstanceVO vm = _vmInstanceDao.findByIdIncludingRemoved(vmId); + storagePolicyId = _serviceOfferingDetailsDao.getDetail(vm.getServiceOfferingId(), ApiConstants.STORAGE_POLICY); + } + } else { + storagePolicyId = _diskOfferingDetailsDao.getDetail(diskProfile.getDiskOfferingId(), ApiConstants.STORAGE_POLICY); + } +======= Volume volume = volumeDiskProfilePair.first(); DiskProfile diskProfile = volumeDiskProfilePair.second(); String storagePolicyId = _diskOfferingDetailsDao.getDetail(diskProfile.getDiskOfferingId(), ApiConstants.STORAGE_POLICY); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Answer answer = getCheckDatastorePolicyComplianceAnswer(storagePolicyId, pool); if (answer != null) { answers.add(new Pair<>(volume, answer)); diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java index 7dfc37379675..010bf844fa7c 100644 --- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java @@ -157,7 +157,10 @@ import com.cloud.org.Grouping; import com.cloud.projects.Project; import com.cloud.projects.ProjectManager; +<<<<<<< HEAD +======= import com.cloud.resource.ResourceManager; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.resource.ResourceState; import com.cloud.serializer.GsonHelper; import com.cloud.server.ManagementService; @@ -257,8 +260,11 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic @Inject private ConfigurationManager _configMgr; @Inject +<<<<<<< HEAD +======= private ResourceManager _resourceMgr; @Inject +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private VolumeDao _volsDao; @Inject private VolumeDetailsDao _volsDetailsDao; @@ -569,7 +575,11 @@ private boolean validateVolume(Account caller, long ownerId, Long zoneId, String _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(ownerId), ResourceType.secondary_storage); } +<<<<<<< HEAD + sanitizeFormat(format); +======= checkFormatWithSupportedHypervisorsInZone(format, zoneId); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 // Check that the disk offering specified is valid if (diskOfferingId != null) { @@ -585,6 +595,8 @@ private boolean validateVolume(Account caller, long ownerId, Long zoneId, String return false; } +<<<<<<< HEAD +======= private void checkFormatWithSupportedHypervisorsInZone(String format, Long zoneId) { ImageFormat imageformat = ImageFormat.valueOf(format); final List supportedHypervisorTypesInZone = _resourceMgr.getSupportedHypervisorTypes(zoneId, false, null); @@ -594,6 +606,7 @@ private void checkFormatWithSupportedHypervisorsInZone(String format, Long zoneI } } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public String getRandomVolumeName() { return UUID.randomUUID().toString(); } diff --git a/server/src/main/java/com/cloud/storage/listener/SnapshotStateListener.java b/server/src/main/java/com/cloud/storage/listener/SnapshotStateListener.java index 18ab4168c249..33fc42a52883 100644 --- a/server/src/main/java/com/cloud/storage/listener/SnapshotStateListener.java +++ b/server/src/main/java/com/cloud/storage/listener/SnapshotStateListener.java @@ -26,9 +26,17 @@ import javax.inject.Inject; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +<<<<<<< HEAD +import org.apache.cloudstack.framework.events.EventBus; +import org.apache.cloudstack.framework.events.EventBusException; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +======= import org.apache.cloudstack.framework.events.EventDistributor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.springframework.stereotype.Component; import com.cloud.configuration.Config; @@ -45,12 +53,19 @@ @Component public class SnapshotStateListener implements StateListener { +<<<<<<< HEAD + protected static EventBus s_eventBus = null; +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 protected static ConfigurationDao s_configDao; @Inject private ConfigurationDao configDao; +<<<<<<< HEAD +======= private EventDistributor eventDistributor = null; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 protected Logger logger = LogManager.getLogger(getClass()); public SnapshotStateListener() { @@ -62,10 +77,13 @@ void init() { s_configDao = configDao; } +<<<<<<< HEAD +======= public void setEventDistributor(EventDistributor eventDistributor) { this.eventDistributor = eventDistributor; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Override public boolean preStateTransitionEvent(State oldState, Event event, State newState, SnapshotVO vo, boolean status, Object opaque) { pubishOnEventBus(event.name(), "preStateTransitionEvent", vo, oldState, newState); @@ -86,15 +104,26 @@ private void pubishOnEventBus(String event, String status, Snapshot vo, State ol if(!configValue) { return; } +<<<<<<< HEAD + try { + s_eventBus = ComponentContext.getComponent(EventBus.class); + } catch (NoSuchBeanDefinitionException nbe) { + return; // no provider is configured to provide events bus, so just return +======= if (eventDistributor == null) { setEventDistributor(ComponentContext.getComponent(EventDistributor.class)); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } String resourceName = getEntityFromClassName(Snapshot.class.getName()); org.apache.cloudstack.framework.events.Event eventMsg = new org.apache.cloudstack.framework.events.Event(ManagementService.Name, EventCategory.RESOURCE_STATE_CHANGE_EVENT.getName(), event, resourceName, vo.getUuid()); +<<<<<<< HEAD + Map eventDescription = new HashMap(); +======= Map eventDescription = new HashMap<>(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 eventDescription.put("resource", resourceName); eventDescription.put("id", vo.getUuid()); eventDescription.put("old-state", oldState.name()); @@ -104,7 +133,15 @@ private void pubishOnEventBus(String event, String status, Snapshot vo, State ol eventDescription.put("eventDateTime", eventDate); eventMsg.setDescription(eventDescription); +<<<<<<< HEAD + try { + s_eventBus.publish(eventMsg); + } catch (EventBusException e) { + logger.warn("Failed to publish state change event on the event bus."); + } +======= eventDistributor.publish(eventMsg); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } private String getEntityFromClassName(String entityClassName) { diff --git a/server/src/main/java/com/cloud/storage/listener/VolumeStateListener.java b/server/src/main/java/com/cloud/storage/listener/VolumeStateListener.java index 961a7a7da43f..c654bd0cb61a 100644 --- a/server/src/main/java/com/cloud/storage/listener/VolumeStateListener.java +++ b/server/src/main/java/com/cloud/storage/listener/VolumeStateListener.java @@ -22,6 +22,24 @@ import java.util.HashMap; import java.util.Map; +<<<<<<< HEAD +import com.cloud.event.EventTypes; +import com.cloud.event.UsageEventUtils; +import com.cloud.utils.fsm.StateMachine2; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.dao.VMInstanceDao; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; + +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.framework.events.EventBus; +import org.apache.cloudstack.framework.events.EventBusException; + +import com.cloud.configuration.Config; +import com.cloud.event.EventCategory; +======= import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.events.EventDistributor; import org.apache.logging.log4j.LogManager; @@ -31,12 +49,22 @@ import com.cloud.event.EventCategory; import com.cloud.event.EventTypes; import com.cloud.event.UsageEventUtils; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.server.ManagementService; import com.cloud.storage.Volume; import com.cloud.storage.Volume.Event; import com.cloud.storage.Volume.State; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.fsm.StateListener; +<<<<<<< HEAD + +public class VolumeStateListener implements StateListener { + + protected static EventBus s_eventBus = null; + protected ConfigurationDao _configDao; + protected VMInstanceDao _vmInstanceDao; + +======= import com.cloud.utils.fsm.StateMachine2; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; @@ -48,6 +76,7 @@ public class VolumeStateListener implements StateListener protected VMInstanceDao _vmInstanceDao; private EventDistributor eventDistributor; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 protected Logger logger = LogManager.getLogger(getClass()); public VolumeStateListener(ConfigurationDao configDao, VMInstanceDao vmInstanceDao) { @@ -55,10 +84,13 @@ public VolumeStateListener(ConfigurationDao configDao, VMInstanceDao vmInstanceD this._vmInstanceDao = vmInstanceDao; } +<<<<<<< HEAD +======= public void setEventDistributor(EventDistributor eventDistributor) { this.eventDistributor = eventDistributor; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Override public boolean preStateTransitionEvent(State oldState, Event event, State newState, Volume vo, boolean status, Object opaque) { pubishOnEventBus(event.name(), "preStateTransitionEvent", vo, oldState, newState); @@ -94,21 +126,36 @@ public boolean postStateTransitionEvent(StateMachine2.Transition t return true; } +<<<<<<< HEAD + private void pubishOnEventBus(String event, String status, Volume vo, State oldState, State newState) { +======= private void pubishOnEventBus(String event, String status, Volume vo, State oldState, State newState) { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 String configKey = Config.PublishResourceStateEvent.key(); String value = _configDao.getValue(configKey); boolean configValue = Boolean.parseBoolean(value); if(!configValue) return; +<<<<<<< HEAD + try { + s_eventBus = ComponentContext.getComponent(EventBus.class); + } catch (NoSuchBeanDefinitionException nbe) { + return; // no provider is configured to provide events bus, so just return +======= if (eventDistributor == null) { setEventDistributor(ComponentContext.getComponent(EventDistributor.class)); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } String resourceName = getEntityFromClassName(Volume.class.getName()); org.apache.cloudstack.framework.events.Event eventMsg = new org.apache.cloudstack.framework.events.Event(ManagementService.Name, EventCategory.RESOURCE_STATE_CHANGE_EVENT.getName(), event, resourceName, +<<<<<<< HEAD + vo.getUuid()); +======= vo.getUuid()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Map eventDescription = new HashMap(); eventDescription.put("resource", resourceName); eventDescription.put("id", vo.getUuid()); @@ -119,7 +166,15 @@ private void pubishOnEventBus(String event, String status, Volume vo, State oldS eventDescription.put("eventDateTime", eventDate); eventMsg.setDescription(eventDescription); +<<<<<<< HEAD + try { + s_eventBus.publish(eventMsg); + } catch (EventBusException e) { + logger.warn("Failed to state change event on the event bus."); + } +======= eventDistributor.publish(eventMsg); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } private String getEntityFromClassName(String entityClassName) { diff --git a/server/src/main/java/com/cloud/user/AccountManagerImpl.java b/server/src/main/java/com/cloud/user/AccountManagerImpl.java index 15121aa0a143..6305a7f46907 100644 --- a/server/src/main/java/com/cloud/user/AccountManagerImpl.java +++ b/server/src/main/java/com/cloud/user/AccountManagerImpl.java @@ -77,13 +77,19 @@ import org.apache.cloudstack.resourcedetail.UserDetailVO; import org.apache.cloudstack.resourcedetail.dao.UserDetailsDao; import org.apache.cloudstack.utils.baremetal.BaremetalUtils; +<<<<<<< HEAD +======= import org.apache.cloudstack.webhook.WebhookHelper; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.commons.codec.binary.Base64; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; +<<<<<<< HEAD +======= import org.springframework.beans.factory.NoSuchBeanDefinitionException; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.api.ApiDBUtils; import com.cloud.api.auth.SetupUserTwoFactorAuthenticationCmd; @@ -170,7 +176,10 @@ import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.Ternary; +<<<<<<< HEAD +======= import com.cloud.utils.component.ComponentContext; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.component.PluggableService; @@ -333,7 +342,10 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M private List _securityCheckers; private int _cleanupInterval; +<<<<<<< HEAD +======= private static final String OAUTH2_PROVIDER_NAME = "oauth2"; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private List apiNameList; protected static Map userTwoFactorAuthenticationProvidersMap = new HashMap<>(); @@ -429,6 +441,8 @@ public void setQuerySelectors(List querySelectors) { _querySelectors = querySelectors; } +<<<<<<< HEAD +======= protected void deleteWebhooksForAccount(long accountId) { try { WebhookHelper webhookService = ComponentContext.getDelegateComponentOfType(WebhookHelper.class); @@ -438,6 +452,7 @@ protected void deleteWebhooksForAccount(long accountId) { } } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Override public List getApiNameList() { return apiNameList; @@ -1117,9 +1132,12 @@ public int compare(NetworkVO network1, NetworkVO network2) { // Delete registered UserData userDataDao.removeByAccountId(accountId); +<<<<<<< HEAD +======= // Delete Webhooks deleteWebhooksForAccount(accountId); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 return true; } catch (Exception ex) { logger.warn("Failed to cleanup account " + account + " due to ", ex); @@ -2676,8 +2694,12 @@ private UserAccount getUserAccount(String username, String password, Long domain continue; } } +<<<<<<< HEAD + if (secretCode != null && !authenticator.getName().equals("oauth2")) { +======= if ((secretCode != null && !authenticator.getName().equals(OAUTH2_PROVIDER_NAME)) || (secretCode == null && authenticator.getName().equals(OAUTH2_PROVIDER_NAME))) { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 continue; } Pair result = authenticator.authenticate(username, password, domainId, requestParameters); diff --git a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java index ee73818638cb..a67dd1445361 100644 --- a/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/main/java/com/cloud/vm/UserVmManagerImpl.java @@ -54,7 +54,11 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; +<<<<<<< HEAD +import com.cloud.kubernetes.cluster.KubernetesClusterHelper; +======= import com.cloud.kubernetes.cluster.KubernetesServiceHelper; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.network.dao.NsxProviderDao; import com.cloud.network.element.NsxProviderVO; import com.cloud.user.AccountVO; @@ -136,8 +140,13 @@ import org.apache.cloudstack.userdata.UserDataManager; import org.apache.cloudstack.utils.bytescale.ByteScaleUtils; import org.apache.cloudstack.utils.security.ParserUtils; +<<<<<<< HEAD +import org.apache.cloudstack.vm.schedule.VMScheduleManager; +import org.apache.cloudstack.vm.UnmanagedVMsManager; +======= import org.apache.cloudstack.vm.UnmanagedVMsManager; import org.apache.cloudstack.vm.schedule.VMScheduleManager; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.commons.codec.binary.Base64; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; @@ -146,7 +155,10 @@ import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.jetbrains.annotations.NotNull; +<<<<<<< HEAD +======= import org.springframework.beans.factory.NoSuchBeanDefinitionException; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.w3c.dom.Document; @@ -352,7 +364,10 @@ import com.cloud.utils.Journal; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; +<<<<<<< HEAD +======= import com.cloud.utils.component.ComponentContext; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.crypt.DBEncryptionUtil; @@ -603,7 +618,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir @Inject NsxProviderDao nsxProviderDao; +<<<<<<< HEAD +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private ScheduledExecutorService _executor = null; private ScheduledExecutorService _vmIpFetchExecutor = null; private int _expungeInterval; @@ -611,7 +629,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir private boolean _dailyOrHourly = false; private int capacityReleaseInterval; private ExecutorService _vmIpFetchThreadExecutor; +<<<<<<< HEAD + private List kubernetesClusterHelpers; +======= private List kubernetesServiceHelpers; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private String _instance; @@ -625,12 +647,21 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir private static final int NUM_OF_2K_BLOCKS = 512; private static final int MAX_HTTP_POST_LENGTH = NUM_OF_2K_BLOCKS * MAX_USER_DATA_LENGTH_BYTES; +<<<<<<< HEAD + public List getKubernetesClusterHelpers() { + return kubernetesClusterHelpers; + } + + public void setKubernetesClusterHelpers(final List kubernetesClusterHelpers) { + this.kubernetesClusterHelpers = kubernetesClusterHelpers; +======= public List getKubernetesServiceHelpers() { return kubernetesServiceHelpers; } public void setKubernetesServiceHelpers(final List kubernetesServiceHelpers) { this.kubernetesServiceHelpers = kubernetesServiceHelpers; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } @Inject @@ -2564,7 +2595,11 @@ private boolean cleanupVmResources(long vmId) { // cleanup port forwarding rules VMInstanceVO vmInstanceVO = _vmInstanceDao.findById(vmId); NsxProviderVO nsx = nsxProviderDao.findByZoneId(vmInstanceVO.getDataCenterId()); +<<<<<<< HEAD + if (Objects.isNull(nsx) || Objects.isNull(kubernetesClusterHelpers.get(0).findByVmId(vmId))) { +======= if (Objects.isNull(nsx) || Objects.isNull(kubernetesServiceHelpers.get(0).findByVmId(vmId))) { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 if (_rulesMgr.revokePortForwardingRulesForVm(vmId)) { logger.debug("Port forwarding rules are removed successfully as a part of vm id=" + vmId + " expunge"); } else { @@ -3262,12 +3297,15 @@ public UserVm startVirtualMachine(StartVMCmd cmd) throws ExecutionException, Con } @Override +<<<<<<< HEAD +======= @ActionEvent(eventType = EventTypes.EVENT_VM_START, eventDescription = "starting Vm", async = true) public void startVirtualMachine(UserVm vm) throws OperationTimedoutException, ResourceUnavailableException, InsufficientCapacityException { _itMgr.advanceStart(vm.getUuid(), null, null); } @Override +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @ActionEvent(eventType = EventTypes.EVENT_VM_REBOOT, eventDescription = "rebooting Vm", async = true) public UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ResourceAllocationException { Account caller = CallContext.current().getCallingAccount(); @@ -3321,6 +3359,8 @@ public UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityE return null; } +<<<<<<< HEAD +======= protected void checkPluginsIfVmCanBeDestroyed(UserVm vm) { try { KubernetesServiceHelper kubernetesServiceHelper = @@ -3331,6 +3371,7 @@ protected void checkPluginsIfVmCanBeDestroyed(UserVm vm) { } } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @Override @ActionEvent(eventType = EventTypes.EVENT_VM_DESTROY, eventDescription = "destroying Vm", async = true) public UserVm destroyVm(DestroyVMCmd cmd) throws ResourceUnavailableException, ConcurrentOperationException { @@ -3357,9 +3398,12 @@ public UserVm destroyVm(DestroyVMCmd cmd) throws ResourceUnavailableException, C // check if vm belongs to AutoScale vm group in Disabled state autoScaleManager.checkIfVmActionAllowed(vmId); +<<<<<<< HEAD +======= // check if vm belongs to any plugin resources checkPluginsIfVmCanBeDestroyed(vm); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 // check if there are active volume snapshots tasks logger.debug("Checking if there are any ongoing snapshots on the ROOT volumes associated with VM with ID " + vmId); if (checkStatusOfVolumeSnapshots(vmId, Volume.Type.ROOT)) { @@ -5514,12 +5558,16 @@ public Pair> startVirtualMach final ServiceOfferingVO offering = serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); Pair cpuCapabilityAndCapacity = _capacityMgr.checkIfHostHasCpuCapabilityAndCapacity(destinationHost, offering, false); if (!cpuCapabilityAndCapacity.first() || !cpuCapabilityAndCapacity.second()) { +<<<<<<< HEAD + String errorMsg = "Cannot deploy the VM to specified host " + hostId + "; host has cpu capability? " + cpuCapabilityAndCapacity.first() + ", host has capacity? " + cpuCapabilityAndCapacity.second(); +======= String errorMsg; if (!cpuCapabilityAndCapacity.first()) { errorMsg = String.format("Cannot deploy the VM to specified host %d, requested CPU and speed is more than the host capability", hostId); } else { errorMsg = String.format("Cannot deploy the VM to specified host %d, host does not have enough free CPU or RAM, please check the logs", hostId); } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 logger.info(errorMsg); if (!AllowDeployVmIfGivenHostFails.value()) { throw new InvalidParameterValueException(errorMsg); @@ -8107,7 +8155,11 @@ public Pair doInTransaction(final TransactionStatus status) th } if (needRestart) { try { +<<<<<<< HEAD + if (vm.getDetail(VmDetailConstants.PASSWORD) != null) { +======= if (Objects.nonNull(password)) { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 params = new HashMap<>(); params.put(VirtualMachineProfile.Param.VmPassword, password); } diff --git a/server/src/main/java/com/cloud/vm/UserVmStateListener.java b/server/src/main/java/com/cloud/vm/UserVmStateListener.java index aa1805d3366e..1dbf4b3e8f31 100644 --- a/server/src/main/java/com/cloud/vm/UserVmStateListener.java +++ b/server/src/main/java/com/cloud/vm/UserVmStateListener.java @@ -24,11 +24,23 @@ import javax.inject.Inject; +<<<<<<< HEAD +import com.cloud.server.ManagementService; +import com.cloud.utils.fsm.StateMachine2; +import com.cloud.vm.dao.UserVmDao; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; + +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.framework.events.EventBus; +======= import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.events.EventDistributor; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.NoSuchBeanDefinitionException; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.configuration.Config; import com.cloud.event.EventCategory; @@ -37,6 +49,14 @@ import com.cloud.event.dao.UsageEventDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; +<<<<<<< HEAD +import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.fsm.StateListener; +import com.cloud.vm.VirtualMachine.Event; +import com.cloud.vm.VirtualMachine.State; +import com.cloud.vm.dao.NicDao; +======= import com.cloud.server.ManagementService; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.utils.component.ComponentContext; @@ -46,6 +66,7 @@ import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.UserVmDao; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public class UserVmStateListener implements StateListener { @@ -56,9 +77,16 @@ public class UserVmStateListener implements StateListener>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public UserVmStateListener(UsageEventDao usageEventDao, NetworkDao networkDao, NicDao nicDao, ServiceOfferingDao offeringDao, UserVmDao userVmDao, UserVmManager userVmMgr, ConfigurationDao configDao) { this._usageEventDao = usageEventDao; @@ -128,16 +156,26 @@ private void pubishOnEventBus(String event, String status, VirtualMachine vo, Vi if(!configValue) return; try { +<<<<<<< HEAD + s_eventBus = ComponentContext.getComponent(EventBus.class); + } catch (NoSuchBeanDefinitionException nbe) { + return; // no provider is configured to provide events bus, so just return +======= eventDistributor = ComponentContext.getComponent(EventDistributor.class); } catch (NoSuchBeanDefinitionException nbe) { return; // no provider is configured to provide events distributor, so just return +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } String resourceName = getEntityFromClassName(VirtualMachine.class.getName()); org.apache.cloudstack.framework.events.Event eventMsg = new org.apache.cloudstack.framework.events.Event(ManagementService.Name, EventCategory.RESOURCE_STATE_CHANGE_EVENT.getName(), event, resourceName, vo.getUuid()); +<<<<<<< HEAD + Map eventDescription = new HashMap(); +======= Map eventDescription = new HashMap<>(); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 eventDescription.put("resource", resourceName); eventDescription.put("id", vo.getUuid()); eventDescription.put("old-state", oldState.name()); @@ -148,7 +186,16 @@ private void pubishOnEventBus(String event, String status, VirtualMachine vo, Vi eventDescription.put("eventDateTime", eventDate); eventMsg.setDescription(eventDescription); +<<<<<<< HEAD + try { + s_eventBus.publish(eventMsg); + } catch (org.apache.cloudstack.framework.events.EventBusException e) { + logger.warn("Failed to publish state change event on the event bus."); + } + +======= eventDistributor.publish(eventMsg); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } private String getEntityFromClassName(String entityClassName) { diff --git a/server/src/main/java/org/apache/cloudstack/annotation/AnnotationManagerImpl.java b/server/src/main/java/org/apache/cloudstack/annotation/AnnotationManagerImpl.java index a5f7a1b8002a..aca2eb99b8e9 100644 --- a/server/src/main/java/org/apache/cloudstack/annotation/AnnotationManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/annotation/AnnotationManagerImpl.java @@ -64,7 +64,11 @@ import com.cloud.exception.PermissionDeniedException; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; +<<<<<<< HEAD +import com.cloud.kubernetes.cluster.KubernetesClusterHelper; +======= import com.cloud.kubernetes.cluster.KubernetesServiceHelper; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.network.as.dao.AutoScaleVmGroupDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.NetworkDao; @@ -163,7 +167,11 @@ public final class AnnotationManagerImpl extends ManagerBase implements Annotati EntityManager entityManager; private static final List adminRoles = Collections.singletonList(RoleType.Admin); +<<<<<<< HEAD + private List kubernetesClusterHelpers; +======= private List kubernetesServiceHelpers; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 public static final Map s_typeMap = new HashMap<>(); static { @@ -198,12 +206,21 @@ public final class AnnotationManagerImpl extends ManagerBase implements Annotati s_typeMap.put(EntityType.OBJECT_STORAGE, ApiCommandResourceType.ObjectStore); } +<<<<<<< HEAD + public List getKubernetesClusterHelpers() { + return kubernetesClusterHelpers; + } + + public void setKubernetesClusterHelpers(final List kubernetesClusterHelpers) { + this.kubernetesClusterHelpers = kubernetesClusterHelpers; +======= public List getKubernetesServiceHelpers() { return kubernetesServiceHelpers; } public void setKubernetesServiceHelpers(final List kubernetesServiceHelpers) { this.kubernetesServiceHelpers = kubernetesServiceHelpers; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } @Override @@ -533,7 +550,11 @@ private ControlledEntity getEntityFromUuidAndType(String entityUuid, EntityType case ISO: return templateDao.findByUuid(entityUuid); case KUBERNETES_CLUSTER: +<<<<<<< HEAD + return kubernetesClusterHelpers.get(0).findByUuid(entityUuid); +======= return kubernetesServiceHelpers.get(0).findByUuid(entityUuid); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 case AUTOSCALE_VM_GROUP: return autoScaleVmGroupDao.findByUuid(entityUuid); case MANAGEMENT_SERVER: diff --git a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java index 73144ac29663..688aa2bdc391 100644 --- a/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/vm/UnmanagedVMsManagerImpl.java @@ -2079,10 +2079,17 @@ private UserVmResponse importKvmInstance(ImportVmCmd cmd) { throw new InvalidParameterValueException("Username need to be provided."); } +<<<<<<< HEAD + HashMap instancesMap = getRemoteVms(zoneId, remoteUrl, cmd.getUsername(), cmd.getPassword()); + unmanagedInstanceTO = instancesMap.get(cmd.getName()); + if (unmanagedInstanceTO == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Vm with name: %s not found on remote host", instanceName)); +======= HashMap instancesMap = getRemoteVmsOnKVMHost(zoneId, remoteUrl, cmd.getUsername(), cmd.getPassword()); unmanagedInstanceTO = instancesMap.get(cmd.getName()); if (unmanagedInstanceTO == null) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("VM with name: %s not found on remote host %s", instanceName, remoteUrl)); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } } @@ -2479,7 +2486,15 @@ public ListResponse listVmsForImport(ListVmsForImport throw new InvalidParameterValueException("Please specify a valid zone."); } final String hypervisorType = cmd.getHypervisor(); +<<<<<<< HEAD + if (Hypervisor.HypervisorType.KVM.toString().equalsIgnoreCase(hypervisorType)) { + if (StringUtils.isBlank(cmd.getUsername())) { + throw new InvalidParameterValueException("Username need to be provided."); + } + } else { +======= if (!Hypervisor.HypervisorType.KVM.toString().equalsIgnoreCase(hypervisorType)) { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 throw new InvalidParameterValueException(String.format("VM Import is currently not supported for hypervisor: %s", hypervisorType)); } @@ -2489,7 +2504,11 @@ public ListResponse listVmsForImport(ListVmsForImport } List responses = new ArrayList<>(); +<<<<<<< HEAD + HashMap vmMap = getRemoteVms(zoneId, cmd.getHost(), cmd.getUsername(), cmd.getPassword()); +======= HashMap vmMap = getRemoteVmsOnKVMHost(zoneId, cmd.getHost(), cmd.getUsername(), cmd.getPassword()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 for (String key : vmMap.keySet()) { UnmanagedInstanceTO instance = vmMap.get(key); if (StringUtils.isNotEmpty(keyword) && @@ -2504,6 +2523,19 @@ public ListResponse listVmsForImport(ListVmsForImport return listResponses; } +<<<<<<< HEAD + private HashMap getRemoteVms(long zoneId, String remoteUrl, String username, String password) { + //ToDo: add option to list one Vm by name + List hosts = resourceManager.listAllUpAndEnabledHostsInOneZoneByHypervisor(Hypervisor.HypervisorType.KVM, zoneId); + if(hosts.size() < 1) { + throw new CloudRuntimeException("No hosts available for Vm Import"); + } + HostVO host = hosts.get(0); + GetRemoteVmsCommand getRemoteVmsCommand = new GetRemoteVmsCommand(remoteUrl, username, password); + Answer answer = agentManager.easySend(host.getId(), getRemoteVmsCommand); + if (!(answer instanceof GetRemoteVmsAnswer)) { + throw new CloudRuntimeException("Error while listing remote Vms"); +======= private HashMap getRemoteVmsOnKVMHost(long zoneId, String remoteHostUrl, String username, String password) { //ToDo: add option to list one Vm by name List hosts = resourceManager.listAllUpAndEnabledHostsInOneZoneByHypervisor(Hypervisor.HypervisorType.KVM, zoneId); @@ -2515,6 +2547,7 @@ private HashMap getRemoteVmsOnKVMHost(long zoneId, Answer answer = agentManager.easySend(host.getId(), getRemoteVmsCommand); if (!(answer instanceof GetRemoteVmsAnswer)) { throw new CloudRuntimeException("Failed to list VMs, due to: " + answer.getDetails()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } GetRemoteVmsAnswer getRemoteVmsAnswer = (GetRemoteVmsAnswer) answer; return getRemoteVmsAnswer.getUnmanagedInstances(); diff --git a/server/src/main/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml b/server/src/main/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml index 163e54a14f3c..b888c0282999 100644 --- a/server/src/main/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml +++ b/server/src/main/resources/META-INF/cloudstack/core/spring-server-core-managers-context.xml @@ -107,7 +107,11 @@ +<<<<<<< HEAD + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @@ -145,10 +149,13 @@ +<<<<<<< HEAD +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @@ -322,7 +329,11 @@ +<<<<<<< HEAD + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 diff --git a/server/src/test/java/com/cloud/event/ActionEventUtilsTest.java b/server/src/test/java/com/cloud/event/ActionEventUtilsTest.java index aba8acf59c26..4ab23b93fbb2 100644 --- a/server/src/test/java/com/cloud/event/ActionEventUtilsTest.java +++ b/server/src/test/java/com/cloud/event/ActionEventUtilsTest.java @@ -29,8 +29,12 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.events.Event; +<<<<<<< HEAD +import org.apache.cloudstack.framework.events.EventBus; +======= import org.apache.cloudstack.framework.events.EventBusException; import org.apache.cloudstack.framework.events.EventDistributor; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -98,7 +102,11 @@ public class ActionEventUtilsTest { protected ConfigurationDao configDao; @Mock +<<<<<<< HEAD + protected EventBus eventBus; +======= protected EventDistributor eventDistributor; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 private AccountVO account; private UserVO user; @@ -150,7 +158,11 @@ public void setupCommonMocks() throws Exception { //Some basic mocks. Mockito.when(configDao.getValue(Config.PublishActionEvent.key())).thenReturn("true"); componentContextMocked = Mockito.mockStatic(ComponentContext.class); +<<<<<<< HEAD + componentContextMocked.when(() -> ComponentContext.getComponent(EventBus.class)).thenReturn(eventBus); +======= componentContextMocked.when(() -> ComponentContext.getComponent(EventDistributor.class)).thenReturn(eventDistributor); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 //Needed for persist to actually set an ID that can be returned from the ActionEventUtils //methods. @@ -167,11 +179,22 @@ public EventVO answer(InvocationOnMock invocation) throws Throwable { }); //Needed to record events published on the bus. +<<<<<<< HEAD + Mockito.doAnswer(new Answer() { + @Override public Void answer(InvocationOnMock invocation) throws Throwable { + Event event = (Event)invocation.getArguments()[0]; + publishedEvents.add(event); + return null; + } + + }).when(eventBus).publish(Mockito.any(Event.class)); +======= Mockito.doAnswer((Answer>) invocation -> { Event event = (Event)invocation.getArguments()[0]; publishedEvents.add(event); return new HashMap<>(); }).when(eventDistributor).publish(Mockito.any(Event.class)); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 account = new AccountVO("testaccount", 1L, "networkdomain", Account.Type.NORMAL, "uuid"); account.setId(ACCOUNT_ID); diff --git a/server/src/test/java/com/cloud/projects/ProjectManagerImplTest.java b/server/src/test/java/com/cloud/projects/ProjectManagerImplTest.java index b9b568facc28..da2792237461 100644 --- a/server/src/test/java/com/cloud/projects/ProjectManagerImplTest.java +++ b/server/src/test/java/com/cloud/projects/ProjectManagerImplTest.java @@ -16,27 +16,40 @@ // under the License. package com.cloud.projects; +<<<<<<< HEAD +import com.cloud.projects.dao.ProjectDao; +======= import java.util.ArrayList; import java.util.List; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.webhook.WebhookHelper; import org.apache.commons.collections.CollectionUtils; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; +<<<<<<< HEAD +======= import org.mockito.MockedStatic; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.mockito.Mockito; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; import org.mockito.stubbing.Answer; +<<<<<<< HEAD + +import java.util.ArrayList; +import java.util.List; +======= import org.springframework.beans.factory.NoSuchBeanDefinitionException; import com.cloud.projects.dao.ProjectDao; import com.cloud.utils.component.ComponentContext; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @RunWith(MockitoJUnitRunner.class) @@ -101,6 +114,8 @@ public void testUpdateProjectNameAndDisplayTextUpdateDisplayText() { public void testUpdateProjectNameAndDisplayTextUpdateNameDisplayText() { runUpdateProjectNameAndDisplayTextTest(true, true); } +<<<<<<< HEAD +======= @Test public void testDeleteWebhooksForAccount() { @@ -128,4 +143,5 @@ public void testDeleteWebhooksForAccountNoBean() { Assert.assertTrue(CollectionUtils.isEmpty(result)); } } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/server/src/test/java/com/cloud/resourcelimit/CheckedReservationTest.java b/server/src/test/java/com/cloud/resourcelimit/CheckedReservationTest.java index 247647dd010e..9492f169f175 100644 --- a/server/src/test/java/com/cloud/resourcelimit/CheckedReservationTest.java +++ b/server/src/test/java/com/cloud/resourcelimit/CheckedReservationTest.java @@ -24,9 +24,13 @@ import static org.mockito.Mockito.when; import java.util.ArrayList; +<<<<<<< HEAD +import java.util.List; +======= import java.util.HashMap; import java.util.List; import java.util.Map; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.reservation.ReservationVO; @@ -145,6 +149,8 @@ public void testReservationPersistAndCallContextParam() { Assert.fail("Exception faced: " + e.getMessage()); } } +<<<<<<< HEAD +======= @Test public void testMultipleReservationsWithOneFailing() { @@ -182,4 +188,5 @@ public void testMultipleReservationsWithOneFailing() { Assert.assertTrue("All persisted reservations are not removed", persistedReservations.isEmpty()); } } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/server/src/test/java/com/cloud/template/HypervisorTemplateAdapterTest.java b/server/src/test/java/com/cloud/template/HypervisorTemplateAdapterTest.java index 5307beb4aba8..ed0d009610c5 100644 --- a/server/src/test/java/com/cloud/template/HypervisorTemplateAdapterTest.java +++ b/server/src/test/java/com/cloud/template/HypervisorTemplateAdapterTest.java @@ -18,6 +18,27 @@ package com.cloud.template; +<<<<<<< HEAD +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.event.EventTypes; +import com.cloud.event.UsageEventUtils; +import com.cloud.event.UsageEventVO; +import com.cloud.event.dao.UsageEventDao; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.org.Grouping; +import com.cloud.server.StatsCollector; +import com.cloud.storage.Storage.ImageFormat; +import com.cloud.storage.TemplateProfile; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.dao.VMTemplateZoneDao; +import com.cloud.user.AccountVO; +import com.cloud.user.ResourceLimitService; +import com.cloud.user.dao.AccountDao; +import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.exception.CloudRuntimeException; +======= import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyLong; import static org.mockito.Mockito.doAnswer; @@ -38,6 +59,7 @@ import java.util.Set; import java.util.concurrent.ExecutionException; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; @@ -47,7 +69,12 @@ import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.events.Event; +<<<<<<< HEAD +import org.apache.cloudstack.framework.events.EventBus; +import org.apache.cloudstack.framework.events.EventBusException; +======= import org.apache.cloudstack.framework.events.EventDistributor; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.secstorage.heuristics.HeuristicType; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; @@ -70,6 +97,27 @@ import org.mockito.junit.MockitoJUnitRunner; import org.mockito.stubbing.Answer; +<<<<<<< HEAD +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ExecutionException; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyLong; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.when; +======= import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.event.EventTypes; @@ -89,11 +137,16 @@ import com.cloud.user.dao.AccountDao; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.exception.CloudRuntimeException; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @RunWith(MockitoJUnitRunner.class) public class HypervisorTemplateAdapterTest { @Mock +<<<<<<< HEAD + EventBus _bus; +======= EventDistributor eventDistributor; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 List events = new ArrayList<>(); @Mock @@ -168,7 +221,11 @@ public void tearDown() throws Exception { closeable.close(); } +<<<<<<< HEAD + public UsageEventUtils setupUsageUtils() throws EventBusException { +======= public UsageEventUtils setupUsageUtils() { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Mockito.when(_configDao.getValue(eq("publish.usage.events"))).thenReturn("true"); Mockito.when(_usageEventDao.persist(Mockito.any(UsageEventVO.class))).then(new Answer() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { @@ -180,6 +237,18 @@ public UsageEventUtils setupUsageUtils() { Mockito.when(_usageEventDao.listAll()).thenReturn(usageEvents); +<<<<<<< HEAD + doAnswer(new Answer() { + @Override public Void answer(InvocationOnMock invocation) throws Throwable { + Event event = (Event)invocation.getArguments()[0]; + events.add(event); + return null; + } + }).when(_bus).publish(any(Event.class)); + + componentContextMocked = Mockito.mockStatic(ComponentContext.class); + when(ComponentContext.getComponent(eq(EventBus.class))).thenReturn(_bus); +======= doAnswer((Answer) invocation -> { Event event = (Event)invocation.getArguments()[0]; events.add(event); @@ -188,6 +257,7 @@ public UsageEventUtils setupUsageUtils() { componentContextMocked = Mockito.mockStatic(ComponentContext.class); when(ComponentContext.getComponent(eq(EventDistributor.class))).thenReturn(eventDistributor); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 UsageEventUtils utils = new UsageEventUtils(); @@ -255,7 +325,11 @@ public void cleanupUsageUtils() { } //@Test +<<<<<<< HEAD + public void testEmitDeleteEventUuid() throws InterruptedException, ExecutionException, EventBusException { +======= public void testEmitDeleteEventUuid() throws InterruptedException, ExecutionException { +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 //All the mocks required for this test to work. ImageStoreEntity store = mock(ImageStoreEntity.class); when(store.getId()).thenReturn(1l); diff --git a/server/src/test/java/com/cloud/user/AccountManagerImplTest.java b/server/src/test/java/com/cloud/user/AccountManagerImplTest.java index e5c623ca6df7..a1bc3adfd709 100644 --- a/server/src/test/java/com/cloud/user/AccountManagerImplTest.java +++ b/server/src/test/java/com/cloud/user/AccountManagerImplTest.java @@ -16,6 +16,8 @@ // under the License. package com.cloud.user; +<<<<<<< HEAD +======= import static org.mockito.ArgumentMatchers.nullable; import java.net.InetAddress; @@ -48,6 +50,7 @@ import org.mockito.junit.MockitoJUnitRunner; import org.springframework.beans.factory.NoSuchBeanDefinitionException; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.acl.DomainChecker; import com.cloud.api.auth.SetupUserTwoFactorAuthenticationCmd; import com.cloud.domain.Domain; @@ -60,12 +63,47 @@ import com.cloud.projects.ProjectAccountVO; import com.cloud.user.Account.State; import com.cloud.utils.Pair; +<<<<<<< HEAD +======= import com.cloud.utils.component.ComponentContext; +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.UserVmManagerImpl; import com.cloud.vm.UserVmVO; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.snapshot.VMSnapshotVO; +<<<<<<< HEAD +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd; +import org.apache.cloudstack.api.command.admin.user.GetUserKeysCmd; +import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd; +import org.apache.cloudstack.api.response.UserTwoFactorAuthenticationSetupResponse; +import org.apache.cloudstack.auth.UserAuthenticator; +import org.apache.cloudstack.auth.UserAuthenticator.ActionOnFailedAuthentication; +import org.apache.cloudstack.auth.UserTwoFactorAuthenticator; +import org.apache.cloudstack.context.CallContext; +import org.apache.cloudstack.framework.config.ConfigKey; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.mockito.ArgumentMatchers.nullable; +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @RunWith(MockitoJUnitRunner.class) public class AccountManagerImplTest extends AccountManagetImplTestBase { @@ -177,7 +215,10 @@ public void deleteUserAccount() { Mockito.when(_sshKeyPairDao.listKeyPairs(Mockito.anyLong(), Mockito.anyLong())).thenReturn(sshkeyList); Mockito.when(_sshKeyPairDao.remove(Mockito.anyLong())).thenReturn(true); Mockito.when(userDataDao.removeByAccountId(Mockito.anyLong())).thenReturn(222); +<<<<<<< HEAD +======= Mockito.doNothing().when(accountManagerImpl).deleteWebhooksForAccount(Mockito.anyLong()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Assert.assertTrue(accountManagerImpl.deleteUserAccount(42l)); // assert that this was a clean delete @@ -197,7 +238,10 @@ public void deleteUserAccountCleanup() { Mockito.when(_vmMgr.expunge(Mockito.any(UserVmVO.class))).thenReturn(false); Mockito.lenient().when(_domainMgr.getDomain(Mockito.anyLong())).thenReturn(domain); Mockito.lenient().when(securityChecker.checkAccess(Mockito.any(Account.class), Mockito.any(Domain.class))).thenReturn(true); +<<<<<<< HEAD +======= Mockito.doNothing().when(accountManagerImpl).deleteWebhooksForAccount(Mockito.anyLong()); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 Assert.assertTrue(accountManagerImpl.deleteUserAccount(42l)); // assert that this was NOT a clean delete @@ -253,7 +297,10 @@ public void testAuthenticateUser() throws UnknownHostException { Mockito.when(userAuthenticator.authenticate("test", "fail", 1L, new HashMap<>())).thenReturn(failureAuthenticationPair); Mockito.lenient().when(userAuthenticator.authenticate("test", null, 1L, new HashMap<>())).thenReturn(successAuthenticationPair); Mockito.lenient().when(userAuthenticator.authenticate("test", "", 1L, new HashMap<>())).thenReturn(successAuthenticationPair); +<<<<<<< HEAD +======= Mockito.when(userAuthenticator.getName()).thenReturn("test"); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 //Test for incorrect password. authentication should fail UserAccount userAccount = accountManagerImpl.authenticateUser("test", "fail", 1L, InetAddress.getByName("127.0.0.1"), new HashMap<>()); @@ -1038,6 +1085,8 @@ public void testGetActiveUserAccountByEmail() { Assert.assertEquals(userAccountVOList.size(), userAccounts.size()); Assert.assertEquals(userAccountVOList.get(0), userAccounts.get(0)); } +<<<<<<< HEAD +======= @Test public void testDeleteWebhooksForAccount() { @@ -1058,4 +1107,5 @@ public void testDeleteWebhooksForAccountNoBean() { accountManagerImpl.deleteWebhooksForAccount(1L); } } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java index 7007ad6b33f5..dbb3fad0ff71 100644 --- a/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/src/test/java/com/cloud/vpc/MockNetworkManagerImpl.java @@ -222,6 +222,8 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac return null; } +<<<<<<< HEAD +======= @Override public Network createGuestNetwork(long networkOfferingId, String name, String displayText, Account owner, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType) throws InsufficientCapacityException, @@ -229,6 +231,7 @@ public Network createGuestNetwork(long networkOfferingId, String name, String di return null; } +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 /* (non-Javadoc) * @see com.cloud.network.NetworkService#searchForNetworks(com.cloud.api.commands.ListNetworksCmd) */ diff --git a/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java b/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java index 2cc61dae133e..05faabad91ed 100644 --- a/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java +++ b/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/HttpUploadServerHandler.java @@ -296,8 +296,12 @@ private void writeResponse(Channel channel, HttpResponseStatus statusCode) { @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { +<<<<<<< HEAD + logger.warn(responseContent.toString(), cause); +======= logger.warn(String.format("%s. Exception occurred: %s", responseContent.toString(), cause.getMessage())); logger.debug("Exception caught by HTTP upload handler, caused due to: ", cause); +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 responseContent.append("\r\nException occurred: ").append(cause.getMessage()); writeResponse(ctx.channel(), HttpResponseStatus.INTERNAL_SERVER_ERROR); ctx.channel().close(); diff --git a/test/integration/smoke/test_register_userdata.py b/test/integration/smoke/test_register_userdata.py index f19b5abc9cf6..c3f8bbee58ba 100644 --- a/test/integration/smoke/test_register_userdata.py +++ b/test/integration/smoke/test_register_userdata.py @@ -28,7 +28,11 @@ NATRule, Template) from marvin.lib.common import get_test_template, get_zone, list_virtual_machines +<<<<<<< HEAD +from marvin.lib.utils import (validateList, cleanup_resources) +======= from marvin.lib.utils import validateList +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 from nose.plugins.attrib import attr from marvin.codes import PASS,FAIL import base64 @@ -87,7 +91,10 @@ def setUp(self): # Get Zone, Domain and Default Built-in template self.domain = get_domain(self.apiclient) self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) +<<<<<<< HEAD +======= self.hypervisor = self.testClient.getHypervisorInfo() +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 #create a user account self.account = Account.create( @@ -97,7 +104,11 @@ def setUp(self): ) self.testdata["mode"] = self.zone.networktype +<<<<<<< HEAD + self.template = get_template(self.apiclient, self.zone.id, self.testdata["ostype"]) +======= self.template = get_test_template(self.apiclient, self.zone.id, self.hypervisor) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 #create a service offering small_service_offering = self.testdata["service_offerings"]["small"] @@ -116,21 +127,41 @@ def setUp(self): self.testdata["network"], networkofferingid=self.no_isolate.id, zoneid=self.zone.id, +<<<<<<< HEAD + accountid="admin", + domainid=1 +======= accountid=self.account.name, domainid=self.account.domainid +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ) #build cleanup list self.cleanup = [ +<<<<<<< HEAD + self.service_offering, + self.isolated_network, + self.no_isolate, + self.account, +======= self.account, self.no_isolate, self.service_offering, self.isolated_network, +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 ] def tearDown(self): +<<<<<<< HEAD + try: + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + self.debug("Warning! Exception in tearDown: %s" % e) + +======= super(TestRegisteredUserdata, self).tearDown() +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 @attr(tags=['advanced', 'simulator', 'basic', 'sg'], required_hardware=False) def test_CRUD_operations_userdata(self): @@ -189,21 +220,35 @@ def test_deploy_vm_with_registered_userdata(self): self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, +<<<<<<< HEAD + accountid="admin", + domainid=1, +======= accountid=self.account.name, domainid=self.account.domainid, +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 serviceofferingid=self.service_offering.id, templateid=self.template.id, networkids=[self.isolated_network.id], userdataid=self.userdata2.userdata.id ) self.cleanup.append(self.virtual_machine) +<<<<<<< HEAD + self.cleanup.append(self.userdata2) +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 networkid = self.virtual_machine.nic[0].networkid src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=networkid, +<<<<<<< HEAD + account="admin", + domainid=1, +======= account=self.account.name, domainid=self.account.domainid, +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 listall=True, issourcenat=True, ) @@ -316,8 +361,13 @@ def test_deploy_vm_with_registered_userdata_with_params(self): self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, +<<<<<<< HEAD + accountid="admin", + domainid=1, +======= accountid=self.account.name, domainid=self.account.domainid, +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 serviceofferingid=self.service_offering.id, templateid=self.template.id, networkids=[self.isolated_network.id], @@ -325,13 +375,22 @@ def test_deploy_vm_with_registered_userdata_with_params(self): userdatadetails=[{"key1": "value1"}] ) self.cleanup.append(self.virtual_machine) +<<<<<<< HEAD + self.cleanup.append(self.userdata2) +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 networkid = self.virtual_machine.nic[0].networkid src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=networkid, +<<<<<<< HEAD + account="admin", + domainid=1, +======= account=self.account.name, domainid=self.account.domainid, +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 listall=True, issourcenat=True, ) @@ -488,14 +547,23 @@ def test_deploy_vm_with_registered_userdata_with_override_policy_allow(self): self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, +<<<<<<< HEAD + accountid="admin", + domainid=1, +======= accountid=self.account.name, domainid=self.account.domainid, +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 serviceofferingid=self.service_offering.id, templateid=self.template.id, networkids=[self.isolated_network.id], userdataid=self.apiUserdata.userdata.id ) self.cleanup.append(self.virtual_machine) +<<<<<<< HEAD + self.cleanup.append(self.apiUserdata) +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 self.template = Template.linkUserDataToTemplate( self.apiclient, @@ -506,8 +574,13 @@ def test_deploy_vm_with_registered_userdata_with_override_policy_allow(self): src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=networkid, +<<<<<<< HEAD + account="admin", + domainid=1, +======= account=self.account.name, domainid=self.account.domainid, +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 listall=True, issourcenat=True, ) @@ -617,14 +690,24 @@ def test_deploy_vm_with_registered_userdata_with_override_policy_append(self): self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, +<<<<<<< HEAD + accountid="admin", + domainid=1, +======= accountid=self.account.name, domainid=self.account.domainid, +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 serviceofferingid=self.service_offering.id, templateid=self.template.id, networkids=[self.isolated_network.id], userdataid=self.apiUserdata.userdata.id ) self.cleanup.append(self.virtual_machine) +<<<<<<< HEAD + self.cleanup.append(self.apiUserdata) + self.cleanup.append(self.templateUserdata) +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 self.template = Template.linkUserDataToTemplate( self.apiclient, @@ -635,8 +718,13 @@ def test_deploy_vm_with_registered_userdata_with_override_policy_append(self): src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=networkid, +<<<<<<< HEAD + account="admin", + domainid=1, +======= account=self.account.name, domainid=self.account.domainid, +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 listall=True, issourcenat=True, ) @@ -762,8 +850,13 @@ def test_deploy_vm_with_registered_userdata_with_override_policy_deny(self): self.apiclient, self.services["virtual_machine"], zoneid=self.zone.id, +<<<<<<< HEAD + accountid="admin", + domainid=1, +======= accountid=self.account.name, domainid=self.account.domainid, +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 serviceofferingid=self.service_offering.id, templateid=self.template.id, networkids=[self.isolated_network.id], @@ -773,6 +866,12 @@ def test_deploy_vm_with_registered_userdata_with_override_policy_deny(self): self.debug("Deploy VM with userdata passed during deployment failed as expected because template userdata override policy is deny. Exception here is : %s" % e.exception) +<<<<<<< HEAD + self.cleanup.append(self.apiUserdata) + self.cleanup.append(self.templateUserdata) + +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 self.template = Template.linkUserDataToTemplate( self.apiclient, templateid=self.template.id @@ -798,6 +897,10 @@ def test_user_userdata_crud(self): account=self.account.name, domainid=self.account.domainid ) +<<<<<<< HEAD + self.cleanup.append(self.userdata) +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 list_userdata = UserData.list(self.apiclient, id=self.userdata.userdata.id, listall=True) self.assertNotEqual( @@ -841,3 +944,7 @@ def test_user_userdata_crud(self): self.userapiclient, id=self.userdata.userdata.id ) +<<<<<<< HEAD + self.cleanup.remove(self.userdata) +======= +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 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 new file mode 100644 index 000000000000..6baadb8b035e --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/sample/UserCloudAPIExecutor.java @@ -0,0 +1,188 @@ +// 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 new file mode 100644 index 000000000000..7a56725681b8 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/longrun/BuildGuestNetwork.java @@ -0,0 +1,124 @@ +// 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.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +public class BuildGuestNetwork { + + protected Logger logger = LogManager.getLogger(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; + 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) { + logger.warn("Error code: ", e); + } + + if (myUser.getUserId() != null) { + 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) { + logger.info("VM with private Ip " + singlePrivateIp + " was successfully created"); + } else { + logger.info("Problems with VM creation for a user" + myUser.getUserName()); + logger.info("Deployment failed"); + break; + } + } + + logger.info("Deployment done..." + numVM + " VMs were created."); + } + + } catch (Exception e) { + 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 new file mode 100644 index 000000000000..7e90d71020cb --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/longrun/GuestNetwork.java @@ -0,0 +1,108 @@ +// 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.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.apache.log4j.NDC; + +import com.trilead.ssh2.Connection; +import com.trilead.ssh2.Session; + +public class GuestNetwork implements Runnable { + protected Logger logger = LogManager.getLogger(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 + logger.info("The size of the array is " + this.virtualMachines.size()); + while (true) { + try { + if (retry > 0) { + logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt"); + Thread.sleep(120000); + } + for (VirtualMachine vm : this.virtualMachines) { + + 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); + + logger.info("SSHed successfully into linux host " + this.publicIp); + + boolean isAuthenticated = conn.authenticateWithPassword("root", "password"); + + if (isAuthenticated == false) { + 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); + 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"); + logger.info("Executing " + downloadCommand); + sess.execCommand(downloadCommand); + Thread.sleep(120000); + sess.close(); + + //close the connection + conn.close(); + } + } catch (Exception ex) { + logger.error(ex); + retry++; + if (retry == retryNum) { + 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 new file mode 100644 index 000000000000..821b5012bb09 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/longrun/PerformanceWithAPI.java @@ -0,0 +1,191 @@ +// 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.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +import com.cloud.test.stress.TestClientWithAPI; + +public class PerformanceWithAPI { + + protected Logger logger = LogManager.getLogger(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; + + 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) { + logger.warn("Error code: ", e); + } + + if (myUser.getUserId() != null) { + 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) { + logger.info("VM with private Ip " + singlePrivateIp + " was successfully created"); + } else { + 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) { + logger.info("Successfully got public Ip " + singlePublicIp + " for user " + myUser.getUserName()); + } else { + 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; + } + + 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 + 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++) { + 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) { + 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(); + 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; + + logger.info("Trying to create IP forwarding rule: " + url); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + responseCode = client.executeMethod(method); + logger.info("create ip forwarding rule response code: " + responseCode); + if (responseCode == 200) { + logger.info("The rule is created successfully"); + } else if (responseCode == 500) { + InputStream is = method.getResponseBodyAsStream(); + Map errorInfo = TestClientWithAPI.getSingleValueFromXML(is, new String[] {"errorCode", "description"}); + logger.error("create ip forwarding rule (linux) test failed with errorCode: " + errorInfo.get("errorCode") + " and description: " + + errorInfo.get("description")); + } else { + 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 new file mode 100644 index 000000000000..56880cb9df79 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/longrun/User.java @@ -0,0 +1,203 @@ +// 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.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +import com.cloud.test.stress.TestClientWithAPI; + +public class User { + protected Logger logger = LogManager.getLogger(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")); + 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"}); + logger.error("associate ip test failed with errorCode: " + errorInfo.get("errorCode") + " and description: " + errorInfo.get("description")); + } else { + 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"; + 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"}); + logger.error("registration failed with errorCode: " + errorInfo.get("errorCode") + " and description: " + errorInfo.get("description")); + } else { + 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 new file mode 100644 index 000000000000..61ca082273cc --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/longrun/VirtualMachine.java @@ -0,0 +1,96 @@ +// 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.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +import com.cloud.test.stress.TestClientWithAPI; + +public class VirtualMachine { + protected Logger logger = LogManager.getLogger(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; + + logger.info("Sending this request to deploy a VM: " + url); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + 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")); + 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"}); + logger.error("deploy linux vm test failed with errorCode: " + errorInfo.get("errorCode") + " and description: " + errorInfo.get("description")); + } else { + 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 new file mode 100644 index 000000000000..4b48be6c7255 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/regression/ApiCommand.java @@ -0,0 +1,849 @@ +// 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.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +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 { + protected Logger logger = LogManager.getLogger(getClass()); + + 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) { + 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) { + logger.error("Unable to set parameter " + key + " for the command " + this.getName()); + } + } + this.command = temp; + 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) { + 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) { + 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) { + 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) { + logger.info("url is " + this.command); + } + + if (this.getCommandType() == CommandType.SCRIPT) { + try { + 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) { + 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; + 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) { + 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) { + logger.info("Response code is " + this.responseCode); + } + } catch (Exception ex) { + 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)) { + 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 { + logger.error("Following return parameter is missing: " + value); + result = false; + } + } catch (Exception ex) { + 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 { + 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 { + 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) { + 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)))) { + logger.error("Incorrect value for the following tag: " + key + ". Expected value is " + verifyParam.get(key) + " while actual value is " + + itemNameElement.getTextContent()); + result = false; + } + } else { + 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) { + 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)))) { + logger.error("Incorrect value for the following tag: " + key + ". Expected value is " + verifyParam.get(key) + + " while actual value is " + itemNameElement.getTextContent()); + result = false; + } + } else { + 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) { + 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) { + logger.error("Unable to get element from result set " + key); + } + + if (!(value.equals("no value")) && !(itemName.equals(verifyParam.get(key)))) { + 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"; + 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) { + 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++; + 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) { + logger.error(ex); + } + } else { + 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) { + 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) { + 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++; + 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) { + logger.debug("[ignored] interrupted while during async job result query."); + } + } else { + break; + } + method.releaseConnection(); + } else { + logger.error("Error during queryJobAsync. Error code is " + code); + this.responseCode = code; + return null; + } + } catch (Exception ex) { + 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 new file mode 100644 index 000000000000..661a42899324 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/regression/ConfigTest.java @@ -0,0 +1,123 @@ +// 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.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 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")) { + + 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); + + logger.info("SSHed successfully into management server " + this.getParam().get("hostip")); + + boolean isAuthenticated = conn.authenticateWithPassword("root", "password"); + + if (isAuthenticated == false) { + logger.info("Authentication failed for root with password"); + return false; + } + + String restartCommand = "service cloud-management restart; service cloud-usage restart"; + Session sess = conn.openSession(); + logger.info("Executing : " + restartCommand); + sess.execCommand(restartCommand); + Thread.sleep(120000); + sess.close(); + conn.close(); + + } catch (Exception ex) { + 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)) { + 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) { + 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) { + logger.error("Command " + api.getName() + " failed. Verification for returned parameters failed. Command was sent with url " + api.getUrl()); + error++; + } else if (api.getTestCaseInfo() != null) { + logger.info("Test case " + api.getTestCaseInfo() + " passed. Command was sent with the url " + api.getUrl()); + } + } + } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { + 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) { + logger.info("The command is required for the future use, so exiging"); + return false; + } + error++; + } else if (api.getTestCaseInfo() != null) { + 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 new file mode 100644 index 000000000000..65c3c1e53785 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/regression/DelegatedAdminTest.java @@ -0,0 +1,127 @@ +// 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.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 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)) { + 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)) { + logger.info("Test case " + api.getTestCaseInfo() + " passed"); + } else if ((api.getResponseType() == ResponseType.ERROR) && (api.getResponseCode() == 200)) { + 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) { + 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) { + logger.info("Test case " + api.getTestCaseInfo() + " passed"); + } + } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { + logger.error("Test case " + api.getTestCaseInfo() + " failed with an error code " + api.getResponseCode() + " . Command was sent with url " + + api.getUrl()); + if (api.getRequired() == true) { + logger.info("The command is required for the future use, so exiging"); + return false; + } + error++; + } else if (api.getTestCaseInfo() != null) { + 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 new file mode 100644 index 000000000000..ab62841270b7 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/regression/Deploy.java @@ -0,0 +1,107 @@ +// 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.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class Deploy extends TestCase { + + 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++; + logger.error("The command " + api.getUrl() + " failed"); + } else { + 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(); + + logger.info("Starting deployment against host " + host); + + boolean result = deploy.executeTest(); + if (result == false) { + logger.error("DEPLOYMENT FAILED"); + System.exit(1); + } else { + 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 new file mode 100644 index 000000000000..e05d6a95f1b3 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/regression/EventsApiTest.java @@ -0,0 +1,174 @@ +// 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.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 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); + + logger.info("Executing mysql command " + itemVariableElement.getTextContent()); + try { + Statement st = this.getConn().createStatement(); + st.executeUpdate(itemVariableElement.getTextContent()); + } catch (Exception ex) { + 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); + + logger.info("Attempting to SSH into agent " + itemVariableElement.getTextContent()); + try { + Connection conn = new Connection(itemVariableElement.getTextContent()); + conn.connect(null, 60000, 60000); + + logger.info("SSHed successfully into agent " + itemVariableElement.getTextContent()); + + boolean isAuthenticated = conn.authenticateWithPassword("root", "password"); + + if (isAuthenticated == false) { + logger.info("Authentication failed for root with password"); + return false; + } + + Session sess = conn.openSession(); + logger.info("Executing : " + commandElement.getTextContent()); + sess.execCommand(commandElement.getTextContent()); + Thread.sleep(60000); + sess.close(); + conn.close(); + + } catch (Exception ex) { + 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)) { + 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) { + logger.info("Test case " + api.getTestCaseInfo() + " passed. Empty response was returned as expected. Command was sent with url " + + api.getUrl()); + } else { + logger.error("Test case " + api.getTestCaseInfo() + " failed. Empty response was expected. Command was sent with url " + api.getUrl()); + } + } else { + if (api.isEmpty() != false) + 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) { + 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) { + logger.info("Test case " + api.getTestCaseInfo() + " passed. Command was sent with the url " + api.getUrl()); + } + } + } + } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { + logger.error("Command " + api.getName() + " failed with an error code " + api.getResponseCode() + " . Command was sent with url " + api.getUrl()); + if (api.getRequired() == true) { + logger.info("The command is required for the future use, so exiging"); + return false; + } + error++; + } else if (api.getTestCaseInfo() != null) { + 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"); + 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")); + 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 new file mode 100644 index 000000000000..b70d050011ed --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/regression/HA.java @@ -0,0 +1,78 @@ +// 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.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 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)) { + 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++; + 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++; + 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) { + 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; + } + 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 new file mode 100644 index 000000000000..52c459622c43 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/regression/LoadBalancingTest.java @@ -0,0 +1,140 @@ +// 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.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 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)) { + 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) { + logger.info("Test case " + api.getTestCaseInfo() + " passed"); + } else { + logger.error("Test case " + api.getTestCaseInfo() + " failed. Empty response was expected. Command was sent with url " + api.getUrl()); + } + } else { + if (api.isEmpty() != false) + 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) { + 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) { + logger.info("Test case " + api.getTestCaseInfo() + " passed"); + } + } + } + } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { + logger.error("Test case " + api.getTestCaseInfo() + " failed. Command was sent with url " + api.getUrl()); + if (api.getRequired() == true) { + logger.info("The command is required for the future use, so exiging"); + return false; + } + error++; + } else if (api.getTestCaseInfo() != null) { + 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++; +// logger.error("Can't create LB rule for the public port " + portValue + ". Request was sent with url " + url); +// } +// }catch (Exception ex) { +// 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++; +// logger.error("Can't create LB rule for the private port " + portValue + ". Request was sent with url " + url); +// } +// }catch (Exception ex) { +// 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 new file mode 100644 index 000000000000..40215c0ecb3e --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/regression/PortForwardingTest.java @@ -0,0 +1,141 @@ +// 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.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 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)) { + 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) { + logger.info("Test case " + api.getTestCaseInfo() + " passed"); + } else { + logger.error("Test case " + api.getTestCaseInfo() + " failed. Empty response was expected. Command was sent with url " + api.getUrl()); + } + } else { + if (api.isEmpty() != false) + 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) { + 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) { + logger.info("Test case " + api.getTestCaseInfo() + " passed"); + } + } + } + } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { + logger.error("Test case " + api.getTestCaseInfo() + " failed . Command was sent with url " + api.getUrl()); + if (api.getRequired() == true) { + logger.info("The command is required for the future use, so exiging"); + return false; + } + error++; + } else if (api.getTestCaseInfo() != null) { + 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 { +// 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++; +// logger.error("Can't create portForwarding rule for the public port " + portValue + ". Request was sent with url " + url); +// } +// }catch (Exception ex) { +// 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++; +// logger.error("Can't create portForwarding rule for the private port " + portValue + ". Request was sent with url " + url); +// } +// }catch (Exception ex) { +// 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 new file mode 100644 index 000000000000..eeeaf20b6d9c --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/regression/SanityTest.java @@ -0,0 +1,84 @@ +// 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.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class SanityTest extends TestCase { + + + 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)) { + 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++; + 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) { + 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) { + 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) { + 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")); + 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 new file mode 100644 index 000000000000..32057f6efaf2 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/regression/Test.java @@ -0,0 +1,86 @@ +// 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.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class Test extends TestCase { + + 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 { + 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++; + logger.error("Can't create portForwarding network rule for the public port " + portValue + ". Request was sent with url " + url); + } + } catch (Exception ex) { + 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 new file mode 100644 index 000000000000..26b534e976cd --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/regression/TestCase.java @@ -0,0 +1,139 @@ +// 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.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Document; + +public abstract class TestCase { + + public static Logger LOGGER = LogManager.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) { + 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) { + 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?" + TransactionLegacy.CONNECTION_PARAMS, "root", dbPassword); + if (!this.conn.isValid(0)) { + LOGGER.error("Connection to DB failed to establish"); + } + + } catch (Exception ex) { + 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) { + 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 new file mode 100644 index 000000000000..18f35e9ce6fd --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/regression/TestCaseEngine.java @@ -0,0 +1,276 @@ +// 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.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class TestCaseEngine { + + protected Logger logger = LogManager.getLogger(getClass()); + 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) { + logger.info("STARTING STRESS TEST IN " + s_numThreads + " THREADS"); + } else { + 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) { + 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) { + logger.error("Error in thread ", e); + } + } + } while (s_repeat); + } + }).start(); + } + + } catch (Exception exc) { + 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) { + 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) { + 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 { + 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")) { + logger.error("FAILURE!!! Test \"" + key + "\" failed\n\n\n"); + s_failure++; + } else { + finalResult = true; + logger.info("SUCCESS!!! Test \"" + key + "\" passed\n\n\n"); + } + + } catch (Exception ex) { + 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 new file mode 100644 index 000000000000..f7ef01a2ed26 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/regression/VMApiTest.java @@ -0,0 +1,89 @@ +// 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.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 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)) { + 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) { + 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) { + logger.error("Test " + api.getTestCaseInfo() + " failed. Verification for returned parameters failed. The command was sent with url " + + api.getUrl()); + error++; + } else { + logger.info("Test " + api.getTestCaseInfo() + " passed"); + } + } else if ((api.getResponseType() != ResponseType.ERROR) && (api.getResponseCode() != 200)) { + logger.error("Test case " + api.getTestCaseInfo() + " failed with an error code " + api.getResponseCode() + " . Command was sent with url " + + api.getUrl()); + if (api.getRequired() == true) { + logger.info("The command is required for the future use, so exiging"); + return false; + } + error++; + } else if (api.getTestCaseInfo() != null) { + 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 new file mode 100644 index 000000000000..6ebaadbffdca --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/stress/SshTest.java @@ -0,0 +1,91 @@ +// 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.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +import com.trilead.ssh2.Connection; +import com.trilead.ssh2.Session; + +public class SshTest { + + protected Logger logger = LogManager.getLogger(getClass()); + 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("")) { + logger.info("Did not receive a host back from test, ignoring ssh test"); + System.exit(2); + } + + if (password == null) { + logger.info("Did not receive a password back from test, ignoring ssh test"); + System.exit(2); + } + + try { + logger.info("Attempting to SSH into host " + host); + Connection conn = new Connection(host); + conn.connect(null, 60000, 60000); + + logger.info("User + ssHed successfully into host " + host); + + boolean isAuthenticated = conn.authenticateWithPassword("root", password); + + if (isAuthenticated == false) { + 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) { + 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 new file mode 100644 index 000000000000..d87677a6da42 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/stress/StressTestDirectAttach.java @@ -0,0 +1,1354 @@ +// 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.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +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; + protected Logger logger = LogManager.getLogger(getClass()); + 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; + logger.info("Starting test against server: " + server + " with " + numThreads + " thread(s)"); + if (cleanUp) + 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); + + 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) { + 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. + + logger.info("Begin Linux SSH test for account " + s_account.get()); + reason = sshTest(s_linuxIP.get(), s_linuxPassword.get()); + + if (reason == null) { + logger.info("Linux SSH test successful for account " + s_account.get()); + } + } + if (reason == null) { + if (internet) { + logger.info("Windows SSH test successful for account " + s_account.get()); + } else { + logger.info("deploy test successful....now cleaning up"); + if (cleanUp) { + logger.info("Waiting " + sleepTime + " ms before cleaning up vms"); + Thread.sleep(sleepTime); + } else { + success = true; + } + } + + if (usageIterator >= numThreads) { + int eventsAndBillingResponseCode = executeEventsAndBilling(server, developerServer); + logger.info("events and usage records command finished with response code: " + eventsAndBillingResponseCode); + usageIterator = 1; + + } else { + logger.info("Skipping events and usage records for this user: usageIterator " + usageIterator + " and number of Threads " + + numThreads); + usageIterator++; + } + + if ((users == null) && (accountName == null)) { + logger.info("Sending cleanup command"); + int cleanupResponseCode = executeCleanup(server, developerServer, username); + logger.info("cleanup command finished with response code: " + cleanupResponseCode); + success = (cleanupResponseCode == 200); + } else { + logger.info("Sending stop DomR / destroy VM command"); + int stopResponseCode = executeStop(server, developerServer, username); + logger.info("stop(destroy) command finished with response code: " + stopResponseCode); + success = (stopResponseCode == 200); + } + + } else { + // Just stop but don't destroy the + // VMs/Routers + logger.info("SSH test failed for account " + s_account.get() + "with reason '" + reason + "', stopping VMs"); + int stopResponseCode = executeStop(server, developerServer, username); + 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 + logger.info("Deploy test failed with reason '" + reason + "', stopping VMs"); + int stopResponseCode = executeStop(server, developerServer, username); + logger.info("stop command finished with response code: " + stopResponseCode); + success = false; // since the deploy test + // failed, mark the + // whole test as failure + } + + if (success) { + logger.info("***** Completed test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + " seconds"); + + } else { + logger.info("##### FAILED test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + + " seconds with reason : " + reason); + } + logger.info("Sleeping for " + wait + " seconds before starting next iteration"); + Thread.sleep(wait); + } catch (Exception e) { + logger.warn("Error in thread", e); + try { + int stopResponseCode = executeStop(server, developerServer, username); + logger.info("stop response code: " + stopResponseCode); + } catch (Exception e1) { + logger.info("[ignored]" + + "error executing stop during stress test: " + e1.getLocalizedMessage()); + } + } finally { + NDC.clear(); + } + } while (repeat); + } + }).start(); + } + } catch (Exception e) { + 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) { + 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) { + 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) { + logger.error("no " + tagNames[i] + " tag in XML response...returning null"); + } else { + returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); + } + } + } catch (Exception ex) { + logger.error("error processing XML", ex); + } + return returnValues; + } + + public static Map getSingleValueFromXML(Element rootElement, String[] tagNames) { + Map returnValues = new HashMap(); + if (rootElement == null) { + 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) { + logger.error("no " + tagNames[i] + " tag in XML response...returning null"); + } else { + returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); + } + } + } catch (Exception ex) { + 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) { + 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) { + 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(); + 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 { + 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"); + 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) { + logger.error("create user (" + username + ") failed to retrieve a valid user id, aborting depolyment test"); + return -1; + } + } + } else { + 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) { + logger.error("FAILED to retrieve secret key during registration, skipping user: " + username); + return -1; + } else { + logger.info("got secret key: " + s_secretKey.get()); + 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) { + logger.info("Create network rule response code: 401"); + return 401; + } else { + logger.info("Create security group response code: " + responseCode); + } + } else { + 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) { + logger.info("Authorise security group ingress response code: 401"); + return 401; + } else { + logger.info("Authorise security group ingress response code: " + responseCode); + } + } else { + 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)) { + logger.info("deploy linux vm response code: 401"); + return 401; + } else { + logger.info("deploy linux vm response code: " + responseCode); + long linuxVMId = Long.parseLong(values.get("id")); + 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 { + 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"; + 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) { + logger.info("create volume response code: 401"); + return 401; + } else { + logger.info("create volume response code: " + responseCode); + String volumeId = values.get("id"); + logger.info("got volume id: " + volumeId); + s_newVolume.set(volumeId); + } + } else { + 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(); + 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); + 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) { + logger.info("Attach volume response code: 401"); + return 401; + } else { + logger.info("Attach volume response code: " + responseCode); + } + } else { + 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)) { + logger.info("deploy linux vm response code: 401"); + return 401; + } else { + logger.info("deploy linux vm response code: " + responseCode); + long linuxVMId = Long.parseLong(values.get("id")); + logger.info("got linux virtual machine id: " + linuxVMId); + s_linuxVmId1.set(values.get("id")); + } + } else { + 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"; + 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) { + logger.info("create volume response code: 401"); + return 401; + } else { + logger.info("create volume response code: " + responseCode); + String volumeId = values.get("id"); + logger.info("got volume id: " + volumeId); + s_newVolume1.set(volumeId); + } + } else { + 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(); + 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); + 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) { + logger.info("Attach volume response code: 401"); + return 401; + } else { + logger.info("Attach volume response code: " + responseCode); + } + } else { + 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; + 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); + 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"))) { + logger.error("get user failed to retrieve requested user, aborting cleanup test" + ". Following URL was sent: " + url); + return -1; + } + + } else { + 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); + logger.info("update user response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map success = getSingleValueFromXML(is, new String[] {"success"}); + logger.info("update user..success? " + success.get("success")); + } else { + 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); + 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"}); + logger.info("VM was rebooted with the status: " + success.get("success")); + } else { + 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); + 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"}); + logger.info("VM was stopped with the status: " + success.get("success")); + } else { + 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); + 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) { + logger.info("Start linux vm response code: 401"); + return 401; + } else { + logger.info("Start vm response code: " + responseCode); + } + + logger.info("VM was started with the status: " + success.get("success")); + } else { + 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); +// logger.info("disable user response code: " + responseCode); +// if (responseCode == 200) { +// InputStream input = method.getResponseBodyAsStream(); +// Element el = queryAsyncJobResult(server, input); +// logger +// .info("Disabled user successfully"); +// } else { +// 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); + logger.info("delete user response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + logger.info("Deleted user successfully"); + } else { + 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(); + + logger.info("Getting events for the account " + s_account.get()); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + 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) { + logger.info("no events retrieved..."); + } else { + for (String text : descriptionText) { + logger.info("event: " + text); + } + } + } else { + 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; + logger.info("Stopping resources for user: " + username); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + 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) { + logger.error("get user failed to retrieve a valid user id, aborting depolyment test" + ". Following URL was sent: " + url); + return -1; + } + } + } else { + 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; + + 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); + 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]; + } + } + logger.info("got virtual machine ids: " + vmIdLogStr); + } + } + + } else { + 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); + 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"}); + logger.info("StopVirtualMachine..success? " + success.get("success")); + } else { + 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); +// logger.info("delete user response code: " + responseCode); +// if (responseCode == 200) { +// InputStream input = method.getResponseBodyAsStream(); +// Element el = queryAsyncJobResult(server, input); +// logger +// .info("Deleted user successfully"); +// } else { +// 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) { + logger.error("unable to sign request", ex); + } + return null; + } + + private static String sshWinTest(String host) { + if (host == null) { + 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) { + logger.info("Retry attempt : " + retry + " ...sleeping 300 seconds before next attempt. Account is " + s_account.get()); + Thread.sleep(300000); + } + + 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); + + 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 { + logger.info("Authentication is successful"); + } + + try { + SCPClient scp = new SCPClient(conn); + scp.put("wget.exe", "wget.exe", "C:\\Users\\Administrator", "0777"); + logger.info("Successfully put wget.exe file"); + } catch (Exception ex) { + logger.error("Unable to put wget.exe " + ex); + } + + if (conn == null) { + logger.error("Connection is null"); + } + Session sess = conn.openSession(); + + 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) { + 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 + 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) { + 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) { + logger.info("Did not receive a host back from test, ignoring ssh test"); + return null; + } + + if (password == null) { + 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) { + logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt. Account is " + s_account.get()); + Thread.sleep(120000); + } + + 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); + + logger.info("User + " + s_account.get() + " ssHed successfully into linux host " + host); + + boolean isAuthenticated = conn.authenticateWithPassword("root", password); + + if (isAuthenticated == false) { + 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(); + 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) { + 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 + 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++; + 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) { + logger.error("Unable to get a jobId"); + return null; + } + + //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); + //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) { + logger.debug("[ignored] interrupted while during async job result query."); + } + } else { + break; + } + + } catch (Exception ex) { + 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 new file mode 100644 index 000000000000..3bb65a3f1556 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/stress/TestClientWithAPI.java @@ -0,0 +1,2290 @@ +// 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.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +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; + protected Logger logger = LogManager.getLogger(getClass()); + 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; + logger.info("Starting test against server: " + server + " with " + numThreads + " thread(s)"); + if (cleanUp) + logger.info("Clean up is enabled, each test will wait " + sleepTime + " ms before cleaning up"); + + if (numOfUsers > 0) { + 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); + + 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) { + 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) { + logger.info("Begin Linux SSH test for account " + s_account.get()); + reason = sshTest(s_linuxIP.get(), s_linuxPassword.get(), snapshotTest); + } + + if (reason == null) { + logger.info("Linux SSH test successful for account " + s_account.get()); + 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 + // 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) ) { + // logger.error("Stopping all the resources for the account " + s_account.get() + + // " as network stat is incorrect"); + // int stopResponseCode = executeStop( + // server, developerServer, + // username, false); + // logger + // .info("stop command finished with response code: " + // + stopResponseCode); + // success = false; // since the SSH test + // + // } else + if (reason == null) { + if (internet) { + logger.info("Windows SSH test successful for account " + s_account.get()); + } else { + logger.info("deploy test successful....now cleaning up"); + if (cleanUp) { + logger.info("Waiting " + sleepTime + " ms before cleaning up vms"); + Thread.sleep(sleepTime); + } else { + success = true; + } + } + + if (usageIterator >= numThreads) { + int eventsAndBillingResponseCode = executeEventsAndBilling(server, developerServer); + logger.info("events and usage records command finished with response code: " + eventsAndBillingResponseCode); + usageIterator = 1; + + } else { + logger.info("Skipping events and usage records for this user: usageIterator " + usageIterator + " and number of Threads " + + numThreads); + usageIterator++; + } + + if ((users == null) && (accountName == null)) { + logger.info("Sending cleanup command"); + int cleanupResponseCode = executeCleanup(server, developerServer, username); + logger.info("cleanup command finished with response code: " + cleanupResponseCode); + success = (cleanupResponseCode == 200); + } else { + logger.info("Sending stop DomR / destroy VM command"); + int stopResponseCode = executeStop(server, developerServer, username, true); + logger.info("stop(destroy) command finished with response code: " + stopResponseCode); + success = (stopResponseCode == 200); + } + + } else { + // Just stop but don't destroy the + // VMs/Routers + logger.info("SSH test failed for account " + s_account.get() + "with reason '" + reason + "', stopping VMs"); + int stopResponseCode = executeStop(server, developerServer, username, false); + 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 + logger.info("Deploy test failed with reason '" + reason + "', stopping VMs"); + int stopResponseCode = executeStop(server, developerServer, username, true); + logger.info("stop command finished with response code: " + stopResponseCode); + success = false; // since the deploy test + // failed, mark the + // whole test as failure + } + + if (success) { + logger.info("***** Completed test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + " seconds"); + + } else { + logger.info("##### FAILED test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + + " seconds with reason : " + reason); + } + logger.info("Sleeping for " + wait + " seconds before starting next iteration"); + Thread.sleep(wait); + } catch (Exception e) { + logger.warn("Error in thread", e); + try { + int stopResponseCode = executeStop(server, developerServer, username, true); + logger.info("stop response code: " + stopResponseCode); + } catch (Exception e1) { + logger.info("[ignored]" + + "error executing stop during api test: " + e1.getLocalizedMessage()); + } + } finally { + NDC.clear(); + } + } while (repeat); + } + }).start(); + } + } catch (Exception e) { + 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) { + 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) { + 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) { + logger.error("no " + tagNames[i] + " tag in XML response...returning null"); + } else { + returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); + } + } + } catch (Exception ex) { + logger.error("error processing XML", ex); + } + return returnValues; + } + + public static Map getSingleValueFromXML(Element rootElement, String[] tagNames) { + Map returnValues = new HashMap(); + if (rootElement == null) { + 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) { + logger.error("no " + tagNames[i] + " tag in XML response...returning null"); + } else { + returnValues.put(tagNames[i], targetNodes.item(0).getTextContent()); + } + } + } catch (Exception ex) { + 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) { + 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) { + 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(); + 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 { + 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"); + 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) { + logger.error("create account (" + username + ") failed to retrieve a valid user id, aborting depolyment test"); + return -1; + } + } + } else { + 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"); + logger.info("listed user " + username + " with id " + userIdStr); + if (userIdStr != null) { + userId = Long.parseLong(userIdStr); + s_userId.set(userId); + if (userId == -1) { + logger.error("list user by username " + username + ") failed to retrieve a valid user id, aborting depolyment test"); + return -1; + } + } + } else { + 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) { + logger.error("FAILED to retrieve secret key during registration, skipping user: " + username); + return -1; + } else { + logger.info("got secret key: " + s_secretKey.get()); + 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"); + logger.info("Created virtual network with name virtualnetwork-" + encodedUsername + " and id " + networkIdStr); + if (networkIdStr != null) { + s_networkId.set(networkIdStr); + } + } else { + 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"); + logger.info("Created direct network with name directnetwork-" + encodedUsername + " and id " + networkIdStr); + if (networkIdStr != null) { + s_networkId_dir.set(networkIdStr); + } + } else { + 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)) { + logger.info("deploy linux vm response code: 401, the command was sent with url " + url); + return 401; + } else { + logger.info("deploy linux vm response code: " + responseCode); + long linuxVMId = Long.parseLong(values.get("id")); + 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); + logger.info("got linux virtual machine password: " + s_linuxPassword.get()); + } + } else { + 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)) { + logger.info("associate ip for Windows response code: 401, the command was sent with url " + url); + return 401; + } else { + logger.info("Associate IP Address response code: " + responseCode); + long publicIpId = Long.parseLong(values.get("id")); + logger.info("Associate IP's Id: " + publicIpId); + s_publicIpId.set(values.get("id")); + } + } else { + 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); + logger.info("url is " + url); + 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)); + logger.info("For Windows, using non-sourceNat IP address ID: " + ipAddressValues.get(0)); + logger.info("For Windows, using non-sourceNat IP address: " + ipAddressValues.get(1)); + } + } else { + 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); + logger.info("url is " + url); + 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)); + logger.info("For linux, using sourceNat IP address ID: " + ipAddressValues.get(0)); + logger.info("For linux, using sourceNat IP address: " + ipAddressValues.get(1)); + } + } else { + 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); + logger.info("url is " + url); + 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" }); + logger.info("Enable Static NAT..success? " + success.get("success")); + } else { + 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; + + 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"}); + logger.info("Port forwarding rule was assigned successfully to Linux VM"); + long ipfwdid = Long.parseLong(values.get("id")); + logger.info("got Port Forwarding Rule's Id:" + ipfwdid); + s_linipfwdid.set(values.get("id")); + + } else { + 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"; + logger.info("Getting rootDisk id of Centos vm"); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + 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) { + logger.error("Unable to get root volume for linux vm. Followin url was sent: " + url); + } + logger.info("Got rootVolume for linux vm with id " + success.get("id")); + s_rootVolume.set(success.get("id")); + } else { + 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; + logger.info("Creating recurring snapshot policy for linux vm ROOT disk"); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + logger.info("Create recurring snapshot policy for linux vm ROOT disk: " + responseCode); + if (responseCode != 200) { + 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)) { + logger.info("deploy windows vm response code: 401, the command was sent with url " + url); + return 401; + } else { + logger.info("deploy windows vm response code: " + responseCode); + windowsVMPrivateIP = values.get("ipaddress"); + long windowsVMId = Long.parseLong(values.get("id")); + logger.info("got windows virtual machine id: " + windowsVMId); + s_windowsVmId.set(values.get("id")); + } + } else { + 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); + logger.info("url is " + url); + 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"}); + logger.info("Enable Static NAT..success? " + success.get("success")); + } else { + 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"; + + 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"}); + logger.info("Port forwarding rule was assigned successfully to Windows VM"); + long ipfwdid = Long.parseLong(values.get("id")); + logger.info("got Ip Forwarding Rule's Id:" + ipfwdid); + s_winipfwdid.set(values.get("id")); + } else { + 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; + 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); + 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"))) { + logger.error("get user failed to retrieve requested user, aborting cleanup test" + ". Following URL was sent: " + url); + return -1; + } + + } else { + 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); + logger.info("update user response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map success = getSingleValueFromXML(is, new String[] {"success"}); + logger.info("update user..success? " + success.get("success")); + } else { + 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"; + logger.info("Getting dataDisk id of Centos vm"); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + logger.info("List volumes response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map success = getSingleValueFromXML(is, new String[] {"id"}); + logger.info("Got dataDiskVolume with id " + success.get("id")); + s_dataVolume.set(success.get("id")); + } else { + 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(); + logger.info("Detaching volume with id " + s_dataVolume.get()); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + logger.info("Detach data volume response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + logger.info("The volume was detached successfully"); + } else { + 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(); + logger.info("Deleting volume with id " + s_dataVolume.get()); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + logger.info("Delete data volume response code: " + responseCode); + if (responseCode == 200) { + logger.info("The volume was deleted successfully"); + } else { + 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"; + 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) { + logger.info("create volume response code: 401"); + return 401; + } else { + logger.info("create volume response code: " + responseCode); + long volumeId = Long.parseLong(values.get("id")); + logger.info("got volume id: " + volumeId); + s_newVolume.set(values.get("id")); + } + } else { + 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(); + 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); + logger.info("Attach data volume response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + logger.info("The volume was attached successfully"); + } else { + 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"; + logger.info("Getting rootDisk id of Centos vm"); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + 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) { + logger.error("Unable to get root volume. Followin url was sent: " + url); + } + logger.info("Got rootVolume with id " + success.get("id")); + s_rootVolume.set(success.get("id")); + } else { + 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); + 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) { + logger.info("create snapshot response code: 401"); + return 401; + } else { + logger.info("create snapshot response code: " + responseCode + ". Got snapshot with id " + values.get("id")); + s_snapshot.set(values.get("id")); + } + } else { + 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); + 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) { + logger.info("create volume from snapshot response code: 401"); + return 401; + } else { + 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 { + 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(); + 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); + logger.info("Attach volume from snapshot to linux vm response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + logger.info("The volume created from snapshot was attached successfully to linux vm"); + } else { + 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); + 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"}); + logger.info("Windows VM was rebooted with the status: " + success.get("success")); + } else { + 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); + 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"}); + logger.info("Linux VM was stopped with the status: " + success.get("success")); + } else { + 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); + 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) { + logger.info("create private template response code: 401"); + return 401; + } else { + logger.info("create private template response code: " + responseCode); + } + } else { + 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); + logger.info("Start linux Vm response code: " + responseCode); + if (responseCode != 200) { + 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); + logger.info("List domain routers response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map success = getSingleValueFromXML(is, new String[] {"id"}); + logger.info("Got the domR with id " + success.get("id")); + s_domainRouterId.set(success.get("id")); + } else { + 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(); + logger.info("Rebooting domR with id " + s_domainRouterId.get()); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + logger.info("Reboot domain router response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + logger.info("Domain router was rebooted successfully"); + } else { + 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); + logger.info("delete account response code: " + responseCode); + if (responseCode == 200) { + InputStream input = method.getResponseBodyAsStream(); + Element el = queryAsyncJobResult(server, input); + logger.info("Deleted account successfully"); + } else { + 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(); + + logger.info("Getting events for the account " + s_account.get()); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + 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) { + logger.info("no events retrieved..."); + } else { + for (String text : descriptionText) { + logger.info("event: " + text); + } + } + } else { + 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); + 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); + logger.info("generate usage records response code: " + responseCode); + if (responseCode == 200) { + InputStream is = method.getResponseBodyAsStream(); + Map successStr = getSingleValueFromXML(is, new String[] {"success"}); + logger.info("successfully generated usage records? " + successStr.get("success")); + } else { + 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) { + logger.error(ex); + } + + // -------------------------------- + // GET USAGE RECORDS + // -------------------------------- + url = server + "?command=listUsageRecords&startdate=2009-09-01&enddate=" + endDate + "&account=" + s_account.get() + "&domaindid=1"; + logger.info("Getting all usage records with request: " + url); + client = new HttpClient(); + method = new GetMethod(url); + responseCode = client.executeMethod(method); + 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); + } + } + logger.info("desc: " + desc + usage); + } + } + + } else { + 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); + 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)) { + 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 { + 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 { + logger.error("listAccountStatistics failed with error code: " + responseCode + ". Following URL was sent: " + url); + return false; + } + } catch (Exception ex) { + 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; + logger.info("Stopping resources for user: " + username); + HttpClient client = new HttpClient(); + HttpMethod method = new GetMethod(url); + int responseCode = client.executeMethod(method); + 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 { + logger.error("get user failed to retrieve a valid user id, aborting depolyment test" + ". Following URL was sent: " + url); + return -1; + } + } else { + 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; + + 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); + 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]; + } + } + logger.info("got virtual machine ids: " + vmIdLogStr); + } + } + + } else { + 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); + 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]; + } + } + logger.info("got IP addresses: " + ipAddressLogStr); + } + } + + } else { + 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); + 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"; + logger.info("got zones names: " + zoneNameLogStr); + } + } + + } else { + 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); + 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"; + logger.info("got accountstatistics: " + statLogStr); + } + } + + } else { + 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); + 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"; + logger.info("got template names: " + templateNameLogStr); + } + } + + } else { + 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); + 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]; + } + } + logger.info("got service offering names: " + serviceOfferingNameLogStr); + } + } + + } else { + 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); + 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"; + logger.info("got event descriptions: " + eventNameLogStr); + } + } + } else { + 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); + 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"}); + logger.info(cmdName + "..success? " + success.get("success")); + } else { + 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); + 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]; + } + } + logger.info("got ip addresses: " + ipAddrLogStr); + + } else { + 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; + + 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); + logger.info("IP forwarding rule was successfully deleted"); + + } else { + 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); + logger.info("url is " + url); + 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"}); + logger.info("Disable Static NAT..success? " + success.get("success")); + } else { + 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); + 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" }); + logger.info("disassociate ip address..success? " + success.get("success")); + } else { + 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) { + logger.error("unable to sign request", ex); + } + return null; + } + + private static String sshWinTest(String host) { + if (host == null) { + 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) { + logger.info("Retry attempt : " + retry + " ...sleeping 300 seconds before next attempt. Account is " + s_account.get()); + Thread.sleep(300000); + } + + 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); + + 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 { + logger.info("Authentication is successful"); + } + + try { + SCPClient scp = new SCPClient(conn); + scp.put("wget.exe", "wget.exe", "C:\\Users\\Administrator", "0777"); + logger.info("Successfully put wget.exe file"); + } catch (Exception ex) { + logger.error("Unable to put wget.exe " + ex); + } + + if (conn == null) { + logger.error("Connection is null"); + } + Session sess = conn.openSession(); + + 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) { + 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 + 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) { + 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) { + logger.info("Did not receive a host back from test, ignoring ssh test"); + return null; + } + + if (password == null) { + 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) { + logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt. Account is " + s_account.get()); + Thread.sleep(120000); + } + + 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); + + logger.info("User + " + s_account.get() + " ssHed successfully into linux host " + host); + + boolean isAuthenticated = conn.authenticateWithPassword("root", password); + + if (isAuthenticated == false) { + 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(); + 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) { + 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 + 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; + logger.info("Sleeping for " + sleep / 1000 / 60 + "minutes before executing next ssh test"); + Thread.sleep(sleep); + } + } catch (Exception e) { + retry++; + 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) { + logger.error("Unable to get a jobId"); + return null; + } + + // 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); + // 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) { + logger.debug("[ignored] interrupted while during async job result query."); + } + } else { + break; + } + + } catch (Exception ex) { + 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 new file mode 100644 index 000000000000..f62c41cd4578 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/stress/WgetTest.java @@ -0,0 +1,151 @@ +// 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.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +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; + protected Logger logger = LogManager.getLogger(getClass()); + 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("")) { + logger.info("Did not receive a host back from test, ignoring ssh test"); + System.exit(2); + } + + if (password == null) { + logger.info("Did not receive a password back from test, ignoring ssh test"); + System.exit(2); + } + int retry = 0; + + try { + if (retry > 0) { + logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt"); + Thread.sleep(120000); + } + + logger.info("Attempting to SSH into linux host " + host + " with retry attempt: " + retry); + + Connection conn = new Connection(host); + conn.connect(null, 60000, 60000); + + logger.info("User + ssHed successfully into linux host " + host); + + boolean isAuthenticated = conn.authenticateWithPassword("root", password); + + if (isAuthenticated == false) { + 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) { + 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 + 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++; + logger.error("SSH Linux Network test fail with error"); + if (retry == MAX_RETRY_LINUX) { + 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 new file mode 100644 index 000000000000..f9e678e25299 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/ui/AbstractSeleniumTestCase.java @@ -0,0 +1,55 @@ +// 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 new file mode 100644 index 000000000000..33eb3089265d --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteAISO.java @@ -0,0 +1,127 @@ +// 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) { + 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) { + 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) { + 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 new file mode 100644 index 000000000000..12dc98541124 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/ui/AddAndDeleteATemplate.java @@ -0,0 +1,126 @@ +// 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) { + 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) { + 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) { + 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 new file mode 100644 index 000000000000..3ba7be90953f --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/ui/UIScenarioTest.java @@ -0,0 +1,86 @@ +// 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) { + 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) { + 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 new file mode 100644 index 000000000000..0d2cb8644f6c --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/utils/ConsoleProxy.java @@ -0,0 +1,108 @@ +// 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 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 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; + 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) { + 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) { + 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 new file mode 100644 index 000000000000..e414f12df501 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/utils/IpSqlGenerator.java @@ -0,0 +1,89 @@ +// 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) { + 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 new file mode 100644 index 000000000000..6fe3a695d383 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/utils/ProxyLoadTemp.java @@ -0,0 +1,110 @@ +// 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; + + +public class ProxyLoadTemp { + 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; + logger.info("Started reading file"); + while (!eof) { + String line = consoleInput.readLine(); + logger.info("Line is " + line); + if (line == null) { + logger.info("Line " + numThreads + " is null"); + eof = true; + } else { + String[] result = null; + try { + logger.info("Starting parsing line " + line); + result = parseLine(line, "[,]"); + 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) { + logger.warn(ex); + } + } + + } + } catch (Exception e) { + logger.warn(e); + } + + } + + public static class ShutdownThread extends Thread { + ProxyLoadTemp temp; + + public ShutdownThread(ProxyLoadTemp temp) { + this.temp = temp; + } + + @Override + public void run() { + 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(); + } + 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(); + logger.info("Summary for all" + numThreads + " threads: Average response time is " + sum / numThreads + " milliseconds"); + 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 new file mode 100644 index 000000000000..97d674c3a36f --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/utils/SignEC2.java @@ -0,0 +1,144 @@ +// 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.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +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; + protected Logger logger = LogManager.getLogger(getClass()); + + 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) { + 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) { + logger.info("Please set host in tool.properties file"); + System.exit(1); + } + + if (port == null) { + logger.info("Please set port in tool.properties file"); + System.exit(1); + } + + if (url == null) { + logger.info("Please specify url with -u option"); + System.exit(1); + } + + if (secretkey == null) { + logger.info("Please set secretkey in tool.properties file"); + System.exit(1); + } + + if (prop.get("apikey") == null) { + logger.info("Please set apikey in tool.properties file"); + System.exit(1); + } + + if (prop.get("accesspoint") == null) { + 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) { + 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) { + logger.error(ex); + } + String url = "http://" + host + ":" + prop.getProperty("port") + "/" + prop.getProperty("accesspoint") + "?" + temp + "&Signature=" + encodedSignature; + 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 new file mode 100644 index 000000000000..95fd7b293745 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/utils/SignRequest.java @@ -0,0 +1,112 @@ +// 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 new file mode 100644 index 000000000000..176182168944 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/utils/SqlDataGenerator.java @@ -0,0 +1,49 @@ +// 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) { + 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 new file mode 100644 index 000000000000..088bdee3f0d1 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/utils/SubmitCert.java @@ -0,0 +1,199 @@ +// 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.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; + +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; + protected Logger logger = LogManager.getLogger(getClass()); + + 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) { + 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) { + logger.error("Please set path to certificate (including file name) with -c option"); + System.exit(1); + } + + if (secretKey == null) { + logger.error("Please set secretkey with -s option"); + System.exit(1); + } + + if (apiKey == null) { + logger.error("Please set apikey with -a option"); + System.exit(1); + } + + if (host == null) { + logger.error("Please set host in tool.properties file"); + System.exit(1); + } + + if (port == null) { + 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) { + 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; + 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) { + 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(); + 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 new file mode 100644 index 000000000000..c6d4a93b9b2e --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/utils/TestClient.java @@ -0,0 +1,386 @@ +// 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.logging.log4j.Logger; +import org.apache.logging.log4j.LogManager; +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; + protected Logger logger = LogManager.getLogger(getClass()); + 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; + logger.info("Starting test against server: " + server + " with " + numThreads + " thread(s)"); + if (cleanUp) + logger.info("Clean up is enabled, each test will wait " + sleepTime + " ms before cleaning up"); + + if (numOfUsers > 0) { + 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"; + 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) { + logger.info("Deploy successful...waiting 5 minute before SSH tests"); + Thread.sleep(300000L); // Wait 60 seconds so the linux VM can boot up. + + logger.info("Begin Linux SSH test"); + reason = sshTest(method.getResponseHeader("linuxIP").getValue()); + + if (reason == null) { + logger.info("Linux SSH test successful"); + logger.info("Begin Windows SSH test"); + reason = sshWinTest(method.getResponseHeader("windowsIP").getValue()); + } + } + if (reason == null) { + if (internet) { + logger.info("Windows SSH test successful"); + } else { + logger.info("deploy test successful....now cleaning up"); + if (cleanUp) { + logger.info("Waiting " + sleepTime + " ms before cleaning up vms"); + Thread.sleep(sleepTime); + } else { + success = true; + } + } + if (users == null) { + logger.info("Sending cleanup command"); + url = server + "?email=" + username + "&password=" + username + "&command=cleanup"; + } else { + 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 + 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(); + 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) { + logger.info("***** Completed test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + " seconds"); + } else { + logger.info("##### FAILED test for user : " + username + " in " + ((System.currentTimeMillis() - now) / 1000L) + + " seconds with reason : " + reason); + } + } catch (Exception e) { + 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) { + logger.info("[ignored]" + + "error while executing last resort stop attempt: " + e1.getLocalizedMessage()); + } + } finally { + NDC.clear(); + } + } while (repeat); + } + }).start(); + } + } catch (Exception e) { + logger.error(e); + } + } + + private static String sshWinTest(String host) { + if (host == null) { + 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) { + logger.info("Retry attempt : " + retry + " ...sleeping 300 seconds before next attempt"); + Thread.sleep(300000); + } + + logger.info("Attempting to SSH into windows host " + host + " with retry attempt: " + retry); + + Connection conn = new Connection(host); + conn.connect(null, 60000, 60000); + + 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(); + 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) { + 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 + 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) { + 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) { + logger.info("Retry attempt : " + retry + " ...sleeping 120 seconds before next attempt"); + Thread.sleep(120000); + } + + logger.info("Attempting to SSH into linux host " + host + " with retry attempt: " + retry); + + Connection conn = new Connection(host); + conn.connect(null, 60000, 60000); + + 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(); + 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) { + 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 + 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 new file mode 100644 index 000000000000..78ba001bb9c1 --- /dev/null +++ b/test/src-not-used/main/java/com/cloud/test/utils/UtilsForTest.java @@ -0,0 +1,210 @@ +// 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; + } + +} diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py index d980583c8ce9..5a218aace91b 100644 --- a/tools/apidoc/gen_toc.py +++ b/tools/apidoc/gen_toc.py @@ -274,9 +274,13 @@ 'deleteBucket': 'Object Store', 'listBuckets': 'Object Store', 'listVmsForImport': 'Virtual Machine', +<<<<<<< HEAD + 'importVm': 'Virtual Machine' +======= 'importVm': 'Virtual Machine', 'Webhook': 'Webhook', 'Webhooks': 'Webhook' +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 } diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py index 6acf6a8ad63e..584c9328b4c9 100755 --- a/tools/marvin/marvin/lib/base.py +++ b/tools/marvin/marvin/lib/base.py @@ -7227,6 +7227,8 @@ def update(self, apiclient, **kwargs): cmd.id = self.id [setattr(cmd, k, v) for k, v in list(kwargs.items())] return apiclient.updateBucket(cmd) +<<<<<<< HEAD +======= class Webhook: """Manage Webhook Life cycle""" @@ -7289,3 +7291,4 @@ def delete_deliveries(self, apiclient, **kwargs): cmd.webhookid = self.id [setattr(cmd, k, v) for k, v in list(kwargs.items())] return apiclient.deleteWebhookDelivery(cmd) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 diff --git a/tools/marvin/mvn-setup.py b/tools/marvin/mvn-setup.py index cabcf0dc6596..e7ea5facbb08 100755 --- a/tools/marvin/mvn-setup.py +++ b/tools/marvin/mvn-setup.py @@ -34,8 +34,11 @@ def replaceVersion(fname, version): with open(fname, 'r') as f: content = f.read() needle = '\nVERSION\s*=\s*[\'"][^\'"]*[\'"]' +<<<<<<< HEAD +======= # Ensure the version is PEP440 compliant version = version.replace('-', '+', 1) +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 replacement = '\nVERSION = "%s"' % version content = re.sub(needle, replacement, content, 1) with open(fname, 'w') as f: diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 26e8358779b5..32581480059f 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -60,8 +60,11 @@ "label.action.bulk.release.public.ip.address": "Bulk release public IP addresses", "label.action.cancel.maintenance.mode": "Cancel maintenance mode", "label.action.change.password": "Change password", +<<<<<<< HEAD +======= "label.action.clear.webhook.deliveries": "Clear deliveries", "label.action.delete.webhook.deliveries": "Delete deliveries", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.action.configure.stickiness": "Stickiness", "label.action.copy.iso": "Copy ISO", "label.action.copy.snapshot": "Copy Snapshot", @@ -585,7 +588,10 @@ "label.create.tungsten.routing.policy": "Create Tungsten-Fabric routing policy", "label.create.user": "Create User", "label.create.vpn.connection": "Create VPN connection", +<<<<<<< HEAD +======= "label.create.webhook": "Create Webhook", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.created": "Created", "label.creating": "Creating", "label.creating.iprange": "Creating IP ranges", @@ -595,7 +601,10 @@ "label.crosszones": "Cross zones", "label.currency": "Currency", "label.current": "Current", +<<<<<<< HEAD +======= "label.current.storage": "Current storage", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.currentpassword": "Current password", "label.custom": "Custom", "label.customconstrained": "Custom constrained", @@ -607,9 +616,12 @@ "label.data.disk": "Data disk", "label.data.disk.offering": "Data disk offering", "label.date": "Date", +<<<<<<< HEAD +======= "label.datetime.filter.period": "From {startDate} to {endDate}", "label.datetime.filter.starting": "Starting {startDate}.", "label.datetime.filter.up.to": "Up to {endDate}.", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.day": "Day", "label.day.of.month": "Day of month", "label.day.of.week": "Day of week", @@ -679,8 +691,11 @@ "label.delete.vpn.customer.gateway": "Delete VPN customer gateway", "label.delete.vpn.gateway": "Delete VPN gateway", "label.delete.vpn.user": "Delete VPN User", +<<<<<<< HEAD +======= "label.delete.webhook": "Delete Webhook", "label.delete.webhook.delivery": "Delete Webhook Delivery", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.deleteconfirm": "Please confirm that you would like to delete this", "label.deleting": "Deleting", "label.deleting.failed": "Deleting failed", @@ -739,7 +754,10 @@ "label.disable.storage": "Disable storage pool", "label.disable.vpc.offering": "Disable VPC offering", "label.disable.vpn": "Disable remote access VPN", +<<<<<<< HEAD +======= "label.disable.webhook": "Disable Webhook", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.disabled": "Disabled", "label.disconnected": "Last disconnected", "label.disk": "Disk", @@ -750,9 +768,13 @@ "label.disk.size": "Disk size", "label.disk.usage.info": "Disk usage information", "label.diskbytesreadrate": "Disk read rate (BPS)", +<<<<<<< HEAD +"label.diskbyteswriterate": "Disk write rate (BPS)", +======= "label.diskbytesreadratemax": "Max disk read rate (BPS)", "label.diskbyteswriterate": "Disk write rate (BPS)", "label.diskbyteswriteratemax": "Max disk write rate (BPS)", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.diskiopsmax": "Max IOPS", "label.diskiopsmin": "Min IOPS", "label.diskiopsreadrate": "Disk read rate (IOPS)", @@ -849,7 +871,10 @@ "label.enable.storage": "Enable storage pool", "label.enable.vpc.offering": "Enable VPC offering", "label.enable.vpn": "Enable remote access VPN", +<<<<<<< HEAD +======= "label.enable.webhook": "Enable Webhook", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.enabled": "Enabled", "label.encrypt": "Encrypt", "label.encryptroot": "Encrypt Root Disk", @@ -885,8 +910,11 @@ "label.esppolicy": "ESP policy", "label.esx.host": "ESX/ESXi host", "label.event": "Event", +<<<<<<< HEAD +======= "label.eventid": "Event", "label.eventtype": "Event type", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.event.archived": "Event(s) archived", "label.event.deleted": "Event(s) deleted", "label.event.timeline": "Event timeline", @@ -1002,7 +1030,10 @@ "label.hardware": "Hardware", "label.hasrules":"FW rules defined", "label.hastate": "HA state", +<<<<<<< HEAD +======= "label.headers": "Headers", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.header.backup.schedule": "You can set up recurring backup schedules by selecting from the available options below and applying your policy preference.", "label.header.volume.snapshot": "You can set up recurring Snapshot schedules by selecting from the available options below and applying your policy preference.", "label.header.volume.take.snapshot": "Please confirm that you want to take a Snapshot of this volume.", @@ -1297,8 +1328,11 @@ "label.managed.volumes": "Managed Volumes", "label.managedstate": "Managed state", "label.management": "Management", +<<<<<<< HEAD +======= "label.managementserverid": "Management server", "label.managementservername": "Management server", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.management.ips": "Management IP addresses", "label.management.server": "Management server", "label.management.servers": "Management servers", @@ -1378,7 +1412,11 @@ "label.miniops": "Min IOPS", "label.minmaxiops": "Min IOPS / Max IOPS", "label.minmembers": "Min members", +<<<<<<< HEAD +"label.minmemory": "Min memory (in MB)", +======= "label.minmemory": "Min. memory (MiB)", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.minorsequence": "Minor Sequence", "label.minsize": "Minimum size", "label.minute.past.hour": "minute(s) past the hour", @@ -1560,7 +1598,10 @@ "label.ovmnetworklabel": "OVM traffic label", "label.ovs": "OVS", "label.owner.account": "Owner Account", +<<<<<<< HEAD +======= "label.owner.type": "Owner type", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.owners": "Owners", "label.pa": "Palo Alto", "label.page": "page", @@ -1581,7 +1622,10 @@ "label.patp": "Palo Alto threat profile", "label.pavr": "Virtual router", "label.payload": "Payload", +<<<<<<< HEAD +======= "label.payloadurl": "Payload URL", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.pcidevice": "GPU", "label.pending.jobs": "Pending Jobs", "label.per.account": "Per Account", @@ -1729,11 +1773,17 @@ "label.readonly": "Read-Only", "label.reason": "Reason", "label.reboot": "Reboot", +<<<<<<< HEAD +"label.receivedbytes": "Bytes received", +"label.recover.vm": "Recover Instance", +"label.recovering": "Recovering", +======= "label.recent.deliveries": "Recent deliveries", "label.receivedbytes": "Bytes received", "label.recover.vm": "Recover Instance", "label.recovering": "Recovering", "label.redeliver": "Redeliver", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.redirect": "Redirect to:", "label.redirecturi": "Redirect URI", "label.redundantrouter": "Redundant router", @@ -1784,7 +1834,11 @@ "label.removing": "Removing", "label.replace.acl": "Replace ACL", "label.replace.acl.list": "Replace ACL list", +<<<<<<< HEAD +"label.report.bug": "Report issue", +======= "label.report.bug": "Ask a question or Report an issue", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.required": "Required", "label.requireshvm": "HVM", "label.requiresupgrade": "Requires upgrade", @@ -1812,7 +1866,10 @@ "label.resources": "Resources", "label.resourcestate": "Resource state", "label.resourcetype": "Resource type", +<<<<<<< HEAD +======= "label.response": "Response", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.restart.network": "Restart Network", "label.restart.vpc": "Restart VPC", "label.restartrequired": "Restart required", @@ -1919,7 +1976,10 @@ "label.select.tier": "Select Network Tier", "label.select.zones": "Select zones", "label.select.2fa.provider": "Select the provider", +<<<<<<< HEAD +======= "label.selected.storage": "Selected storage", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.self": "Mine", "label.selfexecutable": "Self", "label.semanticversion": "Semantic version", @@ -2022,7 +2082,10 @@ "label.sshkeypair": "New SSH key pair", "label.sshkeypairs": "SSH key pairs", "label.sslcertificates": "SSL certificates", +<<<<<<< HEAD +======= "label.sslverification": "SSL verification", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.standard.us.keyboard": "Standard (US) keyboard", "label.start": "Start", "label.start.date.and.time": "Start date and time", @@ -2143,8 +2206,11 @@ "label.templatetype": "Template type", "label.templateversion": "Template version", "label.term.type": "Term type", +<<<<<<< HEAD +======= "label.test": "Test", "label.test.webhook.delivery": "Test Webhook Delivery", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.tftpdir": "TFTP root directory", "label.theme.alert": "The setting is only visible to the current browser. To apply the setting, please download the JSON file and replace its content in the `theme` section of the `config.json` file under the path: `/public/config.json`", "label.theme.color": "Theme color", @@ -2248,7 +2314,10 @@ "label.update.to": "updated to", "label.update.traffic.label": "Update traffic labels", "label.update.vmware.datacenter": "Update VMWare datacenter", +<<<<<<< HEAD +======= "label.update.webhook": "Update Webhook", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.updating": "Updating", "label.upgrade.router.newer.template": "Upgrade router to use newer Template", "label.upgrading": "Upgrading", @@ -2427,10 +2496,13 @@ "label.warn": "Warn", "label.warn.upper": "WARN", "label.warning": "Warning", +<<<<<<< HEAD +======= "label.webhook": "Webhook", "label.webhooks": "Webhooks", "label.webhookname": "Webhook", "label.webhook.deliveries": "Webhook deliveries", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.wednesday": "Wednesday", "label.weekly": "Weekly", "label.welcome": "Welcome", @@ -2579,7 +2651,10 @@ "message.add.ip.v6.firewall.rule.failed": "Failed to add IPv6 firewall rule", "message.add.ip.v6.firewall.rule.processing": "Adding IPv6 firewall rule...", "message.add.ip.v6.firewall.rule.success": "Added IPv6 firewall rule", +<<<<<<< HEAD +======= "message.redeliver.webhook.delivery": "Redeliver this Webhook delivery", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "message.remove.ip.v6.firewall.rule.failed": "Failed to remove IPv6 firewall rule", "message.remove.ip.v6.firewall.rule.processing": "Removing IPv6 firewall rule...", "message.remove.ip.v6.firewall.rule.success": "Removed IPv6 firewall rule", @@ -2691,14 +2766,20 @@ "message.confirm.disable.provider": "Please confirm that you would like to disable this provider.", "message.confirm.disable.storage": "Please confirm that you want to disable the storage pool.", "message.confirm.disable.vpc.offering": "Are you sure you want to disable this VPC offering?", +<<<<<<< HEAD +======= "message.confirm.disable.webhook": "Please confirm that you want to disable this webhook.", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "message.confirm.enable.autoscale.vmgroup": "Please confirm that you want to enable this autoscale Instance group.", "message.confirm.enable.host": "Please confirm that you want to enable the host.", "message.confirm.enable.network.offering": "Are you sure you want to enable this Network offering?", "message.confirm.enable.provider": "Please confirm that you would like to enable this provider.", "message.confirm.enable.storage": "Please confirm that you want to enable the storage pool.", "message.confirm.enable.vpc.offering": "Are you sure you want to enable this VPC offering?", +<<<<<<< HEAD +======= "message.confirm.enable.webhook": "Please confirm that you want to enable this webhook.", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "message.confirm.remove.firewall.rule": "Please confirm that you want to delete this Firewall Rule?", "message.confirm.remove.ip.range": "Please confirm that you would like to remove this IP range.", "message.confirm.remove.network.offering": "Are you sure you want to remove this Network offering?", @@ -2780,8 +2861,11 @@ "message.delete.vpn.connection": "Please confirm that you want to delete VPN connection.", "message.delete.vpn.customer.gateway": "Please confirm that you want to delete this VPN customer gateway.", "message.delete.vpn.gateway": "Please confirm that you want to delete this VPN Gateway.", +<<<<<<< HEAD +======= "message.delete.webhook": "Please confirm that you want to delete this Webhook.", "message.delete.webhook.delivery": "Please confirm that you want to delete this Webhook delivery.", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "message.deleting.firewall.policy": "Deleting Firewall Policy", "message.deleting.node": "Deleting Node", "message.deleting.vm": "Deleting Instance", @@ -2819,7 +2903,10 @@ "message.disable.vpn": "Are you sure you want to disable VPN?", "message.disable.vpn.failed": "Failed to disable VPN.", "message.disable.vpn.processing": "Disabling VPN...", +<<<<<<< HEAD +======= "message.disable.webhook.ssl.verification": "Disabling SSL verification is not recommended", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "message.discovering.feature": "Discovering features, please wait...", "message.disk.offering.created": "Disk offering created:", "message.disk.usage.info.data.points": "Each data point represents the difference in read/write data since the last data point.", @@ -2994,9 +3081,12 @@ "message.error.zone.type": "Please select zone type.", "message.error.linstor.resourcegroup": "Please enter the Linstor Resource-Group.", "message.error.fixed.offering.kvm": "It's not possible to scale up Instances that utilize KVM hypervisor with a fixed compute offering.", +<<<<<<< HEAD +======= "message.error.create.webhook.local.account": "Account must be provided for creating a Webhook with Local scope.", "message.error.create.webhook.name": "Name must be provided for creating a Webhook.", "message.error.create.webhook.payloadurl": "Payload URL must be provided for creating a Webhook.", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "message.fail.to.delete": "Failed to delete.", "message.failed.to.add": "Failed to add", "message.failed.to.assign.vms": "Failed to assign Instances", @@ -3086,7 +3176,11 @@ "message.migrate.resource.to.ss": "Please confirm that you want to migrate this resource to another secondary storage.", "message.migrate.router.confirm": "Please confirm the host you wish to migrate the router to:", "message.migrate.systemvm.confirm": "Please confirm the host you wish to migrate the system VM to:", +<<<<<<< HEAD +"message.migrate.volume": "Please confirm that you want to migrate this volume to another primary storage.", +======= "message.migrate.volume": "Please confirm that you want to migrate the volume \"{volume}\" from \"{storage}\" to another primary storage.", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "message.migrate.volume.failed": "Migrating volume failed.", "message.migrate.volume.pool.auto.assign": "Primary storage for the volume will be automatically chosen based on the suitability and Instance destination", "message.migrate.volume.processing": "Migrating volume...", @@ -3190,7 +3284,10 @@ "message.scaleup.policy.name.continue": "Please input a name to ScaleUp policy to continue", "message.select.a.zone": "A zone typically corresponds to a single datacenter. Multiple zones help make the cloud more reliable by providing physical isolation and redundancy.", "message.select.affinity.groups": "Please select any affinity groups you want this Instance to belong to:", +<<<<<<< HEAD +======= "message.select.deselect.desired.options": "Please select / deselect the desired options", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "message.select.deselect.to.sort": "Please select / deselect to sort the values", "message.select.destination.image.stores": "Please select Image Store(s) to which data is to be migrated to", "message.select.disk.offering": "Please select a disk offering for disk", @@ -3257,7 +3354,10 @@ "message.success.change.affinity.group": "Successfully changed affinity groups", "message.success.change.offering": "Successfully changed offering", "message.success.change.password": "Successfully changed password for User", +<<<<<<< HEAD +======= "message.success.clear.webhook.deliveries": "Successfully cleared webhook deliveries", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "message.success.config.backup.schedule": "Successfully configured Instance backup schedule", "message.success.config.health.monitor": "Successfully Configure Health Monitor", "message.success.config.sticky.policy": "Successfully configured sticky policy", @@ -3274,7 +3374,10 @@ "message.success.create.template": "Successfully created Template", "message.success.create.user": "Successfully created User", "message.success.create.volume": "Successfully created volume", +<<<<<<< HEAD +======= "message.success.create.webhook": "Successfully created Webhook", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "message.success.delete": "Successfully deleted", "message.success.delete.acl.rule": "Successfully removed ACL rule", "message.success.delete.backup.schedule": "Successfully deleted configure Instance backup schedule", @@ -3360,7 +3463,10 @@ "message.update.autoscale.vm.profile.failed": "Failed to update autoscale Instance profile", "message.update.condition.failed": "Failed to update condition", "message.update.condition.processing": "Updating condition...", +<<<<<<< HEAD +======= "message.test.webhook.delivery": "Test delivery to the Webhook with an optional payload", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "message.two.factor.authorization.failed": "Unable to verify 2FA with provided code, please retry.", "message.two.fa.auth": "Open the two-factor authentication app on your mobile device to view your authentication code.", "message.two.fa.auth.register.account": "Open the two-factor authentication application and scan the QR code add the User Account.", @@ -3449,7 +3555,10 @@ "message.warn.filetype": "jpg, jpeg, png, bmp and svg are the only supported image formats.", "message.warn.importing.instance.without.nic": "WARNING: This Instance is being imported without NICs and many Network resources will not be available. Consider creating a NIC via vCenter before importing or as soon as the Instance is imported.", "message.warn.zone.mtu.update": "Please note that this limit won't affect pre-existing Network’s MTU settings", +<<<<<<< HEAD +======= "message.webhook.deliveries.time.filter": "Webhook deliveries list can be filtered based on date-time. Select 'Custom' for specifying start and end date range.", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "message.zone.creation.complete": "Zone creation complete.", "message.zone.detail.description": "Populate zone details.", "message.zone.detail.hint": "A zone is the largest organizational unit in CloudStack, and it typically corresponds to a single datacenter. Zones provide physical isolation and redundancy. A zone consists of one or more pods (each of which contains hosts and primary storage servers) and a secondary storage server which is shared by all pods in the zone.", diff --git a/ui/public/locales/pt_BR.json b/ui/public/locales/pt_BR.json index fec66ba4cef4..3a6fe8cadeaa 100644 --- a/ui/public/locales/pt_BR.json +++ b/ui/public/locales/pt_BR.json @@ -445,7 +445,10 @@ "label.crosszones": "Inter zonas", "label.currency": "Moeda", "label.current": "Atual", +<<<<<<< HEAD +======= "label.current.storage": "Armazenamento atual", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.currentpassword": "Senha antiga", "label.custom": "Customizado", "label.customconstrained": "Customizado limitado", @@ -548,9 +551,13 @@ "label.disk.size": "Tamanho do disco", "label.disk.usage.info": "Informa\u00e7\u00f5es sobre o uso de disco", "label.diskbytesreadrate": "Taxa de leitura de bytes do disco (BPS)", +<<<<<<< HEAD +"label.diskbyteswriterate": "Taxa de escrita de bytes no disco (BPS)", +======= "label.diskbytesreadratemax": "Taxa m\u00e1xima de leitura de bytes do disco (BPS)", "label.diskbyteswriterate": "Taxa de escrita de bytes no disco (BPS)", "label.diskbyteswriteratemax": "Taxa m\u00e1xima de escrita de bytes no disco (BPS)", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.diskiopsmax": "M\u00e1x IOPS", "label.diskiopsmin": "M\u00edn IOPS", "label.diskiopsreadrate": "Taxa de leitura do disco (IOPS)", @@ -1158,7 +1165,10 @@ "label.ovmnetworklabel": "R\u00f3tulo de tr\u00e1fego OVM", "label.ovs": "OVS", "label.owner.account": "Dono da conta", +<<<<<<< HEAD +======= "label.owner.type": "Tipo de dono", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.owners": "Donos", "label.pa": "Palo Alto", "label.page": "p\u00e1gina", @@ -1445,7 +1455,10 @@ "label.select.projects": "Selecionar projetos", "label.select.tier": "Selecionar camada", "label.select.zones": "Selecionar zonas", +<<<<<<< HEAD +======= "label.selected.storage": "Armazenamento selecionado", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "label.self": "Meus", "label.selfexecutable": "Auto", "label.semanticversion": "Vers\u00e3o sem\u00e2ntica", @@ -2239,7 +2252,11 @@ "message.migrate.instance.to.ps": "Por favor confirme que voc\u00ea deseja migrar a inst\u00e2ncia para outro armazenamento prim\u00e1rio.", "message.migrate.router.confirm": "Por favor confirme o host que voc\u00ea deseja migrar o roteador para:", "message.migrate.systemvm.confirm": "Por favor confirme o host para o qual voc\u00ea deseja migrar a VM de sistema:", +<<<<<<< HEAD +"message.migrate.volume": "Por favor confirme que voc\u00ea deseja migrar o volume para outro armazenamento prim\u00e1rio.", +======= "message.migrate.volume": "Por favor confirme que voc\u00ea deseja migrar o volume \"{volume}\" do armazenamento prim\u00e1rio \"{storage}\" para outro.", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "message.migrate.volume.failed": "Falha ao migrar volume", "message.migrate.volume.processing": "Migrando volume...", "message.migrating.failed": "Falha na migra\u00e7\u00e3o", @@ -2322,7 +2339,10 @@ "message.scale.processing": "Escalonamento em progresso", "message.select.a.zone": "A zona tipicamente corresponde a um \u00fanico datacenter. M\u00faltiplas zonas auxiliam a nuvem a ser mais confi\u00e1vel provendo isolamento f\u00edsico e redund\u00e2ncia.", "message.select.affinity.groups": "Por favor, selecione quaisquer grupos de afinidade que voc\u00ea deseja que esta VM perten\u00e7a:", +<<<<<<< HEAD +======= "message.select.deselect.desired.options": "Por favor, selecione / desselecione as op\u00e7\u00f5es desejadas", +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 "message.select.destination.image.stores": "Por favor, selecione o(s) armazenamento(s) de imagem(ns) para os quais os dados devem ser migrados", "message.select.disk.offering": "Por favor, selecione uma oferta de disco para o disco", "message.select.end.date.and.time": "Selecione uma data e hor\u00e1rio final.", diff --git a/ui/src/components/header/CreateMenu.vue b/ui/src/components/header/CreateMenu.vue index e80120d7a1cd..9ae246ab3be0 100644 --- a/ui/src/components/header/CreateMenu.vue +++ b/ui/src/components/header/CreateMenu.vue @@ -16,25 +16,157 @@ // under the License. +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002
diff --git a/ui/src/components/view/ListView.vue b/ui/src/components/view/ListView.vue index 2b1036a293dc..02ca16461596 100644 --- a/ui/src/components/view/ListView.vue +++ b/ui/src/components/view/ListView.vue @@ -23,7 +23,11 @@ :dataSource="items" :rowKey="(record, idx) => record.id || record.name || record.usageType || idx + '-' + Math.random()" :pagination="false" +<<<<<<< HEAD + :rowSelection=" enableGroupAction() || $route.name === 'event' ? {selectedRowKeys: selectedRowKeys, onChange: onSelectChange, columnWidth: 30} : null" +======= :rowSelection="explicitlyAllowRowSelection || enableGroupAction() || $route.name === 'event' ? {selectedRowKeys: selectedRowKeys, onChange: onSelectChange, columnWidth: 30} : null" +>>>>>>> 9e53596ba92eaec1289e97bfc9f441cc3c507002 :rowClassName="getRowClassName" style="overflow-y: auto" > @@ -364,12 +368,18 @@ {{ record.enabled ? 'Enabled' : 'Disabled' }} +<<<<<<< HEAD +