diff --git a/agent-simulator/tomcatconf/components-simulator.xml.in b/agent-simulator/tomcatconf/components-simulator.xml.in
deleted file mode 100755
index 1b7df46ad2b..00000000000
--- a/agent-simulator/tomcatconf/components-simulator.xml.in
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-
-
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- true
-
-
-
-
diff --git a/api/src/com/cloud/agent/api/to/DnsmasqTO.java b/api/src/com/cloud/agent/api/to/DnsmasqTO.java
index f99878c2fed..c7be04d4900 100644
--- a/api/src/com/cloud/agent/api/to/DnsmasqTO.java
+++ b/api/src/com/cloud/agent/api/to/DnsmasqTO.java
@@ -20,11 +20,14 @@ public class DnsmasqTO {
String routerIp;
String gateway;
String netmask;
+ String startIpOfSubnet;
- public DnsmasqTO(String routerIp, String gateway, String netmask) {
+ public DnsmasqTO(String routerIp, String gateway, String netmask, String StartIpOfSubnet) {
this.routerIp = routerIp;
+ this.startIpOfSubnet = StartIpOfSubnet;
this.gateway = gateway;
this.netmask =netmask;
+
}
public void setRouterIp(String routerIp){
@@ -39,6 +42,10 @@ public class DnsmasqTO {
this.netmask = netmask ;
}
+ public void setStartIpOfSubnet( String ipOfSubNet) {
+ startIpOfSubnet = ipOfSubNet;
+ }
+
public String getRouterIp() {
return routerIp;
}
@@ -50,4 +57,8 @@ public class DnsmasqTO {
public String getNetmask() {
return netmask;
}
+ public String getStartIpOfSubnet() {
+ return startIpOfSubnet;
+ }
+
}
diff --git a/api/src/com/cloud/dc/DedicatedResources.java b/api/src/com/cloud/dc/DedicatedResources.java
new file mode 100755
index 00000000000..e8e5ab3dffc
--- /dev/null
+++ b/api/src/com/cloud/dc/DedicatedResources.java
@@ -0,0 +1,33 @@
+// 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.dc;
+
+import org.apache.cloudstack.acl.InfrastructureEntity;
+import org.apache.cloudstack.api.Identity;
+import org.apache.cloudstack.api.InternalIdentity;
+
+public interface DedicatedResources extends InfrastructureEntity, InternalIdentity, Identity{
+ long getId();
+ Long getDataCenterId();
+ Long getPodId();
+ Long getClusterId();
+ Long getHostId();
+ Long getDomainId();
+ Long getAccountId();
+ String getUuid();
+
+}
diff --git a/api/src/com/cloud/deploy/DeploymentClusterPlanner.java b/api/src/com/cloud/deploy/DeploymentClusterPlanner.java
index b12b93e728e..ca73267e732 100644
--- a/api/src/com/cloud/deploy/DeploymentClusterPlanner.java
+++ b/api/src/com/cloud/deploy/DeploymentClusterPlanner.java
@@ -39,6 +39,7 @@ public interface DeploymentClusterPlanner extends DeploymentPlanner {
List orderClusters(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid)
throws InsufficientServerCapacityException;
- PlannerResourceUsage getResourceUsage();
+ PlannerResourceUsage getResourceUsage(VirtualMachineProfile vmProfile,
+ DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException;
}
diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java
index 6dfb1ab57b6..ed4ba1254f0 100755
--- a/api/src/com/cloud/event/EventTypes.java
+++ b/api/src/com/cloud/event/EventTypes.java
@@ -438,6 +438,10 @@ public class EventTypes {
public static final String EVENT_PORTABLE_IP_RANGE_DELETE = "PORTABLE.IP.RANGE.DELETE";
public static final String EVENT_PORTABLE_IP_TRANSFER = "PORTABLE.IP.TRANSFER";
+ // Dedicated Resources
+ public static final String EVENT_DEDICATE_RESOURCE = "DEDICATE.RESOURCE";
+ public static final String EVENT_DEDICATE_RESOURCE_RELEASE = "DEDICATE.RESOURCE.RELEASE";
+
static {
// TODO: need a way to force author adding event types to declare the entity details as well, with out braking
diff --git a/api/src/com/cloud/region/ha/GlobalLoadBalancingRulesService.java b/api/src/com/cloud/region/ha/GlobalLoadBalancingRulesService.java
index 4cdf8081620..1a69be49846 100644
--- a/api/src/com/cloud/region/ha/GlobalLoadBalancingRulesService.java
+++ b/api/src/com/cloud/region/ha/GlobalLoadBalancingRulesService.java
@@ -39,6 +39,9 @@ public interface GlobalLoadBalancingRulesService {
GlobalLoadBalancerRule updateGlobalLoadBalancerRule(UpdateGlobalLoadBalancerRuleCmd updateGslbCmd);
+ boolean revokeAllGslbRulesForAccount(com.cloud.user.Account caller, long accountId)
+ throws com.cloud.exception.ResourceUnavailableException;
+
/*
* methods for managing sites participating in global load balancing
*/
diff --git a/api/src/com/cloud/user/AccountService.java b/api/src/com/cloud/user/AccountService.java
index b8a0b7f45ba..8153a3f1af6 100755
--- a/api/src/com/cloud/user/AccountService.java
+++ b/api/src/com/cloud/user/AccountService.java
@@ -16,7 +16,6 @@
// under the License.
package com.cloud.user;
-import java.util.List;
import java.util.Map;
import org.apache.cloudstack.acl.ControlledEntity;
@@ -26,7 +25,6 @@ import org.apache.cloudstack.api.command.admin.user.RegisterCmd;
import com.cloud.domain.Domain;
import com.cloud.exception.PermissionDeniedException;
-import com.cloud.utils.Pair;
public interface AccountService {
@@ -78,13 +76,11 @@ public interface AccountService {
Account finalizeOwner(Account caller, String accountName, Long domainId, Long projectId);
- Pair, Long> finalizeAccountDomainForList(Account caller, String accountName, Long domainId, Long projectId);
-
Account getActiveAccountByName(String accountName, Long domainId);
- Account getActiveAccountById(Long accountId);
+ Account getActiveAccountById(long accountId);
- Account getAccount(Long accountId);
+ Account getAccount(long accountId);
User getActiveUser(long userId);
diff --git a/api/src/com/cloud/vm/VmDiskStats.java b/api/src/com/cloud/vm/VmDiskStats.java
new file mode 100644
index 00000000000..0cf82d0047d
--- /dev/null
+++ b/api/src/com/cloud/vm/VmDiskStats.java
@@ -0,0 +1,30 @@
+// 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.vm;
+
+public interface VmDiskStats {
+ // vm related disk stats
+
+ public Long getIORead();
+
+ public Long getIOWrite();
+
+ public Long getBytesRead();
+
+ public Long getBytesWrite();
+
+}
diff --git a/api/src/com/cloud/vm/VmStats.java b/api/src/com/cloud/vm/VmStats.java
index 7d0bd61b9d8..d284db0f64a 100644
--- a/api/src/com/cloud/vm/VmStats.java
+++ b/api/src/com/cloud/vm/VmStats.java
@@ -23,5 +23,13 @@ public interface VmStats {
public double getNetworkReadKBs();
public double getNetworkWriteKBs();
+
+ public double getDiskReadIOs();
+
+ public double getDiskWriteIOs();
+
+ public double getDiskReadKBs();
+
+ public double getDiskWriteKBs();
}
diff --git a/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java b/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java
index 26c32c89c1f..7423c4864d5 100644
--- a/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java
+++ b/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java
@@ -18,7 +18,6 @@ package org.apache.cloudstack.affinity;
import java.util.List;
-import com.cloud.exception.ResourceInUseException;
import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
@@ -45,10 +44,8 @@ public interface AffinityGroupService {
* @param account
* @param domainId
* @param affinityGroupName
- * @throws ResourceInUseException
*/
- boolean deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName)
- throws ResourceInUseException;
+ boolean deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName);
/** Lists Affinity Groups in your account
* @param account
diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java
index 1e9435f6a8e..ab1402ccde9 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -206,6 +206,7 @@ public class ApiConstants {
public static final String STATE = "state";
public static final String STATUS = "status";
public static final String STORAGE_TYPE = "storagetype";
+ public static final String STORAGE_MOTION_ENABLED = "storagemotionenabled";
public static final String SYSTEM_VM_TYPE = "systemvmtype";
public static final String TAGS = "tags";
public static final String TARGET_IQN = "targetiqn";
@@ -304,6 +305,8 @@ public class ApiConstants {
public static final String TEMPLATE_TAG = "templatetag";
public static final String HYPERVISOR_VERSION = "hypervisorversion";
public static final String MAX_GUESTS_LIMIT = "maxguestslimit";
+ public static final String MAX_DATA_VOLUMES_LIMIT = "maxdatavolumeslimit";
+ public static final String MAX_HOSTS_PER_CLUSTER = "maxhostspercluster";
public static final String PROJECT_ID = "projectid";
public static final String PROJECT_IDS = "projectids";
public static final String PROJECT = "project";
@@ -402,6 +405,7 @@ public class ApiConstants {
public static final String VSM_CONFIG_MODE = "vsmconfigmode";
public static final String VSM_CONFIG_STATE = "vsmconfigstate";
public static final String VSM_DEVICE_STATE = "vsmdevicestate";
+ public static final String VCENTER = "vcenter";
public static final String ADD_VSM_FLAG = "addvsmflag";
public static final String END_POINT = "endpoint";
public static final String REGION_ID = "regionid";
diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java
index ba01a7914c6..4a0eb028860 100644
--- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java
+++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java
@@ -21,15 +21,8 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Map;
-import com.cloud.vm.NicSecondaryIp;
import org.apache.cloudstack.affinity.AffinityGroup;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
-import com.cloud.network.vpc.NetworkACL;
-import com.cloud.network.vpc.NetworkACLItem;
-import com.cloud.network.vpc.PrivateGateway;
-import com.cloud.network.vpc.StaticRoute;
-import com.cloud.network.vpc.Vpc;
-import com.cloud.network.vpc.VpcOffering;
import org.apache.cloudstack.api.ApiConstants.HostDetails;
import org.apache.cloudstack.api.ApiConstants.VMDetails;
import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
@@ -66,6 +59,7 @@ import org.apache.cloudstack.api.response.LBHealthCheckResponse;
import org.apache.cloudstack.api.response.LBStickinessResponse;
import org.apache.cloudstack.api.response.LDAPConfigResponse;
import org.apache.cloudstack.api.response.LoadBalancerResponse;
+import org.apache.cloudstack.api.response.NetworkACLItemResponse;
import org.apache.cloudstack.api.response.NetworkACLResponse;
import org.apache.cloudstack.api.response.NetworkOfferingResponse;
import org.apache.cloudstack.api.response.NetworkResponse;
@@ -73,6 +67,8 @@ import org.apache.cloudstack.api.response.NicResponse;
import org.apache.cloudstack.api.response.NicSecondaryIpResponse;
import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
import org.apache.cloudstack.api.response.PodResponse;
+import org.apache.cloudstack.api.response.PortableIpRangeResponse;
+import org.apache.cloudstack.api.response.PortableIpResponse;
import org.apache.cloudstack.api.response.PrivateGatewayResponse;
import org.apache.cloudstack.api.response.ProjectAccountResponse;
import org.apache.cloudstack.api.response.ProjectInvitationResponse;
@@ -95,7 +91,6 @@ import org.apache.cloudstack.api.response.SnapshotResponse;
import org.apache.cloudstack.api.response.SnapshotScheduleResponse;
import org.apache.cloudstack.api.response.StaticRouteResponse;
import org.apache.cloudstack.api.response.StorageNetworkIpRangeResponse;
-import org.apache.cloudstack.api.response.StoragePoolForMigrationResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.SwiftResponse;
import org.apache.cloudstack.api.response.SystemVmInstanceResponse;
@@ -115,11 +110,10 @@ import org.apache.cloudstack.api.response.VpcOfferingResponse;
import org.apache.cloudstack.api.response.VpcResponse;
import org.apache.cloudstack.api.response.VpnUsersResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
-import org.apache.cloudstack.api.response.*;
import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRule;
-import org.apache.cloudstack.region.Region;
import org.apache.cloudstack.region.PortableIp;
import org.apache.cloudstack.region.PortableIpRange;
+import org.apache.cloudstack.region.Region;
import org.apache.cloudstack.usage.Usage;
import com.cloud.capacity.Capacity;
@@ -162,6 +156,12 @@ import com.cloud.network.rules.StaticNatRule;
import com.cloud.network.rules.StickinessPolicy;
import com.cloud.network.security.SecurityGroup;
import com.cloud.network.security.SecurityRule;
+import com.cloud.network.vpc.NetworkACL;
+import com.cloud.network.vpc.NetworkACLItem;
+import com.cloud.network.vpc.PrivateGateway;
+import com.cloud.network.vpc.StaticRoute;
+import com.cloud.network.vpc.Vpc;
+import com.cloud.network.vpc.VpcOffering;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.NetworkOffering;
import com.cloud.offering.ServiceOffering;
@@ -257,7 +257,7 @@ public interface ResponseGenerator {
StoragePoolResponse createStoragePoolResponse(StoragePool pool);
- StoragePoolForMigrationResponse createStoragePoolForMigrationResponse(StoragePool pool);
+ StoragePoolResponse createStoragePoolForMigrationResponse(StoragePool pool);
ClusterResponse createClusterResponse(Cluster cluster, Boolean showCapacities);
diff --git a/api/src/org/apache/cloudstack/api/command/admin/internallb/ConfigureInternalLoadBalancerElementCmd.java b/api/src/org/apache/cloudstack/api/command/admin/internallb/ConfigureInternalLoadBalancerElementCmd.java
index 3feecc64a97..3d09bda3b85 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/internallb/ConfigureInternalLoadBalancerElementCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/internallb/ConfigureInternalLoadBalancerElementCmd.java
@@ -99,15 +99,12 @@ public class ConfigureInternalLoadBalancerElementCmd extends BaseAsyncCmd {
@Override
public void execute() throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException{
- s_logger.debug("hello alena");
CallContext.current().setEventDetails("Internal load balancer element: " + id);
- s_logger.debug("hello alena");
VirtualRouterProvider result = _service.get(0).configureInternalLoadBalancerElement(getId(), getEnabled());
- s_logger.debug("hello alena");
if (result != null){
InternalLoadBalancerElementResponse routerResponse = _responseGenerator.createInternalLbElementResponse(result);
routerResponse.setResponseName(getCommandName());
- this.setResponseObject(routerResponse);
+ setResponseObject(routerResponse);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to configure the internal load balancer element");
}
diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java
index 136f1369ee6..2b1832955ce 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/storage/CreateStoragePoolCmd.java
@@ -81,6 +81,10 @@ public class CreateStoragePoolCmd extends BaseCmd {
required=false, description="the scope of the storage: cluster or zone")
private String scope;
+ @Parameter(name=ApiConstants.HYPERVISOR, type=CommandType.STRING, required=false,
+ description="hypervisor type of the hosts in zone that will be attached to this storage pool. KVM, VMware supported as of now.")
+ private String hypervisor;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -121,9 +125,9 @@ public class CreateStoragePoolCmd extends BaseCmd {
return this.scope;
}
- /////////////////////////////////////////////////////
- /////////////// API Implementation///////////////////
- /////////////////////////////////////////////////////
+ public String getHypervisor() {
+ return hypervisor;
+ }
@Override
public String getCommandName() {
diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCmd.java
index e8c74476835..7d9be61696d 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCmd.java
@@ -27,14 +27,14 @@ import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ListResponse;
-import org.apache.cloudstack.api.response.StoragePoolForMigrationResponse;
+import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.VolumeResponse;
import com.cloud.storage.StoragePool;
import com.cloud.utils.Pair;
@APICommand(name = "findStoragePoolsForMigration", description="Lists storage pools available for migration of a volume.",
- responseObject=StoragePoolForMigrationResponse.class)
+ responseObject=StoragePoolResponse.class)
public class FindStoragePoolsForMigrationCmd extends BaseListCmd {
public static final Logger s_logger = Logger.getLogger(FindStoragePoolsForMigrationCmd.class.getName());
@@ -74,13 +74,13 @@ public class FindStoragePoolsForMigrationCmd extends BaseListCmd {
public void execute() {
Pair, List extends StoragePool>> pools =
_mgr.listStoragePoolsForMigrationOfVolume(getId());
- ListResponse response = new ListResponse();
- List poolResponses = new ArrayList();
+ ListResponse response = new ListResponse();
+ List poolResponses = new ArrayList();
List extends StoragePool> allPools = pools.first();
List extends StoragePool> suitablePoolList = pools.second();
for (StoragePool pool : allPools) {
- StoragePoolForMigrationResponse poolResponse = _responseGenerator.createStoragePoolForMigrationResponse(pool);
+ StoragePoolResponse poolResponse = _responseGenerator.createStoragePoolForMigrationResponse(pool);
Boolean suitableForMigration = false;
for (StoragePool suitablePool : suitablePoolList) {
if (suitablePool.getId() == pool.getId()) {
diff --git a/api/src/org/apache/cloudstack/api/command/admin/vpc/UpdateVPCOfferingCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vpc/UpdateVPCOfferingCmd.java
index 1072c9891e9..8acfc674912 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/vpc/UpdateVPCOfferingCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/vpc/UpdateVPCOfferingCmd.java
@@ -39,7 +39,7 @@ public class UpdateVPCOfferingCmd extends BaseAsyncCmd{
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
- @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = VpcOfferingResponse.class,
+ @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = VpcOfferingResponse.class, required=true,
description="the id of the VPC offering")
private Long id;
diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java
index 54e6cf9d0c3..ebd0faedcf1 100644
--- a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java
@@ -32,7 +32,6 @@ import org.apache.cloudstack.context.CallContext;
import com.cloud.event.EventTypes;
import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.exception.ResourceInUseException;
import com.cloud.user.Account;
@APICommand(name = "deleteAffinityGroup", description = "Deletes affinity group", responseObject = SuccessResponse.class)
@@ -124,7 +123,6 @@ public class DeleteAffinityGroupCmd extends BaseAsyncCmd {
@Override
public void execute(){
- try{
boolean result = _affinityGroupService.deleteAffinityGroup(id, accountName, domainId, name);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
@@ -132,10 +130,6 @@ public class DeleteAffinityGroupCmd extends BaseAsyncCmd {
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete affinity group");
}
- } catch (ResourceInUseException ex) {
- s_logger.warn("Exception: ", ex);
- throw new ServerApiException(ApiErrorCode.RESOURCE_IN_USE_ERROR, ex.getMessage());
- }
}
@Override
diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java
index f92c53e969f..ca061608835 100644
--- a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java
@@ -22,13 +22,13 @@ import org.apache.cloudstack.affinity.AffinityGroupResponse;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.BaseListAccountResourcesCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
@APICommand(name = "listAffinityGroups", description = "Lists affinity groups", responseObject = AffinityGroupResponse.class)
-public class ListAffinityGroupsCmd extends BaseListCmd {
+public class ListAffinityGroupsCmd extends BaseListAccountResourcesCmd {
public static final Logger s_logger = Logger.getLogger(ListAffinityGroupsCmd.class.getName());
private static final String s_name = "listaffinitygroupsresponse";
@@ -77,7 +77,8 @@ public class ListAffinityGroupsCmd extends BaseListCmd {
public void execute(){
ListResponse response = _queryService.listAffinityGroups(id, affinityGroupName,
- affinityGroupType, virtualMachineId, getStartIndex(), getPageSizeVal());
+ affinityGroupType, virtualMachineId, getAccountName(), getDomainId(), isRecursive(),
+ listAll(), getStartIndex(), getPageSizeVal());
response.setResponseName(getCommandName());
setResponseObject(response);
diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/DeleteGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/DeleteGlobalLoadBalancerRuleCmd.java
index 17d31113dba..80f8007db20 100644
--- a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/DeleteGlobalLoadBalancerRuleCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/DeleteGlobalLoadBalancerRuleCmd.java
@@ -24,8 +24,10 @@ import org.apache.log4j.Logger;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandJobType;
import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.context.CallContext;
@@ -92,13 +94,19 @@ public class DeleteGlobalLoadBalancerRuleCmd extends BaseAsyncCmd {
@Override
public void execute(){
- _gslbService.deleteGlobalLoadBalancerRule(this);
CallContext.current().setEventDetails("Deleting global Load balancer Id: " + getGlobalLoadBalancerId());
+ boolean result = _gslbService.deleteGlobalLoadBalancerRule(this);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete Global Load Balancer rule.");
+ }
}
@Override
public String getSyncObjType() {
- return BaseAsyncCmd.networkSyncObject;
+ return BaseAsyncCmd.gslbSyncObject;
}
@Override
diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java
index d5abc03aefc..5c482a4ea0a 100644
--- a/api/src/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/vpc/RestartVPCCmd.java
@@ -43,7 +43,7 @@ public class RestartVPCCmd extends BaseAsyncCmd{
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
- @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=VpcResponse.class,
+ @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=VpcResponse.class, required=true,
description="the id of the VPC")
private Long id;
diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmd.java
index ba2cc6d81fa..5733db1abf5 100644
--- a/api/src/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/vpc/UpdateVPCCmd.java
@@ -39,11 +39,11 @@ public class UpdateVPCCmd extends BaseAsyncCmd{
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
- @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=VpcResponse.class,
+ @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=VpcResponse.class, required=true,
description="the id of the VPC")
private Long id;
- @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="the name of the VPC")
+ @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, description="the name of the VPC", required=true)
private String vpcName;
@Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, description="the display text of the VPC")
diff --git a/api/src/org/apache/cloudstack/api/response/HypervisorCapabilitiesResponse.java b/api/src/org/apache/cloudstack/api/response/HypervisorCapabilitiesResponse.java
index ea26a7e897c..1f360a9e539 100644
--- a/api/src/org/apache/cloudstack/api/response/HypervisorCapabilitiesResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/HypervisorCapabilitiesResponse.java
@@ -43,6 +43,14 @@ public class HypervisorCapabilitiesResponse extends BaseResponse {
@SerializedName(ApiConstants.SECURITY_GROUP_EANBLED) @Param(description="true if security group is supported")
private boolean isSecurityGroupEnabled;
+ @SerializedName(ApiConstants.MAX_DATA_VOLUMES_LIMIT) @Param(description="the maximum number of Data Volumes that can be attached for this hypervisor")
+ private Integer maxDataVolumesLimit;
+
+ @SerializedName(ApiConstants.MAX_HOSTS_PER_CLUSTER) @Param(description="the maximum number of Hosts per cluster for this hypervisor")
+ private Integer maxHostsPerCluster;
+
+ @SerializedName(ApiConstants.STORAGE_MOTION_ENABLED) @Param(description="true if storage motion is supported")
+ private boolean isStorageMotionSupported;
public String getId() {
return id;
@@ -84,4 +92,28 @@ public class HypervisorCapabilitiesResponse extends BaseResponse {
public void setIsSecurityGroupEnabled(Boolean sgEnabled) {
this.isSecurityGroupEnabled = sgEnabled;
}
+
+ public Boolean getIsStorageMotionSupported() {
+ return this.isStorageMotionSupported;
+ }
+
+ public void setIsStorageMotionSupported(Boolean smSupported) {
+ this.isStorageMotionSupported = smSupported;
+ }
+
+ public Integer getMaxDataVolumesLimit() {
+ return maxDataVolumesLimit;
+ }
+
+ public void setMaxDataVolumesLimit(Integer maxDataVolumesLimit) {
+ this.maxDataVolumesLimit = maxDataVolumesLimit;
+ }
+
+ public Integer getMaxHostsPerCluster() {
+ return maxHostsPerCluster;
+ }
+
+ public void setMaxHostsPerCluster(Integer maxHostsPerCluster) {
+ this.maxHostsPerCluster = maxHostsPerCluster;
+ }
}
diff --git a/api/src/org/apache/cloudstack/api/response/NetworkResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkResponse.java
index ec7859cef8e..3a8b8752174 100644
--- a/api/src/org/apache/cloudstack/api/response/NetworkResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/NetworkResponse.java
@@ -167,6 +167,10 @@ public class NetworkResponse extends BaseResponse implements ControlledEntityRes
@SerializedName(ApiConstants.DISPLAY_NETWORK) @Param(description="an optional field, whether to the display the network to the end user or not.")
private Boolean displayNetwork;
+ @SerializedName(ApiConstants.ACL_ID) @Param(description="ACL Id associated with the VPC network")
+ private String aclId;
+
+
public Boolean getDisplayNetwork() {
return displayNetwork;
}
@@ -353,4 +357,12 @@ public class NetworkResponse extends BaseResponse implements ControlledEntityRes
public void setIp6Cidr(String ip6Cidr) {
this.ip6Cidr = ip6Cidr;
}
+
+ public String getAclId() {
+ return aclId;
+ }
+
+ public void setAclId(String aclId) {
+ this.aclId = aclId;
+ }
}
diff --git a/api/src/org/apache/cloudstack/api/response/StoragePoolForMigrationResponse.java b/api/src/org/apache/cloudstack/api/response/StoragePoolForMigrationResponse.java
deleted file mode 100644
index e0548f9863f..00000000000
--- a/api/src/org/apache/cloudstack/api/response/StoragePoolForMigrationResponse.java
+++ /dev/null
@@ -1,249 +0,0 @@
-// Licensed to the Apache Software Foundation (ASF) under one
-// or more contributor license agreements. See the NOTICE file
-// distributed with this work for additional information
-// regarding copyright ownership. The ASF licenses this file
-// to you under the Apache License, Version 2.0 (the
-// "License"); you may not use this file except in compliance
-// with the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing,
-// software distributed under the License is distributed on an
-// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-// KIND, either express or implied. See the License for the
-// specific language governing permissions and limitations
-// under the License.
-package org.apache.cloudstack.api.response;
-
-import java.util.Date;
-
-import com.google.gson.annotations.SerializedName;
-
-import org.apache.cloudstack.api.ApiConstants;
-import org.apache.cloudstack.api.BaseResponse;
-import org.apache.cloudstack.api.EntityReference;
-
-import com.cloud.serializer.Param;
-import com.cloud.storage.StoragePool;
-import com.cloud.storage.StoragePoolStatus;
-
-@EntityReference(value=StoragePool.class)
-public class StoragePoolForMigrationResponse extends BaseResponse {
- @SerializedName("id") @Param(description="the ID of the storage pool")
- private String id;
-
- @SerializedName("zoneid") @Param(description="the Zone ID of the storage pool")
- private String zoneId;
-
- @SerializedName(ApiConstants.ZONE_NAME) @Param(description="the Zone name of the storage pool")
- private String zoneName;
-
- @SerializedName("podid") @Param(description="the Pod ID of the storage pool")
- private String podId;
-
- @SerializedName("podname") @Param(description="the Pod name of the storage pool")
- private String podName;
-
- @SerializedName("name") @Param(description="the name of the storage pool")
- private String name;
-
- @SerializedName("ipaddress") @Param(description="the IP address of the storage pool")
- private String ipAddress;
-
- @SerializedName("path") @Param(description="the storage pool path")
- private String path;
-
- @SerializedName("created") @Param(description="the date and time the storage pool was created")
- private Date created;
-
- @SerializedName("type") @Param(description="the storage pool type")
- private String type;
-
- @SerializedName("clusterid") @Param(description="the ID of the cluster for the storage pool")
- private String clusterId;
-
- @SerializedName("clustername") @Param(description="the name of the cluster for the storage pool")
- private String clusterName;
-
- @SerializedName("disksizetotal") @Param(description="the total disk size of the storage pool")
- private Long diskSizeTotal;
-
- @SerializedName("disksizeallocated") @Param(description="the host's currently allocated disk size")
- private Long diskSizeAllocated;
-
- @SerializedName("disksizeused") @Param(description="the host's currently used disk size")
- private Long diskSizeUsed;
-
- @SerializedName("tags") @Param(description="the tags for the storage pool")
- private String tags;
-
- @SerializedName(ApiConstants.STATE) @Param(description="the state of the storage pool")
- private StoragePoolStatus state;
-
- @SerializedName(ApiConstants.SCOPE) @Param(description="the scope of the storage pool")
- private String scope;
-
- @SerializedName("suitableformigration") @Param(description="true if this pool is suitable to migrate a volume," +
- " false otherwise")
- private Boolean suitableForMigration;
-
- /**
- * @return the scope
- */
- public String getScope() {
- return scope;
- }
-
- /**
- * @param scope the scope to set
- */
- public void setScope(String scope) {
- this.scope = scope;
- }
-
- @Override
- public String getObjectId() {
- return this.getId();
- }
-
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- public String getZoneId() {
- return zoneId;
- }
-
- public void setZoneId(String zoneId) {
- this.zoneId = zoneId;
- }
-
- public String getZoneName() {
- return zoneName;
- }
-
- public void setZoneName(String zoneName) {
- this.zoneName = zoneName;
- }
-
- public String getPodId() {
- return podId;
- }
-
- public void setPodId(String podId) {
- this.podId = podId;
- }
-
- public String getPodName() {
- return podName;
- }
-
- public void setPodName(String podName) {
- this.podName = podName;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getIpAddress() {
- return ipAddress;
- }
-
- public void setIpAddress(String ipAddress) {
- this.ipAddress = ipAddress;
- }
-
- public String getPath() {
- return path;
- }
-
- public void setPath(String path) {
- this.path = path;
- }
-
- public Date getCreated() {
- return created;
- }
-
- public void setCreated(Date created) {
- this.created = created;
- }
-
- public String getType() {
- return type;
- }
-
- public void setType(String type) {
- this.type = type;
- }
-
- public String getClusterId() {
- return clusterId;
- }
-
- public void setClusterId(String clusterId) {
- this.clusterId = clusterId;
- }
-
- public String getClusterName() {
- return clusterName;
- }
-
- public void setClusterName(String clusterName) {
- this.clusterName = clusterName;
- }
-
- public Long getDiskSizeTotal() {
- return diskSizeTotal;
- }
-
- public void setDiskSizeTotal(Long diskSizeTotal) {
- this.diskSizeTotal = diskSizeTotal;
- }
-
- public Long getDiskSizeAllocated() {
- return diskSizeAllocated;
- }
-
- public void setDiskSizeAllocated(Long diskSizeAllocated) {
- this.diskSizeAllocated = diskSizeAllocated;
- }
-
- public Long getDiskSizeUsed() {
- return diskSizeUsed;
- }
-
- public void setDiskSizeUsed(Long diskSizeUsed) {
- this.diskSizeUsed = diskSizeUsed;
- }
-
- public String getTags() {
- return tags;
- }
-
- public void setTags(String tags) {
- this.tags = tags;
- }
-
- public StoragePoolStatus getState() {
- return state;
- }
-
- public void setState(StoragePoolStatus state) {
- this.state = state;
- }
-
- public void setSuitableForMigration(Boolean suitableForMigration) {
- this.suitableForMigration = suitableForMigration;
- }
-}
diff --git a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java
index af6f901356c..57257a7535b 100644
--- a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java
@@ -87,6 +87,13 @@ public class StoragePoolResponse extends BaseResponse {
@SerializedName(ApiConstants.SCOPE) @Param(description="the scope of the storage pool")
private String scope;
+ @SerializedName(ApiConstants.HYPERVISOR) @Param(description="the hypervisor type of the storage pool")
+ private String hypervisor;
+
+ @SerializedName("suitableformigration") @Param(description="true if this pool is suitable to migrate a volume," +
+ " false otherwise")
+ private Boolean suitableForMigration;
+
/**
* @return the scope
*/
@@ -101,9 +108,17 @@ public class StoragePoolResponse extends BaseResponse {
this.scope = scope;
}
+ public String getHypervisor() {
+ return hypervisor;
+ }
+
+ public void setHypervisor(String hypervisor) {
+ this.hypervisor = hypervisor;
+ }
+
@Override
public String getObjectId() {
- return this.getId();
+ return getId();
}
public String getId() {
@@ -249,4 +264,8 @@ public class StoragePoolResponse extends BaseResponse {
public void setState(StoragePoolStatus state) {
this.state = state;
}
+
+ public void setSuitableForMigration(Boolean suitableForMigration) {
+ this.suitableForMigration = suitableForMigration;
+ }
}
diff --git a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
index 9901b5f014b..ed7b7dfc4c5 100644
--- a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java
@@ -137,6 +137,18 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
@SerializedName("networkkbswrite") @Param(description="the outgoing network traffic on the host")
private Long networkKbsWrite;
+ @SerializedName("diskkbsread") @Param(description="the read (bytes) of disk on the vm")
+ private Long diskKbsRead;
+
+ @SerializedName("diskkbswrite") @Param(description="the write (bytes) of disk on the vm")
+ private Long diskKbsWrite;
+
+ @SerializedName("diskioread") @Param(description="the read (io) of disk on the vm")
+ private Long diskIORead;
+
+ @SerializedName("diskiowrite") @Param(description="the write (io) of disk on the vm")
+ private Long diskIOWrite;
+
@SerializedName("guestosid") @Param(description="Os type ID of the virtual machine")
private String guestOsId;
@@ -301,6 +313,22 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp
this.isoDisplayText = isoDisplayText;
}
+ public void setDiskKbsRead(Long diskKbsRead) {
+ this.diskKbsRead = diskKbsRead;
+ }
+
+ public void setDiskKbsWrite(Long diskKbsWrite) {
+ this.diskKbsWrite = diskKbsWrite;
+ }
+
+ public void setDiskIORead(Long diskIORead) {
+ this.diskIORead = diskIORead;
+ }
+
+ public void setDiskIOWrite(Long diskIOWrite) {
+ this.diskIOWrite = diskIOWrite;
+ }
+
public void setServiceOfferingId(String serviceOfferingId) {
this.serviceOfferingId = serviceOfferingId;
}
diff --git a/api/src/org/apache/cloudstack/query/QueryService.java b/api/src/org/apache/cloudstack/query/QueryService.java
index 2dfd97cfa98..73e393b069f 100644
--- a/api/src/org/apache/cloudstack/query/QueryService.java
+++ b/api/src/org/apache/cloudstack/query/QueryService.java
@@ -86,7 +86,8 @@ public interface QueryService {
public ListResponse listDataCenters(ListZonesByCmd cmd);
public ListResponse listAffinityGroups(Long affinityGroupId, String affinityGroupName,
- String affinityGroupType, Long vmId, Long startIndex, Long pageSize);
+ String affinityGroupType, Long vmId, String accountName, Long domainId, boolean isRecursive,
+ boolean listAll, Long startIndex, Long pageSize);
public List listResource(ListResourceDetailsCmd cmd);
diff --git a/api/src/org/apache/cloudstack/usage/UsageTypes.java b/api/src/org/apache/cloudstack/usage/UsageTypes.java
index 2baa1d20057..ddf10979cb7 100644
--- a/api/src/org/apache/cloudstack/usage/UsageTypes.java
+++ b/api/src/org/apache/cloudstack/usage/UsageTypes.java
@@ -36,6 +36,10 @@ public class UsageTypes {
public static final int PORT_FORWARDING_RULE = 12;
public static final int NETWORK_OFFERING = 13;
public static final int VPN_USERS = 14;
+ public static final int VM_DISK_IO_READ = 21;
+ public static final int VM_DISK_IO_WRITE = 22;
+ public static final int VM_DISK_BYTES_READ = 23;
+ public static final int VM_DISK_BYTES_WRITE = 24;
public static List listUsageTypes(){
List responseList = new ArrayList();
@@ -53,6 +57,10 @@ public class UsageTypes {
responseList.add(new UsageTypeResponse(PORT_FORWARDING_RULE, "Port Forwarding Usage"));
responseList.add(new UsageTypeResponse(NETWORK_OFFERING, "Network Offering Usage"));
responseList.add(new UsageTypeResponse(VPN_USERS, "VPN users usage"));
+ responseList.add(new UsageTypeResponse(VM_DISK_IO_READ, "VM Disk usage(I/O Read)"));
+ responseList.add(new UsageTypeResponse(VM_DISK_IO_WRITE, "VM Disk usage(I/O Write)"));
+ responseList.add(new UsageTypeResponse(VM_DISK_BYTES_READ, "VM Disk usage(Bytes Read)"));
+ responseList.add(new UsageTypeResponse(VM_DISK_BYTES_WRITE, "VM Disk usage(Bytes Write)"));
return responseList;
}
}
diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties
index 1638be19e49..2b173596b73 100644
--- a/client/WEB-INF/classes/resources/messages.properties
+++ b/client/WEB-INF/classes/resources/messages.properties
@@ -14,6 +14,8 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
+label.view.secondary.ips=View secondary IPs
+message.acquire.ip.nic=Please confirm that you would like to acquire a new secondary IP for this NIC.
NOTE: You need to manually configure the newly-acquired secondary IP inside the virtual machine.
message.select.affinity.groups=Please select any affinity groups you want this VM to belong to:
message.no.affinity.groups=You do not have any affinity groups. Please continue to the next step.
label.action.delete.nic=Remove NIC
@@ -53,6 +55,7 @@ label.account.specific=Account-Specific
label.account=Account
label.accounts=Accounts
label.acquire.new.ip=Acquire New IP
+label.acquire.new.secondary.ip=Acquire new secondary IP
label.action.attach.disk.processing=Attaching Disk....
label.action.attach.disk=Attach Disk
label.action.attach.iso.processing=Attaching ISO....
@@ -464,10 +467,14 @@ label.disabled=Disabled
label.disabling.vpn.access=Disabling VPN Access
label.disk.allocated=Disk Allocated
label.disk.offering=Disk Offering
+label.disk.read.bytes=Disk Read (Bytes)
+label.disk.read.io=Disk Read (IO)
label.disk.size.gb=Disk Size (in GB)
label.disk.size=Disk Size
label.disk.total=Disk Total
label.disk.volume=Disk Volume
+label.disk.write.bytes=Disk Write (Bytes)
+label.disk.write.io=Disk Write (IO)
label.display.name=Display name
label.display.text=Display Text
label.dns.1=DNS 1
diff --git a/client/pom.xml b/client/pom.xml
index 0c38ecb65d2..ab758eb2a67 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -29,6 +29,11 @@
org.apache.cloudstack
cloud-plugin-acl-static-role-based
${project.version}
+
+
+ org.apache.cloudstack
+ cloud-plugin-dedicated-resources
+ ${project.version}
org.apache.cloudstack
@@ -136,6 +141,11 @@
cloud-plugin-planner-implicit-dedication
${project.version}
+
+ org.apache.cloudstack
+ cloud-plugin-explicit-dedication
+ ${project.version}
+
org.apache.cloudstack
cloud-plugin-host-allocator-random
diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in
index 80f380b4885..982cc0f1dac 100644
--- a/client/tomcatconf/applicationContext.xml.in
+++ b/client/tomcatconf/applicationContext.xml.in
@@ -158,6 +158,14 @@
+
+
+
+
+
-
@@ -171,7 +170,7 @@
-
+
@@ -260,13 +259,22 @@
-
+
+
-
+
+
+
+
+
+
+
diff --git a/client/tomcatconf/nonossComponentContext.xml.in b/client/tomcatconf/nonossComponentContext.xml.in
index 6fa9d38baa4..16fd88337fb 100644
--- a/client/tomcatconf/nonossComponentContext.xml.in
+++ b/client/tomcatconf/nonossComponentContext.xml.in
@@ -77,6 +77,10 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/tomcatconf/simulatorComponentContext.xml.in b/client/tomcatconf/simulatorComponentContext.xml.in
index 652c4c824ff..d71cf162569 100644
--- a/client/tomcatconf/simulatorComponentContext.xml.in
+++ b/client/tomcatconf/simulatorComponentContext.xml.in
@@ -234,4 +234,10 @@
+
+
+
+
+
+
diff --git a/core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java b/core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java
new file mode 100644
index 00000000000..18cb7948a38
--- /dev/null
+++ b/core/src/com/cloud/agent/api/GetVmDiskStatsAnswer.java
@@ -0,0 +1,47 @@
+// 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.agent.api;
+
+import java.util.HashMap;
+import java.util.List;
+
+import com.cloud.agent.api.LogLevel.Log4jLevel;
+
+@LogLevel(Log4jLevel.Trace)
+public class GetVmDiskStatsAnswer extends Answer {
+
+ String hostName;
+ HashMap> vmDiskStatsMap;
+
+ public GetVmDiskStatsAnswer(GetVmDiskStatsCommand cmd, String details, String hostName, HashMap> vmDiskStatsMap) {
+ super(cmd, true, details);
+ this.hostName = hostName;
+ this.vmDiskStatsMap = vmDiskStatsMap;
+ }
+
+ public String getHostName() {
+ return hostName;
+ }
+
+ public HashMap> getVmDiskStatsMap() {
+ return vmDiskStatsMap;
+ }
+
+ protected GetVmDiskStatsAnswer() {
+ //no-args constructor for json serialization-deserialization
+ }
+}
diff --git a/core/src/com/cloud/agent/api/GetVmDiskStatsCommand.java b/core/src/com/cloud/agent/api/GetVmDiskStatsCommand.java
new file mode 100644
index 00000000000..2b690020cb2
--- /dev/null
+++ b/core/src/com/cloud/agent/api/GetVmDiskStatsCommand.java
@@ -0,0 +1,54 @@
+// 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.agent.api;
+
+import java.util.List;
+
+import com.cloud.agent.api.LogLevel.Log4jLevel;
+
+@LogLevel(Log4jLevel.Trace)
+public class GetVmDiskStatsCommand extends Command {
+ List vmNames;
+ String hostGuid;
+ String hostName;
+
+ protected GetVmDiskStatsCommand() {
+ }
+
+ public GetVmDiskStatsCommand(List vmNames, String hostGuid, String hostName) {
+ this.vmNames = vmNames;
+ this.hostGuid = hostGuid;
+ this.hostName = hostName;
+ }
+
+ public List getVmNames() {
+ return vmNames;
+ }
+
+ public String getHostGuid(){
+ return this.hostGuid;
+ }
+
+ public String getHostName(){
+ return this.hostName;
+ }
+
+ @Override
+ public boolean executeInSequence() {
+ return false;
+ }
+}
diff --git a/core/src/com/cloud/agent/api/MigrateWithStorageCommand.java b/core/src/com/cloud/agent/api/MigrateWithStorageCommand.java
index 058aa15338e..a108a2a7bed 100644
--- a/core/src/com/cloud/agent/api/MigrateWithStorageCommand.java
+++ b/core/src/com/cloud/agent/api/MigrateWithStorageCommand.java
@@ -24,10 +24,18 @@ import com.cloud.agent.api.to.StorageFilerTO;
public class MigrateWithStorageCommand extends Command {
VirtualMachineTO vm;
Map volumeToFiler;
+ String tgtHost;
public MigrateWithStorageCommand(VirtualMachineTO vm, Map volumeToFiler) {
this.vm = vm;
this.volumeToFiler = volumeToFiler;
+ this.tgtHost = null;
+ }
+
+ public MigrateWithStorageCommand(VirtualMachineTO vm, Map volumeToFiler, String tgtHost) {
+ this.vm = vm;
+ this.volumeToFiler = volumeToFiler;
+ this.tgtHost = tgtHost;
}
public VirtualMachineTO getVirtualMachine() {
@@ -38,6 +46,10 @@ public class MigrateWithStorageCommand extends Command {
return volumeToFiler;
}
+ public String getTargetHost() {
+ return tgtHost;
+ }
+
@Override
public boolean executeInSequence() {
return true;
diff --git a/core/src/com/cloud/agent/api/UnPlugNicCommand.java b/core/src/com/cloud/agent/api/UnPlugNicCommand.java
index b6cab8872f5..b964292f1a2 100644
--- a/core/src/com/cloud/agent/api/UnPlugNicCommand.java
+++ b/core/src/com/cloud/agent/api/UnPlugNicCommand.java
@@ -39,7 +39,7 @@ public class UnPlugNicCommand extends Command{
this.instanceName = instanceName;
}
- public String getInstanceName() {
+ public String getVmName() {
return instanceName;
}
}
diff --git a/core/src/com/cloud/agent/api/VmDiskStatsEntry.java b/core/src/com/cloud/agent/api/VmDiskStatsEntry.java
new file mode 100644
index 00000000000..9bec031c50d
--- /dev/null
+++ b/core/src/com/cloud/agent/api/VmDiskStatsEntry.java
@@ -0,0 +1,90 @@
+// 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.agent.api;
+
+import com.cloud.vm.VmDiskStats;
+
+public class VmDiskStatsEntry implements VmDiskStats {
+
+ String vmName;
+ String path;
+ Long ioRead = 0L;
+ Long ioWrite = 0L;
+ Long bytesWrite = 0L;
+ Long bytesRead = 0L;
+
+ public VmDiskStatsEntry() {
+ }
+
+ public VmDiskStatsEntry(String vmName, String path, Long ioWrite, Long ioRead, Long bytesWrite, Long bytesRead) {
+ this.ioRead = ioRead;
+ this.ioWrite = ioWrite;
+ this.bytesRead = bytesRead;
+ this.bytesWrite = bytesWrite;
+ this.vmName = vmName;
+ this.path = path;
+ }
+
+ public void setVmName(String vmName) {
+ this.vmName = vmName;
+ }
+
+ public String getVmName() {
+ return vmName;
+ }
+
+ public void setPath(String path) {
+ this.path = path;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+ public void setBytesRead(Long bytesRead) {
+ this.bytesRead = bytesRead;
+ }
+
+ public Long getBytesRead() {
+ return bytesRead;
+ }
+
+ public void setBytesWrite(Long bytesWrite) {
+ this.bytesWrite = bytesWrite;
+ }
+
+ public Long getBytesWrite() {
+ return bytesWrite;
+ }
+
+ public void setIORead(Long ioRead) {
+ this.ioRead = ioRead;
+ }
+
+ public Long getIORead() {
+ return ioRead;
+ }
+
+ public void setIOWrite(Long ioWrite) {
+ this.ioWrite = ioWrite;
+ }
+
+ public Long getIOWrite() {
+ return ioWrite;
+ }
+
+}
diff --git a/core/src/com/cloud/agent/api/VmStatsEntry.java b/core/src/com/cloud/agent/api/VmStatsEntry.java
index 8828e9114f4..9c6df1a09f8 100755
--- a/core/src/com/cloud/agent/api/VmStatsEntry.java
+++ b/core/src/com/cloud/agent/api/VmStatsEntry.java
@@ -23,6 +23,10 @@ public class VmStatsEntry implements VmStats {
double cpuUtilization;
double networkReadKBs;
double networkWriteKBs;
+ double diskReadIOs;
+ double diskWriteIOs;
+ double diskReadKBs;
+ double diskWriteKBs;
int numCPUs;
String entityType;
@@ -37,6 +41,18 @@ public class VmStatsEntry implements VmStats {
this.numCPUs = numCPUs;
this.entityType = entityType;
}
+
+ public VmStatsEntry(double cpuUtilization, double networkReadKBs, double networkWriteKBs,
+ double diskReadKBs, double diskWriteKBs, int numCPUs, String entityType)
+ {
+ this.cpuUtilization = cpuUtilization;
+ this.networkReadKBs = networkReadKBs;
+ this.networkWriteKBs = networkWriteKBs;
+ this.diskReadKBs = diskReadKBs;
+ this.diskWriteKBs = diskWriteKBs;
+ this.numCPUs = numCPUs;
+ this.entityType = entityType;
+ }
public double getCPUUtilization() {
return cpuUtilization;
@@ -62,6 +78,38 @@ public class VmStatsEntry implements VmStats {
this.networkWriteKBs = networkWriteKBs;
}
+ public double getDiskReadIOs() {
+ return diskReadIOs;
+ }
+
+ public void setDiskReadIOs(double diskReadIOs) {
+ this.diskReadIOs = diskReadIOs;
+ }
+
+ public double getDiskWriteIOs() {
+ return diskWriteIOs;
+ }
+
+ public void setDiskWriteIOs(double diskWriteIOs) {
+ this.diskWriteIOs = diskWriteIOs;
+ }
+
+ public double getDiskReadKBs() {
+ return diskReadKBs;
+ }
+
+ public void setDiskReadKBs(double diskReadKBs) {
+ this.diskReadKBs = diskReadKBs;
+ }
+
+ public double getDiskWriteKBs() {
+ return diskWriteKBs;
+ }
+
+ public void setDiskWriteKBs(double diskWriteKBs) {
+ this.diskWriteKBs = diskWriteKBs;
+ }
+
public int getNumCPUs() {
return numCPUs;
}
diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
index 8b996d1bfed..9e40eefc11a 100755
--- a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
+++ b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java
@@ -642,7 +642,7 @@ public class VirtualRoutingResource implements Manager {
for (IpAliasTO ipAliasTO : revokedIpAliasTOs) {
args = args + ipAliasTO.getAlias_count()+":"+ipAliasTO.getRouterip()+":"+ipAliasTO.getNetmask()+"-";
}
- args = args + " " ;
+ args = args + "- " ;
List activeIpAliasTOs = cmd.getCreateIpAliasTos();
for (IpAliasTO ipAliasTO : activeIpAliasTOs) {
args = args + ipAliasTO.getAlias_count()+":"+ipAliasTO.getRouterip()+":"+ipAliasTO.getNetmask()+"-";
diff --git a/core/src/com/cloud/network/DnsMasqConfigurator.java b/core/src/com/cloud/network/DnsMasqConfigurator.java
index ee8e5fc2e13..dd349263c0c 100644
--- a/core/src/com/cloud/network/DnsMasqConfigurator.java
+++ b/core/src/com/cloud/network/DnsMasqConfigurator.java
@@ -71,7 +71,7 @@ import java.util.List;
"conf-dir=/etc/dnsmasq.d\n",
"dhcp-option=tag:net1,3,ipaddress\n",
"dhcp-option=tag:net1,1,netmask\n",
- "dhcp-option=6,10.147.28.149,8.8.8.8\n",
+ "dhcp-option=6,router_ip,external_dns\n",
"dhcp-optsfile=/etc/dhcpopts.txt\n",
@@ -85,11 +85,21 @@ import java.util.List;
String netmask="";
String domain= dnsMasqconfigcmd.getDomain();
String dnsServers="";
+ String dns_external="";
+ if (dnsMasqconfigcmd.getDns1()!= null) {
+ dns_external = dnsMasqconfigcmd.getDns1()+",";
+ }
+ if (dnsMasqconfigcmd.getDns2() != null) {
+ dns_external = dns_external+dnsMasqconfigcmd.getDns2()+",";
+ }
+ dns_external = dns_external + "*";
+ dns_external = dns_external.replace(",*","");
int i=0;
for (; i< dnsmasqTOs.size(); i++) {
- range=range + "dhcp-range=set:range"+i+","+dnsmasqTOs.get(i).getRouterIp()+",static\n";
+ range=range + "dhcp-range=set:range"+i+","+dnsmasqTOs.get(i).getStartIpOfSubnet()+",static\n";
gateway=gateway +"dhcp-option=tag:range"+i+",3,"+dnsmasqTOs.get(i).getGateway()+"\n";
netmask=netmask +"dhcp-option=tag:range"+i+",1,"+dnsmasqTOs.get(i).getNetmask()+"\n";
+ dnsServers=dnsServers+"dhcp-option=tag:range"+i+",6,"+dnsmasqTOs.get(i).getRouterIp()+","+dns_external+"\n";
}
dnsMasqconf.set(12, "domain="+domain+"\n");
dnsMasqconf.set(14, "domain="+domain+"\n");
@@ -97,21 +107,7 @@ import java.util.List;
dnsMasqconf.set(18, range);
dnsMasqconf.set(22, gateway);
dnsMasqconf.set(23, netmask);
- if (dnsMasqconfigcmd.getInternal_dns1() != null) {
- dnsServers = dnsServers+dnsMasqconfigcmd.getInternal_dns1()+",";
- }
- if (dnsMasqconfigcmd.getInternal_dns2() != null) {
- dnsServers = dnsServers+dnsMasqconfigcmd.getInternal_dns2()+",";
- }
- if (dnsMasqconfigcmd.getDns1() != null) {
- dnsServers = dnsServers+dnsMasqconfigcmd.getDns1()+",";
- }
- if (dnsMasqconfigcmd.getDns2() != null) {
- dnsServers = dnsServers+dnsMasqconfigcmd.getDns2()+",";
- }
- dnsServers = dnsServers +"*";
- dnsServers = dnsServers.replace(",*", "");
- dnsMasqconf.set(24,"dhcp-option=6,"+dnsServers);
+ dnsMasqconf.set(24,dnsServers);
return dnsMasqconf.toArray( new String[dnsMasqconf.size()]);
}
diff --git a/developer/pom.xml b/developer/pom.xml
index 3dc276adc23..9bfb79294fd 100644
--- a/developer/pom.xml
+++ b/developer/pom.xml
@@ -13,7 +13,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
cloud-developer
- Apache CloudStack Developer Tools
+ Apache CloudStack Developer Mode
pom
org.apache.cloudstack
diff --git a/docs/en-US/CloudStack_GSoC_Guide.ent b/docs/en-US/CloudStack_GSoC_Guide.ent
new file mode 100644
index 00000000000..17415873334
--- /dev/null
+++ b/docs/en-US/CloudStack_GSoC_Guide.ent
@@ -0,0 +1,22 @@
+
+
+
+
+
+
diff --git a/docs/en-US/CloudStack_GSoC_Guide.xml b/docs/en-US/CloudStack_GSoC_Guide.xml
new file mode 100644
index 00000000000..243a0ca361b
--- /dev/null
+++ b/docs/en-US/CloudStack_GSoC_Guide.xml
@@ -0,0 +1,54 @@
+
+
+%BOOK_ENTITIES;
+
+%xinclude;
+]>
+
+
+
+
+
+ &PRODUCT; Guide for the 2013 Google Summer of Code
+ Apache CloudStack
+ 4.3.0
+ 1
+
+
+
+ Guide for 2013 Google Summer of Code Projects.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/en-US/acquire-new-ip-for-vpc.xml b/docs/en-US/acquire-new-ip-for-vpc.xml
index 785e80bb874..c0cb876d483 100644
--- a/docs/en-US/acquire-new-ip-for-vpc.xml
+++ b/docs/en-US/acquire-new-ip-for-vpc.xml
@@ -39,28 +39,43 @@
Click the Configure button of the VPC to which you want to deploy the VMs.
The VPC page is displayed where all the tiers you created are listed in a
diagram.
-
-
- Click the Settings icon.
The following options are displayed.
- IP Addresses
+ Internal LB
- Gateways
+ Public LB IP
- Site-to-Site VPN
+ Static NAT
- Network ACLs
+ Virtual Machines
+
+
+ CIDR
+
+
+ The following router information is displayed:
+
+
+ Private Gateways
+
+
+ Public IP Addresses
+
+
+ Site-to-Site VPNs
+
+
+ Network ACL Lists
Select IP Addresses.
- The IP Addresses page is displayed.
+ The Public IP Addresses page is displayed.
Click Acquire New IP, and click Yes in the confirmation dialog.
@@ -70,4 +85,4 @@
rules.
-
\ No newline at end of file
+
diff --git a/docs/en-US/add-gateway-vpc.xml b/docs/en-US/add-gateway-vpc.xml
index 616794a51d1..a081faf7768 100644
--- a/docs/en-US/add-gateway-vpc.xml
+++ b/docs/en-US/add-gateway-vpc.xml
@@ -21,8 +21,8 @@
Adding a Private Gateway to a VPC
A private gateway can be added by the root admin only. The VPC private network has 1:1
- relationship with the NIC of the physical network. No gateways with duplicated VLAN and IP are
- allowed in the same data center.
+ relationship with the NIC of the physical network. You can configure multiple private gateways
+ to a single VPC. No gateways with duplicated VLAN and IP are allowed in the same data center.
Log in to the &PRODUCT; UI as an administrator or end user.
@@ -45,16 +45,34 @@
The following options are displayed.
- IP Addresses
+ Internal LB
+
+ Public LB IP
+
+
+ Static NAT
+
+
+ Virtual Machines
+
+
+ CIDR
+
+
+ The following router information is displayed:
+
Private Gateways
- Site-to-Site VPN
+ Public IP Addresses
- Network ACLs
+ Site-to-Site VPNs
+
+
+ Network ACL Lists
@@ -96,9 +114,38 @@
VLAN: The VLAN associated with the VPC
gateway.
+
+ Source NAT: Select this option to enable the source
+ NAT service on the VPC private gateway.
+ See .
+
+
+ ACL: Controls both ingress and egress traffic on a
+ VPC private gateway. By default, all the traffic is blocked.
+ See .
+
The new gateway appears in the list. You can repeat these steps to add more gateway for
this VPC.
+
+ Source NAT on Private Gateway
+ You might want to deploy multiple VPCs with the same super CIDR and guest tier CIDR.
+ Therefore, multiple guest VMs from different VPCs can have the same IPs to reach a enterprise
+ data center through the private gateway. In such cases, a NAT service need to be configured on
+ the private gateway. If Source NAT is enabled, the guest VMs in VPC reaches the enterprise
+ network via private gateway IP address by using the NAT service.
+ The Source NAT service on a private gateway can be enabled while adding the private
+ gateway. On deletion of a private gateway, source NAT rules specific to the private gateway
+ are deleted.
+
+
+ ACL on Private Gateway
+ The traffic on the VPC private gateway is controlled by creating both ingress and egress
+ network ACL rules. The ACLs contains both allow and deny rules. As per the rule, all the
+ ingress traffic to the private gateway interface and all the egress traffic out from the
+ private gateway interface are blocked. You can change this default behaviour while creating a
+ private gateway.
+
diff --git a/docs/en-US/add-loadbalancer-rule-vpc.xml b/docs/en-US/add-loadbalancer-rule-vpc.xml
index bba3e5ad134..b7b9e3e7613 100644
--- a/docs/en-US/add-loadbalancer-rule-vpc.xml
+++ b/docs/en-US/add-loadbalancer-rule-vpc.xml
@@ -21,103 +21,310 @@
-->
Adding Load Balancing Rules on a VPC
- A &PRODUCT; user or administrator may create load balancing rules that balance traffic
- received at a public IP to one or more VMs that belong to a network tier that provides load
- balancing service in a VPC. A user creates a rule, specifies an algorithm, and assigns the rule
- to a set of VMs within a VPC.
-
-
- Log in to the &PRODUCT; UI as an administrator or end user.
-
-
- In the left navigation, choose Network.
-
-
- In the Select view, select VPC.
- All the VPCs that you have created for the account is listed in the page.
-
-
- Click the Configure button of the VPC to which you want to configure load balancing
- rules.
- The VPC page is displayed where all the tiers you created are listed in a
- diagram.
-
-
- Click the Settings icon.
- The following options are displayed.
-
+ In a VPC, you can configure two types of load balancing—external LB and internal LB.
+ External LB is nothing but a LB rule created to redirect the traffic received at a public IP of
+ the VPC virtual router. The traffic is load balanced within a tier based on your configuration.
+ Citrix NetScaler and VPC virtual router are supported for external LB. When you use internal LB
+ service, traffic received at a tier is load balanced across different tiers within the VPC. For
+ example, traffic reached at Web tier is redirected to Application tier. External load balancing
+ devices are not supported for internal LB. The service is provided by a internal LB VM
+ configured on the target tier.
+
+ Load Balancing Within a Tier (External LB)
+ A &PRODUCT; user or administrator may create load balancing rules that balance traffic
+ received at a public IP to one or more VMs that belong to a network tier that provides load
+ balancing service in a VPC. A user creates a rule, specifies an algorithm, and assigns the
+ rule to a set of VMs within a VPC.
+
+
+ Log in to the &PRODUCT; UI as an administrator or end user.
+
+
+ In the left navigation, choose Network.
+
+
+ In the Select view, select VPC.
+ All the VPCs that you have created for the account is listed in the page.
+
+
+ Click the Configure button of the VPC, for which you want to configure load balancing
+ rules.
+ The VPC page is displayed where all the tiers you created listed in a diagram.
+ For each tier, the following options are displayed:
+
+
+ Internal LB
+
+
+ Public LB IP
+
+
+ Static NAT
+
+
+ Virtual Machines
+
+
+ CIDR
+
+
+ The following router information is displayed:
+
+
+ Private Gateways
+
+
+ Public IP Addresses
+
+
+ Site-to-Site VPNs
+
+
+ Network ACL Lists
+
+
+
+
+ In the Router node, select Public IP Addresses.
+ The IP Addresses page is displayed.
+
+
+ Click the IP address for which you want to create the rule, then click the
+ Configuration tab.
+
+
+ In the Load Balancing node of the diagram, click View All.
+
+
+ Select the tier to which you want to apply the rule.
+
+
+ Specify the following:
+
+
+ Name: A name for the load balancer rule.
+
+
+ Public Port: The port that receives the incoming
+ traffic to be balanced.
+
+
+ Private Port: The port that the VMs will use to
+ receive the traffic.
+
+
+ Algorithm. Choose the load balancing algorithm
+ you want &PRODUCT; to use. &PRODUCT; supports the following well-known
+ algorithms:
+
+
+ Round-robin
+
+
+ Least connections
+
+
+ Source
+
+
+
+
+ Stickiness. (Optional) Click Configure and choose
+ the algorithm for the stickiness policy. See Sticky Session Policies for Load Balancer
+ Rules.
+
+
+ Add VMs: Click Add VMs, then select two or more
+ VMs that will divide the load of incoming traffic, and click Apply.
+
+
+
+
+ The new load balancing rule appears in the list. You can repeat these steps to add more
+ load balancing rules for this IP address.
+
+
+ Load Balancing Across Tiers
+ &PRODUCT; supports sharing workload across different tiers within your VPC. Assume that
+ multiple tiers are set up in your environment, such as Web tier and Application tier. Traffic
+ to each tier is balanced on the VPC virtual router on the public side, as explained in . If you want the traffic coming from the Web tier to
+ the Application tier to be balanced, use the internal load balancing feature offered by
+ &PRODUCT;.
+
+ How Does Internal LB Work in VPC?
+ In this figure, a public LB rule is created for the public IP 72.52.125.10 with public
+ port 80 and private port 81. The LB rule, created on the VPC virtual router, is applied on
+ the traffic coming from the Internet to the VMs on the Web tier. On the Application tier two
+ internal load balancing rules are created. An internal LB rule for the guest IP 10.10.10.4
+ with load balancer port 23 and instance port 25 is configured on the VM, InternalLBVM1.
+ Another internal LB rule for the guest IP 10.10.10.4 with load balancer port 45 and instance
+ port 46 is configured on the VM, InternalLBVM1. Another internal LB rule for the guest IP
+ 10.10.10.6, with load balancer port 23 and instance port 25 is configured on the VM,
+ InternalLBVM2.
+
+
+
+
+
+ vpc-lb.png: Configuring internal LB for VPC
+
+
+
+
+ Enabling Internal LB on a VPC Tier
+
- IP Addresses
+ Create a network offering, as given in .
- Gateways
+ Create an internal load balancing rule and apply, as given in .
+
+
+
+
+ Creating a Network Offering for Internal LB
+ To have internal LB support on VPC, create a network offering as follows:
+
+
+ Log in to the &PRODUCT; UI as a user or admin.
- Site-to-Site VPN
+ From the Select Offering drop-down, choose Network Offering.
- Network ACLs
-
-
-
-
- Select IP Addresses.
- The IP Addresses page is displayed.
-
-
- Click the IP address for which you want to create the rule, then click the Configuration
- tab.
-
-
- In the Load Balancing node of the diagram, click View All.
-
-
- Select the tier to which you want to apply the rule.
-
- In a VPC, the load balancing service is supported only on a single tier.
-
-
-
- Specify the following:
-
-
- Name: A name for the load balancer rule.
+ Click Add Network Offering.
- Public Port: The port that receives the incoming
- traffic to be balanced.
-
-
- Private Port: The port that the VMs will use to
- receive the traffic.
-
-
- Algorithm. Choose the load balancing algorithm you
- want &PRODUCT; to use. &PRODUCT; supports the following well-known algorithms:
+ In the dialog, make the following choices:
- Round-robin
+ Name: Any desired name for the network
+ offering.
- Least connections
+ Description: A short description of the
+ offering that can be displayed to users.
- Source
+ Network Rate: Allowed data transfer rate in MB
+ per second.
+
+
+ Traffic Type: The type of network traffic that
+ will be carried on the network.
+
+
+ Guest Type: Choose whether the guest network is
+ isolated or shared.
+
+
+ Persistent: Indicate whether the guest network
+ is persistent or not. The network that you can provision without having to deploy a
+ VM on it is termed persistent network.
+
+
+ VPC: This option indicate whether the guest
+ network is Virtual Private Cloud-enabled. A Virtual Private Cloud (VPC) is a
+ private, isolated part of &PRODUCT;. A VPC can have its own virtual network topology
+ that resembles a traditional physical network. For more information on VPCs, see
+ .
+
+
+ Specify VLAN: (Isolated guest networks only)
+ Indicate whether a VLAN should be specified when this offering is used.
+
+
+ Supported Services: Select Load Balancer.
+ Select InternalLbVM from the provider list.
+
+
+ Load Balancer Type: Select Internal LB from the
+ drop-down.
+
+
+ System Offering: Choose the system service
+ offering that you want virtual routers to use in this network.
+
+
+ Conserve mode: Indicate whether to use conserve
+ mode. In this mode, network resources are allocated only when the first virtual
+ machine starts in the network.
- Stickiness. (Optional) Click Configure and choose
- the algorithm for the stickiness policy. See Sticky Session Policies for Load Balancer
- Rules.
+ Click OK and the network offering is created.
+
+
+
+
+ Creating an Internal LB Rule
+
+
+ Log in to the &PRODUCT; UI as an administrator or end user.
- Add VMs: Click Add VMs, then select two or more VMs
- that will divide the load of incoming traffic, and click Apply.
+ In the left navigation, choose Network.
-
-
-
- The new load balancing rule appears in the list. You can repeat these steps to add more load
- balancing rules for this IP address.
-
\ No newline at end of file
+
+ In the Select view, select VPC.
+ All the VPCs that you have created for the account is listed in the page.
+
+
+ Locate the VPC for which you want to configure internal LB, then click
+ Configure.
+ The VPC page is displayed where all the tiers you created listed in a
+ diagram.
+
+
+ Locate the Tier for which you want to configure an internal LB rule, click Internal
+ LB.
+ In the Internal LB page, click Add Internal LB.
+
+
+ In the dialog, specify the following:
+
+
+ Name: A name for the load balancer rule.
+
+
+ Description: A short description of the rule
+ that can be displayed to users.
+
+
+ Source IP Address: The source IP from which
+ traffic originates. Typically, this is the IP of an instance on another tier within
+ your VPC.
+
+
+ Source Port: The port associated with the
+ source IP. Traffic on this port is load balanced.
+
+
+ Instance Port: The port of the internal LB
+ VM.
+
+
+ Algorithm. Choose the load balancing algorithm
+ you want &PRODUCT; to use. &PRODUCT; supports the following well-known
+ algorithms:
+
+
+ Round-robin
+
+
+ Least connections
+
+
+ Source
+
+
+
+
+
+
+
+
+
diff --git a/docs/en-US/add-portforward-rule-vpc.xml b/docs/en-US/add-portforward-rule-vpc.xml
index c3dbc39bb19..5b1bb49a0a3 100644
--- a/docs/en-US/add-portforward-rule-vpc.xml
+++ b/docs/en-US/add-portforward-rule-vpc.xml
@@ -35,28 +35,42 @@
Click the Configure button of the VPC to which you want to deploy the VMs.
The VPC page is displayed where all the tiers you created are listed in a
diagram.
-
-
- Click the Settings icon.
- The following options are displayed.
+ For each tier, the following options are displayed:
- IP Addresses
+ Internal LB
- Gateways
+ Public LB IP
- Site-to-Site VPN
+ Static NAT
- Network ACLs
+ Virtual Machines
+
+
+ CIDR
+
+
+ The following router information is displayed:
+
+
+ Private Gateways
+
+
+ Public IP Addresses
+
+
+ Site-to-Site VPNs
+
+
+ Network ACL Lists
- Choose an existing IP address or acquire a new IP address. Click the name of the IP
- address in the list.
+ In the Router node, select Public IP Addresses.
The IP Addresses page is displayed.
@@ -95,7 +109,7 @@
Add VM: Click Add VM. Select the name of the
instance to which this rule applies, and click Apply.
- You can test the rule by opening an ssh session to the instance.
+ You can test the rule by opening an SSH session to the instance.
diff --git a/docs/en-US/add-tier.xml b/docs/en-US/add-tier.xml
index 6beaab2a151..e5334d39ca6 100644
--- a/docs/en-US/add-tier.xml
+++ b/docs/en-US/add-tier.xml
@@ -41,6 +41,9 @@
Click the Configure button of the VPC for which you want to set up tiers.
+
+
+ Click Create network.
The Add new tier dialog is displayed, as follows:
@@ -62,7 +65,7 @@
Network Offering: The following default network
- offerings are listed: DefaultIsolatedNetworkOfferingForVpcNetworksNoLB,
+ offerings are listed: Internal LB, DefaultIsolatedNetworkOfferingForVpcNetworksNoLB,
DefaultIsolatedNetworkOfferingForVpcNetworks
In a VPC, only one tier can be created by using LB-enabled network offering.
diff --git a/docs/en-US/add-vm-to-tier.xml b/docs/en-US/add-vm-to-tier.xml
index e401eed2656..c7d769d9d11 100644
--- a/docs/en-US/add-vm-to-tier.xml
+++ b/docs/en-US/add-vm-to-tier.xml
@@ -33,13 +33,21 @@
Click the Configure button of the VPC to which you want to deploy the VMs.
- The VPC page is displayed where all the tiers you created are listed.
+ The VPC page is displayed where all the tiers you have created are listed.
- Click the Add VM button of the tier for which you want to add a VM.
+ Click Virtual Machines tab of the tier to which you want to add a VM.
+
+
+
+
+
+ add-vm-vpc.png: adding a VM to a vpc.
+
+
The Add Instance page is displayed.
Follow the on-screen instruction to add an instance. For information on adding an
- instance, see Adding Instances section in the Installation Guide.
+ instance, see the Installation Guide.
diff --git a/docs/en-US/build-rpm.xml b/docs/en-US/build-rpm.xml
index 7caf924bfe4..100a06f486e 100644
--- a/docs/en-US/build-rpm.xml
+++ b/docs/en-US/build-rpm.xml
@@ -48,6 +48,7 @@ under the License.
Generating RPMS
Now that we have the prerequisites and source, you will cd to the packaging/centos63/ directory.
+ $ cd packaging/centos63
Generating RPMs is done using the package.sh script:
$./package.sh
diff --git a/docs/en-US/configure-acl.xml b/docs/en-US/configure-acl.xml
index 299196c5502..e7459e68dbf 100644
--- a/docs/en-US/configure-acl.xml
+++ b/docs/en-US/configure-acl.xml
@@ -37,31 +37,66 @@
All the VPCs that you have created for the account is listed in the page.
- Click the Settings icon.
- The following options are displayed.
+ Click the Configure button of the VPC, for which you want to configure load balancing
+ rules.
+ For each tier, the following options are displayed:
- IP Addresses
+ Internal LB
- Gateways
+ Public LB IP
- Site-to-Site VPN
+ Static NAT
- Network ACLs
+ Virtual Machines
+
+
+ CIDR
+
+
+ The following router information is displayed:
+
+
+ Private Gateways
+
+
+ Public IP Addresses
+
+
+ Site-to-Site VPNs
+
+
+ Network ACL Lists
- Select Network ACLs.
- The Network ACLs page is displayed.
+ Select Network ACL Lists.
+ The following default rules are displayed in the Network ACLs page: default_allow,
+ default_deny.
- Click Add Network ACLs.
+ Click Add ACL Lists, and specify the following:
+
+
+ ACL List Name: A name for the ACL list.
+
+
+ Description: A short description of the ACL list
+ that can be displayed to users.
+
+
+
+
+ Select the ACL list.
+
+
+ Select the ACL List Rules tab.
To add an ACL rule, fill in the following fields to specify what kind of network traffic
- is allowed in this tier.
+ is allowed in the VPC.
CIDR: The CIDR acts as the Source CIDR for the
@@ -74,7 +109,8 @@
Protocol: The networking protocol that sources use
to send traffic to the tier. The TCP and UDP protocols are typically used for data
exchange and end-user communications. The ICMP protocol is typically used to send error
- messages or network monitoring data.
+ messages or network monitoring data. All supports all the traffic. Other option is
+ Protocol Number.
Start Port, End
@@ -83,8 +119,10 @@
fields.
- Select Tier: Select the tier for which you want to
- add this ACL rule.
+ Protocol Number: The protocol number associated
+ with IPv4 or IPv6. For more information, see Protocol
+ Numbers.
ICMP Type, ICMP
@@ -92,48 +130,14 @@
sent.
- Traffic Type: Select the traffic type you want to
- apply.
-
-
- Egress: To add an egress rule, select Egress
- from the Traffic type drop-down box and click Add. This specifies what type of
- traffic is allowed to be sent out of VM instances in this tier. If no egress rules
- are specified, all traffic from the tier is allowed out at the VPC virtual router.
- Once egress rules are specified, only the traffic specified in egress rules and the
- responses to any traffic that has been allowed in through an ingress rule are
- allowed out. No egress rule is required for the VMs in a tier to communicate with
- each other.
-
-
- Ingress: To add an ingress rule, select Ingress
- from the Traffic type drop-down box and click Add. This specifies what network
- traffic is allowed into the VM instances in this tier. If no ingress rules are
- specified, then no traffic will be allowed in, except for responses to any traffic
- that has been allowed out through an egress rule.
-
-
-
- By default, all incoming and outgoing traffic to the guest networks is blocked. To
- open the ports, create a new network ACL.
-
+ Action: What action to be taken.
Click Add. The ACL rule is added.
- To view the list of ACL rules you have added, click the desired tier from the Network
- ACLs page, then select the Network ACL tab.
-
-
-
-
-
- network-acl.png: adding, editing, deleting an ACL rule.
-
-
You can edit the tags assigned to the ACL rules and delete the ACL rules you have
- created. Click the appropriate button in the Actions column.
+ created. Click the appropriate button in the Details tab.
diff --git a/docs/en-US/enable-disable-static-nat-vpc.xml b/docs/en-US/enable-disable-static-nat-vpc.xml
index 17f0c10540f..467a304915d 100644
--- a/docs/en-US/enable-disable-static-nat-vpc.xml
+++ b/docs/en-US/enable-disable-static-nat-vpc.xml
@@ -42,27 +42,42 @@
Click the Configure button of the VPC to which you want to deploy the VMs.
The VPC page is displayed where all the tiers you created are listed in a
diagram.
-
-
- Click the Settings icon.
- The following options are displayed.
+ For each tier, the following options are displayed.
- IP Addresses
+ Internal LB
- Gateways
+ Public LB IP
- Site-to-Site VPN
+ Static NAT
- Network ACLs
+ Virtual Machines
+
+
+ CIDR
+
+
+ The following router information is displayed:
+
+
+ Private Gateways
+
+
+ Public IP Addresses
+
+
+ Site-to-Site VPNs
+
+
+ Network ACL Lists
- Select IP Addresses.
+ In the Router node, select Public IP Addresses.
The IP Addresses page is displayed.
@@ -74,7 +89,7 @@
- enable-disable.png: button to enable Statid NAT.
+ enable-disable.png: button to enable Static NAT.
The button toggles between Enable and Disable, depending on whether
static NAT is currently enabled for the IP address.
diff --git a/docs/en-US/gsoc-dharmesh.xml b/docs/en-US/gsoc-dharmesh.xml
new file mode 100644
index 00000000000..5e2bf734d7f
--- /dev/null
+++ b/docs/en-US/gsoc-dharmesh.xml
@@ -0,0 +1,149 @@
+
+
+%BOOK_ENTITIES;
+]>
+
+
+
+
+ Dharmesh's 2013 GSoC Proposal
+ This chapter describes Dharmrsh's 2013 Google Summer of Code project within the &PRODUCT; ASF project. It is a copy paste of the submitted proposal.
+
+ Abstract
+
+ The project aims to bring cloudformation like service to cloudstack. One of the prime use-case is cluster computing frameworks on cloudstack. A cloudformation service will give users and administrators of cloudstack ability to manage and control a set of resources easily. The cloudformation will allow booting and configuring a set of VMs and form a cluster. Simple example would be LAMP stack. More complex clusters such as mesos or hadoop cluster requires a little more advanced configuration. There is already some work done by Chiradeep Vittal at this front [5]. In this project, I will implement server side cloudformation service for cloudstack and demonstrate how to run mesos cluster using it.
+
+
+
+
+ Mesos
+
+ Mesos is a resource management platform for clusters. It aims to increase resource utilization of clusters by sharing cluster resources among multiple processing frameworks(like MapReduce, MPI, Graph Processing) or multiple instances of same framework. It provides efficient resource isolation through use of containers. Uses zookeeper for state maintenance and fault tolerance.
+
+
+
+
+ What can run on mesos ?
+
+ Spark: A cluster computing framework based on the Resilient Distributed Datasets (RDDs) abstraction. RDD is more generalized than MapReduce and can support iterative and interactive computation while retaining fault tolerance, scalability, data locality etc.
+
+ Hadoop:: Hadoop is fault tolerant and scalable distributed computing framework based on MapReduce abstraction.
+
+ Begel:: A graph processing framework based on pregel.
+
+ and other frameworks like MPI, Hypertable.
+
+
+
+ How to deploy mesos ?
+
+ Mesos provides cluster installation scripts for cluster deployment. There are also scripts available to deploy a cluster on Amazon EC2. It would be interesting to see if this scripts can be leveraged in anyway.
+
+
+
+ Deliverables
+
+
+ Deploy CloudStack and understand instance configuration/contextualization
+
+
+ Test and deploy Mesos on a set of CloudStack based VM, manually. Design/propose an automation framework
+
+
+ Test stackmate and engage chiradeep (report bugs, make suggestion, make pull request)
+
+
+ Create cloudformation template to provision a Mesos Cluster
+
+
+ Compare with Apache Whirr or other cluster provisioning tools for server side implementation of cloudformation service.
+
+
+
+
+
+
+
+ API
+
+ Query API will be based on Amazon AWS cloudformation service. This will allow leveraging existing tools for AWS.
+
+
+
+ Timeline
+ 1-1.5 week : project design. Architecture, tools selection, API design
+ 1-1.5 week : getting familiar with cloudstack and stackmate codebase and architecture details
+ 1-1.5 week : getting familiar with mesos internals
+ 1-1.5 week : setting up the dev environment and create mesos templates
+ 2-3 week : build provisioning and configuration module
+ Midterm evaluation: provisioning module, configuration module
+ 2-3 week : develope cloudformation server side implementation
+ 2-3 week : test and integrate
+
+
+
+ Future Work
+
+
+ Auto Scaling:
+ Automatically adding or removing VMs from mesos cluster based on various conditions like utilization going above/below a static threshold. There can be more sophisticated strategies based on prediction or fine grained metric collection with tight integration with mesos framework.
+
+
+ Cluster Simulator:
+ Integrating with existing simulator to simulate mesos clusters. This can be useful in various scenarios, for example while developing a new scheduling algorithm, testing autoscaling etc.
+
+
+
+
diff --git a/docs/en-US/gsoc-imduffy15.xml b/docs/en-US/gsoc-imduffy15.xml
new file mode 100644
index 00000000000..652152fcc4b
--- /dev/null
+++ b/docs/en-US/gsoc-imduffy15.xml
@@ -0,0 +1,395 @@
+
+
+%BOOK_ENTITIES;
+]>
+
+
+
+
+ Ians's 2013 GSoC Proposal
+ This chapter describes Ians 2013 Google Summer of Code project within the &PRODUCT; ASF project. It is a copy paste of the submitted proposal.
+
+ LDAP user provisioning
+
+ "Need to automate the way the LDAP users are provisioned into cloud stack. This will mean better
+ integration with a LDAP server, ability to import users and a way to define how the LDAP user
+ maps to the cloudstack users."
+
+
+
+ Abstract
+
+ The aim of this project is to provide an more effective mechanism to provision users from LDAP
+ into cloudstack. Currently cloudstack enables LDAP authentication. In this authentication users
+ must be first setup in cloudstack. Once the user is setup in cloudstack they can authenticate
+ using their LDAP username and password. This project will improve Cloudstack LDAP integration
+ by enabling users be setup automatically using their LDAP credential
+
+
+
+ Deliverables
+
+
+ Service that retrieves a list of LDAP users from a configured group
+
+
+ Extension of the cloudstack UI "Add User" screen to offer user list from LDAP
+
+
+ Add service for saving new user it details from LDAP
+
+
+ BDD unit and acceptance automated testing
+
+
+ Document change details
+
+
+
+
+ Quantifiable Results
+
+
+
+
+ Given
+ An administrator wants to add new user to cloudstack and LDAP is setup in cloudstack
+
+
+ When
+ The administrator opens the "Add User" screen
+
+
+ Then
+ A table of users appears for the current list of users (not already created on cloudstack) from the LDAP group displaying their usernames, given name and email address. The timezone dropdown will still be available beside each user
+
+
+
+
+
+
+
+
+
+ Given
+ An administrator wants to add new user to cloudstack and LDAP is not setup in cloudstack
+
+
+ When
+ The administrator opens the "Add User" screen
+
+
+ Then
+ The current add user screen and functionality is provided
+
+
+
+
+
+
+
+
+
+ Given
+ An administrator wants to add new user to cloudstack and LDAP is setup in cloudstack
+
+
+ When
+ The administrator opens the "Add User" screen and mandatory information is missing
+
+
+ Then
+ These fields will be editable to enable you to populate the name or email address
+
+
+
+
+
+
+
+
+
+ Given
+ An administrator wants to add new user to cloudstack, LDAP is setup and the user being created is in the LDAP query group
+
+
+ When
+ The administrator opens the "Add User" screen
+
+
+ Then
+ There is a list of LDAP users displayed but the user is present in the list
+
+
+
+
+
+
+
+
+
+ Given
+ An administrator wants to add a new user to cloudstack, LDAP is setup and the user is not in the query group
+
+
+ When
+ The administrator opens the "Add User" screen
+
+
+ Then
+ There is a list of LDAP users displayed but the user is not in the list
+
+
+
+
+
+
+
+
+
+ Given
+ An administrator wants to add a group of new users to cloudstack
+
+
+ When
+ The administrator opens the "Add User" screen, selects the users and hits save
+
+
+ Then
+ The list of new users are saved to the database
+
+
+
+
+
+
+
+
+
+ Given
+ An administrator has created a new LDAP user on cloudstack
+
+
+ When
+ The user authenticates against cloudstack with the right credentials
+
+
+ Then
+ They are authorised in cloudstack
+
+
+
+
+
+
+
+
+
+ Given
+ A user wants to edit an LDAP user
+
+
+ When
+ They open the "Edit User" screen
+
+
+ Then
+ The password fields are disabled and cannot be changed
+
+
+
+
+
+
+
+ The Design Document
+
+
+ LDAP user list service
+
+
+
+ name: ldapUserList
+
+
+ responseObject: LDAPUserResponse {username,email,name}
+
+
+ parameter: listType:enum {NEW, EXISTING,ALL} (Default to ALL if no option provided)
+
+
+ Create a new API service call for retreiving the list of users from LDAP. This will call a new
+ ConfigurationService which will retrieve the list of users using the configured search base and the query
+ filter. The list may be filtered in the ConfigurationService based on listType parameter
+
+
+
+ LDAP Available Service
+
+
+
+ name: ldapAvailable
+
+
+ responseObject LDAPAvailableResponse {available:boolean}
+
+
+ Create a new API service call veriying LDAP is setup correctly verifying the following configuration elements are all set:
+
+
+ ldap.hostname
+
+
+ ldap.port
+
+
+ ldap.usessl
+
+
+ ldap.queryfilter
+
+
+ ldap.searchbase
+
+
+ ldap.dn
+
+
+ ldap.password
+
+
+
+
+
+ LDAP Save Users Service
+
+
+
+ name: ldapSaveUsers
+
+
+ responseObject: LDAPSaveUsersRssponse {list]]>}
+
+
+ parameter: list of users
+
+
+ Saves the list of objects instead. Following the functionality in CreateUserCmd it will
+
+
+ Create the user via the account service
+
+
+ Handle the response
+
+
+ It will be decided whether a transation should remain over whole save or only over individual users. A list of UserResponse will be returned.
+
+
+
+ Extension of cloudstack UI "Add User" screen
+
+
+
+ Extend account.js enable the adding of a list of users with editable fields where required. The new "add user" screen for LDAP setup will:
+
+
+ Make an ajax call to the ldapAvailable, ldapuserList and ldapSaveUsers services
+
+
+ Validate on username, email, firstname and lastname
+
+
+
+
+
+ Extension of cloudstack UI "Edit User" screen
+
+
+
+ Extend account.js to disable the password fields on the edit user screen if LDAP available, specifically:
+
+
+ Make an ajax call to the ldapAvailable, ldapuserList and ldapSaveUsers services
+
+
+ Validate on username, email, firstname and lastname. Additional server validation will nsure the password has not changed
+
+
+
+
+
+ Approach
+
+ To get started a development cloudstack environment will be created with DevCloud used to verify changes. Once the schedule is agreed with the mentor the deliverables will be broken into small user stories with expected delivery dates set. The development cycle will focus on BDD, enforcing all unit and acceptance tests are written first.
+
+
+ A build pipe line for continious delivery environment around cloudstack will be implemented, the following stages will be adopted:
+
+
+
+
+
+ Stage
+ Action
+
+
+
+
+ Commit
+ Run unit tests
+
+
+ Sonar
+ Runs code quality metrics
+
+
+ Acceptance
+ Deploys the devcloud and runs all acceptance tests
+
+
+ Deployment
+ Deploy a new management server using Chef
+
+
+
+
+
+
+ About me
+
+ I am a Computer Science Student at Dublin City University in Ireland. I have interests in virtualization,
+automation, information systems, networking and web development
+
+
+ I was involved with a project in a K-12(educational) environment of moving their server systems over
+to a virtualized environment on ESXi. I have good knowledge of programming in Java, PHP and
+Scripting langages. During the configuration of an automation system for OS deployment I experienced
+some exposure to scripting in powershell, batch, vbs and bash and configuration of PXE images based
+of WinPE and Debian.
+Additionally I am also a mentor in an opensource teaching movement called CoderDojo, we teach kids
+from the age of 8 everything from web page, HTML 5 game and raspberry pi development. It's really
+cool.
+
+
+ I’m excited at the opportunity and learning experience that cloudstack are offering with this project.
+
+
+
diff --git a/docs/en-US/gsoc-tuna.xml b/docs/en-US/gsoc-tuna.xml
new file mode 100644
index 00000000000..0988734a465
--- /dev/null
+++ b/docs/en-US/gsoc-tuna.xml
@@ -0,0 +1,231 @@
+
+
+%BOOK_ENTITIES;
+]>
+
+
+
+
+ Nguyen's 2013 GSoC Proposal
+ This chapter describes Nguyen 2013 Google Summer of Code project within the &PRODUCT; ASF project. It is a copy paste of the submitted proposal.
+
+ Add Xen/XCP support for GRE SDN controller
+
+ "This project aims to enhance the current native SDN controller in supporting Xen/XCP and integrate successfully the open source SDN controller (FloodLight) driving Open vSwitch through its interfaces."
+
+
+
+ Abstract
+
+ SDN, standing for Software-Defined Networking, is an approach to building data network equipments and softwares. It were invented by ONRC, Stanford University. SDN basically decouples the control from physical networking boxes and given to a software application called a controller. SDN has three parts: controller, protocols and switch; In which, OpenFlow is an open standard to deploy innovative protocols. Nowaday, more and more datacenters use SDN instead of traditional physical networking boxes. For example, Google announced that they completely built its own switches and SDN confrollers for use in its internal backbone network.
+
+
+ OpenvSwitch, an open source software switch, is widely used as a virtual switch in virtualized server environments. It can currently run on any Linux-based virtualization platform, such as: KVM, Xen (XenServer, XCP, Xen hypervisor), VirtualBox... It also has been ported to a number of different operating systems and hardware platforms: Linux, FreeBSD, Windows and even non-POSIX embedded systems. In cloud computing IaaS, using OpenvSwitch instead of Linux bridge on compute nodes becomes an inevitable trend because of its powerful features and the ability of OpenFlow integration as well.
+
+
+ In CloudStack, we already have a native SDN controller. With KVM hypervisor, developers can easily install OpenvSwitch module; whereas, Xen even has a build-in one. The combination of SDN controller and OpenvSwitch gives us many advanced things. For example, creating GRE tunnels as an isolation method instead of VLAN is a good try. In this project, we are planning to support GRE tunnels in Xen/XCP hypervisor with the native SDN controller. When it's done, substituting open-sources SDN controllers (floodlight, beacon, pox, nox) for the current one is an amazing next step.
+
+
+
+ Design description
+
+ CloudStack currently has a native SDN Controller that is used to build meshes of GRE tunnels between Xen hosts. There consists of 4 parts: OVS tunnel manager, OVS Dao/VO, Command/Answer and Ovs tunnel plugin. The details are as follow:
+
+
+ OVS tunnel manager: Consist of OvsElement and OvsTunnelManager.
+
+
+ OvsElement is used for controlling Ovs tunnel lifecycle (prepare, release)
+
+
+
+ prepare(network, nic, vm, dest): create tunnel for vm on network to dest
+
+
+ release(network, nic, vm): destroy tunnel for vm on network
+
+
+
+ OvsTunnelManager drives bridge configuration and tunnel creation via calling respective commands to Agent.
+
+
+
+ destroyTunnel(vm, network): call OvsDestroyTunnelCommand to destroy tunnel for vm on network
+
+
+ createTunnel(vm, network, dest): call OvsCreateTunnelCommand to create tunnel for vm on network to dest
+
+
+
+ OVS tunnel plugin: These are ovstunnel and ovs-vif-flows.py script, writen as XAPI plugin. The OVS tunnel manager will call them via XML-RPC.
+
+
+ Ovstunnel plugin calls corresponding vsctl commands for setting up the OVS bridge, creating GRE tunnels or destroying them.
+
+
+
+ setup_ovs_bridge()
+
+
+ destroy_ovs_bridge()
+
+
+ create_tunnel()
+
+
+ destroy_tunnel()
+
+
+
+ Ovs-vif-flow.py clears or applies rule for VIFs every time it is plugged or unplugged from a OVS bridge.
+
+
+
+ clear_flow()
+
+
+ apply_flow()
+
+
+
+ OVS command/answer: It is designed under the format of requests and answers between Manager and Plugin. These commands will correspondence exactly the mentioned manipulations.
+
+
+
+ OvsSetupBridgeCommand
+
+
+ OvsSetupBridgeAnswer
+
+
+ OvsDestroyBridgeCommand
+
+
+ OvsDestroyBridgeAnswer
+
+
+ OvsCreateTunnelCommand
+
+
+ OvsCreateTunnelAnswer
+
+
+ OvsDestroyTunnelCommand
+
+
+ OvsDestroyTunnelAnswer
+
+
+ OvsFetchInterfaceCommand
+
+
+ OvsFetchInterfaceAnswer
+
+
+
+ OVS Dao/VO
+
+
+
+ OvsTunnelInterfaceDao
+
+
+ OvsTunnelInterfaceVO
+
+
+ OvsTunnelNetworkDao
+
+
+ OvsTunnelNetworkVO
+
+
+
+
+ Integrate FloodLight as SDN controller
+
+ I think that we maybe deploy FloodLight Server as a new SystemVM. This VM acts like current SystemVMs. One Floodlight SystemVM per Zone, so it can manage for virtual switches under this zone.
+
+
+
+ Deliverables
+
+ GRE has been used as isolation method in CloudStack when deploy with Xen/XCP hosts.
+
+
+
+ User set sdn.ovs.controller parameter in Global Setting to true. He deploys Advance Networking and chooses GRE as isolation method
+
+
+ Make use of Floodlight instead of native SDN controller.
+
+
+
+
+ About me
+
+ My name is Nguyen Anh Tu, a young and enthusiastic researcher in Cloud Computing Center - Viettel Research and Development Institute, Vietnam. Since last year, we has built Cloud Platform based on CloudStack, starting with version 3.0.2. As the results, some advanced modules were successfully developed, consists of:
+
+
+
+ Encrypt Data Volume for VMs.
+
+
+ Dynamic Allocate Memory for VMs by changing policy on Squeeze Daemon.
+
+
+ AutoScale without using NetScale.
+
+
+ Deploy a new SystemVM type for Intrustion Detection System.
+
+
+
+ Given the working experience and recent researches, I have obtained remarkably the understanding of specific knowledges to carry on this project, details as follow:
+
+
+
+ Java source code on CloudStack: Design Pattern, Spring framework.
+
+
+ Bash, Python programming.
+
+
+ XAPI plugin.
+
+
+ XML-RPC.
+
+
+ OpenVSwitch on Xen.
+
+
+
+ Other knowledges:
+
+
+
+ XAPI RRD, XenStore.
+
+
+ Ocaml Programming (XAPI functions).
+
+
+
+
diff --git a/docs/en-US/guest-ip-ranges.xml b/docs/en-US/guest-ip-ranges.xml
index b3ebd761394..c49dc6a76f8 100644
--- a/docs/en-US/guest-ip-ranges.xml
+++ b/docs/en-US/guest-ip-ranges.xml
@@ -28,5 +28,5 @@
their guest network and their clients.
In shared networks in Basic zone and Security Group-enabled Advanced networks, you will have
the flexibility to add multiple guest IP ranges from different subnets. You can add or remove
- one IP range at a time.
+ one IP range at a time. For more information, see .
diff --git a/docs/en-US/images/add-new-gateway-vpc.png b/docs/en-US/images/add-new-gateway-vpc.png
index f15b778e0f2..5145622a2f4 100644
Binary files a/docs/en-US/images/add-new-gateway-vpc.png and b/docs/en-US/images/add-new-gateway-vpc.png differ
diff --git a/docs/en-US/images/add-vm-vpc.png b/docs/en-US/images/add-vm-vpc.png
new file mode 100644
index 00000000000..b2821a69156
Binary files /dev/null and b/docs/en-US/images/add-vm-vpc.png differ
diff --git a/docs/en-US/images/del-tier.png b/docs/en-US/images/del-tier.png
new file mode 100644
index 00000000000..aa9846cfd9b
Binary files /dev/null and b/docs/en-US/images/del-tier.png differ
diff --git a/docs/en-US/images/mesos-integration-arch.jpg b/docs/en-US/images/mesos-integration-arch.jpg
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/docs/en-US/images/vpc-lb.png b/docs/en-US/images/vpc-lb.png
new file mode 100644
index 00000000000..4269e8b9f9e
Binary files /dev/null and b/docs/en-US/images/vpc-lb.png differ
diff --git a/docs/en-US/ip-vlan-tenant.xml b/docs/en-US/ip-vlan-tenant.xml
new file mode 100644
index 00000000000..42124f0f446
--- /dev/null
+++ b/docs/en-US/ip-vlan-tenant.xml
@@ -0,0 +1,205 @@
+
+
+%BOOK_ENTITIES;
+]>
+
+
+ Dedicated Resources: Public IP Addresses and VLANs Per Account
+ &PRODUCT; provides you the ability to reserve a set of public IP addresses and VLANs
+ exclusively for an account. During zone creation, you can continue to define a set of VLANs and
+ multiple public IP ranges. This feature extends the functionality to enable you to dedicate a
+ fixed set of VLANs and guest IP addresses for a tenant.
+ This feature provides you the following capabilities:
+
+
+ Reserve a VLAN range and public IP address range from an Advanced zone and assign it to
+ a domain or account
+
+
+ Disassociate a VLAN and public IP address range from an domain or account
+
+
+ View the number of public IP addresses allocated to an account
+
+
+ Check whether the required range is available and is conforms to account limits.
+ The maximum IPs per account limit cannot be superseded.
+
+
+
+ Dedicating IP Address Ranges to an Account
+
+
+ Log in to the &PRODUCT; UI as administrator.
+
+
+ In the left navigation bar, click Infrastructure.
+
+
+ In Zones, click View All.
+
+
+ Choose the zone you want to work with.
+
+
+ Click the Physical Network tab.
+
+
+ In the Public node of the diagram, click Configure.
+
+
+ Click the IP Ranges tab.
+ You can either assign an existing IP range to an account, or create a new IP range and
+ assign to an account.
+
+
+ To assign an existing IP range to an account, perform the following:
+
+
+ Locate the IP range you want to work with.
+
+
+ Click Add Account
+
+
+
+
+ addAccount-icon.png: button to assign an IP range to an account.
+
+ button.
+ The Add Account dialog is displayed.
+
+
+ Specify the following:
+
+
+ Account: The account to which you want to
+ assign the IP address range.
+
+
+ Domain: The domain associated with the
+ account.
+
+
+ To create a new IP range and assign an account, perform the following:
+
+
+ Specify the following:
+
+
+ Gateway
+
+
+ Netmask
+
+
+ VLAN
+
+
+ Start IP
+
+
+ End IP
+
+
+ Account: Perform the following:
+
+
+ Click Account.
+ The Add Account page is displayed.
+
+
+ Specify the following:
+
+
+ Account: The account to which you want to
+ assign an IP address range.
+
+
+ Domain: The domain associated with the
+ account.
+
+
+
+
+ Click OK.
+
+
+
+
+
+
+ Click Add.
+
+
+
+
+
+
+
+
+ Dedicating VLAN Ranges to an Account
+
+
+ After the &PRODUCT; Management Server is installed, log in to the &PRODUCT; UI as
+ administrator.
+
+
+ In the left navigation bar, click Infrastructure.
+
+
+ In Zones, click View All.
+
+
+ Choose the zone you want to work with.
+
+
+ Click the Physical Network tab.
+
+
+ In the Guest node of the diagram, click Configure.
+
+
+ Select the Dedicated VLAN Ranges tab.
+
+
+ Click Dedicate VLAN Range.
+ The Dedicate VLAN Range dialog is displayed.
+
+
+ Specify the following:
+
+
+ VLAN Range: The
+ VLAN range that you want to assign to an account.
+
+
+ Account: The
+ account to which you want to assign the selected VLAN range.
+
+
+ Domain: The
+ domain associated with the account.
+
+
+
+
+
+
diff --git a/docs/en-US/multiple-ip-range.xml b/docs/en-US/multiple-ip-range.xml
new file mode 100644
index 00000000000..42e0c2a9555
--- /dev/null
+++ b/docs/en-US/multiple-ip-range.xml
@@ -0,0 +1,42 @@
+
+
+%BOOK_ENTITIES;
+]>
+
+
+ About Multiple IP Ranges
+
+ The feature can only be implemented on IPv4 addresses.
+
+ &PRODUCT; provides you with the flexibility to add guest IP ranges from different subnets in
+ Basic zones and security groups-enabled Advanced zones. For security groups-enabled Advanced
+ zones, it implies multiple subnets can be added to the same VLAN. With the addition of this
+ feature, you will be able to add IP address ranges from the same subnet or from a different one
+ when IP address are exhausted. This would in turn allows you to employ higher number of subnets
+ and thus reduce the address management overhead. To support this feature, the capability of
+ createVlanIpRange API is extended to add IP ranges also from a different
+ subnet.
+ Ensure that you manually configure the gateway of the new subnet before adding the IP range.
+ Note that &PRODUCT; supports only one gateway for a subnet; overlapping subnets are not
+ currently supported.
+ Use the deleteVlanRange API to delete IP ranges. This operation fails if an IP
+ from the remove range is in use. If the remove range contains the IP address on which the DHCP
+ server is running, &PRODUCT; acquires a new IP from the same subnet. If no IP is available in
+ the subnet, the remove operation fails.
+ This feature is supported on KVM, xenServer, and VMware hypervisors.
+
diff --git a/docs/en-US/networks.xml b/docs/en-US/networks.xml
index 8a7405a63ac..b557088273f 100644
--- a/docs/en-US/networks.xml
+++ b/docs/en-US/networks.xml
@@ -33,6 +33,7 @@
+
diff --git a/docs/en-US/pvlan.xml b/docs/en-US/pvlan.xml
new file mode 100644
index 00000000000..96c1a78a85d
--- /dev/null
+++ b/docs/en-US/pvlan.xml
@@ -0,0 +1,57 @@
+
+
+%BOOK_ENTITIES;
+]>
+
+
+
+ Isolation in Advanced Zone Using Private VLAN
+
+
+ About Private VLAN
+ In an Ethernet switch, a VLAN is a broadcast domain in which hosts can establish direct
+ communication with each another at Layer 2. Private VLAN is designed as an extension of VLAN
+ standard to add further segmentation of the logical broadcast domain. A regular VLAN is a
+ single broadcast domain, whereas a private VLAN partitions a larger VLAN broadcast domain into
+ smaller sub-domains. A sub-domain is represented by a pair of VLANs: a Primary VLAN and a
+ Secondary VLAN. The original VLAN that is being divided into smaller groups is called
+ Primary, That implies all VLAN pairs in a private VLAN share the same Primary VLAN. All the
+ secondary VLANs exist only inside the Primary. Each Secondary VLAN has a specific VLAN ID
+ associated to it, which differentiates one sub-domain from another.
+ For further reading:
+
+
+ Understanding Private VLANs
+
+
+ Cisco Systems' Private VLANs: Scalable
+ Security in a Multi-Client Environment
+
+
+ Private VLAN (PVLAN) on vNetwork Distributed Switch
+ - Concept Overview (1010691)
+
+
+
+
+ Prerequisites
+ Ensure that you configure private VLAN on your physical switches out-of-band.
+
+
diff --git a/docs/en-US/release-ip-for-vpc.xml b/docs/en-US/release-ip-for-vpc.xml
index 466ec663a17..f827b671c03 100644
--- a/docs/en-US/release-ip-for-vpc.xml
+++ b/docs/en-US/release-ip-for-vpc.xml
@@ -40,27 +40,42 @@
Click the Configure button of the VPC whose IP you want to release.
The VPC page is displayed where all the tiers you created are listed in a
diagram.
-
-
- Click the Settings icon.
The following options are displayed.
- IP Addresses
+ Internal LB
- Gateways
+ Public LB IP
- Site-to-Site VPN
+ Static NAT
- Network ACLs
+ Virtual Machines
+
+
+ CIDR
+
+
+ The following router information is displayed:
+
+
+ Private Gateways
+
+
+ Public IP Addresses
+
+
+ Site-to-Site VPNs
+
+
+ Network ACL Lists
- Select IP Addresses.
+ Select Public IP Addresses.
The IP Addresses page is displayed.
diff --git a/docs/en-US/remove-tier.xml b/docs/en-US/remove-tier.xml
index b5996eb2de3..701645cc4ed 100644
--- a/docs/en-US/remove-tier.xml
+++ b/docs/en-US/remove-tier.xml
@@ -40,16 +40,18 @@
The Configure VPC page is displayed. Locate the tier you want to work with.
- Click the Remove VPC button:
-
-
-
-
-
- remove-tier.png: removing a tier from a vpc.
-
-
- Wait for some time for the tier to be removed.
+ Select the tier you want to remove.
+
+
+ In the Network Details tab, click the Delete Network button.
+
+
+
+
+ del-tier.png: button to remove a tier
+
+
+ Click Yes to confirm. Wait for some time for the tier to be removed.
diff --git a/docs/en-US/remove-vpc.xml b/docs/en-US/remove-vpc.xml
index c5eff850fd3..b373f1a52c3 100644
--- a/docs/en-US/remove-vpc.xml
+++ b/docs/en-US/remove-vpc.xml
@@ -38,14 +38,15 @@
Select the VPC you want to work with.
- To remove, click the Remove VPC button
+ In the Details tab, click the Remove VPC button
remove-vpc.png: button to remove a VPC
-
+
+ You can remove the VPC by also using the remove button in the Quick View.
You can edit the name and description of a VPC. To do that, select the VPC, then click
the Edit button.
diff --git a/docs/en-US/vpc.xml b/docs/en-US/vpc.xml
index 0665d372b4e..7c94f0d6dd1 100644
--- a/docs/en-US/vpc.xml
+++ b/docs/en-US/vpc.xml
@@ -151,8 +151,8 @@
cannot be used for StaticNAT or port forwarding.
- The instances only have a private IP address that you provision. To communicate with the
- Internet, enable NAT to an instance that you launch in your VPC.
+ The instances can only have a private IP address that you provision. To communicate with
+ the Internet, enable NAT to an instance that you launch in your VPC.
Only new networks can be added to a VPC. The maximum number of networks per VPC is
diff --git a/docs/publican-gsoc-2013.cfg b/docs/publican-gsoc-2013.cfg
new file mode 100644
index 00000000000..35dc517be12
--- /dev/null
+++ b/docs/publican-gsoc-2013.cfg
@@ -0,0 +1,27 @@
+# Publican configuration file for CloudStack Complete Documentation Set
+# Contains all technical docs except release notes
+# Config::Simple 4.58
+# Tue May 29 00:57:27 2012
+#
+# 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.
+
+xml_lang: en-US
+type: Book
+docname: CloudStack_GSoC_Guide
+brand: cloudstack
+chunk_first: 1
+chunk_section_depth: 1
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java
index 280e02e2a32..cb467093955 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreLifeCycle.java
@@ -21,6 +21,7 @@ package org.apache.cloudstack.engine.subsystem.api.storage;
import java.util.Map;
import com.cloud.agent.api.StoragePoolInfo;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
public interface DataStoreLifeCycle {
@@ -28,8 +29,8 @@ public interface DataStoreLifeCycle {
public boolean attachCluster(DataStore store, ClusterScope scope);
public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo);
- boolean attachZone(DataStore dataStore, ZoneScope scope);
-
+ boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType);
+
public boolean dettach();
public boolean unmanaged();
diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java
index 4d845252f57..d436762c25a 100644
--- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java
+++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java
@@ -22,6 +22,7 @@ import java.util.Map;
import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.utils.db.GenericDao;
/**
@@ -109,4 +110,6 @@ public interface PrimaryDataStoreDao extends GenericDao {
Long clusterId, String[] tags);
List findZoneWideStoragePoolsByTags(long dcId, String[] tags);
+
+ List findZoneWideStoragePoolsByHypervisor(long dataCenterId, HypervisorType hypervisorType);
}
diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java
index 7fcddf1940f..d461d58ddfc 100644
--- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java
+++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java
@@ -32,6 +32,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType;
import org.springframework.stereotype.Component;
import com.cloud.host.Status;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.StoragePoolStatus;
@@ -427,4 +428,14 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase
return listBy(sc);
}
+
+ @Override
+ public List findZoneWideStoragePoolsByHypervisor(long dataCenterId, HypervisorType hypervisorType) {
+ SearchCriteriaService sc = SearchCriteria2.create(StoragePoolVO.class);
+ sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, dataCenterId);
+ sc.addAnd(sc.getEntity().getStatus(), Op.EQ, Status.Up);
+ sc.addAnd(sc.getEntity().getScope(), Op.EQ, ScopeType.ZONE);
+ sc.addAnd(sc.getEntity().getHypervisor(), Op.EQ, hypervisorType);
+ return sc.list();
+ }
}
diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java
index 55b2314f0fd..0262f65af0a 100644
--- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java
+++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolVO.java
@@ -31,6 +31,7 @@ import javax.persistence.TemporalType;
import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.Storage.StoragePoolType;
import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolStatus;
@@ -102,6 +103,10 @@ public class StoragePoolVO implements StoragePool{
@Enumerated(value = EnumType.STRING)
private ScopeType scope;
+ @Column(name = "hypervisor")
+ @Enumerated(value = EnumType.STRING)
+ private HypervisorType hypervisor;
+
public long getId() {
return id;
}
@@ -276,6 +281,14 @@ public class StoragePoolVO implements StoragePool{
return this.scope;
}
+ public HypervisorType getHypervisor() {
+ return hypervisor;
+ }
+
+ public void setHypervisor(HypervisorType hypervisor) {
+ this.hypervisor = hypervisor;
+ }
+
@Override
public boolean equals(Object obj) {
if (!(obj instanceof StoragePoolVO) || obj == null) {
diff --git a/engine/components-api/src/com/cloud/network/NetworkManager.java b/engine/components-api/src/com/cloud/network/NetworkManager.java
index 06db2e6cfbe..0054c9af7e5 100755
--- a/engine/components-api/src/com/cloud/network/NetworkManager.java
+++ b/engine/components-api/src/com/cloud/network/NetworkManager.java
@@ -380,7 +380,7 @@ public interface NetworkManager {
String allocatePublicIpForGuestNic(Long networkId, DataCenter dc, Pod pod, Account caller, String requestedIp) throws InsufficientAddressCapacityException;
- NicVO savePlaceholderNic(Network network, String ip4Address, Type vmType);
+ NicVO savePlaceholderNic(Network network, String ip4Address, String ip6Address, Type vmType);
DhcpServiceProvider getDhcpServiceProvider(Network network);
diff --git a/engine/components-api/src/com/cloud/storage/VolumeManager.java b/engine/components-api/src/com/cloud/storage/VolumeManager.java
index 9821966e6b3..c2e5bdcc4ca 100644
--- a/engine/components-api/src/com/cloud/storage/VolumeManager.java
+++ b/engine/components-api/src/com/cloud/storage/VolumeManager.java
@@ -112,4 +112,8 @@ public interface VolumeManager extends VolumeApiService {
DiskProfile allocateTemplatedVolume(Type type, String name,
DiskOfferingVO offering, VMTemplateVO template, VMInstanceVO vm,
Account owner);
+
+ String getVmNameFromVolumeId(long volumeId);
+
+ String getStoragePoolOfVolume(long volumeId);
}
diff --git a/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java
index f81d5ef1ffb..d343df3d344 100755
--- a/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java
+++ b/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java
@@ -93,7 +93,6 @@ public class CloudOrchestrator implements OrchestrationService {
public VirtualMachineEntity createFromScratch(String uuid, String iso, String os, String hypervisor, String hostName, int cpu, int speed, long memory, List networks, List computeTags,
Map details, String owner) {
- // TODO Auto-generated method stub
return null;
}
diff --git a/engine/schema/src/com/cloud/alert/dao/AlertDaoImpl.java b/engine/schema/src/com/cloud/alert/dao/AlertDaoImpl.java
index 01a560a129a..18115a5e499 100755
--- a/engine/schema/src/com/cloud/alert/dao/AlertDaoImpl.java
+++ b/engine/schema/src/com/cloud/alert/dao/AlertDaoImpl.java
@@ -156,7 +156,7 @@ public class AlertDaoImpl extends GenericDaoBase implements Alert
public List listOlderAlerts(Date oldTime) {
if (oldTime == null) return null;
SearchCriteria sc = createSearchCriteria();
- sc.addAnd("createDate", SearchCriteria.Op.LT, oldTime);
+ sc.addAnd("createdDate", SearchCriteria.Op.LT, oldTime);
sc.addAnd("archived", SearchCriteria.Op.EQ, false);
return listIncludingRemovedBy(sc, null);
}
diff --git a/engine/schema/src/com/cloud/dc/dao/ClusterDao.java b/engine/schema/src/com/cloud/dc/dao/ClusterDao.java
index 3ce0798a8a2..673888bc2ab 100644
--- a/engine/schema/src/com/cloud/dc/dao/ClusterDao.java
+++ b/engine/schema/src/com/cloud/dc/dao/ClusterDao.java
@@ -34,4 +34,5 @@ public interface ClusterDao extends GenericDao {
Map> getPodClusterIdMap(List clusterIds);
List listDisabledClusters(long zoneId, Long podId);
List listClustersWithDisabledPods(long zoneId);
+ List listClustersByDcId(long zoneId);
}
diff --git a/engine/schema/src/com/cloud/dc/dao/ClusterDaoImpl.java b/engine/schema/src/com/cloud/dc/dao/ClusterDaoImpl.java
index 86dc65e05bd..ba2686a4004 100644
--- a/engine/schema/src/com/cloud/dc/dao/ClusterDaoImpl.java
+++ b/engine/schema/src/com/cloud/dc/dao/ClusterDaoImpl.java
@@ -52,6 +52,7 @@ public class ClusterDaoImpl extends GenericDaoBase implements C
protected final SearchBuilder AvailHyperSearch;
protected final SearchBuilder ZoneSearch;
protected final SearchBuilder ZoneHyTypeSearch;
+ protected final SearchBuilder ZoneClusterSearch;
private static final String GET_POD_CLUSTER_MAP_PREFIX = "SELECT pod_id, id FROM cloud.cluster WHERE cluster.id IN( ";
private static final String GET_POD_CLUSTER_MAP_SUFFIX = " )";
@@ -85,12 +86,16 @@ public class ClusterDaoImpl extends GenericDaoBase implements C
AvailHyperSearch.and("zoneId", AvailHyperSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
AvailHyperSearch.select(null, Func.DISTINCT, AvailHyperSearch.entity().getHypervisorType());
AvailHyperSearch.done();
+
+ ZoneClusterSearch = createSearchBuilder();
+ ZoneClusterSearch.and("dataCenterId", ZoneClusterSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
+ ZoneClusterSearch.done();
}
@Override
public List listByZoneId(long zoneId) {
SearchCriteria sc = ZoneSearch.create();
- sc.setParameters("dataCenterId", zoneId);
+ sc.setParameters("dataCenterId", zoneId);
return listBy(sc);
}
@@ -223,6 +228,13 @@ public class ClusterDaoImpl extends GenericDaoBase implements C
return customSearch(sc, null);
}
+ @Override
+ public List listClustersByDcId(long zoneId) {
+ SearchCriteria sc = ZoneClusterSearch.create();
+ sc.setParameters("dataCenterId", zoneId);
+ return listBy(sc);
+ }
+
@Override
public boolean remove(Long id) {
Transaction txn = Transaction.currentTxn();
diff --git a/engine/schema/src/com/cloud/domain/dao/DomainDaoImpl.java b/engine/schema/src/com/cloud/domain/dao/DomainDaoImpl.java
index 9460a73dc57..c84aa60897c 100644
--- a/engine/schema/src/com/cloud/domain/dao/DomainDaoImpl.java
+++ b/engine/schema/src/com/cloud/domain/dao/DomainDaoImpl.java
@@ -288,5 +288,5 @@ public class DomainDaoImpl extends GenericDaoBase implements Dom
return parentDomains;
}
-
+
}
diff --git a/engine/schema/src/com/cloud/host/dao/HostDao.java b/engine/schema/src/com/cloud/host/dao/HostDao.java
index 98bdcb470e1..8ceb8f23132 100755
--- a/engine/schema/src/com/cloud/host/dao/HostDao.java
+++ b/engine/schema/src/com/cloud/host/dao/HostDao.java
@@ -80,4 +80,10 @@ public interface HostDao extends GenericDao, StateDao listAllUpAndEnabledNonHAHosts(Type type, Long clusterId, Long podId, long dcId, String haTag);
+
+ List findByPodId(Long podId);
+
+ List findByClusterId(Long clusterId);
+
+ List listByDataCenterId(long id);
}
diff --git a/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java
index 07a42322ce3..810b973e296 100755
--- a/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java
+++ b/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java
@@ -37,6 +37,7 @@ import com.cloud.cluster.agentlb.HostTransferMapVO;
import com.cloud.cluster.agentlb.dao.HostTransferMapDao;
import com.cloud.cluster.agentlb.dao.HostTransferMapDaoImpl;
import com.cloud.dc.ClusterVO;
+import com.cloud.dc.HostPodVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.ClusterDaoImpl;
import com.cloud.host.Host;
@@ -86,6 +87,7 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao
protected SearchBuilder GuidSearch;
protected SearchBuilder DcSearch;
protected SearchBuilder PodSearch;
+ protected SearchBuilder ClusterSearch;
protected SearchBuilder TypeSearch;
protected SearchBuilder StatusSearch;
protected SearchBuilder ResourceStateSearch;
@@ -201,6 +203,9 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao
DcSearch = createSearchBuilder();
DcSearch.and("dc", DcSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
+ DcSearch.and("type", DcSearch.entity().getType(), Op.EQ);
+ DcSearch.and("status", DcSearch.entity().getStatus(), Op.EQ);
+ DcSearch.and("resourceState", DcSearch.entity().getResourceState(), Op.EQ);
DcSearch.done();
ClusterStatusSearch = createSearchBuilder();
@@ -215,9 +220,13 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao
TypeNameZoneSearch.done();
PodSearch = createSearchBuilder();
- PodSearch.and("pod", PodSearch.entity().getPodId(), SearchCriteria.Op.EQ);
+ PodSearch.and("podId", PodSearch.entity().getPodId(), SearchCriteria.Op.EQ);
PodSearch.done();
+ ClusterSearch = createSearchBuilder();
+ ClusterSearch.and("clusterId", ClusterSearch.entity().getClusterId(), SearchCriteria.Op.EQ);
+ ClusterSearch.done();
+
TypeSearch = createSearchBuilder();
TypeSearch.and("type", TypeSearch.entity().getType(), SearchCriteria.Op.EQ);
TypeSearch.done();
@@ -373,7 +382,17 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao
List hosts = listBy(sc);
return hosts.size();
}
-
+
+ @Override
+ public List listByDataCenterId(long id) {
+ SearchCriteria sc = DcSearch.create();
+ sc.setParameters("dcId", id);
+ sc.setParameters("status", Status.Up);
+ sc.setParameters("type", Host.Type.Routing);
+ sc.setParameters("resourceState", ResourceState.Enabled);
+
+ return listBy(sc);
+ }
@Override
public HostVO findByGuid(String guid) {
@@ -906,6 +925,20 @@ public class HostDaoImpl extends GenericDaoBase implements HostDao
return findOneBy(sc);
}
+ @Override
+ public List findByPodId(Long podId) {
+ SearchCriteria sc = PodSearch.create();
+ sc.setParameters("podId", podId);
+ return listBy(sc);
+ }
+
+ @Override
+ public List findByClusterId(Long clusterId) {
+ SearchCriteria sc = ClusterSearch.create();
+ sc.setParameters("clusterId", clusterId);
+ return listBy(sc);
+ }
+
@Override
public List findHypervisorHostInCluster(long clusterId) {
SearchCriteria sc = TypeClusterStatusSearch.create();
diff --git a/engine/schema/src/com/cloud/upgrade/PremiumDatabaseUpgradeChecker.java b/engine/schema/src/com/cloud/upgrade/PremiumDatabaseUpgradeChecker.java
index bad32536955..b035c10f13c 100755
--- a/engine/schema/src/com/cloud/upgrade/PremiumDatabaseUpgradeChecker.java
+++ b/engine/schema/src/com/cloud/upgrade/PremiumDatabaseUpgradeChecker.java
@@ -18,9 +18,6 @@ package com.cloud.upgrade;
import javax.ejb.Local;
-import org.springframework.context.annotation.Primary;
-import org.springframework.stereotype.Component;
-
import com.cloud.upgrade.dao.DbUpgrade;
import com.cloud.upgrade.dao.Upgrade217to218;
import com.cloud.upgrade.dao.Upgrade218to224DomainVlans;
@@ -43,7 +40,6 @@ import com.cloud.upgrade.dao.Upgrade30to301;
import com.cloud.upgrade.dao.Upgrade40to41;
import com.cloud.upgrade.dao.UpgradeSnapshot217to224;
import com.cloud.upgrade.dao.UpgradeSnapshot223to224;
-import com.cloud.upgrade.dao.VersionDaoImpl;
import com.cloud.utils.component.SystemIntegrityChecker;
diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java
index 16ab05cea06..d8f90adfe39 100644
--- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java
+++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java
@@ -18,6 +18,7 @@
package com.cloud.upgrade.dao;
import com.cloud.deploy.DeploymentPlanner;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
import org.apache.log4j.Logger;
@@ -64,6 +65,7 @@ public class Upgrade410to420 implements DbUpgrade {
@Override
public void performDataMigration(Connection conn) {
upgradeVmwareLabels(conn);
+ persistLegacyZones(conn);
createPlaceHolderNics(conn);
updateRemoteAccessVpn(conn);
updateSystemVmTemplates(conn);
@@ -77,6 +79,7 @@ public class Upgrade410to420 implements DbUpgrade {
updateNetworkACLs(conn);
addHostDetailsIndex(conn);
updateNetworksForPrivateGateways(conn);
+ correctExternalNetworkDevicesSetup(conn);
removeFirewallServiceFromSharedNetworkOfferingWithSGService(conn);
fix22xKVMSnapshots(conn);
addIndexForAlert(conn);
@@ -110,16 +113,215 @@ public class Upgrade410to420 implements DbUpgrade {
}
private void updateSystemVmTemplates(Connection conn) {
- PreparedStatement sql = null;
+
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ boolean xenserver = false;
+ boolean kvm = false;
+ boolean VMware = false;
+ boolean Hyperv = false;
+ boolean LXC = false;
+ s_logger.debug("Updating System Vm template IDs");
+ try{
+ //Get all hypervisors in use
+ try {
+ pstmt = conn.prepareStatement("select distinct(hypervisor_type) from `cloud`.`cluster` where removed is null");
+ rs = pstmt.executeQuery();
+ while(rs.next()){
+ if("XenServer".equals(rs.getString(1))){
+ xenserver = true;
+ } else if("KVM".equals(rs.getString(1))){
+ kvm = true;
+ } else if("VMware".equals(rs.getString(1))){
+ VMware = true;
+ } else if("Hyperv".equals(rs.getString(1))) {
+ Hyperv = true;
+ } else if("LXC".equals(rs.getString(1))) {
+ LXC = true;
+ }
+ }
+ } catch (SQLException e) {
+ throw new CloudRuntimeException("Error while listing hypervisors in use", e);
+ }
+
+ s_logger.debug("Updating XenSever System Vms");
+ //XenServer
+ try {
+ //Get 4.2.0 xenserer system Vm template Id
+ pstmt = conn.prepareStatement("select id from `cloud`.`vm_template` where name like 'systemvm-xenserver-4.2' and removed is null order by id desc limit 1");
+ rs = pstmt.executeQuery();
+ if(rs.next()){
+ long templateId = rs.getLong(1);
+ rs.close();
+ pstmt.close();
+ // change template type to SYSTEM
+ pstmt = conn.prepareStatement("update `cloud`.`vm_template` set type='SYSTEM' where id = ?");
+ pstmt.setLong(1, templateId);
+ pstmt.executeUpdate();
+ pstmt.close();
+ // update templete ID of system Vms
+ pstmt = conn.prepareStatement("update `cloud`.`vm_instance` set vm_template_id = ? where type <> 'User' and hypervisor_type = 'XenServer'");
+ pstmt.setLong(1, templateId);
+ pstmt.executeUpdate();
+ pstmt.close();
+ } else {
+ if (xenserver){
+ throw new CloudRuntimeException("4.2.0 XenServer SystemVm template not found. Cannot upgrade system Vms");
+ } else {
+ s_logger.warn("4.2.0 XenServer SystemVm template not found. XenServer hypervisor is not used, so not failing upgrade");
+ }
+ }
+ } catch (SQLException e) {
+ throw new CloudRuntimeException("Error while updating XenServer systemVm template", e);
+ }
+
+ //KVM
+ s_logger.debug("Updating KVM System Vms");
+ try {
+ //Get 4.2.0 KVM system Vm template Id
+ pstmt = conn.prepareStatement("select id from `cloud`.`vm_template` where name = 'systemvm-kvm-4.2' and removed is null order by id desc limit 1");
+ rs = pstmt.executeQuery();
+ if(rs.next()){
+ long templateId = rs.getLong(1);
+ rs.close();
+ pstmt.close();
+ // change template type to SYSTEM
+ pstmt = conn.prepareStatement("update `cloud`.`vm_template` set type='SYSTEM' where id = ?");
+ pstmt.setLong(1, templateId);
+ pstmt.executeUpdate();
+ pstmt.close();
+ // update templete ID of system Vms
+ pstmt = conn.prepareStatement("update `cloud`.`vm_instance` set vm_template_id = ? where type <> 'User' and hypervisor_type = 'KVM'");
+ pstmt.setLong(1, templateId);
+ pstmt.executeUpdate();
+ pstmt.close();
+ } else {
+ if (kvm){
+ throw new CloudRuntimeException("4.2.0 KVM SystemVm template not found. Cannot upgrade system Vms");
+ } else {
+ s_logger.warn("4.2.0 KVM SystemVm template not found. KVM hypervisor is not used, so not failing upgrade");
+ }
+ }
+ } catch (SQLException e) {
+ throw new CloudRuntimeException("Error while updating KVM systemVm template", e);
+ }
+
+ //VMware
+ s_logger.debug("Updating VMware System Vms");
+ try {
+ //Get 4.2.0 VMware system Vm template Id
+ pstmt = conn.prepareStatement("select id from `cloud`.`vm_template` where name = 'systemvm-vmware-4.2' and removed is null order by id desc limit 1");
+ rs = pstmt.executeQuery();
+ if(rs.next()){
+ long templateId = rs.getLong(1);
+ rs.close();
+ pstmt.close();
+ // change template type to SYSTEM
+ pstmt = conn.prepareStatement("update `cloud`.`vm_template` set type='SYSTEM' where id = ?");
+ pstmt.setLong(1, templateId);
+ pstmt.executeUpdate();
+ pstmt.close();
+ // update templete ID of system Vms
+ pstmt = conn.prepareStatement("update `cloud`.`vm_instance` set vm_template_id = ? where type <> 'User' and hypervisor_type = 'VMware'");
+ pstmt.setLong(1, templateId);
+ pstmt.executeUpdate();
+ pstmt.close();
+ } else {
+ if (VMware){
+ throw new CloudRuntimeException("4.2.0 VMware SystemVm template not found. Cannot upgrade system Vms");
+ } else {
+ s_logger.warn("4.2.0 VMware SystemVm template not found. VMware hypervisor is not used, so not failing upgrade");
+ }
+ }
+ } catch (SQLException e) {
+ throw new CloudRuntimeException("Error while updating VMware systemVm template", e);
+ }
+
+ //Hyperv
+ s_logger.debug("Updating Hyperv System Vms");
+ try {
+ //Get 4.2.0 Hyperv system Vm template Id
+ pstmt = conn.prepareStatement("select id from `cloud`.`vm_template` where name = 'systemvm-hyperv-4.2' and removed is null order by id desc limit 1");
+ rs = pstmt.executeQuery();
+ if(rs.next()){
+ long templateId = rs.getLong(1);
+ rs.close();
+ pstmt.close();
+ // change template type to SYSTEM
+ pstmt = conn.prepareStatement("update `cloud`.`vm_template` set type='SYSTEM' where id = ?");
+ pstmt.setLong(1, templateId);
+ pstmt.executeUpdate();
+ pstmt.close();
+ // update templete ID of system Vms
+ pstmt = conn.prepareStatement("update `cloud`.`vm_instance` set vm_template_id = ? where type <> 'User' and hypervisor_type = 'Hyperv'");
+ pstmt.setLong(1, templateId);
+ pstmt.executeUpdate();
+ pstmt.close();
+ } else {
+ if (Hyperv){
+ throw new CloudRuntimeException("4.2.0 HyperV SystemVm template not found. Cannot upgrade system Vms");
+ } else {
+ s_logger.warn("4.2.0 Hyperv SystemVm template not found. Hyperv hypervisor is not used, so not failing upgrade");
+ }
+ }
+ } catch (SQLException e) {
+ throw new CloudRuntimeException("Error while updating Hyperv systemVm template", e);
+ }
+
+ //LXC
+ s_logger.debug("Updating LXC System Vms");
+ try {
+ //Get 4.2.0 LXC system Vm template Id
+ pstmt = conn.prepareStatement("select id from `cloud`.`vm_template` where name = 'systemvm-lxc-4.2' and removed is null order by id desc limit 1");
+ rs = pstmt.executeQuery();
+ if(rs.next()){
+ long templateId = rs.getLong(1);
+ rs.close();
+ pstmt.close();
+ // change template type to SYSTEM
+ pstmt = conn.prepareStatement("update `cloud`.`vm_template` set type='SYSTEM' where id = ?");
+ pstmt.setLong(1, templateId);
+ pstmt.executeUpdate();
+ pstmt.close();
+ // update templete ID of system Vms
+ pstmt = conn.prepareStatement("update `cloud`.`vm_instance` set vm_template_id = ? where type <> 'User' and hypervisor_type = 'LXC'");
+ pstmt.setLong(1, templateId);
+ pstmt.executeUpdate();
+ pstmt.close();
+ } else {
+ if (LXC){
+ throw new CloudRuntimeException("4.2.0 LXC SystemVm template not found. Cannot upgrade system Vms");
+ } else {
+ s_logger.warn("4.2.0 LXC SystemVm template not found. LXC hypervisor is not used, so not failing upgrade");
+ }
+ }
+ } catch (SQLException e) {
+ throw new CloudRuntimeException("Error while updating LXC systemVm template", e);
+ }
+ s_logger.debug("Updating System Vm Template IDs Complete");
+ }
+ finally {
+ try {
+ if (rs != null) {
+ rs.close();
+ }
+
+ if (pstmt != null) {
+ pstmt.close();
+ }
+ } catch (SQLException e) {
+ }
+ }
+ pstmt = null;
try {
- sql = conn.prepareStatement("update vm_template set image_data_store_id = 1 where type = 'SYSTEM' or type = 'BUILTIN'");
- sql.executeUpdate();
+ pstmt = conn.prepareStatement("update vm_template set image_data_store_id = 1 where type = 'SYSTEM' or type = 'BUILTIN'");
+ pstmt.executeUpdate();
} catch (SQLException e) {
throw new CloudRuntimeException("Failed to upgrade vm template data store uuid: " + e.toString());
} finally {
- if (sql != null) {
+ if (pstmt != null) {
try {
- sql.close();
+ pstmt.close();
} catch (SQLException e) {
}
}
@@ -277,6 +479,180 @@ public class Upgrade410to420 implements DbUpgrade {
}
}
+ private void persistLegacyZones(Connection conn) {
+ List listOfLegacyZones = new ArrayList();
+ PreparedStatement pstmt = null;
+ PreparedStatement clustersQuery = null;
+ PreparedStatement clusterDetailsQuery = null;
+ ResultSet rs = null;
+ ResultSet clusters = null;
+ ResultSet clusterDetails = null;
+ ResultSet dcInfo = null;
+ Long vmwareDcId = 1L;
+ Long zoneId;
+ Long clusterId;
+ String clusterHypervisorType;
+ boolean legacyZone;
+ boolean ignoreZone;
+ Long count;
+ String dcOfPreviousCluster = null;
+ String dcOfCurrentCluster = null;
+ String[] tokens;
+ String url;
+ String user = "";
+ String password = "";
+ String vc = "";
+ String dcName = "";
+ String guid;
+ String key;
+ String value;
+
+ try {
+ clustersQuery = conn.prepareStatement("select id, hypervisor_type from `cloud`.`cluster` where removed is NULL");
+ pstmt = conn.prepareStatement("select id from `cloud`.`data_center` where removed is NULL");
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ zoneId = rs.getLong("id");
+ legacyZone = false;
+ ignoreZone = true;
+ count = 0L;
+ // Legacy zone term is meant only for VMware
+ // Legacy zone is a zone with atleast 2 clusters & with multiple DCs or VCs
+ clusters = clustersQuery.executeQuery();
+ if (!clusters.next()) {
+ continue; // Ignore the zone without any clusters
+ } else {
+ dcOfPreviousCluster = null;
+ dcOfCurrentCluster = null;
+ do {
+ clusterHypervisorType = clusters.getString("hypervisor_type");
+ clusterId = clusters.getLong("id");
+ if (clusterHypervisorType.equalsIgnoreCase("VMware")) {
+ ignoreZone = false;
+ clusterDetailsQuery = conn.prepareStatement("select value from `cloud`.`cluster_details` where name='url' and cluster_id=?");
+ clusterDetailsQuery.setLong(1, clusterId);
+ clusterDetails = clusterDetailsQuery.executeQuery();
+ clusterDetails.next();
+ url = clusterDetails.getString("value");
+ tokens = url.split("/"); // url format - http://vcenter/dc/cluster
+ vc = tokens[2];
+ dcName = tokens[3];
+ if (count > 0) {
+ dcOfPreviousCluster = dcOfCurrentCluster;
+ dcOfCurrentCluster = dcName + "@" + vc;
+ if (!dcOfPreviousCluster.equals(dcOfCurrentCluster)) {
+ legacyZone = true;
+ s_logger.debug("Marking the zone " + zoneId + " as legacy zone.");
+ }
+ }
+ } else {
+ s_logger.debug("Ignoring zone " + zoneId + " with hypervisor type " + clusterHypervisorType);
+ break;
+ }
+ count++;
+ } while (clusters.next());
+ if (ignoreZone) {
+ continue; // Ignore the zone with hypervisors other than VMware
+ }
+ }
+ if (legacyZone) {
+ listOfLegacyZones.add(zoneId);
+ } else {
+ assert(clusterDetails != null) : "Couldn't retrieve details of cluster!";
+ s_logger.debug("Discovered non-legacy zone " + zoneId + ". Processing the zone to associate with VMware datacenter.");
+
+ clusterDetailsQuery = conn.prepareStatement("select name, value from `cloud`.`cluster_details` where cluster_id=?");
+ clusterDetailsQuery.setLong(1, clusterId);
+ clusterDetails = clusterDetailsQuery.executeQuery();
+ while (clusterDetails.next()) {
+ key = clusterDetails.getString(1);
+ value = clusterDetails.getString(2);
+ if (key.equalsIgnoreCase("username")) {
+ user = value;
+ } else if (key.equalsIgnoreCase("password")) {
+ password = value;
+ }
+ }
+ guid = dcName + "@" + vc;
+
+ pstmt = conn.prepareStatement("INSERT INTO `cloud`.`vmware_data_center` (uuid, name, guid, vcenter_host, username, password) values(?, ?, ?, ?, ?, ?)");
+ pstmt.setString(1, UUID.randomUUID().toString());
+ pstmt.setString(2, dcName);
+ pstmt.setString(3, guid);
+ pstmt.setString(4, vc);
+ pstmt.setString(5, user);
+ pstmt.setString(6, password);
+ pstmt.executeUpdate();
+
+ pstmt = conn.prepareStatement("SELECT id FROM `cloud`.`vmware_data_center` where guid=?");
+ pstmt.setString(1, guid);
+ dcInfo = pstmt.executeQuery();
+ if(dcInfo.next()) {
+ vmwareDcId = dcInfo.getLong("id");
+ }
+
+ pstmt = conn.prepareStatement("INSERT INTO `cloud`.`vmware_data_center_zone_map` (zone_id, vmware_data_center_id) values(?, ?)");
+ pstmt.setLong(1, zoneId);
+ pstmt.setLong(2, vmwareDcId);
+ pstmt.executeUpdate();
+ }
+ }
+ updateLegacyZones(conn, listOfLegacyZones);
+ } catch (SQLException e) {
+ String msg = "Unable to discover legacy zones." + e.getMessage();
+ s_logger.error(msg);
+ throw new CloudRuntimeException(msg, e);
+ } finally {
+ try {
+ if (rs != null) {
+ rs.close();
+ }
+ if (pstmt != null) {
+ pstmt.close();
+ }
+ if (dcInfo != null) {
+ dcInfo.close();
+ }
+ if (clusters != null) {
+ clusters.close();
+ }
+ if (clusterDetails != null) {
+ clusterDetails.close();
+ }
+ if (clustersQuery != null) {
+ clustersQuery.close();
+ }
+ if (clusterDetailsQuery != null) {
+ clusterDetailsQuery.close();
+ }
+ } catch (SQLException e) {
+ }
+ }
+ }
+
+ private void updateLegacyZones(Connection conn, List zones) {
+ PreparedStatement legacyZonesQuery = null;
+ //Insert legacy zones into table for legacy zones.
+ try {
+ legacyZonesQuery = conn.prepareStatement("INSERT INTO `cloud`.`legacy_zones` (zone_id) VALUES (?)");
+ for(Long zoneId : zones) {
+ legacyZonesQuery.setLong(1, zoneId);
+ legacyZonesQuery.executeUpdate();
+ s_logger.debug("Inserted zone " + zoneId + " into cloud.legacyzones table");
+ }
+ } catch (SQLException e) {
+ throw new CloudRuntimeException("Unable add zones to cloud.legacyzones table.", e);
+ } finally {
+ try {
+ if (legacyZonesQuery != null) {
+ legacyZonesQuery.close();
+ }
+ } catch (SQLException e) {
+ }
+ }
+ }
+
private void createPlaceHolderNics(Connection conn) {
PreparedStatement pstmt = null;
ResultSet rs = null;
@@ -849,4 +1225,363 @@ public class Upgrade410to420 implements DbUpgrade {
}
}
}
+
+ // Corrects upgrade for deployment with F5 and SRX devices (pre 3.0) to network offering &
+ // network service provider paradigm
+ private void correctExternalNetworkDevicesSetup(Connection conn) {
+ PreparedStatement zoneSearchStmt = null, pNetworkStmt = null, f5DevicesStmt = null, srxDevicesStmt = null;
+ ResultSet zoneResults = null, pNetworksResults = null, f5DevicesResult = null, srxDevicesResult = null;
+
+ try {
+ zoneSearchStmt = conn.prepareStatement("SELECT id, networktype FROM `cloud`.`data_center`");
+ zoneResults = zoneSearchStmt.executeQuery();
+ while (zoneResults.next()) {
+ long zoneId = zoneResults.getLong(1);
+ String networkType = zoneResults.getString(2);
+
+ if (!com.cloud.dc.DataCenter.NetworkType.Advanced.toString().equalsIgnoreCase(networkType)) {
+ continue;
+ }
+
+ pNetworkStmt = conn.prepareStatement("SELECT id FROM `cloud`.`physical_network` where data_center_id=?");
+ pNetworkStmt.setLong(1, zoneId);
+ pNetworksResults = pNetworkStmt.executeQuery();
+ while (pNetworksResults.next()) {
+ long physicalNetworkId = pNetworksResults.getLong(1);
+ PreparedStatement fetchF5NspStmt = conn.prepareStatement("SELECT id from `cloud`.`physical_network_service_providers` where physical_network_id=" + physicalNetworkId
+ + " and provider_name = 'F5BigIp'");
+ ResultSet rsF5NSP = fetchF5NspStmt.executeQuery();
+ boolean hasF5Nsp = rsF5NSP.next();
+ fetchF5NspStmt.close();
+
+ // if there is no 'F5BigIP' physical network service provider added into physical network then
+ // add 'F5BigIP' as network service provider and add the entry in 'external_load_balancer_devices'
+ if (!hasF5Nsp) {
+ f5DevicesStmt = conn.prepareStatement("SELECT id FROM host WHERE data_center_id=? AND type = 'ExternalLoadBalancer' AND removed IS NULL");
+ f5DevicesStmt.setLong(1, zoneId);
+ f5DevicesResult = f5DevicesStmt.executeQuery();
+ // add F5BigIP provider and provider instance to physical network if there are any external load
+ // balancers added in the zone
+ while (f5DevicesResult.next()) {
+ long f5HostId = f5DevicesResult.getLong(1);;
+ addF5ServiceProvider(conn, physicalNetworkId, zoneId);
+ addF5LoadBalancer(conn, f5HostId, physicalNetworkId);
+ }
+ }
+
+ PreparedStatement fetchSRXNspStmt = conn.prepareStatement("SELECT id from `cloud`.`physical_network_service_providers` where physical_network_id=" + physicalNetworkId
+ + " and provider_name = 'JuniperSRX'");
+ ResultSet rsSRXNSP = fetchSRXNspStmt.executeQuery();
+ boolean hasSrxNsp = rsSRXNSP.next();
+ fetchSRXNspStmt.close();
+
+ // if there is no 'JuniperSRX' physical network service provider added into physical network then
+ // add 'JuniperSRX' as network service provider and add the entry in 'external_firewall_devices'
+ if (!hasSrxNsp) {
+ srxDevicesStmt = conn.prepareStatement("SELECT id FROM host WHERE data_center_id=? AND type = 'ExternalFirewall' AND removed IS NULL");
+ srxDevicesStmt.setLong(1, zoneId);
+ srxDevicesResult = srxDevicesStmt.executeQuery();
+ // add JuniperSRX provider and provider instance to physical network if there are any external
+ // firewall instances added in to the zone
+ while (srxDevicesResult.next()) {
+ long srxHostId = srxDevicesResult.getLong(1);
+ // add SRX provider and provider instance to physical network
+ addSrxServiceProvider(conn, physicalNetworkId, zoneId);
+ addSrxFirewall(conn, srxHostId, physicalNetworkId);
+ }
+ }
+ }
+ }
+
+ // not the network service provider has been provisioned in to physical network, mark all guest network
+ // to be using network offering 'Isolated with external providers'
+ fixZoneUsingExternalDevices(conn);
+
+ if (zoneResults != null) {
+ try {
+ zoneResults.close();
+ } catch (SQLException e) {
+ }
+ }
+
+ if (zoneSearchStmt != null) {
+ try {
+ zoneSearchStmt.close();
+ } catch (SQLException e) {
+ }
+ }
+ } catch (SQLException e) {
+ throw new CloudRuntimeException("Exception while adding PhysicalNetworks", e);
+ } finally {
+
+ }
+ }
+
+ private void addF5LoadBalancer(Connection conn, long hostId, long physicalNetworkId){
+ PreparedStatement pstmtUpdate = null;
+ try{
+ s_logger.debug("Adding F5 Big IP load balancer with host id " + hostId + " in to physical network" + physicalNetworkId);
+ String insertF5 = "INSERT INTO `cloud`.`external_load_balancer_devices` (physical_network_id, host_id, provider_name, " +
+ "device_name, capacity, is_dedicated, device_state, allocation_state, is_inline, is_managed, uuid) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ pstmtUpdate = conn.prepareStatement(insertF5);
+ pstmtUpdate.setLong(1, physicalNetworkId);
+ pstmtUpdate.setLong(2, hostId);
+ pstmtUpdate.setString(3, "F5BigIp");
+ pstmtUpdate.setString(4, "F5BigIpLoadBalancer");
+ pstmtUpdate.setLong(5, 0);
+ pstmtUpdate.setBoolean(6, false);
+ pstmtUpdate.setString(7, "Enabled");
+ pstmtUpdate.setString(8, "Shared");
+ pstmtUpdate.setBoolean(9, false);
+ pstmtUpdate.setBoolean(10, false);
+ pstmtUpdate.setString(11, UUID.randomUUID().toString());
+ pstmtUpdate.executeUpdate();
+ }catch (SQLException e) {
+ throw new CloudRuntimeException("Exception while adding F5 load balancer device" , e);
+ } finally {
+ if (pstmtUpdate != null) {
+ try {
+ pstmtUpdate.close();
+ } catch (SQLException e) {
+ }
+ }
+ }
+ }
+
+ private void addSrxFirewall(Connection conn, long hostId, long physicalNetworkId){
+ PreparedStatement pstmtUpdate = null;
+ try{
+ s_logger.debug("Adding SRX firewall device with host id " + hostId + " in to physical network" + physicalNetworkId);
+ String insertSrx = "INSERT INTO `cloud`.`external_firewall_devices` (physical_network_id, host_id, provider_name, " +
+ "device_name, capacity, is_dedicated, device_state, allocation_state, uuid) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ pstmtUpdate = conn.prepareStatement(insertSrx);
+ pstmtUpdate.setLong(1, physicalNetworkId);
+ pstmtUpdate.setLong(2, hostId);
+ pstmtUpdate.setString(3, "JuniperSRX");
+ pstmtUpdate.setString(4, "JuniperSRXFirewall");
+ pstmtUpdate.setLong(5, 0);
+ pstmtUpdate.setBoolean(6, false);
+ pstmtUpdate.setString(7, "Enabled");
+ pstmtUpdate.setString(8, "Shared");
+ pstmtUpdate.setString(9, UUID.randomUUID().toString());
+ pstmtUpdate.executeUpdate();
+ }catch (SQLException e) {
+ throw new CloudRuntimeException("Exception while adding SRX firewall device ", e);
+ } finally {
+ if (pstmtUpdate != null) {
+ try {
+ pstmtUpdate.close();
+ } catch (SQLException e) {
+ }
+ }
+ }
+ }
+
+ private void addF5ServiceProvider(Connection conn, long physicalNetworkId, long zoneId){
+ PreparedStatement pstmtUpdate = null;
+ try{
+ // add physical network service provider - F5BigIp
+ s_logger.debug("Adding PhysicalNetworkServiceProvider F5BigIp" + " in to physical network" + physicalNetworkId);
+ String insertPNSP = "INSERT INTO `cloud`.`physical_network_service_providers` (`uuid`, `physical_network_id` , `provider_name`, `state` ," +
+ "`destination_physical_network_id`, `vpn_service_provided`, `dhcp_service_provided`, `dns_service_provided`, `gateway_service_provided`," +
+ "`firewall_service_provided`, `source_nat_service_provided`, `load_balance_service_provided`, `static_nat_service_provided`," +
+ "`port_forwarding_service_provided`, `user_data_service_provided`, `security_group_service_provided`) VALUES (?,?,?,?,0,0,0,0,0,0,0,1,0,0,0,0)";
+
+ pstmtUpdate = conn.prepareStatement(insertPNSP);
+ pstmtUpdate.setString(1, UUID.randomUUID().toString());
+ pstmtUpdate.setLong(2, physicalNetworkId);
+ pstmtUpdate.setString(3, "F5BigIp");
+ pstmtUpdate.setString(4, "Enabled");
+ pstmtUpdate.executeUpdate();
+ }catch (SQLException e) {
+ throw new CloudRuntimeException("Exception while adding PhysicalNetworkServiceProvider F5BigIp", e);
+ } finally {
+ if (pstmtUpdate != null) {
+ try {
+ pstmtUpdate.close();
+ } catch (SQLException e) {
+ }
+ }
+ }
+ }
+
+ private void addSrxServiceProvider(Connection conn, long physicalNetworkId, long zoneId){
+ PreparedStatement pstmtUpdate = null;
+ try{
+ // add physical network service provider - JuniperSRX
+ s_logger.debug("Adding PhysicalNetworkServiceProvider JuniperSRX");
+ String insertPNSP = "INSERT INTO `cloud`.`physical_network_service_providers` (`uuid`, `physical_network_id` , `provider_name`, `state` ," +
+ "`destination_physical_network_id`, `vpn_service_provided`, `dhcp_service_provided`, `dns_service_provided`, `gateway_service_provided`," +
+ "`firewall_service_provided`, `source_nat_service_provided`, `load_balance_service_provided`, `static_nat_service_provided`," +
+ "`port_forwarding_service_provided`, `user_data_service_provided`, `security_group_service_provided`) VALUES (?,?,?,?,0,0,0,0,1,1,1,0,1,1,0,0)";
+
+ pstmtUpdate = conn.prepareStatement(insertPNSP);
+ pstmtUpdate.setString(1, UUID.randomUUID().toString());
+ pstmtUpdate.setLong(2, physicalNetworkId);
+ pstmtUpdate.setString(3, "JuniperSRX");
+ pstmtUpdate.setString(4, "Enabled");
+ pstmtUpdate.executeUpdate();
+ }catch (SQLException e) {
+ throw new CloudRuntimeException("Exception while adding PhysicalNetworkServiceProvider JuniperSRX" , e);
+ } finally {
+ if (pstmtUpdate != null) {
+ try {
+ pstmtUpdate.close();
+ } catch (SQLException e) {
+ }
+ }
+ }
+ }
+
+ // This method does two things
+ //
+ // 1) ensure that networks using external load balancer/firewall in deployments prior to release 3.0
+ // has entry in network_external_lb_device_map and network_external_firewall_device_map
+ //
+ // 2) Some keys of host details for F5 and SRX devices were stored in Camel Case in 2.x releases. From 3.0
+ // they are made in lowercase. On upgrade change the host details name to lower case
+ private void fixZoneUsingExternalDevices(Connection conn) {
+ //Get zones to upgrade
+ List zoneIds = new ArrayList();
+ PreparedStatement pstmt = null;
+ PreparedStatement pstmtUpdate = null;
+ ResultSet rs = null;
+ long networkOfferingId, networkId;
+ long f5DeviceId, f5HostId;
+ long srxDevivceId, srxHostId;
+
+ try {
+ pstmt = conn.prepareStatement("select id from `cloud`.`data_center` where lb_provider='F5BigIp' or firewall_provider='JuniperSRX' or gateway_provider='JuniperSRX'");
+ rs = pstmt.executeQuery();
+ while (rs.next()) {
+ zoneIds.add(rs.getLong(1));
+ }
+ } catch (SQLException e) {
+ throw new CloudRuntimeException("Unable to create network to LB & firewall device mapping for networks that use them", e);
+ }
+
+ if (zoneIds.size() == 0) {
+ return; // no zones using F5 and SRX devices so return
+ }
+
+ // find the default network offering created for external devices during upgrade from 2.2.14
+ try {
+ pstmt = conn.prepareStatement("select id from `cloud`.`network_offerings` where unique_name='Isolated with external providers' ");
+ rs = pstmt.executeQuery();
+ if (rs.first()) {
+ networkOfferingId = rs.getLong(1);
+ } else {
+ throw new CloudRuntimeException("Cannot upgrade as there is no 'Isolated with external providers' network offering crearted .");
+ }
+ } catch (SQLException e) {
+ throw new CloudRuntimeException("Unable to create network to LB & firewalla device mapping for networks that use them", e);
+ }
+
+ for (Long zoneId : zoneIds) {
+ try {
+ // find the F5 device id in the zone
+ pstmt = conn.prepareStatement("SELECT id FROM host WHERE data_center_id=? AND type = 'ExternalLoadBalancer' AND removed IS NULL");
+ pstmt.setLong(1, zoneId);
+ rs = pstmt.executeQuery();
+ if (rs.first()) {
+ f5HostId = rs.getLong(1);
+ } else {
+ throw new CloudRuntimeException("Cannot upgrade as there is no F5 load balancer device found in data center " + zoneId);
+ }
+ pstmt = conn.prepareStatement("SELECT id FROM external_load_balancer_devices WHERE host_id=?");
+ pstmt.setLong(1, f5HostId);
+ rs = pstmt.executeQuery();
+ if (rs.first()) {
+ f5DeviceId = rs.getLong(1);
+ } else {
+ throw new CloudRuntimeException("Cannot upgrade as there is no F5 load balancer device with host ID " + f5HostId + " found in external_load_balancer_device");
+ }
+
+ // find the SRX device id in the zone
+ pstmt = conn.prepareStatement("SELECT id FROM host WHERE data_center_id=? AND type = 'ExternalFirewall' AND removed IS NULL");
+ pstmt.setLong(1, zoneId);
+ rs = pstmt.executeQuery();
+ if (rs.first()) {
+ srxHostId = rs.getLong(1);
+ } else {
+ throw new CloudRuntimeException("Cannot upgrade as there is no SRX firewall device found in data center " + zoneId);
+ }
+ pstmt = conn.prepareStatement("SELECT id FROM external_firewall_devices WHERE host_id=?");
+ pstmt.setLong(1, srxHostId);
+ rs = pstmt.executeQuery();
+ if (rs.first()) {
+ srxDevivceId = rs.getLong(1);
+ } else {
+ throw new CloudRuntimeException("Cannot upgrade as there is no SRX firewall device found with host ID " + srxHostId + " found in external_firewall_devices");
+ }
+
+ // check if network any uses F5 or SRX devices in the zone
+ pstmt = conn.prepareStatement("select id from `cloud`.`networks` where guest_type='Virtual' and data_center_id=? and network_offering_id=? and removed IS NULL");
+ pstmt.setLong(1, zoneId);
+ pstmt.setLong(2, networkOfferingId);
+ rs = pstmt.executeQuery();
+ while (rs.next()) {
+ // get the network Id
+ networkId = rs.getLong(1);
+
+ // add mapping for the network in network_external_lb_device_map
+ String insertLbMapping = "INSERT INTO `cloud`.`network_external_lb_device_map` (uuid, network_id, external_load_balancer_device_id, created) VALUES ( ?, ?, ?, now())";
+ pstmtUpdate = conn.prepareStatement(insertLbMapping);
+ pstmtUpdate.setString(1, UUID.randomUUID().toString());
+ pstmtUpdate.setLong(2, networkId);
+ pstmtUpdate.setLong(3, f5DeviceId);
+ pstmtUpdate.executeUpdate();
+ s_logger.debug("Successfully added entry in network_external_lb_device_map for network " + networkId + " and F5 device ID " + f5DeviceId);
+
+ // add mapping for the network in network_external_firewall_device_map
+ String insertFwMapping = "INSERT INTO `cloud`.`network_external_firewall_device_map` (uuid, network_id, external_firewall_device_id, created) VALUES ( ?, ?, ?, now())";
+ pstmtUpdate = conn.prepareStatement(insertFwMapping);
+ pstmtUpdate.setString(1, UUID.randomUUID().toString());
+ pstmtUpdate.setLong(2, networkId);
+ pstmtUpdate.setLong(3, srxDevivceId);
+ pstmtUpdate.executeUpdate();
+ s_logger.debug("Successfully added entry in network_external_firewall_device_map for network " + networkId + " and SRX device ID " + srxDevivceId);
+ }
+
+ // update host details for F5 and SRX devices
+ s_logger.debug("Updating the host details for F5 and SRX devices");
+ pstmt = conn.prepareStatement("SELECT host_id, name FROM `cloud`.`host_details` WHERE host_id=? OR host_id=?");
+ pstmt.setLong(1, f5HostId);
+ pstmt.setLong(2, srxHostId);
+ rs = pstmt.executeQuery();
+ while (rs.next()) {
+ long hostId = rs.getLong(1);
+ String camlCaseName = rs.getString(2);
+ if (!(camlCaseName.equalsIgnoreCase("numRetries") ||
+ camlCaseName.equalsIgnoreCase("publicZone") ||
+ camlCaseName.equalsIgnoreCase("privateZone") ||
+ camlCaseName.equalsIgnoreCase("publicInterface") ||
+ camlCaseName.equalsIgnoreCase("privateInterface") ||
+ camlCaseName.equalsIgnoreCase("usageInterface") )) {
+ continue;
+ }
+ String lowerCaseName = camlCaseName.toLowerCase();
+ pstmt = conn.prepareStatement("update `cloud`.`host_details` set name=? where host_id=? AND name=?");
+ pstmt.setString(1, lowerCaseName);
+ pstmt.setLong(2, hostId);
+ pstmt.setString(3, camlCaseName);
+ pstmt.executeUpdate();
+ }
+ s_logger.debug("Successfully updated host details for F5 and SRX devices");
+ } catch (SQLException e) {
+ throw new CloudRuntimeException("Unable create a mapping for the networks in network_external_lb_device_map and network_external_firewall_device_map", e);
+ } finally {
+ try {
+ if (rs != null) {
+ rs.close();
+ }
+ if (pstmt != null) {
+ pstmt.close();
+ }
+ } catch (SQLException e) {
+ }
+ }
+ s_logger.info("Successfully upgraded network using F5 and SRX devices to have a entry in the network_external_lb_device_map and network_external_firewall_device_map");
+ }
+ }
}
diff --git a/engine/schema/src/com/cloud/usage/UsageVmDiskVO.java b/engine/schema/src/com/cloud/usage/UsageVmDiskVO.java
new file mode 100644
index 00000000000..6c3ca6940b1
--- /dev/null
+++ b/engine/schema/src/com/cloud/usage/UsageVmDiskVO.java
@@ -0,0 +1,180 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.usage;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="usage_vm_disk")
+public class UsageVmDiskVO {
+ @Id
+ @Column(name="account_id")
+ private long accountId;
+
+ @Column(name="zone_id")
+ private long zoneId;
+
+ @Column(name="vm_id")
+ private Long vmId;
+
+ @Column(name="volume_id")
+ private Long volumeId;
+
+ @Column(name="io_read")
+ private long ioRead;
+
+ @Column(name="io_write")
+ private long ioWrite;
+
+ @Column(name="agg_io_write")
+ private long aggIOWrite;
+
+ @Column(name="agg_io_read")
+ private long aggIORead;
+
+ @Column(name="bytes_read")
+ private long bytesRead;
+
+ @Column(name="bytes_write")
+ private long bytesWrite;
+
+ @Column(name="agg_bytes_write")
+ private long aggBytesWrite;
+
+ @Column(name="agg_bytes_read")
+ private long aggBytesRead;
+
+ @Column(name="event_time_millis")
+ private long eventTimeMillis = 0;
+
+ protected UsageVmDiskVO() {
+ }
+
+ public UsageVmDiskVO(Long accountId, long zoneId, Long vmId, Long volumeId, long ioRead, long ioWrite, long aggIORead, long aggIOWrite,
+ long bytesRead, long bytesWrite, long aggBytesRead, long aggBytesWrite, long eventTimeMillis) {
+ this.accountId = accountId;
+ this.zoneId = zoneId;
+ this.vmId = vmId;
+ this.volumeId = volumeId;
+ this.ioRead = ioRead;
+ this.ioWrite = ioWrite;
+ this.aggIOWrite = aggIOWrite;
+ this.aggIORead = aggIORead;
+ this.bytesRead = bytesRead;
+ this.bytesWrite = bytesWrite;
+ this.aggBytesWrite = aggBytesWrite;
+ this.aggBytesRead = aggBytesRead;
+ this.eventTimeMillis = eventTimeMillis;
+ }
+
+ public long getAccountId() {
+ return accountId;
+ }
+
+ public void setAccountId(long accountId) {
+ this.accountId = accountId;
+ }
+
+ public long getZoneId() {
+ return zoneId;
+ }
+ public void setZoneId(long zoneId) {
+ this.zoneId = zoneId;
+ }
+
+ public Long getIORead() {
+ return ioRead;
+ }
+
+ public void setIORead(Long ioRead) {
+ this.ioRead = ioRead;
+ }
+
+ public Long getIOWrite() {
+ return ioWrite;
+ }
+
+ public void setIOWrite(Long ioWrite) {
+ this.ioWrite = ioWrite;
+ }
+
+ public Long getBytesRead() {
+ return bytesRead;
+ }
+
+ public void setBytesRead(Long bytesRead) {
+ this.bytesRead = bytesRead;
+ }
+
+ public Long getBytesWrite() {
+ return bytesWrite;
+ }
+
+ public void setBytesWrite(Long bytesWrite) {
+ this.bytesWrite = bytesWrite;
+ }
+
+ public long getEventTimeMillis() {
+ return eventTimeMillis;
+ }
+ public void setEventTimeMillis(long eventTimeMillis) {
+ this.eventTimeMillis = eventTimeMillis;
+ }
+
+ public Long getVmId() {
+ return vmId;
+ }
+
+ public Long getVolumeId() {
+ return volumeId;
+ }
+
+ public long getAggIOWrite() {
+ return aggIOWrite;
+ }
+
+ public void setAggIOWrite(long aggIOWrite) {
+ this.aggIOWrite = aggIOWrite;
+ }
+
+ public long getAggIORead() {
+ return aggIORead;
+ }
+
+ public void setAggIORead(long aggIORead) {
+ this.aggIORead = aggIORead;
+ }
+
+ public long getAggBytesWrite() {
+ return aggBytesWrite;
+ }
+
+ public void setAggBytesWrite(long aggBytesWrite) {
+ this.aggBytesWrite = aggBytesWrite;
+ }
+
+ public long getAggBytesRead() {
+ return aggBytesRead;
+ }
+
+ public void setAggBytesRead(long aggBytesRead) {
+ this.aggBytesRead = aggBytesRead;
+ }
+}
diff --git a/engine/schema/src/com/cloud/usage/dao/UsageDao.java b/engine/schema/src/com/cloud/usage/dao/UsageDao.java
index 6d0c162b52b..8a806553112 100644
--- a/engine/schema/src/com/cloud/usage/dao/UsageDao.java
+++ b/engine/schema/src/com/cloud/usage/dao/UsageDao.java
@@ -21,6 +21,7 @@ import java.util.List;
import com.cloud.usage.UsageVO;
import com.cloud.user.AccountVO;
import com.cloud.user.UserStatisticsVO;
+import com.cloud.user.VmDiskStatisticsVO;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDao;
import com.cloud.utils.db.SearchCriteria;
@@ -36,4 +37,7 @@ public interface UsageDao extends GenericDao {
Long getLastAccountId();
Long getLastUserStatsId();
List listPublicTemplatesByAccount(long accountId);
+ Long getLastVmDiskStatsId();
+ void updateVmDiskStats(List vmNetStats);
+ void saveVmDiskStats(List vmNetStats);
}
diff --git a/engine/schema/src/com/cloud/usage/dao/UsageDaoImpl.java b/engine/schema/src/com/cloud/usage/dao/UsageDaoImpl.java
index a5867f0656e..f7d5069eef9 100644
--- a/engine/schema/src/com/cloud/usage/dao/UsageDaoImpl.java
+++ b/engine/schema/src/com/cloud/usage/dao/UsageDaoImpl.java
@@ -32,6 +32,7 @@ import org.springframework.stereotype.Component;
import com.cloud.usage.UsageVO;
import com.cloud.user.AccountVO;
import com.cloud.user.UserStatisticsVO;
+import com.cloud.user.VmDiskStatisticsVO;
import com.cloud.utils.DateUtil;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
@@ -56,6 +57,13 @@ public class UsageDaoImpl extends GenericDaoBase implements Usage
private static final String GET_LAST_USER_STATS = "SELECT id FROM cloud_usage.user_statistics ORDER BY id DESC LIMIT 1";
private static final String GET_PUBLIC_TEMPLATES_BY_ACCOUNTID = "SELECT id FROM cloud.vm_template WHERE account_id = ? AND public = '1' AND removed IS NULL";
+ private static final String GET_LAST_VM_DISK_STATS = "SELECT id FROM cloud_usage.vm_disk_statistics ORDER BY id DESC LIMIT 1";
+ private static final String INSERT_VM_DISK_STATS = "INSERT INTO cloud_usage.vm_disk_statistics (id, data_center_id, account_id, vm_id, volume_id, net_io_read, net_io_write, current_io_read, " +
+ "current_io_write, agg_io_read, agg_io_write, net_bytes_read, net_bytes_write, current_bytes_read, current_bytes_write, agg_bytes_read, agg_bytes_write) " +
+ " VALUES (?,?,?,?,?,?,?,?,?,?, ?, ?, ?, ?,?, ?, ?)";
+ private static final String UPDATE_VM_DISK_STATS = "UPDATE cloud_usage.vm_disk_statistics SET net_io_read=?, net_io_write=?, current_io_read=?, current_io_write=?, agg_io_read=?, agg_io_write=?, " +
+ "net_bytes_read=?, net_bytes_write=?, current_bytes_read=?, current_bytes_write=?, agg_bytes_read=?, agg_bytes_write=? WHERE id=?";
+
protected final static TimeZone s_gmtTimeZone = TimeZone.getTimeZone("GMT");
public UsageDaoImpl () {}
@@ -270,4 +278,101 @@ public class UsageDaoImpl extends GenericDaoBase implements Usage
}
return templateList;
}
+
+ @Override
+ public Long getLastVmDiskStatsId() {
+ Transaction txn = Transaction.currentTxn();
+ PreparedStatement pstmt = null;
+ String sql = GET_LAST_VM_DISK_STATS;
+ try {
+ pstmt = txn.prepareAutoCloseStatement(sql);
+ ResultSet rs = pstmt.executeQuery();
+ if (rs.next()) {
+ return Long.valueOf(rs.getLong(1));
+ }
+ } catch (Exception ex) {
+ s_logger.error("error getting last vm disk stats id", ex);
+ }
+ return null;
+ }
+
+ @Override
+ public void updateVmDiskStats(List vmDiskStats) {
+ Transaction txn = Transaction.currentTxn();
+ try {
+ txn.start();
+ String sql = UPDATE_VM_DISK_STATS;
+ PreparedStatement pstmt = null;
+ pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
+ for (VmDiskStatisticsVO vmDiskStat : vmDiskStats) {
+ pstmt.setLong(1, vmDiskStat.getNetIORead());
+ pstmt.setLong(2, vmDiskStat.getNetIOWrite());
+ pstmt.setLong(3, vmDiskStat.getCurrentIORead());
+ pstmt.setLong(4, vmDiskStat.getCurrentIOWrite());
+ pstmt.setLong(5, vmDiskStat.getAggIORead());
+ pstmt.setLong(6, vmDiskStat.getAggIOWrite());
+ pstmt.setLong(7, vmDiskStat.getNetBytesRead());
+ pstmt.setLong(8, vmDiskStat.getNetBytesWrite());
+ pstmt.setLong(9, vmDiskStat.getCurrentBytesRead());
+ pstmt.setLong(10, vmDiskStat.getCurrentBytesWrite());
+ pstmt.setLong(11, vmDiskStat.getAggBytesRead());
+ pstmt.setLong(12, vmDiskStat.getAggBytesWrite());
+ pstmt.setLong(13, vmDiskStat.getId());
+ pstmt.addBatch();
+ }
+ pstmt.executeBatch();
+ txn.commit();
+ } catch (Exception ex) {
+ txn.rollback();
+ s_logger.error("error saving vm disk stats to cloud_usage db", ex);
+ throw new CloudRuntimeException(ex.getMessage());
+ }
+
+ }
+
+ @Override
+ public void saveVmDiskStats(List vmDiskStats) {
+ Transaction txn = Transaction.currentTxn();
+ try {
+ txn.start();
+ String sql = INSERT_VM_DISK_STATS;
+ PreparedStatement pstmt = null;
+ pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
+ for (VmDiskStatisticsVO vmDiskStat : vmDiskStats) {
+ pstmt.setLong(1, vmDiskStat.getId());
+ pstmt.setLong(2, vmDiskStat.getDataCenterId());
+ pstmt.setLong(3, vmDiskStat.getAccountId());
+ if(vmDiskStat.getVmId() != null){
+ pstmt.setLong(4, vmDiskStat.getVmId());
+ } else {
+ pstmt.setNull(4, Types.BIGINT);
+ }
+ if(vmDiskStat.getVolumeId() != null){
+ pstmt.setLong(5, vmDiskStat.getVolumeId());
+ } else {
+ pstmt.setNull(5, Types.BIGINT);
+ }
+ pstmt.setLong(6, vmDiskStat.getNetIORead());
+ pstmt.setLong(7, vmDiskStat.getNetIOWrite());
+ pstmt.setLong(8, vmDiskStat.getCurrentIORead());
+ pstmt.setLong(9, vmDiskStat.getCurrentIOWrite());
+ pstmt.setLong(10, vmDiskStat.getAggIORead());
+ pstmt.setLong(11, vmDiskStat.getAggIOWrite());
+ pstmt.setLong(12, vmDiskStat.getNetBytesRead());
+ pstmt.setLong(13, vmDiskStat.getNetBytesWrite());
+ pstmt.setLong(14, vmDiskStat.getCurrentBytesRead());
+ pstmt.setLong(15, vmDiskStat.getCurrentBytesWrite());
+ pstmt.setLong(16, vmDiskStat.getAggBytesRead());
+ pstmt.setLong(17, vmDiskStat.getAggBytesWrite());
+ pstmt.addBatch();
+ }
+ pstmt.executeBatch();
+ txn.commit();
+ } catch (Exception ex) {
+ txn.rollback();
+ s_logger.error("error saving vm disk stats to cloud_usage db", ex);
+ throw new CloudRuntimeException(ex.getMessage());
+ }
+
+ }
}
diff --git a/engine/schema/src/com/cloud/usage/dao/UsageVmDiskDao.java b/engine/schema/src/com/cloud/usage/dao/UsageVmDiskDao.java
new file mode 100644
index 00000000000..b72a8d4120f
--- /dev/null
+++ b/engine/schema/src/com/cloud/usage/dao/UsageVmDiskDao.java
@@ -0,0 +1,29 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+package com.cloud.usage.dao;
+
+import java.util.List;
+import java.util.Map;
+
+import com.cloud.usage.UsageVmDiskVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface UsageVmDiskDao extends GenericDao {
+ Map getRecentVmDiskStats();
+ void deleteOldStats(long maxEventTime);
+ void saveUsageVmDisks(List usageVmDisks);
+}
diff --git a/engine/schema/src/com/cloud/usage/dao/UsageVmDiskDaoImpl.java b/engine/schema/src/com/cloud/usage/dao/UsageVmDiskDaoImpl.java
new file mode 100644
index 00000000000..8436c5955c8
--- /dev/null
+++ b/engine/schema/src/com/cloud/usage/dao/UsageVmDiskDaoImpl.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.usage.dao;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import com.cloud.usage.UsageVmDiskVO;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+@Component
+@Local(value={UsageVmDiskDao.class})
+public class UsageVmDiskDaoImpl extends GenericDaoBase implements UsageVmDiskDao {
+ private static final Logger s_logger = Logger.getLogger(UsageVMInstanceDaoImpl.class.getName());
+ private static final String SELECT_LATEST_STATS = "SELECT uvd.account_id, uvd.zone_id, uvd.vm_id, uvd.volume_id, uvd.io_read, uvd.io_write, uvd.agg_io_read, uvd.agg_io_write, " +
+ "uvd.bytes_read, uvd.bytes_write, uvd.agg_bytes_read, uvd.agg_bytes_write, uvd.event_time_millis " +
+ "FROM cloud_usage.usage_vm_disk uvd INNER JOIN (SELECT vmdiskusage.account_id as acct_id, vmdiskusage.zone_id as z_id, max(vmdiskusage.event_time_millis) as max_date " +
+ "FROM cloud_usage.usage_vm_disk vmdiskusage " +
+ "GROUP BY vmdiskusage.account_id, vmdiskusage.zone_id " +
+ ") joinnet on uvd.account_id = joinnet.acct_id and uvd.zone_id = joinnet.z_id and uvd.event_time_millis = joinnet.max_date";
+ private static final String DELETE_OLD_STATS = "DELETE FROM cloud_usage.usage_vm_disk WHERE event_time_millis < ?";
+
+ private static final String INSERT_USAGE_VM_DISK = "INSERT INTO cloud_usage.usage_vm_disk (account_id, zone_id, vm_id, volume_id, io_read, io_write, agg_io_read, agg_io_write, bytes_read, bytes_write, agg_bytes_read, agg_bytes_write, event_time_millis) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)";
+
+ public UsageVmDiskDaoImpl() {
+ }
+
+ @Override
+ public Map getRecentVmDiskStats() {
+ Transaction txn = Transaction.open(Transaction.USAGE_DB);
+ String sql = SELECT_LATEST_STATS;
+ PreparedStatement pstmt = null;
+ try {
+ pstmt = txn.prepareAutoCloseStatement(sql);
+ ResultSet rs = pstmt.executeQuery();
+ Map returnMap = new HashMap();
+ while (rs.next()) {
+ long accountId = rs.getLong(1);
+ long zoneId = rs.getLong(2);
+ long vmId = rs.getLong(3);
+ Long volumeId = rs.getLong(4);
+ long ioRead = rs.getLong(5);
+ long ioWrite = rs.getLong(6);
+ long aggIORead = rs.getLong(7);
+ long aggIOWrite = rs.getLong(8);
+ long bytesRead = rs.getLong(9);
+ long bytesWrite = rs.getLong(10);
+ long aggBytesRead = rs.getLong(11);
+ long aggBytesWrite = rs.getLong(12);
+ long eventTimeMillis = rs.getLong(13);
+ if(vmId != 0){
+ returnMap.put(zoneId + "-" + accountId+ "-Vm-" + vmId+ "-Disk-" + volumeId, new UsageVmDiskVO(accountId, zoneId, vmId, volumeId, ioRead, ioWrite, aggIORead, aggIOWrite, bytesRead, bytesWrite, aggBytesRead, aggBytesWrite, eventTimeMillis));
+ } else {
+ returnMap.put(zoneId + "-" + accountId, new UsageVmDiskVO(accountId, zoneId, vmId, volumeId, ioRead, ioWrite, aggIORead, aggIOWrite, bytesRead, bytesWrite, aggBytesRead, aggBytesWrite, eventTimeMillis));
+ }
+ }
+ return returnMap;
+ } catch (Exception ex) {
+ s_logger.error("error getting recent usage disk stats", ex);
+ } finally {
+ txn.close();
+ }
+ return null;
+ }
+
+ @Override
+ public void deleteOldStats(long maxEventTime) {
+ Transaction txn = Transaction.currentTxn();
+ String sql = DELETE_OLD_STATS;
+ PreparedStatement pstmt = null;
+ try {
+ txn.start();
+ pstmt = txn.prepareAutoCloseStatement(sql);
+ pstmt.setLong(1, maxEventTime);
+ pstmt.executeUpdate();
+ txn.commit();
+ } catch (Exception ex) {
+ txn.rollback();
+ s_logger.error("error deleting old usage disk stats", ex);
+ }
+ }
+
+ @Override
+ public void saveUsageVmDisks(List usageVmDisks) {
+ Transaction txn = Transaction.currentTxn();
+ try {
+ txn.start();
+ String sql = INSERT_USAGE_VM_DISK;
+ PreparedStatement pstmt = null;
+ pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection
+ for (UsageVmDiskVO usageVmDisk : usageVmDisks) {
+ pstmt.setLong(1, usageVmDisk.getAccountId());
+ pstmt.setLong(2, usageVmDisk.getZoneId());
+ pstmt.setLong(3, usageVmDisk.getVmId());
+ pstmt.setLong(4, usageVmDisk.getVolumeId());
+ pstmt.setLong(5, usageVmDisk.getIORead());
+ pstmt.setLong(6, usageVmDisk.getIOWrite());
+ pstmt.setLong(7, usageVmDisk.getAggIORead());
+ pstmt.setLong(8, usageVmDisk.getAggIOWrite());
+ pstmt.setLong(9, usageVmDisk.getBytesRead());
+ pstmt.setLong(10, usageVmDisk.getBytesWrite());
+ pstmt.setLong(11, usageVmDisk.getAggBytesRead());
+ pstmt.setLong(12, usageVmDisk.getAggBytesWrite());
+ pstmt.setLong(13, usageVmDisk.getEventTimeMillis());
+ pstmt.addBatch();
+ }
+ pstmt.executeBatch();
+ txn.commit();
+ } catch (Exception ex) {
+ txn.rollback();
+ s_logger.error("error saving usage_vm_disk to cloud_usage db", ex);
+ throw new CloudRuntimeException(ex.getMessage());
+ }
+ }
+}
diff --git a/engine/schema/src/com/cloud/user/VmDiskStatisticsVO.java b/engine/schema/src/com/cloud/user/VmDiskStatisticsVO.java
new file mode 100644
index 00000000000..d1842c3042c
--- /dev/null
+++ b/engine/schema/src/com/cloud/user/VmDiskStatisticsVO.java
@@ -0,0 +1,216 @@
+// 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.user;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="vm_disk_statistics")
+public class VmDiskStatisticsVO {
+ @Id
+ @GeneratedValue(strategy=GenerationType.IDENTITY)
+ @Column(name="id")
+ private Long id;
+
+ @Column(name="data_center_id", updatable=false)
+ private long dataCenterId;
+
+ @Column(name="account_id", updatable=false)
+ private long accountId;
+
+ @Column(name="vm_id")
+ private Long vmId;
+
+ @Column(name="volume_id")
+ private Long volumeId;
+
+ @Column(name="net_io_read")
+ private long netIORead;
+
+ @Column(name="net_io_write")
+ private long netIOWrite;
+
+ @Column(name="current_io_read")
+ private long currentIORead;
+
+ @Column(name="current_io_write")
+ private long currentIOWrite;
+
+ @Column(name="agg_io_read")
+ private long aggIORead;
+
+ @Column(name="agg_io_write")
+ private long aggIOWrite;
+
+ @Column(name="net_bytes_read")
+ private long netBytesRead;
+
+ @Column(name="net_bytes_write")
+ private long netBytesWrite;
+
+ @Column(name="current_bytes_read")
+ private long currentBytesRead;
+
+ @Column(name="current_bytes_write")
+ private long currentBytesWrite;
+
+ @Column(name="agg_bytes_read")
+ private long aggBytesRead;
+
+ @Column(name="agg_bytes_write")
+ private long aggBytesWrite;
+
+ protected VmDiskStatisticsVO() {
+ }
+
+ public VmDiskStatisticsVO(long accountId, long dcId, Long vmId, Long volumeId) {
+ this.accountId = accountId;
+ this.dataCenterId = dcId;
+ this.vmId = vmId;
+ this.volumeId = volumeId;
+ this.netBytesRead = 0;
+ this.netBytesWrite = 0;
+ this.currentBytesRead = 0;
+ this.currentBytesWrite = 0;
+ this.netBytesRead = 0;
+ this.netBytesWrite = 0;
+ this.currentBytesRead = 0;
+ this.currentBytesWrite = 0;
+ }
+
+ public long getAccountId() {
+ return accountId;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public long getDataCenterId() {
+ return dataCenterId;
+ }
+
+ public Long getVmId() {
+ return vmId;
+ }
+
+ public Long getVolumeId() {
+ return volumeId;
+ }
+
+ public long getCurrentIORead() {
+ return currentIORead;
+ }
+
+ public void setCurrentIORead(long currentIORead) {
+ this.currentIORead = currentIORead;
+ }
+
+ public long getCurrentIOWrite() {
+ return currentIOWrite;
+ }
+
+ public void setCurrentIOWrite(long currentIOWrite) {
+ this.currentIOWrite = currentIOWrite;
+ }
+
+ public long getNetIORead() {
+ return netIORead;
+ }
+
+ public long getNetIOWrite() {
+ return netIOWrite;
+ }
+
+ public void setNetIORead(long netIORead) {
+ this.netIORead = netIORead;
+ }
+
+ public void setNetIOWrite(long netIOWrite) {
+ this.netIOWrite = netIOWrite;
+ }
+
+ public long getAggIORead() {
+ return aggIORead;
+ }
+
+ public void setAggIORead(long aggIORead) {
+ this.aggIORead = aggIORead;
+ }
+
+ public long getAggIOWrite() {
+ return aggIOWrite;
+ }
+
+ public void setAggIOWrite(long aggIOWrite) {
+ this.aggIOWrite = aggIOWrite;
+ }
+
+ public long getCurrentBytesRead() {
+ return currentBytesRead;
+ }
+
+ public void setCurrentBytesRead(long currentBytesRead) {
+ this.currentBytesRead = currentBytesRead;
+ }
+
+ public long getCurrentBytesWrite() {
+ return currentBytesWrite;
+ }
+
+ public void setCurrentBytesWrite(long currentBytesWrite) {
+ this.currentBytesWrite = currentBytesWrite;
+ }
+
+ public long getNetBytesRead() {
+ return netBytesRead;
+ }
+
+ public long getNetBytesWrite() {
+ return netBytesWrite;
+ }
+
+ public void setNetBytesRead(long netBytesRead) {
+ this.netBytesRead = netBytesRead;
+ }
+
+ public void setNetBytesWrite(long netBytesWrite) {
+ this.netBytesWrite = netBytesWrite;
+ }
+
+ public long getAggBytesRead() {
+ return aggBytesRead;
+ }
+
+ public void setAggBytesRead(long aggBytesRead) {
+ this.aggBytesRead = aggBytesRead;
+ }
+
+ public long getAggBytesWrite() {
+ return aggBytesWrite;
+ }
+
+ public void setAggBytesWrite(long aggBytesWrite) {
+ this.aggBytesWrite = aggBytesWrite;
+ }
+
+}
diff --git a/engine/schema/src/com/cloud/user/dao/VmDiskStatisticsDao.java b/engine/schema/src/com/cloud/user/dao/VmDiskStatisticsDao.java
new file mode 100644
index 00000000000..55206a61935
--- /dev/null
+++ b/engine/schema/src/com/cloud/user/dao/VmDiskStatisticsDao.java
@@ -0,0 +1,35 @@
+// 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.user.dao;
+
+import java.util.Date;
+import java.util.List;
+
+import com.cloud.user.VmDiskStatisticsVO;
+import com.cloud.utils.db.GenericDao;
+
+public interface VmDiskStatisticsDao extends GenericDao {
+ VmDiskStatisticsVO findBy(long accountId, long dcId, long vmId, long volumeId);
+
+ VmDiskStatisticsVO lock(long accountId, long dcId, long vmId, long volumeId);
+
+ List listBy(long accountId);
+
+ List listActiveAndRecentlyDeleted(Date minRemovedDate, int startIndex, int limit);
+
+ List listUpdatedStats();
+}
diff --git a/engine/schema/src/com/cloud/user/dao/VmDiskStatisticsDaoImpl.java b/engine/schema/src/com/cloud/user/dao/VmDiskStatisticsDaoImpl.java
new file mode 100644
index 00000000000..02f3406c497
--- /dev/null
+++ b/engine/schema/src/com/cloud/user/dao/VmDiskStatisticsDaoImpl.java
@@ -0,0 +1,134 @@
+// 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.user.dao;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+
+import javax.ejb.Local;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import com.cloud.user.VmDiskStatisticsVO;
+import com.cloud.utils.DateUtil;
+import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
+import com.cloud.utils.db.Transaction;
+
+@Component
+@Local(value={VmDiskStatisticsDao.class})
+public class VmDiskStatisticsDaoImpl extends GenericDaoBase implements VmDiskStatisticsDao {
+ private static final Logger s_logger = Logger.getLogger(VmDiskStatisticsDaoImpl.class);
+ private static final String ACTIVE_AND_RECENTLY_DELETED_SEARCH = "SELECT vns.id, vns.data_center_id, vns.account_id, vns.vm_id, vns.volume_id, vns.agg_io_read, vns.agg_io_write, vns.agg_bytes_read, vns.agg_bytes_write " +
+ "FROM vm_disk_statistics vns, account a " +
+ "WHERE vns.account_id = a.id AND (a.removed IS NULL OR a.removed >= ?) " +
+ "ORDER BY vns.id";
+ private static final String UPDATED_VM_NETWORK_STATS_SEARCH = "SELECT id, current_io_read, current_io_write, net_io_read, net_io_write, agg_io_read, agg_io_write, " +
+ "current_bytes_read, current_bytes_write, net_bytes_read, net_bytes_write, agg_bytes_read, agg_bytes_write " +
+ "from vm_disk_statistics " +
+ "where (agg_io_read < net_io_read + current_io_read) OR (agg_io_write < net_io_write + current_io_write) OR " +
+ "(agg_bytes_read < net_bytes_read + current_bytes_read) OR (agg_bytes_write < net_bytes_write + current_bytes_write)";
+ private final SearchBuilder AllFieldsSearch;
+ private final SearchBuilder AccountSearch;
+
+
+ public VmDiskStatisticsDaoImpl() {
+ AccountSearch = createSearchBuilder();
+ AccountSearch.and("account", AccountSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
+ AccountSearch.done();
+
+ AllFieldsSearch = createSearchBuilder();
+ AllFieldsSearch.and("account", AllFieldsSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
+ AllFieldsSearch.and("dc", AllFieldsSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
+ AllFieldsSearch.and("volume", AllFieldsSearch.entity().getVolumeId(), SearchCriteria.Op.EQ);
+ AllFieldsSearch.and("vm", AllFieldsSearch.entity().getVmId(), SearchCriteria.Op.EQ);
+ AllFieldsSearch.done();
+ }
+
+ @Override
+ public VmDiskStatisticsVO findBy(long accountId, long dcId, long vmId, long volumeId) {
+ SearchCriteria sc = AllFieldsSearch.create();
+ sc.setParameters("account", accountId);
+ sc.setParameters("dc", dcId);
+ sc.setParameters("volume", volumeId);
+ sc.setParameters("vm", vmId);
+ return findOneBy(sc);
+ }
+
+ @Override
+ public VmDiskStatisticsVO lock(long accountId, long dcId, long vmId, long volumeId) {
+ SearchCriteria sc = AllFieldsSearch.create();
+ sc.setParameters("account", accountId);
+ sc.setParameters("dc", dcId);
+ sc.setParameters("volume", volumeId);
+ sc.setParameters("vm", vmId);
+ return lockOneRandomRow(sc, true);
+ }
+
+ @Override
+ public List listBy(long accountId) {
+ SearchCriteria sc = AccountSearch.create();
+ sc.setParameters("account", accountId);
+ return search(sc, null);
+ }
+
+ @Override
+ public List listActiveAndRecentlyDeleted(Date minRemovedDate, int startIndex, int limit) {
+ List vmDiskStats = new ArrayList();
+ if (minRemovedDate == null) return vmDiskStats;
+
+ Transaction txn = Transaction.currentTxn();
+ try {
+ String sql = ACTIVE_AND_RECENTLY_DELETED_SEARCH + " LIMIT " + startIndex + "," + limit;
+ PreparedStatement pstmt = null;
+ pstmt = txn.prepareAutoCloseStatement(sql);
+ pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), minRemovedDate));
+ ResultSet rs = pstmt.executeQuery();
+ while (rs.next()) {
+ vmDiskStats.add(toEntityBean(rs, false));
+ }
+ } catch (Exception ex) {
+ s_logger.error("error saving vm disk stats to cloud_usage db", ex);
+ }
+ return vmDiskStats;
+ }
+
+ @Override
+ public List listUpdatedStats() {
+ List vmDiskStats = new ArrayList();
+
+ Transaction txn = Transaction.currentTxn();
+ try {
+ PreparedStatement pstmt = null;
+ pstmt = txn.prepareAutoCloseStatement(UPDATED_VM_NETWORK_STATS_SEARCH);
+ ResultSet rs = pstmt.executeQuery();
+ while (rs.next()) {
+ vmDiskStats.add(toEntityBean(rs, false));
+ }
+ } catch (Exception ex) {
+ s_logger.error("error lisitng updated vm disk stats", ex);
+ }
+ return vmDiskStats;
+ }
+
+}
diff --git a/engine/schema/src/com/cloud/vm/dao/UserVmDao.java b/engine/schema/src/com/cloud/vm/dao/UserVmDao.java
index e7cd61bddfe..b4f9991c99b 100755
--- a/engine/schema/src/com/cloud/vm/dao/UserVmDao.java
+++ b/engine/schema/src/com/cloud/vm/dao/UserVmDao.java
@@ -54,10 +54,9 @@ public interface UserVmDao extends GenericDao {
/**
* List user vm instances with virtualized networking (i.e. not direct attached networking) for the given account and datacenter
* @param accountId will search for vm instances belonging to this account
- * @param dcId will search for vm instances in this zone
* @return the list of vm instances owned by the account in the given data center that have virtualized networking (not direct attached networking)
*/
- List listVirtualNetworkInstancesByAcctAndZone(long accountId, long dcId, long networkId);
+ List listVirtualNetworkInstancesByAcctAndNetwork(long accountId, long networkId);
List listByNetworkIdAndStates(long networkId, State... states);
diff --git a/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java b/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java
index 5e8be1054a9..1c11563b270 100755
--- a/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java
+++ b/engine/schema/src/com/cloud/vm/dao/UserVmDaoImpl.java
@@ -283,11 +283,10 @@ public class UserVmDaoImpl extends GenericDaoBase implements Use
}
@Override
- public List listVirtualNetworkInstancesByAcctAndZone(long accountId, long dcId, long networkId) {
+ public List listVirtualNetworkInstancesByAcctAndNetwork(long accountId, long networkId) {
SearchCriteria sc = AccountDataCenterVirtualSearch.create();
sc.setParameters("account", accountId);
- sc.setParameters("dc", dcId);
sc.setJoinParameters("nicSearch", "networkId", networkId);
return listBy(sc);
diff --git a/engine/schema/src/com/cloud/vm/dao/UserVmData.java b/engine/schema/src/com/cloud/vm/dao/UserVmData.java
index 674fc005a85..6622a7dc8e6 100644
--- a/engine/schema/src/com/cloud/vm/dao/UserVmData.java
+++ b/engine/schema/src/com/cloud/vm/dao/UserVmData.java
@@ -57,6 +57,10 @@ public class UserVmData {
private String cpuUsed;
private Long networkKbsRead;
private Long networkKbsWrite;
+ private Long diskKbsRead;
+ private Long diskKbsWrite;
+ private Long diskIORead;
+ private Long diskIOWrite;
private Long guestOsId;
private Long rootDeviceId;
private String rootDeviceType;
@@ -364,6 +368,38 @@ public class UserVmData {
this.networkKbsWrite = networkKbsWrite;
}
+ public Long getDiskKbsRead() {
+ return diskKbsRead;
+ }
+
+ public void setDiskKbsRead(Long diskKbsRead) {
+ this.diskKbsRead = diskKbsRead;
+ }
+
+ public Long getDiskKbsWrite() {
+ return diskKbsWrite;
+ }
+
+ public void setDiskKbsWrite(Long diskKbsWrite) {
+ this.diskKbsWrite = diskKbsWrite;
+ }
+
+ public Long getDiskIORead() {
+ return diskIORead;
+ }
+
+ public void setDiskIORead(Long diskIORead) {
+ this.diskIORead = diskIORead;
+ }
+
+ public Long getDiskIOWrite() {
+ return diskIOWrite;
+ }
+
+ public void setDiskIOWrite(Long diskIOWrite) {
+ this.diskIOWrite = diskIOWrite;
+ }
+
public Long getGuestOsId() {
return guestOsId;
}
diff --git a/engine/schema/src/org/apache/cloudstack/lb/dao/ApplicationLoadBalancerRuleDao.java b/engine/schema/src/org/apache/cloudstack/lb/dao/ApplicationLoadBalancerRuleDao.java
index c385e62f6ab..47f1d361216 100644
--- a/engine/schema/src/org/apache/cloudstack/lb/dao/ApplicationLoadBalancerRuleDao.java
+++ b/engine/schema/src/org/apache/cloudstack/lb/dao/ApplicationLoadBalancerRuleDao.java
@@ -31,5 +31,6 @@ public interface ApplicationLoadBalancerRuleDao extends GenericDao listBySourceIpAndNotRevoked(Ip sourceIp, long sourceNetworkId);
List listLbIpsBySourceIpNetworkIdAndScheme(long sourceIpNetworkId, Scheme scheme);
+ long countBySourceIpAndNotRevoked(Ip sourceIp, long sourceIpNetworkId);
}
diff --git a/engine/schema/src/org/apache/cloudstack/lb/dao/ApplicationLoadBalancerRuleDaoImpl.java b/engine/schema/src/org/apache/cloudstack/lb/dao/ApplicationLoadBalancerRuleDaoImpl.java
index 880c67e732c..6036b5a2d60 100644
--- a/engine/schema/src/org/apache/cloudstack/lb/dao/ApplicationLoadBalancerRuleDaoImpl.java
+++ b/engine/schema/src/org/apache/cloudstack/lb/dao/ApplicationLoadBalancerRuleDaoImpl.java
@@ -25,6 +25,7 @@ import org.apache.cloudstack.lb.ApplicationLoadBalancerRuleVO;
import org.springframework.stereotype.Component;
import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.FirewallRule.State;
import com.cloud.network.rules.LoadBalancerContainer.Scheme;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
@@ -41,8 +42,8 @@ public class ApplicationLoadBalancerRuleDaoImpl extends GenericDaoBase listIps;
final GenericSearchBuilder CountBy;
protected final SearchBuilder NotRevokedSearch;
-
-
+ final GenericSearchBuilder CountNotRevoked;
+
protected ApplicationLoadBalancerRuleDaoImpl() {
AllFieldsSearch = createSearchBuilder();
@@ -69,6 +70,13 @@ public class ApplicationLoadBalancerRuleDaoImpl extends GenericDaoBase sc = CountNotRevoked.create();
+ sc.setParameters("sourceIp", sourceIp);
+ sc.setParameters("sourceIpNetworkId", sourceIpNetworkId);
+ sc.setParameters("state", State.Revoke);
+ List results = customSearch(sc, null);
+ return results.get(0);
+ }
+
}
diff --git a/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerDaoImpl.java b/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerDaoImpl.java
index 0020f5d4256..ba9dea067ca 100644
--- a/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerDaoImpl.java
+++ b/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerDaoImpl.java
@@ -31,12 +31,17 @@ public class GlobalLoadBalancerDaoImpl extends GenericDaoBase listByDomainSearch;
private final SearchBuilder listByRegionIDSearch;
+ private final SearchBuilder AccountIdSearch;
public GlobalLoadBalancerDaoImpl() {
listByDomainSearch = createSearchBuilder();
listByDomainSearch.and("gslbDomain", listByDomainSearch.entity().getGslbDomain(), SearchCriteria.Op.EQ);
listByDomainSearch.done();
+ AccountIdSearch = createSearchBuilder();
+ AccountIdSearch.and("account", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
+ AccountIdSearch.done();
+
listByRegionIDSearch = createSearchBuilder();
listByRegionIDSearch.and("region", listByRegionIDSearch.entity().getRegion(), SearchCriteria.Op.EQ);
listByRegionIDSearch.done();
@@ -49,6 +54,13 @@ public class GlobalLoadBalancerDaoImpl extends GenericDaoBase listByAccount(long accountId) {
+ SearchCriteria sc = AccountIdSearch.create();
+ sc.setParameters("account", accountId);
+ return listBy(sc, null);
+ }
+
@Override
public GlobalLoadBalancerRuleVO findByDomainName(String domainName) {
SearchCriteria sc = listByDomainSearch.create();
diff --git a/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleDao.java b/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleDao.java
index 1b44caa444a..cfc86256c42 100644
--- a/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleDao.java
+++ b/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleDao.java
@@ -24,5 +24,8 @@ import java.util.List;
public interface GlobalLoadBalancerRuleDao extends GenericDao {
List listByRegionId(int regionId);
+
+ List listByAccount(long accountId);
+
GlobalLoadBalancerRuleVO findByDomainName(String domainName);
}
diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/DefaultImageDataStoreLifeCycle.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/DefaultImageDataStoreLifeCycle.java
index ba29c1a14b0..fef97671961 100644
--- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/DefaultImageDataStoreLifeCycle.java
+++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/lifecycle/DefaultImageDataStoreLifeCycle.java
@@ -30,6 +30,7 @@ import org.apache.cloudstack.storage.image.db.ImageDataStoreDao;
import org.apache.cloudstack.storage.image.db.ImageDataStoreVO;
import com.cloud.agent.api.StoragePoolInfo;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
public class DefaultImageDataStoreLifeCycle implements ImageDataStoreLifeCycle {
@Inject
@@ -65,7 +66,7 @@ public class DefaultImageDataStoreLifeCycle implements ImageDataStoreLifeCycle {
@Override
- public boolean attachZone(DataStore dataStore, ZoneScope scope) {
+ public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisor) {
// TODO Auto-generated method stub
return false;
}
diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java
index ad1c22c6d3c..9da3475a1ce 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java
@@ -59,13 +59,15 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator {
List suitablePools = new ArrayList();
HypervisorType hypervisor = dskCh.getHypervisorType();
if (hypervisor != null) {
- if (hypervisor != HypervisorType.KVM) {
- s_logger.debug("Only kvm supports zone wide storage");
+ if (hypervisor != HypervisorType.KVM && hypervisor != HypervisorType.VMware) {
+ s_logger.debug("Only kvm, VMware hypervisors are enabled to support zone wide storage");
return suitablePools;
}
}
List storagePools = _storagePoolDao.findZoneWideStoragePoolsByTags(plan.getDataCenterId(), dskCh.getTags());
+ List storagePoolsByHypervisor = _storagePoolDao.findZoneWideStoragePoolsByHypervisor(plan.getDataCenterId(), dskCh.getHypervisorType());
+ storagePools.retainAll(storagePoolsByHypervisor);
// add remaining pools in zone, that did not match tags, to avoid set
List allPools = _storagePoolDao.findZoneWideStoragePoolsByTags(plan.getDataCenterId(), null);
diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java b/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java
index 5f8daf42bb3..349f6ba9079 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/volume/datastore/PrimaryDataStoreHelper.java
@@ -29,25 +29,20 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
import org.apache.cloudstack.engine.subsystem.api.storage.HostScope;
import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreParameters;
import org.apache.cloudstack.engine.subsystem.api.storage.ScopeType;
-import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
-import com.cloud.agent.api.Answer;
-import com.cloud.agent.api.DeleteStoragePoolCommand;
import com.cloud.agent.api.StoragePoolInfo;
-import com.cloud.alert.AlertManager;
import com.cloud.capacity.Capacity;
import com.cloud.capacity.CapacityVO;
import com.cloud.capacity.dao.CapacityDao;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.StorageManager;
-import com.cloud.storage.StoragePool;
import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.dao.StoragePoolHostDao;
-import com.cloud.utils.db.DB;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
@@ -70,7 +65,7 @@ public class PrimaryDataStoreHelper {
if (dataStoreVO != null) {
throw new CloudRuntimeException("duplicate uuid: " + params.getUuid());
}
-
+
dataStoreVO = new StoragePoolVO();
dataStoreVO.setStorageProviderName(params.getProviderName());
dataStoreVO.setHostAddress(params.getHost());
@@ -84,7 +79,7 @@ public class PrimaryDataStoreHelper {
dataStoreVO.setClusterId(params.getClusterId());
dataStoreVO.setStatus(StoragePoolStatus.Initialized);
dataStoreVO.setUserInfo(params.getUserInfo());
-
+
Map details = params.getDetails();
String tags = params.getTags();
if (tags != null) {
@@ -98,19 +93,19 @@ public class PrimaryDataStoreHelper {
details.put(tag, "true");
}
}
-
+
dataStoreVO = dataStoreDao.persist(dataStoreVO, details);
return dataStoreMgr.getDataStore(dataStoreVO.getId(), DataStoreRole.Primary);
}
-
+
public DataStore attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo) {
StoragePoolHostVO poolHost = storagePoolHostDao.findByPoolHost(store.getId(), scope.getScopeId());
if (poolHost == null) {
poolHost = new StoragePoolHostVO(store.getId(), scope.getScopeId(), existingInfo.getLocalPath());
storagePoolHostDao.persist(poolHost);
}
-
+
StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
pool.setScope(scope.getScopeType());
pool.setAvailableBytes(existingInfo.getAvailableBytes());
@@ -120,18 +115,18 @@ public class PrimaryDataStoreHelper {
this.storageMgr.createCapacityEntry(pool, Capacity.CAPACITY_TYPE_LOCAL_STORAGE, pool.getCapacityBytes() - pool.getAvailableBytes());
return dataStoreMgr.getDataStore(pool.getId(), DataStoreRole.Primary);
}
-
+
public DataStore attachCluster(DataStore store) {
StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
-
+
storageMgr.createCapacityEntry(pool.getId());
-
+
pool.setScope(ScopeType.CLUSTER);
pool.setStatus(StoragePoolStatus.Up);
this.dataStoreDao.update(pool.getId(), pool);
return dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary);
}
-
+
public DataStore attachZone(DataStore store) {
StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
pool.setScope(ScopeType.ZONE);
@@ -139,21 +134,30 @@ public class PrimaryDataStoreHelper {
this.dataStoreDao.update(pool.getId(), pool);
return dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary);
}
-
+
+ public DataStore attachZone(DataStore store, HypervisorType hypervisor) {
+ StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
+ pool.setScope(ScopeType.ZONE);
+ pool.setHypervisor(hypervisor);
+ pool.setStatus(StoragePoolStatus.Up);
+ this.dataStoreDao.update(pool.getId(), pool);
+ return dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Primary);
+ }
+
public boolean maintain(DataStore store) {
StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
pool.setStatus(StoragePoolStatus.Maintenance);
this.dataStoreDao.update(pool.getId(), pool);
return true;
}
-
+
public boolean cancelMaintain(DataStore store) {
StoragePoolVO pool = this.dataStoreDao.findById(store.getId());
pool.setStatus(StoragePoolStatus.Up);
dataStoreDao.update(store.getId(), pool);
return true;
}
-
+
protected boolean deletePoolStats(Long poolId) {
CapacityVO capacity1 = _capacityDao.findByHostIdType(poolId,
@@ -167,10 +171,10 @@ public class PrimaryDataStoreHelper {
if (capacity2 != null) {
_capacityDao.remove(capacity2.getId());
}
-
+
return true;
}
-
+
public boolean deletePrimaryDataStore(DataStore store) {
List hostPoolRecords = this.storagePoolHostDao
.listByPoolId(store.getId());
diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java
index fea02e8d1ed..cffa1cee4dc 100644
--- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java
+++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java
@@ -114,7 +114,7 @@ public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLif
}
@Override
- public boolean attachZone(DataStore dataStore, ZoneScope scope) {
+ public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType) {
// TODO Auto-generated method stub
return false;
}
diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
index b9c39c793b7..56a6651462b 100644
--- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
+++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
@@ -428,6 +428,7 @@ public class VolumeServiceImpl implements VolumeService {
try {
DataObject volumeOnStore = store.create(volume);
+ volume = this.volFactory.getVolume(volume.getId(), store);
volume.processEvent(Event.CreateOnlyRequested);
CreateVolumeFromBaseImageContext context = new CreateVolumeFromBaseImageContext(null,
(VolumeObject)volume, store, volumeOnStore, future);
diff --git a/packaging/centos63/cloud-management.rc b/packaging/centos63/cloud-management.rc
index 6fd435b555d..35f31b28538 100755
--- a/packaging/centos63/cloud-management.rc
+++ b/packaging/centos63/cloud-management.rc
@@ -16,7 +16,7 @@
# specific language governing permissions and limitations
# under the License.
#
-# cloud-management This shell script takes care of starting and stopping Tomcat
+# cloudstack-management This shell script takes care of starting and stopping Tomcat
#
# chkconfig: - 80 20
#
@@ -56,13 +56,13 @@ stop() {
let count="${count}+1"
done
if [ "$(ps --pid $pid | grep -c $pid)" -eq "0" ]; then
- log_success_msg "Stopping cloud-management:"
+ log_success_msg "Stopping ${NAME}:"
else
- log_failure_msg "Stopping cloud-management:"
+ log_failure_msg "Stopping ${NAME}:"
fi
else
- echo "Cannot find PID file of Cloud-management"
- log_failure_msg "Stopping cloud-management:"
+ echo "Cannot find PID file of ${NAME}"
+ log_failure_msg "Stopping ${NAME}:"
fi
}
diff --git a/packaging/centos63/cloud.spec b/packaging/centos63/cloud.spec
index 1cde336e7b1..1f112ddd686 100644
--- a/packaging/centos63/cloud.spec
+++ b/packaging/centos63/cloud.spec
@@ -165,11 +165,11 @@ echo VERSION=%{_maventag} >> build/replace.properties
echo PACKAGE=%{name} >> build/replace.properties
if [ "%{_ossnoss}" == "NONOSS" -o "%{_ossnoss}" == "nonoss" ] ; then
- echo "Executing mvn packaging for NONOSS ..."
- mvn -Pawsapi,systemvm -Dnonoss package
+ echo "Executing mvn packaging for NONOSS ..."
+ mvn -Pawsapi,systemvm -Dnonoss package clean install
else
- echo "Executing mvn packaging for OSS ..."
- mvn -Pawsapi package -Dsystemvm
+ echo "Executing mvn packaging for OSS ..."
+ mvn -Pawsapi package -Dsystemvm clean install
fi
%install
@@ -216,6 +216,8 @@ ln -sf /var/log/%{name}/management ${RPM_BUILD_ROOT}%{_datadir}/%{name}-manageme
ln -sf /var/cache/%{name}/management/temp ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/temp
ln -sf /var/cache/%{name}/management/work ${RPM_BUILD_ROOT}%{_datadir}/%{name}-management/work
+/bin/touch ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/management/catalina.out
+
install -D client/target/utilities/bin/cloud-migrate-databases ${RPM_BUILD_ROOT}%{_bindir}/%{name}-migrate-databases
install -D client/target/utilities/bin/cloud-set-guest-password ${RPM_BUILD_ROOT}%{_bindir}/%{name}-set-guest-password
install -D client/target/utilities/bin/cloud-set-guest-sshkey ${RPM_BUILD_ROOT}%{_bindir}/%{name}-set-guest-sshkey
@@ -519,6 +521,7 @@ fi
%dir %attr(0770,root,root) %{_localstatedir}/log/%{name}-management
%{_defaultdocdir}/%{name}-management-%{version}/LICENSE
%{_defaultdocdir}/%{name}-management-%{version}/NOTICE
+%attr(0644,cloud,cloud) %{_localstatedir}/log/%{name}/management/catalina.out
%files agent
%attr(0755,root,root) %{_bindir}/%{name}-setup-agent
diff --git a/patches/systemvm/debian/config/etc/init.d/cloud-early-config b/patches/systemvm/debian/config/etc/init.d/cloud-early-config
index ca3b970210b..0dcd5710664 100755
--- a/patches/systemvm/debian/config/etc/init.d/cloud-early-config
+++ b/patches/systemvm/debian/config/etc/init.d/cloud-early-config
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/bash
### BEGIN INIT INFO
# Provides: cloud-early-config
# Required-Start: mountkernfs $local_fs
@@ -87,14 +87,13 @@ EOF
hypervisor() {
[ -d /proc/xen ] && mount -t xenfs none /proc/xen
+ [ -d /proc/xen ] && echo "xen-domU" && return 0
local try=$([ -x /usr/sbin/virt-what ] && virt-what | tail -1)
[ "$try" != "" ] && echo $try && return 0
vmware-checkvm &> /dev/null && echo "vmware" && return 0
- [ -d /proc/xen ] && echo "xen-domU" && return 0
-
grep -q QEMU /proc/cpuinfo && echo "kvm" && return 0
grep -q QEMU /var/log/messages && echo "kvm" && return 0
@@ -343,6 +342,22 @@ enable_svc() {
[ -f $cfg ] && sed -i "s/ENABLED=.*$/ENABLED=$enabled/" $cfg && return
}
+
+enable_irqbalance() {
+ local enabled=$1
+ local proc=0
+
+ proc=$(cat /proc/cpuinfo | grep "processor" | wc -l)
+ if [ $proc -le 1 ] && [ $enabled -eq 1 ]
+ then
+ enabled=0
+ fi
+
+ log_it "Processors = $proc Enable service ${svc} = $enabled"
+ local cfg=/etc/default/irqbalance
+ [ -f $cfg ] && sed -i "s/ENABLED=.*$/ENABLED=$enabled/" $cfg && return
+}
+
disable_hvc() {
[ ! -d /proc/xen ] && sed -i 's/^vc/#vc/' /etc/inittab && telinit q
[ -d /proc/xen ] && sed -i 's/^#vc/vc/' /etc/inittab && telinit q
@@ -699,6 +714,7 @@ setup_router() {
enable_svc dnsmasq 1
enable_svc haproxy 1
+ enable_irqbalance 1
enable_svc cloud-passwd-srvr 1
enable_svc cloud 0
disable_rpfilter_domR
@@ -778,6 +794,7 @@ EOF
enable_svc dnsmasq 1
enable_svc haproxy 1
+ enable_irqbalance 1
enable_svc cloud 0
disable_rpfilter
enable_fwding 1
@@ -804,6 +821,7 @@ setup_dhcpsrvr() {
enable_svc dnsmasq 1
enable_svc haproxy 0
+ enable_irqbalance 0
enable_svc cloud-passwd-srvr 1
enable_svc cloud 0
enable_fwding 0
@@ -856,6 +874,7 @@ setup_secstorage() {
disable_rpfilter
enable_fwding 0
enable_svc haproxy 0
+ enable_irqbalance 0
enable_svc dnsmasq 0
enable_svc cloud-passwd-srvr 0
enable_svc cloud 1
@@ -880,6 +899,7 @@ setup_console_proxy() {
disable_rpfilter
enable_fwding 0
enable_svc haproxy 0
+ enable_irqbalance 0
enable_svc dnsmasq 0
enable_svc cloud-passwd-srvr 0
enable_svc cloud 1
@@ -906,6 +926,7 @@ setup_elbvm() {
enable_fwding 0
enable_svc haproxy 0
+ enable_irqbalance 0
enable_svc dnsmasq 0
enable_svc cloud-passwd-srvr 0
enable_svc cloud 0
@@ -928,6 +949,7 @@ setup_ilbvm() {
enable_fwding 0
enable_svc haproxy 1
+ enable_irqbalance 1
enable_svc dnsmasq 0
enable_svc cloud-passwd-srvr 0
enable_svc cloud 0
diff --git a/patches/systemvm/debian/config/etc/iptables/iptables-router b/patches/systemvm/debian/config/etc/iptables/iptables-router
index 3f5bc5f736b..b214e4025fe 100644
--- a/patches/systemvm/debian/config/etc/iptables/iptables-router
+++ b/patches/systemvm/debian/config/etc/iptables/iptables-router
@@ -37,6 +37,7 @@ COMMIT
-A INPUT -i eth0 -p tcp -m tcp --dport 53 -j ACCEPT
-A INPUT -i eth1 -p tcp -m state --state NEW --dport 3922 -j ACCEPT
-A INPUT -i eth0 -p tcp -m state --state NEW --dport 80 -j ACCEPT
+-A INPUT -i eth0 -p tcp -m state --state NEW --dport 8080 -j ACCEPT
-A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth2 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i eth0 -o eth0 -m state --state NEW -j ACCEPT
diff --git a/patches/systemvm/debian/config/opt/cloud/bin/vpc_func.sh b/patches/systemvm/debian/config/opt/cloud/bin/vpc_func.sh
index 17cb078b34f..2f8835120e4 100755
--- a/patches/systemvm/debian/config/opt/cloud/bin/vpc_func.sh
+++ b/patches/systemvm/debian/config/opt/cloud/bin/vpc_func.sh
@@ -22,7 +22,7 @@ getEthByIp (){
local ip=$1
for dev in `ls -1 /sys/class/net | grep eth`
do
- sudo ip addr show dev $dev | grep $ip > /dev/null
+ sudo ip addr show dev $dev | grep $ip\/ > /dev/null
if [ $? -eq 0 ]
then
echo $dev
diff --git a/patches/systemvm/debian/config/root/deleteIpAlias.sh b/patches/systemvm/debian/config/root/deleteIpAlias.sh
index 865ff3b4769..cf6d4de5269 100755
--- a/patches/systemvm/debian/config/root/deleteIpAlias.sh
+++ b/patches/systemvm/debian/config/root/deleteIpAlias.sh
@@ -24,7 +24,7 @@ set -x
var="$1"
cert="/root/.ssh/id_rsa.cloud"
-while [ -n "$var" ]
+while [[ !( "$var" == "-" ) ]]
do
var1=$(echo $var | cut -f1 -d "-")
alias_count=$( echo $var1 | cut -f1 -d ":" )
diff --git a/plugins/affinity-group-processors/explicit-dedication/pom.xml b/plugins/affinity-group-processors/explicit-dedication/pom.xml
new file mode 100644
index 00000000000..bb3c595841a
--- /dev/null
+++ b/plugins/affinity-group-processors/explicit-dedication/pom.xml
@@ -0,0 +1,33 @@
+
+
+ 4.0.0
+ cloud-plugin-explicit-dedication
+ Apache CloudStack Plugin - Explicit Dedication Processor
+
+ org.apache.cloudstack
+ cloudstack-plugins
+ 4.2.0-SNAPSHOT
+ ../../pom.xml
+
+
+ install
+ src
+
+
diff --git a/plugins/affinity-group-processors/explicit-dedication/src/org/apache/cloudstack/affinity/ExplicitDedicationProcessor.java b/plugins/affinity-group-processors/explicit-dedication/src/org/apache/cloudstack/affinity/ExplicitDedicationProcessor.java
new file mode 100644
index 00000000000..21693592e69
--- /dev/null
+++ b/plugins/affinity-group-processors/explicit-dedication/src/org/apache/cloudstack/affinity/ExplicitDedicationProcessor.java
@@ -0,0 +1,384 @@
+// 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.affinity;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cloudstack.affinity.dao.AffinityGroupDao;
+import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao;
+
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.DataCenter;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.dc.HostPodVO;
+import com.cloud.dc.dao.ClusterDao;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.dc.dao.DedicatedResourceDao;
+import com.cloud.dc.dao.HostPodDao;
+import com.cloud.deploy.DeploymentPlan;
+import com.cloud.deploy.DeploymentPlanner.ExcludeList;
+import com.cloud.domain.DomainVO;
+import com.cloud.domain.dao.DomainDao;
+import com.cloud.exception.AffinityConflictException;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineProfile;
+import com.cloud.vm.dao.UserVmDao;
+import com.cloud.vm.dao.VMInstanceDao;
+
+@Local(value = AffinityGroupProcessor.class)
+public class ExplicitDedicationProcessor extends AffinityProcessorBase implements AffinityGroupProcessor {
+
+ private static final Logger s_logger = Logger.getLogger(ExplicitDedicationProcessor.class);
+ @Inject
+ protected UserVmDao _vmDao;
+ @Inject
+ protected VMInstanceDao _vmInstanceDao;
+ @Inject
+ protected DataCenterDao _dcDao;
+ @Inject
+ protected DedicatedResourceDao _dedicatedDao;
+ @Inject
+ protected HostPodDao _podDao;
+ @Inject
+ protected ClusterDao _clusterDao;
+ @Inject
+ protected HostDao _hostDao;
+ @Inject
+ protected DomainDao _domainDao;
+ @Inject
+ protected AffinityGroupDao _affinityGroupDao;
+ @Inject
+ protected AffinityGroupVMMapDao _affinityGroupVMMapDao;
+
+ /**
+ * This method will process the affinity group of type 'Explicit Dedication' for a deployment of a VM that demands dedicated resources.
+ * For ExplicitDedicationProcessor we need to add dedicated resources into the IncludeList based on the level we have dedicated resources available.
+ * For eg. if admin dedicates a pod to a domain, then all the user in that domain can use the resources of that pod.
+ * We need to take care of the situation when dedicated resources further have resources dedicated to sub-domain/account.
+ * This IncludeList is then used to update the avoid list for a given data center.
+ */
+ @Override
+ public void process(VirtualMachineProfile vmProfile, DeploymentPlan plan,
+ ExcludeList avoid) throws AffinityConflictException {
+ VirtualMachine vm = vmProfile.getVirtualMachine();
+ List vmGroupMappings = _affinityGroupVMMapDao.findByVmIdType(vm.getId(), getType());
+ DataCenter dc = _dcDao.findById(vm.getDataCenterId());
+ long domainId = vm.getDomainId();
+ long accountId = vm.getAccountId();
+
+ for (AffinityGroupVMMapVO vmGroupMapping : vmGroupMappings) {
+ if (vmGroupMapping != null) {
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("Processing affinity group of type 'ExplicitDedication' for VM Id: " + vm.getId());
+ }
+
+ List dr = _dedicatedDao.listByAccountId(accountId);
+ List drOfDomain = searchInDomainResources(domainId);
+ List drOfParentDomain = searchInParentDomainResources(domainId);
+ List resourceList = new ArrayList();
+ resourceList.addAll(dr);
+ resourceList.addAll(drOfDomain);
+ resourceList.addAll(drOfParentDomain);
+ boolean canUse = false;
+
+ if (plan.getHostId() != null) {
+ HostVO host = _hostDao.findById(plan.getHostId());
+ ClusterVO clusterofHost = _clusterDao.findById(host.getClusterId());
+ HostPodVO podOfHost = _podDao.findById(host.getPodId());
+ DataCenterVO zoneOfHost = _dcDao.findById(host.getDataCenterId());
+ if (resourceList != null && resourceList.size() != 0) {
+ for(DedicatedResourceVO resource : resourceList){
+ if ((resource.getHostId() != null && resource.getHostId() == plan.getHostId()) ||
+ (resource.getClusterId() != null && resource.getClusterId() == clusterofHost.getId()) ||
+ (resource.getPodId() != null && resource.getPodId() == podOfHost.getId()) ||
+ (resource.getDataCenterId() != null && resource.getDataCenterId() == zoneOfHost.getId())){
+ canUse = true;
+ }
+ }
+ }
+ if (!canUse) {
+ throw new CloudRuntimeException("Cannot use this host " + host.getName() + " for explicit dedication");
+ }
+ } else if (plan.getClusterId() != null) {
+ ClusterVO cluster = _clusterDao.findById(plan.getClusterId());
+ HostPodVO podOfCluster = _podDao.findById(cluster.getPodId());
+ DataCenterVO zoneOfCluster = _dcDao.findById(cluster.getDataCenterId());
+ List hostToUse = new ArrayList();
+ // check whether this cluster or its pod is dedicated
+ if (resourceList != null && resourceList.size() != 0) {
+ for(DedicatedResourceVO resource : resourceList){
+ if ((resource.getClusterId() != null && resource.getClusterId() == cluster.getId()) ||
+ (resource.getPodId() != null && resource.getPodId() == podOfCluster.getId()) ||
+ (resource.getDataCenterId() != null && resource.getDataCenterId() == zoneOfCluster.getId())){
+ canUse = true;
+ }
+
+ // check for all dedicated host; if it belongs to this cluster
+ if (!canUse){
+ if (resource.getHostId() != null) {
+ HostVO dHost = _hostDao.findById(resource.getHostId());
+ if (dHost.getClusterId() == cluster.getId()) {
+ hostToUse.add(dHost);
+ }
+ }
+ }
+
+ }
+ }
+
+ if (hostToUse.isEmpty() && !canUse) {
+ throw new CloudRuntimeException("Cannot use this cluster " + cluster.getName() + " for explicit dedication");
+ }
+
+ if (hostToUse != null && hostToUse.size() != 0) {
+ // add other non-dedicated hosts to avoid list
+ List hostList = _hostDao.findByClusterId(cluster.getId());
+ for (HostVO host : hostList){
+ if (!hostToUse.contains(host)) {
+ avoid.addHost(host.getId());
+ }
+ }
+ }
+
+ } else if (plan.getPodId() != null) {
+ HostPodVO pod = _podDao.findById(plan.getPodId());
+ DataCenterVO zoneOfPod = _dcDao.findById(pod.getDataCenterId());
+ List clustersToUse = new ArrayList();
+ List hostsToUse = new ArrayList();
+ // check whether this cluster or its pod is dedicated
+ if (resourceList != null && resourceList.size() != 0) {
+ for(DedicatedResourceVO resource : resourceList){
+ if ((resource.getPodId() != null && resource.getPodId() == pod.getId()) ||
+ (resource.getDataCenterId() != null && resource.getDataCenterId() == zoneOfPod.getId())){
+ canUse = true;
+ }
+
+ // check for all dedicated cluster/host; if it belongs to this pod
+ if (!canUse){
+ if (resource.getClusterId() != null) {
+ ClusterVO dCluster = _clusterDao.findById(resource.getClusterId());
+ if (dCluster.getPodId() == pod.getId()) {
+ clustersToUse.add(dCluster);
+ }
+ }
+ if (resource.getHostId() != null) {
+ HostVO dHost = _hostDao.findById(resource.getHostId());
+ if (dHost.getPodId() == pod.getId()) {
+ hostsToUse.add(dHost);
+ }
+ }
+ }
+
+ }
+ }
+
+ if (hostsToUse.isEmpty() && clustersToUse.isEmpty() && !canUse) {
+ throw new CloudRuntimeException("Cannot use this pod " + pod.getName() + " for explicit dedication");
+ }
+
+ if (clustersToUse != null && clustersToUse.size() != 0) {
+ // add other non-dedicated clusters to avoid list
+ List clusterList = _clusterDao.listByPodId(pod.getId());
+ for (ClusterVO cluster : clusterList){
+ if (!clustersToUse.contains(cluster)) {
+ avoid.addCluster(cluster.getId());
+ }
+ }
+ }
+
+ if (hostsToUse != null && hostsToUse.size() != 0) {
+ // add other non-dedicated hosts to avoid list
+ List hostList = _hostDao.findByPodId(pod.getId());
+ for (HostVO host : hostList){
+ if (!hostsToUse.contains(host)) {
+ avoid.addHost(host.getId());
+ }
+ }
+ }
+
+ } else {
+ //check all resources under this zone
+ if (dr != null && dr.size() != 0) {
+ avoid = updateAvoidList(dr, avoid, dc);
+ } else if(drOfDomain != null && drOfDomain.size() != 0){
+ avoid = updateAvoidList(drOfDomain, avoid, dc);
+ } else if(drOfParentDomain != null && drOfParentDomain.size() != 0){
+ avoid = updateAvoidList(drOfParentDomain, avoid, dc);
+ } else {
+ avoid.addDataCenter(dc.getId());
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("No dedicated resources available for this domain or account");
+ }
+ }
+
+ if (s_logger.isDebugEnabled()) {
+ s_logger.debug("ExplicitDedicationProcessor returns Avoid List as: Deploy avoids pods: " + avoid.getPodsToAvoid() + ", clusters: "
+ + avoid.getClustersToAvoid() + ", hosts: " + avoid.getHostsToAvoid());
+ }
+ }
+ }
+ }
+ }
+
+ private ExcludeList updateAvoidList(List dedicatedResources, ExcludeList avoidList, DataCenter dc) {
+ ExcludeList includeList = new ExcludeList();
+ for (DedicatedResourceVO dr : dedicatedResources) {
+ if (dr.getHostId() != null){
+ includeList.addHost(dr.getHostId());
+ HostVO dedicatedHost = _hostDao.findById(dr.getHostId());
+ includeList.addCluster(dedicatedHost.getClusterId());
+ includeList.addPod(dedicatedHost.getPodId());
+ }
+
+ if (dr.getClusterId() != null) {
+ includeList.addCluster(dr.getClusterId());
+ //add all hosts inside this in includeList
+ List hostList = _hostDao.findByClusterId(dr.getClusterId());
+ for (HostVO host : hostList) {
+ DedicatedResourceVO dHost = _dedicatedDao.findByHostId(host.getId());
+ if (dHost != null) {
+ avoidList.addHost(host.getId());
+ } else {
+ includeList.addHost(host.getId());
+ }
+ }
+ ClusterVO dedicatedCluster = _clusterDao.findById(dr.getClusterId());
+ includeList.addPod(dedicatedCluster.getPodId());
+ }
+
+ if (dr.getPodId() != null) {
+ includeList.addPod(dr.getPodId());
+ //add all cluster under this pod in includeList
+ List clusterList = _clusterDao.listByPodId(dr.getPodId());
+ for (ClusterVO cluster : clusterList) {
+ if (_dedicatedDao.findByClusterId(cluster.getId()) != null) {
+ avoidList.addCluster(cluster.getId());
+ } else {
+ includeList.addCluster(cluster.getId());
+ }
+ }
+ //add all hosts inside this pod in includeList
+ List hostList = _hostDao.findByPodId(dr.getPodId());
+ for (HostVO host : hostList) {
+ if (_dedicatedDao.findByHostId(host.getId()) != null) {
+ avoidList.addHost(host.getId());
+ } else {
+ includeList.addHost(host.getId());
+ }
+ }
+ }
+
+ if (dr.getDataCenterId() != null) {
+ includeList.addDataCenter(dr.getDataCenterId());
+ //add all Pod under this data center in includeList
+ List podList = _podDao.listByDataCenterId(dr.getDataCenterId());
+ for (HostPodVO pod : podList) {
+ if (_dedicatedDao.findByPodId(pod.getId()) != null) {
+ avoidList.addPod(pod.getId());
+ } else {
+ includeList.addPod(pod.getId());
+ }
+ }
+ List clusterList = _clusterDao.listClustersByDcId(dr.getDataCenterId());
+ for (ClusterVO cluster : clusterList) {
+ if (_dedicatedDao.findByClusterId(cluster.getId()) != null) {
+ avoidList.addCluster(cluster.getId());
+ } else {
+ includeList.addCluster(cluster.getId());
+ }
+ }
+ //add all hosts inside this in includeList
+ List hostList = _hostDao.listByDataCenterId(dr.getDataCenterId());
+ for (HostVO host : hostList) {
+ if (_dedicatedDao.findByHostId(host.getId()) != null) {
+ avoidList.addHost(host.getId());
+ } else {
+ includeList.addHost(host.getId());
+ }
+ }
+ }
+ }
+ //Update avoid list using includeList.
+ //add resources in avoid list which are not in include list.
+
+ List pods = _podDao.listByDataCenterId(dc.getId());
+ List clusters = _clusterDao.listClustersByDcId(dc.getId());
+ List hosts = _hostDao.listByDataCenterId(dc.getId());
+ Set podsInIncludeList = includeList.getPodsToAvoid();
+ Set clustersInIncludeList = includeList.getClustersToAvoid();
+ Set hostsInIncludeList = includeList.getHostsToAvoid();
+
+ for (HostPodVO pod : pods){
+ if (podsInIncludeList != null && !podsInIncludeList.contains(pod.getId())) {
+ avoidList.addPod(pod.getId());
+ }
+ }
+
+ for (ClusterVO cluster : clusters) {
+ if (clustersInIncludeList != null && !clustersInIncludeList.contains(cluster.getId())) {
+ avoidList.addCluster(cluster.getId());
+ }
+ }
+
+ for (HostVO host : hosts) {
+ if (hostsInIncludeList != null && !hostsInIncludeList.contains(host.getId())) {
+ avoidList.addHost(host.getId());
+ }
+ }
+ return avoidList;
+ }
+
+ private List searchInParentDomainResources(long domainId) {
+ List domainIds = getDomainParentIds(domainId);
+ List dr = new ArrayList();
+ for (Long id : domainIds) {
+ List resource = _dedicatedDao.listByDomainId(id);
+ if(resource != null) {
+ dr.addAll(resource);
+ }
+ }
+ return dr;
+ }
+
+ private List searchInDomainResources(long domainId) {
+ List dr = _dedicatedDao.listByDomainId(domainId);
+ return dr;
+ }
+
+ private List getDomainParentIds(long domainId) {
+ DomainVO domainRecord = _domainDao.findById(domainId);
+ List domainIds = new ArrayList();
+ domainIds.add(domainRecord.getId());
+ while (domainRecord.getParent() != null ){
+ domainRecord = _domainDao.findById(domainRecord.getParent());
+ domainIds.add(domainRecord.getId());
+ }
+ return domainIds;
+ }
+
+}
diff --git a/plugins/dedicated-resources/pom.xml b/plugins/dedicated-resources/pom.xml
new file mode 100644
index 00000000000..4c908f4ff96
--- /dev/null
+++ b/plugins/dedicated-resources/pom.xml
@@ -0,0 +1,29 @@
+
+
+ 4.0.0
+ cloud-plugin-dedicated-resources
+ Apache CloudStack Plugin - Dedicated Resources
+
+ org.apache.cloudstack
+ cloudstack-plugins
+ 4.2.0-SNAPSHOT
+ ../pom.xml
+
+
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/DedicateClusterCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/DedicateClusterCmd.java
new file mode 100644
index 00000000000..91e4fcee3ad
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/DedicateClusterCmd.java
@@ -0,0 +1,115 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ClusterResponse;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.DedicateClusterResponse;
+import org.apache.cloudstack.dedicated.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResources;
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "dedicateCluster", description= "Dedicate an existing cluster", responseObject = DedicateClusterResponse.class )
+public class DedicateClusterCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(DedicateClusterCmd.class.getName());
+
+ private static final String s_name = "dedicateclusterresponse";
+ @Inject DedicatedService dedicatedService;
+
+ @Parameter(name=ApiConstants.CLUSTER_ID, type=CommandType.UUID, entityType=ClusterResponse.class,
+ required=true, description="the ID of the Cluster")
+ private Long clusterId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class, required=true, description="the ID of the containing domain")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "the name of the account which needs dedication. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getClusterId() {
+ return clusterId;
+ }
+
+ public Long getDomainId() {
+ return domainId;
+ }
+
+ public String getAccountName() {
+ return accountName;
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "dedicating a cluster";
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ List extends DedicatedResources> result = dedicatedService.dedicateCluster(getClusterId(), getDomainId(), getAccountName());
+ ListResponse response = new ListResponse();
+ List clusterResponseList = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result) {
+ DedicateClusterResponse clusterResponse = dedicatedService.createDedicateClusterResponse(resource);
+ clusterResponseList.add(clusterResponse);
+ }
+ response.setResponses(clusterResponseList);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to dedicate cluster");
+ }
+ }
+
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/DedicateHostCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/DedicateHostCmd.java
new file mode 100644
index 00000000000..cb8eb45e0c4
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/DedicateHostCmd.java
@@ -0,0 +1,118 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.DedicateHostResponse;
+import org.apache.cloudstack.dedicated.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResources;
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "dedicateHost", description = "Dedicates a host.", responseObject = DedicateHostResponse.class)
+public class DedicateHostCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(DedicateHostCmd.class.getName());
+ private static final String s_name = "dedicatehostresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.HOST_ID, type=CommandType.UUID, entityType = HostResponse.class,
+ required=true, description="the ID of the host to update")
+ private Long hostId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class, required=true, description="the ID of the containing domain")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "the name of the account which needs dedication. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ public Long getDomainId() {
+ return domainId;
+ }
+
+ public String getAccountName() {
+ return accountName;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ List extends DedicatedResources> result = dedicatedService.dedicateHost(getHostId(), getDomainId(), getAccountName());
+ ListResponse response = new ListResponse();
+ List hostResponseList = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result) {
+ DedicateHostResponse hostResponse = dedicatedService.createDedicateHostResponse(resource);
+ hostResponseList.add(hostResponse);
+ }
+ response.setResponses(hostResponseList);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to dedicate host");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "dedicating a host";
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/DedicatePodCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/DedicatePodCmd.java
new file mode 100644
index 00000000000..ed3c227e508
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/DedicatePodCmd.java
@@ -0,0 +1,120 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.PodResponse;
+import org.apache.cloudstack.api.response.DedicatePodResponse;
+import org.apache.cloudstack.dedicated.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResources;
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "dedicatePod", description ="Dedicates a Pod.", responseObject = DedicatePodResponse.class)
+public class DedicatePodCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(DedicatePodCmd.class.getName());
+
+ private static final String s_name = "dedicatepodresponse";
+ @Inject public DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.POD_ID, type=CommandType.UUID, entityType=PodResponse.class,
+ required=true, description="the ID of the Pod")
+ private Long podId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class, required=true, description="the ID of the containing domain")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "the name of the account which needs dedication. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+
+ public Long getPodId() {
+ return podId;
+ }
+
+ public Long getDomainId() {
+ return domainId;
+ }
+
+ public String getAccountName() {
+ return accountName;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ List extends DedicatedResources> result = dedicatedService.dedicatePod(getPodId(), getDomainId(), getAccountName());
+ ListResponse response = new ListResponse();
+ List podResponseList = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result) {
+ DedicatePodResponse podresponse = dedicatedService.createDedicatePodResponse(resource);
+ podResponseList.add(podresponse);
+ }
+ response.setResponses(podResponseList);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to dedicate pod");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "dedicating a pod";
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/DedicateZoneCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/DedicateZoneCmd.java
new file mode 100644
index 00000000000..31c6025c305
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/DedicateZoneCmd.java
@@ -0,0 +1,120 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.api.response.DedicateZoneResponse;
+import org.apache.cloudstack.dedicated.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResources;
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "dedicateZone", description ="Dedicates a zones.", responseObject = DedicateZoneResponse.class)
+public class DedicateZoneCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(DedicateZoneCmd.class.getName());
+
+ private static final String s_name = "dedicatezoneresponse";
+ @Inject public DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class,
+ required=true, description="the ID of the zone")
+ private Long zoneId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class, required=true, description="the ID of the containing domain")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "the name of the account which needs dedication. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+
+ public Long getZoneId() {
+ return zoneId;
+ }
+
+ public Long getDomainId() {
+ return domainId;
+ }
+
+ public String getAccountName() {
+ return accountName;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ List extends DedicatedResources> result = dedicatedService.dedicateZone(getZoneId(), getDomainId(), getAccountName());
+ ListResponse response = new ListResponse();
+ List zoneResponseList = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result) {
+ DedicateZoneResponse zoneresponse = dedicatedService.createDedicateZoneResponse(resource);
+ zoneResponseList.add(zoneresponse);
+ }
+ response.setResponses(zoneResponseList);
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to dedicate zone");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "dedicating a zone";
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ListDedicatedClustersCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ListDedicatedClustersCmd.java
new file mode 100644
index 00000000000..f3947876581
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ListDedicatedClustersCmd.java
@@ -0,0 +1,105 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ClusterResponse;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.DedicateClusterResponse;
+import org.apache.cloudstack.dedicated.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.dc.DedicatedResources;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listDedicatedClusters", description = "Lists dedicated clusters.", responseObject = DedicateClusterResponse.class)
+public class ListDedicatedClustersCmd extends BaseListCmd {
+ public static final Logger s_logger = Logger.getLogger(ListDedicatedClustersCmd.class.getName());
+
+ private static final String s_name = "listdedicatedclustersresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+ @Parameter(name=ApiConstants.CLUSTER_ID, type=CommandType.UUID, entityType=ClusterResponse.class,
+ description="the ID of the cluster")
+ private Long clusterId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class,
+ description="the ID of the domain associated with the cluster")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING,
+ description = "the name of the account associated with the cluster. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getClusterId() {
+ return clusterId;
+ }
+
+ public Long getDomainId(){
+ return domainId;
+ }
+
+ public String getAccountName(){
+ return accountName;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public void execute(){
+ Pair, Integer> result = dedicatedService.listDedicatedClusters(this);
+ ListResponse response = new ListResponse();
+ List Responses = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result.first()) {
+ DedicateClusterResponse clusterResponse = dedicatedService.createDedicateClusterResponse(resource);
+ Responses.add(clusterResponse);
+ }
+ response.setResponses(Responses, result.second());
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to list dedicated clusters");
+ }
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ListDedicatedHostsCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ListDedicatedHostsCmd.java
new file mode 100644
index 00000000000..736251b36d6
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ListDedicatedHostsCmd.java
@@ -0,0 +1,105 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.DedicateHostResponse;
+import org.apache.cloudstack.dedicated.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.dc.DedicatedResources;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listDedicatedHosts", description = "Lists dedicated hosts.", responseObject = DedicateHostResponse.class)
+public class ListDedicatedHostsCmd extends BaseListCmd {
+ public static final Logger s_logger = Logger.getLogger(ListDedicatedHostsCmd.class.getName());
+
+ private static final String s_name = "listdedicatedhostsresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+ @Parameter(name=ApiConstants.HOST_ID, type=CommandType.UUID, entityType=HostResponse.class,
+ description="the ID of the host")
+ private Long hostId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class,
+ description="the ID of the domain associated with the host")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING,
+ description = "the name of the account associated with the host. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ public Long getDomainId(){
+ return domainId;
+ }
+
+ public String getAccountName(){
+ return accountName;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////l
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public void execute(){
+ Pair, Integer> result = dedicatedService.listDedicatedHosts(this);
+ ListResponse response = new ListResponse();
+ List Responses = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result.first()) {
+ DedicateHostResponse hostResponse = dedicatedService.createDedicateHostResponse(resource);
+ Responses.add(hostResponse);
+ }
+ response.setResponses(Responses, result.second());
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to list dedicated hosts");
+ }
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ListDedicatedPodsCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ListDedicatedPodsCmd.java
new file mode 100644
index 00000000000..da59edae8d3
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ListDedicatedPodsCmd.java
@@ -0,0 +1,105 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.PodResponse;
+import org.apache.cloudstack.api.response.DedicatePodResponse;
+import org.apache.cloudstack.dedicated.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.dc.DedicatedResources;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listDedicatedPods", description = "Lists dedicated pods.", responseObject = DedicatePodResponse.class)
+public class ListDedicatedPodsCmd extends BaseListCmd {
+ public static final Logger s_logger = Logger.getLogger(ListDedicatedPodsCmd.class.getName());
+
+ private static final String s_name = "listdedicatedpodsresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+ @Parameter(name=ApiConstants.POD_ID, type=CommandType.UUID, entityType=PodResponse.class,
+ description="the ID of the pod")
+ private Long podId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class,
+ description="the ID of the domain associated with the pod")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING,
+ description = "the name of the account associated with the pod. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getPodId() {
+ return podId;
+ }
+
+ public Long getDomainId(){
+ return domainId;
+ }
+
+ public String getAccountName(){
+ return accountName;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public void execute(){
+ Pair, Integer> result = dedicatedService.listDedicatedPods(this);
+ ListResponse response = new ListResponse();
+ List Responses = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result.first()) {
+ DedicatePodResponse podresponse = dedicatedService.createDedicatePodResponse(resource);
+ Responses.add(podresponse);
+ }
+ response.setResponses(Responses, result.second());
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to list dedicated pods");
+ }
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ListDedicatedZonesCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ListDedicatedZonesCmd.java
new file mode 100644
index 00000000000..a21f129f5be
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ListDedicatedZonesCmd.java
@@ -0,0 +1,105 @@
+// 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.api.commands;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseListCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.DomainResponse;
+import org.apache.cloudstack.api.response.ListResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.api.response.DedicateZoneResponse;
+import org.apache.cloudstack.dedicated.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.dc.DedicatedResources;
+import com.cloud.utils.Pair;
+
+@APICommand(name = "listDedicatedZones", description = "List dedicated zones.", responseObject = DedicateZoneResponse.class)
+public class ListDedicatedZonesCmd extends BaseListCmd {
+ public static final Logger s_logger = Logger.getLogger(ListDedicatedZonesCmd.class.getName());
+
+ private static final String s_name = "listdedicatedzonesresponse";
+ @Inject DedicatedService _dedicatedservice;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+ @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class,
+ description="the ID of the Zone")
+ private Long zoneId;
+
+ @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType=DomainResponse.class,
+ description="the ID of the domain associated with the zone")
+ private Long domainId;
+
+ @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING,
+ description = "the name of the account associated with the zone. Must be used with domainId.")
+ private String accountName;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getZoneId() {
+ return zoneId;
+ }
+
+ public Long getDomainId(){
+ return domainId;
+ }
+
+ public String getAccountName(){
+ return accountName;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ @Override
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public void execute(){
+ Pair, Integer> result = _dedicatedservice.listDedicatedZones(this);
+ ListResponse response = new ListResponse();
+ List Responses = new ArrayList();
+ if (result != null) {
+ for (DedicatedResources resource : result.first()) {
+ DedicateZoneResponse zoneResponse = _dedicatedservice.createDedicateZoneResponse(resource);
+ Responses.add(zoneResponse);
+ }
+ response.setResponses(Responses, result.second());
+ response.setResponseName(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to list dedicated zones");
+ }
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ReleaseDedicatedClusterCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ReleaseDedicatedClusterCmd.java
new file mode 100644
index 00000000000..ba1c6aad7cc
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ReleaseDedicatedClusterCmd.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 org.apache.cloudstack.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.ClusterResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.dedicated.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "releaseDedicatedCluster", description = "Release the dedication for cluster", responseObject = SuccessResponse.class)
+public class ReleaseDedicatedClusterCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(ReleaseDedicatedClusterCmd.class.getName());
+
+ private static final String s_name = "releasededicatedclusterresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.CLUSTER_ID, type=CommandType.UUID, entityType=ClusterResponse.class,
+ required=true, description="the ID of the Cluster")
+ private Long clusterId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getClusterId() {
+ return clusterId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ boolean result = dedicatedService.releaseDedicatedResource(null, null, getClusterId(), null);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to release dedicated cluster");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE_RELEASE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "releasing dedicated cluster";
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ReleaseDedicatedHostCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ReleaseDedicatedHostCmd.java
new file mode 100644
index 00000000000..a79c965926d
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ReleaseDedicatedHostCmd.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 org.apache.cloudstack.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.HostResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.dedicated.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "releaseDedicatedHost", description = "Release the dedication for host", responseObject = SuccessResponse.class)
+public class ReleaseDedicatedHostCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(ReleaseDedicatedHostCmd.class.getName());
+
+ private static final String s_name = "releasededicatedhostresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.HOST_ID, type=CommandType.UUID, entityType=HostResponse.class,
+ required=true, description="the ID of the host")
+ private Long hostId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getHostId() {
+ return hostId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ boolean result = dedicatedService.releaseDedicatedResource(null, null, null, getHostId());
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to release dedicated Host");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE_RELEASE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "releasing dedicated host";
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ReleaseDedicatedPodCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ReleaseDedicatedPodCmd.java
new file mode 100644
index 00000000000..d84ef66ef5a
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ReleaseDedicatedPodCmd.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 org.apache.cloudstack.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.PodResponse;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.dedicated.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "releaseDedicatedPod", description = "Release the dedication for the pod", responseObject = SuccessResponse.class)
+public class ReleaseDedicatedPodCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(ReleaseDedicatedPodCmd.class.getName());
+
+ private static final String s_name = "releasededicatedpodresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.POD_ID, type=CommandType.UUID, entityType=PodResponse.class,
+ required=true, description="the ID of the Pod")
+ private Long podId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getPodId() {
+ return podId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ boolean result = dedicatedService.releaseDedicatedResource(null, getPodId(), null, null);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to release dedicated pod");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE_RELEASE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "releasing dedicated pod";
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ReleaseDedicatedZoneCmd.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ReleaseDedicatedZoneCmd.java
new file mode 100644
index 00000000000..c78a4961dc8
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/commands/ReleaseDedicatedZoneCmd.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 org.apache.cloudstack.api.commands;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.ApiErrorCode;
+import org.apache.cloudstack.api.BaseAsyncCmd;
+import org.apache.cloudstack.api.Parameter;
+import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.api.response.ZoneResponse;
+import org.apache.cloudstack.dedicated.DedicatedService;
+import org.apache.log4j.Logger;
+
+import com.cloud.event.EventTypes;
+import com.cloud.user.Account;
+
+@APICommand(name = "releaseDedicatedZone", description = "Release dedication of zone", responseObject = SuccessResponse.class)
+public class ReleaseDedicatedZoneCmd extends BaseAsyncCmd {
+ public static final Logger s_logger = Logger.getLogger(ReleaseDedicatedZoneCmd.class.getName());
+
+ private static final String s_name = "releasededicatedzoneresponse";
+ @Inject DedicatedService dedicatedService;
+
+ /////////////////////////////////////////////////////
+ //////////////// API parameters /////////////////////
+ /////////////////////////////////////////////////////
+
+ @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType= ZoneResponse.class,
+ required=true, description="the ID of the Zone")
+ private Long zoneId;
+
+ /////////////////////////////////////////////////////
+ /////////////////// Accessors ///////////////////////
+ /////////////////////////////////////////////////////
+
+ public Long getZoneId() {
+ return zoneId;
+ }
+
+ /////////////////////////////////////////////////////
+ /////////////// API Implementation///////////////////
+ /////////////////////////////////////////////////////
+
+ public String getCommandName() {
+ return s_name;
+ }
+
+ @Override
+ public long getEntityOwnerId() {
+ return Account.ACCOUNT_ID_SYSTEM;
+ }
+
+ @Override
+ public void execute(){
+ boolean result = dedicatedService.releaseDedicatedResource(getZoneId(), null, null, null);
+ if (result) {
+ SuccessResponse response = new SuccessResponse(getCommandName());
+ this.setResponseObject(response);
+ } else {
+ throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to release dedicated zone");
+ }
+ }
+
+ @Override
+ public String getEventType() {
+ return EventTypes.EVENT_DEDICATE_RESOURCE_RELEASE;
+ }
+
+ @Override
+ public String getEventDescription() {
+ return "releasing dedicated zone";
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/response/DedicateClusterResponse.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/response/DedicateClusterResponse.java
new file mode 100644
index 00000000000..3c8dde3fd08
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/response/DedicateClusterResponse.java
@@ -0,0 +1,79 @@
+// 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.api.response;
+
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+public class DedicateClusterResponse extends BaseResponse {
+ @SerializedName("id") @Param(description="the ID of the dedicated resource")
+ private String id;
+
+ @SerializedName("clusterid") @Param(description="the ID of the cluster")
+ private String clusterId;
+
+ @SerializedName("clustername") @Param(description="the name of the cluster")
+ private String clusterName;
+
+ @SerializedName("domainid") @Param(description="the domain ID of the cluster")
+ private String domainId;
+
+ @SerializedName("accountid") @Param(description="the Account ID of the cluster")
+ private String accountId;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getClusterId() {
+ return clusterId;
+ }
+
+ public void setClusterId(String clusterId) {
+ this.clusterId = clusterId;
+ }
+
+ public String getClusterName() {
+ return clusterName;
+ }
+
+ public void setClusterName(String clusterName) {
+ this.clusterName = clusterName;
+ }
+
+ public String getDomainId() {
+ return domainId;
+ }
+
+ public void setDomainId(String domainId) {
+ this.domainId = domainId;
+ }
+
+ public String getAccountId() {
+ return accountId;
+ }
+
+ public void setAccountId(String accountId) {
+ this.accountId = accountId;
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/response/DedicateHostResponse.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/response/DedicateHostResponse.java
new file mode 100644
index 00000000000..cea31fe392b
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/response/DedicateHostResponse.java
@@ -0,0 +1,79 @@
+// 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.api.response;
+
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+public class DedicateHostResponse extends BaseResponse {
+ @SerializedName("id") @Param(description="the ID of the dedicated resource")
+ private String id;
+
+ @SerializedName("hostid") @Param(description="the ID of the host")
+ private String hostId;
+
+ @SerializedName("hostname") @Param(description="the name of the host")
+ private String hostName;
+
+ @SerializedName("domainid") @Param(description="the domain ID of the host")
+ private String domainId;
+
+ @SerializedName("accountid") @Param(description="the Account ID of the host")
+ private String accountId;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getHostId() {
+ return hostId;
+ }
+
+ public void setHostId(String hostId) {
+ this.hostId = hostId;
+ }
+
+ public String getHostName() {
+ return hostName;
+ }
+
+ public void setHostName(String hostName) {
+ this.hostName = hostName;
+ }
+
+ public String getDomainId() {
+ return domainId;
+ }
+
+ public void setDomainId(String domainId) {
+ this.domainId = domainId;
+ }
+
+ public String getAccountId() {
+ return accountId;
+ }
+
+ public void setAccountId(String accountId) {
+ this.accountId = accountId;
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/response/DedicatePodResponse.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/response/DedicatePodResponse.java
new file mode 100644
index 00000000000..4bcaa61c269
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/response/DedicatePodResponse.java
@@ -0,0 +1,82 @@
+// 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.api.response;
+
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+
+import com.cloud.dc.DedicatedResources;
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+@EntityReference(value = DedicatedResources.class)
+public class DedicatePodResponse extends BaseResponse {
+ @SerializedName("id") @Param(description="the ID of the dedicated resource")
+ private String id;
+
+ @SerializedName("podid") @Param(description="the ID of the Pod")
+ private String podId;
+
+ @SerializedName("podname") @Param(description="the Name of the Pod")
+ private String podName;
+
+ @SerializedName("domainid") @Param(description="the domain ID to which the Pod is dedicated")
+ private String domainId;
+
+ @SerializedName("accountid") @Param(description="the Account Id to which the Pod is dedicated")
+ private String accountId;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getPodId() {
+ return podId;
+ }
+
+ public void setPodId(String podId) {
+ this.podId = podId;
+ }
+
+ public String getPodName() {
+ return podName;
+ }
+
+ public void setPodName(String podName) {
+ this.podName = podName;
+ }
+
+ public String getDomainId() {
+ return domainId;
+ }
+
+ public void setDomainId(String domainId) {
+ this.domainId = domainId;
+ }
+
+ public String getAccountId() {
+ return accountId;
+ }
+
+ public void setAccountId(String accountId) {
+ this.accountId = accountId;
+ }
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/api/response/DedicateZoneResponse.java b/plugins/dedicated-resources/src/org/apache/cloudstack/api/response/DedicateZoneResponse.java
new file mode 100644
index 00000000000..57497cd3484
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/api/response/DedicateZoneResponse.java
@@ -0,0 +1,83 @@
+// 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.api.response;
+
+import org.apache.cloudstack.api.BaseResponse;
+import org.apache.cloudstack.api.EntityReference;
+
+import com.cloud.dc.DedicatedResources;
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+@EntityReference(value = DedicatedResources.class)
+public class DedicateZoneResponse extends BaseResponse {
+ @SerializedName("id") @Param(description="the ID of the dedicated resource")
+ private String id;
+
+ @SerializedName("zoneid") @Param(description="the ID of the Zone")
+ private String zoneId;
+
+ @SerializedName("zonename") @Param(description="the Name of the Zone")
+ private String zoneName;
+
+ @SerializedName("domainid") @Param(description="the domain ID to which the Zone is dedicated")
+ private String domainId;
+
+ @SerializedName("accountid") @Param(description="the Account Id to which the Zone is dedicated")
+ private String accountId;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getZoneId() {
+ return zoneId;
+ }
+
+ public void setZoneId(String zoneId) {
+ this.zoneId = zoneId;
+ }
+
+ public String getZoneName() {
+ return zoneName;
+ }
+
+ public void setZoneName(String zoneName) {
+ this.zoneName = zoneName;
+ }
+
+ public String getDomainId() {
+ return domainId;
+ }
+
+ public void setDomainId(String domainId) {
+ this.domainId = domainId;
+ }
+
+ public String getAccountId() {
+ return accountId;
+ }
+
+ public void setAccountId(String accountId) {
+ this.accountId = accountId;
+ }
+
+}
diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java
new file mode 100755
index 00000000000..682a6aa692b
--- /dev/null
+++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/DedicatedResourceManagerImpl.java
@@ -0,0 +1,815 @@
+// 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.dedicated;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import org.apache.cloudstack.api.commands.DedicateClusterCmd;
+import org.apache.cloudstack.api.commands.DedicateHostCmd;
+import org.apache.cloudstack.api.commands.DedicatePodCmd;
+import org.apache.cloudstack.api.commands.DedicateZoneCmd;
+import org.apache.cloudstack.api.commands.ListDedicatedClustersCmd;
+import org.apache.cloudstack.api.commands.ListDedicatedHostsCmd;
+import org.apache.cloudstack.api.commands.ListDedicatedPodsCmd;
+import org.apache.cloudstack.api.commands.ListDedicatedZonesCmd;
+import org.apache.cloudstack.api.commands.ReleaseDedicatedClusterCmd;
+import org.apache.cloudstack.api.commands.ReleaseDedicatedHostCmd;
+import org.apache.cloudstack.api.commands.ReleaseDedicatedPodCmd;
+import org.apache.cloudstack.api.commands.ReleaseDedicatedZoneCmd;
+import org.apache.cloudstack.api.response.DedicateClusterResponse;
+import org.apache.cloudstack.api.response.DedicateHostResponse;
+import org.apache.cloudstack.api.response.DedicatePodResponse;
+import org.apache.cloudstack.api.response.DedicateZoneResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import com.cloud.configuration.Config;
+import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.dc.ClusterVO;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.DedicatedResourceVO;
+import com.cloud.dc.DedicatedResources;
+import com.cloud.dc.HostPodVO;
+import com.cloud.dc.dao.ClusterDao;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.dc.dao.DedicatedResourceDao;
+import com.cloud.dc.dao.HostPodDao;
+import com.cloud.domain.DomainVO;
+import com.cloud.domain.dao.DomainDao;
+import com.cloud.event.ActionEvent;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.user.Account;
+import com.cloud.user.AccountManager;
+import com.cloud.user.AccountVO;
+import com.cloud.user.dao.AccountDao;
+import com.cloud.utils.DateUtil;
+import com.cloud.utils.NumbersUtil;
+import com.cloud.utils.Pair;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.UserVmVO;
+import com.cloud.vm.dao.UserVmDao;
+
+@Component
+@Local({DedicatedService.class })
+public class DedicatedResourceManagerImpl implements DedicatedService {
+ private static final Logger s_logger = Logger.getLogger(DedicatedResourceManagerImpl.class);
+
+ @Inject AccountDao _accountDao;
+ @Inject DomainDao _domainDao;
+ @Inject HostPodDao _podDao;
+ @Inject ClusterDao _clusterDao;
+ @Inject HostDao _hostDao;
+ @Inject DedicatedResourceDao _dedicatedDao;
+ @Inject DataCenterDao _zoneDao;
+ @Inject AccountManager _accountMgr;
+ @Inject UserVmDao _userVmDao;
+ @Inject ConfigurationDao _configDao;
+
+ private int capacityReleaseInterval;
+
+ public boolean configure(final String name, final Map params) throws ConfigurationException {
+ capacityReleaseInterval = NumbersUtil.parseInt(_configDao.getValue(Config.CapacitySkipcountingHours.key()), 3600);
+ return true;
+ }
+
+ @Override
+ @DB
+ @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE, eventDescription = "dedicating a Zone")
+ public List dedicateZone(Long zoneId, Long domainId, String accountName) {
+ Long accountId = null;
+ List hosts = null;
+ if(accountName != null){
+ Account caller = CallContext.current().getCallingAccount();
+ Account owner = _accountMgr.finalizeOwner(caller, accountName, domainId, null);
+ accountId = owner.getId();
+ }
+ List childDomainIds = getDomainChildIds(domainId);
+ childDomainIds.add(domainId);
+ checkAccountAndDomain(accountId, domainId);
+ DataCenterVO dc = _zoneDao.findById(zoneId);
+ if (dc == null) {
+ throw new InvalidParameterValueException("Unable to find zone by id " + zoneId);
+ } else {
+ DedicatedResourceVO dedicatedZone = _dedicatedDao.findByZoneId(zoneId);
+ //check if zone is dedicated
+ if(dedicatedZone != null) {
+ s_logger.error("Zone " + dc.getName() + " is already dedicated");
+ throw new CloudRuntimeException("Zone " + dc.getName() + " is already dedicated");
+ }
+
+ //check if any resource under this zone is dedicated to different account or sub-domain
+ List pods = _podDao.listByDataCenterId(dc.getId());
+ List podsToRelease = new ArrayList();
+ List clustersToRelease = new ArrayList();
+ List hostsToRelease = new ArrayList();
+ for (HostPodVO pod : pods) {
+ DedicatedResourceVO dPod = _dedicatedDao.findByPodId(pod.getId());
+ if (dPod != null) {
+ if(!(childDomainIds.contains(dPod.getDomainId()))) {
+ throw new CloudRuntimeException("Pod " + pod.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ }
+ if (accountId != null) {
+ if (dPod.getAccountId() == accountId) {
+ podsToRelease.add(dPod);
+ } else {
+ s_logger.error("Pod " + pod.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ throw new CloudRuntimeException("Pod " + pod.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ }
+ } else {
+ if (dPod.getAccountId() == null && dPod.getDomainId() == domainId) {
+ podsToRelease.add(dPod);
+ }
+ }
+ }
+ }
+
+ for (DedicatedResourceVO dr : podsToRelease) {
+ releaseDedicatedResource(null, dr.getPodId(), null, null);
+ }
+
+ List clusters = _clusterDao.listClustersByDcId(dc.getId());
+ for (ClusterVO cluster : clusters) {
+ DedicatedResourceVO dCluster = _dedicatedDao.findByClusterId(cluster.getId());
+ if (dCluster != null) {
+ if(!(childDomainIds.contains(dCluster.getDomainId()))) {
+ throw new CloudRuntimeException("Cluster " + cluster.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ }
+ if (accountId != null) {
+ if (dCluster.getAccountId() == accountId) {
+ clustersToRelease.add(dCluster);
+ } else {
+ s_logger.error("Cluster " + cluster.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ throw new CloudRuntimeException("Cluster " + cluster.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ }
+ } else {
+ if (dCluster.getAccountId() == null && dCluster.getDomainId() == domainId) {
+ clustersToRelease.add(dCluster);
+ }
+ }
+ }
+ }
+
+ for (DedicatedResourceVO dr : clustersToRelease) {
+ releaseDedicatedResource(null, null, dr.getClusterId(), null);
+ }
+
+ hosts = _hostDao.listByDataCenterId(dc.getId());
+ for (HostVO host : hosts) {
+ DedicatedResourceVO dHost = _dedicatedDao.findByHostId(host.getId());
+ if (dHost != null) {
+ if(!(childDomainIds.contains(dHost.getDomainId()))) {
+ throw new CloudRuntimeException("Host " + host.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ }
+ if (accountId != null) {
+ if (dHost.getAccountId() == accountId) {
+ hostsToRelease.add(dHost);
+ } else {
+ s_logger.error("Host " + host.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ throw new CloudRuntimeException("Host " + host.getName() + " under this Zone " + dc.getName() + " is dedicated to different account/domain");
+ }
+ } else {
+ if (dHost.getAccountId() == null && dHost.getDomainId() == domainId) {
+ hostsToRelease.add(dHost);
+ }
+ }
+ }
+ }
+
+ for (DedicatedResourceVO dr : hostsToRelease) {
+ releaseDedicatedResource(null, null, null, dr.getHostId());
+ }
+ }
+
+ checkHostsSuitabilityForExplicitDedication(accountId, childDomainIds, hosts);
+
+ Transaction txn = Transaction.currentTxn();
+ txn.start();
+ DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(zoneId, null, null, null, null, null);
+ try {
+ dedicatedResource.setDomainId(domainId);
+ if (accountId != null) {
+ dedicatedResource.setAccountId(accountId);
+ }
+ dedicatedResource = _dedicatedDao.persist(dedicatedResource);
+ } catch (Exception e) {
+ s_logger.error("Unable to dedicate zone due to " + e.getMessage(), e);
+ throw new CloudRuntimeException("Failed to dedicate zone. Please contact Cloud Support.");
+ }
+ txn.commit();
+
+ List result = new ArrayList();
+ result.add(dedicatedResource);
+ return result;
+ }
+
+ @Override
+ @DB
+ @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE, eventDescription = "dedicating a Pod")
+ public List dedicatePod(Long podId, Long domainId, String accountName) {
+ Long accountId = null;
+ if(accountName != null){
+ Account caller = CallContext.current().getCallingAccount();
+ Account owner = _accountMgr.finalizeOwner(caller, accountName, domainId, null);
+ accountId = owner.getId();
+ }
+ List childDomainIds = getDomainChildIds(domainId);
+ childDomainIds.add(domainId);
+ checkAccountAndDomain(accountId, domainId);
+ HostPodVO pod = _podDao.findById(podId);
+ List hosts = null;
+ if (pod == null) {
+ throw new InvalidParameterValueException("Unable to find pod by id " + podId);
+ } else {
+ DedicatedResourceVO dedicatedPod = _dedicatedDao.findByPodId(podId);
+ DedicatedResourceVO dedicatedZoneOfPod = _dedicatedDao.findByZoneId(pod.getDataCenterId());
+ //check if pod is dedicated
+ if(dedicatedPod != null ) {
+ s_logger.error("Pod " + pod.getName() + " is already dedicated");
+ throw new CloudRuntimeException("Pod " + pod.getName() + " is already dedicated");
+ }
+
+ if (dedicatedZoneOfPod != null) {
+ boolean domainIdInChildreanList = getDomainChildIds(dedicatedZoneOfPod.getDomainId()).contains(domainId);
+ //can dedicate a pod to an account/domain if zone is dedicated to parent-domain
+ if (dedicatedZoneOfPod.getAccountId() != null || (accountId == null && !domainIdInChildreanList)
+ || (accountId != null && !(dedicatedZoneOfPod.getDomainId() == domainId || domainIdInChildreanList))) {
+ DataCenterVO zone = _zoneDao.findById(pod.getDataCenterId());
+ s_logger.error("Cannot dedicate Pod. Its zone is already dedicated");
+ throw new CloudRuntimeException("Pod's Zone " + zone.getName() + " is already dedicated");
+ }
+ }
+
+ //check if any resource under this pod is dedicated to different account or sub-domain
+ List clusters = _clusterDao.listByPodId(pod.getId());
+ List clustersToRelease = new ArrayList();
+ List hostsToRelease = new ArrayList();
+ for (ClusterVO cluster : clusters) {
+ DedicatedResourceVO dCluster = _dedicatedDao.findByClusterId(cluster.getId());
+ if (dCluster != null) {
+ if(!(childDomainIds.contains(dCluster.getDomainId()))) {
+ throw new CloudRuntimeException("Cluster " + cluster.getName() + " under this Pod " + pod.getName() + " is dedicated to different account/domain");
+ }
+ /*if all dedicated resources belongs to same account and domain then we should release dedication
+ and make new entry for this Pod*/
+ if (accountId != null) {
+ if (dCluster.getAccountId() == accountId) {
+ clustersToRelease.add(dCluster);
+ } else {
+ s_logger.error("Cluster " + cluster.getName() + " under this Pod " + pod.getName() + " is dedicated to different account/domain");
+ throw new CloudRuntimeException("Cluster " + cluster.getName() + " under this Pod " + pod.getName() + " is dedicated to different account/domain");
+ }
+ } else {
+ if (dCluster.getAccountId() == null && dCluster.getDomainId() == domainId) {
+ clustersToRelease.add(dCluster);
+ }
+ }
+ }
+ }
+
+ for (DedicatedResourceVO dr : clustersToRelease) {
+ releaseDedicatedResource(null, null, dr.getClusterId(), null);
+ }
+
+ hosts = _hostDao.findByPodId(pod.getId());
+ for (HostVO host : hosts) {
+ DedicatedResourceVO dHost = _dedicatedDao.findByHostId(host.getId());
+ if (dHost != null) {
+ if(!(getDomainChildIds(domainId).contains(dHost.getDomainId()))) {
+ throw new CloudRuntimeException("Host " + host.getName() + " under this Pod " + pod.getName() + " is dedicated to different account/domain");
+ }
+ if (accountId != null) {
+ if (dHost.getAccountId() == accountId) {
+ hostsToRelease.add(dHost);
+ } else {
+ s_logger.error("Host " + host.getName() + " under this Pod " + pod.getName() + " is dedicated to different account/domain");
+ throw new CloudRuntimeException("Host " + host.getName() + " under this Pod " + pod.getName() + " is dedicated to different account/domain");
+ }
+ } else {
+ if (dHost.getAccountId() == null && dHost.getDomainId() == domainId) {
+ hostsToRelease.add(dHost);
+ }
+ }
+ }
+ }
+
+ for (DedicatedResourceVO dr : hostsToRelease) {
+ releaseDedicatedResource(null, null, null, dr.getHostId());
+ }
+ }
+
+ checkHostsSuitabilityForExplicitDedication(accountId, childDomainIds, hosts);
+
+ Transaction txn = Transaction.currentTxn();
+ txn.start();
+ DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(null, podId, null, null, null, null);
+ try {
+ dedicatedResource.setDomainId(domainId);
+ if (accountId != null) {
+ dedicatedResource.setAccountId(accountId);
+ }
+ dedicatedResource = _dedicatedDao.persist(dedicatedResource);
+ } catch (Exception e) {
+ s_logger.error("Unable to dedicate pod due to " + e.getMessage(), e);
+ throw new CloudRuntimeException("Failed to dedicate pod. Please contact Cloud Support.");
+ }
+ txn.commit();
+
+ List result = new ArrayList();
+ result.add(dedicatedResource);
+ return result;
+ }
+
+ @Override
+ @DB
+ @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE, eventDescription = "dedicating a Cluster")
+ public List dedicateCluster(Long clusterId, Long domainId, String accountName) {
+ Long accountId = null;
+ List hosts = null;
+ if(accountName != null){
+ Account caller = CallContext.current().getCallingAccount();
+ Account owner = _accountMgr.finalizeOwner(caller, accountName, domainId, null);
+ accountId = owner.getId();
+ }
+ List childDomainIds = getDomainChildIds(domainId);
+ childDomainIds.add(domainId);
+ checkAccountAndDomain(accountId, domainId);
+ ClusterVO cluster = _clusterDao.findById(clusterId);
+ if (cluster == null) {
+ throw new InvalidParameterValueException("Unable to find cluster by id " + clusterId);
+ } else {
+ DedicatedResourceVO dedicatedCluster = _dedicatedDao.findByClusterId(clusterId);
+ DedicatedResourceVO dedicatedPodOfCluster = _dedicatedDao.findByPodId(cluster.getPodId());
+ DedicatedResourceVO dedicatedZoneOfCluster = _dedicatedDao.findByZoneId(cluster.getDataCenterId());
+
+ //check if cluster is dedicated
+ if(dedicatedCluster != null) {
+ s_logger.error("Cluster " + cluster.getName() + " is already dedicated");
+ throw new CloudRuntimeException("Cluster "+ cluster.getName() + " is already dedicated");
+ }
+
+ if (dedicatedPodOfCluster != null) {
+ boolean domainIdInChildreanList = getDomainChildIds(dedicatedPodOfCluster.getDomainId()).contains(domainId);
+ //can dedicate a cluster to an account/domain if pod is dedicated to parent-domain
+ if (dedicatedPodOfCluster.getAccountId() != null || (accountId == null && !domainIdInChildreanList)
+ || (accountId != null && !(dedicatedPodOfCluster.getDomainId() == domainId || domainIdInChildreanList))) {
+ s_logger.error("Cannot dedicate Cluster. Its Pod is already dedicated");
+ HostPodVO pod = _podDao.findById(cluster.getPodId());
+ throw new CloudRuntimeException("Cluster's Pod " + pod.getName() + " is already dedicated");
+ }
+ }
+
+ if (dedicatedZoneOfCluster != null) {
+ boolean domainIdInChildreanList = getDomainChildIds(dedicatedZoneOfCluster.getDomainId()).contains(domainId);
+ //can dedicate a cluster to an account/domain if zone is dedicated to parent-domain
+ if (dedicatedZoneOfCluster.getAccountId() != null || (accountId == null && !domainIdInChildreanList)
+ || (accountId != null && !(dedicatedZoneOfCluster.getDomainId() == domainId || domainIdInChildreanList))) {
+ s_logger.error("Cannot dedicate Cluster. Its zone is already dedicated");
+ DataCenterVO zone = _zoneDao.findById(cluster.getDataCenterId());
+ throw new CloudRuntimeException("Cluster's Zone "+ zone.getName() + " is already dedicated");
+ }
+ }
+
+ //check if any resource under this cluster is dedicated to different account or sub-domain
+ hosts = _hostDao.findByClusterId(cluster.getId());
+ List hostsToRelease = new ArrayList();
+ for (HostVO host : hosts) {
+ DedicatedResourceVO dHost = _dedicatedDao.findByHostId(host.getId());
+ if (dHost != null) {
+ if(!(childDomainIds.contains(dHost.getDomainId()))) {
+ throw new CloudRuntimeException("Host " + host.getName() + " under this Cluster " + cluster.getName() + " is dedicated to different account/domain");
+ }
+ /*if all dedicated resources belongs to same account and domain then we should release dedication
+ and make new entry for this cluster */
+ if (accountId != null) {
+ if (dHost.getAccountId() == accountId) {
+ hostsToRelease.add(dHost);
+ } else {
+ s_logger.error("Cannot dedicate Cluster " + cluster.getName() + " to account" + accountName);
+ throw new CloudRuntimeException("Cannot dedicate Cluster " + cluster.getName() + " to account" + accountName);
+ }
+ } else {
+ if (dHost.getAccountId() == null && dHost.getDomainId() == domainId) {
+ hostsToRelease.add(dHost);
+ }
+ }
+ }
+ }
+
+ for (DedicatedResourceVO dr : hostsToRelease) {
+ releaseDedicatedResource(null, null, null, dr.getHostId());
+ }
+ }
+
+ checkHostsSuitabilityForExplicitDedication(accountId, childDomainIds, hosts);
+
+ Transaction txn = Transaction.currentTxn();
+ txn.start();
+ DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(null, null, clusterId, null, null, null);
+ try {
+ dedicatedResource.setDomainId(domainId);
+ if (accountId != null) {
+ dedicatedResource.setAccountId(accountId);
+ }
+ dedicatedResource = _dedicatedDao.persist(dedicatedResource);
+ } catch (Exception e) {
+ s_logger.error("Unable to dedicate host due to " + e.getMessage(), e);
+ throw new CloudRuntimeException("Failed to dedicate cluster. Please contact Cloud Support.");
+ }
+ txn.commit();
+
+ List result = new ArrayList();
+ result.add(dedicatedResource);
+ return result;
+ }
+
+ @Override
+ @DB
+ @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE, eventDescription = "dedicating a Host")
+ public List dedicateHost(Long hostId, Long domainId, String accountName) {
+ Long accountId = null;
+ if(accountName != null){
+ Account caller = CallContext.current().getCallingAccount();
+ Account owner = _accountMgr.finalizeOwner(caller, accountName, domainId, null);
+ accountId = owner.getId();
+ }
+ checkAccountAndDomain(accountId, domainId);
+ HostVO host = _hostDao.findById(hostId);
+ if (host == null) {
+ throw new InvalidParameterValueException("Unable to find host by id " + hostId);
+ } else {
+ //check if host is of routing type
+ if (host.getType() != Host.Type.Routing) {
+ throw new CloudRuntimeException("Invalid host type for host " + host.getName());
+ }
+
+ DedicatedResourceVO dedicatedHost = _dedicatedDao.findByHostId(hostId);
+ DedicatedResourceVO dedicatedClusterOfHost = _dedicatedDao.findByClusterId(host.getClusterId());
+ DedicatedResourceVO dedicatedPodOfHost = _dedicatedDao.findByPodId(host.getPodId());
+ DedicatedResourceVO dedicatedZoneOfHost = _dedicatedDao.findByZoneId(host.getDataCenterId());
+
+ if(dedicatedHost != null) {
+ s_logger.error("Host "+ host.getName() + " is already dedicated");
+ throw new CloudRuntimeException("Host "+ host.getName() + " is already dedicated");
+ }
+
+ if (dedicatedClusterOfHost != null) {
+ boolean domainIdInChildreanList = getDomainChildIds(dedicatedClusterOfHost.getDomainId()).contains(domainId);
+ //can dedicate a host to an account/domain if cluster is dedicated to parent-domain
+ if (dedicatedClusterOfHost.getAccountId() != null || (accountId == null && !domainIdInChildreanList)
+ || (accountId != null && !(dedicatedClusterOfHost.getDomainId() == domainId || domainIdInChildreanList))) {
+ ClusterVO cluster = _clusterDao.findById(host.getClusterId());
+ s_logger.error("Host's Cluster " + cluster.getName() + " is already dedicated");
+ throw new CloudRuntimeException("Host's Cluster " + cluster.getName() + " is already dedicated");
+ }
+ }
+
+ if (dedicatedPodOfHost != null){
+ boolean domainIdInChildreanList = getDomainChildIds(dedicatedPodOfHost.getDomainId()).contains(domainId);
+ //can dedicate a host to an account/domain if pod is dedicated to parent-domain
+ if (dedicatedPodOfHost.getAccountId() != null || (accountId == null && !domainIdInChildreanList)
+ || (accountId != null && !(dedicatedPodOfHost.getDomainId() == domainId || domainIdInChildreanList))) {
+ HostPodVO pod = _podDao.findById(host.getPodId());
+ s_logger.error("Host's Pod " + pod.getName() + " is already dedicated");
+ throw new CloudRuntimeException("Host's Pod " + pod.getName() + " is already dedicated");
+ }
+ }
+
+ if (dedicatedZoneOfHost != null) {
+ boolean domainIdInChildreanList = getDomainChildIds(dedicatedZoneOfHost.getDomainId()).contains(domainId);
+ //can dedicate a host to an account/domain if zone is dedicated to parent-domain
+ if (dedicatedZoneOfHost.getAccountId() != null || (accountId == null && !domainIdInChildreanList)
+ || (accountId != null && !(dedicatedZoneOfHost.getDomainId() == domainId || domainIdInChildreanList))) {
+ DataCenterVO zone = _zoneDao.findById(host.getDataCenterId());
+ s_logger.error("Host's Data Center " + zone.getName() + " is already dedicated");
+ throw new CloudRuntimeException("Host's Data Center " + zone.getName() + " is already dedicated");
+ }
+ }
+ }
+
+ List childDomainIds = getDomainChildIds(domainId);
+ childDomainIds.add(domainId);
+ checkHostSuitabilityForExplicitDedication(accountId, childDomainIds, hostId);
+
+ Transaction txn = Transaction.currentTxn();
+ txn.start();
+ DedicatedResourceVO dedicatedResource = new DedicatedResourceVO(null, null, null, hostId, null, null);
+ try {
+ dedicatedResource.setDomainId(domainId);
+ if (accountId != null) {
+ dedicatedResource.setAccountId(accountId);
+ }
+ dedicatedResource = _dedicatedDao.persist(dedicatedResource);
+ } catch (Exception e) {
+ s_logger.error("Unable to dedicate host due to " + e.getMessage(), e);
+ throw new CloudRuntimeException("Failed to dedicate host. Please contact Cloud Support.");
+ }
+ txn.commit();
+
+ List result = new ArrayList();
+ result.add(dedicatedResource);
+ return result;
+ }
+
+ private List getVmsOnHost(long hostId) {
+ List vms = _userVmDao.listUpByHostId(hostId);
+ List