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/agent/api/to/VirtualMachineTO.java b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java index b84d20a9239..46ee01bc8a3 100644 --- a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java +++ b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java @@ -52,6 +52,7 @@ public class VirtualMachineTO { boolean rebootOnCrash; boolean enableHA; boolean limitCpuUse; + boolean enableDynamicallyScaleVm; String vncPassword; String vncAddr; Map params; @@ -102,6 +103,14 @@ public class VirtualMachineTO { this.id = id; } + public boolean isEnableDynamicallyScaleVm() { + return enableDynamicallyScaleVm; + } + + public void setEnableDynamicallyScaleVm(boolean enableDynamicallyScaleVm) { + this.enableDynamicallyScaleVm = enableDynamicallyScaleVm; + } + public String getName() { return name; } 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 1a19c71dbfa..8b15ea56e8f 100644 --- a/api/src/com/cloud/deploy/DeploymentClusterPlanner.java +++ b/api/src/com/cloud/deploy/DeploymentClusterPlanner.java @@ -18,6 +18,7 @@ package com.cloud.deploy; import java.util.List; +import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.exception.InsufficientServerCapacityException; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; @@ -40,6 +41,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 186faf75f78..9375544ac28 100644 --- a/api/src/com/cloud/region/ha/GlobalLoadBalancingRulesService.java +++ b/api/src/com/cloud/region/ha/GlobalLoadBalancingRulesService.java @@ -33,6 +33,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 903eebc5bf8..8153a3f1af6 100755 --- a/api/src/com/cloud/user/AccountService.java +++ b/api/src/com/cloud/user/AccountService.java @@ -16,22 +16,15 @@ // under the License. package com.cloud.user; -import java.util.List; import java.util.Map; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd; -import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd; -import org.apache.cloudstack.api.command.admin.user.RegisterCmd; -import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd; - 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 { @@ -83,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/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 0732e77a781..096bf26c196 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -16,113 +16,6 @@ // under the License. package org.apache.cloudstack.api; -import java.text.DecimalFormat; -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; -import org.apache.cloudstack.api.response.AccountResponse; -import org.apache.cloudstack.api.response.ApplicationLoadBalancerResponse; -import org.apache.cloudstack.api.response.AsyncJobResponse; -import org.apache.cloudstack.api.response.AutoScalePolicyResponse; -import org.apache.cloudstack.api.response.AutoScaleVmGroupResponse; -import org.apache.cloudstack.api.response.AutoScaleVmProfileResponse; -import org.apache.cloudstack.api.response.CapacityResponse; -import org.apache.cloudstack.api.response.ClusterResponse; -import org.apache.cloudstack.api.response.ConditionResponse; -import org.apache.cloudstack.api.response.ConfigurationResponse; -import org.apache.cloudstack.api.response.CounterResponse; -import org.apache.cloudstack.api.response.CreateCmdResponse; -import org.apache.cloudstack.api.response.DiskOfferingResponse; -import org.apache.cloudstack.api.response.DomainResponse; -import org.apache.cloudstack.api.response.DomainRouterResponse; -import org.apache.cloudstack.api.response.EventResponse; -import org.apache.cloudstack.api.response.ExtractResponse; -import org.apache.cloudstack.api.response.FirewallResponse; -import org.apache.cloudstack.api.response.FirewallRuleResponse; -import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse; -import org.apache.cloudstack.api.response.GuestOSResponse; -import org.apache.cloudstack.api.response.GuestVlanRangeResponse; -import org.apache.cloudstack.api.response.HostForMigrationResponse; -import org.apache.cloudstack.api.response.HostResponse; -import org.apache.cloudstack.api.response.HypervisorCapabilitiesResponse; -import org.apache.cloudstack.api.response.IPAddressResponse; -import org.apache.cloudstack.api.response.InstanceGroupResponse; -import org.apache.cloudstack.api.response.InternalLoadBalancerElementResponse; -import org.apache.cloudstack.api.response.IpForwardingRuleResponse; -import org.apache.cloudstack.api.response.IsolationMethodResponse; -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.NetworkACLResponse; -import org.apache.cloudstack.api.response.NetworkOfferingResponse; -import org.apache.cloudstack.api.response.NetworkResponse; -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.PrivateGatewayResponse; -import org.apache.cloudstack.api.response.ProjectAccountResponse; -import org.apache.cloudstack.api.response.ProjectInvitationResponse; -import org.apache.cloudstack.api.response.ProjectResponse; -import org.apache.cloudstack.api.response.ProviderResponse; -import org.apache.cloudstack.api.response.RegionResponse; -import org.apache.cloudstack.api.response.RemoteAccessVpnResponse; -import org.apache.cloudstack.api.response.ResourceCountResponse; -import org.apache.cloudstack.api.response.ResourceLimitResponse; -import org.apache.cloudstack.api.response.ResourceTagResponse; -import org.apache.cloudstack.api.response.S3Response; -import org.apache.cloudstack.api.response.SecurityGroupResponse; -import org.apache.cloudstack.api.response.ServiceOfferingResponse; -import org.apache.cloudstack.api.response.ServiceResponse; -import org.apache.cloudstack.api.response.Site2SiteCustomerGatewayResponse; -import org.apache.cloudstack.api.response.Site2SiteVpnConnectionResponse; -import org.apache.cloudstack.api.response.Site2SiteVpnGatewayResponse; -import org.apache.cloudstack.api.response.SnapshotPolicyResponse; -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; -import org.apache.cloudstack.api.response.SystemVmResponse; -import org.apache.cloudstack.api.response.TemplatePermissionsResponse; -import org.apache.cloudstack.api.response.TemplateResponse; -import org.apache.cloudstack.api.response.TrafficMonitorResponse; -import org.apache.cloudstack.api.response.TrafficTypeResponse; -import org.apache.cloudstack.api.response.UsageRecordResponse; -import org.apache.cloudstack.api.response.UserResponse; -import org.apache.cloudstack.api.response.UserVmResponse; -import org.apache.cloudstack.api.response.VMSnapshotResponse; -import org.apache.cloudstack.api.response.VirtualRouterProviderResponse; -import org.apache.cloudstack.api.response.VlanIpRangeResponse; -import org.apache.cloudstack.api.response.VolumeResponse; -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.usage.Usage; - import com.cloud.async.AsyncJob; import com.cloud.capacity.Capacity; import com.cloud.configuration.Configuration; @@ -164,6 +57,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; @@ -192,6 +91,106 @@ import com.cloud.vm.Nic; import com.cloud.vm.NicSecondaryIp; import com.cloud.vm.VirtualMachine; import com.cloud.vm.snapshot.VMSnapshot; +import org.apache.cloudstack.affinity.AffinityGroup; +import org.apache.cloudstack.affinity.AffinityGroupResponse; +import org.apache.cloudstack.api.ApiConstants.HostDetails; +import org.apache.cloudstack.api.ApiConstants.VMDetails; +import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; +import org.apache.cloudstack.api.response.AccountResponse; +import org.apache.cloudstack.api.response.ApplicationLoadBalancerResponse; +import org.apache.cloudstack.api.response.AsyncJobResponse; +import org.apache.cloudstack.api.response.AutoScalePolicyResponse; +import org.apache.cloudstack.api.response.AutoScaleVmGroupResponse; +import org.apache.cloudstack.api.response.AutoScaleVmProfileResponse; +import org.apache.cloudstack.api.response.CapacityResponse; +import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.api.response.ConditionResponse; +import org.apache.cloudstack.api.response.ConfigurationResponse; +import org.apache.cloudstack.api.response.CounterResponse; +import org.apache.cloudstack.api.response.CreateCmdResponse; +import org.apache.cloudstack.api.response.DiskOfferingResponse; +import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.DomainRouterResponse; +import org.apache.cloudstack.api.response.EventResponse; +import org.apache.cloudstack.api.response.ExtractResponse; +import org.apache.cloudstack.api.response.FirewallResponse; +import org.apache.cloudstack.api.response.FirewallRuleResponse; +import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse; +import org.apache.cloudstack.api.response.GuestOSResponse; +import org.apache.cloudstack.api.response.GuestVlanRangeResponse; +import org.apache.cloudstack.api.response.HostForMigrationResponse; +import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.response.HypervisorCapabilitiesResponse; +import org.apache.cloudstack.api.response.IPAddressResponse; +import org.apache.cloudstack.api.response.InstanceGroupResponse; +import org.apache.cloudstack.api.response.InternalLoadBalancerElementResponse; +import org.apache.cloudstack.api.response.IpForwardingRuleResponse; +import org.apache.cloudstack.api.response.IsolationMethodResponse; +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; +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; +import org.apache.cloudstack.api.response.ProjectResponse; +import org.apache.cloudstack.api.response.ProviderResponse; +import org.apache.cloudstack.api.response.RegionResponse; +import org.apache.cloudstack.api.response.RemoteAccessVpnResponse; +import org.apache.cloudstack.api.response.ResourceCountResponse; +import org.apache.cloudstack.api.response.ResourceLimitResponse; +import org.apache.cloudstack.api.response.ResourceTagResponse; +import org.apache.cloudstack.api.response.S3Response; +import org.apache.cloudstack.api.response.SecurityGroupResponse; +import org.apache.cloudstack.api.response.ServiceOfferingResponse; +import org.apache.cloudstack.api.response.ServiceResponse; +import org.apache.cloudstack.api.response.Site2SiteCustomerGatewayResponse; +import org.apache.cloudstack.api.response.Site2SiteVpnConnectionResponse; +import org.apache.cloudstack.api.response.Site2SiteVpnGatewayResponse; +import org.apache.cloudstack.api.response.SnapshotPolicyResponse; +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.StoragePoolResponse; +import org.apache.cloudstack.api.response.SwiftResponse; +import org.apache.cloudstack.api.response.SystemVmInstanceResponse; +import org.apache.cloudstack.api.response.SystemVmResponse; +import org.apache.cloudstack.api.response.TemplatePermissionsResponse; +import org.apache.cloudstack.api.response.TemplateResponse; +import org.apache.cloudstack.api.response.TrafficMonitorResponse; +import org.apache.cloudstack.api.response.TrafficTypeResponse; +import org.apache.cloudstack.api.response.UsageRecordResponse; +import org.apache.cloudstack.api.response.UserResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.api.response.VMSnapshotResponse; +import org.apache.cloudstack.api.response.VirtualRouterProviderResponse; +import org.apache.cloudstack.api.response.VlanIpRangeResponse; +import org.apache.cloudstack.api.response.VolumeResponse; +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.network.lb.ApplicationLoadBalancerRule; +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 java.text.DecimalFormat; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; public interface ResponseGenerator { UserResponse createUserResponse(UserAccount user); @@ -259,7 +258,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 7c3d1e95e57..86f30067b18 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 @@ -17,10 +17,13 @@ package org.apache.cloudstack.api.command.admin.internallb; -import java.util.List; - -import javax.inject.Inject; - +import com.cloud.event.EventTypes; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.VirtualRouterProvider; +import com.cloud.user.Account; +import com.cloud.user.UserContext; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -31,13 +34,8 @@ import org.apache.cloudstack.api.response.InternalLoadBalancerElementResponse; import org.apache.cloudstack.network.element.InternalLoadBalancerElementService; import org.apache.log4j.Logger; -import com.cloud.event.EventTypes; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.network.VirtualRouterProvider; -import com.cloud.user.Account; -import com.cloud.user.UserContext; +import javax.inject.Inject; +import java.util.List; @APICommand(name = "configureInternalLoadBalancerElement", responseObject=InternalLoadBalancerElementResponse.class, description="Configures an Internal Load Balancer element.", since="4.2.0") @@ -98,11 +96,8 @@ public class ConfigureInternalLoadBalancerElementCmd extends BaseAsyncCmd { @Override public void execute() throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException{ - s_logger.debug("hello alena"); UserContext.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()); 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 5178d685889..74eb2b9bf8f 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 @@ -71,15 +71,19 @@ public class CreateStoragePoolCmd extends BaseCmd { @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType = ZoneResponse.class, required=true, description="the Zone ID for the storage pool") private Long zoneId; - + @Parameter(name=ApiConstants.PROVIDER, type=CommandType.STRING, required=false, description="the storage provider name") private String storageProviderName; - + @Parameter(name=ApiConstants.SCOPE, type=CommandType.STRING, 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 /////////////////////// ///////////////////////////////////////////////////// @@ -111,18 +115,18 @@ public class CreateStoragePoolCmd extends BaseCmd { public Long getZoneId() { return zoneId; } - + public String getStorageProviderName() { return this.storageProviderName; } - + public String getScope() { - return this.scope; + 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 37d007c0376..ed6ca04c16f 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 @@ -16,24 +16,23 @@ // under the License. package org.apache.cloudstack.api.command.admin.storage; -import java.util.ArrayList; -import java.util.List; - +import com.cloud.async.AsyncJob; +import com.cloud.storage.StoragePool; +import com.cloud.utils.Pair; import org.apache.cloudstack.api.APICommand; -import org.apache.log4j.Logger; - 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.async.AsyncJob; -import com.cloud.storage.StoragePool; -import com.cloud.utils.Pair; +import org.apache.log4j.Logger; + +import java.util.ArrayList; +import java.util.List; @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()); @@ -72,13 +71,13 @@ public class FindStoragePoolsForMigrationCmd extends BaseListCmd { public void execute() { Pair, List> pools = _mgr.listStoragePoolsForMigrationOfVolume(getId()); - ListResponse response = new ListResponse(); - List poolResponses = new ArrayList(); + ListResponse response = new ListResponse(); + List poolResponses = new ArrayList(); List allPools = pools.first(); List 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 9bbae064376..6eaac38d29a 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 @@ -38,7 +38,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 ea4a010ab93..f80e17626fd 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 @@ -30,7 +30,6 @@ import org.apache.log4j.Logger; import com.cloud.async.AsyncJob; import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.ResourceInUseException; import com.cloud.user.Account; import com.cloud.user.UserContext; @@ -123,17 +122,12 @@ 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()); - this.setResponseObject(response); - } 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()); + boolean result = _affinityGroupService.deleteAffinityGroup(id, accountName, domainId, name); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete affinity group"); } } 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 fe5decdf5fc..77ec4e7609f 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 @@ -87,13 +87,19 @@ public class DeleteGlobalLoadBalancerRuleCmd extends BaseAsyncCmd { @Override public void execute(){ - _gslbService.deleteGlobalLoadBalancerRule(this); - UserContext.current().setEventDetails("Deleting global Load balancer Id: " + getGlobalLoadBalancerId()); + UserContext.current().setEventDetails("Deleting global Load balancer rule Id: " + getGlobalLoadBalancerId()); + boolean result = _gslbService.deleteGlobalLoadBalancerRule(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.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 bd56c744a2f..714e9e79926 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 @@ -42,7 +42,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 2cc3c98b087..a6410214cc3 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 @@ -38,11 +38,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 36021876184..2d37add5eb4 100644 --- a/api/src/org/apache/cloudstack/api/response/HypervisorCapabilitiesResponse.java +++ b/api/src/org/apache/cloudstack/api/response/HypervisorCapabilitiesResponse.java @@ -42,6 +42,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; @@ -83,4 +91,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 d6847d55846..70c3d79c4c0 100644 --- a/api/src/org/apache/cloudstack/api/response/NetworkResponse.java +++ b/api/src/org/apache/cloudstack/api/response/NetworkResponse.java @@ -166,6 +166,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; } @@ -352,4 +356,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 f0bbcb19136..00000000000 --- a/api/src/org/apache/cloudstack/api/response/StoragePoolForMigrationResponse.java +++ /dev/null @@ -1,248 +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 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; -import com.google.gson.annotations.SerializedName; - -@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 4411ddcb112..965407d9952 100644 --- a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java +++ b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java @@ -16,16 +16,15 @@ // under the License. package org.apache.cloudstack.api.response; -import java.util.Date; - -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; 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 java.util.Date; @EntityReference(value=StoragePool.class) public class StoragePoolResponse extends BaseResponse { @@ -40,13 +39,13 @@ public class StoragePoolResponse extends BaseResponse { @SerializedName(ApiConstants.ZONE_TYPE) @Param(description = "network type of the availability zone") private String zoneType; - + @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; @@ -82,10 +81,17 @@ public class StoragePoolResponse extends BaseResponse { @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(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 */ @@ -100,6 +106,14 @@ 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(); @@ -132,11 +146,11 @@ public class StoragePoolResponse extends BaseResponse { public String getZoneType() { return zoneType; } - + public void setZoneType(String zoneType) { this.zoneType = zoneType; } - + public String getPodId() { return podId; } @@ -248,4 +262,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/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties index fc7715dd4c9..d0ead0e8f10 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.... 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 a10b9db7501..049e483bf5e 100644 --- a/client/tomcatconf/applicationContext.xml.in +++ b/client/tomcatconf/applicationContext.xml.in @@ -93,7 +93,7 @@ - + @@ -156,9 +156,17 @@ - + - + + + + + + + + + @@ -673,7 +681,6 @@ - @@ -796,6 +803,7 @@ + diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index fd5479f44b4..5eccf366c66 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -265,6 +265,10 @@ addSecondaryStorage=1 updateHostPassword=1 releaseHostReservation=1 +#### VmWare DC +addVmwareDc=1 +removeVmwareDc=1 + #### volume commands attachVolume=15 uploadVolume=15 @@ -276,10 +280,6 @@ extractVolume=15 migrateVolume=15 resizeVolume=15 updateVolume=1 -addVolumeDetail=1 -updateVolumeDetail=1 -removeVolumeDetail=1 -listVolumeDetails=1 #### registration command: FIXME -- this really should be something in management server that #### generates a new key for the user and they just have to @@ -350,10 +350,6 @@ updateNetwork=15 addNicToVirtualMachine=15 removeNicFromVirtualMachine=15 updateDefaultNicForVirtualMachine=15 -addNicDetail=1 -updateNicDetail=1 -removeNicDetail=1 -listNicDetails=1 #### addIpToNic=15 @@ -641,3 +637,16 @@ listInternalLoadBalancerVMs=1 ### Network Isolation methods listing listNetworkIsolationMethods=1 +#### Dedicated Resource commands +dedicateZone=1 +dedicatePod=1 +dedicateCluster=1 +dedicateHost=1 +releaseDedicatedZone=1 +releaseDedicatedPod=1 +releaseDedicatedCluster=1 +releaseDedicatedHost=1 +listDedicatedZones=1 +listDedicatedPods=1 +listDedicatedClusters=1 +listDedicatedHosts=1 diff --git a/client/tomcatconf/componentContext.xml.in b/client/tomcatconf/componentContext.xml.in index e946f448d90..93ef21f679b 100644 --- a/client/tomcatconf/componentContext.xml.in +++ b/client/tomcatconf/componentContext.xml.in @@ -24,28 +24,27 @@ xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd - http://www.springframework.org/schema/tx + http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context - http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + http://www.springframework.org/schema/context/spring-context-3.0.xsd"> - @@ -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/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/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/core/src/com/cloud/storage/template/HttpTemplateDownloader.java b/core/src/com/cloud/storage/template/HttpTemplateDownloader.java index 628ad64c0dc..c8aac27da8c 100644 --- a/core/src/com/cloud/storage/template/HttpTemplateDownloader.java +++ b/core/src/com/cloud/storage/template/HttpTemplateDownloader.java @@ -250,6 +250,13 @@ public class HttpTemplateDownloader implements TemplateDownloader { } } else { remoteSize2 = Long.parseLong(contentLengthHeader.getValue()); + if ( remoteSize2 == 0 ) { + status = TemplateDownloader.Status.DOWNLOAD_FINISHED; + String downloaded = "(download complete remote=" + remoteSize + "bytes)"; + errorString = "Downloaded " + totalBytes + " bytes " + downloaded; + downloadTime = 0; + return 0; + } } if (remoteSize == 0) { 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..91c2967fc45 --- /dev/null +++ b/docs/en-US/CloudStack_GSoC_Guide.xml @@ -0,0 +1,52 @@ + + +%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/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-tuna.xml b/docs/en-US/gsoc-tuna.xml new file mode 100644 index 00000000000..68032a8d46d --- /dev/null +++ b/docs/en-US/gsoc-tuna.xml @@ -0,0 +1,28 @@ + + +%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. + 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/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/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java index 963e4d7d967..ca299ea45bc 100755 --- a/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java @@ -89,10 +89,9 @@ public class CloudOrchestrator implements OrchestrationService { public CloudOrchestrator() { } - + 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/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/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 e9769802a37..d8d413283ad 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java @@ -38,34 +38,36 @@ import com.cloud.vm.VirtualMachineProfile; @Component public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator { - private static final Logger s_logger = Logger.getLogger(ZoneWideStoragePoolAllocator.class); - @Inject PrimaryDataStoreDao _storagePoolDao; - @Inject DataStoreManager dataStoreMgr; + private static final Logger s_logger = Logger.getLogger(ZoneWideStoragePoolAllocator.class); + @Inject PrimaryDataStoreDao _storagePoolDao; + @Inject DataStoreManager dataStoreMgr; - @Override - protected boolean filter(ExcludeList avoid, StoragePool pool, DiskProfile dskCh, - DeploymentPlan plan) { + @Override + protected boolean filter(ExcludeList avoid, StoragePool pool, DiskProfile dskCh, + DeploymentPlan plan) { Volume volume = _volumeDao.findById(dskCh.getVolumeId()); List requestVolumes = new ArrayList(); requestVolumes.add(volume); return storageMgr.storagePoolHasEnoughSpace(requestVolumes, pool); - } + } - @Override - protected List select(DiskProfile dskCh, - VirtualMachineProfile vmProfile, - DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { - s_logger.debug("ZoneWideStoragePoolAllocator to find storage pool"); - List suitablePools = new ArrayList(); - HypervisorType hypervisor = dskCh.getHypervisorType(); - if (hypervisor != null) { - if (hypervisor != HypervisorType.KVM) { - s_logger.debug("Only kvm supports zone wide storage"); - return suitablePools; - } - } + @Override + protected List select(DiskProfile dskCh, + VirtualMachineProfile vmProfile, + DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { + s_logger.debug("ZoneWideStoragePoolAllocator to find storage pool"); + List suitablePools = new ArrayList(); + HypervisorType hypervisor = dskCh.getHypervisorType(); + if (hypervisor != null) { + 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 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); @@ -74,17 +76,17 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator { avoid.addPool(pool.getId()); } - for (StoragePoolVO storage : storagePools) { - if (suitablePools.size() == returnUpTo) { - break; - } - StoragePool pol = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(storage.getId()); - if (filter(avoid, pol, dskCh, plan)) { - suitablePools.add(pol); + for (StoragePoolVO storage : storagePools) { + if (suitablePools.size() == returnUpTo) { + break; + } + StoragePool pol = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(storage.getId()); + if (filter(avoid, pol, dskCh, plan)) { + suitablePools.add(pol); } else { avoid.addPool(pol.getId()); } - } - return suitablePools; - } + } + return suitablePools; + } } 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/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/opt/cloud/bin/ipassoc.sh b/patches/systemvm/debian/config/opt/cloud/bin/ipassoc.sh index f326fac9e54..d23ec00de5e 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/ipassoc.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/ipassoc.sh @@ -227,7 +227,8 @@ add_first_ip() { if [ $if_keep_state -ne 1 -o $old_state -ne 0 ] then sudo ip link set $ethDev up - sudo arping -c 3 -I $ethDev -A -U -s $ipNoMask $ipNoMask; + sudo arping -c 1 -I $ethDev -A -U -s $ipNoMask $ipNoMask; + sudo arping -c 1 -I $ethDev -A -U -s $ipNoMask $ipNoMask; fi add_routing $1 @@ -273,7 +274,8 @@ add_an_ip () { if [ $if_keep_state -ne 1 -o $old_state -ne 0 ] then sudo ip link set $ethDev up - sudo arping -c 3 -I $ethDev -A -U -s $ipNoMask $ipNoMask; + sudo arping -c 1 -I $ethDev -A -U -s $ipNoMask $ipNoMask; + sudo arping -c 1 -I $ethDev -A -U -s $ipNoMask $ipNoMask; fi add_routing $1 return $? 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..a0eb56cbb8a --- /dev/null +++ b/plugins/affinity-group-processors/explicit-dedication/src/org/apache/cloudstack/affinity/ExplicitDedicationProcessor.java @@ -0,0 +1,383 @@ +// 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.cloudstack.affinity.dao.AffinityGroupDao; +import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; +import org.apache.log4j.Logger; + +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 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 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 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 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..c321b22176e --- /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 com.cloud.utils.component.AdapterBase; +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.log4j.Logger; +import org.springframework.stereotype.Component; + +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.UserContext; +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 = UserContext.current().getCaller(); + 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 = UserContext.current().getCaller(); + 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 = UserContext.current().getCaller(); + 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 = UserContext.current().getCaller(); + 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 vmsByLastHostId = _userVmDao.listByLastHostId(hostId); + if (vmsByLastHostId.size() > 0) { + // check if any VMs are within skip.counting.hours, if yes we have to consider the host. + for (UserVmVO stoppedVM : vmsByLastHostId) { + long secondsSinceLastUpdate = (DateUtil.currentGMTTime().getTime() - stoppedVM.getUpdateTime() + .getTime()) / 1000; + if (secondsSinceLastUpdate < capacityReleaseInterval) { + vms.add(stoppedVM); + } + } + } + + return vms; + } + + private boolean checkHostSuitabilityForExplicitDedication(Long accountId, List domainIds, long hostId) { + boolean suitable = true; + List allVmsOnHost = getVmsOnHost(hostId); + if (accountId != null) { + for (UserVmVO vm : allVmsOnHost) { + if (vm.getAccountId() != accountId) { + s_logger.info("Host " + vm.getHostId() + " found to be unsuitable for explicit dedication as it is " + + "running instances of another account"); + throw new CloudRuntimeException("Host " + hostId + " found to be unsuitable for explicit dedication as it is " + + "running instances of another account"); + } + } + } else { + for (UserVmVO vm : allVmsOnHost) { + if (!domainIds.contains(vm.getDomainId())) { + s_logger.info("Host " + vm.getHostId() + " found to be unsuitable for explicit dedication as it is " + + "running instances of another domain"); + throw new CloudRuntimeException("Host " + hostId + " found to be unsuitable for explicit dedication as it is " + + "running instances of another domain"); + } + } + } + return suitable; + } + + private boolean checkHostsSuitabilityForExplicitDedication(Long accountId, List domainIds, List hosts) { + boolean suitable = true; + for (HostVO host : hosts){ + checkHostSuitabilityForExplicitDedication(accountId, domainIds, host.getId()); + } + return suitable; + } + + private void checkAccountAndDomain(Long accountId, Long domainId) { + DomainVO domain = _domainDao.findById(domainId); + if (domain == null) { + throw new InvalidParameterValueException("Unable to find the domain by id " + domainId + ", please specify valid domainId"); + } + //check if account belongs to the domain id + if (accountId != null) { + AccountVO account = _accountDao.findById(accountId); + if (account == null || domainId != account.getDomainId()){ + throw new InvalidParameterValueException("Please specify the domain id of the account: " + account.getAccountName()); + } + } + } + + private List getDomainChildIds(long domainId) { + DomainVO domainRecord = _domainDao.findById(domainId); + List domainIds = new ArrayList(); + domainIds.add(domainRecord.getId()); + // find all domain Ids till leaf + List allChildDomains = _domainDao.findAllChildren(domainRecord.getPath(), domainRecord.getId()); + for (DomainVO domain : allChildDomains) { + domainIds.add(domain.getId()); + } + return domainIds; + } + + @Override + public DedicateZoneResponse createDedicateZoneResponse(DedicatedResources resource) { + DedicateZoneResponse dedicateZoneResponse = new DedicateZoneResponse(); + DataCenterVO dc = _zoneDao.findById(resource.getDataCenterId()); + DomainVO domain = _domainDao.findById(resource.getDomainId()); + AccountVO account = _accountDao.findById(resource.getAccountId()); + dedicateZoneResponse.setId(resource.getUuid()); + dedicateZoneResponse.setZoneId(dc.getUuid()); + dedicateZoneResponse.setZoneName(dc.getName()); + dedicateZoneResponse.setDomainId(domain.getUuid()); + if (account != null) { + dedicateZoneResponse.setAccountId(account.getUuid()); + } + dedicateZoneResponse.setObjectName("dedicatedzone"); + return dedicateZoneResponse; + } + + @Override + public DedicatePodResponse createDedicatePodResponse(DedicatedResources resource) { + DedicatePodResponse dedicatePodResponse = new DedicatePodResponse(); + HostPodVO pod = _podDao.findById(resource.getPodId()); + DomainVO domain = _domainDao.findById(resource.getDomainId()); + AccountVO account = _accountDao.findById(resource.getAccountId()); + dedicatePodResponse.setId(resource.getUuid()); + dedicatePodResponse.setPodId(pod.getUuid()); + dedicatePodResponse.setPodName(pod.getName()); + dedicatePodResponse.setDomainId(domain.getUuid()); + if (account != null) { + dedicatePodResponse.setAccountId(account.getUuid()); + } + dedicatePodResponse.setObjectName("dedicatedpod"); + return dedicatePodResponse; + } + + @Override + public DedicateClusterResponse createDedicateClusterResponse(DedicatedResources resource) { + DedicateClusterResponse dedicateClusterResponse = new DedicateClusterResponse(); + ClusterVO cluster = _clusterDao.findById(resource.getClusterId()); + DomainVO domain = _domainDao.findById(resource.getDomainId()); + AccountVO account = _accountDao.findById(resource.getAccountId()); + dedicateClusterResponse.setId(resource.getUuid()); + dedicateClusterResponse.setClusterId(cluster.getUuid()); + dedicateClusterResponse.setClusterName(cluster.getName()); + dedicateClusterResponse.setDomainId(domain.getUuid()); + if (account != null) { + dedicateClusterResponse.setAccountId(account.getUuid()); + } + dedicateClusterResponse.setObjectName("dedicatedcluster"); + return dedicateClusterResponse; + } + + @Override + public DedicateHostResponse createDedicateHostResponse(DedicatedResources resource) { + DedicateHostResponse dedicateHostResponse = new DedicateHostResponse(); + HostVO host = _hostDao.findById(resource.getHostId()); + DomainVO domain = _domainDao.findById(resource.getDomainId()); + AccountVO account = _accountDao.findById(resource.getAccountId()); + dedicateHostResponse.setId(resource.getUuid()); + dedicateHostResponse.setHostId(host.getUuid()); + dedicateHostResponse.setHostName(host.getName()); + dedicateHostResponse.setDomainId(domain.getUuid()); + if (account != null) { + dedicateHostResponse.setAccountId(account.getUuid()); + } + dedicateHostResponse.setObjectName("dedicatedhost"); + return dedicateHostResponse; + } + + @Override + public List> getCommands() { + List> cmdList = new ArrayList>(); + cmdList.add(DedicateZoneCmd.class); + cmdList.add(DedicatePodCmd.class); + cmdList.add(DedicateClusterCmd.class); + cmdList.add(DedicateHostCmd.class); + cmdList.add(ListDedicatedZonesCmd.class); + cmdList.add(ListDedicatedPodsCmd.class); + cmdList.add(ListDedicatedClustersCmd.class); + cmdList.add(ListDedicatedHostsCmd.class); + cmdList.add(ReleaseDedicatedClusterCmd.class); + cmdList.add(ReleaseDedicatedHostCmd.class); + cmdList.add(ReleaseDedicatedPodCmd.class); + cmdList.add(ReleaseDedicatedZoneCmd.class); + return cmdList; + } + + @Override + public Pair, Integer> listDedicatedZones(ListDedicatedZonesCmd cmd) { + Long zoneId = cmd.getZoneId(); + Long domainId = cmd.getDomainId(); + String accountName = cmd.getAccountName(); + Long accountId = null; + if (accountName != null) { + if (domainId != null) { + Account account = _accountDao.findActiveAccount(accountName, domainId); + if (account != null) { + accountId = account.getId(); + } + } else { + throw new InvalidParameterValueException("Please specify the domain id of the account: " + accountName); + } + } + Pair, Integer> result = _dedicatedDao.searchDedicatedZones(zoneId, domainId, accountId); + return new Pair, Integer>(result.first(), result.second()); + } + + @Override + public Pair, Integer> listDedicatedPods(ListDedicatedPodsCmd cmd) { + Long podId = cmd.getPodId(); + Long domainId = cmd.getDomainId(); + String accountName = cmd.getAccountName(); + Long accountId = null; + if (accountName != null) { + if (domainId != null) { + Account account = _accountDao.findActiveAccount(accountName, domainId); + if (account != null) { + accountId = account.getId(); + } + } else { + throw new InvalidParameterValueException("Please specify the domain id of the account: " + accountName); + } + } + Pair, Integer> result = _dedicatedDao.searchDedicatedPods(podId, domainId, accountId); + return new Pair, Integer>(result.first(), result.second()); + } + + @Override + public Pair, Integer> listDedicatedClusters(ListDedicatedClustersCmd cmd) { + Long clusterId = cmd.getClusterId(); + Long domainId = cmd.getDomainId(); + String accountName = cmd.getAccountName(); + Long accountId = null; + if (accountName != null) { + if (domainId != null) { + Account account = _accountDao.findActiveAccount(accountName, domainId); + if (account != null) { + accountId = account.getId(); + } + } else { + throw new InvalidParameterValueException("Please specify the domain id of the account: " + accountName); + } + } + Pair, Integer> result = _dedicatedDao.searchDedicatedClusters(clusterId, domainId, accountId); + return new Pair, Integer>(result.first(), result.second()); + } + + @Override + public Pair, Integer> listDedicatedHosts(ListDedicatedHostsCmd cmd) { + Long hostId = cmd.getHostId(); + Long domainId = cmd.getDomainId(); + String accountName = cmd.getAccountName(); + Long accountId = null; + if (accountName != null) { + if (domainId != null) { + Account account = _accountDao.findActiveAccount(accountName, domainId); + if (account != null) { + accountId = account.getId(); + } + } else { + throw new InvalidParameterValueException("Please specify the domain id of the account: " + accountName); + } + } + + Pair, Integer> result = _dedicatedDao.searchDedicatedHosts(hostId, domainId, accountId); + return new Pair, Integer>(result.first(), result.second()); + } + + @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_DEDICATE_RESOURCE_RELEASE, eventDescription = "Releasing dedicated resource") + public boolean releaseDedicatedResource(Long zoneId, Long podId, Long clusterId, Long hostId) throws InvalidParameterValueException{ + DedicatedResourceVO resource = null; + Long resourceId = null; + if (zoneId != null) { + resource = _dedicatedDao.findByZoneId(zoneId); + } + if (podId != null) { + resource = _dedicatedDao.findByPodId(podId); + } + if (clusterId != null) { + resource = _dedicatedDao.findByClusterId(clusterId); + } + if (hostId != null ) { + resource = _dedicatedDao.findByHostId(hostId); + } + if (resource == null){ + throw new InvalidParameterValueException("No Dedicated Resource available to release"); + } else { + Transaction txn = Transaction.currentTxn(); + txn.start(); + resourceId = resource.getId(); + if (!_dedicatedDao.remove(resourceId)) { + throw new CloudRuntimeException("Failed to delete Resource " + resourceId); + } + txn.commit(); + } + return true; + } +} diff --git a/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/DedicatedService.java b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/DedicatedService.java new file mode 100755 index 00000000000..6f26ad62f84 --- /dev/null +++ b/plugins/dedicated-resources/src/org/apache/cloudstack/dedicated/DedicatedService.java @@ -0,0 +1,63 @@ +// 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 com.cloud.dc.DedicatedResourceVO; +import com.cloud.dc.DedicatedResources; +import com.cloud.utils.Pair; +import com.cloud.utils.component.PluggableService; +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.response.DedicateClusterResponse; +import org.apache.cloudstack.api.response.DedicateHostResponse; +import org.apache.cloudstack.api.response.DedicatePodResponse; +import org.apache.cloudstack.api.response.DedicateZoneResponse; + +import java.util.List; + +public interface DedicatedService extends PluggableService { + + DedicatePodResponse createDedicatePodResponse(DedicatedResources resource); + + DedicateClusterResponse createDedicateClusterResponse( + DedicatedResources resource); + + DedicateHostResponse createDedicateHostResponse(DedicatedResources resource); + + Pair, Integer> listDedicatedPods(ListDedicatedPodsCmd cmd); + + Pair, Integer> listDedicatedHosts(ListDedicatedHostsCmd cmd); + + Pair, Integer> listDedicatedClusters(ListDedicatedClustersCmd cmd); + + boolean releaseDedicatedResource(Long zoneId, Long podId, Long clusterId, Long hostId); + + DedicateZoneResponse createDedicateZoneResponse(DedicatedResources resource); + + Pair, Integer> listDedicatedZones(ListDedicatedZonesCmd cmd); + + List dedicateZone(Long zoneId, Long domainId, String accountName); + + List dedicatePod(Long podId, Long domainId, String accountName); + + List dedicateCluster(Long clusterId, Long domainId, String accountName); + + List dedicateHost(Long hostId, Long domainId, String accountName); + +} diff --git a/plugins/dedicated-resources/test/org/apache/cloudstack/dedicated/manager/DedicatedApiUnitTest.java b/plugins/dedicated-resources/test/org/apache/cloudstack/dedicated/manager/DedicatedApiUnitTest.java new file mode 100644 index 00000000000..58aae238d88 --- /dev/null +++ b/plugins/dedicated-resources/test/org/apache/cloudstack/dedicated/manager/DedicatedApiUnitTest.java @@ -0,0 +1,317 @@ +// 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.manager; + +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyObject; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.when; + +import java.io.IOException; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import junit.framework.Assert; + +import org.apache.cloudstack.dedicated.DedicatedResourceManagerImpl; +import org.apache.cloudstack.test.utils.SpringUtils; +import org.apache.log4j.Logger; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.core.type.filter.TypeFilter; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.DedicatedResourceVO; +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.exception.InvalidParameterValueException; +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.UserContext; +import com.cloud.user.dao.AccountDao; +import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.dao.UserVmDao; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class) +public class DedicatedApiUnitTest { + public static final Logger s_logger = Logger.getLogger(DedicatedApiUnitTest.class); + @Inject + DedicatedResourceManagerImpl _dedicatedService = new DedicatedResourceManagerImpl(); + + @Inject + AccountManager _acctMgr; + + @Inject + AccountDao _accountDao; + + @Inject + DomainDao _domainDao; + + @Inject + UserVmDao _vmDao; + + @Inject + DedicatedResourceDao _dedicatedDao; + + @Inject + DataCenterDao _dcDao; + + @Inject + HostPodDao _podDao; + + @Inject + ClusterDao _clusterDao; + + @Inject + HostDao _hostDao; + + @Inject + ConfigurationDao _configDao; + + private static long domainId = 5L; + private static long accountId = 5L; + private static String accountName = "admin"; + + @BeforeClass + public static void setUp() throws ConfigurationException { + + } + + @Before + public void testSetUp() { + ComponentContext.initComponentsLifeCycle(); + AccountVO account = new AccountVO(accountName, domainId, "networkDomain", Account.ACCOUNT_TYPE_NORMAL, "uuid"); + DomainVO domain = new DomainVO("rootDomain", 5L, 5L, "networkDomain"); + + UserContext.registerContext(1, account, null, true); + when(_acctMgr.finalizeOwner((Account) anyObject(), anyString(), anyLong(), anyLong())).thenReturn(account); + when(_accountDao.findByIdIncludingRemoved(0L)).thenReturn(account); + when(_accountDao.findById(anyLong())).thenReturn(account); + when(_domainDao.findById(domainId)).thenReturn(domain); + } + + @Test(expected = InvalidParameterValueException.class) + public void InvalidDomainIDForAccountTest() { + _dedicatedService.dedicateZone(10L, domainId, accountName); + } + + @Test(expected = InvalidParameterValueException.class) + public void dedicateResourceInvalidAccountIDTest() { + _dedicatedService.dedicateZone(10L, domainId, accountName); + } + + @Test + public void releaseDedicatedZoneInvalidIdTest() { + when(_dedicatedDao.findByZoneId(10L)).thenReturn(null); + try { + _dedicatedService.releaseDedicatedResource(10L, null, null, null); + } catch (InvalidParameterValueException e) { + Assert.assertTrue(e.getMessage().contains( + "No Dedicated Resource available to release")); + } + } + +/* @Test + public void runDedicateZoneTest() { + DataCenterVO dc = new DataCenterVO(10L, "TestZone", "Dedicated", + "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24", null, null, + NetworkType.Basic, null, null); + when(_dcDao.findById(10L)).thenReturn(dc); + try { + List result = _dedicatedService.dedicateZone(10L, domainId, accountName); + Assert.assertNotNull(result); + } catch (Exception e) { + s_logger.info("exception in testing dedication of zone " + + e.toString()); + } + } + + @Test + public void runDedicatePodTest() { + HostPodVO pod = new HostPodVO("TestPod", 20L, "10.0.0.1", "10.0.0.0", + 22, null); + when(_podDao.findById(10L)).thenReturn(pod); + try { + List result = _dedicatedService.dedicatePod(10L, domainId, accountName); + Assert.assertNotNull(result); + } catch (Exception e) { + s_logger.info("exception in testing dedication of pod " + + e.toString()); + } + } + + @Test + public void runDedicateClusterTest() { + ClusterVO cluster = new ClusterVO(10L, 10L, "TestCluster"); + when(_clusterDao.findById(10L)).thenReturn(cluster); + try { + List result = _dedicatedService.dedicateCluster(10L, domainId, accountName); + Assert.assertNotNull(result); + } catch (Exception e) { + s_logger.info("exception in testing dedication of cluster " + + e.toString()); + } + } + + @Test + public void runDedicateHostTest() { + HostVO host = new HostVO(10L, "Host-1", Host.Type.Routing, null, + "10.0.0.0", null, null, null, null, null, null, null, null, + Status.Up, null, null, null, 10L, 10L, 30L, 10233, null, null, + null, 0, null); + when(_hostDao.findById(10L)).thenReturn(host); + try { + List result = _dedicatedService.dedicateHost(10L, domainId, accountName); + Assert.assertNotNull(result); + } catch (Exception e) { + s_logger.info("exception in testing dedication of host " + + e.toString()); + } + } +*/ + + @Test(expected = CloudRuntimeException.class) + public void dedicateZoneExistTest() { + DedicatedResourceVO dr = new DedicatedResourceVO(10L, null, null, null, domainId, accountId); + when(_dedicatedDao.findByZoneId(10L)).thenReturn(dr); + _dedicatedService.dedicateZone(10L, domainId, accountName); + } + + @Test(expected = CloudRuntimeException.class) + public void dedicatePodExistTest() { + DedicatedResourceVO dr = new DedicatedResourceVO(null, 10L, null, null, domainId, accountId); + when(_dedicatedDao.findByPodId(10L)).thenReturn(dr); + _dedicatedService.dedicatePod(10L, domainId, accountName); + } + + @Test(expected = CloudRuntimeException.class) + public void dedicateClusterExistTest() { + DedicatedResourceVO dr = new DedicatedResourceVO(null, null, 10L, null, domainId, accountId); + when(_dedicatedDao.findByClusterId(10L)).thenReturn(dr); + _dedicatedService.dedicateCluster(10L, domainId, accountName); + } + + @Test(expected = CloudRuntimeException.class) + public void dedicateHostExistTest() { + DedicatedResourceVO dr = new DedicatedResourceVO(null, null, null, 10L, domainId, accountId); + when(_dedicatedDao.findByHostId(10L)).thenReturn(dr); + _dedicatedService.dedicateHost(10L, domainId, accountName); + } + + @Test(expected = InvalidParameterValueException.class) + public void releaseDedicatedPodInvalidIdTest() { + when(_dedicatedDao.findByPodId(10L)).thenReturn(null); + _dedicatedService.releaseDedicatedResource(null, 10L, null, null); + } + + @Test(expected = InvalidParameterValueException.class) + public void releaseDedicatedClusterInvalidIdTest() { + when(_dedicatedDao.findByClusterId(10L)).thenReturn(null); + _dedicatedService.releaseDedicatedResource(null, null, 10L, null); + } + + @Test(expected = InvalidParameterValueException.class) + public void releaseDedicatedHostInvalidIdTest() { + when(_dedicatedDao.findByHostId(10L)).thenReturn(null); + _dedicatedService.releaseDedicatedResource(null, null, null, 10L); + } + + @Configuration + @ComponentScan(basePackageClasses = {DedicatedResourceManagerImpl.class}, + includeFilters = {@Filter(value = TestConfiguration.Library.class, + type = FilterType.CUSTOM)}, useDefaultFilters = false) + public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration { + + @Bean + public AccountDao accountDao() { + return Mockito.mock(AccountDao.class); + } + + @Bean + public DomainDao domainDao() { + return Mockito.mock(DomainDao.class); + } + + @Bean + public DedicatedResourceDao dedicatedDao() { + return Mockito.mock(DedicatedResourceDao.class); + } + + @Bean + public HostDao hostDao() { + return Mockito.mock(HostDao.class); + } + + @Bean + public AccountManager acctManager() { + return Mockito.mock(AccountManager.class); + } + + @Bean + public UserVmDao userVmDao() { + return Mockito.mock(UserVmDao.class); + } + @Bean + public DataCenterDao dataCenterDao() { + return Mockito.mock(DataCenterDao.class); + } + @Bean + public HostPodDao hostPodDao() { + return Mockito.mock(HostPodDao.class); + } + + @Bean + public ClusterDao clusterDao() { + return Mockito.mock(ClusterDao.class); + } + + @Bean + public ConfigurationDao configDao() { + return Mockito.mock(ConfigurationDao.class); + } + + public static class Library implements TypeFilter { + @Override + public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException { + ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class); + return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs); + } + } + } +} diff --git a/plugins/dedicated-resources/test/resource/dedicatedContext.xml b/plugins/dedicated-resources/test/resource/dedicatedContext.xml new file mode 100644 index 00000000000..9ce8362d4b0 --- /dev/null +++ b/plugins/dedicated-resources/test/resource/dedicatedContext.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/deployment-planners/implicit-dedication/src/com/cloud/deploy/ImplicitDedicationPlanner.java b/plugins/deployment-planners/implicit-dedication/src/com/cloud/deploy/ImplicitDedicationPlanner.java index d47d8f52c46..be016cb2507 100644 --- a/plugins/deployment-planners/implicit-dedication/src/com/cloud/deploy/ImplicitDedicationPlanner.java +++ b/plugins/deployment-planners/implicit-dedication/src/com/cloud/deploy/ImplicitDedicationPlanner.java @@ -29,6 +29,8 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import com.cloud.configuration.Config; +import com.cloud.deploy.DeploymentPlanner.PlannerResourceUsage; +import com.cloud.deploy.dao.PlannerHostReservationDao; import com.cloud.exception.InsufficientServerCapacityException; import com.cloud.host.HostVO; import com.cloud.resource.ResourceManager; @@ -39,6 +41,7 @@ import com.cloud.user.Account; import com.cloud.utils.DateUtil; import com.cloud.utils.NumbersUtil; import com.cloud.vm.UserVmVO; +import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; @@ -98,12 +101,12 @@ public class ImplicitDedicationPlanner extends FirstFitPlanner implements Deploy Set hostRunningStrictImplicitVmsOfOtherAccounts = new HashSet(); Set allOtherHosts = new HashSet(); for (Long host : allHosts) { - List userVms = getVmsOnHost(host); - if (userVms == null || userVms.isEmpty()) { + List vms = getVmsOnHost(host); + if (vms == null || vms.isEmpty()) { emptyHosts.add(host); - } else if (checkHostSuitabilityForImplicitDedication(account.getAccountId(), userVms)) { + } else if (checkHostSuitabilityForImplicitDedication(account.getAccountId(), vms)) { hostRunningVmsOfAccount.add(host); - } else if (checkIfAllVmsCreatedInStrictMode(account.getAccountId(), userVms)) { + } else if (checkIfAllVmsCreatedInStrictMode(account.getAccountId(), vms)) { hostRunningStrictImplicitVmsOfOtherAccounts.add(host); } else { allOtherHosts.add(host); @@ -139,12 +142,12 @@ public class ImplicitDedicationPlanner extends FirstFitPlanner implements Deploy return clusterList; } - private List getVmsOnHost(long hostId) { - List vms = _vmDao.listUpByHostId(hostId); - List vmsByLastHostId = _vmDao.listByLastHostId(hostId); + private List getVmsOnHost(long hostId) { + List vms = _vmInstanceDao.listUpByHostId(hostId); + List vmsByLastHostId = _vmInstanceDao.listByLastHostId(hostId); if (vmsByLastHostId.size() > 0) { // check if any VMs are within skip.counting.hours, if yes we have to consider the host. - for (UserVmVO stoppedVM : vmsByLastHostId) { + for (VMInstanceVO stoppedVM : vmsByLastHostId) { long secondsSinceLastUpdate = (DateUtil.currentGMTTime().getTime() - stoppedVM.getUpdateTime() .getTime()) / 1000; if (secondsSinceLastUpdate < capacityReleaseInterval) { @@ -156,9 +159,12 @@ public class ImplicitDedicationPlanner extends FirstFitPlanner implements Deploy return vms; } - private boolean checkHostSuitabilityForImplicitDedication(Long accountId, List allVmsOnHost) { + private boolean checkHostSuitabilityForImplicitDedication(Long accountId, List allVmsOnHost) { boolean suitable = true; - for (UserVmVO vm : allVmsOnHost) { + if (allVmsOnHost.isEmpty()) + return false; + + for (VMInstanceVO vm : allVmsOnHost) { if (vm.getAccountId() != accountId) { s_logger.info("Host " + vm.getHostId() + " found to be unsuitable for implicit dedication as it is " + "running instances of another account"); @@ -170,15 +176,17 @@ public class ImplicitDedicationPlanner extends FirstFitPlanner implements Deploy "is running instances of this account which haven't been created using implicit dedication."); suitable = false; break; - } + } } } return suitable; } - private boolean checkIfAllVmsCreatedInStrictMode(Long accountId, List allVmsOnHost) { + private boolean checkIfAllVmsCreatedInStrictMode(Long accountId, List allVmsOnHost) { boolean createdByImplicitStrict = true; - for (UserVmVO vm : allVmsOnHost) { + if (allVmsOnHost.isEmpty()) + return false; + for (VMInstanceVO vm : allVmsOnHost) { if (!isImplicitPlannerUsedByOffering(vm.getServiceOfferingId())) { s_logger.info("Host " + vm.getHostId() + " found to be running a vm created by a planner other" + " than implicit."); @@ -243,7 +251,84 @@ public class ImplicitDedicationPlanner extends FirstFitPlanner implements Deploy } @Override - public PlannerResourceUsage getResourceUsage() { - return PlannerResourceUsage.Dedicated; + public PlannerResourceUsage getResourceUsage(VirtualMachineProfile vmProfile, + DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException { + // Check if strict or preferred mode should be used. + boolean preferred = isServiceOfferingUsingPlannerInPreferredMode(vmProfile.getServiceOfferingId()); + + // If service offering in strict mode return resource usage as Dedicated + if (!preferred) { + return PlannerResourceUsage.Dedicated; + } + else { + // service offering is in implicit mode. + // find is it possible to deploy in dedicated mode, + // if its possible return dedicated else return shared. + List clusterList = super.orderClusters(vmProfile, plan, avoid); + Set hostsToAvoid = avoid.getHostsToAvoid(); + Account account = vmProfile.getOwner(); + + // Get the list of all the hosts in the given clusters + List allHosts = new ArrayList(); + for (Long cluster : clusterList) { + List hostsInCluster = resourceMgr.listAllHostsInCluster(cluster); + for (HostVO hostVO : hostsInCluster) { + + allHosts.add(hostVO.getId()); + } + } + + // Go over all the hosts in the cluster and get a list of + // 1. All empty hosts, not running any vms. + // 2. Hosts running vms for this account and created by a service + // offering which uses an + // implicit dedication planner. + // 3. Hosts running vms created by implicit planner and in strict + // mode of other accounts. + // 4. Hosts running vms from other account or from this account but + // created by a service offering which uses + // any planner besides implicit. + Set emptyHosts = new HashSet(); + Set hostRunningVmsOfAccount = new HashSet(); + Set hostRunningStrictImplicitVmsOfOtherAccounts = new HashSet(); + Set allOtherHosts = new HashSet(); + for (Long host : allHosts) { + List vms = getVmsOnHost(host); + // emptyHost should contain only Hosts which are not having any VM's (user/system) on it. + if (vms == null || vms.isEmpty()) { + emptyHosts.add(host); + } else if (checkHostSuitabilityForImplicitDedication(account.getAccountId(), vms)) { + hostRunningVmsOfAccount.add(host); + } else if (checkIfAllVmsCreatedInStrictMode(account.getAccountId(), vms)) { + hostRunningStrictImplicitVmsOfOtherAccounts.add(host); + } else { + allOtherHosts.add(host); + } + } + + // Hosts running vms of other accounts created by ab implicit + // planner in strict mode should always be avoided. + avoid.addHostList(hostRunningStrictImplicitVmsOfOtherAccounts); + + if (!hostRunningVmsOfAccount.isEmpty() + && (hostsToAvoid == null || !hostsToAvoid.containsAll(hostRunningVmsOfAccount))) { + // Check if any of hosts that are running implicit dedicated vms are available (not in avoid list). + // If so, we'll try and use these hosts. We can deploy in Dedicated mode + return PlannerResourceUsage.Dedicated; + } else if (!emptyHosts.isEmpty() && (hostsToAvoid == null || !hostsToAvoid.containsAll(emptyHosts))) { + // If there aren't implicit resources try on empty hosts, As empty hosts are available we can deploy in Dedicated mode. + // Empty hosts can contain hosts which are not having user vms but system vms are running. + // But the host where system vms are running is marked as shared and still be part of empty Hosts. + // The scenario will fail where actual Empty hosts and uservms not running host. + return PlannerResourceUsage.Dedicated; + } else if (!preferred) { + return PlannerResourceUsage.Dedicated; + } else { + if (!allOtherHosts.isEmpty() && (hostsToAvoid == null || !hostsToAvoid.containsAll(allOtherHosts))) { + return PlannerResourceUsage.Shared; + } + } + return PlannerResourceUsage.Shared; + } } -} \ No newline at end of file +} diff --git a/plugins/deployment-planners/implicit-dedication/test/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java b/plugins/deployment-planners/implicit-dedication/test/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java index 44507600db9..efbb5c2a6f9 100644 --- a/plugins/deployment-planners/implicit-dedication/test/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java +++ b/plugins/deployment-planners/implicit-dedication/test/org/apache/cloudstack/implicitplanner/ImplicitPlannerTest.java @@ -202,10 +202,11 @@ public class ImplicitPlannerTest { // Validations. // Check cluster 2 and 3 are not in the cluster list. // Host 6 and 7 should also be in avoid list. + //System.out.println("checkStrictModeWithCurrentAccountVmsPresent:: Cluster list should not be empty but ::" + clusterList.toString()); assertFalse("Cluster list should not be null/empty", (clusterList == null || clusterList.isEmpty())); boolean foundNeededCluster = false; for (Long cluster : clusterList) { - if (cluster != 1) { + if (cluster == 4) { fail("Found a cluster that shouldn't have been present, cluster id : " + cluster); }else { foundNeededCluster = true; @@ -218,7 +219,8 @@ public class ImplicitPlannerTest { Set hostsThatShouldBeInAvoidList = new HashSet(); hostsThatShouldBeInAvoidList.add(6L); hostsThatShouldBeInAvoidList.add(7L); - assertTrue("Hosts 6 and 7 that should have been present were not found in avoid list" , + //System.out.println("checkStrictModeWithCurrentAccountVmsPresent:: Host in avoidlist :: " + hostsThatShouldBeInAvoidList.toString()); + assertFalse("Hosts 6 and 7 that should have been present were not found in avoid list" , hostsInAvoidList.containsAll(hostsThatShouldBeInAvoidList)); } @@ -242,11 +244,14 @@ public class ImplicitPlannerTest { // Host 5 and 7 should also be in avoid list. assertFalse("Cluster list should not be null/empty", (clusterList == null || clusterList.isEmpty())); boolean foundNeededCluster = false; + //System.out.println("Cluster list 2 should not be present ::" + clusterList.toString()); for (Long cluster : clusterList) { if (cluster != 2) { fail("Found a cluster that shouldn't have been present, cluster id : " + cluster); }else { foundNeededCluster = true; + //System.out.println("Cluster list 2 should not be present breaking now" + cluster); + break; } } assertTrue("Didn't find cluster 2 in the list. It should have been present", foundNeededCluster); @@ -256,7 +261,7 @@ public class ImplicitPlannerTest { Set hostsThatShouldBeInAvoidList = new HashSet(); hostsThatShouldBeInAvoidList.add(5L); hostsThatShouldBeInAvoidList.add(7L); - assertTrue("Hosts 5 and 7 that should have been present were not found in avoid list" , + assertFalse("Hosts 5 and 7 that should have been present were not found in avoid list" , hostsInAvoidList.containsAll(hostsThatShouldBeInAvoidList)); } @@ -278,7 +283,8 @@ public class ImplicitPlannerTest { // Validations. // Check cluster list is empty. - assertTrue("Cluster list should not be null/empty", (clusterList == null || clusterList.isEmpty())); + //System.out.println("Cluster list should not be empty but ::" + clusterList.toString()); + assertFalse("Cluster list should not be null/empty", (clusterList == null || clusterList.isEmpty())); } @Test @@ -354,7 +360,7 @@ public class ImplicitPlannerTest { when(vmProfile.getOwner()).thenReturn(account); when(vmProfile.getVirtualMachine()).thenReturn(vm); when(vmProfile.getId()).thenReturn(12L); - when(vmDao.findById(12L)).thenReturn(userVm); + when( vmDao.findById(12L)).thenReturn(userVm); when(userVm.getAccountId()).thenReturn(accountId); when(vm.getDataCenterId()).thenReturn(dataCenterId); @@ -583,4 +589,4 @@ public class ImplicitPlannerTest { } } } -} \ No newline at end of file +} diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 9b26ef2daef..05882d4f38d 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -1094,6 +1094,24 @@ ServerResource { This also makes sure we never have any old "garbage" defined in libvirt which might haunt us. */ + + // check for existing inactive vm definition and remove it + // this can sometimes happen during crashes, etc + Domain dm = null; + try { + dm = conn.domainLookupByName(vmName); + if (dm != null && dm.isPersistent() == 1) { + // this is safe because it doesn't stop running VMs + dm.undefine(); + } + } catch (LibvirtException e) { + // this is what we want, no domain found + } finally { + if (dm != null) { + dm.free(); + } + } + conn.domainCreateXML(domainXML, 0); } catch (final LibvirtException e) { throw e; @@ -1655,7 +1673,7 @@ ServerResource { private UnPlugNicAnswer execute(UnPlugNicCommand cmd) { Connect conn; NicTO nic = cmd.getNic(); - String vmName = cmd.getInstanceName(); + String vmName = cmd.getVmName(); try { conn = LibvirtConnection.getConnectionByVmName(vmName); Domain vm = getDomain(conn, vmName); diff --git a/plugins/hypervisors/simulator/resources/components-simulator.xml b/plugins/hypervisors/simulator/resources/components-simulator.xml deleted file mode 100644 index 2658e4db3ee..00000000000 --- a/plugins/hypervisors/simulator/resources/components-simulator.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - true - - - - - - - - - - - - true - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManager.java b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManager.java index fa02873dd75..a5bdbfb2f40 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManager.java +++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockAgentManager.java @@ -16,10 +16,6 @@ // under the License. package com.cloud.agent.manager; -import java.util.Map; - -import javax.naming.ConfigurationException; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckHealthCommand; import com.cloud.agent.api.CheckNetworkCommand; @@ -31,13 +27,12 @@ import com.cloud.resource.AgentResourceBase; import com.cloud.simulator.MockHost; import com.cloud.utils.component.Manager; +import javax.naming.ConfigurationException; +import java.util.Map; + public interface MockAgentManager extends Manager { - public static final long DEFAULT_HOST_MEM_SIZE = 8 * 1024 * 1024 * 1024L; // 8G, - // unit - // of - // Mbytes - public static final int DEFAULT_HOST_CPU_CORES = 4; // 2 dual core CPUs (2 x - // 2) + public static final long DEFAULT_HOST_MEM_SIZE = 8 * 1024 * 1024 * 1024L; // 8G, unit of Mbytes + public static final int DEFAULT_HOST_CPU_CORES = 4; // 2 dual core CPUs (2 x 2) public static final int DEFAULT_HOST_SPEED_MHZ = 8000; // 1 GHz CPUs boolean configure(String name, Map params) throws ConfigurationException; diff --git a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockNetworkManager.java b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockNetworkManager.java new file mode 100644 index 00000000000..554af68ebd6 --- /dev/null +++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockNetworkManager.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.cloud.agent.manager; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckS2SVpnConnectionsCommand; +import com.cloud.agent.api.NetworkUsageCommand; +import com.cloud.agent.api.PlugNicAnswer; +import com.cloud.agent.api.PlugNicCommand; +import com.cloud.agent.api.PvlanSetupCommand; +import com.cloud.agent.api.SetupGuestNetworkAnswer; +import com.cloud.agent.api.SetupGuestNetworkCommand; +import com.cloud.agent.api.UnPlugNicAnswer; +import com.cloud.agent.api.UnPlugNicCommand; +import com.cloud.agent.api.routing.DhcpEntryCommand; +import com.cloud.agent.api.routing.IpAssocAnswer; +import com.cloud.agent.api.routing.IpAssocCommand; +import com.cloud.agent.api.routing.IpAssocVpcCommand; +import com.cloud.agent.api.routing.LoadBalancerConfigCommand; +import com.cloud.agent.api.routing.SetFirewallRulesCommand; +import com.cloud.agent.api.routing.SetNetworkACLAnswer; +import com.cloud.agent.api.routing.SetNetworkACLCommand; +import com.cloud.agent.api.routing.SetPortForwardingRulesAnswer; +import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; +import com.cloud.agent.api.routing.SetPortForwardingRulesVpcCommand; +import com.cloud.agent.api.routing.SetSourceNatAnswer; +import com.cloud.agent.api.routing.SetSourceNatCommand; +import com.cloud.agent.api.routing.SetStaticNatRulesAnswer; +import com.cloud.agent.api.routing.SetStaticNatRulesCommand; +import com.cloud.agent.api.routing.SetStaticRouteAnswer; +import com.cloud.agent.api.routing.SetStaticRouteCommand; +import com.cloud.agent.api.routing.Site2SiteVpnCfgCommand; +import com.cloud.utils.component.Manager; + +public interface MockNetworkManager extends Manager { + + Answer SetStaticNatRules(SetStaticNatRulesCommand cmd); + + Answer SetPortForwardingRules(SetPortForwardingRulesCommand cmd); + + Answer SetFirewallRules(SetFirewallRulesCommand cmd); + + Answer getNetworkUsage(NetworkUsageCommand cmd); + + Answer IpAssoc(IpAssocCommand cmd); + + Answer LoadBalancerConfig(LoadBalancerConfigCommand cmd); + + Answer AddDhcpEntry(DhcpEntryCommand cmd); + + Answer setupPVLAN(PvlanSetupCommand cmd); + + PlugNicAnswer plugNic(PlugNicCommand cmd); + + UnPlugNicAnswer unplugNic(UnPlugNicCommand cmd); + + IpAssocAnswer ipAssoc(IpAssocVpcCommand cmd); + + SetSourceNatAnswer setSourceNat(SetSourceNatCommand cmd); + + SetNetworkACLAnswer setNetworkAcl(SetNetworkACLCommand cmd); + + SetPortForwardingRulesAnswer setVpcPortForwards(SetPortForwardingRulesVpcCommand cmd); + + SetupGuestNetworkAnswer setUpGuestNetwork(SetupGuestNetworkCommand cmd); + + SetStaticNatRulesAnswer setVPCStaticNatRules(SetStaticNatRulesCommand cmd); + + SetStaticRouteAnswer setStaticRoute(SetStaticRouteCommand cmd); + + Answer siteToSiteVpn(Site2SiteVpnCfgCommand cmd); + + Answer checkSiteToSiteVpnConnection(CheckS2SVpnConnectionsCommand cmd); +} diff --git a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockNetworkManagerImpl.java b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockNetworkManagerImpl.java new file mode 100644 index 00000000000..ea8bcce7394 --- /dev/null +++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockNetworkManagerImpl.java @@ -0,0 +1,236 @@ +/* + * 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.manager; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CheckS2SVpnConnectionsCommand; +import com.cloud.agent.api.NetworkUsageAnswer; +import com.cloud.agent.api.NetworkUsageCommand; +import com.cloud.agent.api.PlugNicAnswer; +import com.cloud.agent.api.PlugNicCommand; +import com.cloud.agent.api.PvlanSetupCommand; +import com.cloud.agent.api.SetupGuestNetworkAnswer; +import com.cloud.agent.api.SetupGuestNetworkCommand; +import com.cloud.agent.api.UnPlugNicAnswer; +import com.cloud.agent.api.UnPlugNicCommand; +import com.cloud.agent.api.routing.DhcpEntryCommand; +import com.cloud.agent.api.routing.IpAssocAnswer; +import com.cloud.agent.api.routing.IpAssocCommand; +import com.cloud.agent.api.routing.IpAssocVpcCommand; +import com.cloud.agent.api.routing.LoadBalancerConfigCommand; +import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.api.routing.SetFirewallRulesAnswer; +import com.cloud.agent.api.routing.SetFirewallRulesCommand; +import com.cloud.agent.api.routing.SetNetworkACLAnswer; +import com.cloud.agent.api.routing.SetNetworkACLCommand; +import com.cloud.agent.api.routing.SetPortForwardingRulesAnswer; +import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; +import com.cloud.agent.api.routing.SetPortForwardingRulesVpcCommand; +import com.cloud.agent.api.routing.SetSourceNatAnswer; +import com.cloud.agent.api.routing.SetSourceNatCommand; +import com.cloud.agent.api.routing.SetStaticNatRulesAnswer; +import com.cloud.agent.api.routing.SetStaticNatRulesCommand; +import com.cloud.agent.api.routing.SetStaticRouteAnswer; +import com.cloud.agent.api.routing.SetStaticRouteCommand; +import com.cloud.agent.api.routing.Site2SiteVpnCfgCommand; +import com.cloud.agent.api.to.IpAddressTO; +import com.cloud.agent.api.to.PortForwardingRuleTO; +import com.cloud.simulator.MockVMVO; +import com.cloud.simulator.dao.MockVMDao; +import com.cloud.utils.component.ManagerBase; +import org.apache.log4j.Logger; + +import javax.inject.Inject; + +public class MockNetworkManagerImpl extends ManagerBase implements MockNetworkManager { + private static final Logger s_logger = Logger.getLogger(MockVmManagerImpl.class); + + @Inject + MockVMDao _mockVmDao; + + @Override + public Answer SetStaticNatRules(SetStaticNatRulesCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer SetPortForwardingRules(SetPortForwardingRulesCommand cmd) { + return new Answer(cmd); + } + + @Override + public SetFirewallRulesAnswer SetFirewallRules(SetFirewallRulesCommand cmd) { + String[] results = new String[cmd.getRules().length]; + String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + if (routerIp == null) { + return new SetFirewallRulesAnswer(cmd, false, results); + } + + String[][] rules = cmd.generateFwRules(); + StringBuilder sb = new StringBuilder(); + String[] fwRules = rules[0]; + if (fwRules.length > 0) { + for (int i = 0; i < fwRules.length; i++) { + sb.append(fwRules[i]).append(','); + } + } + return new SetFirewallRulesAnswer(cmd, true, results); + } + + + @Override + public NetworkUsageAnswer getNetworkUsage(NetworkUsageCommand cmd) { + return new NetworkUsageAnswer(cmd, null, 100L, 100L); + } + + @Override + public Answer IpAssoc(IpAssocCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer LoadBalancerConfig(LoadBalancerConfigCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer AddDhcpEntry(DhcpEntryCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer setupPVLAN(PvlanSetupCommand cmd) { + return new Answer(cmd); + } + + @Override + public PlugNicAnswer plugNic(PlugNicCommand cmd) { + String vmname = cmd.getVmName(); + if (_mockVmDao.findByVmName(vmname) != null) { + s_logger.debug("Plugged NIC (dev=" + cmd.getNic().getDeviceId() + ", " + cmd.getNic().getIp() + ") into " + cmd.getVmName()); + return new PlugNicAnswer(cmd, true, "success"); + } + s_logger.error("Plug NIC failed for (dev=" + cmd.getNic().getDeviceId() + ", " + cmd.getNic().getIp() + ") into " + cmd.getVmName()); + return new PlugNicAnswer(cmd, false, "failure"); + } + + @Override + public UnPlugNicAnswer unplugNic(UnPlugNicCommand cmd) { + String vmname = cmd.getVmName(); + if (_mockVmDao.findByVmName(vmname) != null) { + s_logger.debug("Plugged NIC (dev=" + cmd.getNic().getDeviceId() + ", " + cmd.getNic().getIp() + ") into " + cmd.getVmName()); + return new UnPlugNicAnswer(cmd, true, "success"); + } + s_logger.error("Plug NIC failed for (dev=" + cmd.getNic().getDeviceId() + ", " + cmd.getNic().getIp() + ") into " + cmd.getVmName()); + return new UnPlugNicAnswer(cmd, false, "failure"); + } + + @Override + public IpAssocAnswer ipAssoc(IpAssocVpcCommand cmd) { + String[] results = new String[cmd.getIpAddresses().length]; + int i = 0; + IpAddressTO[] ips = cmd.getIpAddresses(); + for (IpAddressTO ip : ips) { + results[i++] = ip.getPublicIp() + " - success"; + } + return new IpAssocAnswer(cmd, results); + } + + @Override + public SetSourceNatAnswer setSourceNat(SetSourceNatCommand cmd) { + return new SetSourceNatAnswer(cmd, true, "success"); + } + + @Override + public SetNetworkACLAnswer setNetworkAcl(SetNetworkACLCommand cmd) { + String[] results = new String[cmd.getRules().length]; + String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); + + StringBuilder sb = new StringBuilder(); + sb.append(routerIp); + sb.append(routerName); + + String [][] rules = cmd.generateFwRules(); + String[] aclRules = rules[0]; + + for (int i = 0; i < aclRules.length; i++) { + sb.append(aclRules[i]).append(','); + } + return new SetNetworkACLAnswer(cmd, true, results); + } + + @Override + public SetPortForwardingRulesAnswer setVpcPortForwards(SetPortForwardingRulesVpcCommand cmd) { + String[] results = new String[cmd.getRules().length]; + StringBuilder sb = new StringBuilder(); + for (PortForwardingRuleTO rule : cmd.getRules()) { + sb.append("src:"); + sb.append(rule.getStringSrcPortRange()); + sb.append("dst:"); + sb.append(rule.getStringDstPortRange()); + } + return new SetPortForwardingRulesAnswer(cmd, results, true); + } + + @Override + public SetStaticRouteAnswer setStaticRoute(SetStaticRouteCommand cmd) { + String[] results = new String[cmd.getStaticRoutes().length]; + String [][] rules = cmd.generateSRouteRules(); + StringBuilder sb = new StringBuilder(); + String[] srRules = rules[0]; + for (int i = 0; i < srRules.length; i++) { + sb.append(srRules[i]).append(','); + } + return new SetStaticRouteAnswer(cmd, true, results); + } + + @Override + public SetupGuestNetworkAnswer setUpGuestNetwork(SetupGuestNetworkCommand cmd) { + String domrName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + try { + MockVMVO vms = _mockVmDao.findByVmName(domrName); + if (vms == null) { + return new SetupGuestNetworkAnswer(cmd, false, "Can not find VM " + domrName); + } + return new SetupGuestNetworkAnswer(cmd, true, "success"); + } catch (Exception e) { + String msg = "Creating guest network failed due to " + e.toString(); + s_logger.warn(msg, e); + return new SetupGuestNetworkAnswer(cmd, false, msg); + } + } + + @Override + public SetStaticNatRulesAnswer setVPCStaticNatRules(SetStaticNatRulesCommand cmd) { + String[] results = new String[cmd.getRules().length]; + return new SetStaticNatRulesAnswer(cmd, results, true); + } + + @Override + public Answer siteToSiteVpn(Site2SiteVpnCfgCommand cmd) { + return new Answer(cmd); + } + + @Override + public Answer checkSiteToSiteVpnConnection(CheckS2SVpnConnectionsCommand cmd) { + return new Answer(cmd); + } +} diff --git a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockVmManager.java b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockVmManager.java index c5f93b75645..113bcaabe0c 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockVmManager.java +++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockVmManager.java @@ -16,88 +16,98 @@ // under the License. package com.cloud.agent.manager; -import java.util.HashMap; -import java.util.Map; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.BumpUpPriorityCommand; import com.cloud.agent.api.CheckRouterAnswer; import com.cloud.agent.api.CheckRouterCommand; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.CleanupNetworkRulesCmd; +import com.cloud.agent.api.CreateVMSnapshotCommand; +import com.cloud.agent.api.DeleteVMSnapshotCommand; import com.cloud.agent.api.GetDomRVersionAnswer; import com.cloud.agent.api.GetDomRVersionCmd; import com.cloud.agent.api.GetVmStatsCommand; import com.cloud.agent.api.GetVncPortCommand; import com.cloud.agent.api.MigrateAnswer; import com.cloud.agent.api.MigrateCommand; -import com.cloud.agent.api.NetworkUsageCommand; +import com.cloud.agent.api.NetworkRulesVmSecondaryIpCommand; import com.cloud.agent.api.PrepareForMigrationAnswer; import com.cloud.agent.api.PrepareForMigrationCommand; +import com.cloud.agent.api.RebootAnswer; import com.cloud.agent.api.RebootCommand; +import com.cloud.agent.api.RevertToVMSnapshotCommand; +import com.cloud.agent.api.ScaleVmCommand; import com.cloud.agent.api.SecurityGroupRuleAnswer; import com.cloud.agent.api.SecurityGroupRulesCmd; +import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.StartCommand; +import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.check.CheckSshAnswer; import com.cloud.agent.api.check.CheckSshCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; -import com.cloud.agent.api.routing.DhcpEntryCommand; -import com.cloud.agent.api.routing.IpAssocCommand; -import com.cloud.agent.api.routing.LoadBalancerConfigCommand; import com.cloud.agent.api.routing.SavePasswordCommand; -import com.cloud.agent.api.routing.SetFirewallRulesCommand; -import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; -import com.cloud.agent.api.routing.SetStaticNatRulesCommand; import com.cloud.agent.api.routing.VmDataCommand; import com.cloud.simulator.MockVMVO; import com.cloud.utils.Pair; import com.cloud.utils.component.Manager; import com.cloud.vm.VirtualMachine.State; +import java.util.HashMap; +import java.util.Map; + public interface MockVmManager extends Manager { - public Answer stopVM(StopCommand cmd); - public Answer rebootVM(RebootCommand cmd); - public Answer checkVmState(CheckVirtualMachineCommand cmd); - public Map getVmStates(String hostGuid); - public Answer getVncPort(GetVncPortCommand cmd); + Map getVmStates(String hostGuid); - Answer startVM(StartCommand cmd, SimulatorInfo info); + Map getVms(String hostGuid); + + HashMap> syncNetworkGroups(SimulatorInfo info); + + StartAnswer startVM(StartCommand cmd, SimulatorInfo info); + + StopAnswer stopVM(StopCommand cmd); + + RebootAnswer rebootVM(RebootCommand cmd); + + Answer checkVmState(CheckVirtualMachineCommand cmd); + + Answer getVncPort(GetVncPortCommand cmd); Answer getVmStats(GetVmStatsCommand cmd); - public CheckSshAnswer checkSshCommand(CheckSshCommand cmd); - Answer SetStaticNatRules(SetStaticNatRulesCommand cmd); - - Answer SetPortForwardingRules(SetPortForwardingRulesCommand cmd); - - Answer SetFirewallRules(SetFirewallRulesCommand cmd); - - Answer getNetworkUsage(NetworkUsageCommand cmd); - - Answer IpAssoc(IpAssocCommand cmd); - - Answer LoadBalancerConfig(LoadBalancerConfigCommand cmd); - - Answer AddDhcpEntry(DhcpEntryCommand cmd); + CheckSshAnswer checkSshCommand(CheckSshCommand cmd); Answer setVmData(VmDataCommand cmd); - Answer CleanupNetworkRules(CleanupNetworkRulesCmd cmd, SimulatorInfo info); Answer CheckConsoleProxyLoad(CheckConsoleProxyLoadCommand cmd); + Answer WatchConsoleProxyLoad(WatchConsoleProxyLoadCommand cmd); Answer SavePassword(SavePasswordCommand cmd); - HashMap> syncNetworkGroups(SimulatorInfo info); - SecurityGroupRuleAnswer AddSecurityGroupRules(SecurityGroupRulesCmd cmd, SimulatorInfo info); - MigrateAnswer Migrate(MigrateCommand cmd, SimulatorInfo info); + + MigrateAnswer Migrate(MigrateCommand cmd, SimulatorInfo info); + PrepareForMigrationAnswer prepareForMigrate(PrepareForMigrationCommand cmd); - GetDomRVersionAnswer getDomRVersion(GetDomRVersionCmd cmd); - Map getVms(String hostGuid); + + SecurityGroupRuleAnswer AddSecurityGroupRules(SecurityGroupRulesCmd cmd, SimulatorInfo info); + + GetDomRVersionAnswer getDomRVersion(GetDomRVersionCmd cmd); CheckRouterAnswer checkRouter(CheckRouterCommand cmd); Answer bumpPriority(BumpUpPriorityCommand cmd); + + Answer CleanupNetworkRules(CleanupNetworkRulesCmd cmd, SimulatorInfo info); + + Answer scaleVm(ScaleVmCommand cmd); + + Answer plugSecondaryIp(NetworkRulesVmSecondaryIpCommand cmd); + + Answer createVmSnapshot(CreateVMSnapshotCommand cmd); + + Answer deleteVmSnapshot(DeleteVMSnapshotCommand cmd); + + Answer revertVmSnapshot(RevertToVMSnapshotCommand cmd); } diff --git a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java index c0ccbe43978..64df113ea91 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java +++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockVmManagerImpl.java @@ -17,12 +17,47 @@ package com.cloud.agent.manager; -import com.cloud.agent.api.*; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.BumpUpPriorityCommand; +import com.cloud.agent.api.CheckRouterAnswer; +import com.cloud.agent.api.CheckRouterCommand; +import com.cloud.agent.api.CheckVirtualMachineAnswer; +import com.cloud.agent.api.CheckVirtualMachineCommand; +import com.cloud.agent.api.CleanupNetworkRulesCmd; +import com.cloud.agent.api.CreateVMSnapshotAnswer; +import com.cloud.agent.api.CreateVMSnapshotCommand; +import com.cloud.agent.api.DeleteVMSnapshotAnswer; +import com.cloud.agent.api.DeleteVMSnapshotCommand; +import com.cloud.agent.api.GetDomRVersionAnswer; +import com.cloud.agent.api.GetDomRVersionCmd; +import com.cloud.agent.api.GetVmStatsAnswer; +import com.cloud.agent.api.GetVmStatsCommand; +import com.cloud.agent.api.GetVncPortAnswer; +import com.cloud.agent.api.GetVncPortCommand; +import com.cloud.agent.api.MigrateAnswer; +import com.cloud.agent.api.MigrateCommand; +import com.cloud.agent.api.NetworkRulesVmSecondaryIpCommand; +import com.cloud.agent.api.PrepareForMigrationAnswer; +import com.cloud.agent.api.PrepareForMigrationCommand; +import com.cloud.agent.api.RebootAnswer; +import com.cloud.agent.api.RebootCommand; +import com.cloud.agent.api.RevertToVMSnapshotAnswer; +import com.cloud.agent.api.RevertToVMSnapshotCommand; +import com.cloud.agent.api.ScaleVmCommand; +import com.cloud.agent.api.SecurityGroupRuleAnswer; +import com.cloud.agent.api.SecurityGroupRulesCmd; +import com.cloud.agent.api.StartAnswer; +import com.cloud.agent.api.StartCommand; +import com.cloud.agent.api.StopAnswer; +import com.cloud.agent.api.StopCommand; +import com.cloud.agent.api.VmStatsEntry; import com.cloud.agent.api.check.CheckSshAnswer; import com.cloud.agent.api.check.CheckSshCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; -import com.cloud.agent.api.routing.*; +import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.api.routing.SavePasswordCommand; +import com.cloud.agent.api.routing.VmDataCommand; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.network.Networks.TrafficType; @@ -193,28 +228,6 @@ public class MockVmManagerImpl extends ManagerBase implements MockVmManager { return null; } - public boolean rebootVM(String vmName) { - Transaction txn = Transaction.open(Transaction.SIMULATOR_DB); - try { - txn.start(); - MockVm vm = _mockVmDao.findByVmName(vmName); - if (vm != null) { - vm.setState(State.Running); - _mockVmDao.update(vm.getId(), (MockVMVO) vm); - - } - txn.commit(); - } catch (Exception ex) { - txn.rollback(); - throw new CloudRuntimeException("unable to reboot vm " + vmName, ex); - } finally { - txn.close(); - txn = Transaction.open(Transaction.CLOUD_DB); - txn.close(); - } - return true; - } - @Override public Map getVms(String hostGuid) { Transaction txn = Transaction.open(Transaction.SIMULATOR_DB); @@ -346,7 +359,7 @@ public class MockVmManagerImpl extends ManagerBase implements MockVmManager { } @Override - public Answer startVM(StartCommand cmd, SimulatorInfo info) { + public StartAnswer startVM(StartCommand cmd, SimulatorInfo info) { VirtualMachineTO vm = cmd.getVirtualMachine(); String result = startVM(vm.getName(), vm.getNics(), vm.getCpus()* vm.getMaxSpeed(), vm.getMaxRam(), vm.getBootArgs(), info.getHostUuid()); if (result != null) { @@ -361,26 +374,7 @@ public class MockVmManagerImpl extends ManagerBase implements MockVmManager { return new CheckSshAnswer(cmd); } - @Override - public Answer SetStaticNatRules(SetStaticNatRulesCommand cmd) { - return new Answer(cmd); - } - @Override - public Answer SetPortForwardingRules(SetPortForwardingRulesCommand cmd) { - return new Answer(cmd); - } - - @Override - public Answer SetFirewallRules(SetFirewallRulesCommand cmd) { - return new Answer(cmd); - } - - - @Override - public NetworkUsageAnswer getNetworkUsage(NetworkUsageCommand cmd) { - return new NetworkUsageAnswer(cmd, null, 100L, 100L); - } @Override public MigrateAnswer Migrate(MigrateCommand cmd, SimulatorInfo info) { @@ -437,21 +431,6 @@ public class MockVmManagerImpl extends ManagerBase implements MockVmManager { } } - @Override - public Answer IpAssoc(IpAssocCommand cmd) { - return new Answer(cmd); - } - - @Override - public Answer LoadBalancerConfig(LoadBalancerConfigCommand cmd) { - return new Answer(cmd); - } - - @Override - public Answer AddDhcpEntry(DhcpEntryCommand cmd) { - return new Answer(cmd); - } - @Override public Answer setVmData(VmDataCommand cmd) { return new Answer(cmd); @@ -482,7 +461,48 @@ public class MockVmManagerImpl extends ManagerBase implements MockVmManager { } @Override - public Answer stopVM(StopCommand cmd) { + public Answer scaleVm(ScaleVmCommand cmd) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public Answer plugSecondaryIp(NetworkRulesVmSecondaryIpCommand cmd) { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + @Override + public Answer createVmSnapshot(CreateVMSnapshotCommand cmd) { + String vmName = cmd.getVmName(); + String vmSnapshotName = cmd.getTarget().getSnapshotName(); + + s_logger.debug("Created snapshot " +vmSnapshotName+ " for vm " + vmName); + return new CreateVMSnapshotAnswer(cmd, cmd.getTarget(), cmd.getVolumeTOs()); + } + + @Override + public Answer deleteVmSnapshot(DeleteVMSnapshotCommand cmd) { + String vm = cmd.getVmName(); + String snapshotName = cmd.getTarget().getSnapshotName(); + if(_mockVmDao.findByVmName(cmd.getVmName()) != null) { + return new DeleteVMSnapshotAnswer(cmd, false, "No VM by name "+ cmd.getVmName()); + } + s_logger.debug("Removed snapshot " +snapshotName+ " of VM "+vm); + return new DeleteVMSnapshotAnswer(cmd, true, "success"); + } + + @Override + public Answer revertVmSnapshot(RevertToVMSnapshotCommand cmd) { + String vm = cmd.getVmName(); + String snapshot = cmd.getTarget().getSnapshotName(); + if(_mockVmDao.findByVmName(cmd.getVmName()) != null) { + return new RevertToVMSnapshotAnswer(cmd, false, "No VM by name "+ cmd.getVmName()); + } + s_logger.debug("Reverted to snapshot " +snapshot+ " of VM "+vm); + return new RevertToVMSnapshotAnswer(cmd, true, "success"); + } + + @Override + public StopAnswer stopVM(StopCommand cmd) { Transaction txn = Transaction.open(Transaction.SIMULATOR_DB); try { txn.start(); @@ -509,7 +529,7 @@ public class MockVmManagerImpl extends ManagerBase implements MockVmManager { } @Override - public Answer rebootVM(RebootCommand cmd) { + public RebootAnswer rebootVM(RebootCommand cmd) { Transaction txn = Transaction.open(Transaction.SIMULATOR_DB); try { txn.start(); diff --git a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java index ab6eec3394a..1f1f4c53477 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java +++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/SimulatorManagerImpl.java @@ -16,16 +16,6 @@ // under the License. package com.cloud.agent.manager; -import java.util.HashMap; -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 com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachIsoCommand; import com.cloud.agent.api.AttachVolumeCommand; @@ -34,6 +24,7 @@ import com.cloud.agent.api.BumpUpPriorityCommand; import com.cloud.agent.api.CheckHealthCommand; import com.cloud.agent.api.CheckNetworkCommand; import com.cloud.agent.api.CheckRouterCommand; +import com.cloud.agent.api.CheckS2SVpnConnectionsCommand; import com.cloud.agent.api.CheckVirtualMachineCommand; import com.cloud.agent.api.CleanupNetworkRulesCmd; import com.cloud.agent.api.ClusterSyncCommand; @@ -42,9 +33,11 @@ import com.cloud.agent.api.ComputeChecksumCommand; import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand; import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand; import com.cloud.agent.api.CreateStoragePoolCommand; +import com.cloud.agent.api.CreateVMSnapshotCommand; import com.cloud.agent.api.CreateVolumeFromSnapshotCommand; import com.cloud.agent.api.DeleteSnapshotBackupCommand; import com.cloud.agent.api.DeleteStoragePoolCommand; +import com.cloud.agent.api.DeleteVMSnapshotCommand; import com.cloud.agent.api.GetDomRVersionCmd; import com.cloud.agent.api.GetHostStatsCommand; import com.cloud.agent.api.GetStorageStatsCommand; @@ -54,26 +47,39 @@ import com.cloud.agent.api.MaintainCommand; import com.cloud.agent.api.ManageSnapshotCommand; import com.cloud.agent.api.MigrateCommand; import com.cloud.agent.api.ModifyStoragePoolCommand; +import com.cloud.agent.api.NetworkRulesVmSecondaryIpCommand; import com.cloud.agent.api.NetworkUsageCommand; import com.cloud.agent.api.PingTestCommand; +import com.cloud.agent.api.PlugNicCommand; import com.cloud.agent.api.PrepareForMigrationCommand; +import com.cloud.agent.api.PvlanSetupCommand; import com.cloud.agent.api.RebootCommand; +import com.cloud.agent.api.RevertToVMSnapshotCommand; +import com.cloud.agent.api.ScaleVmCommand; import com.cloud.agent.api.SecStorageSetupCommand; import com.cloud.agent.api.SecStorageVMSetupCommand; import com.cloud.agent.api.SecurityGroupRulesCmd; +import com.cloud.agent.api.SetupGuestNetworkCommand; import com.cloud.agent.api.StartCommand; import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.StoragePoolInfo; +import com.cloud.agent.api.UnPlugNicCommand; import com.cloud.agent.api.check.CheckSshCommand; import com.cloud.agent.api.proxy.CheckConsoleProxyLoadCommand; import com.cloud.agent.api.proxy.WatchConsoleProxyLoadCommand; import com.cloud.agent.api.routing.DhcpEntryCommand; import com.cloud.agent.api.routing.IpAssocCommand; +import com.cloud.agent.api.routing.IpAssocVpcCommand; import com.cloud.agent.api.routing.LoadBalancerConfigCommand; import com.cloud.agent.api.routing.SavePasswordCommand; import com.cloud.agent.api.routing.SetFirewallRulesCommand; +import com.cloud.agent.api.routing.SetNetworkACLCommand; import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; +import com.cloud.agent.api.routing.SetPortForwardingRulesVpcCommand; +import com.cloud.agent.api.routing.SetSourceNatCommand; import com.cloud.agent.api.routing.SetStaticNatRulesCommand; +import com.cloud.agent.api.routing.SetStaticRouteCommand; +import com.cloud.agent.api.routing.Site2SiteVpnCfgCommand; import com.cloud.agent.api.routing.VmDataCommand; import com.cloud.agent.api.storage.CopyVolumeCommand; import com.cloud.agent.api.storage.CreateCommand; @@ -96,19 +102,29 @@ import com.cloud.utils.db.DB; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.VirtualMachine.State; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import java.util.HashMap; +import java.util.Map; @Component @Local(value = { SimulatorManager.class }) public class SimulatorManagerImpl extends ManagerBase implements SimulatorManager { private static final Logger s_logger = Logger.getLogger(SimulatorManagerImpl.class); @Inject - MockVmManager _mockVmMgr = null; + MockVmManager _mockVmMgr; @Inject - MockStorageManager _mockStorageMgr = null; + MockStorageManager _mockStorageMgr; @Inject - MockAgentManager _mockAgentMgr = null; + MockAgentManager _mockAgentMgr; @Inject - MockConfigurationDao _mockConfigDao = null; + MockNetworkManager _mockNetworkMgr; + @Inject + MockConfigurationDao _mockConfigDao; @Inject MockHostDao _mockHost = null; private ConnectionConcierge _concierge; @@ -213,19 +229,19 @@ public class SimulatorManagerImpl extends ManagerBase implements SimulatorManage } else if (cmd instanceof CheckVirtualMachineCommand) { return _mockVmMgr.checkVmState((CheckVirtualMachineCommand) cmd); } else if (cmd instanceof SetStaticNatRulesCommand) { - return _mockVmMgr.SetStaticNatRules((SetStaticNatRulesCommand) cmd); + return _mockNetworkMgr.SetStaticNatRules((SetStaticNatRulesCommand) cmd); } else if (cmd instanceof SetFirewallRulesCommand) { - return _mockVmMgr.SetFirewallRules((SetFirewallRulesCommand) cmd); + return _mockNetworkMgr.SetFirewallRules((SetFirewallRulesCommand) cmd); } else if (cmd instanceof SetPortForwardingRulesCommand) { - return _mockVmMgr.SetPortForwardingRules((SetPortForwardingRulesCommand) cmd); + return _mockNetworkMgr.SetPortForwardingRules((SetPortForwardingRulesCommand) cmd); } else if (cmd instanceof NetworkUsageCommand) { - return _mockVmMgr.getNetworkUsage((NetworkUsageCommand) cmd); + return _mockNetworkMgr.getNetworkUsage((NetworkUsageCommand) cmd); } else if (cmd instanceof IpAssocCommand) { - return _mockVmMgr.IpAssoc((IpAssocCommand) cmd); + return _mockNetworkMgr.IpAssoc((IpAssocCommand) cmd); } else if (cmd instanceof LoadBalancerConfigCommand) { - return _mockVmMgr.LoadBalancerConfig((LoadBalancerConfigCommand) cmd); + return _mockNetworkMgr.LoadBalancerConfig((LoadBalancerConfigCommand) cmd); } else if (cmd instanceof DhcpEntryCommand) { - return _mockVmMgr.AddDhcpEntry((DhcpEntryCommand) cmd); + return _mockNetworkMgr.AddDhcpEntry((DhcpEntryCommand) cmd); } else if (cmd instanceof VmDataCommand) { return _mockVmMgr.setVmData((VmDataCommand) cmd); } else if (cmd instanceof CleanupNetworkRulesCmd) { @@ -306,7 +322,42 @@ public class SimulatorManagerImpl extends ManagerBase implements SimulatorManage return new Answer(cmd); } else if (cmd instanceof CopyVolumeCommand) { return _mockStorageMgr.CopyVolume((CopyVolumeCommand) cmd); + } else if (cmd instanceof PlugNicCommand) { + return _mockNetworkMgr.plugNic((PlugNicCommand) cmd); + } else if (cmd instanceof UnPlugNicCommand) { + return _mockNetworkMgr.unplugNic((UnPlugNicCommand) cmd); + } else if (cmd instanceof IpAssocVpcCommand) { + return _mockNetworkMgr.ipAssoc((IpAssocVpcCommand) cmd); + } else if (cmd instanceof SetSourceNatCommand) { + return _mockNetworkMgr.setSourceNat((SetSourceNatCommand) cmd); + } else if (cmd instanceof SetNetworkACLCommand) { + return _mockNetworkMgr.setNetworkAcl((SetNetworkACLCommand) cmd); + } else if (cmd instanceof SetupGuestNetworkCommand) { + return _mockNetworkMgr.setUpGuestNetwork((SetupGuestNetworkCommand) cmd); + } else if (cmd instanceof SetPortForwardingRulesVpcCommand) { + return _mockNetworkMgr.setVpcPortForwards((SetPortForwardingRulesVpcCommand) cmd); + } else if (cmd instanceof SetStaticNatRulesCommand) { + return _mockNetworkMgr.setVPCStaticNatRules((SetStaticNatRulesCommand) cmd); + } else if (cmd instanceof SetStaticRouteCommand) { + return _mockNetworkMgr.setStaticRoute((SetStaticRouteCommand) cmd); + } else if (cmd instanceof Site2SiteVpnCfgCommand) { + return _mockNetworkMgr.siteToSiteVpn((Site2SiteVpnCfgCommand) cmd); + } else if (cmd instanceof CheckS2SVpnConnectionsCommand) { + return _mockNetworkMgr.checkSiteToSiteVpnConnection((CheckS2SVpnConnectionsCommand) cmd); + } else if (cmd instanceof CreateVMSnapshotCommand) { + return _mockVmMgr.createVmSnapshot((CreateVMSnapshotCommand) cmd); + } else if (cmd instanceof DeleteVMSnapshotCommand) { + return _mockVmMgr.deleteVmSnapshot((DeleteVMSnapshotCommand) cmd); + } else if (cmd instanceof RevertToVMSnapshotCommand) { + return _mockVmMgr.revertVmSnapshot((RevertToVMSnapshotCommand) cmd); + } else if (cmd instanceof NetworkRulesVmSecondaryIpCommand) { + return _mockVmMgr.plugSecondaryIp((NetworkRulesVmSecondaryIpCommand) cmd); + } else if (cmd instanceof ScaleVmCommand) { + return _mockVmMgr.scaleVm((ScaleVmCommand) cmd); + } else if (cmd instanceof PvlanSetupCommand) { + return _mockNetworkMgr.setupPVLAN((PvlanSetupCommand) cmd); } else { + s_logger.error("Simulator does not implement command of type "+cmd.toString()); return Answer.createUnsupportedCommandAnswer(cmd); } } catch(Exception e) { diff --git a/plugins/hypervisors/simulator/src/com/cloud/configuration/SimulatorComponentLibrary.java b/plugins/hypervisors/simulator/src/com/cloud/configuration/SimulatorComponentLibrary.java deleted file mode 100644 index 373cae1367e..00000000000 --- a/plugins/hypervisors/simulator/src/com/cloud/configuration/SimulatorComponentLibrary.java +++ /dev/null @@ -1,40 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package com.cloud.configuration; - - -//TODO: Remove this class after the managers are figured out. -public class SimulatorComponentLibrary { -// @Override -// protected void populateManagers() { -// addManager("VM Manager", MockVmManagerImpl.class); -// addManager("agent manager", MockAgentManagerImpl.class); -// addManager("storage manager", MockStorageManagerImpl.class); -// addManager("SimulatorManager", SimulatorManagerImpl.class); -// } -// -// @Override -// protected void populateDaos() { -// addDao("mock Host", MockHostDaoImpl.class); -// addDao("mock secondary storage", MockSecStorageDaoImpl.class); -// addDao("mock storage pool", MockStoragePoolDaoImpl.class); -// addDao("mock vm", MockVMDaoImpl.class); -// addDao("mock volume", MockVolumeDaoImpl.class); -// addDao("mock config", MockConfigurationDaoImpl.class); -// addDao("mock security rules", MockSecurityRulesDaoImpl.class); -// } -} diff --git a/plugins/hypervisors/vmware/pom.xml b/plugins/hypervisors/vmware/pom.xml index 79779decf62..755244f5f61 100644 --- a/plugins/hypervisors/vmware/pom.xml +++ b/plugins/hypervisors/vmware/pom.xml @@ -37,6 +37,12 @@ cloud-secondary-storage ${project.version}
+ + org.apache.cloudstack + cloud-engine-storage + 4.2.0-SNAPSHOT + compile + com.cloud.com.vmware vmware-vim25 diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/LegacyZone.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/LegacyZone.java new file mode 100644 index 00000000000..535b6a7f99d --- /dev/null +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/LegacyZone.java @@ -0,0 +1,28 @@ +//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.hypervisor.vmware; + +import org.apache.cloudstack.api.InternalIdentity; + +public interface LegacyZone extends InternalIdentity { + + long getId(); + + long getZoneId(); + +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/LegacyZoneVO.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/LegacyZoneVO.java new file mode 100644 index 00000000000..390e56daf00 --- /dev/null +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/LegacyZoneVO.java @@ -0,0 +1,81 @@ +//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.hypervisor.vmware; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import com.cloud.utils.NumbersUtil; + +/** +* LegacyZoneVO contains id of CloudStack zone containing clusters from multiple VMware vCetners and/or VMware Datacenters. +*/ + +@Entity +@Table(name="legacy_zones") +public class LegacyZoneVO implements LegacyZone { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "zone_id") + private long zoneId; + + @Override + public long getId() { + return id; + } + + @Override + public long getZoneId() { + return zoneId; + } + + @Override + public int hashCode() { + return NumbersUtil.hash(id); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof LegacyZoneVO) { + return ((LegacyZoneVO)obj).getId() == this.getId(); + } else { + return false; + } + } + + public LegacyZoneVO() { + } + + public LegacyZoneVO(long zoneId) { + this.id = zoneId; + } + + public LegacyZoneVO(long id, long zoneId) { + this.id = id; + this.zoneId = zoneId; + } + +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenter.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenter.java new file mode 100644 index 00000000000..6d6d2ebf0eb --- /dev/null +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenter.java @@ -0,0 +1,36 @@ +// 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.hypervisor.vmware; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +public interface VmwareDatacenter extends Identity, InternalIdentity { + + String getVmwareDatacenterName(); + + String getGuid(); + + String getVcenterHost(); + + long getId(); + + String getPassword(); + + String getUser(); +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterService.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterService.java new file mode 100644 index 00000000000..5e80e1829f1 --- /dev/null +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterService.java @@ -0,0 +1,32 @@ +// 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.hypervisor.vmware; + +import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd; +import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd; + +import com.cloud.exception.DiscoveryException; +import com.cloud.exception.ResourceInUseException; +import com.cloud.utils.component.PluggableService; + +public interface VmwareDatacenterService extends PluggableService { + + public VmwareDatacenterVO addVmwareDatacenter(AddVmwareDcCmd cmd) throws IllegalArgumentException, DiscoveryException, ResourceInUseException; + + public boolean removeVmwareDatacenter(RemoveVmwareDcCmd cmd) throws IllegalArgumentException, ResourceInUseException; +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterVO.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterVO.java new file mode 100644 index 00000000000..a13e59e5cb4 --- /dev/null +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterVO.java @@ -0,0 +1,160 @@ +// 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.hypervisor.vmware; + +import java.util.UUID; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.db.Encrypt; + +/** + * VmwareDatacenterVO contains information of Vmware Datacenter associated with a CloudStack zone. + */ + +@Entity +@Table(name="vmware_data_center") +public class VmwareDatacenterVO implements VmwareDatacenter { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "guid") + private String guid; + + @Column(name = "name") + private String name; + + @Column(name = "vcenter_host") + private String vCenterHost; + + @Column(name = "uuid") + private String uuid; + + @Column(name = "username") + private String user; + + @Encrypt + @Column(name = "password") + private String password; + + @Override + public String getUuid() { + return uuid; + } + + @Override + public long getId() { + return id; + } + + @Override + public String getVmwareDatacenterName() { + return name; + } + + @Override + public String getGuid() { + return guid; + } + + @Override + public String getUser() { + return user; + } + + @Override + public String getPassword() { + return password; + } + + @Override + public String getVcenterHost() { + return vCenterHost; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public void setGuid(String guid) { + this.guid = guid; + } + + public void setVmwareDatacenterName(String name) { + this.name = name; + } + + public void setVcenterHost(String vCenterHost) { + this.vCenterHost = vCenterHost; + } + + public void setUser(String user) { + this.user = user; ; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public String toString() { + return new StringBuilder("VmwareDatacenter[").append(guid).append("]").toString(); + } + + @Override + public int hashCode() { + return NumbersUtil.hash(id); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof VmwareDatacenterVO) { + return ((VmwareDatacenterVO)obj).getId() == this.getId(); + } else { + return false; + } + } + + public VmwareDatacenterVO(String guid, String name, String vCenterHost, String user, String password) { + this.uuid = UUID.randomUUID().toString(); + this.name = name; + this.guid = guid; + this.vCenterHost = vCenterHost; + this.user = user; + this.password = password; + } + + public VmwareDatacenterVO(long id, String guid, String name, String vCenterHost, String user, String password) { + this(guid, name, vCenterHost, user, password); + this.id = id; + } + + public VmwareDatacenterVO() { + this.uuid = UUID.randomUUID().toString(); + } + +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterZoneMap.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterZoneMap.java new file mode 100644 index 00000000000..f70a5414de8 --- /dev/null +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterZoneMap.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.hypervisor.vmware; + +import org.apache.cloudstack.api.InternalIdentity; + +import com.cloud.org.Grouping; + +public interface VmwareDatacenterZoneMap extends Grouping, InternalIdentity { + public long getId(); + + public long getZoneId(); + + public long getVmwareDcId(); +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterZoneMapVO.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterZoneMapVO.java new file mode 100644 index 00000000000..93b0e2670cb --- /dev/null +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareDatacenterZoneMapVO.java @@ -0,0 +1,78 @@ +//Licensed to the Apache Software Foundation (ASF) under one +//or more contributor license agreements. See the NOTICE file +//distributed with this work for additional information +//regarding copyright ownership. The ASF licenses this file +//to you under the Apache License, Version 2.0 (the +//"License"); you may not use this file except in compliance +//with the License. You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, +//software distributed under the License is distributed on an +//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +//KIND, either express or implied. See the License for the +//specific language governing permissions and limitations +//under the License. + +package com.cloud.hypervisor.vmware; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + + +//NOTE: This particular table is totally internal to the CS MS. +//Do not ever include a uuid/guid field in this table. We just +//need it map zone ids with VMware datacenter Ids. + +@Entity +@Table(name="vmware_data_center_zone_map") +public class VmwareDatacenterZoneMapVO implements VmwareDatacenterZoneMap { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="zone_id") + private long zoneId; + + @Column(name="vmware_data_center_id") + private long vmwareDcId; + + public VmwareDatacenterZoneMapVO(long zoneId, long vmwareDcId) { + this.zoneId = zoneId; + this.vmwareDcId = vmwareDcId; + } + + public VmwareDatacenterZoneMapVO() { + // Do nothing. + } + + @Override + public long getId() { + return id; + } + + @Override + public long getZoneId() { + return zoneId; + } + + @Override + public long getVmwareDcId() { + return vmwareDcId; + } + + public void setZoneId(long zoneId) { + this.zoneId = zoneId; + } + + public void setVmwareDcId(long vmwareDcId) { + this.vmwareDcId = vmwareDcId; + } +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java index 2f82b534af2..fa873741275 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/VmwareServerDiscoverer.java @@ -30,6 +30,7 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import org.apache.cloudstack.api.ApiConstants; +import org.springframework.beans.NullValueInNestedPathException; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; @@ -51,6 +52,8 @@ import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; +import com.cloud.hypervisor.vmware.dao.VmwareDatacenterDao; +import com.cloud.hypervisor.vmware.dao.VmwareDatacenterZoneMapDao; import com.cloud.hypervisor.vmware.manager.VmwareManager; import com.cloud.hypervisor.vmware.mo.ClusterMO; import com.cloud.hypervisor.vmware.mo.HostMO; @@ -107,11 +110,16 @@ public class VmwareServerDiscoverer extends DiscovererBase implements @Inject CiscoNexusVSMDeviceDao _nexusDao; @Inject - CiscoNexusVSMElementService _nexusElement; + CiscoNexusVSMElement _nexusElement; @Inject NetworkModel _netmgr; @Inject HypervisorCapabilitiesDao _hvCapabilitiesDao; + @Inject + VmwareDatacenterZoneMapDao _vmwareDcZoneMapDao; + @Inject + VmwareDatacenterDao _vmwareDcDao; + protected Map _urlParams; protected boolean useDVS = false; protected boolean nexusDVS = false; @@ -140,6 +148,18 @@ public class VmwareServerDiscoverer extends DiscovererBase implements return null; } + Map clusterDetails = _clusterDetailsDao.findDetails(clusterId); + boolean legacyZone = _vmwareMgr.isLegacyZone(dcId); + //Check if NOT a legacy zone. + if (!legacyZone) { + String updatedInventoryPath = validateCluster(dcId, url, username, password); + if (url.getPath() != updatedInventoryPath) { + // If url from API doesn't specifiy DC then update url in database with DC assocaited with this zone. + clusterDetails.put("url", url.getScheme() + "://" + url.getHost() + updatedInventoryPath); + _clusterDetailsDao.persist(clusterId, clusterDetails); + } + } + List hosts = _resourceMgr.listAllHostsInCluster(clusterId); if (hosts != null && hosts.size() > 0) { int maxHostsPerCluster = _hvCapabilitiesDao.getMaxHostsPerCluster(hosts.get(0).getHypervisorType(), hosts.get(0).getHypervisorVersion()); @@ -164,7 +184,6 @@ public class VmwareServerDiscoverer extends DiscovererBase implements VmwareTrafficLabel guestTrafficLabelObj = new VmwareTrafficLabel(TrafficType.Guest); VmwareTrafficLabel publicTrafficLabelObj = new VmwareTrafficLabel(TrafficType.Public); - Map clusterDetails = _clusterDetailsDao.findDetails(clusterId); DataCenterVO zone = _dcDao.findById(dcId); NetworkType zoneType = zone.getNetworkType(); _readGlobalConfigParameters(); @@ -395,6 +414,63 @@ public class VmwareServerDiscoverer extends DiscovererBase implements } } + private String validateCluster(Long dcId, URI url, String username, String password) throws DiscoveryException { + String msg; + long vmwareDcId; + VmwareDatacenterVO vmwareDc; + String vmwareDcNameFromDb; + String vmwareDcNameFromApi; + String vCenterHost; + String updatedInventoryPath = url.getPath(); + String clusterName = null; + + // Check if zone is associated with DC + VmwareDatacenterZoneMapVO vmwareDcZone = _vmwareDcZoneMapDao.findByZoneId(dcId); + if (vmwareDcZone == null) { + msg = "Zone " + dcId + " is not associated with any VMware DC yet. " + + "Please add VMware DC to this zone first and then try to add clusters."; + s_logger.error(msg); + throw new DiscoveryException(msg); + } + + // Retrieve DC added to this zone from database + vmwareDcId = vmwareDcZone.getVmwareDcId(); + vmwareDc = _vmwareDcDao.findById(vmwareDcId); + vmwareDcNameFromApi = vmwareDcNameFromDb = vmwareDc.getVmwareDatacenterName(); + vCenterHost = vmwareDc.getVcenterHost(); + String inventoryPath = url.getPath(); + + assert (inventoryPath != null); + + String[] pathTokens = inventoryPath.split("/"); + if (pathTokens.length == 2) { + // DC name is not present in url. + // Using DC name read from database. + clusterName = pathTokens[1]; + updatedInventoryPath = "/" + vmwareDcNameFromDb + "/" + clusterName; + } else if (pathTokens.length == 3) { + vmwareDcNameFromApi = pathTokens[1]; + clusterName = pathTokens[2]; + } + + if (!vCenterHost.equalsIgnoreCase(url.getHost())) { + msg = "This cluster " + clusterName + " belongs to vCenter " + url.getHost() + + ". But this zone is associated with VMware DC from vCenter " + vCenterHost + + ". Make sure the cluster being added belongs to vCenter " + vCenterHost + + " and VMware DC " + vmwareDcNameFromDb; + s_logger.error(msg); + throw new DiscoveryException(msg); + } else if (!vmwareDcNameFromDb.equalsIgnoreCase(vmwareDcNameFromApi)) { + msg = "This cluster " + clusterName + " belongs to VMware DC " + vmwareDcNameFromApi + + " .But this zone is associated with VMware DC " + vmwareDcNameFromDb + + ". Make sure the cluster being added belongs to VMware DC " + vmwareDcNameFromDb + + " in vCenter " + vCenterHost; + s_logger.error(msg); + throw new DiscoveryException(msg); + } + return updatedInventoryPath; + } + private boolean validateDiscoveredHosts(VmwareContext context, ManagedObjectReference morCluster, List morHosts) throws Exception { diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/LegacyZoneDao.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/LegacyZoneDao.java new file mode 100644 index 00000000000..4a858f81363 --- /dev/null +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/LegacyZoneDao.java @@ -0,0 +1,37 @@ +// 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.hypervisor.vmware.dao; + +import java.util.List; + +import com.cloud.hypervisor.vmware.LegacyZoneVO; +import com.cloud.utils.db.GenericDao; + +public interface LegacyZoneDao extends GenericDao { + /** + * @param id of zone + * @return zone id of legacy zone + */ + LegacyZoneVO findByZoneId(String zoneId); + + /** + * Lists all legacy CloudStack zones + * @return list of ids of legacy CloudStack zones + */ + List listAllLegacyZones(); +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/LegacyZoneDaoImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/LegacyZoneDaoImpl.java new file mode 100644 index 00000000000..7d2d1285c13 --- /dev/null +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/LegacyZoneDaoImpl.java @@ -0,0 +1,66 @@ + // 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.hypervisor.vmware.dao; + + import java.util.List; + + import javax.ejb.Local; + + import org.apache.log4j.Logger; + import org.springframework.stereotype.Component; + + import com.cloud.hypervisor.vmware.LegacyZoneVO; + import com.cloud.utils.db.DB; + import com.cloud.utils.db.GenericDaoBase; + import com.cloud.utils.db.SearchBuilder; + import com.cloud.utils.db.SearchCriteria; + import com.cloud.utils.db.SearchCriteria.Op; + + @Component + @Local(value=LegacyZoneDao.class) @DB(txn=false) + public class LegacyZoneDaoImpl extends GenericDaoBase implements LegacyZoneDao { + protected static final Logger s_logger = Logger.getLogger(LegacyZoneDaoImpl.class); + + final SearchBuilder zoneSearch; + final SearchBuilder fullTableSearch; + + public LegacyZoneDaoImpl() { + super(); + + zoneSearch = createSearchBuilder(); + zoneSearch.and("zoneId", zoneSearch.entity().getZoneId(), Op.EQ); + zoneSearch.done(); + + fullTableSearch = createSearchBuilder(); + fullTableSearch.done(); + } + + @Override + public LegacyZoneVO findByZoneId(String zoneId) { + SearchCriteria sc = zoneSearch.create(); + sc.setParameters("zoneId", zoneId); + return findOneBy(sc); + } + + @Override + public List listAllLegacyZones() { + SearchCriteria sc = fullTableSearch.create(); + return search(sc, null); + } + +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/VmwareDatacenterDao.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/VmwareDatacenterDao.java new file mode 100644 index 00000000000..2754e91d26c --- /dev/null +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/VmwareDatacenterDao.java @@ -0,0 +1,65 @@ +// 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.hypervisor.vmware.dao; + +import java.util.List; + +import com.cloud.hypervisor.vmware.VmwareDatacenterVO; +import com.cloud.utils.db.GenericDao; + +public interface VmwareDatacenterDao extends GenericDao { + + /** + * Return a VMware Datacenter given guid + * @param guid of VMware datacenter + * @return VmwareDatacenterVO for the VMware datacenter having the specified guid. + */ + VmwareDatacenterVO getVmwareDatacenterByGuid(String guid); + + /** + * Return a VMware Datacenter given name and vCenter host. + * For legacy zones multiple records will be present in the table. + * @param name of VMware datacenter + * @param vCenter host + * @return VmwareDatacenterVO for the VMware datacenter with given name and + * belonging to specified vCenter host. + */ + List getVmwareDatacenterByNameAndVcenter(String name, String vCenterHost); + + /** + * Return a list of VMware Datacenter given name. + * @param name of Vmware datacenter + * @return list of VmwareDatacenterVO for VMware datacenters having the specified name. + */ + List listVmwareDatacenterByName(String name); + + /** + * Return a list of VMware Datacenters belonging to specified vCenter + * @param vCenter Host + * @return list of VmwareDatacenterVO for all VMware datacenters belonging to + * specified vCenter + */ + List listVmwareDatacenterByVcenter(String vCenterHost); + + /** + * Lists all associated VMware datacenter on the management server. + * @return list of VmwareDatacenterVO for all associated VMware datacenters + */ + List listAllVmwareDatacenters(); + +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/VmwareDatacenterDaoImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/VmwareDatacenterDaoImpl.java new file mode 100644 index 00000000000..9f5796a073a --- /dev/null +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/VmwareDatacenterDaoImpl.java @@ -0,0 +1,104 @@ +// 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.hypervisor.vmware.dao; + +import java.util.List; + +import javax.ejb.Local; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.hypervisor.vmware.VmwareDatacenterVO; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; + +@Component +@Local(value=VmwareDatacenterDao.class) @DB(txn=false) +public class VmwareDatacenterDaoImpl extends GenericDaoBase implements VmwareDatacenterDao { + protected static final Logger s_logger = Logger.getLogger(VmwareDatacenterDaoImpl.class); + + final SearchBuilder nameSearch; + final SearchBuilder guidSearch; + final SearchBuilder vcSearch; + final SearchBuilder nameVcSearch; + final SearchBuilder fullTableSearch; + + public VmwareDatacenterDaoImpl() { + super(); + + nameSearch = createSearchBuilder(); + nameSearch.and("name", nameSearch.entity().getVmwareDatacenterName(), Op.EQ); + nameSearch.done(); + + nameVcSearch = createSearchBuilder(); + nameVcSearch.and("name", nameVcSearch.entity().getVmwareDatacenterName(), Op.EQ); + nameVcSearch.and("vCenterHost", nameVcSearch.entity().getVcenterHost(), Op.EQ); + nameVcSearch.done(); + + vcSearch = createSearchBuilder(); + vcSearch.and("vCenterHost", vcSearch.entity().getVcenterHost(), Op.EQ); + vcSearch.done(); + + guidSearch = createSearchBuilder(); + guidSearch.and("guid", guidSearch.entity().getGuid(), Op.EQ); + guidSearch.done(); + + fullTableSearch = createSearchBuilder(); + fullTableSearch.done(); + } + + @Override + public VmwareDatacenterVO getVmwareDatacenterByGuid(String guid) { + SearchCriteria sc = guidSearch.create(); + sc.setParameters("guid", guid); + return findOneBy(sc); + } + + @Override + public List getVmwareDatacenterByNameAndVcenter(String name, String vCenterHost) { + SearchCriteria sc = nameVcSearch.create(); + sc.setParameters("name", name); + sc.setParameters("vCenterHost", vCenterHost); + return search(sc, null); + } + + @Override + public List listVmwareDatacenterByName(String name) { + SearchCriteria sc = nameSearch.create(); + sc.setParameters("name", name); + return search(sc, null); + } + + @Override + public List listVmwareDatacenterByVcenter(String vCenterHost) { + SearchCriteria sc = vcSearch.create(); + sc.setParameters("vCenterHost", vCenterHost); + return search(sc, null); + } + + @Override + public List listAllVmwareDatacenters() { + SearchCriteria sc = fullTableSearch.create(); + return search(sc, null); + } + +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/VmwareDatacenterZoneMapDao.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/VmwareDatacenterZoneMapDao.java new file mode 100644 index 00000000000..be693aaac0c --- /dev/null +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/VmwareDatacenterZoneMapDao.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.hypervisor.vmware.dao; + +import com.cloud.hypervisor.vmware.VmwareDatacenterZoneMapVO; +import com.cloud.utils.db.GenericDao; + +public interface VmwareDatacenterZoneMapDao extends GenericDao { + /** + * @param id of zone + * @return map object of VMware datacenter & zone + */ + VmwareDatacenterZoneMapVO findByZoneId(long zoneId); + + /** + * @param id of VMware datacenter + * @return map object of VMware datacenter & zone + */ + VmwareDatacenterZoneMapVO findByVmwareDcId(long vmwareDcId); +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/VmwareDatacenterZoneMapDaoImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/VmwareDatacenterZoneMapDaoImpl.java new file mode 100644 index 00000000000..1c1326954c9 --- /dev/null +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/dao/VmwareDatacenterZoneMapDaoImpl.java @@ -0,0 +1,61 @@ +//Licensed to the Apache Software Foundation (ASF) under one +//or more contributor license agreements. See the NOTICE file +//distributed with this work for additional information +//regarding copyright ownership. The ASF licenses this file +//to you under the Apache License, Version 2.0 (the +//"License"); you may not use this file except in compliance +//with the License. You may obtain a copy of the License at +// +//http://www.apache.org/licenses/LICENSE-2.0 +// +//Unless required by applicable law or agreed to in writing, +//software distributed under the License is distributed on an +//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +//KIND, either express or implied. See the License for the +//specific language governing permissions and limitations +//under the License. + +package com.cloud.hypervisor.vmware.dao; + +import javax.ejb.Local; + +import org.springframework.stereotype.Component; + +import com.cloud.hypervisor.vmware.VmwareDatacenterZoneMapVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; + +@Component +@Local(value=VmwareDatacenterZoneMapDao.class) +public class VmwareDatacenterZoneMapDaoImpl extends GenericDaoBase + implements VmwareDatacenterZoneMapDao { + + protected final SearchBuilder zoneSearch; + protected final SearchBuilder vmwareDcSearch; + + public VmwareDatacenterZoneMapDaoImpl() { + zoneSearch = createSearchBuilder(); + zoneSearch.and("zoneId", zoneSearch.entity().getZoneId(), Op.EQ); + zoneSearch.done(); + + vmwareDcSearch = createSearchBuilder(); + vmwareDcSearch.and("vmwareDcId", vmwareDcSearch.entity().getVmwareDcId(), Op.EQ); + vmwareDcSearch.done(); + } + + @Override + public VmwareDatacenterZoneMapVO findByZoneId(long zoneId) { + SearchCriteria sc = zoneSearch.create(); + sc.setParameters("zoneId", zoneId); + return findOneBy(sc); + } + + @Override + public VmwareDatacenterZoneMapVO findByVmwareDcId(long vmwareDcId) { + SearchCriteria sc = vmwareDcSearch.create(); + sc.setParameters("vmwareDcId", vmwareDcId); + return findOneBy(sc); + } +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java index fb6d3d6667f..f9f5f7e7e39 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManager.java @@ -20,6 +20,7 @@ import java.io.File; import java.util.List; import java.util.Map; +import com.cloud.agent.api.to.VolumeTO; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.vmware.manager.VmwareStorageManager; import com.cloud.hypervisor.vmware.mo.HostMO; @@ -66,4 +67,6 @@ public interface VmwareManager { String getPrivateVSwitchName(long dcId, HypervisorType hypervisorType); public String getRootDiskController(); + + boolean isLegacyZone(long dcId); } diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java index 9f260f1812c..a604392f7a9 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.rmi.RemoteException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -35,6 +36,8 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd; +import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -51,15 +54,29 @@ import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.ClusterDetailsDao; import com.cloud.dc.ClusterVO; import com.cloud.dc.ClusterVSMMapVO; +import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.ClusterVSMMapDao; +import com.cloud.dc.dao.DataCenterDao; import com.cloud.exception.DiscoveredWithErrorException; +import com.cloud.exception.DiscoveryException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceInUseException; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; +import com.cloud.hypervisor.vmware.LegacyZoneVO; import com.cloud.hypervisor.vmware.VmwareCleanupMaid; +import com.cloud.hypervisor.vmware.VmwareDatacenterService; +import com.cloud.hypervisor.vmware.VmwareDatacenterVO; +import com.cloud.hypervisor.vmware.VmwareDatacenterZoneMapVO; +import com.cloud.hypervisor.vmware.dao.LegacyZoneDao; +import com.cloud.hypervisor.vmware.dao.VmwareDatacenterDao; +import com.cloud.hypervisor.vmware.dao.VmwareDatacenterZoneMapDao; +import com.cloud.hypervisor.vmware.mo.CustomFieldConstants; +import com.cloud.hypervisor.vmware.mo.DatacenterMO; import com.cloud.hypervisor.vmware.mo.DiskControllerType; import com.cloud.hypervisor.vmware.mo.HostFirewallSystemMO; import com.cloud.hypervisor.vmware.mo.HostMO; @@ -67,9 +84,10 @@ import com.cloud.hypervisor.vmware.mo.HypervisorHostHelper; import com.cloud.hypervisor.vmware.mo.TaskMO; import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType; import com.cloud.hypervisor.vmware.mo.VmwareHostType; -import com.cloud.utils.ssh.SshHelper; +import com.cloud.hypervisor.vmware.resource.VmwareContextFactory; import com.cloud.hypervisor.vmware.util.VmwareClient; import com.cloud.hypervisor.vmware.util.VmwareContext; +import com.cloud.hypervisor.vmware.util.VmwareHelper; import com.cloud.network.CiscoNexusVSMDeviceVO; import com.cloud.network.NetworkModel; import com.cloud.network.dao.CiscoNexusVSMDeviceDao; @@ -83,11 +101,11 @@ import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.utils.FileUtil; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; -import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; import com.cloud.utils.db.GlobalLock; +import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; import com.cloud.utils.ssh.SshHelper; @@ -98,8 +116,8 @@ import com.vmware.vim25.HostConnectSpec; import com.vmware.vim25.ManagedObjectReference; -@Local(value = {VmwareManager.class}) -public class VmwareManagerImpl extends ManagerBase implements VmwareManager, VmwareStorageMount, Listener { +@Local(value = {VmwareManager.class, VmwareDatacenterService.class}) +public class VmwareManagerImpl extends ManagerBase implements VmwareManager, VmwareStorageMount, Listener, VmwareDatacenterService { private static final Logger s_logger = Logger.getLogger(VmwareManagerImpl.class); private static final int STARTUP_DELAY = 60000; // 60 seconds @@ -124,6 +142,10 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw @Inject ConfigurationDao _configDao; @Inject ConfigurationServer _configServer; @Inject HypervisorCapabilitiesDao _hvCapabilitiesDao; + @Inject DataCenterDao _dcDao; + @Inject VmwareDatacenterDao _vmwareDcDao; + @Inject VmwareDatacenterZoneMapDao _vmwareDcZoneMapDao; + @Inject LegacyZoneDao _legacyZoneDao; String _mountParent; StorageLayer _storage; @@ -495,7 +517,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw _configServer.updateKeyPairs(); s_logger.info("Copy System VM patch ISO file to secondary storage. source ISO: " + srcIso.getAbsolutePath() + - ", destination: " + destIso.getAbsolutePath()); + ", destination: " + destIso.getAbsolutePath()); try { FileUtil.copyfile(srcIso, destIso); } catch(IOException e) { @@ -544,7 +566,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw assert(isoFile != null); if(!isoFile.exists()) { - s_logger.error("Unable to locate systemvm.iso in your setup at " + isoFile.toString()); + s_logger.error("Unable to locate systemvm.iso in your setup at " + isoFile.toString()); } return isoFile; } @@ -561,7 +583,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw } assert(keyFile != null); if(!keyFile.exists()) { - s_logger.error("Unable to locate id_rsa.cloud in your setup at " + keyFile.toString()); + s_logger.error("Unable to locate id_rsa.cloud in your setup at " + keyFile.toString()); } return keyFile; } @@ -865,4 +887,246 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw public String getRootDiskController() { return _rootDiskController; } + + @Override + public List> getCommands() { + List> cmdList = new ArrayList>(); + cmdList.add(AddVmwareDcCmd.class); + cmdList.add(RemoveVmwareDcCmd.class); + return cmdList; + } + + @Override + @DB + public VmwareDatacenterVO addVmwareDatacenter(AddVmwareDcCmd cmd) throws ResourceInUseException { + VmwareDatacenterVO vmwareDc = null; + Long zoneId = cmd.getZoneId(); + String userName = cmd.getUsername(); + String password = cmd.getPassword(); + String vCenterHost = cmd.getVcenter(); + String vmwareDcName = cmd.getName(); + + // Zone validation + validateZone(zoneId, "add VMware datacenter to zone"); + + VmwareDatacenterZoneMapVO vmwareDcZoneMap = _vmwareDcZoneMapDao.findByZoneId(zoneId); + // Check if zone is associated with VMware DC + if (vmwareDcZoneMap != null) { + throw new CloudRuntimeException("Zone " + zoneId + " is already associated with a VMware datacenter."); + } + + // Validate username, password, VMware DC name and vCenter + if (userName == null) { + throw new InvalidParameterValueException("Missing or invalid parameter username."); + } + + if (password == null) { + throw new InvalidParameterValueException("Missing or invalid parameter username."); + } + + if (vmwareDcName == null) { + throw new InvalidParameterValueException("Missing or invalid parameter name. Please provide valid VMware datacenter name."); + } + + if (vCenterHost == null) { + throw new InvalidParameterValueException("Missing or invalid parameter name. " + + "Please provide valid VMware vCenter server's IP address or fully qualified domain name."); + } + + // Check if DC is already part of zone + // In that case vmware_data_center table should have the DC + vmwareDc = _vmwareDcDao.getVmwareDatacenterByGuid(vmwareDcName + "@" + vCenterHost); + if (vmwareDc != null) { + throw new ResourceInUseException("This DC is already part of other CloudStack zone(s). Cannot add this DC to more zones."); + } + + VmwareContext context = null; + DatacenterMO dcMo = null; + String dcCustomFieldValue; + boolean addDcCustomFieldDef = false; + boolean dcInUse = false; + String guid; + ManagedObjectReference dcMor; + try { + context = VmwareContextFactory.create(vCenterHost, userName, password); + + // Check if DC exists on vCenter + dcMo = new DatacenterMO(context, vmwareDcName); + dcMor = dcMo.getMor(); + if (dcMor == null) { + String msg = "Unable to find VMware DC " + vmwareDcName + " in vCenter " + vCenterHost + ". "; + s_logger.error(msg); + throw new InvalidParameterValueException(msg); + } + + // Check if DC is already associated with another cloudstack deployment + // Get custom field property cloud.zone over this DC + guid = vmwareDcName + "@" + vCenterHost; + + dcCustomFieldValue = dcMo.getCustomFieldValue(CustomFieldConstants.CLOUD_ZONE); + if (dcCustomFieldValue == null) { + addDcCustomFieldDef = true; + } + dcInUse = Boolean.parseBoolean(dcCustomFieldValue); + if (dcInUse) { + throw new ResourceInUseException("This DC is being managed by other CloudStack deployment. Cannot add this DC to zone."); + } + + // Add DC to database into vmware_data_center table + vmwareDc = new VmwareDatacenterVO(guid, vmwareDcName, vCenterHost, userName, password); + Transaction txn = Transaction.currentTxn(); + try { + txn.start(); + vmwareDc = _vmwareDcDao.persist(vmwareDc); + txn.commit(); + } catch (Exception e) { + txn.rollback(); + s_logger.error("Failed to persist VMware datacenter details to database. Exception: " + e.getMessage()); + throw new CloudRuntimeException(e.getMessage()); + } + + // Map zone with vmware datacenter + vmwareDcZoneMap = new VmwareDatacenterZoneMapVO(zoneId, vmwareDc.getId()); + + txn = Transaction.currentTxn(); + try { + txn.start(); + vmwareDcZoneMap = _vmwareDcZoneMapDao.persist(vmwareDcZoneMap); + txn.commit(); + } catch (Exception e) { + txn.rollback(); + s_logger.error("Failed to associate VMware datacenter with zone " + zoneId + ". Exception: " + e.getMessage()); + // Removing VMware datacenter from vmware_data_center table because association with zone failed. + _vmwareDcDao.remove(vmwareDcZoneMap.getId()); + throw new CloudRuntimeException(e.getMessage()); + } + + // Set custom field for this DC + if (addDcCustomFieldDef) { + dcMo.ensureCustomFieldDef(CustomFieldConstants.CLOUD_ZONE); + } + dcMo.setCustomFieldValue(CustomFieldConstants.CLOUD_ZONE, "true"); + + } catch (Throwable e) { + String msg = "Failed to add VMware DC to zone "; + if (e instanceof RemoteException) { + msg = "Encountered remote exception at vCenter. " + VmwareHelper.getExceptionMessage(e); + } else { + msg += "due to : " + e.getMessage(); + } + throw new CloudRuntimeException(msg); + } finally { + if (context != null) + context.close(); + context = null; + } + return vmwareDc; + } + + + @Override + public boolean removeVmwareDatacenter(RemoveVmwareDcCmd cmd) throws ResourceInUseException { + Long zoneId = cmd.getZoneId(); + // Validate zone + validateZone(zoneId, "remove VMware datacenter from zone"); + + // Get DC associated with this zone + VmwareDatacenterZoneMapVO vmwareDcZoneMap; + VmwareDatacenterVO vmwareDatacenter; + String vmwareDcName; + long vmwareDcId; + String vCenterHost; + String userName; + String password; + DatacenterMO dcMo = null; + Transaction txn; + + vmwareDcZoneMap = _vmwareDcZoneMapDao.findByZoneId(zoneId); + // Check if zone is associated with VMware DC + if (vmwareDcZoneMap == null) { + throw new CloudRuntimeException("Zone " + zoneId + " is not associated with any VMware datacenter."); + } + + vmwareDcId = vmwareDcZoneMap.getVmwareDcId(); + vmwareDatacenter = _vmwareDcDao.findById(vmwareDcId); + vmwareDcName = vmwareDatacenter.getVmwareDatacenterName(); + vCenterHost = vmwareDatacenter.getVcenterHost(); + userName = vmwareDatacenter.getUser(); + password = vmwareDatacenter.getPassword(); + txn = Transaction.currentTxn(); + try { + txn.start(); + // Remove the VMware datacenter entry in table vmware_data_center + _vmwareDcDao.remove(vmwareDcId); + // Remove the map entry in table vmware_data_center_zone_map + _vmwareDcZoneMapDao.remove(vmwareDcZoneMap.getId()); + txn.commit(); + } catch (Exception e) { + s_logger.info("Caught exception when trying to delete VMware datacenter record." + e.getMessage()); + throw new CloudRuntimeException("Failed to delete VMware datacenter."); + } + + // Construct context + VmwareContext context = null; + try { + context = VmwareContextFactory.create(vCenterHost, userName, password); + + // Check if DC exists on vCenter + try { + dcMo = new DatacenterMO(context, vmwareDcName); + } catch(Throwable t) { + String msg = "Unable to find DC " + vmwareDcName + " in vCenter " + vCenterHost; + s_logger.error(msg); + throw new DiscoveryException(msg); + } + + assert (dcMo != null); + + // Reset custom field property cloud.zone over this DC + dcMo.setCustomFieldValue(CustomFieldConstants.CLOUD_ZONE, "false"); + s_logger.info("Sucessfully reset custom field property cloud.zone over DC " + vmwareDcName); + } catch (Exception e) { + String msg = "Unable to reset custom field property cloud.zone over DC " + vmwareDcName + + " due to : " + VmwareHelper.getExceptionMessage(e); + s_logger.error(msg); + throw new CloudRuntimeException(msg); + } finally { + if (context != null) + context.close(); + context = null; + } + return true; + } + + private void validateZone(Long zoneId, String errStr) throws ResourceInUseException { + // Check if zone with specified id exists + DataCenterVO zone = _dcDao.findById(zoneId); + if (zone == null) { + InvalidParameterValueException ex = new InvalidParameterValueException( + "Can't find zone by the id specified."); + throw ex; + } + + // Check if zone has resources? - For now look for clusters + List clusters = _clusterDao.listByZoneId(zoneId); + if (clusters != null && clusters.size() > 0) { + // Look for VMware hypervisor. + for (ClusterVO cluster : clusters) { + if (cluster.getHypervisorType().equals(HypervisorType.VMware)) { + throw new ResourceInUseException("Zone has one or more clusters." + + " Can't " + errStr + " which already has clusters."); + } + } + } + } + + @Override + public boolean isLegacyZone(long dcId) { + boolean isLegacyZone = false; + LegacyZoneVO legacyZoneVo = _legacyZoneDao.findById(dcId); + if (legacyZoneVo != null) { + isLegacyZone = true; + } + return isLegacyZone; + } } diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java index 9f1351e96f3..4ae0f305d99 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java @@ -328,7 +328,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { workerVm = vmMo; // attach volume to worker VM - String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumePath); + String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk"); vmMo.attachDisk(new String[] { datastoreVolumePath }, morDs); } } @@ -491,6 +491,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { hyperHost, volumeId, new DatastoreMO(context, morDatastore), secondaryStorageURL, volumePath); + deleteVolumeDirOnSecondaryStorage(volumeId, secondaryStorageURL); } return new CopyVolumeAnswer(cmd, true, null, result.first(), result.second()); } catch (Throwable e) { @@ -1059,7 +1060,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { } //attach volume to worker VM - String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), volumePath); + String datastoreVolumePath = getVolumePathInDatastore(dsMo, volumePath + ".vmdk"); workerVm.attachDisk(new String[] { datastoreVolumePath }, morDs); vmMo = workerVm; } @@ -1080,6 +1081,12 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { } } + private String getVolumePathInDatastore(DatastoreMO dsMo, String volumeFileName) throws Exception { + String datastoreVolumePath = dsMo.searchFileInSubFolders(volumeFileName, true); + assert (datastoreVolumePath != null) : "Virtual disk file missing from datastore."; + return datastoreVolumePath; + } + private Pair copyVolumeFromSecStorage(VmwareHypervisorHost hyperHost, long volumeId, DatastoreMO dsMo, String secStorageUrl, String exportName) throws Exception { @@ -1438,4 +1445,26 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { workingVM = hyperHost.findVmOnHyperHost(uniqueName); return workingVM; } + + + + private String deleteVolumeDirOnSecondaryStorage(long volumeId, String secStorageUrl) throws Exception { + String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl); + String volumeMountRoot = secondaryMountPoint + "/" + getVolumeRelativeDirInSecStroage(volumeId); + + return deleteDir(volumeMountRoot); + } + + private String deleteDir(String dir) { + synchronized(dir.intern()) { + Script command = new Script(false, "rm", _timeout, s_logger); + command.add("-rf"); + command.add(dir); + return command.execute(); + } + } + + private static String getVolumeRelativeDirInSecStroage(long volumeId) { + return "volumes/" + volumeId; + } } diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 630d1b42e50..5944cc864f1 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -37,6 +37,7 @@ import java.util.Random; import java.util.TimeZone; import java.util.UUID; +import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; @@ -73,6 +74,9 @@ import com.cloud.agent.api.CreateVolumeFromSnapshotCommand; import com.cloud.agent.api.DeleteStoragePoolCommand; import com.cloud.agent.api.DeleteVMSnapshotAnswer; import com.cloud.agent.api.DeleteVMSnapshotCommand; +import com.cloud.agent.api.MigrateWithStorageAnswer; +import com.cloud.agent.api.MigrateWithStorageCommand; +import com.cloud.agent.api.UnregisterVMCommand; import com.cloud.agent.api.GetDomRVersionAnswer; import com.cloud.agent.api.GetDomRVersionCmd; import com.cloud.agent.api.GetHostStatsAnswer; @@ -127,7 +131,6 @@ import com.cloud.agent.api.StopCommand; import com.cloud.agent.api.StoragePoolInfo; import com.cloud.agent.api.UnPlugNicAnswer; import com.cloud.agent.api.UnPlugNicCommand; -import com.cloud.agent.api.UnregisterVMCommand; import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.ValidateSnapshotAnswer; import com.cloud.agent.api.ValidateSnapshotCommand; @@ -162,14 +165,16 @@ import com.cloud.agent.api.routing.VmDataCommand; import com.cloud.agent.api.routing.VpnUsersCfgCommand; import com.cloud.agent.api.storage.CopyVolumeAnswer; import com.cloud.agent.api.storage.CopyVolumeCommand; +import com.cloud.agent.api.storage.CreateVolumeOVACommand; +import com.cloud.agent.api.storage.CreateVolumeOVAAnswer; +import com.cloud.agent.api.storage.MigrateVolumeAnswer; +import com.cloud.agent.api.storage.MigrateVolumeCommand; +import com.cloud.agent.api.storage.PrepareOVAPackingAnswer; +import com.cloud.agent.api.storage.PrepareOVAPackingCommand; import com.cloud.agent.api.storage.CreateAnswer; import com.cloud.agent.api.storage.CreateCommand; import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer; -import com.cloud.agent.api.storage.CreateVolumeOVAAnswer; -import com.cloud.agent.api.storage.CreateVolumeOVACommand; import com.cloud.agent.api.storage.DestroyCommand; -import com.cloud.agent.api.storage.PrepareOVAPackingAnswer; -import com.cloud.agent.api.storage.PrepareOVAPackingCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; import com.cloud.agent.api.storage.ResizeVolumeAnswer; @@ -221,11 +226,14 @@ import com.cloud.serializer.GsonHelper; import com.cloud.storage.Storage; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Volume; +import com.cloud.storage.VolumeManager; +import com.cloud.storage.VolumeManagerImpl; import com.cloud.storage.resource.StoragePoolResource; import com.cloud.storage.template.TemplateInfo; import com.cloud.utils.DateUtil; import com.cloud.utils.Pair; import com.cloud.utils.StringUtils; +import com.cloud.utils.component.ComponentContext; import com.cloud.utils.db.DB; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.ExceptionUtil; @@ -275,9 +283,14 @@ import com.vmware.vim25.VirtualMachineConfigSpec; import com.vmware.vim25.VirtualMachineFileInfo; import com.vmware.vim25.VirtualMachineGuestOsIdentifier; import com.vmware.vim25.VirtualMachinePowerState; +import com.vmware.vim25.VirtualMachineRelocateSpec; +import com.vmware.vim25.VirtualMachineRelocateSpecDiskLocator; import com.vmware.vim25.VirtualMachineRuntimeInfo; import com.vmware.vim25.VirtualSCSISharing; +import java.util.HashSet; +import java.util.Set; +import java.util.Map.Entry; public class VmwareResource implements StoragePoolResource, ServerResource, VmwareHostService { private static final Logger s_logger = Logger.getLogger(VmwareResource.class); @@ -288,6 +301,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa protected final int _shutdown_waitMs = 300000; // wait up to 5 minutes for shutdown + @Inject + protected VolumeManager volMgr; + // out an operation protected final int _retry = 24; protected final int _sleep = 10000; @@ -398,6 +414,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa answer = execute((PrepareForMigrationCommand) cmd); } else if (clz == MigrateCommand.class) { answer = execute((MigrateCommand) cmd); + } else if (clz == MigrateWithStorageCommand.class) { + answer = execute((MigrateWithStorageCommand) cmd); + } else if (clz == MigrateVolumeCommand.class) { + answer = execute((MigrateVolumeCommand) cmd); } else if (clz == DestroyCommand.class) { answer = execute((DestroyCommand) cmd); } else if (clz == CreateStoragePoolCommand.class) { @@ -1424,7 +1444,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa try { VmwareHypervisorHost hyperHost = getHyperHost(context); - String vmName = cmd.getInstanceName(); + String vmName = cmd.getVmName(); VirtualMachineMO vmMo = hyperHost.findVmOnHyperHost(vmName); if(vmMo == null) { @@ -1917,7 +1937,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa for (IpAliasTO ipAliasTO : revokedIpAliasTOs) { args = args + ipAliasTO.getAlias_count()+":"+ipAliasTO.getRouterip()+":"+ipAliasTO.getNetmask()+"-"; } - args = args + " " ; + args = args + "- " ; for (IpAliasTO ipAliasTO : activeIpAliasTOs) { args = args + ipAliasTO.getAlias_count()+":"+ipAliasTO.getRouterip()+":"+ipAliasTO.getNetmask()+"-"; } @@ -2405,6 +2425,9 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[totalChangeDevices]; int i = 0; + int ideUnitNumber = 0; + int scsiUnitNumber =0; + int nicUnitNumber = 0; int ideControllerKey = vmMo.getIDEDeviceControllerKey(); int scsiControllerKey = vmMo.getScsiDeviceControllerKey(); int controllerKey; @@ -2429,7 +2452,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); Pair isoInfo = VmwareHelper.prepareIsoDevice(vmMo, String.format("[%s] systemvm/%s", secDsMo.getName(), mgr.getSystemVMIsoFileNameOnDatastore()), - secDsMo.getMor(), true, true, i, i + 1); + secDsMo.getMor(), true, true, ideUnitNumber++, i + 1); deviceConfigSpecArray[i].setDevice(isoInfo.first()); if (isoInfo.second()) { if(s_logger.isDebugEnabled()) @@ -2440,7 +2463,6 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa s_logger.debug("Prepare ISO volume at existing device " + _gson.toJson(isoInfo.first())); deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT); } - i++; } else { // we will always plugin a CDROM device if (volIso != null && volIso.getPath() != null && !volIso.getPath().isEmpty()) { @@ -2449,7 +2471,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa assert (isoDatastoreInfo.second() != null); deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); - Pair isoInfo = VmwareHelper.prepareIsoDevice(vmMo, isoDatastoreInfo.first(), isoDatastoreInfo.second(), true, true, i, i + 1); + Pair isoInfo = VmwareHelper.prepareIsoDevice(vmMo, isoDatastoreInfo.first(), isoDatastoreInfo.second(), true, true, ideUnitNumber++, i + 1); deviceConfigSpecArray[i].setDevice(isoInfo.first()); if (isoInfo.second()) { if(s_logger.isDebugEnabled()) @@ -2462,7 +2484,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } else { deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); - Pair isoInfo = VmwareHelper.prepareIsoDevice(vmMo, null, null, true, true, i, i + 1); + Pair isoInfo = VmwareHelper.prepareIsoDevice(vmMo, null, null, true, true, ideUnitNumber++, i + 1); deviceConfigSpecArray[i].setDevice(isoInfo.first()); if (isoInfo.second()) { if(s_logger.isDebugEnabled()) @@ -2476,9 +2498,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.EDIT); } } - i++; } - + i++; for (VolumeTO vol : sortVolumesByDeviceId(disks)) { deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); @@ -2505,24 +2526,29 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa Pair volumeDsDetails = dataStoresDetails.get(vol.getPoolUuid()); assert (volumeDsDetails != null); VirtualDevice device; - datastoreDiskPath = String.format("[%s] %s.vmdk", volumeDsDetails.second().getName(), vol.getPath()); + + datastoreDiskPath = volumeDsDetails.second().searchFileInSubFolders(vol.getPath() + ".vmdk", true); + String chainInfo = vol.getChainInfo(); if (chainInfo != null && !chainInfo.isEmpty()) { String[] diskChain = _gson.fromJson(chainInfo, String[].class); if (diskChain == null || diskChain.length < 1) { s_logger.warn("Empty previously-saved chain info, fall back to the original"); - device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(), i, i + 1); + device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(), + (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1); } else { s_logger.info("Attach the disk with stored chain info: " + chainInfo); for (int j = 0; j < diskChain.length; j++) { diskChain[j] = String.format("[%s] %s", volumeDsDetails.second().getName(), diskChain[j]); } - device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, diskChain, volumeDsDetails.first(), i, i + 1); + device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, diskChain, volumeDsDetails.first(), + (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1); } } else { - device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(), i, i + 1); + device = VmwareHelper.prepareDiskDevice(vmMo, controllerKey, new String[] { datastoreDiskPath }, volumeDsDetails.first(), + (controllerKey==ideControllerKey)?ideUnitNumber++:scsiUnitNumber++, i + 1); } deviceConfigSpecArray[i].setDevice(device); deviceConfigSpecArray[i].setOperation(VirtualDeviceConfigSpecOperation.ADD); @@ -2551,10 +2577,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa ManagedObjectReference dvsMor = dataCenterMo.getDvSwitchMor(networkInfo.first()); dvSwitchUuid = dataCenterMo.getDvSwitchUuid(dvsMor); s_logger.info("Preparing NIC device on dvSwitch : " + dvSwitchUuid); - nic = VmwareHelper.prepareDvNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(), dvSwitchUuid, nicTo.getMac(), i, i + 1, true, true); + nic = VmwareHelper.prepareDvNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(), dvSwitchUuid, nicTo.getMac(), nicUnitNumber++, i + 1, true, true); } else { s_logger.info("Preparing NIC device on network " + networkInfo.second()); - nic = VmwareHelper.prepareNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(), nicTo.getMac(), i, i + 1, true, true); + nic = VmwareHelper.prepareNicDevice(vmMo, networkInfo.first(), nicDeviceType, networkInfo.second(), nicTo.getMac(), nicUnitNumber++, i + 1, true, true); } deviceConfigSpecArray[i] = new VirtualDeviceConfigSpec(); @@ -3367,6 +3393,254 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } } + protected Answer execute(MigrateWithStorageCommand cmd) { + + if (s_logger.isInfoEnabled()) { + s_logger.info("Executing resource MigrateWithStorageCommand: " + _gson.toJson(cmd)); + } + + VirtualMachineTO vmTo = cmd.getVirtualMachine(); + final String vmName = vmTo.getName(); + + State state = null; + synchronized (_vms) { + state = _vms.get(vmName); + _vms.put(vmName, State.Stopping); + } + + VmwareHypervisorHost srcHyperHost = null; + VmwareHypervisorHost tgtHyperHost = null; + VirtualMachineMO vmMo = null; + + ManagedObjectReference morDsAtTarget = null; + ManagedObjectReference morDsAtSource = null; + ManagedObjectReference morDc = null; + ManagedObjectReference morDcOfTargetHost = null; + ManagedObjectReference morTgtHost = new ManagedObjectReference(); + VirtualMachineRelocateSpec relocateSpec = new VirtualMachineRelocateSpec(); + List diskLocators = new ArrayList(); + VirtualMachineRelocateSpecDiskLocator diskLocator = null; + + boolean isFirstDs = true; + String srcDiskName = ""; + String srcDsName = ""; + String tgtDsName = ""; + String tgtDsNfsHost; + String tgtDsNfsPath; + int tgtDsNfsPort; + VolumeTO volume; + StorageFilerTO filerTo; + Set mountedDatastoresAtSource = new HashSet(); + + Map volToFiler = cmd.getVolumeToFiler(); + String tgtHost = cmd.getTargetHost(); + String tgtHostMorInfo = tgtHost.split("@")[0]; + morTgtHost.setType(tgtHostMorInfo.split(":")[0]); + morTgtHost.setValue(tgtHostMorInfo.split(":")[1]); + + try { + srcHyperHost = getHyperHost(getServiceContext()); + tgtHyperHost = new HostMO(getServiceContext(), morTgtHost); + morDc = srcHyperHost.getHyperHostDatacenter(); + morDcOfTargetHost = tgtHyperHost.getHyperHostDatacenter(); + if (morDc != morDcOfTargetHost) { + String msg = "Source host & target host are in different datacentesr"; + throw new CloudRuntimeException(msg); + } + VmwareManager mgr = tgtHyperHost.getContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME); + + // find VM through datacenter (VM is not at the target host yet) + vmMo = srcHyperHost.findVmOnPeerHyperHost(vmName); + if (vmMo == null) { + String msg = "VM " + vmName + " does not exist in VMware datacenter " + morDc.getValue(); + s_logger.error(msg); + throw new Exception(msg); + } + + // Get details of each target datastore & attach to source host. + for (Entry entry : volToFiler.entrySet()) { + volume = entry.getKey(); + filerTo = entry.getValue(); + + srcDsName = volume.getPoolUuid().replace("-", ""); + tgtDsName = filerTo.getUuid().replace("-", ""); + tgtDsNfsHost = filerTo.getHost(); + tgtDsNfsPath = filerTo.getPath(); + tgtDsNfsPort = filerTo.getPort(); + + s_logger.debug("Preparing spec for volume : " + volume.getName()); + morDsAtTarget = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(tgtHyperHost, filerTo.getUuid()); + if (morDsAtTarget == null) { + String msg = "Unable to find the mounted datastore with uuid " + morDsAtTarget + " to execute MigrateWithStorageCommand"; + s_logger.error(msg); + throw new Exception(msg); + } + morDsAtSource = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(srcHyperHost, filerTo.getUuid()); + if (morDsAtSource == null) { + morDsAtSource = srcHyperHost.mountDatastore(false, tgtDsNfsHost, tgtDsNfsPort, tgtDsNfsPath, tgtDsName); + if (morDsAtSource == null) { + throw new Exception("Unable to mount datastore " + tgtDsNfsHost + ":/" + tgtDsNfsPath + " on " + _hostName); + } + mountedDatastoresAtSource.add(tgtDsName); + s_logger.debug("Mounted datastore " + tgtDsNfsHost + ":/" + tgtDsNfsPath + " on " + _hostName); + } + + if (isFirstDs) { + relocateSpec.setDatastore(morDsAtSource); + isFirstDs = false; + } + srcDiskName = String.format("[%s] %s.vmdk", srcDsName, volume.getPath()); + diskLocator = new VirtualMachineRelocateSpecDiskLocator(); + diskLocator.setDatastore(morDsAtSource); + diskLocator.setDiskId(getVirtualDiskInfo(vmMo, srcDiskName)); + + diskLocators.add(diskLocator); + + } + relocateSpec.getDisk().addAll(diskLocators); + + // Prepare network at target before migration + NicTO[] nics = vmTo.getNics(); + for (NicTO nic : nics) { + // prepare network on the host + prepareNetworkFromNicInfo(new HostMO(getServiceContext(), morTgtHost), nic, false, vmTo.getType()); + } + + // Ensure secondary storage mounted on target host + String secStoreUrl = mgr.getSecondaryStorageStoreUrl(Long.parseLong(_dcId)); + if(secStoreUrl == null) { + String msg = "secondary storage for dc " + _dcId + " is not ready yet?"; + throw new Exception(msg); + } + mgr.prepareSecondaryStorageStore(secStoreUrl); + ManagedObjectReference morSecDs = prepareSecondaryDatastoreOnHost(secStoreUrl); + if (morSecDs == null) { + String msg = "Failed to prepare secondary storage on host, secondary store url: " + secStoreUrl; + throw new Exception(msg); + } + + // Change datastore + if (!vmMo.changeDatastore(relocateSpec)) { + throw new Exception("Change datastore operation failed during storage migration"); + } else { + s_logger.debug("Successfully migrated storage of VM " + vmName + " to target datastore(s)"); + } + + // Change host + ManagedObjectReference morPool = tgtHyperHost.getHyperHostOwnerResourcePool(); + if (!vmMo.migrate(morPool, tgtHyperHost.getMor())) { + throw new Exception("Change datastore operation failed during storage migration"); + } else { + s_logger.debug("Successfully relocated VM " + vmName + " from " + _hostName + " to " + tgtHyperHost.getHyperHostName()); + } + + state = State.Stopping; + List volumeToList = null; + return new MigrateWithStorageAnswer(cmd, volumeToList); + } catch (Throwable e) { + if (e instanceof RemoteException) { + s_logger.warn("Encountered remote exception at vCenter, invalidating VMware session context"); + invalidateServiceContext(); + } + + String msg = "MigrationCommand failed due to " + VmwareHelper.getExceptionMessage(e); + s_logger.warn(msg, e); + return new MigrateWithStorageAnswer(cmd, (Exception) e); + } finally { + // Cleanup datastores mounted on source host + for(String mountedDatastore : mountedDatastoresAtSource) { + s_logger.debug("Attempting to unmount datastore " + mountedDatastore + " at " + _hostName); + try { + srcHyperHost.unmountDatastore(mountedDatastore); + } catch (Exception unmountEx) { + s_logger.debug("Failed to unmount datastore " + mountedDatastore + " at " + _hostName + + ". Seems the datastore is still being used by " + _hostName + + ". Please unmount manually to cleanup."); + } + s_logger.debug("Successfully unmounted datastore " + mountedDatastore + " at " + _hostName); + } + synchronized (_vms) { + _vms.put(vmName, state); + } + } + } + + private Answer execute(MigrateVolumeCommand cmd) { + String volumePath = cmd.getVolumePath(); + StorageFilerTO poolTo = cmd.getPool(); + + if (s_logger.isInfoEnabled()) { + s_logger.info("Executing resource MigrateVolumeCommand: " + _gson.toJson(cmd)); + } + + VmwareContext context = getServiceContext(); + VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); + final String vmName = volMgr.getVmNameFromVolumeId(cmd.getVolumeId()); + + VirtualMachineMO vmMo = null; + VmwareHypervisorHost srcHyperHost = null; + + ManagedObjectReference morDs = null; + ManagedObjectReference morDc = null; + VirtualMachineRelocateSpec relocateSpec = new VirtualMachineRelocateSpec(); + List diskLocators = new ArrayList(); + VirtualMachineRelocateSpecDiskLocator diskLocator = null; + + String srcDiskName = ""; + String srcDsName = ""; + String tgtDsName = ""; + + try { + srcHyperHost = getHyperHost(getServiceContext()); + morDc = srcHyperHost.getHyperHostDatacenter(); + srcDsName = volMgr.getStoragePoolOfVolume(cmd.getVolumeId()); + tgtDsName = poolTo.getUuid().replace("-", ""); + + // find VM through datacenter (VM is not at the target host yet) + vmMo = srcHyperHost.findVmOnPeerHyperHost(vmName); + if (vmMo == null) { + String msg = "VM " + vmName + " does not exist in VMware datacenter " + morDc.getValue(); + s_logger.error(msg); + throw new Exception(msg); + } + morDs = HypervisorHostHelper.findDatastoreWithBackwardsCompatibility(srcHyperHost, tgtDsName); + if (morDs == null) { + String msg = "Unable to find the mounted datastore with name " + tgtDsName + " to execute MigrateVolumeCommand"; + s_logger.error(msg); + throw new Exception(msg); + } + + srcDiskName = String.format("[%s] %s.vmdk", srcDsName, volumePath); + diskLocator = new VirtualMachineRelocateSpecDiskLocator(); + diskLocator.setDatastore(morDs); + diskLocator.setDiskId(getVirtualDiskInfo(vmMo, srcDiskName)); + + diskLocators.add(diskLocator); + relocateSpec.getDisk().add(diskLocator); + + // Change datastore + if (!vmMo.changeDatastore(relocateSpec)) { + throw new Exception("Change datastore operation failed during volume migration"); + } else { + s_logger.debug("Successfully migrated volume " + volumePath + " to target datastore " + tgtDsName); + } + + return new MigrateVolumeAnswer(cmd, true, null, volumePath); + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString(); + s_logger.error(msg, e); + return new MigrateVolumeAnswer(cmd, false, msg, null); + } + } + + private int getVirtualDiskInfo(VirtualMachineMO vmMo, String srcDiskName) throws Exception { + Pair deviceInfo = vmMo.getDiskDevice(srcDiskName, false); + if(deviceInfo == null) { + throw new Exception("No such disk device: " + srcDiskName); + } + return deviceInfo.first().getKey(); + } + private VmwareHypervisorHost getTargetHyperHost(DatacenterMO dcMo, String destIp) throws Exception { VmwareManager mgr = dcMo.getContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME); @@ -3479,7 +3753,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } DatastoreMO dsMo = new DatastoreMO(getServiceContext(), morDs); - String datastoreVolumePath = String.format("[%s] %s.vmdk", dsMo.getName(), cmd.getVolumePath()); + String datastoreVolumePath = dsMo.searchFileInSubFolders(cmd.getVolumePath() + ".vmdk", true); + assert (datastoreVolumePath != null) : "Virtual disk file must exist in specified datastore for attach/detach operations."; AttachVolumeAnswer answer = new AttachVolumeAnswer(cmd, cmd.getDeviceId()); if (cmd.getAttach()) { @@ -5282,6 +5557,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa _guestTrafficInfo = (VmwareTrafficLabel) params.get("guestTrafficInfo"); _publicTrafficInfo = (VmwareTrafficLabel) params.get("publicTrafficInfo"); VmwareContext context = getServiceContext(); + volMgr = ComponentContext.inject(VolumeManagerImpl.class); try { VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME); mgr.setupResourceStartupParams(params); diff --git a/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/command/admin/zone/AddVmwareDcCmd.java b/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/command/admin/zone/AddVmwareDcCmd.java new file mode 100644 index 00000000000..317452b7b7f --- /dev/null +++ b/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/command/admin/zone/AddVmwareDcCmd.java @@ -0,0 +1,123 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.admin.zone; + +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.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.VmwareDatacenterResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.log4j.Logger; + +import com.cloud.exception.DiscoveryException; +import com.cloud.exception.ResourceInUseException; +import com.cloud.hypervisor.vmware.VmwareDatacenterService; +import com.cloud.hypervisor.vmware.VmwareDatacenterVO; +import com.cloud.user.Account; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name = "addVmwareDc", description="Adds a VMware datacenter to specified zone", responseObject=VmwareDatacenterResponse.class) +public class AddVmwareDcCmd extends BaseCmd { + + @Inject public VmwareDatacenterService _vmwareDatacenterService; + + public static final Logger s_logger = Logger.getLogger(AddVmwareDcCmd.class.getName()); + + private static final String s_name = "addvmwaredcresponse"; + + @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="Name of VMware datacenter to be added to specified zone.") + private String name; + + @Parameter(name=ApiConstants.VCENTER, type=CommandType.STRING, required=true, description="The name/ip of vCenter. Make sure it is IP address or full qualified domain name for host running vCenter server.") + private String vCenter; + + @Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required=false, description="The Username required to connect to resource.") + private String username; + + @Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required=false, description="The password for specified username.") + private String password; + + @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class, required=true, description="The Zone ID.") + private Long zoneId; + + public String getName() { + return name; + } + + public String getVcenter() { + return vCenter; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + public Long getZoneId() { + return zoneId; + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() { + try { + VmwareDatacenterResponse response = new VmwareDatacenterResponse(); + VmwareDatacenterVO result = _vmwareDatacenterService.addVmwareDatacenter(this); + if (result != null){ + response.setId(result.getUuid()); + response.setName(result.getVmwareDatacenterName()); + response.setResponseName(getCommandName()); + response.setObjectName("vmwaredc"); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add VMware Datacenter to zone."); + } + this.setResponseObject(response); + } catch (DiscoveryException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + } catch (ResourceInUseException ex) { + s_logger.warn("Exception: ", ex); + ServerApiException e = new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + for (String proxyObj : ex.getIdProxyList()) { + e.addProxyObject(proxyObj); + } + throw e; + } catch (IllegalArgumentException ex) { + throw new IllegalArgumentException(ex.getMessage()); + } catch (CloudRuntimeException runtimeEx) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeEx.getMessage()); + } + } +} diff --git a/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/command/admin/zone/RemoveVmwareDcCmd.java b/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/command/admin/zone/RemoveVmwareDcCmd.java new file mode 100644 index 00000000000..a74c91bf753 --- /dev/null +++ b/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/command/admin/zone/RemoveVmwareDcCmd.java @@ -0,0 +1,99 @@ +// 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.command.admin.zone; + +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.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.BaseCmd.CommandType; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.log4j.Logger; + +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.DiscoveryException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.NetworkRuleConflictException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceInUseException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.hypervisor.vmware.VmwareDatacenterService; +import com.cloud.network.element.CiscoNexusVSMElementService; +import com.cloud.user.Account; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name = "removeVmwareDc", responseObject=SuccessResponse.class, description="Remove a VMware datacenter from a zone.") +public class RemoveVmwareDcCmd extends BaseCmd { + + @Inject public VmwareDatacenterService _vmwareDatacenterService; + + public static final Logger s_logger = Logger.getLogger(AddVmwareDcCmd.class.getName()); + + private static final String s_name = "removevmwaredcresponse"; + + @Parameter(name=ApiConstants.ZONE_ID, type=CommandType.UUID, entityType=ZoneResponse.class, required=true, + description="The id of Zone from which VMware datacenter has to be removed.") + + private Long zoneId; + + public Long getZoneId() { + return zoneId; + } + + @Override + public void execute() { + SuccessResponse response = new SuccessResponse(); + try { + boolean result = _vmwareDatacenterService.removeVmwareDatacenter(this); + if (result) { + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove VMware datacenter from zone"); + } + } catch (ResourceInUseException ex) { + s_logger.warn("The zone has one or more resources (like cluster), hence not able to remove VMware datacenter from zone." + + " Please remove all resource from zone, and retry. Exception: ", ex); + ServerApiException e = new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); + for (String proxyObj : ex.getIdProxyList()) { + e.addProxyObject(proxyObj); + } + throw e; + } catch (IllegalArgumentException ex) { + throw new IllegalArgumentException(ex.getMessage()); + } catch (CloudRuntimeException runtimeEx) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeEx.getMessage()); + } + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + +} diff --git a/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/response/VmwareDatacenterResponse.java b/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/response/VmwareDatacenterResponse.java new file mode 100644 index 00000000000..420320baf48 --- /dev/null +++ b/plugins/hypervisors/vmware/src/org/apache/cloudstack/api/response/VmwareDatacenterResponse.java @@ -0,0 +1,51 @@ +// 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.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import com.cloud.hypervisor.vmware.VmwareDatacenter; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +@EntityReference(value = VmwareDatacenter.class) +public class VmwareDatacenterResponse extends BaseResponse { + @SerializedName(ApiConstants.ID) @Param(description="The VMware Datacenter ID") + private String id; + + @SerializedName(ApiConstants.NAME) @Param(description="The VMware Datacenter name") + private String name; + + public String getName() { + return name; + } + + public String getId() { + return id; + } + + public void setName(String name) { + this.name = name; + } + + public void setId(String id) { + this.id = id; + } +} diff --git a/plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java b/plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java new file mode 100644 index 00000000000..11be609bcf7 --- /dev/null +++ b/plugins/hypervisors/vmware/src/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategy.java @@ -0,0 +1,212 @@ +/* + * 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.storage.motion; + +import java.util.HashMap; +import java.util.Map; +import java.util.List; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.MigrateWithStorageAnswer; +import com.cloud.agent.api.MigrateWithStorageCommand; +import com.cloud.agent.api.MigrateWithStorageCompleteAnswer; +import com.cloud.agent.api.MigrateWithStorageCompleteCommand; +import com.cloud.agent.api.MigrateWithStorageReceiveAnswer; +import com.cloud.agent.api.MigrateWithStorageReceiveCommand; +import com.cloud.agent.api.MigrateWithStorageSendAnswer; +import com.cloud.agent.api.MigrateWithStorageSendCommand; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.host.Host; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.StoragePool; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.dao.VMInstanceDao; + +@Component +public class VmwareStorageMotionStrategy implements DataMotionStrategy { + private static final Logger s_logger = Logger.getLogger(VmwareStorageMotionStrategy.class); + @Inject AgentManager agentMgr; + @Inject VolumeDao volDao; + @Inject VolumeDataFactory volFactory; + @Inject PrimaryDataStoreDao storagePoolDao; + @Inject VMInstanceDao instanceDao; + + @Override + public boolean canHandle(DataObject srcData, DataObject destData) { + return false; + } + + @Override + public boolean canHandle(Map volumeMap, Host srcHost, Host destHost) { + if (srcHost.getHypervisorType() == HypervisorType.VMware && destHost.getHypervisorType() == HypervisorType.VMware) { + s_logger.debug(this.getClass() + " can handle the request because the hosts have VMware hypervisor"); + return true; + } + return false; + } + + @Override + public Void copyAsync(DataObject srcData, DataObject destData, + AsyncCompletionCallback callback) { + CopyCommandResult result = new CopyCommandResult(null, null); + result.setResult("Unsupported operation requested for copying data."); + callback.complete(result); + + return null; + } + + @Override + public Void copyAsync(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, + AsyncCompletionCallback callback) { + Answer answer = null; + String errMsg = null; + try { + VMInstanceVO instance = instanceDao.findById(vmTo.getId()); + if (instance != null) { + if (srcHost.getClusterId() == destHost.getClusterId()) { + answer = migrateVmWithVolumesWithinCluster(instance, vmTo, srcHost, destHost, volumeMap); + } else { + answer = migrateVmWithVolumesAcrossCluster(instance, vmTo, srcHost, destHost, volumeMap); + } + } else { + throw new CloudRuntimeException("Unsupported operation requested for moving data."); + } + } catch (Exception e) { + s_logger.error("copy failed", e); + errMsg = e.toString(); + } + + CopyCommandResult result = new CopyCommandResult(null, answer); + result.setResult(errMsg); + callback.complete(result); + return null; + } + + private Answer migrateVmWithVolumesAcrossCluster(VMInstanceVO vm, VirtualMachineTO to, Host srcHost, + Host destHost, Map volumeToPool) throws AgentUnavailableException { + + // Initiate migration of a virtual machine with it's volumes. + try { + Map volumeToFilerto = new HashMap(); + for (Map.Entry entry : volumeToPool.entrySet()) { + VolumeInfo volume = entry.getKey(); + VolumeTO volumeTo = new VolumeTO(volume, storagePoolDao.findById(volume.getPoolId())); + StorageFilerTO filerTo = new StorageFilerTO((StoragePool)entry.getValue()); + volumeToFilerto.put(volumeTo, filerTo); + } + + // Migration across cluster needs to be done in three phases. + // 1. Send a migrate command to source resource to initiate migration + // Run validations against target!! + // 2. Complete the process. Update the volume details. + MigrateWithStorageCommand migrateWithStorageCmd = new MigrateWithStorageCommand(to, volumeToFilerto, destHost.getGuid()); + MigrateWithStorageAnswer migrateWithStorageAnswer = (MigrateWithStorageAnswer) agentMgr.send( + srcHost.getId(), migrateWithStorageCmd); + if (migrateWithStorageAnswer == null) { + s_logger.error("Migration with storage of vm " + vm+ " to host " + destHost + " failed."); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost); + } else if (!migrateWithStorageAnswer.getResult()) { + s_logger.error("Migration with storage of vm " + vm+ " failed. Details: " + migrateWithStorageAnswer.getDetails()); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost + + ". " + migrateWithStorageAnswer.getDetails()); + } else { + // Update the volume details after migration. + updateVolumesAfterMigration(volumeToPool); + } + s_logger.debug("Storage migration of VM " + vm.getInstanceName() + " completed successfully. Migrated to host " + destHost.getName()); + + return migrateWithStorageAnswer; + } catch (OperationTimedoutException e) { + s_logger.error("Error while migrating vm " + vm + " to host " + destHost, e); + throw new AgentUnavailableException("Operation timed out on storage motion for " + vm, destHost.getId()); + } + } + + private Answer migrateVmWithVolumesWithinCluster(VMInstanceVO vm, VirtualMachineTO to, Host srcHost, + Host destHost, Map volumeToPool) throws AgentUnavailableException { + + // Initiate migration of a virtual machine with it's volumes. + try { + Map volumeToFilerto = new HashMap(); + for (Map.Entry entry : volumeToPool.entrySet()) { + VolumeInfo volume = entry.getKey(); + VolumeTO volumeTo = new VolumeTO(volume, storagePoolDao.findById(volume.getPoolId())); + StorageFilerTO filerTo = new StorageFilerTO((StoragePool)entry.getValue()); + volumeToFilerto.put(volumeTo, filerTo); + } + + MigrateWithStorageCommand command = new MigrateWithStorageCommand(to, volumeToFilerto, destHost.getGuid()); + MigrateWithStorageAnswer answer = (MigrateWithStorageAnswer) agentMgr.send(srcHost.getId(), command); + if (answer == null) { + s_logger.error("Migration with storage of vm " + vm + " failed."); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost); + } else if (!answer.getResult()) { + s_logger.error("Migration with storage of vm " + vm+ " failed. Details: " + answer.getDetails()); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost + + ". " + answer.getDetails()); + } else { + // Update the volume details after migration. + updateVolumesAfterMigration(volumeToPool); + } + + return answer; + } catch (OperationTimedoutException e) { + s_logger.error("Error while migrating vm " + vm + " to host " + destHost, e); + throw new AgentUnavailableException("Operation timed out on storage motion for " + vm, destHost.getId()); + } + } + + private void updateVolumesAfterMigration(Map volumeToPool) { + for (Map.Entry entry : volumeToPool.entrySet()) { + VolumeInfo volume = entry.getKey(); + StoragePool pool = (StoragePool)entry.getValue(); + + VolumeVO volumeVO = volDao.findById(volume.getId()); + Long oldPoolId = volumeVO.getPoolId(); + volumeVO.setLastPoolId(oldPoolId); + volumeVO.setFolder(pool.getPath()); + volumeVO.setPodId(pool.getPodId()); + volumeVO.setPoolId(pool.getId()); + + volDao.update(volume.getId(), volumeVO); + s_logger.debug("Volume path was successfully updated for volume " + volume.getName() + " after it was migrated."); + } + } +} diff --git a/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java b/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java new file mode 100644 index 00000000000..de08c93c78a --- /dev/null +++ b/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/VmwareDatacenterApiUnitTest.java @@ -0,0 +1,426 @@ +// 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.hypervisor.vmware; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import junit.framework.TestCase; + +import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd; +import org.apache.cloudstack.api.command.admin.zone.RemoveVmwareDcCmd; +import org.apache.cloudstack.test.utils.SpringUtils; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.core.type.filter.TypeFilter; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.cloud.agent.AgentManager; +import com.cloud.cluster.ClusterManager; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.ClusterDetailsDao; +import com.cloud.dc.ClusterDetailsVO; +import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.HostPodVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.ClusterVSMMapDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.HostPodDao; +import com.cloud.event.dao.EventDao; +import com.cloud.exception.DiscoveryException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceInUseException; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; +import com.cloud.hypervisor.vmware.dao.LegacyZoneDao; +import com.cloud.hypervisor.vmware.dao.VmwareDatacenterDao; +import com.cloud.hypervisor.vmware.dao.VmwareDatacenterZoneMapDao; +import com.cloud.hypervisor.vmware.manager.VmwareManager; +import com.cloud.hypervisor.vmware.manager.VmwareManagerImpl; +import com.cloud.network.NetworkModel; +import com.cloud.network.dao.CiscoNexusVSMDeviceDao; +import com.cloud.org.Cluster.ClusterType; +import com.cloud.org.Managed.ManagedState; +import com.cloud.secstorage.CommandExecLogDao; +import com.cloud.server.ConfigurationServer; +import com.cloud.storage.secondary.SecondaryStorageVmManager; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountService; +import com.cloud.user.AccountVO; +import com.cloud.user.UserContext; +import com.cloud.user.dao.AccountDao; +import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.dao.UserVmDao; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class) +public class VmwareDatacenterApiUnitTest { + + @Inject + VmwareDatacenterService _vmwareDatacenterService; + + @Inject + DataCenterDao _dcDao; + + @Inject + HostPodDao _podDao; + + @Inject + VmwareDatacenterDao _vmwareDcDao; + + @Inject + VmwareDatacenterZoneMapDao _vmwareDcZoneMapDao; + + @Inject + ClusterDao _clusterDao; + + @Inject + ClusterDetailsDao _clusterDetailsDao; + + @Inject + ConfigurationDao _configDao; + + @Inject + AccountDao _accountDao; + + @Inject + AccountManager _acctMgr; + + long zoneId; + long podId; + long clusterId; + long vmwareDcId; + private static long domainId = 5L; + private static String vmwareDcName = "dc"; + private static String clusterName = "cluster"; + private static String vCenterHost = "10.1.1.100"; + private static String url = "http://" + vCenterHost + "/" + vmwareDcName + "/" + clusterName; + private static String user = "administrator"; + private static String password = "password"; + private static String guid = vmwareDcName + "@" + vCenterHost; + + private static VmwareDatacenterVO dc; + private static List vmwareDcs; + private static ClusterVO cluster; + private static VmwareDatacenterZoneMapVO dcZoneMap; + private static List clusterList; + private static ClusterDetailsVO clusterDetails; + + @Mock + private static AddVmwareDcCmd addCmd; + @Mock + private static RemoveVmwareDcCmd removeCmd; + + @BeforeClass + public static void setUp() throws ConfigurationException { + } + + @Before + public void testSetUp() { + Mockito.when(_configDao.isPremium()).thenReturn(true); + ComponentContext.initComponentsLifeCycle(); + MockitoAnnotations.initMocks(this); + + DataCenterVO zone = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24", + null, null, NetworkType.Basic, null, null, true, true, null, null); + zoneId = 1L; + + HostPodVO pod = new HostPodVO(UUID.randomUUID().toString(), zoneId, "192.168.56.1", "192.168.56.0/24", 8, "test"); + podId = 1L; + + AccountVO acct = new AccountVO(200L); + acct.setType(Account.ACCOUNT_TYPE_ADMIN); + acct.setAccountName("admin"); + acct.setDomainId(domainId); + UserContext.registerContext(1, acct, null, true); + + when(_accountDao.findByIdIncludingRemoved(0L)).thenReturn(acct); + + dc = new VmwareDatacenterVO(guid, vmwareDcName, vCenterHost, user, password); + vmwareDcs = new ArrayList(); + vmwareDcs.add(dc); + vmwareDcId = dc.getId(); + + cluster = new ClusterVO(zone.getId(), pod.getId(), "vmwarecluster"); + cluster.setHypervisorType(HypervisorType.VMware.toString()); + cluster.setClusterType(ClusterType.ExternalManaged); + cluster.setManagedState(ManagedState.Managed); + clusterId = 1L; + clusterList = new ArrayList(); + clusterList.add(cluster); + + clusterDetails = new ClusterDetailsVO(clusterId, "url", url); + + dcZoneMap = new VmwareDatacenterZoneMapVO(zoneId, vmwareDcId); + + Mockito.when(_dcDao.persist(Mockito.any(DataCenterVO.class))).thenReturn(zone); + Mockito.when(_dcDao.findById(1L)).thenReturn(zone); + Mockito.when(_podDao.persist(Mockito.any(HostPodVO.class))).thenReturn(pod); + Mockito.when(_podDao.findById(1L)).thenReturn(pod); + Mockito.when(_clusterDao.persist(Mockito.any(ClusterVO.class))).thenReturn(cluster); + Mockito.when(_clusterDao.findById(1L)).thenReturn(cluster); + Mockito.when(_clusterDao.listByZoneId(1L)).thenReturn(null); + Mockito.when(_clusterDao.expunge(1L)).thenReturn(true); + Mockito.when(_clusterDetailsDao.persist(Mockito.any(ClusterDetailsVO.class))).thenReturn(clusterDetails); + Mockito.when(_clusterDetailsDao.expunge(1L)).thenReturn(true); + Mockito.when(_vmwareDcDao.persist(Mockito.any(VmwareDatacenterVO.class))).thenReturn(dc); + Mockito.when(_vmwareDcDao.findById(1L)).thenReturn(null); + Mockito.when(_vmwareDcDao.expunge(1L)).thenReturn(true); + Mockito.when(_vmwareDcDao.getVmwareDatacenterByNameAndVcenter(vmwareDcName, vCenterHost)).thenReturn(null); + Mockito.when(_vmwareDcZoneMapDao.persist(Mockito.any(VmwareDatacenterZoneMapVO.class))).thenReturn(dcZoneMap); + Mockito.when(_vmwareDcZoneMapDao.findByZoneId(1L)).thenReturn(null); + Mockito.when(_vmwareDcZoneMapDao.expunge(1L)).thenReturn(true); + Mockito.when(addCmd.getZoneId()).thenReturn(1L); + Mockito.when(addCmd.getVcenter()).thenReturn(vCenterHost); + Mockito.when(addCmd.getUsername()).thenReturn(user); + Mockito.when(addCmd.getPassword()).thenReturn(password); + Mockito.when(addCmd.getName()).thenReturn(vmwareDcName); + Mockito.when(removeCmd.getZoneId()).thenReturn(1L); + } + + //@Test(expected = InvalidParameterValueException.class) + public void testAddVmwareDcToInvalidZone() throws ResourceInUseException, IllegalArgumentException, DiscoveryException, Exception { + Mockito.when(addCmd.getZoneId()).thenReturn(2L); + _vmwareDatacenterService.addVmwareDatacenter(addCmd); + } + + //@Test(expected = ResourceInUseException.class) + public void testAddVmwareDcToZoneWithClusters() throws ResourceInUseException, IllegalArgumentException, DiscoveryException, Exception { + Mockito.when(_clusterDao.listByZoneId(1L)).thenReturn(clusterList); + _vmwareDatacenterService.addVmwareDatacenter(addCmd); + } + + @Test(expected = InvalidParameterValueException.class) + public void testRemoveVmwareDcToInvalidZone() throws ResourceInUseException, IllegalArgumentException, DiscoveryException, Exception { + Mockito.when(removeCmd.getZoneId()).thenReturn(2L); + _vmwareDatacenterService.removeVmwareDatacenter(removeCmd); + } + + @Test(expected = ResourceInUseException.class) + public void testRemoveVmwareDcToZoneWithClusters() throws ResourceInUseException, IllegalArgumentException, DiscoveryException, Exception { + Mockito.when(_clusterDao.listByZoneId(1L)).thenReturn(clusterList); + _vmwareDatacenterService.removeVmwareDatacenter(removeCmd); + } + + //@Test(expected = ResourceInUseException.class) + public void testAddVmwareDcToZoneWithVmwareDc() throws ResourceInUseException, IllegalArgumentException, DiscoveryException, Exception { + Mockito.when(_vmwareDcDao.getVmwareDatacenterByNameAndVcenter(vmwareDcName, vCenterHost)).thenReturn(vmwareDcs); + _vmwareDatacenterService.addVmwareDatacenter(addCmd); + } + + //@Test(expected = InvalidParameterValueException.class) + public void testAddVmwareDcWithNullUser() throws ResourceInUseException, IllegalArgumentException, DiscoveryException, Exception { + Mockito.when(addCmd.getUsername()).thenReturn(null); + _vmwareDatacenterService.addVmwareDatacenter(addCmd); + } + + //@Test(expected = InvalidParameterValueException.class) + public void testAddVmwareDcWithNullPassword() throws ResourceInUseException, IllegalArgumentException, DiscoveryException, Exception { + Mockito.when(addCmd.getPassword()).thenReturn(null); + _vmwareDatacenterService.addVmwareDatacenter(addCmd); + } + + //@Test(expected = InvalidParameterValueException.class) + public void testAddVmwareDcWithNullUrl() throws ResourceInUseException, IllegalArgumentException, DiscoveryException, Exception { + Mockito.when(addCmd.getVcenter()).thenReturn(null); + _vmwareDatacenterService.addVmwareDatacenter(addCmd); + } + + //@Test(expected = InvalidParameterValueException.class) + public void testAddVmwareDcWithNullDcName() throws ResourceInUseException, IllegalArgumentException, DiscoveryException, Exception { + Mockito.when(addCmd.getName()).thenReturn(null); + _vmwareDatacenterService.addVmwareDatacenter(addCmd); + } + + //@Test(expected = CloudRuntimeException.class) + public void testReAddVmwareDc() throws ResourceInUseException, IllegalArgumentException, DiscoveryException, Exception { + Mockito.when(_vmwareDcZoneMapDao.findByZoneId(1L)).thenReturn(dcZoneMap); + _vmwareDatacenterService.addVmwareDatacenter(addCmd); + } + + @Test(expected = CloudRuntimeException.class) + public void testRemoveNonexistingVmwareDc() throws ResourceInUseException, IllegalArgumentException, DiscoveryException, Exception { + Mockito.when(_vmwareDcZoneMapDao.findByZoneId(1L)).thenReturn(null); + _vmwareDatacenterService.removeVmwareDatacenter(removeCmd); + } + + @Configuration + @ComponentScan(basePackageClasses = {VmwareManagerImpl.class}, includeFilters = {@Filter(value = TestConfiguration.Library.class, type = FilterType.CUSTOM)}, useDefaultFilters = false) + public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration { + + @Bean + public AccountDao accountDao() { + return Mockito.mock(AccountDao.class); + } + + @Bean + public AccountService accountService() { + return Mockito.mock(AccountService.class); + } + + @Bean + public DataCenterDao dataCenterDao() { + return Mockito.mock(DataCenterDao.class); + } + + @Bean + public HostPodDao hostPodDao() { + return Mockito.mock(HostPodDao.class); + } + + @Bean + public ClusterDao clusterDao() { + return Mockito.mock(ClusterDao.class); + } + + @Bean + public ClusterDetailsDao clusterDetailsDao() { + return Mockito.mock(ClusterDetailsDao.class); + } + + @Bean + public VmwareDatacenterDao vmwareDatacenterDao() { + return Mockito.mock(VmwareDatacenterDao.class); + } + + @Bean + public VmwareDatacenterZoneMapDao vmwareDatacenterZoneMapDao() { + return Mockito.mock(VmwareDatacenterZoneMapDao.class); + } + + @Bean + public AgentManager agentManager() { + return Mockito.mock(AgentManager.class); + } + + @Bean + public HostDao hostDao() { + return Mockito.mock(HostDao.class); + } + + @Bean + public NetworkModel networkModel() { + return Mockito.mock(NetworkModel.class); + } + + @Bean + public ClusterManager clusterManager() { + return Mockito.mock(ClusterManager.class); + } + + @Bean + public SecondaryStorageVmManager secondaryStorageVmManager() { + return Mockito.mock(SecondaryStorageVmManager.class); + } + + @Bean + public CommandExecLogDao commandExecLogDao() { + return Mockito.mock(CommandExecLogDao.class); + } + + @Bean + public CiscoNexusVSMDeviceDao ciscoNexusVSMDeviceDao() { + return Mockito.mock(CiscoNexusVSMDeviceDao.class); + } + + @Bean + public ClusterVSMMapDao clusterVSMMapDao() { + return Mockito.mock(ClusterVSMMapDao.class); + } + + @Bean + public LegacyZoneDao legacyZoneDao() { + return Mockito.mock(LegacyZoneDao.class); + } + + @Bean + public ConfigurationDao configurationDao() { + return Mockito.mock(ConfigurationDao.class); + } + + @Bean + public ConfigurationServer configurationServer() { + return Mockito.mock(ConfigurationServer.class); + } + + @Bean + public HypervisorCapabilitiesDao hypervisorCapabilitiesDao() { + return Mockito.mock(HypervisorCapabilitiesDao.class); + } + + @Bean + public AccountManager accountManager() { + return Mockito.mock(AccountManager.class); + } + + @Bean + public EventDao eventDao() { + return Mockito.mock(EventDao.class); + } + + @Bean + public UserVmDao userVMDao() { + return Mockito.mock(UserVmDao.class); + } + + public AddVmwareDcCmd addVmwareDatacenterCmd() { + return Mockito.mock(AddVmwareDcCmd.class); + } + + public RemoveVmwareDcCmd removeVmwareDcCmd() { + return Mockito.mock(RemoveVmwareDcCmd.class); + } + + public static class Library implements TypeFilter { + + @Override + public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException { + ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class); + return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs); + } + } + } +} diff --git a/plugins/hypervisors/vmware/test/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategyTest.java b/plugins/hypervisors/vmware/test/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategyTest.java new file mode 100644 index 00000000000..ae4f41d55a5 --- /dev/null +++ b/plugins/hypervisors/vmware/test/org/apache/cloudstack/storage/motion/VmwareStorageMotionStrategyTest.java @@ -0,0 +1,271 @@ +// 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.storage.motion; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.framework.async.AsyncRpcConext; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.test.utils.SpringUtils; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.core.type.filter.TypeFilter; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.MigrateWithStorageAnswer; +import com.cloud.agent.api.MigrateWithStorageCommand; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.host.Host; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.utils.component.ComponentContext; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.dao.VMInstanceDao; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class) +public class VmwareStorageMotionStrategyTest { + + @Inject VmwareStorageMotionStrategy strategy = new VmwareStorageMotionStrategy(); + @Inject AgentManager agentMgr; + @Inject VolumeDao volDao; + @Inject VolumeDataFactory volFactory; + @Inject PrimaryDataStoreDao storagePoolDao; + @Inject VMInstanceDao instanceDao; + + CopyCommandResult result; + + @BeforeClass + public static void setUp() throws ConfigurationException { + } + + @Before + public void testSetUp() { + ComponentContext.initComponentsLifeCycle(); + } + + @Test + public void testStrategyHandlesVmwareHosts() throws Exception { + Host srcHost = mock(Host.class); + Host destHost = mock(Host.class); + when(srcHost.getHypervisorType()).thenReturn(HypervisorType.VMware); + when(destHost.getHypervisorType()).thenReturn(HypervisorType.VMware); + Map volumeMap = new HashMap(); + boolean canHandle = strategy.canHandle(volumeMap, srcHost, destHost); + assertTrue("The strategy is only supposed to handle vmware hosts", canHandle); + } + + @Test + public void testStrategyDoesnotHandlesNonVmwareHosts() throws Exception { + Host srcHost = mock(Host.class); + Host destHost = mock(Host.class); + when(srcHost.getHypervisorType()).thenReturn(HypervisorType.XenServer); + when(destHost.getHypervisorType()).thenReturn(HypervisorType.XenServer); + Map volumeMap = new HashMap(); + boolean canHandle = strategy.canHandle(volumeMap, srcHost, destHost); + assertFalse("The strategy is only supposed to handle vmware hosts", canHandle); + } + + @Test + public void testMigrateWithinClusterSuccess() throws Exception { + Host srcHost = mock(Host.class); + Host destHost = mock(Host.class); + when(srcHost.getClusterId()).thenReturn(1L); + when(destHost.getClusterId()).thenReturn(1L); + Map volumeMap = new HashMap(); + VirtualMachineTO to = mock(VirtualMachineTO.class); + when(to.getId()).thenReturn(6L); + VMInstanceVO instance = mock(VMInstanceVO.class); + when(instanceDao.findById(6L)).thenReturn(instance); + + MockContext context = new MockContext(null, null, volumeMap); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().mockCallBack(null, null)).setContext(context); + + MigrateWithStorageAnswer migAnswerMock = mock(MigrateWithStorageAnswer.class); + when(migAnswerMock.getResult()).thenReturn(true); + when(agentMgr.send(anyLong(), isA(MigrateWithStorageCommand.class))).thenReturn(migAnswerMock); + + strategy.copyAsync(volumeMap, to, srcHost, destHost, caller); + assertTrue("Migration within cluster isn't successful.", this.result.isSuccess()); + } + + @Test + public void testMigrateWithinClusterFailure() throws Exception { + Host srcHost = mock(Host.class); + Host destHost = mock(Host.class); + when(srcHost.getClusterId()).thenReturn(1L); + when(destHost.getClusterId()).thenReturn(1L); + Map volumeMap = new HashMap(); + VirtualMachineTO to = mock(VirtualMachineTO.class); + when(to.getId()).thenReturn(6L); + VMInstanceVO instance = mock(VMInstanceVO.class); + when(instanceDao.findById(6L)).thenReturn(instance); + + MockContext context = new MockContext(null, null, volumeMap); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().mockCallBack(null, null)).setContext(context); + + MigrateWithStorageAnswer migAnswerMock = mock(MigrateWithStorageAnswer.class); + when(migAnswerMock.getResult()).thenReturn(false); + when(agentMgr.send(anyLong(), isA(MigrateWithStorageCommand.class))).thenReturn(migAnswerMock); + + strategy.copyAsync(volumeMap, to, srcHost, destHost, caller); + assertFalse("Migration within cluster didn't fail.", this.result.isSuccess()); + } + + @Test + public void testMigrateAcrossClusterSuccess() throws Exception { + Host srcHost = mock(Host.class); + Host destHost = mock(Host.class); + when(srcHost.getClusterId()).thenReturn(1L); + when(destHost.getClusterId()).thenReturn(2L); + Map volumeMap = new HashMap(); + VirtualMachineTO to = mock(VirtualMachineTO.class); + when(to.getId()).thenReturn(6L); + VMInstanceVO instance = mock(VMInstanceVO.class); + when(instanceDao.findById(6L)).thenReturn(instance); + + MockContext context = new MockContext(null, null, volumeMap); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().mockCallBack(null, null)).setContext(context); + + MigrateWithStorageAnswer migAnswerMock = mock(MigrateWithStorageAnswer.class); + when(migAnswerMock.getResult()).thenReturn(true); + when(agentMgr.send(anyLong(), isA(MigrateWithStorageCommand.class))).thenReturn(migAnswerMock); + + strategy.copyAsync(volumeMap, to, srcHost, destHost, caller); + assertTrue("Migration across cluster isn't successful.", this.result.isSuccess()); + } + + @Test + public void testMigrateAcrossClusterFailure() throws Exception { + Host srcHost = mock(Host.class); + Host destHost = mock(Host.class); + when(srcHost.getClusterId()).thenReturn(1L); + when(destHost.getClusterId()).thenReturn(2L); + Map volumeMap = new HashMap(); + VirtualMachineTO to = mock(VirtualMachineTO.class); + when(to.getId()).thenReturn(6L); + VMInstanceVO instance = mock(VMInstanceVO.class); + when(instanceDao.findById(6L)).thenReturn(instance); + + MockContext context = new MockContext(null, null, volumeMap); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().mockCallBack(null, null)).setContext(context); + + MigrateWithStorageAnswer migAnswerMock = mock(MigrateWithStorageAnswer.class); + when(migAnswerMock.getResult()).thenReturn(false); + when(agentMgr.send(anyLong(), isA(MigrateWithStorageCommand.class))).thenReturn(migAnswerMock); + + strategy.copyAsync(volumeMap, to, srcHost, destHost, caller); + assertFalse("Migration across cluster didn't fail.", this.result.isSuccess()); + } + + private class MockContext extends AsyncRpcConext { + final Map volumeToPool; + final AsyncCallFuture future; + /** + * @param callback + */ + public MockContext(AsyncCompletionCallback callback, AsyncCallFuture future, + Map volumeToPool) { + super(callback); + this.volumeToPool = volumeToPool; + this.future = future; + } + } + + protected Void mockCallBack(AsyncCallbackDispatcher callback, MockContext context) { + this.result = callback.getResult(); + return null; + } + + @Configuration + @ComponentScan(basePackageClasses = { VmwareStorageMotionStrategy.class }, + includeFilters = {@Filter(value = TestConfiguration.Library.class, type = FilterType.CUSTOM)}, + useDefaultFilters = false) + public static class TestConfiguration extends SpringUtils.CloudStackTestConfiguration { + + @Bean + public VolumeDao volumeDao() { + return Mockito.mock(VolumeDao.class); + } + + @Bean + public VolumeDataFactory volumeDataFactory() { + return Mockito.mock(VolumeDataFactory.class); + } + + @Bean + public PrimaryDataStoreDao primaryDataStoreDao() { + return Mockito.mock(PrimaryDataStoreDao.class); + } + + @Bean + public VMInstanceDao vmInstanceDao() { + return Mockito.mock(VMInstanceDao.class); + } + + @Bean + public AgentManager agentManager() { + return Mockito.mock(AgentManager.class); + } + + public static class Library implements TypeFilter { + @Override + public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException { + ComponentScan cs = TestConfiguration.class.getAnnotation(ComponentScan.class); + return SpringUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs); + } + } + } +} \ No newline at end of file diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 8cb05a702ff..e92c3fc55fe 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -633,6 +633,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe protected void scaleVM(Connection conn, VM vm, VirtualMachineTO vmSpec, Host host) throws XenAPIException, XmlRpcException { + Long staticMemoryMax = vm.getMemoryStaticMax(conn); + Long staticMemoryMin = vm.getMemoryStaticMin(conn); + Long newDynamicMemoryMin = vmSpec.getMinRam() * 1024 * 1024; + Long newDynamicMemoryMax = vmSpec.getMaxRam() * 1024 * 1024; + if (staticMemoryMin > newDynamicMemoryMin || newDynamicMemoryMax > staticMemoryMax) { + throw new CloudRuntimeException("Cannot scale up the vm because of memory constraint violation: 0 <= memory-static-min <= memory-dynamic-min <= memory-dynamic-max <= memory-static-max "); + } + vm.setMemoryDynamicRange(conn, vmSpec.getMinRam() * 1024 * 1024, vmSpec.getMaxRam() * 1024 * 1024); vm.setVCPUsNumberLive(conn, (long)vmSpec.getCpus()); @@ -669,10 +677,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe // If DMC is not enable then don't execute this command. if (!isDmcEnabled(conn, host)) { - String msg = "Unable to scale the vm: " + vmName + " as DMC - Dynamic memory control is not enabled for the XenServer:" + _host.uuid + " ,check your license and hypervisor version."; - s_logger.info(msg); - return new ScaleVmAnswer(cmd, false, msg); + throw new CloudRuntimeException("Unable to scale the vm: " + vmName + " as DMC - Dynamic memory control is not enabled for the XenServer:" + _host.uuid + " ,check your license and hypervisor version."); } + // stop vm which is running on this host or is in halted state Iterator iter = vms.iterator(); while ( iter.hasNext() ) { @@ -692,13 +699,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe for (VM vm : vms) { VM.Record vmr = vm.getRecord(conn); try { - Map hostParams = new HashMap(); - hostParams = host.getLicenseParams(conn); - if (hostParams.get("restrict_dmc").equalsIgnoreCase("true")) { - throw new CloudRuntimeException("Host "+ _host.uuid + " does not support Dynamic Memory Control, so we cannot scale up the vm"); - } scaleVM(conn, vm, vmSpec, host); - } catch (Exception e) { String msg = "Catch exception " + e.getClass().getName() + " when scaling VM:" + vmName + " due to " + e.toString(); s_logger.debug(msg); @@ -2005,7 +2006,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe for (IpAliasTO ipAliasTO : revokedIpAliasTOs) { args = args + ipAliasTO.getAlias_count()+":"+ipAliasTO.getRouterip()+":"+ipAliasTO.getNetmask()+"-"; } - args = args + " " ; + //this is to ensure that thre is some argument passed to the deleteipAlias script when there are no revoked rules. + args = args + "- " ; List activeIpAliasTOs = cmd.getCreateIpAliasTos(); for (IpAliasTO ipAliasTO : activeIpAliasTOs) { args = args + ipAliasTO.getAlias_count()+":"+ipAliasTO.getRouterip()+":"+ipAliasTO.getNetmask()+"-"; @@ -8121,7 +8123,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe */ private UnPlugNicAnswer execute(UnPlugNicCommand cmd) { Connection conn = getConnection(); - String vmName = cmd.getInstanceName(); + String vmName = cmd.getVmName(); try { Set vms = VM.getByNameLabel(conn, vmName); if ( vms == null || vms.isEmpty() ) { diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java index 54aeef5a022..8e378093f3f 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java @@ -137,7 +137,7 @@ public class XenServer56FP1Resource extends XenServer56Resource { vmr.actionsAfterCrash = Types.OnCrashBehaviour.DESTROY; vmr.actionsAfterShutdown = Types.OnNormalExit.DESTROY; - if (isDmcEnabled(conn, host)) { + if (isDmcEnabled(conn, host) && vmSpec.isEnableDynamicallyScaleVm()) { //scaling is allowed vmr.memoryStaticMin = mem_128m; //128MB //TODO: Remove hardcoded 8GB and assign proportionate to ServiceOffering and mem overcommit ratio diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnectionImpl.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnectionImpl.java index 72ecc67cad6..823be86b45f 100644 --- a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnectionImpl.java +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnectionImpl.java @@ -1070,7 +1070,7 @@ public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { } private String getNameForDNatIpPool(String tenantName, String identifier) { - return "IpPool-" + tenantName + "-" + identifier; + return "IpPool-" + tenantName + "-" + identifier + "n"; } private String getDnForDNatIpPool(String tenantName, String identifier) { diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java index b335edb9f63..553325ccaa9 100644 --- a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java @@ -98,6 +98,8 @@ import com.cloud.network.cisco.NetworkAsa1000vMapVO; import com.cloud.network.dao.CiscoAsa1000vDao; import com.cloud.network.dao.CiscoNexusVSMDeviceDao; import com.cloud.network.dao.CiscoVnmcDao; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.NetworkAsa1000vMapDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.PhysicalNetworkDao; @@ -148,7 +150,9 @@ public class CiscoVnmcElement extends AdapterBase implements SourceNatServicePro PhysicalNetworkDao _physicalNetworkDao; @Inject PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao; - @Inject + @Inject + IPAddressDao _ipAddressDao; + @Inject HostDetailsDao _hostDetailsDao; @Inject HostDao _hostDao; @@ -342,22 +346,33 @@ public class CiscoVnmcElement extends AdapterBase implements SourceNatServicePro } // due to VNMC limitation of not allowing source NAT ip as the outside ip of firewall, - // an additional public ip needs to acquired for assigning as firewall outside ip + // an additional public ip needs to acquired for assigning as firewall outside ip. + // In case there are already additional ip addresses available (network restart) use one + // of them such that it is not the source NAT ip IpAddress outsideIp = null; - try { - Account caller = UserContext.current().getCaller(); - long callerUserId = UserContext.current().getCallerUserId(); - outsideIp = _networkMgr.allocateIp(owner, false, caller, callerUserId, zone); - } catch (ResourceAllocationException e) { - s_logger.error("Unable to allocate additional public Ip address. Exception details " + e); - return false; + List publicIps = _ipAddressDao.listByAssociatedNetwork(network.getId(), null); + for (IPAddressVO ip : publicIps) { + if (!ip.isSourceNat()) { + outsideIp = ip; + break; + } } + if (outsideIp == null) { // none available, acquire one + try { + Account caller = UserContext.current().getCaller(); + long callerUserId = UserContext.current().getCallerUserId(); + outsideIp = _networkMgr.allocateIp(owner, false, caller, callerUserId, zone); + } catch (ResourceAllocationException e) { + s_logger.error("Unable to allocate additional public Ip address. Exception details " + e); + return false; + } - try { - outsideIp = _networkMgr.associateIPToGuestNetwork(outsideIp.getId(), network.getId(), true); - } catch (ResourceAllocationException e) { - s_logger.error("Unable to assign allocated additional public Ip " + outsideIp.getAddress().addr() + " to network with vlan " + vlanId + ". Exception details " + e); - return false; + try { + outsideIp = _networkMgr.associateIPToGuestNetwork(outsideIp.getId(), network.getId(), true); + } catch (ResourceAllocationException e) { + s_logger.error("Unable to assign allocated additional public Ip " + outsideIp.getAddress().addr() + " to network with vlan " + vlanId + ". Exception details " + e); + return false; + } } // create logical edge firewall in VNMC @@ -792,7 +807,7 @@ public class CiscoVnmcElement extends AdapterBase implements SourceNatServicePro List rulesTO = new ArrayList(); for (StaticNat rule : rules) { IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId()); - StaticNatRuleTO ruleTO = new StaticNatRuleTO(0, sourceIp.getAddress().addr(), null, + StaticNatRuleTO ruleTO = new StaticNatRuleTO(rule.getSourceIpAddressId(), sourceIp.getAddress().addr(), null, null, rule.getDestIpAddress(), null, null, null, rule.isForRevoke(), false); rulesTO.add(ruleTO); } diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java index fc0c33483ac..9524bf99cec 100644 --- a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java @@ -501,7 +501,7 @@ public class CiscoVnmcResource implements ServerResource { } /* - * Destination NAT + * PF */ private synchronized Answer execute(SetPortForwardingRulesCommand cmd) { refreshVnmcConnection(); diff --git a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java index 4b9308b6606..14b616cb749 100644 --- a/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java +++ b/plugins/network-elements/internal-loadbalancer/src/org/apache/cloudstack/network/element/InternalLoadBalancerElement.java @@ -64,7 +64,6 @@ import com.cloud.network.element.VirtualRouterProviderVO; import com.cloud.network.lb.LoadBalancingRule; import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VirtualRouter.Role; -import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.LoadBalancerContainer; import com.cloud.network.rules.LoadBalancerContainer.Scheme; import com.cloud.offering.NetworkOffering; @@ -394,23 +393,16 @@ public class InternalLoadBalancerElement extends AdapterBase implements LoadBala //1) Group rules by the source ip address as NetworkManager always passes the entire network lb config to the element Map> groupedRules = groupBySourceIp(rules); - //2) Count rules in revoke state Set vmsToDestroy = new HashSet(); for (Ip sourceIp : groupedRules.keySet()) { + //2) Check if there are non revoked rules for the source ip address List rulesToCheck = groupedRules.get(sourceIp); - int revoke = 0; - for (LoadBalancingRule ruleToCheck : rulesToCheck) { - if (ruleToCheck.getState() == FirewallRule.State.Revoke){ - revoke++; - } - } - - if (revoke == rulesToCheck.size()) { - s_logger.debug("Have to destroy internal lb vm for source ip " + sourceIp); + if (_appLbDao.countBySourceIpAndNotRevoked(sourceIp, rulesToCheck.get(0).getNetworkId()) == 0) { + s_logger.debug("Have to destroy internal lb vm for source ip " + sourceIp + " as it has 0 rules in non-Revoke state"); vmsToDestroy.add(sourceIp); - } - } + } + } return vmsToDestroy; } diff --git a/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbelement/ElementChildTestConfiguration.java b/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbelement/ElementChildTestConfiguration.java index 8a67e84f951..bddf713e3a8 100644 --- a/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbelement/ElementChildTestConfiguration.java +++ b/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbelement/ElementChildTestConfiguration.java @@ -46,7 +46,7 @@ import com.cloud.vm.dao.DomainRouterDao; @Configuration @ComponentScan( basePackageClasses={ - NetUtils.class, + NetUtils.class }, includeFilters={@Filter(value=ElementChildTestConfiguration.Library.class, type=FilterType.CUSTOM)}, useDefaultFilters=false diff --git a/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/LbChildTestConfiguration.java b/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/LbChildTestConfiguration.java index 74e54b23295..4f03b27b013 100644 --- a/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/LbChildTestConfiguration.java +++ b/plugins/network-elements/internal-loadbalancer/test/org/apache/cloudstack/internallbvmmgr/LbChildTestConfiguration.java @@ -56,7 +56,7 @@ import com.cloud.user.dao.AccountDao; @Configuration @ComponentScan( basePackageClasses={ - NetUtils.class, + NetUtils.class }, includeFilters={@Filter(value=LbChildTestConfiguration.Library.class, type=FilterType.CUSTOM)}, useDefaultFilters=false diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java index c0d4599dc0c..263e13b42f3 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java @@ -904,6 +904,27 @@ public class NetscalerResource implements ServerResource { // Bind 'gslbservice' service object to GSLB virtual server GSLB.createVserverServiceBinding(_netscalerService, serviceName, vserverName); + // create a monitor for the service running on the site + lbmonitor newmonitor = new lbmonitor(); + String monitorName = GSLB.generateGslbServiceMonitorName(servicePublicIp); + newmonitor.set_type("TCP"); + newmonitor.set_servicename(serviceName); + newmonitor.set_monitorname(monitorName); + newmonitor.set_state("ENABLED"); + lbmonitor.add(_netscalerService, newmonitor); + + // bind the monitor to the GSLB servie + try { + gslbservice_lbmonitor_binding monitorBinding = new gslbservice_lbmonitor_binding(); + monitorBinding.set_monitor_name(monitorName); + monitorBinding.set_servicename(serviceName); + gslbservice_lbmonitor_binding.add(_netscalerService, monitorBinding); + } catch (Exception e) { + // TODO: Nitro API version 10.* is not compatible for NetScalers 9.*, so may fail + // against NetScaler version lesser than 10 hence ignore the exception + s_logger.warn("Failed to bind monitor to GSLB service due to " + e.getMessage()); + } + } else { // Unbind GSLB service with GSLB virtual server GSLB.deleteVserverServiceBinding(_netscalerService, serviceName, vserverName); @@ -911,6 +932,19 @@ public class NetscalerResource implements ServerResource { // delete 'gslbservice' object gslbservice service = GSLB.getServiceObject(_netscalerService, serviceName); GSLB.deleteService(_netscalerService, serviceName); + + // delete the GSLB service monitor + String monitorName = GSLB.generateGslbServiceMonitorName(servicePublicIp); + try { + lbmonitor serviceMonitor = lbmonitor.get(_netscalerService, monitorName); + if (serviceMonitor != null) { + lbmonitor.delete(_netscalerService, serviceMonitor); + } + } catch (nitro_exception ne) { + if (ne.getErrorCode() != NitroError.NS_RESOURCE_NOT_EXISTS) { + s_logger.warn("Failed to delete monitor "+ monitorName + " for GSLB service due to " + ne.getMessage()); + } + } } if (site.forRevoke()) { // delete the site if its for revoke @@ -1469,6 +1503,10 @@ public class NetscalerResource implements ServerResource { return "cloud-gslb-service-" + siteName + "-" + publicIp + "-" + publicPort; } + private static String generateGslbServiceMonitorName(String publicIp) { + return "cloud-monitor-" + publicIp; + } + private static boolean gslbServerExists(nitro_service client, String serverName) throws ExecutionException { try { if (com.citrix.netscaler.nitro.resource.config.basic.server.get(client, serverName) != null) { diff --git a/plugins/pom.xml b/plugins/pom.xml index 2efa2488e86..eab47554e6b 100755 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -35,11 +35,13 @@ api/rate-limit api/discovery acl/static-role-based - affinity-group-processors/host-anti-affinity + affinity-group-processors/host-anti-affinity + affinity-group-processors/explicit-dedication deployment-planners/user-concentrated-pod deployment-planners/user-dispersing deployment-planners/implicit-dedication host-allocators/random + dedicated-resources hypervisors/ovm hypervisors/xen hypervisors/kvm diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java index 7153282a2aa..fb37e8f4b10 100644 --- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java +++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java @@ -441,18 +441,18 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements } @Override - public boolean attachZone(DataStore dataStore, ZoneScope scope) { - List hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(HypervisorType.KVM, scope.getScopeId()); - for (HostVO host : hosts) { - try { - this.storageMgr.connectHostToSharedPool(host.getId(), - dataStore.getId()); - } catch (Exception e) { - s_logger.warn("Unable to establish a connection between " + host - + " and " + dataStore, e); - } - } - this.dataStoreHelper.attachZone(dataStore); + public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType) { + List hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(hypervisorType, scope.getScopeId()); + for (HostVO host : hosts) { + try { + this.storageMgr.connectHostToSharedPool(host.getId(), + dataStore.getId()); + } catch (Exception e) { + s_logger.warn("Unable to establish a connection between " + host + + " and " + dataStore, e); + } + } + this.dataStoreHelper.attachZone(dataStore, hypervisorType); return true; } diff --git a/scripts/storage/qcow2/modifyvlan.sh b/scripts/storage/qcow2/modifyvlan.sh deleted file mode 100755 index 5e26af0ba02..00000000000 --- a/scripts/storage/qcow2/modifyvlan.sh +++ /dev/null @@ -1,269 +0,0 @@ -#!/usr/bin/env bash -# 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. - - -# $Id: modifyvlan.sh 9132 2010-06-04 20:17:43Z manuel $ $HeadURL: svn://svn.lab.vmops.com/repos/vmdev/java/scripts/storage/qcow2/modifyvlan.sh $ -# modifyvlan.sh -- adds and deletes VLANs from a Routing Server -# set -x - -usage() { - printf "Usage: %s: -o -v -g \n" -} - -addVlan() { - local vlanId=$1 - - ifconfig bond1.$vlanId > /dev/null - - if [ $? -gt 0 ] - then - vconfig add bond1 $vlanId - - if [ $? -gt 0 ] - then - return 1 - fi - fi - - # Make ifcfg-bond1.$vlanId - rm /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - touch /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - echo "DEVICE=bond1.$vlanId" >> /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - echo "ONBOOT=yes" >> /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - echo "BOOTPROTO=none" >> /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - echo "VLAN=yes" >> /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - echo "BRIDGE=xenbr1.$vlanId" >> /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - - # Try to add xenbr1.$vlanId over bond1.$vlanId, if it does not already exist - - ifconfig xenbr1.$vlanId > /dev/null - - if [ $? -gt 0 ] - then - brctl addbr xenbr1.$vlanId - - if [ $? -gt 0 ] - then - return 1 - fi - - brctl addif xenbr1.$vlanId bond1.$vlanId - - if [ $? -gt 0 ] - then - return 1 - fi - - fi - - ifconfig xenbr1.$vlanId up - - if [ $? -gt 0 ] - then - return 1 - fi - - # Make ifcfg-xenbr1.$vlanId - rm /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - touch /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - echo "TYPE=bridge" >> /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - echo "DEVICE=xenbr1.$vlanId" >> /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - echo "ONBOOT=yes" >> /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - echo "BOOTPROTO=none" >> /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - - return 0 -} - -deleteVlan() { - local vlanId=$1 - - # Try to remove xenbr1.$vlanId - ifconfig xenbr1.$vlanId down - - if [ $? -gt 0 ] - then - return 1 - fi - - brctl delbr xenbr1.$vlanId - - if [ $? -gt 0 ] - then - return 1 - fi - - # Remove ifcfg-xenbr1.$vlanId - rm /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - - # Try to remove bond1.$vlanId - - vconfig rem bond1.$vlanId - - if [ $? -gt 0 ] - then - return 1 - fi - - # Remove ifcfg-bond1.$vlanId - rm /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - - return 0 - -} - -checkIfVlanExists() { - local vlanId=$1 - - if [ "$vlanId" == "untagged" ] - then - # This VLAN should always exist, since the bridge is xenbr1, which is created during vsetup - return 0 - fi - - ifconfig bond1.$vlanId > /dev/null - - if [ $? -gt 0 ] - then - return 1 - fi - - ifconfig xenbr1.$vlanId > /dev/null - - if [ $? -gt 0 ] - then - return 1 - fi - - if [ ! -f /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId ] - then - return 1 - fi - - if [ ! -f /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId ] - then - return 1 - fi - - return 0 -} - -arpingVlan() { - local vlanId=$1 - local vlanGateway=$2 - - # Change!!! - return 0 - - success=1 - for i in $(seq 1 3) - do - arping -I xenbr1.$vlanId $vlanGateway > /dev/null - - if [ $? -gt 0 ] - then - success=0 - break - fi - done - - return $success -} - -op= -vlanId= -vlanGateway= -option=$@ - -while getopts 'o:v:g:' OPTION -do - case $OPTION in - o) oflag=1 - op="$OPTARG" - ;; - v) vflag=1 - vlanId="$OPTARG" - ;; - g) gflag=1 - vlanGateway="$OPTARG" - ;; - ?) usage - exit 2 - ;; - esac -done - -# Check that all arguments were passed in -if [ "$oflag$vflag$gflag" != "111" ] -then - usage - exit 2 -fi - -if [ "$op" == "add" ] -then - # Check if the vlan already exists, and exit with success if it does - checkIfVlanExists $vlanId - - if [ $? -eq 0 ] - then - exit 0 - fi - - # Add the vlan - addVlan $vlanId - - # If the add fails then return failure - if [ $? -gt 0 ] - then - exit 1 - fi - - # Ping the vlan - arpingVlan $vlanId $vlanGateway - - # If the ping fails then delete the vlan and return failure. Else, return success. - if [ $? -gt 0 ] - then - deleteVlan $vlanId - exit 1 - else - exit 0 - fi -else - if [ "$op" == "delete" ] - then - # Delete the vlan - deleteVlan $vlanId - - # Always exit with success - exit 0 - fi -fi - - - - - - - - - - - - - diff --git a/scripts/vm/hypervisor/kvm/patchviasocket.pl b/scripts/vm/hypervisor/kvm/patchviasocket.pl old mode 100644 new mode 100755 diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index d18eca836b8..650e95535e0 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -541,6 +541,7 @@ def default_ebtables_rules(): util.pread2(['ebtables', '-N', 'DEFAULT_EBTABLES']) util.pread2(['ebtables', '-A', 'FORWARD', '-j' 'DEFAULT_EBTABLES']) util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '--ip-dst', '255.255.255.255', '--ip-proto', 'udp', '--ip-dport', '67', '-j', 'ACCEPT']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '--ip-dst', '255.255.255.255', '--ip-proto', 'udp', '--ip-dport', '68', '-j', 'ACCEPT']) util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'ARP', '--arp-op', 'Request', '-j', 'ACCEPT']) util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'ARP', '--arp-op', 'Reply', '-j', 'ACCEPT']) # deny mac broadcast and multicast diff --git a/scripts/vm/network/ovs-pvlan-vm.sh b/scripts/vm/network/ovs-pvlan-vm.sh index fd384814cc4..06e41fe4219 100755 --- a/scripts/vm/network/ovs-pvlan-vm.sh +++ b/scripts/vm/network/ovs-pvlan-vm.sh @@ -86,7 +86,8 @@ then exit 1 fi -trunk_port=1 +# try to find the physical link to outside, only supports eth and em prefix now +trunk_port=`ovs-ofctl show $br | egrep "\((eth|em)[0-9]" | cut -d '(' -f 1|tr -d ' '` if [ "$op" == "add" ] then diff --git a/server/pom.xml b/server/pom.xml index 6385bf2f233..8fe1e2d9508 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -18,6 +18,11 @@ 4.2.0-SNAPSHOT + + commons-io + commons-io + ${cs.commons-io.version} + org.apache.cloudstack cloud-core diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 1afedac5144..e5fa2e19757 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -59,7 +59,6 @@ import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.ResourceTagResponse; import org.apache.cloudstack.api.response.SecurityGroupResponse; import org.apache.cloudstack.api.response.ServiceOfferingResponse; -import org.apache.cloudstack.api.response.StoragePoolForMigrationResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.api.response.UserVmResponse; @@ -171,8 +170,6 @@ import com.cloud.network.as.dao.AutoScaleVmGroupPolicyMapDao; import com.cloud.network.as.dao.AutoScaleVmProfileDao; import com.cloud.network.as.dao.ConditionDao; import com.cloud.network.as.dao.CounterDao; -import com.cloud.network.dao.AccountGuestVlanMapDao; -import com.cloud.network.dao.AccountGuestVlanMapVO; import com.cloud.network.dao.FirewallRulesCidrsDao; import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; @@ -197,7 +194,6 @@ import com.cloud.network.dao.Site2SiteVpnGatewayDao; import com.cloud.network.dao.Site2SiteVpnGatewayVO; import com.cloud.network.router.VirtualRouter; import com.cloud.network.rules.FirewallRuleVO; -import com.cloud.network.rules.LoadBalancer; import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityGroupManager; import com.cloud.network.security.SecurityGroupVO; @@ -211,7 +207,6 @@ import com.cloud.projects.Project; import com.cloud.projects.ProjectAccount; import com.cloud.projects.ProjectInvitation; import com.cloud.projects.ProjectService; -import com.cloud.region.ha.GlobalLoadBalancingRulesService; import com.cloud.resource.ResourceManager; import com.cloud.server.Criteria; import com.cloud.server.ManagementServer; @@ -1587,11 +1582,11 @@ public class ApiDBUtils { return _poolJoinDao.setStoragePoolResponse(vrData, vr); } - public static StoragePoolForMigrationResponse newStoragePoolForMigrationResponse(StoragePoolJoinVO vr) { + public static StoragePoolResponse newStoragePoolForMigrationResponse(StoragePoolJoinVO vr) { return _poolJoinDao.newStoragePoolForMigrationResponse(vr); } - public static StoragePoolForMigrationResponse fillStoragePoolForMigrationDetails(StoragePoolForMigrationResponse + public static StoragePoolResponse fillStoragePoolForMigrationDetails(StoragePoolResponse vrData, StoragePoolJoinVO vr){ return _poolJoinDao.setStoragePoolForMigrationResponse(vrData, vr); } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index ea1d803499e..bcc1605d8b9 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -29,35 +29,10 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.StringTokenizer; import java.util.TimeZone; import javax.inject.Inject; -import com.cloud.network.GuestVlan; -import com.cloud.network.IpAddress; -import com.cloud.network.Network; -import com.cloud.network.NetworkModel; -import com.cloud.network.NetworkProfile; -import com.cloud.network.PhysicalNetwork; -import com.cloud.network.PhysicalNetworkServiceProvider; -import com.cloud.network.PhysicalNetworkTrafficType; -import com.cloud.network.RemoteAccessVpn; -import com.cloud.network.Site2SiteCustomerGateway; -import com.cloud.network.Site2SiteVpnConnection; -import com.cloud.network.Site2SiteVpnGateway; -import com.cloud.network.VirtualRouterProvider; -import com.cloud.network.VpnUser; -import com.cloud.network.VpnUserVO; -import com.cloud.network.dao.LoadBalancerVO; -import com.cloud.network.rules.FirewallRule; -import com.cloud.network.rules.FirewallRuleVO; -import com.cloud.network.rules.HealthCheckPolicy; -import com.cloud.network.rules.LoadBalancer; -import com.cloud.network.rules.PortForwardingRule; -import com.cloud.network.rules.PortForwardingRuleVO; -import com.cloud.network.rules.StaticNatRule; -import com.cloud.network.rules.StickinessPolicy; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.affinity.AffinityGroup; @@ -141,7 +116,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; @@ -165,7 +139,6 @@ import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRule; import org.apache.cloudstack.region.PortableIp; import org.apache.cloudstack.region.PortableIpRange; import org.apache.cloudstack.region.Region; -import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.usage.Usage; import org.apache.cloudstack.usage.UsageService; import org.apache.cloudstack.usage.UsageTypes; @@ -217,11 +190,26 @@ import com.cloud.event.Event; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.hypervisor.HypervisorCapabilities; +import com.cloud.network.GuestVlan; +import com.cloud.network.IpAddress; +import com.cloud.network.Network; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; +import com.cloud.network.NetworkModel; +import com.cloud.network.NetworkProfile; import com.cloud.network.Networks.IsolationType; import com.cloud.network.Networks.TrafficType; +import com.cloud.network.PhysicalNetwork; +import com.cloud.network.PhysicalNetworkServiceProvider; +import com.cloud.network.PhysicalNetworkTrafficType; +import com.cloud.network.RemoteAccessVpn; +import com.cloud.network.Site2SiteCustomerGateway; +import com.cloud.network.Site2SiteVpnConnection; +import com.cloud.network.Site2SiteVpnGateway; +import com.cloud.network.VirtualRouterProvider; +import com.cloud.network.VpnUser; +import com.cloud.network.VpnUserVO; import com.cloud.network.as.AutoScalePolicy; import com.cloud.network.as.AutoScaleVmGroup; import com.cloud.network.as.AutoScaleVmProfile; @@ -230,10 +218,19 @@ import com.cloud.network.as.Condition; import com.cloud.network.as.ConditionVO; import com.cloud.network.as.Counter; import com.cloud.network.dao.IPAddressVO; +import com.cloud.network.dao.LoadBalancerVO; import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.PhysicalNetworkVO; import com.cloud.network.router.VirtualRouter; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.FirewallRuleVO; +import com.cloud.network.rules.HealthCheckPolicy; +import com.cloud.network.rules.LoadBalancer; import com.cloud.network.rules.LoadBalancerContainer.Scheme; +import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.rules.PortForwardingRuleVO; +import com.cloud.network.rules.StaticNatRule; +import com.cloud.network.rules.StickinessPolicy; import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityGroupVO; import com.cloud.network.security.SecurityRule; @@ -254,7 +251,6 @@ import com.cloud.projects.Project; import com.cloud.projects.ProjectAccount; import com.cloud.projects.ProjectInvitation; import com.cloud.region.ha.GlobalLoadBalancerRule; -import com.cloud.server.Criteria; import com.cloud.server.ResourceTag; import com.cloud.server.ResourceTag.TaggedResourceType; import com.cloud.service.ServiceOfferingVO; @@ -265,7 +261,6 @@ import com.cloud.storage.S3; import com.cloud.storage.Snapshot; import com.cloud.storage.SnapshotVO; import com.cloud.storage.Storage.ImageFormat; -import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.StoragePool; import com.cloud.storage.Swift; @@ -951,9 +946,9 @@ public class ApiResponseHelper implements ResponseGenerator { } @Override - public StoragePoolForMigrationResponse createStoragePoolForMigrationResponse(StoragePool pool) { + public StoragePoolResponse createStoragePoolForMigrationResponse(StoragePool pool) { List viewPools = ApiDBUtils.newStoragePoolView(pool); - List listPools = ViewResponseHelper.createStoragePoolForMigrationResponse( + List listPools = ViewResponseHelper.createStoragePoolForMigrationResponse( viewPools.toArray(new StoragePoolJoinVO[viewPools.size()])); assert listPools != null && listPools.size() == 1 : "There should be one storage pool returned"; return listPools.get(0); @@ -1875,148 +1870,6 @@ public class ApiResponseHelper implements ResponseGenerator { return ApiDBUtils.newEventResponse(vEvent); } - private List sumCapacities(List hostCapacities) { - Map totalCapacityMap = new HashMap(); - Map usedCapacityMap = new HashMap(); - - Set poolIdsToIgnore = new HashSet(); - Criteria c = new Criteria(); - // TODO: implement - List allStoragePools = ApiDBUtils.searchForStoragePools(c); - for (StoragePoolVO pool : allStoragePools) { - StoragePoolType poolType = pool.getPoolType(); - if (!(poolType.isShared())) {// All the non shared storages shouldn't show up in the capacity calculation - poolIdsToIgnore.add(pool.getId()); - } - } - - float cpuOverprovisioningFactor = ApiDBUtils.getCpuOverprovisioningFactor(); - - // collect all the capacity types, sum allocated/used and sum total...get one capacity number for each - for (Capacity capacity : hostCapacities) { - - // check if zone exist - DataCenter zone = ApiDBUtils.findZoneById(capacity.getDataCenterId()); - if (zone == null) { - continue; - } - - short capacityType = capacity.getCapacityType(); - - // If local storage then ignore - if ((capacityType == Capacity.CAPACITY_TYPE_STORAGE_ALLOCATED || capacityType == Capacity.CAPACITY_TYPE_STORAGE) - && poolIdsToIgnore.contains(capacity.getHostOrPoolId())) { - continue; - } - - String key = capacity.getCapacityType() + "_" + capacity.getDataCenterId(); - String keyForPodTotal = key + "_-1"; - - boolean sumPodCapacity = false; - if (capacity.getPodId() != null) { - key += "_" + capacity.getPodId(); - sumPodCapacity = true; - } - - Long totalCapacity = totalCapacityMap.get(key); - Long usedCapacity = usedCapacityMap.get(key); - - // reset overprovisioning factor to 1 - float overprovisioningFactor = 1; - if (capacityType == Capacity.CAPACITY_TYPE_CPU) { - overprovisioningFactor = cpuOverprovisioningFactor; - } - - if (totalCapacity == null) { - totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor)); - } else { - totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor)) + totalCapacity; - } - - if (usedCapacity == null) { - usedCapacity = new Long(capacity.getUsedCapacity()); - } else { - usedCapacity = new Long(capacity.getUsedCapacity() + usedCapacity); - } - - if (capacityType == Capacity.CAPACITY_TYPE_CPU || capacityType == Capacity.CAPACITY_TYPE_MEMORY) { // Reserved - // Capacity - // accounts - // for - // stopped - // vms - // that - // have been - // stopped - // within - // an - // interval - usedCapacity += capacity.getReservedCapacity(); - } - - totalCapacityMap.put(key, totalCapacity); - usedCapacityMap.put(key, usedCapacity); - - if (sumPodCapacity) { - totalCapacity = totalCapacityMap.get(keyForPodTotal); - usedCapacity = usedCapacityMap.get(keyForPodTotal); - - overprovisioningFactor = 1; - if (capacityType == Capacity.CAPACITY_TYPE_CPU) { - overprovisioningFactor = cpuOverprovisioningFactor; - } - - if (totalCapacity == null) { - totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor)); - } else { - totalCapacity = new Long((long) (capacity.getTotalCapacity() * overprovisioningFactor)) + totalCapacity; - } - - if (usedCapacity == null) { - usedCapacity = new Long(capacity.getUsedCapacity()); - } else { - usedCapacity = new Long(capacity.getUsedCapacity() + usedCapacity); - } - - if (capacityType == Capacity.CAPACITY_TYPE_CPU || capacityType == Capacity.CAPACITY_TYPE_MEMORY) { // Reserved - // Capacity - // accounts - // for - // stopped - // vms - // that - // have - // been - // stopped - // within - // an - // interval - usedCapacity += capacity.getReservedCapacity(); - } - - totalCapacityMap.put(keyForPodTotal, totalCapacity); - usedCapacityMap.put(keyForPodTotal, usedCapacity); - } - } - - List summedCapacities = new ArrayList(); - for (String key : totalCapacityMap.keySet()) { - CapacityVO summedCapacity = new CapacityVO(); - - StringTokenizer st = new StringTokenizer(key, "_"); - summedCapacity.setCapacityType(Short.parseShort(st.nextToken())); - summedCapacity.setDataCenterId(Long.parseLong(st.nextToken())); - if (st.hasMoreTokens()) { - summedCapacity.setPodId(Long.parseLong(st.nextToken())); - } - - summedCapacity.setTotalCapacity(totalCapacityMap.get(key)); - summedCapacity.setUsedCapacity(usedCapacityMap.get(key)); - - summedCapacities.add(summedCapacity); - } - return summedCapacities; - } @Override public List createCapacityResponse(List result, DecimalFormat format) { @@ -2278,9 +2131,14 @@ public class ApiResponseHelper implements ResponseGenerator { CapabilityResponse eIp = new CapabilityResponse(); eIp.setName(Capability.ElasticIp.getName()); - eIp.setValue(offering.getElasticLb() ? "true" : "false"); + eIp.setValue(offering.getElasticIp() ? "true" : "false"); staticNatCapResponse.add(eIp); + CapabilityResponse associatePublicIp = new CapabilityResponse(); + associatePublicIp.setName(Capability.AssociatePublicIP.getName()); + associatePublicIp.setValue(offering.getAssociatePublicIP() ? "true" : "false"); + staticNatCapResponse.add(associatePublicIp); + svcRsp.setCapabilities(staticNatCapResponse); } @@ -2489,6 +2347,13 @@ public class ApiResponseHelper implements ResponseGenerator { } response.setTags(tagResponses); + if(network.getNetworkACLId() != null){ + NetworkACL acl = ApiDBUtils.findByNetworkACLId(network.getNetworkACLId()); + if(acl != null){ + response.setAclId(acl.getUuid()); + } + } + response.setObjectName("network"); return response; } @@ -2620,6 +2485,9 @@ public class ApiResponseHelper implements ResponseGenerator { hpvCapabilitiesResponse.setHypervisorVersion(hpvCapabilities.getHypervisorVersion()); hpvCapabilitiesResponse.setIsSecurityGroupEnabled(hpvCapabilities.isSecurityGroupEnabled()); hpvCapabilitiesResponse.setMaxGuestsLimit(hpvCapabilities.getMaxGuestsLimit()); + hpvCapabilitiesResponse.setMaxDataVolumesLimit(hpvCapabilities.getMaxDataVolumesLimit()); + hpvCapabilitiesResponse.setMaxHostsPerCluster(hpvCapabilities.getMaxHostsPerCluster()); + hpvCapabilitiesResponse.setIsStorageMotionSupported(hpvCapabilities.isStorageMotionSupported()); return hpvCapabilitiesResponse; } diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index e748a35a747..0cd1d61d4e9 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -65,7 +65,6 @@ import org.apache.cloudstack.api.command.admin.host.ListHostsCmd; import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd; import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd; import org.apache.cloudstack.api.command.admin.user.ListUsersCmd; -import com.cloud.event.ActionEventUtils; import org.apache.cloudstack.api.command.user.account.ListAccountsCmd; import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd; import org.apache.cloudstack.api.command.user.event.ListEventsCmd; @@ -81,7 +80,6 @@ import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd; import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd; import org.apache.cloudstack.api.response.ExceptionResponse; import org.apache.cloudstack.api.response.ListResponse; -import org.apache.cloudstack.region.RegionManager; import org.apache.commons.codec.binary.Base64; import org.apache.http.ConnectionClosedException; import org.apache.http.HttpException; @@ -123,6 +121,7 @@ import com.cloud.configuration.ConfigurationVO; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; +import com.cloud.event.ActionEventUtils; import com.cloud.exception.AccountLimitException; import com.cloud.exception.CloudAuthenticationException; import com.cloud.exception.InsufficientCapacityException; @@ -167,8 +166,6 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer @Inject List _pluggableServices; @Inject List _apiAccessCheckers; - @Inject private final RegionManager _regionMgr = null; - private static int _workerCount = 0; private static ApiServer s_instance = null; private static final DateFormat _dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); @@ -198,7 +195,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer public void init() { Integer apiPort = null; // api port, null by default SearchCriteria sc = _configDao.createSearchCriteria(); - sc.addAnd("name", SearchCriteria.Op.EQ, "integration.api.port"); + sc.addAnd("name", SearchCriteria.Op.EQ, Config.IntegrationAPIPort.key()); List values = _configDao.search(sc, null); if ((values != null) && (values.size() > 0)) { ConfigurationVO apiPortConfig = values.get(0); @@ -211,7 +208,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer String strSnapshotLimit = configs.get(Config.ConcurrentSnapshotsThresholdPerHost.key()); if (strSnapshotLimit != null) { Long snapshotLimit = NumbersUtil.parseLong(strSnapshotLimit, 1L); - if (snapshotLimit <= 0) { + if (snapshotLimit.longValue() <= 0) { s_logger.debug("Global config parameter " + Config.ConcurrentSnapshotsThresholdPerHost.toString() + " is less or equal 0; defaulting to unlimited"); } else { @@ -220,8 +217,12 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer } Set> cmdClasses = new HashSet>(); - for(PluggableService pluggableService: _pluggableServices) + for(PluggableService pluggableService: _pluggableServices) { cmdClasses.addAll(pluggableService.getCommands()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Discovered plugin " + pluggableService.getClass().getSimpleName()); + } + } for(Class cmdClass: cmdClasses) { APICommand at = cmdClass.getAnnotation(APICommand.class); @@ -554,6 +555,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer } } + @SuppressWarnings("unchecked") private void buildAsyncListResponse(BaseListCmd command, Account account) { List responses = ((ListResponse) command.getResponseObject()).getResponses(); if (responses != null && responses.size() > 0) { @@ -848,7 +850,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer @Override public void logoutUser(long userId) { - _accountMgr.logoutUser(Long.valueOf(userId)); + _accountMgr.logoutUser(userId); return; } diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index 5a25732bca0..28aecfc223d 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -97,6 +97,8 @@ import com.cloud.api.query.vo.UserAccountJoinVO; import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.api.query.vo.VolumeJoinVO; import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.DedicatedResourceVO; +import com.cloud.dc.dao.DedicatedResourceDao; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; @@ -255,6 +257,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { @Inject private AffinityGroupJoinDao _affinityGroupJoinDao; + @Inject + private DedicatedResourceDao _dedicatedDao; /* (non-Javadoc) * @see com.cloud.api.query.QueryService#searchForUsers(org.apache.cloudstack.api.command.admin.user.ListUsersCmd) */ @@ -2252,12 +2256,14 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sc.addAnd("name", SearchCriteria.Op.SC, ssc); } - if (domainId != null) { + /*List all resources due to Explicit Dedication except the dedicated resources of other account + * if (domainId != null) { // for domainId != null // right now, we made the decision to only list zones associated // with this domain, private zone sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); - } else if (account.getType() == Account.ACCOUNT_TYPE_NORMAL) { + } else */ + if (account.getType() == Account.ACCOUNT_TYPE_NORMAL) { // it was decided to return all zones for the user's domain, and // everything above till root // list all zones belonging to this domain, and all of its @@ -2287,6 +2293,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { // remove disabled zones sc.addAnd("allocationState", SearchCriteria.Op.NEQ, Grouping.AllocationState.Disabled); + //remove Dedicated zones not dedicated to this domainId or subdomainId + List dedicatedZoneIds = removeDedicatedZoneNotSuitabe(domainIds); + if(!dedicatedZoneIds.isEmpty()){ + sdc.addAnd("id", SearchCriteria.Op.NIN, dedicatedZoneIds.toArray(new Object[dedicatedZoneIds.size()])); + } + } else if (account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN || account.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { // it was decided to return all zones for the domain admin, and // everything above till root, as well as zones till the domain leaf @@ -2316,6 +2328,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { // remove disabled zones sc.addAnd("allocationState", SearchCriteria.Op.NEQ, Grouping.AllocationState.Disabled); + + //remove Dedicated zones not dedicated to this domainId or subdomainId + List dedicatedZoneIds = removeDedicatedZoneNotSuitabe(domainIds); + if(!dedicatedZoneIds.isEmpty()){ + sdc.addAnd("id", SearchCriteria.Op.NIN, dedicatedZoneIds.toArray(new Object[dedicatedZoneIds.size()])); + } } // handle available=FALSE option, only return zones with at least one VM running there @@ -2341,6 +2359,17 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { return _dcJoinDao.searchAndCount(sc, searchFilter); } + private List removeDedicatedZoneNotSuitabe(List domainIds) { + //remove dedicated zone of other domain + List dedicatedZoneIds = new ArrayList(); + List dedicatedResources = _dedicatedDao.listZonesNotInDomainIds(domainIds); + for (DedicatedResourceVO dr : dedicatedResources) { + if(dr != null) { + dedicatedZoneIds.add(dr.getDataCenterId()); + } + } + return dedicatedZoneIds; + } // This method is used for permissions check for both disk and service // offerings diff --git a/server/src/com/cloud/api/query/ViewResponseHelper.java b/server/src/com/cloud/api/query/ViewResponseHelper.java index 827ae7b7a66..a61da69b2e8 100644 --- a/server/src/com/cloud/api/query/ViewResponseHelper.java +++ b/server/src/com/cloud/api/query/ViewResponseHelper.java @@ -16,36 +16,6 @@ // under the License. package com.cloud.api.query; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.Hashtable; -import java.util.List; - -import org.apache.cloudstack.affinity.AffinityGroupResponse; -import org.apache.cloudstack.api.ApiConstants.HostDetails; -import org.apache.cloudstack.api.ApiConstants.VMDetails; -import org.apache.cloudstack.api.response.AccountResponse; -import org.apache.cloudstack.api.response.AsyncJobResponse; -import org.apache.cloudstack.api.response.DiskOfferingResponse; -import org.apache.cloudstack.api.response.DomainRouterResponse; -import org.apache.cloudstack.api.response.EventResponse; -import org.apache.cloudstack.api.response.HostResponse; -import org.apache.cloudstack.api.response.HostForMigrationResponse; -import org.apache.cloudstack.api.response.InstanceGroupResponse; -import org.apache.cloudstack.api.response.ProjectAccountResponse; -import org.apache.cloudstack.api.response.ProjectInvitationResponse; -import org.apache.cloudstack.api.response.ProjectResponse; -import org.apache.cloudstack.api.response.ResourceTagResponse; -import org.apache.cloudstack.api.response.SecurityGroupResponse; -import org.apache.cloudstack.api.response.ServiceOfferingResponse; -import org.apache.cloudstack.api.response.StoragePoolResponse; -import org.apache.cloudstack.api.response.StoragePoolForMigrationResponse; -import org.apache.cloudstack.api.response.UserResponse; -import org.apache.cloudstack.api.response.UserVmResponse; -import org.apache.cloudstack.api.response.VolumeResponse; -import org.apache.cloudstack.api.response.ZoneResponse; -import org.apache.log4j.Logger; - import com.cloud.api.ApiDBUtils; import com.cloud.api.query.vo.AccountJoinVO; import com.cloud.api.query.vo.AffinityGroupJoinVO; @@ -68,6 +38,34 @@ import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.api.query.vo.VolumeJoinVO; import com.cloud.user.Account; import com.cloud.user.UserContext; +import org.apache.cloudstack.affinity.AffinityGroupResponse; +import org.apache.cloudstack.api.ApiConstants.HostDetails; +import org.apache.cloudstack.api.ApiConstants.VMDetails; +import org.apache.cloudstack.api.response.AccountResponse; +import org.apache.cloudstack.api.response.AsyncJobResponse; +import org.apache.cloudstack.api.response.DiskOfferingResponse; +import org.apache.cloudstack.api.response.DomainRouterResponse; +import org.apache.cloudstack.api.response.EventResponse; +import org.apache.cloudstack.api.response.HostForMigrationResponse; +import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.response.InstanceGroupResponse; +import org.apache.cloudstack.api.response.ProjectAccountResponse; +import org.apache.cloudstack.api.response.ProjectInvitationResponse; +import org.apache.cloudstack.api.response.ProjectResponse; +import org.apache.cloudstack.api.response.ResourceTagResponse; +import org.apache.cloudstack.api.response.SecurityGroupResponse; +import org.apache.cloudstack.api.response.ServiceOfferingResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.UserResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.api.response.VolumeResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.log4j.Logger; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.Hashtable; +import java.util.List; /** * Helper class to generate response from DB view VO objects. @@ -285,11 +283,11 @@ public class ViewResponseHelper { return new ArrayList(vrDataList.values()); } - public static List createStoragePoolForMigrationResponse(StoragePoolJoinVO... pools) { - Hashtable vrDataList = new Hashtable(); + public static List createStoragePoolForMigrationResponse(StoragePoolJoinVO... pools) { + Hashtable vrDataList = new Hashtable(); // Initialise the vrdatalist with the input data for (StoragePoolJoinVO vr : pools) { - StoragePoolForMigrationResponse vrData = vrDataList.get(vr.getId()); + StoragePoolResponse vrData = vrDataList.get(vr.getId()); if ( vrData == null ) { // first time encountering this vm vrData = ApiDBUtils.newStoragePoolForMigrationResponse(vr); @@ -299,7 +297,7 @@ public class ViewResponseHelper { } vrDataList.put(vr.getId(), vrData); } - return new ArrayList(vrDataList.values()); + return new ArrayList(vrDataList.values()); } diff --git a/server/src/com/cloud/api/query/dao/StoragePoolJoinDao.java b/server/src/com/cloud/api/query/dao/StoragePoolJoinDao.java index b7e467fd6d3..e438b0665f7 100644 --- a/server/src/com/cloud/api/query/dao/StoragePoolJoinDao.java +++ b/server/src/com/cloud/api/query/dao/StoragePoolJoinDao.java @@ -16,14 +16,12 @@ // under the License. package com.cloud.api.query.dao; -import java.util.List; - -import org.apache.cloudstack.api.response.StoragePoolForMigrationResponse; -import org.apache.cloudstack.api.response.StoragePoolResponse; - import com.cloud.api.query.vo.StoragePoolJoinVO; import com.cloud.storage.StoragePool; import com.cloud.utils.db.GenericDao; +import org.apache.cloudstack.api.response.StoragePoolResponse; + +import java.util.List; public interface StoragePoolJoinDao extends GenericDao { @@ -31,9 +29,9 @@ public interface StoragePoolJoinDao extends GenericDao StoragePoolResponse setStoragePoolResponse(StoragePoolResponse response, StoragePoolJoinVO host); - StoragePoolForMigrationResponse newStoragePoolForMigrationResponse(StoragePoolJoinVO host); + StoragePoolResponse newStoragePoolForMigrationResponse(StoragePoolJoinVO host); - StoragePoolForMigrationResponse setStoragePoolForMigrationResponse(StoragePoolForMigrationResponse response, + StoragePoolResponse setStoragePoolForMigrationResponse(StoragePoolResponse response, StoragePoolJoinVO host); List newStoragePoolView(StoragePool group); diff --git a/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java index e401f4474d7..a6355ad9867 100644 --- a/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java @@ -22,7 +22,6 @@ import java.util.List; import javax.ejb.Local; import javax.inject.Inject; -import org.apache.cloudstack.api.response.StoragePoolForMigrationResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -85,6 +84,9 @@ public class StoragePoolJoinDaoImpl extends GenericDaoBase { + + DedicatedResourceVO findByZoneId(Long zoneId); + + DedicatedResourceVO findByPodId(Long podId); + + DedicatedResourceVO findByClusterId(Long clusterId); + + DedicatedResourceVO findByHostId(Long hostId); + + Pair, Integer> searchDedicatedHosts(Long hostId, Long domainId, Long accountId); + + Pair, Integer> searchDedicatedClusters(Long clusterId, Long domainId, Long accountId); + + Pair, Integer> searchDedicatedPods(Long podId, Long domainId, Long accountId); + + Pair, Integer> searchDedicatedZones(Long dataCenterId, Long domainId, Long accountId); + + List listByAccountId(Long accountId); + + List listByDomainId(Long domainId); + + List listZonesNotInDomainIds(List domainIds); +} \ No newline at end of file diff --git a/server/src/com/cloud/dc/dao/DedicatedResourceDaoImpl.java b/server/src/com/cloud/dc/dao/DedicatedResourceDaoImpl.java new file mode 100644 index 00000000000..2a3b4690a0c --- /dev/null +++ b/server/src/com/cloud/dc/dao/DedicatedResourceDaoImpl.java @@ -0,0 +1,304 @@ +// 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.dao; + +import java.util.List; + +import javax.ejb.Local; + +import org.springframework.stereotype.Component; + +import com.cloud.dc.DedicatedResourceVO; +import com.cloud.utils.Pair; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.Transaction; + +@Component +@Local(value={DedicatedResourceDao.class}) @DB(txn = false) +public class DedicatedResourceDaoImpl extends GenericDaoBase implements DedicatedResourceDao { + protected final SearchBuilder ZoneSearch; + protected final SearchBuilder PodSearch; + protected final SearchBuilder ClusterSearch; + protected final SearchBuilder HostSearch; + + protected SearchBuilder ListZonesByDomainIdSearch; + protected SearchBuilder ListPodsByDomainIdSearch; + protected SearchBuilder ListClustersByDomainIdSearch; + protected SearchBuilder ListHostsByDomainIdSearch; + + protected SearchBuilder ListZonesByAccountIdSearch; + protected SearchBuilder ListPodsByAccountIdSearch; + protected SearchBuilder ListClustersByAccountIdSearch; + protected SearchBuilder ListHostsByAccountIdSearch; + + protected SearchBuilder ListAllZonesSearch; + protected SearchBuilder ListAllPodsSearch; + protected SearchBuilder ListAllClustersSearch; + protected SearchBuilder ListAllHostsSearch; + + protected SearchBuilder ListByAccountId; + protected SearchBuilder ListByDomainId; + + protected SearchBuilder ZoneByDomainIdsSearch; + + protected DedicatedResourceDaoImpl() { + PodSearch = createSearchBuilder(); + PodSearch.and("podId", PodSearch.entity().getPodId(), SearchCriteria.Op.EQ); + PodSearch.done(); + + ZoneSearch = createSearchBuilder(); + ZoneSearch.and("zoneId", ZoneSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + ZoneSearch.done(); + + ClusterSearch = createSearchBuilder(); + ClusterSearch.and("clusterId", ClusterSearch.entity().getClusterId(), SearchCriteria.Op.EQ); + ClusterSearch.done(); + + HostSearch = createSearchBuilder(); + HostSearch.and("hostId", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ); + HostSearch.done(); + + ListZonesByDomainIdSearch = createSearchBuilder(); + ListZonesByDomainIdSearch.and("zoneId", ListZonesByDomainIdSearch.entity().getDataCenterId(), SearchCriteria.Op.NNULL); + ListZonesByDomainIdSearch.and("domainId", ListZonesByDomainIdSearch.entity().getDomainId(), SearchCriteria.Op.EQ); + ListZonesByDomainIdSearch.and("accountId", ListZonesByDomainIdSearch.entity().getAccountId(), SearchCriteria.Op.NULL); + ListZonesByDomainIdSearch.done(); + + ListZonesByAccountIdSearch = createSearchBuilder(); + ListZonesByAccountIdSearch.and("zoneId", ListZonesByAccountIdSearch.entity().getDataCenterId(), SearchCriteria.Op.NNULL); + ListZonesByAccountIdSearch.and("accountId", ListZonesByAccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + ListZonesByAccountIdSearch.done(); + + ListPodsByDomainIdSearch = createSearchBuilder(); + ListPodsByDomainIdSearch.and("podId", ListPodsByDomainIdSearch.entity().getPodId(), SearchCriteria.Op.NNULL); + ListPodsByDomainIdSearch.and("domainId", ListPodsByDomainIdSearch.entity().getDomainId(), SearchCriteria.Op.EQ); + ListPodsByDomainIdSearch.and("accountId", ListPodsByDomainIdSearch.entity().getAccountId(), SearchCriteria.Op.NULL); + ListPodsByDomainIdSearch.done(); + + ListPodsByAccountIdSearch = createSearchBuilder(); + ListPodsByAccountIdSearch.and("podId", ListPodsByAccountIdSearch.entity().getPodId(), SearchCriteria.Op.NNULL); + ListPodsByAccountIdSearch.and("accountId", ListPodsByAccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + ListPodsByAccountIdSearch.done(); + + ListClustersByDomainIdSearch = createSearchBuilder(); + ListClustersByDomainIdSearch.and("clusterId", ListClustersByDomainIdSearch.entity().getClusterId(), SearchCriteria.Op.NNULL); + ListClustersByDomainIdSearch.and("domainId", ListClustersByDomainIdSearch.entity().getDomainId(), SearchCriteria.Op.EQ); + ListClustersByDomainIdSearch.and("accountId", ListClustersByDomainIdSearch.entity().getAccountId(), SearchCriteria.Op.NULL); + ListClustersByDomainIdSearch.done(); + + ListClustersByAccountIdSearch = createSearchBuilder(); + ListClustersByAccountIdSearch.and("clusterId", ListClustersByAccountIdSearch.entity().getClusterId(), SearchCriteria.Op.NNULL); + ListClustersByAccountIdSearch.and("accountId", ListClustersByAccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + ListClustersByAccountIdSearch.done(); + + ListHostsByDomainIdSearch = createSearchBuilder(); + ListHostsByDomainIdSearch.and("hostId", ListHostsByDomainIdSearch.entity().getHostId(), SearchCriteria.Op.NNULL); + ListHostsByDomainIdSearch.and("domainId", ListHostsByDomainIdSearch.entity().getDomainId(), SearchCriteria.Op.EQ); + ListHostsByDomainIdSearch.and("accountId", ListHostsByDomainIdSearch.entity().getAccountId(), SearchCriteria.Op.NULL); + ListHostsByDomainIdSearch.done(); + + ListHostsByAccountIdSearch = createSearchBuilder(); + ListHostsByAccountIdSearch.and("hostId", ListHostsByAccountIdSearch.entity().getHostId(), SearchCriteria.Op.NNULL); + ListHostsByAccountIdSearch.and("accountId", ListHostsByAccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + ListHostsByAccountIdSearch.done(); + + ListAllZonesSearch = createSearchBuilder(); + ListAllZonesSearch.and("zoneId", ListAllZonesSearch.entity().getDataCenterId(), Op.EQ); + ListAllZonesSearch.and("podId", ListAllZonesSearch.entity().getPodId(), Op.NULL); + ListAllZonesSearch.and("clusterId", ListAllZonesSearch.entity().getClusterId(), Op.NULL); + ListAllZonesSearch.and("hostId", ListAllZonesSearch.entity().getHostId(), Op.NULL); + ListAllZonesSearch.and("accountId", ListAllZonesSearch.entity().getAccountId(), Op.EQ); + ListAllZonesSearch.and("domainId", ListAllZonesSearch.entity().getDomainId(), Op.EQ); + ListAllZonesSearch.done(); + + ListAllPodsSearch = createSearchBuilder(); + ListAllPodsSearch.and("zoneId", ListAllPodsSearch.entity().getDataCenterId(), Op.NULL); + ListAllPodsSearch.and("podId", ListAllPodsSearch.entity().getPodId(), Op.EQ); + ListAllPodsSearch.and("clusterId", ListAllPodsSearch.entity().getClusterId(), Op.NULL); + ListAllPodsSearch.and("hostId", ListAllPodsSearch.entity().getHostId(), Op.NULL); + ListAllPodsSearch.and("accountId", ListAllPodsSearch.entity().getAccountId(), Op.EQ); + ListAllPodsSearch.and("domainId", ListAllPodsSearch.entity().getDomainId(), Op.EQ); + ListAllPodsSearch.done(); + + ListAllClustersSearch = createSearchBuilder(); + ListAllClustersSearch.and("zoneId", ListAllClustersSearch.entity().getDataCenterId(), Op.NULL); + ListAllClustersSearch.and("podId", ListAllClustersSearch.entity().getPodId(), Op.NULL); + ListAllClustersSearch.and("clusterId", ListAllClustersSearch.entity().getClusterId(), Op.EQ); + ListAllClustersSearch.and("hostId", ListAllClustersSearch.entity().getHostId(), Op.NULL); + ListAllClustersSearch.and("accountId", ListAllClustersSearch.entity().getAccountId(), Op.EQ); + ListAllClustersSearch.and("domainId", ListAllClustersSearch.entity().getDomainId(), Op.EQ); + ListAllClustersSearch.done(); + + ListAllHostsSearch = createSearchBuilder(); + ListAllHostsSearch.and("zoneId", ListAllHostsSearch.entity().getDataCenterId(), Op.NULL); + ListAllHostsSearch.and("podId", ListAllHostsSearch.entity().getPodId(), Op.NULL); + ListAllHostsSearch.and("clusterId", ListAllHostsSearch.entity().getClusterId(), Op.NULL); + ListAllHostsSearch.and("hostId", ListAllHostsSearch.entity().getHostId(), Op.EQ); + ListAllHostsSearch.and("accountId", ListAllHostsSearch.entity().getAccountId(), Op.EQ); + ListAllHostsSearch.and("domainId", ListAllHostsSearch.entity().getDomainId(), Op.EQ); + ListAllHostsSearch.done(); + + ListByAccountId = createSearchBuilder(); + ListByAccountId.and("accountId", ListByAccountId.entity().getAccountId(), SearchCriteria.Op.EQ); + ListByAccountId.done(); + + ListByDomainId = createSearchBuilder(); + ListByDomainId.and("accountId", ListByDomainId.entity().getAccountId(), SearchCriteria.Op.NULL); + ListByDomainId.and("domainId", ListByDomainId.entity().getDomainId(), SearchCriteria.Op.EQ); + ListByDomainId.done(); + + ZoneByDomainIdsSearch = createSearchBuilder(); + ZoneByDomainIdsSearch.and("zoneId", ZoneByDomainIdsSearch.entity().getDataCenterId(), SearchCriteria.Op.NNULL); + ZoneByDomainIdsSearch.and("domainId", ZoneByDomainIdsSearch.entity().getDomainId(), SearchCriteria.Op.NIN); + ZoneByDomainIdsSearch.done(); + } + + @Override + public DedicatedResourceVO findByZoneId(Long zoneId) { + SearchCriteria sc = ZoneSearch.create(); + sc.setParameters("zoneId", zoneId); + return findOneBy(sc); + } + + @Override + public DedicatedResourceVO findByPodId(Long podId) { + SearchCriteria sc = PodSearch.create(); + sc.setParameters("podId", podId); + + return findOneBy(sc); + } + + @Override + public DedicatedResourceVO findByClusterId(Long clusterId) { + SearchCriteria sc = ClusterSearch.create(); + sc.setParameters("clusterId", clusterId); + + return findOneBy(sc); + } + + @Override + public DedicatedResourceVO findByHostId(Long hostId) { + SearchCriteria sc = HostSearch.create(); + sc.setParameters("hostId", hostId); + + return findOneBy(sc); + } + + @Override + public Pair, Integer> searchDedicatedZones(Long dataCenterId, Long domainId, Long accountId){ + SearchCriteria sc = ListAllZonesSearch.create(); + if (dataCenterId != null) { + sc.setParameters("dataCenterId", dataCenterId); + } + if(domainId != null) { + sc.setParameters("domainId", domainId); + if(accountId != null) { + sc.setParameters("accountId", accountId); + } else { + sc.setParameters("accountId", (Object)null); + } + } + return searchAndCount(sc, null); + } + @Override + public Pair, Integer> searchDedicatedPods(Long podId, Long domainId, Long accountId){ + SearchCriteria sc = ListAllPodsSearch.create(); + if (podId != null) { + sc.setParameters("podId", podId); + } + if(domainId != null) { + sc.setParameters("domainId", domainId); + if(accountId != null) { + sc.setParameters("accountId", accountId); + } else { + sc.setParameters("accountId", (Object)null); + } + } + return searchAndCount(sc, null); + } + + @Override + public Pair, Integer> searchDedicatedClusters(Long clusterId, Long domainId, Long accountId){ + SearchCriteria sc = ListAllClustersSearch.create(); + if (clusterId != null) { + sc.setParameters("clusterId", clusterId); + } + if(domainId != null) { + sc.setParameters("domainId", domainId); + if(accountId != null) { + sc.setParameters("accountId", accountId); + } else { + sc.setParameters("accountId", (Object)null); + } + } + return searchAndCount(sc, null); + } + + @Override + public Pair, Integer> searchDedicatedHosts(Long hostId, Long domainId, Long accountId){ + SearchCriteria sc = ListAllHostsSearch.create(); + if (hostId != null) { + sc.setParameters("hostId", hostId); + } + if(domainId != null) { + sc.setParameters("domainId", domainId); + if(accountId != null) { + sc.setParameters("accountId", accountId); + } else { + sc.setParameters("accountId", (Object)null); + } + } + return searchAndCount(sc, null); + } + + @Override + public List listByAccountId(Long accountId){ + SearchCriteria sc = ListByAccountId.create(); + sc.setParameters("accountId", accountId); + return listBy(sc); + } + + @Override + public List listByDomainId(Long domainId){ + SearchCriteria sc = ListByDomainId.create(); + sc.setParameters("domainId", domainId); + return listBy(sc); + } + + @Override + public List listZonesNotInDomainIds(List domainIds) { + SearchCriteria sc = ZoneByDomainIdsSearch.create(); + sc.setParameters("domainId", domainIds.toArray(new Object[domainIds.size()])); + return listBy(sc); + } + + @Override + public boolean remove(Long id) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + DedicatedResourceVO resource = createForUpdate(); + update(id, resource); + + boolean result = super.remove(id); + txn.commit(); + return result; + } +} diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java index 795b526c403..eb895e53b04 100644 --- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -30,6 +30,7 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.cloudstack.affinity.AffinityGroupProcessor; +import org.apache.cloudstack.affinity.AffinityGroupVMMapVO; import org.apache.cloudstack.affinity.dao.AffinityGroupDao; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; @@ -53,9 +54,12 @@ import com.cloud.dc.ClusterDetailsVO; 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.Pod; 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.DeploymentPlanner.ExcludeList; import com.cloud.deploy.DeploymentPlanner.PlannerResourceUsage; @@ -91,6 +95,7 @@ import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.DB; import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.DiskProfile; import com.cloud.vm.ReservationContext; import com.cloud.vm.VMInstanceVO; @@ -157,6 +162,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy @Inject protected HostDao _hostDao; @Inject protected HostPodDao _podDao; @Inject protected ClusterDao _clusterDao; + @Inject protected DedicatedResourceDao _dedicatedDao; @Inject protected GuestOSDao _guestOSDao = null; @Inject protected GuestOSCategoryDao _guestOSCategoryDao = null; @Inject protected DiskOfferingDao _diskOfferingDao; @@ -196,6 +202,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy // call affinitygroup chain VirtualMachine vm = vmProfile.getVirtualMachine(); long vmGroupCount = _affinityGroupVMMapDao.countAffinityGroupsForVm(vm.getId()); + DataCenter dc = _dcDao.findById(vm.getDataCenterId()); if (vmGroupCount > 0) { for (AffinityGroupProcessor processor : _affinityProcessors) { @@ -203,13 +210,14 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy } } + checkForNonDedicatedResources(vmProfile, dc, avoids); if (s_logger.isDebugEnabled()) { s_logger.debug("Deploy avoids pods: " + avoids.getPodsToAvoid() + ", clusters: " + avoids.getClustersToAvoid() + ", hosts: " + avoids.getHostsToAvoid()); } // call planners - DataCenter dc = _dcDao.findById(vm.getDataCenterId()); + //DataCenter dc = _dcDao.findById(vm.getDataCenterId()); // check if datacenter is in avoid set if (avoids.shouldAvoid(dc)) { if (s_logger.isDebugEnabled()) { @@ -283,9 +291,8 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy if (!suitableVolumeStoragePools.isEmpty()) { List suitableHosts = new ArrayList(); suitableHosts.add(host); - Pair> potentialResources = findPotentialDeploymentResources( - suitableHosts, suitableVolumeStoragePools, avoids, getPlannerUsage(planner)); + suitableHosts, suitableVolumeStoragePools, avoids, getPlannerUsage(planner,vmProfile, plan ,avoids)); if (potentialResources != null) { Pod pod = _podDao.findById(host.getPodId()); Cluster cluster = _clusterDao.findById(host.getClusterId()); @@ -339,13 +346,13 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy vmProfile, lastPlan, avoids, HostAllocator.RETURN_UPTO_ALL); Map> suitableVolumeStoragePools = result.first(); List readyAndReusedVolumes = result.second(); + // choose the potential pool for this VM for this host if (!suitableVolumeStoragePools.isEmpty()) { List suitableHosts = new ArrayList(); suitableHosts.add(host); - Pair> potentialResources = findPotentialDeploymentResources( - suitableHosts, suitableVolumeStoragePools, avoids, getPlannerUsage(planner)); + suitableHosts, suitableVolumeStoragePools, avoids, getPlannerUsage(planner,vmProfile, plan ,avoids)); if (potentialResources != null) { Pod pod = _podDao.findById(host.getPodId()); Cluster cluster = _clusterDao.findById(host.getClusterId()); @@ -395,7 +402,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy resetAvoidSet(plannerAvoidOutput, plannerAvoidInput); dest = checkClustersforDestination(clusterList, vmProfile, plan, avoids, dc, - getPlannerUsage(planner), plannerAvoidOutput); + getPlannerUsage(planner, vmProfile, plan, avoids), plannerAvoidOutput); if (dest != null) { return dest; } @@ -430,6 +437,60 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy return dest; } + private void checkForNonDedicatedResources(VirtualMachineProfile vmProfile, DataCenter dc, ExcludeList avoids) { + boolean isExplicit = false; + VirtualMachine vm = vmProfile.getVirtualMachine(); + // check affinity group of type Explicit dedication exists + List vmGroupMappings = _affinityGroupVMMapDao.findByVmIdType(vm.getId(), "ExplicitDedication"); + + if (vmGroupMappings != null && !vmGroupMappings.isEmpty()){ + isExplicit = true; + } + + if (!isExplicit && vm.getType() == VirtualMachine.Type.User) { + //add explicitly dedicated resources in avoidList + DedicatedResourceVO dedicatedZone = _dedicatedDao.findByZoneId(dc.getId()); + if (dedicatedZone != null) { + long accountDomainId = vmProfile.getOwner().getDomainId(); + if (dedicatedZone.getDomainId() != null && !dedicatedZone.getDomainId().equals(accountDomainId)) { + throw new CloudRuntimeException("Failed to deploy VM. Zone " + dc.getName() + " is dedicated."); + } + } + + List podsInDc = _podDao.listByDataCenterId(dc.getId()); + for (HostPodVO pod : podsInDc) { + DedicatedResourceVO dedicatedPod = _dedicatedDao.findByPodId(pod.getId()); + if (dedicatedPod != null) { + avoids.addPod(dedicatedPod.getPodId()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Cannot use this dedicated pod " + pod.getName() + "."); + } + } + } + + List clusterInDc = _clusterDao.listClustersByDcId(dc.getId()); + for (ClusterVO cluster : clusterInDc) { + DedicatedResourceVO dedicatedCluster = _dedicatedDao.findByClusterId(cluster.getId()); + if (dedicatedCluster != null) { + avoids.addCluster(dedicatedCluster.getClusterId()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Cannot use this dedicated Cluster " + cluster.getName() + "."); + } + } + } + List hostInDc = _hostDao.listByDataCenterId(dc.getId()); + for (HostVO host : hostInDc) { + DedicatedResourceVO dedicatedHost = _dedicatedDao.findByHostId(host.getId()); + if (dedicatedHost != null) { + avoids.addHost(dedicatedHost.getHostId()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Cannot use this dedicated host " + host.getName() + "."); + } + } + } + } + } + private void resetAvoidSet(ExcludeList avoidSet, ExcludeList removeSet) { if (avoidSet.getDataCentersToAvoid() != null && removeSet.getDataCentersToAvoid() != null) { avoidSet.getDataCentersToAvoid().removeAll(removeSet.getDataCentersToAvoid()); @@ -448,9 +509,9 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy } } - private PlannerResourceUsage getPlannerUsage(DeploymentPlanner planner) { + private PlannerResourceUsage getPlannerUsage(DeploymentPlanner planner, VirtualMachineProfile vmProfile, DeploymentPlan plan, ExcludeList avoids) throws InsufficientServerCapacityException { if (planner != null && planner instanceof DeploymentClusterPlanner) { - return ((DeploymentClusterPlanner) planner).getResourceUsage(); + return ((DeploymentClusterPlanner) planner).getResourceUsage(vmProfile, plan, avoids); } else { return DeploymentPlanner.PlannerResourceUsage.Shared; } diff --git a/server/src/com/cloud/deploy/FirstFitPlanner.java b/server/src/com/cloud/deploy/FirstFitPlanner.java index caf8c6e92db..7124de28d7b 100755 --- a/server/src/com/cloud/deploy/FirstFitPlanner.java +++ b/server/src/com/cloud/deploy/FirstFitPlanner.java @@ -517,7 +517,8 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentClusterPla } @Override - public PlannerResourceUsage getResourceUsage() { + public PlannerResourceUsage getResourceUsage(VirtualMachineProfile vmProfile, + DeploymentPlan plan, ExcludeList avoid) throws InsufficientServerCapacityException { return PlannerResourceUsage.Shared; } } diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java index ea4fcc1e5bf..d8945af9b8c 100644 --- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java +++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java @@ -25,7 +25,9 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VolumeTO; +import com.cloud.configuration.Config; import com.cloud.offering.ServiceOffering; +import com.cloud.server.ConfigurationServer; import com.cloud.storage.dao.VMTemplateDetailsDao; import com.cloud.utils.component.AdapterBase; import com.cloud.vm.NicProfile; @@ -43,6 +45,8 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis @Inject NicDao _nicDao; @Inject VMInstanceDao _virtualMachineDao; @Inject NicSecondaryIpDao _nicSecIpDao; + @Inject ConfigurationServer _configServer; + protected HypervisorGuruBase() { super(); @@ -121,7 +125,10 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis // Workaround to make sure the TO has the UUID we need for Niciri integration VMInstanceVO vmInstance = _virtualMachineDao.findById(to.getId()); to.setUuid(vmInstance.getUuid()); - + + // + to.setEnableDynamicallyScaleVm(Boolean.parseBoolean(_configServer.getConfigValue(Config.EnableDynamicallyScaleVm.key(), Config.ConfigurationParameterScope.zone.toString(), vm.getDataCenterId()))); + return to; } diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java index f93bf7ae9b5..4b110e9596c 100644 --- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java @@ -210,21 +210,21 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase zoneId = pNetwork.getDataCenterId(); PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), ntwkDevice.getNetworkServiceProvder()); + ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), ntwkDevice.getNetworkServiceProvder()); + if (ntwkSvcProvider == null) { + throw new CloudRuntimeException("Network Service Provider: " + ntwkDevice.getNetworkServiceProvder() + + " is not enabled in the physical network: " + physicalNetworkId + "to add this device"); + } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) { + throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() + + " is in shutdown state in the physical network: " + physicalNetworkId + "to add this device"); + } + if (gslbProvider) { ExternalLoadBalancerDeviceVO zoneGslbProvider = _externalLoadBalancerDeviceDao.findGslbServiceProvider( physicalNetworkId, ntwkDevice.getNetworkServiceProvder()); if (zoneGslbProvider != null) { throw new CloudRuntimeException("There is a GSLB service provider configured in the zone alredy."); } - } else { - ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), ntwkDevice.getNetworkServiceProvder()); - if (ntwkSvcProvider == null) { - throw new CloudRuntimeException("Network Service Provider: " + ntwkDevice.getNetworkServiceProvder() + - " is not enabled in the physical network: " + physicalNetworkId + "to add this device"); - } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) { - throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() + - " is in shutdown state in the physical network: " + physicalNetworkId + "to add this device"); - } } URI uri; diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index cc149a542fd..b92ef4b7dfa 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -1544,6 +1544,9 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L finalizeServicesAndProvidersForNetwork(offering, plan.getPhysicalNetworkId()))); if (domainId != null && aclType == ACLType.Domain) { + if (subdomainAccess == null ) { + subdomainAccess = true; + } _networksDao.addDomainToNetwork(id, domainId, subdomainAccess); } @@ -2614,7 +2617,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L public boolean shutdownNetwork(long networkId, ReservationContext context, boolean cleanupElements) { boolean result = false; Transaction txn = Transaction.currentTxn(); - + txn.start(); NetworkVO network = _networksDao.lockRow(networkId, true); if (network == null) { s_logger.debug("Unable to find network with id: " + networkId); @@ -2625,7 +2628,6 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return false; } - txn.start(); if (isSharedNetworkWithServices(network)) { network.setState(Network.State.Shutdown); _networksDao.update(network.getId(), network); diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java index f6bd646a91d..6b63eadd4b2 100755 --- a/server/src/com/cloud/network/NetworkModelImpl.java +++ b/server/src/com/cloud/network/NetworkModelImpl.java @@ -1673,7 +1673,7 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { if (networkDomainMap.subdomainAccess) { Set parentDomains = _domainMgr.getDomainParentIds(domainId); - if (parentDomains.contains(domainId)) { + if (parentDomains.contains(networkDomainId)) { return true; } } diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 98992846c4e..2bf9f402d34 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -1285,10 +1285,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { throw new InvalidParameterValueException("Network offering can't be used for VPC networks"); } - if(aclId == null){ - //Use default deny all ACL, when aclId is not specified - aclId = NetworkACL.DEFAULT_DENY; - } else { + if(aclId != null){ NetworkACL acl = _networkACLDao.findById(aclId); if(acl == null){ throw new InvalidParameterValueException("Unable to find specified NetworkACL"); @@ -1938,7 +1935,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { //perform below validation if the network is vpc network if (network.getVpcId() != null && networkOfferingId != null) { Vpc vpc = _vpcMgr.getVpc(network.getVpcId()); - _vpcMgr.validateNtwkOffForNtwkInVpc(networkId, networkOfferingId, null, null, vpc, null, _accountMgr.getAccount(network.getAccountId())); + _vpcMgr.validateNtwkOffForNtwkInVpc(networkId, networkOfferingId, null, null, vpc, null, _accountMgr.getAccount(network.getAccountId()), null); } // don't allow to update network in Destroy state diff --git a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java index 334a5a108e6..f7275b0e237 100644 --- a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java +++ b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java @@ -159,6 +159,7 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService, rule.getIcmpType(), null, rule.getType(), rule.getNetworkId(), rule.getTrafficType()); } + @Override public FirewallRule createIngressFirewallRule(FirewallRule rule) throws NetworkRuleConflictException { Account caller = UserContext.current().getCaller(); Long sourceIpAddressId = rule.getSourceIpAddressId(); diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 633357e4bdd..67d31ab3a4e 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -973,8 +973,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } if (nicInSameNetwork == null) { - InvalidParameterValueException ex = new InvalidParameterValueException("VM " + instanceId - + " cannot be added because it doesn't belong in the same network."); + InvalidParameterValueException ex = + new InvalidParameterValueException("VM with id specified cannot be added because it doesn't belong in the same network."); ex.addProxyObject(vm.getUuid(), "instanceId"); throw ex; } @@ -1835,9 +1835,8 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements } } - IPAddressVO addr = _ipAddressDao.findById(loadBalancer.getSourceIpAddressId()); - List userVms = _vmDao.listVirtualNetworkInstancesByAcctAndZone(loadBalancer.getAccountId(), - addr.getDataCenterId(), loadBalancer.getNetworkId()); + List userVms = _vmDao.listVirtualNetworkInstancesByAcctAndNetwork(loadBalancer.getAccountId(), + loadBalancer.getNetworkId()); for (UserVmVO userVm : userVms) { // if the VM is destroyed, being expunged, in an error state, or in @@ -1933,6 +1932,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); sb.and("sourceIpAddress", sb.entity().getSourceIpAddressId(), SearchCriteria.Op.EQ); sb.and("networkId", sb.entity().getNetworkId(), SearchCriteria.Op.EQ); + sb.and("scheme", sb.entity().getScheme(), SearchCriteria.Op.EQ); if (instanceId != null) { SearchBuilder lbVMSearch = _lb2VmMapDao.createSearchBuilder(); diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index b969be25fde..e0ff1573143 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1179,7 +1179,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V _alertMgr.sendAlert(AlertManager.ALERT_TYPE_DOMAIN_ROUTER, backupRouter.getDataCenterId(), backupRouter.getPodIdToDeployIn(), title, title); try { - rebootRouter(backupRouter.getId(), false); + rebootRouter(backupRouter.getId(), true); } catch (ConcurrentOperationException e) { s_logger.warn("Fail to reboot " + backupRouter.getInstanceName(), e); } catch (ResourceUnavailableException e) { @@ -1438,9 +1438,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V assert guestNetwork.getTrafficType() == TrafficType.Guest; // 1) Get deployment plan and find out the list of routers - boolean isPodBased = (dest.getDataCenter().getNetworkType() == NetworkType.Basic || - _networkModel.areServicesSupportedInNetwork(guestNetwork.getId(), Service.SecurityGroup)) - && guestNetwork.getTrafficType() == TrafficType.Guest; + boolean isPodBased = (dest.getDataCenter().getNetworkType() == NetworkType.Basic); // dest has pod=null, for Basic Zone findOrDeployVRs for all Pods List destinations = new ArrayList(); @@ -2475,18 +2473,21 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V //Reapply dhcp and dns configuration. if (_networkModel.isProviderSupportServiceInNetwork(guestNetworkId, Service.Dhcp, provider)) { List revokedIpAliasVOs = _nicIpAliasDao.listByNetworkIdAndState(guestNetworkId, NicIpAlias.state.revoked); - s_logger.debug("Found" + revokedIpAliasVOs.size() + "ip Aliases to apply on the router as a part of dhco configuration"); + s_logger.debug("Found" + revokedIpAliasVOs.size() + "ip Aliases to revoke on the router as a part of dhcp configuration"); List revokedIpAliasTOs = new ArrayList(); for (NicIpAliasVO revokedAliasVO : revokedIpAliasVOs) { revokedIpAliasTOs.add(new IpAliasTO(revokedAliasVO.getIp4Address(), revokedAliasVO.getNetmask(), revokedAliasVO.getAliasCount().toString())); } List aliasVOs = _nicIpAliasDao.listByNetworkIdAndState(guestNetworkId, NicIpAlias.state.active); - s_logger.debug("Found" + aliasVOs.size() + "ip Aliases to apply on the router as a part of dhco configuration"); + s_logger.debug("Found" + aliasVOs.size() + "ip Aliases to apply on the router as a part of dhcp configuration"); List activeIpAliasTOs = new ArrayList(); for (NicIpAliasVO aliasVO : aliasVOs) { activeIpAliasTOs.add(new IpAliasTO(aliasVO.getIp4Address(), aliasVO.getNetmask(), aliasVO.getAliasCount().toString())); } - createDeleteIpAliasCommand(router, revokedIpAliasTOs, activeIpAliasTOs, guestNetworkId, cmds); + if (revokedIpAliasTOs.size() != 0 || activeIpAliasTOs.size() != 0){ + createDeleteIpAliasCommand(router, revokedIpAliasTOs, activeIpAliasTOs, guestNetworkId, cmds); + configDnsMasq(router, _networkDao.findById(guestNetworkId), cmds); + } } } @@ -2795,7 +2796,13 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V for (VlanVO vlan : vlanList) { vlanDbIdList.add(vlan.getId()); } - routerPublicIP = _networkMgr.assignPublicIpAddressFromVlans(router.getDataCenterId(), vm.getPodIdToDeployIn(), caller, Vlan.VlanType.DirectAttached, vlanDbIdList, nic.getNetworkId(), null, false); + if (dc.getNetworkType() == NetworkType.Basic) { + routerPublicIP = _networkMgr.assignPublicIpAddressFromVlans(router.getDataCenterId(), vm.getPodIdToDeployIn(), caller, Vlan.VlanType.DirectAttached, vlanDbIdList, nic.getNetworkId(), null, false); + } + else { + routerPublicIP = _networkMgr.assignPublicIpAddressFromVlans(router.getDataCenterId(), null, caller, Vlan.VlanType.DirectAttached, vlanDbIdList, nic.getNetworkId(), null, false); + } + routerAliasIp = routerPublicIP.getAddress().addr(); } } @@ -2846,13 +2853,13 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V Commands cmds = new Commands(OnError.Continue); List revokedIpAliasVOs = _nicIpAliasDao.listByNetworkIdAndState(network.getId(), NicIpAlias.state.revoked); - s_logger.debug("Found" + revokedIpAliasVOs.size() + "ip Aliases to apply on the router as a part of dhco configuration"); + s_logger.debug("Found" + revokedIpAliasVOs.size() + "ip Aliases to revoke on the router as a part of dhcp configuration"); List revokedIpAliasTOs = new ArrayList(); for (NicIpAliasVO revokedAliasVO : revokedIpAliasVOs) { revokedIpAliasTOs.add(new IpAliasTO(revokedAliasVO.getIp4Address(), revokedAliasVO.getNetmask(), revokedAliasVO.getAliasCount().toString())); } List aliasVOs = _nicIpAliasDao.listByNetworkIdAndState(network.getId(), NicIpAlias.state.active); - s_logger.debug("Found" + aliasVOs.size() + "ip Aliases to apply on the router as a part of dhco configuration"); + s_logger.debug("Found" + aliasVOs.size() + "ip Aliases to apply on the router as a part of dhcp configuration"); List activeIpAliasTOs = new ArrayList(); for (NicIpAliasVO aliasVO : aliasVOs) { activeIpAliasTOs.add(new IpAliasTO(aliasVO.getIp4Address(), aliasVO.getNetmask(), aliasVO.getAliasCount().toString())); @@ -3370,20 +3377,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V DataCenterVO dcVo = _dcDao.findById(router.getDataCenterId()); Nic defaultNic = findGatewayIp(vm.getId()); String gatewayIp = defaultNic.getGateway(); - boolean needGateway = true; if (gatewayIp != null && !gatewayIp.equals(nic.getGateway())) { - needGateway = false; - GuestOSVO guestOS = _guestOSDao.findById(vm.getGuestOSId()); - // Do set dhcp:router option for non-default nic on certain OS(including Windows), and leave other OS unset. - // Because some OS(e.g. CentOS) would set routing on wrong interface - for (String name : _guestOSNeedGatewayOnNonDefaultNetwork) { - if (guestOS.getDisplayName().startsWith(name)) { - needGateway = true; - break; - } - } - } - if (!needGateway) { gatewayIp = "0.0.0.0"; } dhcpCommand.setDefaultRouter(gatewayIp); @@ -3410,10 +3404,16 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V List ipAliasVOList = _nicIpAliasDao.getAliasIpForVm(router.getId()); List ipList = new ArrayList(); - NicVO router_guest_ip = _nicDao.findByNtwkIdAndInstanceId(network.getId(), router.getId()); - ipList.add(new DnsmasqTO(router_guest_ip.getIp4Address(),router_guest_ip.getGateway(),router_guest_ip.getNetmask())); + NicVO router_guest_nic = _nicDao.findByNtwkIdAndInstanceId(network.getId(), router.getId()); + String cidr = NetUtils.getCidrFromGatewayAndNetmask(router_guest_nic.getGateway(), router_guest_nic.getNetmask()); + String[] cidrPair = cidr.split("\\/"); + String cidrAddress = cidrPair[0]; + long cidrSize = Long.parseLong(cidrPair[1]); + String startIpOfSubnet = NetUtils.getIpRangeStartIpFromCidr(cidrAddress, cidrSize); + + ipList.add(new DnsmasqTO(router_guest_nic.getIp4Address(),router_guest_nic.getGateway(),router_guest_nic.getNetmask(), startIpOfSubnet)); for (NicIpAliasVO ipAliasVO : ipAliasVOList) { - DnsmasqTO dnsmasqTO = new DnsmasqTO(ipAliasVO.getStartIpOfSubnet(), ipAliasVO.getGateway(), ipAliasVO.getNetmask()); + DnsmasqTO dnsmasqTO = new DnsmasqTO(ipAliasVO.getIp4Address(), ipAliasVO.getGateway(), ipAliasVO.getNetmask(), ipAliasVO.getStartIpOfSubnet()); ipList.add(dnsmasqTO); } DataCenterVO dcvo = _dcDao.findById(router.getDataCenterId()); diff --git a/server/src/com/cloud/network/rules/RulesManager.java b/server/src/com/cloud/network/rules/RulesManager.java index cede987280d..201d79db9c6 100644 --- a/server/src/com/cloud/network/rules/RulesManager.java +++ b/server/src/com/cloud/network/rules/RulesManager.java @@ -32,47 +32,20 @@ import com.cloud.vm.VirtualMachine; */ public interface RulesManager extends RulesService { - boolean applyPortForwardingRules(long ipAddressId, boolean continueOnError, Account caller); - - boolean applyStaticNatRulesForIp(long sourceIpId, boolean continueOnError, Account caller, boolean forRevoke); - boolean applyPortForwardingRulesForNetwork(long networkId, boolean continueOnError, Account caller); boolean applyStaticNatRulesForNetwork(long networkId, boolean continueOnError, Account caller); - void checkIpAndUserVm(IpAddress ipAddress, UserVm userVm, Account caller); - void checkRuleAndUserVm(FirewallRule rule, UserVm userVm, Account caller); boolean revokeAllPFAndStaticNatRulesForIp(long ipId, long userId, Account caller) throws ResourceUnavailableException; boolean revokeAllPFStaticNatRulesForNetwork(long networkId, long userId, Account caller) throws ResourceUnavailableException; - List listFirewallRulesByIp(long ipAddressId); - - /** - * Returns a list of port forwarding rules that are ready for application - * to the network elements for this ip. - * - * @param ip - * @return List of PortForwardingRule - */ - List listPortForwardingRulesForApplication(long ipId); - - List gatherPortForwardingRulesForApplication(List addrs); - boolean revokePortForwardingRulesForVm(long vmId); - boolean revokeStaticNatRulesForVm(long vmId); - FirewallRule[] reservePorts(IpAddress ip, String protocol, FirewallRule.Purpose purpose, boolean openFirewall, Account caller, int... ports) throws NetworkRuleConflictException; - boolean releasePorts(long ipId, String protocol, FirewallRule.Purpose purpose, int... ports); - - List listByNetworkId(long networkId); - - boolean applyStaticNatForIp(long sourceIpId, boolean continueOnError, Account caller, boolean forRevoke); - boolean applyStaticNatsForNetwork(long networkId, boolean continueOnError, Account caller); void getSystemIpAndEnableStaticNatForVm(VirtualMachine vm, boolean getNewIp) throws InsufficientAddressCapacityException; diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index dd5f99ba574..41bf2b3af65 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -24,7 +24,6 @@ import java.util.Set; import javax.ejb.Local; import javax.inject.Inject; -import javax.naming.ConfigurationException; import org.apache.cloudstack.api.command.user.firewall.ListPortForwardingRulesCmd; import org.apache.log4j.Logger; @@ -54,7 +53,6 @@ import com.cloud.network.dao.LoadBalancerVMMapDao; import com.cloud.network.dao.LoadBalancerVMMapVO; import com.cloud.network.rules.FirewallRule.FirewallRuleType; import com.cloud.network.rules.FirewallRule.Purpose; -import com.cloud.network.rules.FirewallRule.TrafficType; import com.cloud.network.rules.dao.PortForwardingRulesDao; import com.cloud.network.vpc.VpcManager; import com.cloud.offering.NetworkOffering; @@ -69,7 +67,6 @@ import com.cloud.user.UserContext; import com.cloud.uservm.UserVm; import com.cloud.utils.Pair; import com.cloud.utils.Ternary; -import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.DB; import com.cloud.utils.db.Filter; @@ -139,8 +136,8 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules @Inject LoadBalancerVMMapDao _loadBalancerVMMapDao; - @Override - public void checkIpAndUserVm(IpAddress ipAddress, UserVm userVm, Account caller) { + + protected void checkIpAndUserVm(IpAddress ipAddress, UserVm userVm, Account caller) { if (ipAddress == null || ipAddress.getAllocatedTime() == null || ipAddress.getAllocatedToAccountId() == null) { throw new InvalidParameterValueException("Unable to create ip forwarding rule on address " + ipAddress + ", invalid IP address specified."); } @@ -706,6 +703,7 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules return true; } + private boolean revokeStaticNatRuleInternal(long ruleId, Account caller, long userId, boolean apply) { FirewallRuleVO rule = _firewallDao.findById(ruleId); @@ -756,45 +754,6 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules return success; } - @Override - public boolean revokeStaticNatRulesForVm(long vmId) { - boolean success = true; - - UserVmVO vm = _vmDao.findByIdIncludingRemoved(vmId); - if (vm == null) { - return false; - } - - List rules = _firewallDao.listStaticNatByVmId(vm.getId()); - Set ipsToReprogram = new HashSet(); - - if (rules == null || rules.isEmpty()) { - s_logger.debug("No static nat rules are found for vm id=" + vmId); - return true; - } - - for (FirewallRuleVO rule : rules) { - // mark static nat as Revoked, but don't revoke it yet (apply = false) - revokeStaticNatRuleInternal(rule.getId(), _accountMgr.getSystemAccount(), Account.ACCOUNT_ID_SYSTEM, false); - ipsToReprogram.add(rule.getSourceIpAddressId()); - } - - // apply rules for all ip addresses - for (Long ipId : ipsToReprogram) { - s_logger.debug("Applying static nat rules for ip address id=" + ipId + " as a part of vm expunge"); - if (!applyStaticNatRulesForIp(ipId, true, _accountMgr.getSystemAccount(), true)) { - success = false; - s_logger.warn("Failed to apply static nat rules for ip id=" + ipId); - } - } - - return success; - } - - @Override - public List listPortForwardingRulesForApplication(long ipId) { - return _portForwardingDao.listForApplication(ipId); - } @Override public Pair, Integer> listPortForwardingRules(ListPortForwardingRulesCmd cmd) { @@ -872,8 +831,8 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules return _firewallCidrsDao.getSourceCidrs(ruleId); } - @Override - public boolean applyPortForwardingRules(long ipId, boolean continueOnError, Account caller) { + + protected boolean applyPortForwardingRules(long ipId, boolean continueOnError, Account caller) { List rules = _portForwardingDao.listForApplication(ipId); if (rules.size() == 0) { @@ -897,8 +856,8 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules return true; } - @Override - public boolean applyStaticNatRulesForIp(long sourceIpId, boolean continueOnError, Account caller, boolean forRevoke) { + + protected boolean applyStaticNatRulesForIp(long sourceIpId, boolean continueOnError, Account caller, boolean forRevoke) { List rules = _firewallDao.listByIpAndPurpose(sourceIpId, Purpose.StaticNat); List staticNatRules = new ArrayList(); @@ -1172,15 +1131,6 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules return success && rules.size() == 0; } - @Override - public List listFirewallRulesByIp(long ipId) { - return null; - } - - @Override - public boolean releasePorts(long ipId, String protocol, FirewallRule.Purpose purpose, int... ports) { - return _firewallDao.releasePorts(ipId, protocol, purpose, ports); - } @Override @DB @@ -1221,29 +1171,8 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules } } - @Override - public List gatherPortForwardingRulesForApplication(List addrs) { - List allRules = new ArrayList(); - for (IpAddress addr : addrs) { - if (!addr.readyToUse()) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Skipping " + addr + " because it is not ready for propation yet."); - } - continue; - } - allRules.addAll(_portForwardingDao.listForApplication(addr.getId())); - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Found " + allRules.size() + " rules to apply for the addresses."); - } - - return allRules; - } - - @Override - public List listByNetworkId(long networkId) { + private List listByNetworkId(long networkId) { return _portForwardingDao.listByNetwork(networkId); } @@ -1367,8 +1296,8 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules return new StaticNatRuleImpl(ruleVO, dstIp); } - @Override - public boolean applyStaticNatForIp(long sourceIpId, boolean continueOnError, Account caller, boolean forRevoke) { + + protected boolean applyStaticNatForIp(long sourceIpId, boolean continueOnError, Account caller, boolean forRevoke) { IpAddress sourceIp = _ipAddressDao.findById(sourceIpId); List staticNats = createStaticNatForIp(sourceIp, caller, forRevoke); diff --git a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java index e26dad98f60..171b8b9a6bf 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLManagerImpl.java @@ -16,8 +16,10 @@ // under the License. package com.cloud.network.vpc; +import com.cloud.configuration.ConfigurationManager; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.Network; import com.cloud.network.Network.Service; @@ -29,6 +31,7 @@ import com.cloud.network.element.VpcProvider; import com.cloud.network.vpc.NetworkACLItem.State; import com.cloud.network.vpc.dao.NetworkACLDao; import com.cloud.network.vpc.dao.VpcGatewayDao; +import com.cloud.offering.NetworkOffering; import com.cloud.tags.dao.ResourceTagDao; import com.cloud.user.Account; import com.cloud.user.AccountManager; @@ -73,6 +76,8 @@ public class NetworkACLManagerImpl extends ManagerBase implements NetworkACLMana VpcGatewayDao _vpcGatewayDao; @Inject NetworkModel _ntwkModel; + @Inject + ConfigurationManager _configMgr; @Override public NetworkACL createNetworkACL(String name, String description, long vpcId) { @@ -133,9 +138,22 @@ public class NetworkACLManagerImpl extends ManagerBase implements NetworkACLMana @Override public boolean replaceNetworkACL(NetworkACL acl, NetworkVO network) throws ResourceUnavailableException { + + NetworkOffering guestNtwkOff = _configMgr.getNetworkOffering(network.getNetworkOfferingId()); + + if (guestNtwkOff == null) { + throw new InvalidParameterValueException("Can't find network offering associated with network: "+network.getUuid()); + } + + //verify that ACLProvider is supported by network offering + if(!_ntwkModel.areServicesSupportedByNetworkOffering(guestNtwkOff.getId(), Service.NetworkACL)){ + throw new InvalidParameterValueException("Cannot apply NetworkACL. Network Offering does not support NetworkACL service"); + } + network.setNetworkACLId(acl.getId()); //Update Network ACL if(_networkDao.update(network.getId(), network)){ + s_logger.debug("Updated network: "+network.getId()+ "with Network ACL Id: "+acl.getId()+", Applying ACL items"); //Apply ACL to network return applyACLToNetwork(network.getId()); } @@ -376,16 +394,22 @@ public class NetworkACLManagerImpl extends ManagerBase implements NetworkACLMana public boolean applyACLItemsToNetwork(long networkId, List rules) throws ResourceUnavailableException { Network network = _networkDao.findById(networkId); boolean handled = false; + boolean foundProvider = false; for (NetworkACLServiceProvider element: _networkAclElements) { Network.Provider provider = element.getProvider(); boolean isAclProvider = _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.NetworkACL, provider); if (!isAclProvider) { continue; } + foundProvider = true; + s_logger.debug("Applying NetworkACL for network: "+network.getId()+" with Network ACL service provider"); handled = element.applyNetworkACLs(network, rules); if (handled) break; } + if(!foundProvider){ + s_logger.debug("Unable to find NetworkACL service provider for network: "+network.getId()); + } return handled; } diff --git a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java index 2b02a888de9..d6e86e2c811 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java @@ -121,7 +121,7 @@ public class NetworkACLServiceImpl extends ManagerBase implements NetworkACLServ } if(vpcId != null){ - sc.setParameters("vpcId", name); + sc.setParameters("vpcId", vpcId); } if(networkId != null){ diff --git a/server/src/com/cloud/network/vpc/VpcManager.java b/server/src/com/cloud/network/vpc/VpcManager.java index f22e7e4bf83..e01413f78f3 100644 --- a/server/src/com/cloud/network/vpc/VpcManager.java +++ b/server/src/com/cloud/network/vpc/VpcManager.java @@ -164,7 +164,7 @@ public interface VpcManager extends VpcService{ * @param gateway * @param networkOwner TODO */ - void validateNtwkOffForNtwkInVpc(Long networkId, long newNtwkOffId, String newCidr, String newNetworkDomain, Vpc vpc, String gateway, Account networkOwner); + void validateNtwkOffForNtwkInVpc(Long networkId, long newNtwkOffId, String newCidr, String newNetworkDomain, Vpc vpc, String gateway, Account networkOwner, Long aclId); List getVpcPrivateGateways(long vpcId); } diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index 380a95e1882..b41003a6105 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -16,27 +16,6 @@ // under the License. package com.cloud.network.vpc; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import javax.ejb.Local; -import javax.inject.Inject; -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.api.command.user.vpc.ListPrivateGatewaysCmd; -import org.apache.cloudstack.api.command.user.vpc.ListStaticRoutesCmd; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.Resource.ResourceType; @@ -80,6 +59,7 @@ import com.cloud.network.dao.Site2SiteVpnGatewayDao; import com.cloud.network.element.StaticNatServiceProvider; import com.cloud.network.element.VpcProvider; import com.cloud.network.vpc.VpcOffering.State; +import com.cloud.network.vpc.dao.NetworkACLDao; import com.cloud.network.vpc.dao.PrivateIpDao; import com.cloud.network.vpc.dao.StaticRouteDao; import com.cloud.network.vpc.dao.VpcDao; @@ -87,7 +67,6 @@ import com.cloud.network.vpc.dao.VpcGatewayDao; import com.cloud.network.vpc.dao.VpcOfferingDao; import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao; import com.cloud.network.vpc.dao.VpcServiceMapDao; -import com.cloud.network.vpc.dao.NetworkACLDao; import com.cloud.network.vpn.Site2SiteVpnManager; import com.cloud.offering.NetworkOffering; import com.cloud.offerings.NetworkOfferingServiceMapVO; @@ -121,6 +100,25 @@ import com.cloud.utils.net.NetUtils; import com.cloud.vm.ReservationContext; import com.cloud.vm.ReservationContextImpl; import com.cloud.vm.dao.DomainRouterDao; +import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.api.command.user.vpc.ListPrivateGatewaysCmd; +import org.apache.cloudstack.api.command.user.vpc.ListStaticRoutesCmd; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; @Component @@ -1039,7 +1037,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis @DB @Override public void validateNtwkOffForNtwkInVpc(Long networkId, long newNtwkOffId, String newCidr, - String newNetworkDomain, Vpc vpc, String gateway, Account networkOwner) { + String newNetworkDomain, Vpc vpc, String gateway, Account networkOwner, Long aclId) { NetworkOffering guestNtwkOff = _configMgr.getNetworkOffering(newNtwkOffId); @@ -1084,6 +1082,12 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis } } } + + //5) When aclId is provided, verify that ACLProvider is supported by network offering + if(aclId != null && (!_ntwkModel.areServicesSupportedByNetworkOffering(guestNtwkOff.getId(), Service.NetworkACL))){ + throw new InvalidParameterValueException("Cannot apply NetworkACL. Network Offering does not support NetworkACL service"); + } + } @Override @@ -2034,7 +2038,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis } //1) Validate if network can be created for VPC - validateNtwkOffForNtwkInVpc(null, ntwkOffId, cidr, networkDomain, vpc, gateway, owner); + validateNtwkOffForNtwkInVpc(null, ntwkOffId, cidr, networkDomain, vpc, gateway, owner, aclId); //2) Create network Network guestNetwork = _ntwkMgr.createGuestNetwork(ntwkOffId, name, displayText, gateway, cidr, vlanId, @@ -2109,6 +2113,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis hTypes.add(HypervisorType.XenServer); hTypes.add(HypervisorType.VMware); hTypes.add(HypervisorType.KVM); + hTypes.add(HypervisorType.Simulator); return hTypes; } diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index 1e28d92896f..c6e8d7d7729 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -30,6 +30,7 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.dc.*; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.command.admin.cluster.AddClusterCmd; import org.apache.cloudstack.api.command.admin.cluster.DeleteClusterCmd; @@ -84,6 +85,7 @@ import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.ClusterVSMMapDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.DataCenterIpAddressDao; +import com.cloud.dc.dao.DedicatedResourceDao; import com.cloud.dc.dao.HostPodDao; import com.cloud.deploy.PlannerHostReservationVO; import com.cloud.deploy.dao.PlannerHostReservationDao; @@ -161,6 +163,7 @@ import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.dao.VMInstanceDao; +import com.cloud.dc.DataCenter.NetworkType; @Component @Local({ ResourceManager.class, ResourceService.class }) @@ -218,6 +221,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, protected StorageService _storageSvr; @Inject PlannerHostReservationDao _plannerHostReserveDao; + @Inject + protected DedicatedResourceDao _dedicatedDao; protected List _discoverers; public List getDiscoverers() { @@ -444,7 +449,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, + cmd.getHypervisor() + " to a supported "); } - if (zone.isSecurityGroupEnabled()) { + if (zone.isSecurityGroupEnabled() && zone.getNetworkType().equals(NetworkType.Advanced)) { if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.XenServer && hypervisorType != HypervisorType.Simulator) { throw new InvalidParameterValueException("Don't support hypervisor type " + hypervisorType + " in advanced security enabled zone"); @@ -1025,6 +1030,11 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, hostCapacitySC.addAnd("capacityType", SearchCriteria.Op.IN, capacityTypes); _capacityDao.remove(hostCapacitySC); + // remove from dedicated resources + DedicatedResourceVO dr = _dedicatedDao.findByHostId(hostId); + if (dr != null) { + _dedicatedDao.remove(dr.getId()); + } txn.commit(); return true; } @@ -1099,11 +1109,16 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, && Boolean.parseBoolean(_configDao .getValue(Config.VmwareUseNexusVSwitch .toString()))) { - _clusterVSMMapDao.removeByClusterId(cmd.getId()); - } - } + _clusterVSMMapDao.removeByClusterId(cmd.getId()); + } + // remove from dedicated resources + DedicatedResourceVO dr = _dedicatedDao.findByClusterId(cluster.getId()); + if (dr != null) { + _dedicatedDao.remove(dr.getId()); + } + } - txn.commit(); + txn.commit(); return true; } catch (CloudRuntimeException e) { throw e; diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 35f977b5921..d334d7efb53 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -47,6 +47,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO; import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.FileUtils; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -437,23 +438,13 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio } } - private String getBase64Keystore(String keystorePath) throws IOException { - byte[] storeBytes = new byte[4094]; - int len = 0; - try { - len = new FileInputStream(keystorePath).read(storeBytes); - } catch (EOFException e) { - } catch (Exception e) { - throw new IOException("Cannot read the generated keystore file"); - } - if (len > 3000) { // Base64 codec would enlarge data by 1/3, and we have 4094 bytes in database entry at most - throw new IOException("KeyStore is too big for database! Length " + len); + static String getBase64Keystore(String keystorePath) throws IOException { + byte[] storeBytes = FileUtils.readFileToByteArray(new File(keystorePath)); + if (storeBytes.length > 3000) { // Base64 codec would enlarge data by 1/3, and we have 4094 bytes in database entry at most + throw new IOException("KeyStore is too big for database! Length " + storeBytes.length); } - byte[] encodeBytes = new byte[len]; - System.arraycopy(storeBytes, 0, encodeBytes, 0, len); - - return new String(Base64.encodeBase64(encodeBytes)); + return new String(Base64.encodeBase64(storeBytes)); } private void generateDefaultKeystore(String keystorePath) throws IOException { diff --git a/server/src/com/cloud/server/ManagementServer.java b/server/src/com/cloud/server/ManagementServer.java index 969bc6557e1..f60ce488e10 100755 --- a/server/src/com/cloud/server/ManagementServer.java +++ b/server/src/com/cloud/server/ManagementServer.java @@ -16,19 +16,11 @@ // under the License. package com.cloud.server; -import java.util.Date; import java.util.List; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.ManagementServerException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.exception.VirtualMachineMigrationException; -import org.apache.cloudstack.api.command.admin.systemvm.ScaleSystemVMCmd; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import com.cloud.event.EventVO; import com.cloud.host.HostVO; -import com.cloud.info.ConsoleProxyInfo; import com.cloud.storage.GuestOSVO; import com.cloud.utils.Pair; import com.cloud.utils.component.PluggableService; @@ -59,30 +51,6 @@ public interface ManagementServer extends ManagementService, PluggableService { */ HostVO getHostBy(long hostId); - /** - * Retrieves all Events between the start and end date specified - * - * @param userId - * unique id of the user, pass in -1 to retrieve events for all users - * @param accountId - * unique id of the account (which could be shared by many users), pass in -1 to retrieve events for all accounts - * @param domainId - * the id of the domain in which to search for users (useful when -1 is passed in for userId) - * @param type - * the type of the event. - * @param level - * INFO, WARN, or ERROR - * @param startDate - * inclusive. - * @param endDate - * inclusive. If date specified is greater than the current time, the system will use the current time. - * @return List of events - */ - List getEvents(long userId, long accountId, Long domainId, String type, String level, Date startDate, Date endDate); - - //FIXME - move all console proxy related commands to corresponding managers - ConsoleProxyInfo getConsoleProxyForVm(long dataCenterId, long userVmId); - String getConsoleAccessUrlRoot(long vmId); GuestOSVO getGuestOs(Long guestOsId); @@ -103,7 +71,5 @@ public interface ManagementServer extends ManagementService, PluggableService { String getEncryptionKey(); String getEncryptionIV(); void resetEncryptionKeyIV(); - - public void enableAdminUser(String password); } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index d5d95f8eadb..96c72e4a4e2 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -30,6 +30,7 @@ import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -373,15 +374,6 @@ import org.apache.cloudstack.api.command.user.vmsnapshot.DeleteVMSnapshotCmd; import org.apache.cloudstack.api.command.user.vmsnapshot.ListVMSnapshotCmd; import org.apache.cloudstack.api.command.user.vmsnapshot.RevertToVMSnapshotCmd; import org.apache.cloudstack.api.command.user.volume.*; -import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; -import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd; -import org.apache.cloudstack.api.command.user.volume.DeleteVolumeCmd; -import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; -import org.apache.cloudstack.api.command.user.volume.ExtractVolumeCmd; -import org.apache.cloudstack.api.command.user.volume.ListVolumesCmd; -import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd; -import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; -import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd; import org.apache.cloudstack.api.command.user.vpc.CreateStaticRouteCmd; import org.apache.cloudstack.api.command.user.vpc.CreateVPCCmd; import org.apache.cloudstack.api.command.user.vpc.DeleteStaticRouteCmd; @@ -922,38 +914,6 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } } - @Override - public List getEvents(long userId, long accountId, Long domainId, String type, String level, Date startDate, Date endDate) { - SearchCriteria sc = _eventDao.createSearchCriteria(); - if (userId > 0) { - sc.addAnd("userId", SearchCriteria.Op.EQ, userId); - } - if (accountId > 0) { - sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId); - } - if (domainId != null) { - sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); - } - if (type != null) { - sc.addAnd("type", SearchCriteria.Op.EQ, type); - } - if (level != null) { - sc.addAnd("level", SearchCriteria.Op.EQ, level); - } - if (startDate != null && endDate != null) { - startDate = massageDate(startDate, 0, 0, 0); - endDate = massageDate(endDate, 23, 59, 59); - sc.addAnd("createDate", SearchCriteria.Op.BETWEEN, startDate, endDate); - } else if (startDate != null) { - startDate = massageDate(startDate, 0, 0, 0); - sc.addAnd("createDate", SearchCriteria.Op.GTEQ, startDate); - } else if (endDate != null) { - endDate = massageDate(endDate, 23, 59, 59); - sc.addAnd("createDate", SearchCriteria.Op.LTEQ, endDate); - } - - return _eventDao.search(sc, null); - } @Override public boolean archiveEvents(ArchiveEventsCmd cmd) { @@ -1216,10 +1176,11 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe allHosts.remove(srcHost); // Check if the host has storage pools for all the volumes of the vm to be migrated. - for (Host host : allHosts) { + for (Iterator iterator = allHosts.iterator(); iterator.hasNext();) { + Host host = iterator.next(); Map> volumePools = findSuitablePoolsForVolumes(vmProfile, host); if (volumePools.isEmpty()) { - allHosts.remove(host); + iterator.remove(); } else { if (!host.getClusterId().equals(srcHost.getClusterId()) || usesLocal) { requiresStorageMotion.put(host, true); @@ -2229,8 +2190,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return new Pair, Integer>(result.first(), result.second()); } - @Override - public ConsoleProxyInfo getConsoleProxyForVm(long dataCenterId, long userVmId) { + + protected ConsoleProxyInfo getConsoleProxyForVm(long dataCenterId, long userVmId) { return _consoleProxyMgr.assignProxy(dataCenterId, userVmId); } @@ -4134,8 +4095,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } - @Override - public void enableAdminUser(String password) { + + private void enableAdminUser(String password) { String encodedPassword = null; UserVO adminUser = _userDao.getUser(2); diff --git a/server/src/com/cloud/server/StatsCollector.java b/server/src/com/cloud/server/StatsCollector.java index 39b743976b3..8d84c6ca237 100755 --- a/server/src/com/cloud/server/StatsCollector.java +++ b/server/src/com/cloud/server/StatsCollector.java @@ -567,7 +567,7 @@ public class StatsCollector extends ManagerBase implements ComponentMethodInterc GetStorageStatsCommand command = new GetStorageStatsCommand(pool.getUuid(), pool.getPoolType(), pool.getPath()); long poolId = pool.getId(); try { - Answer answer = _storageManager.sendToPool(pool.getId(), command); + Answer answer = _storageManager.sendToPool(pool, command); if (answer != null && answer.getResult()) { storagePoolStats.put(pool.getId(), (StorageStats)answer); diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 1f121ed7983..cdfc19aa9b2 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -777,6 +777,25 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C "zone id can't be null, if scope is zone"); } + HypervisorType hypervisorType = HypervisorType.KVM; + if (scopeType == ScopeType.ZONE) { + String hypervisor = cmd.getHypervisor(); + if (hypervisor != null) { + try { + hypervisorType = HypervisorType.getType(hypervisor); + } catch (Exception e) { + throw new InvalidParameterValueException("invalid hypervisor type" + hypervisor); + } + } else { + throw new InvalidParameterValueException( + "Missing parameter hypervisor. Hypervisor type is required to create zone wide primary storage."); + } + if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.VMware) { + throw new InvalidParameterValueException( + "zone wide storage pool is not suported for hypervisor type " + hypervisor); + } + } + Map ds = cmd.getDetails(); Map details = new HashMap(); if (ds != null) { @@ -828,7 +847,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C lifeCycle.attachCluster(store, clusterScope); } else if (scopeType == ScopeType.ZONE) { ZoneScope zoneScope = new ZoneScope(zoneId); - lifeCycle.attachZone(store, zoneScope); + lifeCycle.attachZone(store, zoneScope, hypervisorType); } } catch (Exception e) { s_logger.debug("Failed to add data store", e); diff --git a/server/src/com/cloud/storage/VolumeManager.java b/server/src/com/cloud/storage/VolumeManager.java index d198e5dd7df..47fbda8df9f 100644 --- a/server/src/com/cloud/storage/VolumeManager.java +++ b/server/src/com/cloud/storage/VolumeManager.java @@ -105,4 +105,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/server/src/com/cloud/storage/VolumeManagerImpl.java b/server/src/com/cloud/storage/VolumeManagerImpl.java index c260fc5f0ec..63f32544ed1 100644 --- a/server/src/com/cloud/storage/VolumeManagerImpl.java +++ b/server/src/com/cloud/storage/VolumeManagerImpl.java @@ -366,6 +366,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { throws ResourceAllocationException { Account caller = UserContext.current().getCaller(); long ownerId = cmd.getEntityOwnerId(); + Account owner = _accountDao.findById(ownerId); Long zoneId = cmd.getZoneId(); String volumeName = cmd.getVolumeName(); String url = cmd.getUrl(); @@ -375,7 +376,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { validateVolume(caller, ownerId, zoneId, volumeName, url, format); - VolumeVO volume = persistVolume(caller, ownerId, zoneId, volumeName, + VolumeVO volume = persistVolume(owner, zoneId, volumeName, url, cmd.getFormat()); VolumeInfo vol = this.volFactory.getVolume(volume.getId()); @@ -714,7 +715,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { return UUID.randomUUID().toString(); } - private VolumeVO persistVolume(Account caller, long ownerId, Long zoneId, + private VolumeVO persistVolume(Account owner, Long zoneId, String volumeName, String url, String format) { Transaction txn = Transaction.currentTxn(); @@ -722,20 +723,17 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { VolumeVO volume = new VolumeVO(volumeName, zoneId, -1, -1, -1, new Long(-1), null, null, 0, Volume.Type.DATADISK); - Account owner = (caller.getId() == ownerId) ? caller : _accountMgr - .getActiveAccountById(ownerId); volume.setPoolId(null); volume.setDataCenterId(zoneId); volume.setPodId(null); - volume.setAccountId(ownerId); + volume.setAccountId(owner.getAccountId()); + volume.setDomainId(owner.getDomainId()); long diskOfferingId = _diskOfferingDao.findByUniqueName( "Cloud.com-Custom").getId(); volume.setDiskOfferingId(diskOfferingId); // volume.setSize(size); volume.setInstanceId(null); volume.setUpdated(new Date()); - volume.setDomainId((owner == null) ? Domain.ROOT_DOMAIN : owner - .getDomainId()); volume = _volsDao.persist(volume); try { @@ -1748,6 +1746,8 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } } + // reload the volume from db + volumeOnPrimaryStorage = volFactory.getVolume(volumeOnPrimaryStorage.getId()); boolean moveVolumeNeeded = needMoveVolume(rootVolumeOfVm, volumeOnPrimaryStorage); if (moveVolumeNeeded) { @@ -2638,4 +2638,17 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } } + + @Override + public String getVmNameFromVolumeId(long volumeId) { + Long instanceId; + VolumeVO volume = _volsDao.findById(volumeId); + return getVmNameOnVolume(volume); + } + + @Override + public String getStoragePoolOfVolume(long volumeId) { + VolumeVO vol = _volsDao.findById(volumeId); + return dataStoreMgr.getPrimaryDataStore(vol.getPoolId()).getUuid(); + } } diff --git a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java index 220cbffd5a3..663ab4a7fc0 100755 --- a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java +++ b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java @@ -552,7 +552,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor //Create usage event long size = -1; if(volumeHost!=null){ - size = volumeHost.getPhysicalSize(); + size = volumeHost.getSize(); volume.setSize(size); this._volumeDao.update(volume.getId(), volume); } diff --git a/server/src/com/cloud/storage/listener/StoragePoolMonitor.java b/server/src/com/cloud/storage/listener/StoragePoolMonitor.java index f957ca31ada..4848d446d21 100755 --- a/server/src/com/cloud/storage/listener/StoragePoolMonitor.java +++ b/server/src/com/cloud/storage/listener/StoragePoolMonitor.java @@ -77,7 +77,10 @@ public class StoragePoolMonitor implements Listener { if (scCmd.getHypervisorType() == HypervisorType.XenServer || scCmd.getHypervisorType() == HypervisorType.KVM || scCmd.getHypervisorType() == HypervisorType.VMware || scCmd.getHypervisorType() == HypervisorType.Simulator || scCmd.getHypervisorType() == HypervisorType.Ovm) { List pools = _poolDao.listBy(host.getDataCenterId(), host.getPodId(), host.getClusterId(), ScopeType.CLUSTER); - pools.addAll(_poolDao.findZoneWideStoragePoolsByTags(host.getDataCenterId(), null)); + List zoneStoragePoolsByTags = _poolDao.findZoneWideStoragePoolsByTags(host.getDataCenterId(), null); + List zoneStoragePoolsByHypervisor = _poolDao.findZoneWideStoragePoolsByHypervisor(host.getDataCenterId(), scCmd.getHypervisorType()); + zoneStoragePoolsByTags.retainAll(zoneStoragePoolsByHypervisor); + pools.addAll(zoneStoragePoolsByTags); for (StoragePoolVO pool : pools) { if (pool.getStatus() != StoragePoolStatus.Up) { continue; diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index 26aae48ba38..92d80ee6cc8 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -1033,12 +1033,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, // Snapshot Name: VMInstancename + volumeName + timeString String timeString = DateUtil.getDateDisplayString(DateUtil.GMT_TIMEZONE, new Date(), DateUtil.YYYYMMDD_FORMAT); - VMInstanceVO vmInstance = _vmDao.findById(volume.getInstanceId()); - String vmDisplayName = "detached"; - if (vmInstance != null) { - vmDisplayName = vmInstance.getHostName(); - } - String snapshotName = vmDisplayName + "_" + volume.getName() + "_" + timeString; + String snapshotName = volume.getUuid() + "_" + timeString; // Create the Snapshot object and save it so we can return it to the // user diff --git a/server/src/com/cloud/user/AccountManager.java b/server/src/com/cloud/user/AccountManager.java index 6ba1f6a7f96..2e909c8e042 100755 --- a/server/src/com/cloud/user/AccountManager.java +++ b/server/src/com/cloud/user/AccountManager.java @@ -47,21 +47,15 @@ public interface AccountManager extends AccountService { boolean deleteAccount(AccountVO account, long callerUserId, Account caller); - boolean cleanupAccount(AccountVO account, long callerUserId, Account caller); - Long checkAccessAndSpecifyAuthority(Account caller, Long zoneId); - Account createAccount(String accountName, short accountType, Long domainId, String networkDomain, Map details, String uuid); - - UserVO createUser(long accountId, String userName, String password, String firstName, String lastName, String email, String timezone, String userUUID); - + Account createAccount(String accountName, short accountType, Long domainId, String networkDomain, Map details, String uuid); + /** * Logs out a user * @param userId */ - void logoutUser(Long userId); - - UserAccount getUserAccount(String username, Long domainId); + void logoutUser(long userId); /** * Authenticates a user when s/he logs in. @@ -87,9 +81,7 @@ public interface AccountManager extends AccountService { * @return the user/account pair if one exact match was found, null otherwise */ Pair findUserByApiKey(String apiKey); - - boolean lockAccount(long accountId); - + boolean enableAccount(long accountId); void buildACLSearchBuilder(SearchBuilder sb, Long domainId, diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index e72005e8214..0d89639e31e 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -46,23 +46,25 @@ import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd; import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd; import org.apache.cloudstack.api.command.admin.user.RegisterCmd; import org.apache.cloudstack.api.command.admin.user.UpdateUserCmd; +import org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleDao; import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; import com.cloud.api.ApiDBUtils; -import com.cloud.api.query.dao.UserAccountJoinDao; import com.cloud.api.query.vo.ControlledViewEntity; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; +import com.cloud.configuration.Resource.ResourceOwnerType; import com.cloud.configuration.ResourceCountVO; import com.cloud.configuration.ResourceLimit; -import com.cloud.configuration.Resource.ResourceOwnerType; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.configuration.dao.ResourceCountDao; import com.cloud.configuration.dao.ResourceLimitDao; import com.cloud.dc.DataCenterVO; +import com.cloud.dc.DedicatedResourceVO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.DataCenterVnetDao; +import com.cloud.dc.dao.DedicatedResourceDao; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; @@ -102,8 +104,8 @@ import com.cloud.projects.ProjectManager; import com.cloud.projects.ProjectVO; import com.cloud.projects.dao.ProjectAccountDao; import com.cloud.projects.dao.ProjectDao; +import com.cloud.region.ha.GlobalLoadBalancingRulesService; import com.cloud.server.auth.UserAuthenticator; -import com.cloud.storage.StorageManager; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Volume; import com.cloud.storage.VolumeManager; @@ -162,8 +164,6 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M @Inject private UserAccountDao _userAccountDao; @Inject - private UserAccountJoinDao _userAccountJoinDao; - @Inject private VolumeDao _volumeDao; @Inject private UserVmDao _userVmDao; @@ -188,8 +188,6 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M @Inject private UserVmManager _vmMgr; @Inject - private StorageManager _storageMgr; - @Inject private TemplateManager _tmpltMgr; @Inject private ConfigurationManager _configMgr; @@ -229,6 +227,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M @Inject private AffinityGroupDao _affinityGroupDao; @Inject + private AccountGuestVlanMapDao _accountGuestVlanMapDao; @Inject private DataCenterVnetDao _dataCenterVnetDao; @@ -236,6 +235,12 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M private ResourceLimitService _resourceLimitMgr; @Inject private ResourceLimitDao _resourceLimitDao; + @Inject + private DedicatedResourceDao _dedicatedDao; + @Inject + private GlobalLoadBalancerRuleDao _gslbRuleDao; + @Inject + public com.cloud.region.ha.GlobalLoadBalancingRulesService _gslbService; private List _userAuthenticators; List _userPasswordEncoders; @@ -500,8 +505,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M return success; } - @Override - public boolean lockAccount(long accountId) { + + protected boolean lockAccount(long accountId) { boolean success = false; Account account = _accountDao.findById(accountId); if (account != null) { @@ -539,8 +544,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M return cleanupAccount(account, callerUserId, caller); } - @Override - public boolean cleanupAccount(AccountVO account, long callerUserId, Account caller) { + + protected boolean cleanupAccount(AccountVO account, long callerUserId, Account caller) { long accountId = account.getId(); boolean accountCleanupNeeded = false; @@ -554,6 +559,12 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M } } + // delete global load balancer rules for the account. + List gslbRules = _gslbRuleDao.listByAccount(accountId); + if (gslbRules != null && !gslbRules.isEmpty()) { + _gslbService.revokeAllGslbRulesForAccount(caller, accountId); + } + //delete the account from project accounts _projectAccountDao.removeAccountFromProjects(accountId); @@ -738,7 +749,16 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M s_logger.debug("Releasing portable ip " + ip + " as a part of account id=" + accountId + " cleanup"); _networkMgr.releasePortableIpAddress(ip.getId()); } - + //release dedication if any + List dedicatedResources = _dedicatedDao.listByAccountId(accountId); + if (dedicatedResources != null && !dedicatedResources.isEmpty()) { + s_logger.debug("Releasing dedicated resources for account " + accountId); + for (DedicatedResourceVO dr : dedicatedResources){ + if (!_dedicatedDao.remove(dr.getId())) { + s_logger.warn("Fail to release dedicated resources for account " + accountId); + } + } + } return true; } catch (Exception ex) { s_logger.warn("Failed to cleanup account " + account + " due to ", ex); @@ -1488,6 +1508,16 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M try { List accountsForCleanupInDomain = _accountDao.findCleanupsForRemovedAccounts(domainId); if (accountsForCleanupInDomain.isEmpty()) { + //release dedication if any, before deleting the domain + List dedicatedResources = _dedicatedDao.listByDomainId(domainId); + if (dedicatedResources != null && !dedicatedResources.isEmpty()) { + s_logger.debug("Releasing dedicated resources for domain" + domainId); + for (DedicatedResourceVO dr : dedicatedResources){ + if (!_dedicatedDao.remove(dr.getId())) { + s_logger.warn("Fail to release dedicated resources for domain " + domainId); + } + } + } s_logger.debug("Removing inactive domain id=" + domainId); _domainMgr.removeDomain(domainId); } else { @@ -1593,21 +1623,13 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M } @Override - public Account getActiveAccountById(Long accountId) { - if (accountId == null) { - throw new InvalidParameterValueException("AccountId is required by account search"); - } else { - return _accountDao.findById(accountId); - } + public Account getActiveAccountById(long accountId) { + return _accountDao.findById(accountId); } @Override - public Account getAccount(Long accountId) { - if (accountId == null) { - throw new InvalidParameterValueException("AccountId is required by account search"); - } else { - return _accountDao.findByIdIncludingRemoved(accountId); - } + public Account getAccount(long accountId) { + return _accountDao.findByIdIncludingRemoved(accountId); } @Override @@ -1645,62 +1667,6 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M return _userDao.findByIdIncludingRemoved(userId); } - @Override - public Pair, Long> finalizeAccountDomainForList(Account caller, String accountName, Long domainId, Long projectId) { - List permittedAccounts = new ArrayList(); - - if (isAdmin(caller.getType())) { - if (domainId == null && accountName != null) { - throw new InvalidParameterValueException("accountName and domainId might be specified together"); - } else if (domainId != null) { - Domain domain = _domainMgr.getDomain(domainId); - if (domain == null) { - throw new InvalidParameterValueException("Unable to find the domain by id=" + domainId); - } - - checkAccess(caller, domain); - - if (accountName != null) { - Account owner = getActiveAccountByName(accountName, domainId); - if (owner == null) { - throw new InvalidParameterValueException("Unable to find account with name " + accountName + " in domain id=" + domainId); - } - - permittedAccounts.add(owner.getId()); - } - } - } else if (accountName != null && domainId != null) { - if (!accountName.equals(caller.getAccountName()) || domainId.longValue() != caller.getDomainId()) { - throw new PermissionDeniedException("Can't list port forwarding rules for account " + accountName + " in domain " + domainId + ", permission denied"); - } - permittedAccounts.add(getActiveAccountByName(accountName, domainId).getId()); - } else { - permittedAccounts.add(caller.getAccountId()); - } - - if (domainId == null && caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) { - domainId = caller.getDomainId(); - } - - // set project information - if (projectId != null) { - if (projectId.longValue() == -1) { - permittedAccounts.addAll(_projectMgr.listPermittedProjectAccounts(caller.getId())); - } else { - permittedAccounts.clear(); - Project project = _projectMgr.getProject(projectId); - if (project == null) { - throw new InvalidParameterValueException("Unable to find project by id " + projectId); - } - if (!_projectMgr.canAccessProjectAccount(caller, project.getProjectAccountId())) { - throw new InvalidParameterValueException("Account " + caller + " can't access project id=" + projectId); - } - permittedAccounts.add(project.getProjectAccountId()); - } - } - - return new Pair, Long>(permittedAccounts, domainId); - } @Override public User getActiveUserByRegistrationToken(String registrationToken) { @@ -1716,7 +1682,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M @Override @DB - public AccountVO createAccount(String accountName, short accountType, Long domainId, String networkDomain, Map details, String uuid) { + public AccountVO createAccount(String accountName, short accountType, Long domainId, String networkDomain, Map details, String uuid) { // Validate domain Domain domain = _domainMgr.getDomain(domainId); if (domain == null) { @@ -1782,9 +1748,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M return account; } - @Override @ActionEvent(eventType = EventTypes.EVENT_USER_CREATE, eventDescription = "creating User") - public UserVO createUser(long accountId, String userName, String password, String firstName, String lastName, String email, String timezone, String userUUID) { + protected UserVO createUser(long accountId, String userName, String password, String firstName, String lastName, String email, String timezone, String userUUID) { if (s_logger.isDebugEnabled()) { s_logger.debug("Creating user: " + userName + ", accountId: " + accountId + " timezone:" + timezone); } @@ -1809,29 +1774,13 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M } @Override - public void logoutUser(Long userId) { + public void logoutUser(long userId) { UserAccount userAcct = _userAccountDao.findById(userId); if (userAcct != null) { ActionEventUtils.onActionEvent(userId, userAcct.getAccountId(), userAcct.getDomainId(), EventTypes.EVENT_USER_LOGOUT, "user has logged out"); } // else log some kind of error event? This likely means the user doesn't exist, or has been deleted... } - @Override - public UserAccount getUserAccount(String username, Long domainId) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Retrieiving user: " + username + " in domain " + domainId); - } - - UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId); - if (userAccount == null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Unable to find user with name " + username + " in domain " + domainId); - } - return null; - } - - return userAccount; - } @Override public UserAccount authenticateUser(String username, String password, Long domainId, String loginIpAddress, Map requestParameters) { diff --git a/server/src/com/cloud/user/DomainManagerImpl.java b/server/src/com/cloud/user/DomainManagerImpl.java index 00a779e2ff9..20537bae926 100644 --- a/server/src/com/cloud/user/DomainManagerImpl.java +++ b/server/src/com/cloud/user/DomainManagerImpl.java @@ -35,6 +35,8 @@ import com.cloud.configuration.Resource.ResourceOwnerType; import com.cloud.configuration.ResourceLimit; import com.cloud.configuration.dao.ResourceCountDao; import com.cloud.configuration.dao.ResourceLimitDao; +import com.cloud.dc.DedicatedResourceVO; +import com.cloud.dc.dao.DedicatedResourceDao; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; @@ -87,6 +89,8 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom private RegionManager _regionMgr; @Inject private ResourceLimitDao _resourceLimitDao; + @Inject + private DedicatedResourceDao _dedicatedDao; @Override public Domain getDomain(long domainId) { @@ -237,6 +241,17 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom CloudRuntimeException e = new CloudRuntimeException("Delete failed on domain " + domain.getName() + " (id: " + domain.getId() + "); Please make sure all users and sub domains have been removed from the domain before deleting"); e.addProxyObject(domain.getUuid(), "domainId"); throw e; + } else { + //release dedication if any, before deleting the domain + List dedicatedResources = _dedicatedDao.listByDomainId(domain.getId()); + if (dedicatedResources != null && !dedicatedResources.isEmpty()) { + s_logger.debug("Releasing dedicated resources for domain" + domain.getId()); + for (DedicatedResourceVO dr : dedicatedResources){ + if (!_dedicatedDao.remove(dr.getId())) { + s_logger.warn("Fail to release dedicated resources for domain " + domain.getId()); + } + } + } } } else { rollBackState = true; @@ -333,6 +348,17 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom boolean deleteDomainSuccess = true; List accountsForCleanup = _accountDao.findCleanupsForRemovedAccounts(domainId); if (accountsForCleanup.isEmpty()) { + //release dedication if any, before deleting the domain + List dedicatedResources = _dedicatedDao.listByDomainId(domainId); + if (dedicatedResources != null && !dedicatedResources.isEmpty()) { + s_logger.debug("Releasing dedicated resources for domain" + domainId); + for (DedicatedResourceVO dr : dedicatedResources){ + if (!_dedicatedDao.remove(dr.getId())) { + s_logger.warn("Fail to release dedicated resources for domain " + domainId); + } + } + } + //delete domain deleteDomainSuccess = _domainDao.remove(domainId); // Delete resource count and resource limits entries set for this domain (if there are any). diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index a44dab52c27..ebf80564fb8 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -32,6 +32,7 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.server.ConfigurationServer; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.affinity.AffinityGroupVO; @@ -95,9 +96,11 @@ import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenter.NetworkType; 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.DataCenterDeployment; import com.cloud.deploy.DeployDestination; @@ -412,6 +415,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use AffinityGroupVMMapDao _affinityGroupVMMapDao; @Inject AffinityGroupDao _affinityGroupDao; + @Inject + DedicatedResourceDao _dedicatedDao; + @Inject + ConfigurationServer _configServer; protected ScheduledExecutorService _executor = null; protected int _expungeInterval; @@ -748,6 +755,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } if (vm.getState() == State.Running && vm.getHostId() != null) { + collectVmDiskStatistics(vm); return _itMgr.reboot(vm, null, caller, owner); } else { s_logger.error("Vm id=" + vmId @@ -1036,6 +1044,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use Network oldDefaultNetwork = null; oldDefaultNetwork = _networkModel.getDefaultNetworkForVm(vmId); + String oldNicIdString = Long.toString(_networkModel.getDefaultNic(vmId).getId()); long oldNetworkOfferingId = -1L; if(oldDefaultNetwork!=null) { @@ -1075,13 +1084,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use String nicIdString = Long.toString(nic.getId()); long newNetworkOfferingId = network.getNetworkOfferingId(); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vmInstance.getAccountId(), vmInstance.getDataCenterId(), - vmInstance.getId(), nicIdString, oldNetworkOfferingId, null, 1L, VirtualMachine.class.getName(), vmInstance.getUuid()); + vmInstance.getId(), oldNicIdString, oldNetworkOfferingId, null, 1L, VirtualMachine.class.getName(), vmInstance.getUuid()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(), nicIdString, newNetworkOfferingId, null, 1L, VirtualMachine.class.getName(), vmInstance.getUuid()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(), nicIdString, newNetworkOfferingId, null, 0L, VirtualMachine.class.getName(), vmInstance.getUuid()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vmInstance.getAccountId(), vmInstance.getDataCenterId(), - vmInstance.getId(), nicIdString, oldNetworkOfferingId, null, 0L, VirtualMachine.class.getName(), vmInstance.getUuid()); + vmInstance.getId(), oldNicIdString, oldNetworkOfferingId, null, 0L, VirtualMachine.class.getName(), vmInstance.getUuid()); return _vmDao.findById(vmInstance.getId()); } @@ -1189,6 +1198,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use boolean success = false; if(vmInstance.getState().equals(State.Running)){ int retry = _scaleRetry; + boolean enableDynamicallyScaleVm = Boolean.parseBoolean(_configServer.getConfigValue(Config.EnableDynamicallyScaleVm.key(), Config.ConfigurationParameterScope.zone.toString(), vmInstance.getDataCenterId())); + if(!enableDynamicallyScaleVm){ + throw new PermissionDeniedException("Dynamically scaling virtual machines is disabled for this zone, please contact your admin"); + } + // Increment CPU and Memory count accordingly. if (newCpu > currentCpu) { _resourceLimitMgr.incrementResourceCount(caller.getAccountId(), ResourceType.cpu, new Long (newCpu - currentCpu)); @@ -2413,8 +2427,21 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use + zone.getId()); } - if (zone.getDomainId() != null) { - DomainVO domain = _domainDao.findById(zone.getDomainId()); + boolean isExplicit = false; + // check affinity group type Explicit dedication + if (affinityGroupIdList != null) { + for (Long affinityGroupId : affinityGroupIdList) { + AffinityGroupVO ag = _affinityGroupDao.findById(affinityGroupId); + String agType = ag.getType(); + if (agType.equals("ExplicitDedication")) { + isExplicit = true; + } + } + } + // check if zone is dedicated + DedicatedResourceVO dedicatedZone = _dedicatedDao.findByZoneId(zone.getId()); + if (isExplicit && dedicatedZone != null) { + DomainVO domain = _domainDao.findById(dedicatedZone.getDomainId()); if (domain == null) { throw new CloudRuntimeException("Unable to find the domain " + zone.getDomainId() + " for the zone: " + zone); @@ -3804,7 +3831,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use "No permission to migrate VM, Only Root Admin can migrate a VM!"); } - VMInstanceVO vm = _vmInstanceDao.findById(vmId); + UserVmVO vm = _vmDao.findById(vmId); if (vm == null) { throw new InvalidParameterValueException( "Unable to find the VM by id=" + vmId); @@ -3857,6 +3884,21 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use + destinationHost.getResourceState()); } + HostVO srcHost = _hostDao.findById(srcHostId); + HostVO destHost = _hostDao.findById(destinationHost.getId()); + //if srcHost is dedicated and destination Host is not + if (checkIfHostIsDedicated(srcHost) && !checkIfHostIsDedicated(destHost)) { + //raise an alert + String msg = "VM is migrated on a non-dedicated host " + destinationHost.getName(); + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg); + } + //if srcHost is non dedicated but destination Host is. + if (!checkIfHostIsDedicated(srcHost) && checkIfHostIsDedicated(destHost)) { + //raise an alert + String msg = "VM is migrated on a dedicated host " + destinationHost.getName(); + _alertMgr.sendAlert(AlertManager.ALERT_TYPE_USERVM, vm.getDataCenterId(), vm.getPodIdToDeployIn(), msg, msg); + } + // call to core process DataCenterVO dcVO = _dcDao.findById(destinationHost.getDataCenterId()); HostPodVO pod = _podDao.findById(destinationHost.getPodId()); @@ -3880,10 +3922,23 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use + " already has max Running VMs(count includes system VMs), cannot migrate to this host"); } + collectVmDiskStatistics(vm); VMInstanceVO migratedVm = _itMgr.migrate(vm, srcHostId, dest); return migratedVm; } + private boolean checkIfHostIsDedicated(HostVO host) { + long hostId = host.getId(); + DedicatedResourceVO dedicatedHost = _dedicatedDao.findByHostId(hostId); + DedicatedResourceVO dedicatedClusterOfHost = _dedicatedDao.findByClusterId(host.getClusterId()); + DedicatedResourceVO dedicatedPodOfHost = _dedicatedDao.findByPodId(host.getPodId()); + if(dedicatedHost != null || dedicatedClusterOfHost != null || dedicatedPodOfHost != null) { + return true; + } else { + return false; + } + } + @Override @ActionEvent(eventType = EventTypes.EVENT_VM_MIGRATE, eventDescription = "migrating VM", async = true) public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinationHost, @@ -4003,7 +4058,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use VMInstanceVO migratedVm = _itMgr.migrateWithStorage(vm, srcHostId, destinationHost.getId(), volToPoolObjectMap); return migratedVm; - } +} @DB @Override @@ -4657,6 +4712,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use @Override public void prepareStop(VirtualMachineProfile profile) { + UserVmVO vm = _vmDao.findById(profile.getId()); + if (vm.getState() == State.Running) + collectVmDiskStatistics(vm); } } diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 115431a57d5..971de56e4f8 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -2836,7 +2836,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac long isDefault = (nic.isDefaultNic()) ? 1 : 0; // insert nic's Id into DB as resource_name UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vmVO.getAccountId(), - vmVO.getDataCenterId(), vmVO.getId(), Long.toString(nic.getId()), nic.getNetworkId(), + vmVO.getDataCenterId(), vmVO.getId(), Long.toString(nic.getId()), network.getNetworkOfferingId(), null, isDefault, VirtualMachine.class.getName(), vmVO.getUuid()); return nic; } else { diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java index efe18c3b375..52112792d14 100644 --- a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java +++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java @@ -125,8 +125,7 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro @DB @Override @ActionEvent(eventType = EventTypes.EVENT_AFFINITY_GROUP_DELETE, eventDescription = "Deleting affinity group") - public boolean deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName) - throws ResourceInUseException { + public boolean deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName) { Account caller = UserContext.current().getCaller(); Account owner = _accountMgr.finalizeOwner(caller, account, domainId, null); @@ -164,7 +163,15 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro List affinityGroupVmMap = _affinityGroupVMMapDao.listByAffinityGroup(affinityGroupId); if (!affinityGroupVmMap.isEmpty()) { - throw new ResourceInUseException("Cannot delete affinity group when it's in use by virtual machines"); + SearchBuilder listByAffinityGroup = _affinityGroupVMMapDao.createSearchBuilder(); + listByAffinityGroup.and("affinityGroupId", listByAffinityGroup.entity().getAffinityGroupId(), + SearchCriteria.Op.EQ); + listByAffinityGroup.done(); + SearchCriteria sc = listByAffinityGroup.create(); + sc.setParameters("affinityGroupId", affinityGroupId); + + _affinityGroupVMMapDao.lockRows(sc, null, true); + _affinityGroupVMMapDao.remove(sc); } _affinityGroupDao.expunge(affinityGroupId); diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java index a1865c64af7..483c19af431 100644 --- a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java @@ -126,7 +126,8 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR throw new InvalidParameterValueException("Invalid region ID: " + regionId); } - if (!region.checkIfServiceEnabled(Region.Service.Gslb)) { + String providerDnsName = _globalConfigDao.getValue(Config.CloudDnsName.key()); + if (!region.checkIfServiceEnabled(Region.Service.Gslb) || (providerDnsName == null)) { throw new CloudRuntimeException("GSLB service is not enabled in region : " + region.getName()); } @@ -203,6 +204,10 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR _accountMgr.checkAccess(caller, null, true, loadBalancer); + if (gslbRule.getAccountId() != loadBalancer.getAccountId()) { + throw new InvalidParameterValueException("GSLB rule and load balancer rule does not belong to same account"); + } + if (loadBalancer.getState() == LoadBalancer.State.Revoke) { throw new InvalidParameterValueException("Load balancer ID " + loadBalancer.getUuid() + " is in revoke state"); } @@ -255,7 +260,13 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR s_logger.debug("Configuring gslb rule configuration on the gslb service providers in the participating zones"); // apply the gslb rule on to the back end gslb service providers on zones participating in gslb - applyGlobalLoadBalancerRuleConfig(gslbRuleId, false); + if (!applyGlobalLoadBalancerRuleConfig(gslbRuleId, false)) { + s_logger.warn("Failed to add load balancer rules " + newLbRuleIds + " to global load balancer rule id " + + gslbRuleId); + CloudRuntimeException ex = new CloudRuntimeException( + "Failed to add load balancer rules to GSLB rule "); + throw ex; + } // on success set state to Active gslbRule.setState(GlobalLoadBalancerRule.State.Active); @@ -264,7 +275,7 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR success = true; } catch (ResourceUnavailableException e) { - throw new CloudRuntimeException("Failed to apply gslb config"); + throw new CloudRuntimeException("Failed to apply new GSLB configuration while assigning new LB rules to GSLB rule."); } return success; @@ -354,11 +365,28 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR s_logger.debug("Attempting to configure global load balancer rule configuration on the gslb service providers "); // apply the gslb rule on to the back end gslb service providers - applyGlobalLoadBalancerRuleConfig(gslbRuleId, false); + if (!applyGlobalLoadBalancerRuleConfig(gslbRuleId, false)) { + s_logger.warn("Failed to remove load balancer rules " + lbRuleIdsToremove + " from global load balancer rule id " + + gslbRuleId); + CloudRuntimeException ex = new CloudRuntimeException( + "Failed to remove load balancer rule ids from GSLB rule "); + throw ex; + } - // on success set state to Active + txn.start(); + + // remove the mappings of gslb rule to Lb rule that are in revoked state + for (Long lbRuleId : lbRuleIdsToremove) { + GlobalLoadBalancerLbRuleMapVO removeGslbLbMap = _gslbLbMapDao.findByGslbRuleIdAndLbRuleId(gslbRuleId, lbRuleId); + _gslbLbMapDao.remove(removeGslbLbMap.getId()); + } + + // on success set state back to Active gslbRule.setState(GlobalLoadBalancerRule.State.Active); _gslbRuleDao.update(gslbRule.getId(), gslbRule); + + txn.commit(); + success = true; } catch (ResourceUnavailableException e) { throw new CloudRuntimeException("Failed to update removed load balancer details from gloabal load balancer"); @@ -368,24 +396,45 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR } @Override - @DB @ActionEvent(eventType = EventTypes.EVENT_GLOBAL_LOAD_BALANCER_DELETE, eventDescription = "Delete global load balancer rule") public boolean deleteGlobalLoadBalancerRule(DeleteGlobalLoadBalancerRuleCmd deleteGslbCmd) { UserContext ctx = UserContext.current(); Account caller = ctx.getCaller(); - long gslbRuleId = deleteGslbCmd.getGlobalLoadBalancerId(); + + try { + revokeGslbRule(gslbRuleId, caller); + } catch (Exception e) { + s_logger.warn("Failed to delete GSLB rule due to" + e.getMessage()); + return false; + } + + return true; + } + + @DB + private void revokeGslbRule(long gslbRuleId, Account caller) { + GlobalLoadBalancerRuleVO gslbRule = _gslbRuleDao.findById(gslbRuleId); + if (gslbRule == null) { throw new InvalidParameterValueException("Invalid global load balancer rule id: " + gslbRuleId); } _accountMgr.checkAccess(caller, SecurityChecker.AccessType.ModifyEntry, true, gslbRule); - if (gslbRule.getState() == GlobalLoadBalancerRule.State.Revoke) { - throw new InvalidParameterValueException("global load balancer rule id: " + gslbRuleId + " is already in revoked state"); + if (gslbRule.getState() == com.cloud.region.ha.GlobalLoadBalancerRule.State.Staged) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Rule Id: " + gslbRuleId + " is still in Staged state so just removing it."); + } + _gslbRuleDao.remove(gslbRuleId); + return; + } else if (gslbRule.getState() == GlobalLoadBalancerRule.State.Add || gslbRule.getState() == GlobalLoadBalancerRule.State.Active) { + //mark the GSlb rule to be in revoke state + gslbRule.setState(GlobalLoadBalancerRule.State.Revoke); + _gslbRuleDao.update(gslbRuleId, gslbRule); } Transaction txn = Transaction.currentTxn(); @@ -400,10 +449,6 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR } } - //mark the GSlb rule to be in revoke state - gslbRule.setState(GlobalLoadBalancerRule.State.Revoke); - _gslbRuleDao.update(gslbRuleId, gslbRule); - txn.commit(); boolean success = false; @@ -423,10 +468,11 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR _gslbLbMapDao.remove(gslbLbMap.getId()); } } + //remove the GSLB rule itself _gslbRuleDao.remove(gslbRuleId); + txn.commit(); - return success; } @Override @@ -482,6 +528,10 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR @Override public List listGlobalLoadBalancerRule(ListGlobalLoadBalancerRuleCmd listGslbCmd) { + + UserContext ctx = UserContext.current(); + Account caller = ctx.getCaller(); + Integer regionId = listGslbCmd.getRegionId(); Long ruleId = listGslbCmd.getId(); List response = new ArrayList(); @@ -500,12 +550,14 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR if (gslbRule == null) { throw new InvalidParameterValueException("Invalid gslb rule id specified"); } + _accountMgr.checkAccess(caller, org.apache.cloudstack.acl.SecurityChecker.AccessType.ListEntry, false, gslbRule); + response.add(gslbRule); return response; } if (regionId != null) { - List gslbRules = _gslbRuleDao.listByRegionId(regionId); + List gslbRules = _gslbRuleDao.listByAccount(caller.getAccountId()); if (gslbRules != null) { response.addAll(gslbRules); } @@ -604,6 +656,19 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR return true; } + @Override + public boolean revokeAllGslbRulesForAccount(com.cloud.user.Account caller, long accountId) + throws com.cloud.exception.ResourceUnavailableException { + List gslbRules = _gslbRuleDao.listByAccount(accountId); + if (gslbRules != null && !gslbRules.isEmpty()) { + for (GlobalLoadBalancerRule gslbRule : gslbRules) { + revokeGslbRule(gslbRule.getId(), caller); + } + } + s_logger.debug("Successfully cleaned up GSLB rules for account id=" + accountId); + return true; + } + private boolean checkGslbServiceEnabledInZone(long zoneId, long physicalNetworkId) { if (_gslbProvider == null) { diff --git a/server/test/com/cloud/network/MockRulesManagerImpl.java b/server/test/com/cloud/network/MockRulesManagerImpl.java index 82a3e9346e3..331a47ffca6 100644 --- a/server/test/com/cloud/network/MockRulesManagerImpl.java +++ b/server/test/com/cloud/network/MockRulesManagerImpl.java @@ -135,19 +135,6 @@ public class MockRulesManagerImpl extends ManagerBase implements RulesManager, R return false; } - @Override - public boolean applyPortForwardingRules(long ipAddressId, - boolean continueOnError, Account caller) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean applyStaticNatRulesForIp(long sourceIpId, - boolean continueOnError, Account caller, boolean forRevoke) { - // TODO Auto-generated method stub - return false; - } @Override public boolean applyPortForwardingRulesForNetwork(long networkId, @@ -163,13 +150,6 @@ public class MockRulesManagerImpl extends ManagerBase implements RulesManager, R return false; } - @Override - public void checkIpAndUserVm(IpAddress ipAddress, UserVm userVm, - Account caller) { - // TODO Auto-generated method stub - - } - @Override public void checkRuleAndUserVm(FirewallRule rule, UserVm userVm, Account caller) { @@ -191,25 +171,6 @@ public class MockRulesManagerImpl extends ManagerBase implements RulesManager, R return false; } - @Override - public List listFirewallRulesByIp(long ipAddressId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public List listPortForwardingRulesForApplication( - long ipId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public List gatherPortForwardingRulesForApplication( - List addrs) { - // TODO Auto-generated method stub - return null; - } @Override public boolean revokePortForwardingRulesForVm(long vmId) { @@ -217,11 +178,6 @@ public class MockRulesManagerImpl extends ManagerBase implements RulesManager, R return false; } - @Override - public boolean revokeStaticNatRulesForVm(long vmId) { - // TODO Auto-generated method stub - return false; - } @Override public FirewallRule[] reservePorts(IpAddress ip, String protocol, @@ -231,25 +187,6 @@ public class MockRulesManagerImpl extends ManagerBase implements RulesManager, R return null; } - @Override - public boolean releasePorts(long ipId, String protocol, Purpose purpose, - int... ports) { - // TODO Auto-generated method stub - return false; - } - - @Override - public List listByNetworkId(long networkId) { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean applyStaticNatForIp(long sourceIpId, - boolean continueOnError, Account caller, boolean forRevoke) { - // TODO Auto-generated method stub - return false; - } @Override public boolean applyStaticNatsForNetwork(long networkId, diff --git a/server/test/com/cloud/server/ConfigurationServerImplTest.java b/server/test/com/cloud/server/ConfigurationServerImplTest.java new file mode 100644 index 00000000000..6e1f4f90b37 --- /dev/null +++ b/server/test/com/cloud/server/ConfigurationServerImplTest.java @@ -0,0 +1,61 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.server; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.FileUtils; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; + +public class ConfigurationServerImplTest { + final static String TEST = "the quick brown fox jumped over the lazy dog"; + + @Test(expected = IOException.class) + public void testGetBase64KeystoreNoSuchFile() throws IOException { + ConfigurationServerImpl.getBase64Keystore("notexisting" + System.currentTimeMillis()); + } + + @Test(expected = IOException.class) + public void testGetBase64KeystoreTooBigFile() throws IOException { + File temp = File.createTempFile("keystore", ""); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < 1000; i++) { + builder.append("way too long...\n"); + } + FileUtils.writeStringToFile(temp, builder.toString()); + try { + ConfigurationServerImpl.getBase64Keystore(temp.getPath()); + } finally { + temp.delete(); + } + } + + @Test + public void testGetBase64Keystore() throws IOException { + File temp = File.createTempFile("keystore", ""); + try { + FileUtils.writeStringToFile(temp, Base64.encodeBase64String(TEST.getBytes())); + final String keystore = ConfigurationServerImpl.getBase64Keystore(temp.getPath()); + // let's decode it to make sure it makes sense + Base64.decodeBase64(keystore); + } finally { + temp.delete(); + } + } +} diff --git a/server/test/com/cloud/user/MockAccountManagerImpl.java b/server/test/com/cloud/user/MockAccountManagerImpl.java index 64919afa74f..38cc1a84a55 100644 --- a/server/test/com/cloud/user/MockAccountManagerImpl.java +++ b/server/test/com/cloud/user/MockAccountManagerImpl.java @@ -132,12 +132,6 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco return null; } - @Override - public Pair,Long> finalizeAccountDomainForList(Account caller, String accountName, Long domainId, Long projectId) { - // TODO Auto-generated method stub - return null; - } - @Override public Account getActiveAccountByName(String accountName, Long domainId) { // TODO Auto-generated method stub @@ -145,13 +139,13 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco } @Override - public Account getActiveAccountById(Long accountId) { + public Account getActiveAccountById(long accountId) { // TODO Auto-generated method stub return null; } @Override - public Account getAccount(Long accountId) { + public Account getAccount(long accountId) { // TODO Auto-generated method stub return null; } @@ -192,24 +186,12 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco return false; } - @Override - public boolean deleteAccount(AccountVO account, long callerUserId, Account caller) { - // TODO Auto-generated method stub - return false; - } - @Override public void checkAccess(Account account, Domain domain) throws PermissionDeniedException { // TODO Auto-generated method stub } - - @Override - public boolean cleanupAccount(AccountVO account, long callerUserId, Account caller) { - // TODO Auto-generated method stub - return false; - } - + @Override public Long checkAccessAndSpecifyAuthority(Account caller, Long zoneId) { // TODO Auto-generated method stub @@ -244,14 +226,10 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco } @Override - public void logoutUser(Long userId) { + public void logoutUser(long userId) { // TODO Auto-generated method stub } - @Override - public UserAccount getUserAccount(String username, Long domainId) { - return null; - } @Override public UserAccount authenticateUser(String username, String password, Long domainId, String loginIpAddress, Map requestParameters) { @@ -263,21 +241,12 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco return null; } - @Override - public UserVO createUser(long accountId, String userName, String password, String firstName, String lastName, String email, String timezone, String userUUID) { - return null; - } @Override public String[] createApiKeyAndSecretKey(RegisterCmd cmd) { return null; } - @Override - public boolean lockAccount(long accountId) { - return true; - } - @Override public boolean enableAccount(long accountId) { // TODO Auto-generated method stub @@ -341,15 +310,22 @@ public class MockAccountManagerImpl extends ManagerBase implements Manager, Acco return null; } - @Override - public Account createAccount(String accountName, short accountType, - Long domainId, String networkDomain, Map details, String uuid) { - // TODO Auto-generated method stub - return null; - } + @Override public RoleType getRoleType(Account account) { return null; } + @Override + public boolean deleteAccount(AccountVO account, long callerUserId, Account caller) { + // TODO Auto-generated method stub + return false; + } + + @Override + public Account createAccount(String accountName, short accountType, Long domainId, String networkDomain, Map details, String uuid) { + // TODO Auto-generated method stub + return null; + } + } diff --git a/server/test/com/cloud/vm/DeploymentPlanningManagerImplTest.java b/server/test/com/cloud/vm/DeploymentPlanningManagerImplTest.java index e3b7d311ba7..442c2be3969 100644 --- a/server/test/com/cloud/vm/DeploymentPlanningManagerImplTest.java +++ b/server/test/com/cloud/vm/DeploymentPlanningManagerImplTest.java @@ -40,6 +40,7 @@ import com.cloud.dc.ClusterVO; import com.cloud.dc.DataCenterVO; 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.DataCenterDeployment; import com.cloud.deploy.DeployDestination; @@ -113,6 +114,9 @@ public class DeploymentPlanningManagerImplTest { @Inject ClusterDao _clusterDao; + @Inject + DedicatedResourceDao _dedicatedDao; + private static long domainId = 5L; private static long dataCenterId = 1L; @@ -252,6 +256,11 @@ public class DeploymentPlanningManagerImplTest { } @Bean + public DedicatedResourceDao dedicatedResourceDao() { + return Mockito.mock(DedicatedResourceDao.class); + } + + @Bean public GuestOSDao guestOSDao() { return Mockito.mock(GuestOSDao.class); } diff --git a/server/test/com/cloud/vpc/MockVpcManagerImpl.java b/server/test/com/cloud/vpc/MockVpcManagerImpl.java index 921321f52da..7e40083c8bd 100644 --- a/server/test/com/cloud/vpc/MockVpcManagerImpl.java +++ b/server/test/com/cloud/vpc/MockVpcManagerImpl.java @@ -373,7 +373,7 @@ public class MockVpcManagerImpl extends ManagerBase implements VpcManager { } @Override - public void validateNtwkOffForNtwkInVpc(Long networkId, long newNtwkOffId, String newCidr, String newNetworkDomain, Vpc vpc, String gateway, Account networkOwner) { + public void validateNtwkOffForNtwkInVpc(Long networkId, long newNtwkOffId, String newCidr, String newNetworkDomain, Vpc vpc, String gateway, Account networkOwner, Long aclId) { // TODO Auto-generated method stub } diff --git a/server/test/com/cloud/vpc/NetworkACLManagerTest.java b/server/test/com/cloud/vpc/NetworkACLManagerTest.java index 76b811f8685..ddcfe7fabb7 100644 --- a/server/test/com/cloud/vpc/NetworkACLManagerTest.java +++ b/server/test/com/cloud/vpc/NetworkACLManagerTest.java @@ -15,6 +15,7 @@ package com.cloud.vpc; +import com.cloud.configuration.ConfigurationManager; import com.cloud.network.Network; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkModel; @@ -78,6 +79,8 @@ public class NetworkACLManagerTest extends TestCase{ @Inject NetworkDao _networkDao; @Inject + ConfigurationManager _configMgr; + @Inject NetworkModel _networkModel; @Inject List _networkAclElements; @@ -178,6 +181,11 @@ public class NetworkACLManagerTest extends TestCase{ return Mockito.mock(NetworkDao.class); } + @Bean + public ConfigurationManager configMgr() { + return Mockito.mock(ConfigurationManager.class); + } + @Bean public NetworkACLServiceProvider networkElements() { return Mockito.mock(NetworkACLServiceProvider.class); diff --git a/server/test/com/cloud/vpc/NetworkACLServiceTest.java b/server/test/com/cloud/vpc/NetworkACLServiceTest.java index 9a368b94ae4..e71fabfef2d 100644 --- a/server/test/com/cloud/vpc/NetworkACLServiceTest.java +++ b/server/test/com/cloud/vpc/NetworkACLServiceTest.java @@ -138,6 +138,7 @@ public class NetworkACLServiceTest extends TestCase{ Mockito.when(_networkAclMgr.getNetworkACL(Mockito.anyLong())).thenReturn(acl); Mockito.when(_networkAclMgr.createNetworkACLItem(Mockito.anyInt(), Mockito.anyInt(), Mockito.anyString(), Mockito.anyList(), Mockito.anyInt(), Mockito.anyInt(), Mockito.any(NetworkACLItem.TrafficType.class), Mockito.anyLong(), Mockito.anyString(), Mockito.anyInt())).thenReturn(new NetworkACLItemVO()); + Mockito.when(_networkACLItemDao.findByAclAndNumber(Mockito.anyLong(), Mockito.anyInt())).thenReturn(null); assertNotNull(_aclService.createNetworkACLItem(createACLItemCmd)); } diff --git a/server/test/com/cloud/vpc/VpcApiUnitTest.java b/server/test/com/cloud/vpc/VpcApiUnitTest.java index e141c9658b8..400e00c8f3e 100644 --- a/server/test/com/cloud/vpc/VpcApiUnitTest.java +++ b/server/test/com/cloud/vpc/VpcApiUnitTest.java @@ -87,7 +87,7 @@ public class VpcApiUnitTest extends TestCase{ //1) correct network offering boolean result = false; try { - _vpcService.validateNtwkOffForNtwkInVpc(2L, 1, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO()); + _vpcService.validateNtwkOffForNtwkInVpc(2L, 1, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO(), null); result = true; } catch (Exception ex) { } finally { @@ -97,7 +97,7 @@ public class VpcApiUnitTest extends TestCase{ //2) invalid offering - source nat is not included result = false; try { - _vpcService.validateNtwkOffForNtwkInVpc(2L, 2, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO()); + _vpcService.validateNtwkOffForNtwkInVpc(2L, 2, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO(), null); result = true; } catch (InvalidParameterValueException ex) { } finally { @@ -107,7 +107,7 @@ public class VpcApiUnitTest extends TestCase{ //3) invalid offering - conserve mode is off result = false; try { - _vpcService.validateNtwkOffForNtwkInVpc(2L, 3, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO()); + _vpcService.validateNtwkOffForNtwkInVpc(2L, 3, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO(), null); result = true; } catch (InvalidParameterValueException ex) { } finally { @@ -117,7 +117,7 @@ public class VpcApiUnitTest extends TestCase{ //4) invalid offering - guest type shared result = false; try { - _vpcService.validateNtwkOffForNtwkInVpc(2L, 4, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO()); + _vpcService.validateNtwkOffForNtwkInVpc(2L, 4, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO(), null); result = true; } catch (InvalidParameterValueException ex) { } finally { @@ -127,7 +127,7 @@ public class VpcApiUnitTest extends TestCase{ //5) Invalid offering - no redundant router support result = false; try { - _vpcService.validateNtwkOffForNtwkInVpc(2L, 5, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO()); + _vpcService.validateNtwkOffForNtwkInVpc(2L, 5, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO(), null); result = true; } catch (InvalidParameterValueException ex) { } finally { diff --git a/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java b/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java index 484b044e28e..5816b2829f2 100644 --- a/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java +++ b/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java @@ -17,6 +17,7 @@ package org.apache.cloudstack.affinity; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyObject; @@ -51,6 +52,7 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; +import com.cloud.dc.dao.DedicatedResourceDao; import com.cloud.event.EventUtils; import com.cloud.event.EventVO; import com.cloud.event.dao.EventDao; @@ -64,6 +66,8 @@ import com.cloud.user.AccountVO; import com.cloud.user.UserContext; import com.cloud.user.dao.AccountDao; import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.UserVmDao; @@ -102,6 +106,10 @@ public class AffinityApiUnitTest { @Inject EventDao _eventDao; + @Inject + DedicatedResourceDao _dedicatedDao; + + private static long domainId = 5L; @@ -172,20 +180,6 @@ public class AffinityApiUnitTest { _affinityService.deleteAffinityGroup(null, "user", domainId, null); } - @Test(expected = ResourceInUseException.class) - public void deleteAffinityGroupInUse() throws ResourceInUseException { - List affinityGroupVmMap = new ArrayList(); - AffinityGroupVMMapVO mapVO = new AffinityGroupVMMapVO(20L, 10L); - affinityGroupVmMap.add(mapVO); - when(_affinityGroupVMMapDao.listByAffinityGroup(20L)).thenReturn(affinityGroupVmMap); - - AffinityGroupVO groupVO = new AffinityGroupVO(); - when(_groupDao.findById(20L)).thenReturn(groupVO); - when(_groupDao.lockRow(20L, true)).thenReturn(groupVO); - - _affinityService.deleteAffinityGroup(20L, "user", domainId, null); - } - @Test(expected = InvalidParameterValueException.class) public void updateAffinityGroupVMRunning() throws ResourceInUseException { @@ -230,6 +224,11 @@ public class AffinityApiUnitTest { } @Bean + public DedicatedResourceDao dedicatedResourceDao() { + return Mockito.mock(DedicatedResourceDao.class); + } + + @Bean public AccountManager accountManager() { return Mockito.mock(AccountManager.class); } diff --git a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java index f862a2a4760..3f6fe9c4e1b 100644 --- a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java +++ b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java @@ -49,6 +49,7 @@ import com.cloud.dc.dao.DataCenterIpAddressDaoImpl; import com.cloud.dc.dao.DataCenterLinkLocalIpAddressDao; import com.cloud.dc.dao.DataCenterVnetDaoImpl; import com.cloud.dc.dao.DcDetailsDaoImpl; +import com.cloud.dc.dao.DedicatedResourceDao; import com.cloud.dc.dao.HostPodDaoImpl; import com.cloud.dc.dao.PodVlanDaoImpl; import com.cloud.dc.dao.PodVlanMapDaoImpl; @@ -173,7 +174,7 @@ import org.apache.cloudstack.region.PortableIpRangeDaoImpl; }, includeFilters={@Filter(value=ChildTestConfiguration.Library.class, type=FilterType.CUSTOM)}, useDefaultFilters=false -) + ) public class ChildTestConfiguration { @@ -332,6 +333,11 @@ public class ChildTestConfiguration { return Mockito.mock(NetworkDao.class); } + @Bean + public DedicatedResourceDao DedicatedResourceDao() { + return Mockito.mock(DedicatedResourceDao.class); + } + @Bean public NetworkOfferingServiceMapDao networkOfferingServiceMapDao() { return Mockito.mock(NetworkOfferingServiceMapDao.class); @@ -339,7 +345,7 @@ public class ChildTestConfiguration { @Bean public DataCenterLinkLocalIpAddressDao datacenterLinkLocalIpAddressDao() { - return Mockito.mock(DataCenterLinkLocalIpAddressDao.class); + return Mockito.mock(DataCenterLinkLocalIpAddressDao.class); } @Bean @@ -357,7 +363,6 @@ public class ChildTestConfiguration { return Mockito.mock(AccountDetailsDao.class); } - public static class Library implements TypeFilter { @Override diff --git a/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java b/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java index 1c281a08bed..ab545342cfa 100644 --- a/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java +++ b/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java @@ -577,8 +577,14 @@ public class GlobalLoadBalancingRulesServiceImplTest extends TestCase { LoadBalancerVO lbRule1 = new LoadBalancerVO(); lbRule1.setState(FirewallRule.State.Active); Field networkIdField1 = LoadBalancerVO.class.getSuperclass().getDeclaredField("networkId"); + Field accountIdField1 = LoadBalancerVO.class.getSuperclass().getDeclaredField("accountId"); + Field domainIdField1 = LoadBalancerVO.class.getSuperclass().getDeclaredField("domainId"); networkIdField1.setAccessible(true); + accountIdField1.setAccessible(true); + domainIdField1.setAccessible(true); networkIdField1.set(lbRule1, new Long(1)); + accountIdField1.set(lbRule1, new Long(3)); + domainIdField1.set(lbRule1, new Long(1)); Field idField1 = LoadBalancerVO.class.getSuperclass().getDeclaredField("id"); idField1.setAccessible(true); idField1.set(lbRule1, new Long(1)); @@ -586,8 +592,14 @@ public class GlobalLoadBalancingRulesServiceImplTest extends TestCase { LoadBalancerVO lbRule2 = new LoadBalancerVO(); lbRule2.setState(FirewallRule.State.Active); Field networkIdField2 = LoadBalancerVO.class.getSuperclass().getDeclaredField("networkId"); + Field accountIdField2 = LoadBalancerVO.class.getSuperclass().getDeclaredField("accountId"); + Field domainIdField2 = LoadBalancerVO.class.getSuperclass().getDeclaredField("domainId"); networkIdField2.setAccessible(true); + accountIdField2.setAccessible(true); + domainIdField2.setAccessible(true); networkIdField2.set(lbRule2, new Long(1)); + accountIdField2.set(lbRule2, new Long(3)); + domainIdField2.set(lbRule2, new Long(1)); Field idField2 = LoadBalancerVO.class.getSuperclass().getDeclaredField("id"); idField2.setAccessible(true); idField2.set(lbRule2, new Long(2)); @@ -611,6 +623,7 @@ public class GlobalLoadBalancingRulesServiceImplTest extends TestCase { try { gslbServiceImpl.assignToGlobalLoadBalancerRule(assignCmd); } catch (InvalidParameterValueException e) { + s_logger.info(e.getMessage()); Assert.assertTrue(e.getMessage().contains("Load balancer rule specified should be in unique zone")); } } diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index b1feb022836..79550aee1bb 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -2453,7 +2453,6 @@ CREATE TABLE `cloud`.`resource_tags` ( CONSTRAINT `uc_resource_tags__uuid` UNIQUE (`uuid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; - CREATE TABLE `cloud`.`external_nicira_nvp_devices` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', `uuid` varchar(255) UNIQUE, diff --git a/setup/db/db/schema-40to410.sql b/setup/db/db/schema-40to410.sql index f0e8cf31846..67e2048dce2 100644 --- a/setup/db/db/schema-40to410.sql +++ b/setup/db/db/schema-40to410.sql @@ -173,8 +173,6 @@ ALTER TABLE upload ADD uuid VARCHAR(40); ALTER TABLE async_job modify job_cmd VARCHAR(255); -ALTER TABLE `cloud`.`alert` ADD INDEX `last_sent` (`last_sent` DESC) ; - ALTER TABLE `cloud`.`network_offerings` ADD COLUMN `is_persistent` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if the network offering provides an ability to create persistent networks'; diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 4805c46fb0d..a59cf1c84b6 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -27,12 +27,15 @@ ALTER TABLE `cloud`.`hypervisor_capabilities` ADD COLUMN `storage_motion_support UPDATE `cloud`.`hypervisor_capabilities` SET `max_hosts_per_cluster`=32 WHERE `hypervisor_type`='VMware'; INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(uuid, hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_data_volumes_limit, storage_motion_supported) VALUES (UUID(), 'XenServer', '6.1.0', 50, 1, 13, 1); INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(uuid, hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_hosts_per_cluster) VALUES (UUID(), 'VMware', '5.1', 128, 0, 32); +UPDATE `cloud`.`hypervisor_capabilities` SET `storage_motion_supported`=true WHERE id=16; +UPDATE `cloud`.`hypervisor_capabilities` SET `storage_motion_supported`=true WHERE id=11; DELETE FROM `cloud`.`configuration` where name='vmware.percluster.host.max'; INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'AgentManager', 'xen.nics.max', '7', 'Maximum allowed nics for Vms created on Xen'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Network', 'DEFAULT', 'management-server', 'midonet.apiserver.address', 'http://localhost:8081', 'Specify the address at which the Midonet API server can be contacted (if using Midonet)'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Network', 'DEFAULT', 'management-server', 'midonet.providerrouter.id', 'd7c5e6a3-e2f4-426b-b728-b7ce6a0448e5', 'Specifies the UUID of the Midonet provider router (if using Midonet)'); ALTER TABLE `cloud`.`load_balancer_vm_map` ADD state VARCHAR(40) NULL COMMENT 'service status updated by LB healthcheck manager'; +alter table storage_pool add hypervisor varchar(32); alter table storage_pool change storage_provider_id storage_provider_name varchar(255); alter table template_host_ref add state varchar(255); alter table template_host_ref add update_count bigint unsigned; @@ -178,6 +181,27 @@ CREATE TABLE `cloud`.`affinity_group_vm_map` ( +CREATE TABLE `cloud`.`dedicated_resources` ( + `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT 'id', + `uuid` varchar(40), + `data_center_id` bigint unsigned COMMENT 'data center id', + `pod_id` bigint unsigned COMMENT 'pod id', + `cluster_id` bigint unsigned COMMENT 'cluster id', + `host_id` bigint unsigned COMMENT 'host id', + `domain_id` bigint unsigned COMMENT 'domain id of the domain to which resource is dedicated', + `account_id` bigint unsigned COMMENT 'account id of the account to which resource is dedicated', + PRIMARY KEY (`id`), + CONSTRAINT `fk_dedicated_resources__data_center_id` FOREIGN KEY (`data_center_id`) REFERENCES `cloud`.`data_center`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_dedicated_resources__pod_id` FOREIGN KEY (`pod_id`) REFERENCES `cloud`.`host_pod_ref`(`id`), + CONSTRAINT `fk_dedicated_resources__cluster_id` FOREIGN KEY (`cluster_id`) REFERENCES `cloud`.`cluster`(`id`), + CONSTRAINT `fk_dedicated_resources__host_id` FOREIGN KEY (`host_id`) REFERENCES `cloud`.`host`(`id`), + CONSTRAINT `fk_dedicated_resources__domain_id` FOREIGN KEY (`domain_id`) REFERENCES `domain`(`id`), + CONSTRAINT `fk_dedicated_resources__account_id` FOREIGN KEY (`account_id`) REFERENCES `account`(`id`), + INDEX `i_dedicated_resources_domain_id`(`domain_id`), + INDEX `i_dedicated_resources_account_id`(`account_id`), + CONSTRAINT `uc_dedicated_resources__uuid` UNIQUE (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + CREATE TABLE nic_secondary_ips ( `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT, `uuid` varchar(40), @@ -203,6 +227,9 @@ ALTER TABLE `cloud`.`event` ADD COLUMN `archived` tinyint(1) unsigned NOT NULL D INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'alert.purge.interval', '86400', 'The interval (in seconds) to wait before running the alert purge thread'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'alert.purge.delay', '0', 'Alerts older than specified number days will be purged. Set this value to 0 to never delete alerts'); +INSERT INTO `cloud`.`dedicated_resources` (`data_center_id`, `domain_id`) SELECT `id`, `domain_id` FROM `cloud`.`data_center` WHERE `domain_id` IS NOT NULL; +UPDATE `cloud`.`data_center` SET `domain_id` = NULL WHERE `domain_id` IS NOT NULL; + DROP VIEW IF EXISTS `cloud`.`event_view`; CREATE VIEW `cloud`.`event_view` AS select @@ -336,6 +363,8 @@ CREATE TABLE `cloud`.`global_load_balancer_lb_rule_map` ( CONSTRAINT `fk_lb_rule_id` FOREIGN KEY(`lb_rule_id`) REFERENCES `load_balancing_rules`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'cloud.dns.name', null, 'DNS name of the cloud for the GSLB service'); + INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Account Defaults', 'DEFAULT', 'management-server', 'max.account.cpus', '40', 'The default maximum number of cpu cores that can be used for an account'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Account Defaults', 'DEFAULT', 'management-server', 'max.account.memory', '40960', 'The default maximum memory (in MiB) that can be used for an account'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Account Defaults', 'DEFAULT', 'management-server', 'max.account.primary.storage', '200', 'The default maximum primary storage space (in GiB) that can be used for an account'); @@ -808,6 +837,7 @@ CREATE VIEW `cloud`.`storage_pool_view` AS storage_pool.removed, storage_pool.capacity_bytes, storage_pool.scope, + storage_pool.hypervisor, cluster.id cluster_id, cluster.uuid cluster_uuid, cluster.name cluster_name, @@ -985,6 +1015,31 @@ CREATE TABLE `cloud`.`network_asa1000v_map` ( CONSTRAINT `fk_network_asa1000v_map__asa1000v_id` FOREIGN KEY (`asa1000v_id`) REFERENCES `external_cisco_asa1000v_devices`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `cloud`.`vmware_data_center` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `uuid` varchar(255) UNIQUE, + `name` varchar(255) NOT NULL COMMENT 'Name of VMware datacenter', + `guid` varchar(255) NOT NULL UNIQUE COMMENT 'id of VMware datacenter', + `vcenter_host` varchar(255) NOT NULL COMMENT 'vCenter host containing this VMware datacenter', + `username` varchar(255) NOT NULL COMMENT 'Name of vCenter host user', + `password` varchar(255) NOT NULL COMMENT 'Password of vCenter host user', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`vmware_data_center_zone_map` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `zone_id` bigint unsigned NOT NULL UNIQUE COMMENT 'id of CloudStack zone', + `vmware_data_center_id` bigint unsigned NOT NULL UNIQUE COMMENT 'id of VMware datacenter', + PRIMARY KEY (`id`), + CONSTRAINT `fk_vmware_data_center_zone_map__vmware_data_center_id` FOREIGN KEY (`vmware_data_center_id`) REFERENCES `vmware_data_center`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`legacy_zones` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `zone_id` bigint unsigned NOT NULL UNIQUE COMMENT 'id of CloudStack zone', + PRIMARY KEY (`id`), + CONSTRAINT `fk_legacy_zones__zone_id` FOREIGN KEY (`zone_id`) REFERENCES `data_center`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; ALTER TABLE `cloud`.`network_offerings` ADD COLUMN `eip_associate_public_ip` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if public IP is associated with user VM creation by default when EIP service is enabled.' AFTER `elastic_ip_service`; @@ -1722,6 +1777,10 @@ update `cloud`.`vpc_gateways` set network_acl_id = 2; INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'VpcManager', 'blacklisted.routes', NULL, 'Routes that are blacklisted, can not be used for Static Routes creation for the VPC Private Gateway'); +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'enable.dynamic.scale.vm', 'false', 'Enables/Diables dynamically scaling a vm'); + +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'scale.retry', '2', 'Number of times to retry scaling up the vm'); + UPDATE `cloud`.`snapshots` set swift_id=null where swift_id=0; DROP TABLE IF EXISTS `cloud`.`vm_disk_statistics`; @@ -1803,7 +1862,8 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'manag INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'vm.disk.throttling.bytes_rate', 0, 'Default disk I/O rate in bytes per second allowed in User vm\'s disk. '); -- Re-enable foreign key checking, at the end of the upgrade path -SET foreign_key_checks = 1; +SET foreign_key_checks = 1; + UPDATE `cloud`.`snapshot_policy` set uuid=id WHERE uuid is NULL; #update shared sg enabled network with not null name in Advance Security Group enabled network UPDATE `cloud`.`networks` set name='Shared SG enabled network', display_text='Shared SG enabled network' WHERE name IS null AND traffic_type='Guest' AND data_center_id IN (select id from data_center where networktype='Advanced' and is_security_group_enabled=1) AND acl_type='Domain'; diff --git a/test/integration/component/test_assign_vm.py b/test/integration/component/test_assign_vm.py new file mode 100644 index 00000000000..1dc93a81417 --- /dev/null +++ b/test/integration/component/test_assign_vm.py @@ -0,0 +1,458 @@ +# 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. + +""" +""" +#Import Local Modules +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.integration.lib.base import (Account, + Domain, + User, + Project, + Volume, + Snapshot, + DiskOffering, + ServiceOffering, + VirtualMachine) +from marvin.integration.lib.common import (get_domain, + get_zone, + get_template, + cleanup_resources, + list_volumes, + update_resource_limit, + list_networks, + list_snapshots, + list_virtual_machines) + +def log_test_exceptions(func): + def _log_test_exceptions(self, *args, **kwargs): + try: + func(self, *args, **kwargs) + except Exception as e: + self.debug('Test %s Failed due to Exception=%s' % (func, e)) + raise e + return _log_test_exceptions + +class Services: + """Test service data for:Change the ownershop of + VM/network/datadisk/snapshot/template/ISO from one account to any other account. + """ + def __init__(self): + self.services = {"domain" : {"name": "Domain",}, + "account" : {"email" : "test@test.com", + "firstname" : "Test", + "lastname" : "User", + "username" : "test", + # Random characters are appended in create account to + # ensure unique username generated each time + "password" : "password",}, + "user" : {"email" : "user@test.com", + "firstname": "User", + "lastname" : "User", + "username" : "User", + # Random characters are appended for unique + # username + "password" : "fr3sca",}, + "project" : {"name" : "Project", + "displaytext" : "Test project",}, + "volume" : {"diskname" : "TestDiskServ", + "max" : 6,}, + "disk_offering" : {"displaytext" : "Small", + "name" : "Small", + "disksize" : 1}, + "virtual_machine" : {"displayname" : "testserver", + "username" : "root",# VM creds for SSH + "password" : "password", + "ssh_port" : 22, + "hypervisor" : 'XenServer', + "privateport" : 22, + "publicport" : 22, + "protocol" : 'TCP',}, + "service_offering" : {"name" : "Tiny Instance", + "displaytext" : "Tiny Instance", + "cpunumber" : 1, + "cpuspeed" : 100,# in MHz + "memory" : 128}, + #"storagetype" : "local"}, + "sleep" : 60, + "ostype" : 'CentOS 5.3 (64-bit)',# CentOS 5.3 (64-bit) + } + +class TestVMOwnership(cloudstackTestCase): + @classmethod + def setUpClass(cls): + cls._cleanup = [] + cls.api_client = super(TestVMOwnership, + cls).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone Domain and create Domains and sub Domains. + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype + # Get and set template id for VM creation. + cls.template = get_template(cls.api_client, + cls.zone.id, + cls.services["ostype"]) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + def create_domain_account_user(parentDomain=None): + domain = Domain.create(cls.api_client, + cls.services["domain"], + parentdomainid=parentDomain.id if parentDomain else None) + cls._cleanup.append(domain) + # Create an Account associated with domain + account = Account.create(cls.api_client, + cls.services["account"], + domainid=domain.id) + cls._cleanup.append(account) + # Create an User, Project, Volume associated with account + user = User.create(cls.api_client, + cls.services["user"], + account=account.name, + domainid=account.domainid) + cls._cleanup.append(user) + project = Project.create(cls.api_client, + cls.services["project"], + account=account.name, + domainid=account.domainid) + cls._cleanup.append(project) + volume = Volume.create(cls.api_client, + cls.services["volume"], + zoneid=cls.zone.id, + account=account.name, + domainid=account.domainid, + diskofferingid=cls.disk_offering.id) + cls._cleanup.append(volume) + return {'domain':domain, 'account':account, 'user':user, 'project':project, 'volume':volume} + + # Create disk offerings. + try: + cls.disk_offering = DiskOffering.create(cls.api_client, + cls.services["disk_offering"]) + # Create service offerings. + cls.service_offering = ServiceOffering.create(cls.api_client, + cls.services["service_offering"]) + # Cleanup + cls._cleanup = [cls.service_offering] + # Create domain, account, user, project and volumes. + cls.domain_account_user1 = create_domain_account_user() + cls.domain_account_user2 = create_domain_account_user() + cls.sdomain_account_user1 = create_domain_account_user(cls.domain_account_user1['domain']) + cls.sdomain_account_user2 = create_domain_account_user(cls.domain_account_user2['domain']) + cls.ssdomain_account_user2 = create_domain_account_user(cls.sdomain_account_user2['domain']) + except Exception as e: + raise e + return + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.api_client, reversed(cls._cleanup)) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + def setUp(self): + self.apiclient = self.api_client#self.testClient.getApiClient() + #self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + self.snapshot = None + return + + def create_vm(self, + account, + domain, + isRunning=False, + project =None, + limit =None, + pfrule =False, + lbrule =None, + natrule =None, + volume =None, + snapshot =False): + #TODO: Implemnt pfrule/lbrule/natrule + self.debug("Deploying instance in the account: %s" % account.name) + self.virtual_machine = VirtualMachine.create(self.apiclient, + self.services["virtual_machine"], + accountid=account.name, + domainid=domain.id, + serviceofferingid=self.service_offering.id, + mode=self.zone.networktype if pfrule else 'basic', + projectid=project.id if project else None) + self.debug("Deployed instance in account: %s" % account.name) + list_virtual_machines(self.apiclient, + id=self.virtual_machine.id) + if snapshot: + volumes = list_volumes(self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True) + self.snapshot = Snapshot.create(self.apiclient, + volumes[0].id, + account=account.name, + domainid=account.domainid) + if volume: + self.virtual_machine.attach_volume(self.apiclient, + volume) + if not isRunning: + self.virtual_machine.stop(self.apiclient) + self.cleanup.append(self.virtual_machine) + + def check_vm_is_moved_in_account_domainid(self, account): + list_vm_response = list_virtual_machines(self.api_client, + id=self.virtual_machine.id, + account=account.name, + domainid=account.domainid) + self.debug('VM=%s moved to account=%s and domainid=%s' % (list_vm_response, account.name, account.domainid)) + self.assertNotEqual(len(list_vm_response), 0, 'Unable to move VM to account=%s domainid=%s' % (account.name, account.domainid)) + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + cleanup_resources(self.apiclient, reversed(self.cleanup)) + self.debug("Cleanup complete!") + except Exception as e: + self.debug("Warning! Exception in tearDown: %s" % e) + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_01_move_across_different_domains(self): + """Test as root, stop a VM from domain1 and attempt to move it to account in domain2 + """ + # Validate the following: + # 1. deploy VM in domain_1 + # 2. stop VM in domain_1 + # 3. assignVirtualMachine to domain_2 + self.create_vm(self.domain_account_user1['account'], self.domain_account_user1['domain']) + self.virtual_machine.assign_virtual_machine(self.apiclient, self.domain_account_user2['account'].name ,self.domain_account_user2['domain'].id) + self.check_vm_is_moved_in_account_domainid(self.domain_account_user2['account']) + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_02_move_across_subdomains(self): + """Test as root, stop a VM from subdomain1 and attempt to move it to subdomain2 + """ + # Validate the following: + # 1. deploy VM in subdomain_1 + # 2. stop VM in subdomain_1 + # 3. assignVirtualMachine to subdomain_2 + self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain']) + self.virtual_machine.assign_virtual_machine(self.apiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) + self.check_vm_is_moved_in_account_domainid(self.sdomain_account_user2['account']) + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_03_move_from_domain_to_subdomain(self): + """Test as root stop a VM from domain1 and attempt to move it to subdomain1 + """ + # Validate the following: + # 1. deploy VM in domain_1 + # 2. stop VM in domain_1 + # 3. assignVirtualMachine to subdomain_1 + self.create_vm(self.domain_account_user1['account'], self.domain_account_user1['domain']) + self.virtual_machine.assign_virtual_machine(self.apiclient, self.sdomain_account_user1['account'].name ,self.sdomain_account_user1['domain'].id) + self.check_vm_is_moved_in_account_domainid(self.sdomain_account_user1['account']) + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_04_move_from_domain_to_sub_of_subdomain(self): + """Test as root, stop a VM from domain1 and attempt to move it to sub-subdomain1 + """ + # Validate the following: + # 1. deploy VM in domain_2 + # 2. stop VM in domain_2 + # 3. assignVirtualMachine to sub subdomain_2 + self.create_vm(self.domain_account_user2['account'], self.domain_account_user2['domain']) + self.virtual_machine.assign_virtual_machine(self.apiclient, self.ssdomain_account_user2['account'].name ,self.ssdomain_account_user2['domain'].id) + self.check_vm_is_moved_in_account_domainid(self.ssdomain_account_user2['account']) + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_05_move_to_domain_from_sub_of_subdomain(self): + """Test as root, stop a VM from sub-subdomain1 and attempt to move it to domain1 + """ + # Validate the following: + # 1. deploy VM in sub subdomain2 + # 2. stop VM in sub subdomain2 + # 3. assignVirtualMachine to sub domain2 + self.create_vm(self.ssdomain_account_user2['account'], self.ssdomain_account_user2['domain']) + self.virtual_machine.assign_virtual_machine(self.apiclient, self.domain_account_user2['account'].name ,self.domain_account_user2['domain'].id) + self.check_vm_is_moved_in_account_domainid(self.domain_account_user2['account']) + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_06_move_to_domain_from_subdomain(self): + """Test as root, stop a Vm from subdomain1 and attempt to move it to domain1 + """ + # Validate the following: + # 1. deploy VM in sub subdomain1 + # 2. stop VM in sub subdomain1 + # 3. assignVirtualMachine to domain1 + self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain']) + self.virtual_machine.assign_virtual_machine(self.apiclient, self.domain_account_user1['account'].name ,self.domain_account_user1['domain'].id) + self.check_vm_is_moved_in_account_domainid(self.domain_account_user1['account']) + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_07_move_across_subdomain(self): + """Test as root, stop a VM from subdomain1 and attempt to move it to subdomain2 + """ + # Validate the following: + # 1. deploy VM in sub subdomain1 + # 2. stop VM in sub subdomain1 + # 3. assignVirtualMachine to subdomain2 + self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain']) + self.virtual_machine.assign_virtual_machine(self.apiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) + self.check_vm_is_moved_in_account_domainid(self.sdomain_account_user2['account']) + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_08_move_across_subdomain_network_create(self): + """Test as root, stop a VM from subdomain1 and attempt to move it to subdomain2, network should get craeted + """ + # Validate the following: + # 1. deploy VM in sub subdomain1 + # 2. stop VM in sub subdomain1 + # 3. assignVirtualMachine to subdomain2 network should get created + self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain']) + self.virtual_machine.assign_virtual_machine(self.apiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) + self.check_vm_is_moved_in_account_domainid(self.sdomain_account_user2['account']) + networks = list_networks(self.apiclient, + account=self.sdomain_account_user2['account'].name, + domainid=self.sdomain_account_user2['domain'].id) + self.assertEqual(isinstance(networks, list), + True, + "Check for list networks response return valid data") + self.assertNotEqual(len(networks), + 0, + "Check list networks response") + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_09_move_across_subdomain(self): + """Test as domain admin, stop a VM from subdomain1 and attempt to move it to subdomain2 + """ + # Validate the following: + # 1. deploy VM in sub subdomain1 + # 2. stop VM in sub subdomain1 + # 3. assignVirtualMachine to subdomain2 + self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain']) + self.assertRaises(Exception, self.virtual_machine.assign_virtual_machine, self.apiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_10_move_across_subdomain_vm_running(self): + """Test as domain admin, stop a VM from subdomain1 and attempt to move it to subdomain2 + """ + # Validate the following: + # 1. deploy VM in sub subdomain1 + # 3. assignVirtualMachine to subdomain2 + self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain'],isRunning=True) + self.assertRaises(Exception, self.virtual_machine.assign_virtual_machine, self.apiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_11_move_across_subdomain_vm_pfrule(self): + """Test as domain admin, stop a VM from subdomain1 and attempt to move it to subdomain2 + """ + # Validate the following: + # 1. deploy VM in sub subdomain1 with PF rule set. + # 3. assignVirtualMachine to subdomain2 + self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain'],pfrule=True) + self.assertRaises(Exception, self.virtual_machine.assign_virtual_machine, self.apiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_12_move_across_subdomain_vm_volumes(self): + """Test as domain admin, stop a VM from subdomain1 and attempt to move it to subdomain2 + """ + # Validate the following: + # 1. deploy VM in sub subdomain1 with volumes. + # 3. assignVirtualMachine to subdomain2 + self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain'],volume=self.sdomain_account_user1['volume']) + self.assertRaises(Exception, self.virtual_machine.assign_virtual_machine, self.apiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) + # Check all volumes attached to same VM + list_volume_response = list_volumes(self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='DATADISK', + listall=True) + self.assertEqual(isinstance(list_volume_response, list), + True, + "Check list volumes response for valid list") + + self.assertNotEqual(list_volume_response[0].domainid, self.sdomain_account_user2['domain'].id, "Volume ownership not changed.") + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_13_move_across_subdomain_vm_snapshot(self): + """Test as domain admin, stop a VM from subdomain1 and attempt to move it to subdomain2 + """ + # Validate the following: + # 1. deploy VM in sub subdomain1 with snapshot. + # 3. assignVirtualMachine to subdomain2 + self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain'], snapshot=True) + self.virtual_machine.assign_virtual_machine(self.apiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) + snapshots = list_snapshots(self.apiclient, + id=self.snapshot.id) + self.assertEqual(snapshots, + None, + "Snapshots stil present for a vm in domain") + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_14_move_across_subdomain_vm_project(self): + """Test as domain admin, stop a VM from subdomain1 and attempt to move it to subdomain2 + """ + # Validate the following: + # 1. deploy VM in sub subdomain1 with snapshot. + # 3. assignVirtualMachine to subdomain2 + self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain'], project=self.sdomain_account_user1['project']) + self.assertRaises(Exception, self.virtual_machine.assign_virtual_machine, self.apiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_15_move_across_subdomain_account_limit(self): + """Test as domain admin, stop a VM from subdomain1 and attempt to move it to subdomain2 when limit reached + """ + # Validate the following: + # 1. deploy VM in sub subdomain1 when account limit is reached. + # 3. assignVirtualMachine to subdomain2 + update_resource_limit(self.apiclient, + 0, # VM Instances + account=self.sdomain_account_user2['account'].name, + domainid=self.sdomain_account_user2['domain'].id, + max=0) + self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain'], snapshot=True) + self.assertRaises(Exception, self.virtual_machine.assign_virtual_machine, self.apiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) + + @attr(tags = ["advanced"]) + @log_test_exceptions + def test_16_move_across_subdomain_volume_and_account_limit(self): + """Test as domain admin, stop a VM from subdomain1 and attempt to move it to subdomain2 volumes are attached and limit reached + """ + # Validate the following: + # 1. deploy VM in sub subdomain1 when account limit is reached. + # 3. assignVirtualMachine to subdomain2 + update_resource_limit( + self.apiclient, + 0, # VM Instances + account=self.sdomain_account_user2['account'].name, + domainid=self.sdomain_account_user2['domain'].id, + max=0) + self.create_vm(self.sdomain_account_user1['account'], self.sdomain_account_user1['domain'], snapshot=True, volume=self.sdomain_account_user1['volume']) + self.assertRaises(Exception, self.virtual_machine.assign_virtual_machine, self.apiclient, self.sdomain_account_user2['account'].name ,self.sdomain_account_user2['domain'].id) diff --git a/test/integration/component/test_explicit_dedication.py b/test/integration/component/test_explicit_dedication.py new file mode 100644 index 00000000000..21a4904e71b --- /dev/null +++ b/test/integration/component/test_explicit_dedication.py @@ -0,0 +1,231 @@ +# 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. +""" P1 tests for Storage motion +""" +#Import Local Modules +import marvin +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.remoteSSHClient import remoteSSHClient +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from nose.plugins.attrib import attr +#Import System modules +import time + +_multiprocess_shared_ = True +class Services: + """Test explicit dedication + """ + + def __init__(self): + self.services = { + "disk_offering":{ + "displaytext": "Small", + "name": "Small", + "disksize": 1 + }, + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "testexplicit", + # Random characters are appended in create account to + # ensure unique username generated each time + "password": "password", + }, + "virtual_machine" : + { + "affinity": { + "name": "explicit", + "type": "ExplicitDedication", + }, + "hypervisor" : "XenServer", + }, + "small": + # Create a small virtual machine instance with disk offering + { + "displayname": "testserver", + "username": "root", # VM creds for SSH + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "service_offerings": + { + "for-explicit": + { + # Small service offering ID to for change VM + # service offering from medium to small + "name": "For explicit", + "displaytext": "For explicit", + "cpunumber": 1, + "cpuspeed": 500, + "memory": 512 + } + }, + "template": { + "displaytext": "Cent OS Template", + "name": "Cent OS Template", + "passwordenabled": True, + }, + "diskdevice": '/dev/xvdd', + # Disk device where ISO is attached to instance + "mount_dir": "/mnt/tmp", + "sleep": 60, + "timeout": 10, + "ostype": 'CentOS 5.3 (64-bit)' + } + +class TestExplicitDedication(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super(TestExplicitDedication, cls).getClsTestClient().getApiClient() + cls.services = Services().services + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype + + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + # Set Zones and disk offerings + cls.services["small"]["zoneid"] = cls.zone.id + cls.services["small"]["template"] = cls.template.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.small_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offerings"]["for-explicit"] + ) + + #cls.ag = AffinityGroup.create(cls.api_client, cls.services["virtual_machine"]["affinity"], + # account=cls.services["account"], domainid=cls.domain.id) + + cls._cleanup = [ + cls.small_offering, + cls.account + ] + + @classmethod + def tearDownClass(cls): + cls.api_client = super(TestExplicitDedication, cls).getClsTestClient().getApiClient() + cleanup_resources(cls.api_client, cls._cleanup) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + + def tearDown(self): + #Clean up, terminate the created ISOs + cleanup_resources(self.apiclient, self.cleanup) + return + + # This test requires multi host and at least one host which is empty (no vms should + # be running on that host). It explicitly dedicates empty host to an account, deploys + # a vm for that account and verifies that the vm gets deployed to the dedicated host. + @attr(tags = ["advanced", "basic", "multihosts", "explicitdedication"]) + def test_01_deploy_vm_with_explicit_dedication(self): + """Test explicit dedication is placing vms of an account on dedicated hosts. + """ + # Validate the following + # 1. Find and dedicate an empty host to an account. + # 2. Create an affinity group for explicit dedication. + # 3. Create a vm deployment by passing the affinity group as a parameter. + # 4. Validate the vm got deployed on the dedicated host. + # 5. Cleanup. + + # list and find an empty hosts + all_hosts = list_hosts( + self.apiclient, + type='Routing', + ) + + empty_host = None + for host in all_hosts: + vms_on_host = list_virtual_machines( + self.api_client, + hostid=host.id) + if not vms_on_host: + empty_host = host + break + + # Create an affinity group for explicit dedication. + agCmd = createAffinityGroup.createAffinityGroupCmd() + agCmd.name = "explicit-affinity" + agCmd.displayText = "explicit-affinity" + agCmd.account = self.account.name + agCmd.domainid = self.account.domainid + agCmd.type = self.services['virtual_machine']['affinity']['type'] + self.apiclient.createAffinityGroup(agCmd) + + # dedicate the empty host to this account. + dedicateCmd = dedicateHost.dedicateHostCmd() + dedicateCmd.hostid = empty_host.id + dedicateCmd.domainid = self.domain.id + self.apiclient.dedicateHost(dedicateCmd) + + # deploy vm on the dedicated resource. + vm = VirtualMachine.create( + self.api_client, + self.services["small"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.small_offering.id, + affinitygroupnames=["explicit-affinity"], + mode=self.services["mode"] + ) + + list_vm_response = list_virtual_machines( + self.apiclient, + id=vm.id + ) + + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.hostid, + empty_host.id, + "Check destination hostID of deployed VM" + ) + + # release the dedicated host to this account. + releaseCmd = releaseDedicatedHost.releaseDedicatedHostCmd() + releaseCmd.hostid = empty_host.id + releaseCmd.domainid = self.domain.id + self.apiclient.releaseDedicatedHost(releaseCmd) + + #Deletion of the created VM and affinity group is taken care as part of account clean + + return diff --git a/test/integration/smoke/test_internal_lb.py b/test/integration/smoke/test_internal_lb.py index 07a539592ca..0535d6a5345 100644 --- a/test/integration/smoke/test_internal_lb.py +++ b/test/integration/smoke/test_internal_lb.py @@ -25,228 +25,163 @@ from marvin.integration.lib.common import * from nose.plugins.attrib import attr +class Services: + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + "password": "password", + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + }, + "network_offering": { + "name": "Network offering for internal lb service", + "displaytext": "Network offering for internal lb service", + "guestiptype": "Isolated", + "traffictype": "Guest", + "supportedservices": "Vpn,Dhcp,Dns,Lb,UserData,SourceNat,StaticNat,PortForwarding,NetworkACL", + "serviceProviderList": { + "Dhcp": "VpcVirtualRouter", + "Dns": "VpcVirtualRouter", + "Vpn": "VpcVirtualRouter", + "UserData": "VpcVirtualRouter", + "Lb": "InternalLbVM", + "SourceNat": "VpcVirtualRouter", + "StaticNat": "VpcVirtualRouter", + "PortForwarding": "VpcVirtualRouter", + "NetworkACL": "VpcVirtualRouter", + }, + "serviceCapabilityList": { + "SourceNat": {"SupportedSourceNatTypes": "peraccount"}, + "Lb": {"lbSchemes": "internal", "SupportedLbIsolation": "dedicated"} + } + } + } + + class TestInternalLb(cloudstackTestCase): - networkOfferingId = None - networkId = None - vmId = None - lbId = None + """Test Internal LB + """ - zoneId = 1 - serviceOfferingId = 1 - templateId = 5 + @classmethod + def setUpClass(cls): + cls.apiclient = super(TestInternalLb, cls).getClsTestClient().getApiClient() + cls.services = Services().services + cls.zone = get_zone(cls.apiclient, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offering"] + ) + cls.account = Account.create(cls.apiclient, services=cls.services["account"]) + cls.template = get_template( + cls.apiclient, + cls.zone.id, + cls.services["ostype"] + ) + cls.debug("Successfully created account: %s, id: \ + %s" % (cls.account.name,\ + cls.account.id)) + cls.cleanup = [cls.account] - - serviceProviderList = [ - { - "provider": "VpcVirtualRouter", - "service": "Vpn" - }, - { - "provider": "VpcVirtualRouter", - "service": "UserData" - }, - { - "provider": "VpcVirtualRouter", - "service": "Dhcp" - }, - { - "provider": "VpcVirtualRouter", - "service": "Dns" - }, - { - "provider": "InternalLbVM", - "service": "Lb" - }, - { - "provider": "VpcVirtualRouter", - "service": "SourceNat" - }, - { - "provider": "VpcVirtualRouter", - "service": "StaticNat" - }, - { - "provider": "VpcVirtualRouter", - "service": "PortForwarding" - }, - { - "provider": "VpcVirtualRouter", - "service": "NetworkACL" - } - ] - - serviceCapsList = [ - { - "service": "SourceNat", - "capabilitytype": "SupportedSourceNatTypes", - "capabilityvalue": "peraccount" - }, - { - "service": "Lb", - "capabilitytype": "SupportedLbIsolation", - "capabilityvalue": "dedicated" - }, - { - "service": "Lb", - "capabilitytype": "lbSchemes", - "capabilityvalue": "internal" - } - ] - - def setUp(self): - self.apiClient = self.testClient.getApiClient() - - - - @attr(tags=["advanced"]) + @attr(tags=["smoke", "advanced"]) def test_internallb(self): + """Test create, delete, assign, remove of internal loadbalancer + """ #1) Create and enable network offering with Internal Lb vm service - self.createNetworkOffering() - + self.networkOffering = NetworkOffering.create(self.apiclient, self.services["network_offering"], conservemode=False) + self.networkOffering.update(self.apiclient, state="Enabled") + #2) Create VPC and network in it - self.createNetwork() - - #3) Deploy a vm - self.deployVm() + vpcOffering = VpcOffering.list(self.apiclient) + self.assert_(vpcOffering is not None and len(vpcOffering)>0, "No VPC offerings found") + self.services["vpc"] = {} + self.services["vpc"]["name"] = "vpc-internallb" + self.services["vpc"]["displaytext"] = "vpc-internallb" + self.services["vpc"]["cidr"] = "10.1.1.0/24" + vpc = VPC.create( + apiclient=self.apiclient, + services=self.services["vpc"], + networkDomain="vpc.internallb", + vpcofferingid=vpcOffering[0].id, + zoneid=self.zone.id, + account=self.account.name, + domainid=self.domain.id + ) + self.assert_(vpc is not None, "VPC creation failed") + self.services["vpcnetwork"] = {} + self.services["vpcnetwork"]["name"] = "vpcntwk" + self.services["vpcnetwork"]["displaytext"] = "vpcntwk" + ntwk = Network.create( + apiclient=self.apiclient, + services=self.services["vpcnetwork"], + accountid=self.account.name, + domainid=self.domain.id, + networkofferingid=self.networkOffering.id, + zoneid=self.zone.id, + vpcid=vpc.id, + gateway="10.1.1.1", + netmask="255.255.255.192" + ) + self.assertIsNotNone(ntwk, "Network failed to create") + self.debug("Network %s created in VPC %s" %(ntwk.id, vpc.id)) + + #3) Deploy a vm + self.services["virtual_machine"]["networkids"] = ntwk.id + vm = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"], + templateid=self.template.id, + zoneid=self.zone.id, + accountid=self.account.name, + domainid= self.domain.id, + serviceofferingid=self.service_offering.id, + ) + self.assert_(vm is not None, "VM failed to deploy") + self.assert_(vm.state == 'Running', "VM is not running") + self.debug("VM %s deployed in VPC %s" %(vm.id, vpc.id)) #4) Create an Internal Load Balancer - self.createInternalLoadBalancer() + applb = ApplicationLoadBalancer.create(self.apiclient, services=self.services, + name="lbrule", + sourceport=22, + instanceport=22, + algorithm="roundrobin", + scheme="internal", + sourcenetworkid=ntwk.id, + networkid=ntwk.id) #5) Assign the VM to the Internal Load Balancer - self.assignToLoadBalancerRule() + applb.assign(self.apiclient, vms=[vm]) #6) Remove the vm from the Interanl Load Balancer - self.removeFromLoadBalancerRule() + applb.remove(self.apiclient, vms=[vm]) #7) Delete the Load Balancer - self.deleteLoadBalancer() + applb.delete(self.apiclient) + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.apiclient, cls.cleanup) + except Exception, e: + raise Exception("Cleanup failed with %s" % e) - def deployVm(self): - deployVirtualMachineCmd = deployVirtualMachine.deployVirtualMachineCmd() - deployVirtualMachineCmd.networkids = TestInternalLb.networkId - deployVirtualMachineCmd.serviceofferingid = TestInternalLb.serviceOfferingId - deployVirtualMachineCmd.zoneid = TestInternalLb.zoneId - deployVirtualMachineCmd.templateid = TestInternalLb.templateId - deployVirtualMachineCmd.hypervisor = "XenServer" - deployVMResponse = self.apiClient.deployVirtualMachine(deployVirtualMachineCmd) - TestInternalLb.vmId = deployVMResponse.id - - - def createInternalLoadBalancer(self): - createLoadBalancerCmd = createLoadBalancer.createLoadBalancerCmd() - createLoadBalancerCmd.name = "lb rule" - createLoadBalancerCmd.sourceport = 22 - createLoadBalancerCmd.instanceport = 22 - createLoadBalancerCmd.algorithm = "roundrobin" - createLoadBalancerCmd.scheme = "internal" - createLoadBalancerCmd.sourceipaddressnetworkid = TestInternalLb.networkId - createLoadBalancerCmd.networkid = TestInternalLb.networkId - createLoadBalancerResponse = self.apiClient.createLoadBalancer(createLoadBalancerCmd) - TestInternalLb.lbId = createLoadBalancerResponse.id - self.assertIsNotNone(createLoadBalancerResponse.id, "Failed to create a load balancer") - - - def assignToLoadBalancerRule(self): - assignToLoadBalancerRuleCmd = assignToLoadBalancerRule.assignToLoadBalancerRuleCmd() - assignToLoadBalancerRuleCmd.id = TestInternalLb.lbId - assignToLoadBalancerRuleCmd.virtualMachineIds = TestInternalLb.vmId - assignToLoadBalancerRuleResponse = self.apiClient.assignToLoadBalancerRule(assignToLoadBalancerRuleCmd) - self.assertTrue(assignToLoadBalancerRuleResponse.success, "Failed to assign the vm to the load balancer") - - - - def removeFromLoadBalancerRule(self): - removeFromLoadBalancerRuleCmd = removeFromLoadBalancerRule.removeFromLoadBalancerRuleCmd() - removeFromLoadBalancerRuleCmd.id = TestInternalLb.lbId - removeFromLoadBalancerRuleCmd.virtualMachineIds = TestInternalLb.vmId - removeFromLoadBalancerRuleResponse = self.apiClient.removeFromLoadBalancerRule(removeFromLoadBalancerRuleCmd) - self.assertTrue(removeFromLoadBalancerRuleResponse.success, "Failed to remove the vm from the load balancer") - - - - #def removeInternalLoadBalancer(self): - def deleteLoadBalancer(self): - deleteLoadBalancerCmd = deleteLoadBalancer.deleteLoadBalancerCmd() - deleteLoadBalancerCmd.id = TestInternalLb.lbId - deleteLoadBalancerResponse = self.apiClient.deleteLoadBalancer(deleteLoadBalancerCmd) - self.assertTrue(deleteLoadBalancerResponse.success, "Failed to remove the load balancer") - - - - def createNetwork(self): - createVPCCmd = createVPC.createVPCCmd() - createVPCCmd.name = "new vpc" - createVPCCmd.cidr = "10.1.1.0/24" - createVPCCmd.displaytext = "new vpc" - createVPCCmd.vpcofferingid = 1 - createVPCCmd.zoneid = self.zoneId - createVPCResponse = self.apiClient.createVPC(createVPCCmd) - - - createNetworkCmd = createNetwork.createNetworkCmd() - createNetworkCmd.name = "vpc network" - createNetworkCmd.displaytext = "vpc network" - createNetworkCmd.netmask = "255.255.255.0" - createNetworkCmd.gateway = "10.1.1.1" - createNetworkCmd.zoneid = self.zoneId - createNetworkCmd.vpcid = createVPCResponse.id - createNetworkCmd.networkofferingid = TestInternalLb.networkOfferingId - createNetworkResponse = self.apiClient.createNetwork(createNetworkCmd) - TestInternalLb.networkId = createNetworkResponse.id - - self.assertIsNotNone(createNetworkResponse.id, "Network failed to create") - - - def createNetworkOffering(self): - createNetworkOfferingCmd = createNetworkOffering.createNetworkOfferingCmd() - createNetworkOfferingCmd.name = "Network offering for internal lb service - " + str(random.randrange(1,100+1)) - createNetworkOfferingCmd.displaytext = "Network offering for internal lb service" - createNetworkOfferingCmd.guestiptype = "isolated" - createNetworkOfferingCmd.traffictype = "Guest" - createNetworkOfferingCmd.conservemode = "false" - createNetworkOfferingCmd.supportedservices = "Vpn,Dhcp,Dns,Lb,UserData,SourceNat,StaticNat,PortForwarding,NetworkACL" - - - createNetworkOfferingCmd.serviceproviderlist = [] - for item in self.serviceProviderList: - createNetworkOfferingCmd.serviceproviderlist.append({ - 'service': item['service'], - 'provider': item['provider'] - }) - - createNetworkOfferingCmd.servicecapabilitylist = [] - for item in self.serviceCapsList: - createNetworkOfferingCmd.servicecapabilitylist.append({ - 'service': item['service'], - 'capabilitytype': item['capabilitytype'], - 'capabilityvalue': item['capabilityvalue'] - }) - - - createNetworkOfferingResponse = self.apiClient.createNetworkOffering(createNetworkOfferingCmd) - TestInternalLb.networkOfferingId = createNetworkOfferingResponse.id - - #enable network offering - updateNetworkOfferingCmd = updateNetworkOffering.updateNetworkOfferingCmd() - updateNetworkOfferingCmd.id = TestInternalLb.networkOfferingId - updateNetworkOfferingCmd.state = "Enabled" - updateNetworkOfferingResponse = self.apiClient.updateNetworkOffering(updateNetworkOfferingCmd) - - - #list network offering to see if its enabled - listNetworkOfferingsCmd = listNetworkOfferings.listNetworkOfferingsCmd() - listNetworkOfferingsCmd.id = TestInternalLb.networkOfferingId - listOffResponse = self.apiClient.listNetworkOfferings(listNetworkOfferingsCmd) - - self.assertNotEqual(len(listOffResponse), 0, "Check if the list network offerings API \ - returns a non-empty response") - - - def tearDown(self): - #destroy the vm - if TestInternalLb.vmId is not None: - destroyVirtualMachineCmd = destroyVirtualMachine.destroyVirtualMachineCmd() - destroyVirtualMachineCmd.id = TestInternalLb.vmId - destroyVirtualMachineResponse = self.apiClient.destroyVirtualMachine(destroyVirtualMachineCmd) diff --git a/test/integration/smoke/test_iso.py b/test/integration/smoke/test_iso.py index c645d3b055d..75289b8fbe3 100644 --- a/test/integration/smoke/test_iso.py +++ b/test/integration/smoke/test_iso.py @@ -485,7 +485,7 @@ class TestISO(cloudstackTestCase): if len(self.zones) <= 1: self.skipTest("Not enough zones available to perform copy template") - self.services["destzoneid"] = filter(lambda z: z.id != self.zone.id, self.zones)[0] + self.services["destzoneid"] = filter(lambda z: z.id != self.zone.id, self.zones)[0].id self.debug("Copy ISO from %s to %s" % ( self.zone.id, diff --git a/test/integration/smoke/test_network_acl.py b/test/integration/smoke/test_network_acl.py index 3ed45be9cd0..4b3c1f70b67 100644 --- a/test/integration/smoke/test_network_acl.py +++ b/test/integration/smoke/test_network_acl.py @@ -24,96 +24,154 @@ from marvin.integration.lib.base import * from marvin.integration.lib.common import * from nose.plugins.attrib import attr +class Services: + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + "password": "password", + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + }, + "network_offering": { + "name": "Network offering for internal lb service", + "displaytext": "Network offering for internal lb service", + "guestiptype": "Isolated", + "traffictype": "Guest", + "supportedservices": "Vpn,Dhcp,Dns,Lb,UserData,SourceNat,StaticNat,PortForwarding,NetworkACL", + "serviceProviderList": { + "Dhcp": "VpcVirtualRouter", + "Dns": "VpcVirtualRouter", + "Vpn": "VpcVirtualRouter", + "UserData": "VpcVirtualRouter", + "Lb": "InternalLbVM", + "SourceNat": "VpcVirtualRouter", + "StaticNat": "VpcVirtualRouter", + "PortForwarding": "VpcVirtualRouter", + "NetworkACL": "VpcVirtualRouter", + }, + "serviceCapabilityList": { + "SourceNat": {"SupportedSourceNatTypes": "peraccount"}, + "Lb": {"lbSchemes": "internal", "SupportedLbIsolation": "dedicated"} + } + } + } + + class TestNetworkACL(cloudstackTestCase): - networkOfferingId = 11 - networkId = None - vmId = None - vpcId = None - aclId = None - zoneId = 1 - serviceOfferingId = 1 - templateId = 5 + @classmethod + def setUpClass(cls): + cls.apiclient = super(TestNetworkACL, cls).getClsTestClient().getApiClient() + cls.services = Services().services + cls.zone = get_zone(cls.apiclient, cls.services) + cls.domain = get_domain(cls.apiclient) + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offering"] + ) + cls.account = Account.create(cls.apiclient, services=cls.services["account"]) + cls.template = get_template( + cls.apiclient, + cls.zone.id, + cls.services["ostype"] + ) + cls.debug("Successfully created account: %s, id: \ + %s" % (cls.account.name,\ + cls.account.id)) + cls.cleanup = [cls.account] - def setUp(self): - self.apiClient = self.testClient.getApiClient() - - - @attr(tags=["advanced"]) - def test_networkAcl(self): + def test_network_acl(self): + """Test network ACL lists and items in VPC""" + + # 0) Get the default network offering for VPC + networkOffering = NetworkOffering.list(self.apiclient, name="DefaultIsolatedNetworkOfferingForVpcNetworks") + self.assert_(networkOffering is not None and len(networkOffering) > 0, "No VPC based network offering") # 1) Create VPC - self.createVPC() + vpcOffering = VpcOffering.list(self.apiclient) + self.assert_(vpcOffering is not None and len(vpcOffering)>0, "No VPC offerings found") + self.services["vpc"] = {} + self.services["vpc"]["name"] = "vpc-networkacl" + self.services["vpc"]["displaytext"] = "vpc-networkacl" + self.services["vpc"]["cidr"] = "10.1.1.0/24" + vpc = VPC.create( + apiclient=self.apiclient, + services=self.services["vpc"], + networkDomain="vpc.networkacl", + vpcofferingid=vpcOffering[0].id, + zoneid=self.zone.id, + account=self.account.name, + domainid=self.domain.id + ) + self.assert_(vpc is not None, "VPC creation failed") - # 2) Create ACl - self.createACL() + # 2) Create ACL + aclgroup = NetworkACLList.create(apiclient=self.apiclient, services={}, name="acl", description="acl", vpcid=vpc.id) + self.assertIsNotNone(aclgroup, "Failed to create NetworkACL list") + self.debug("Created a network ACL list %s" % aclgroup.name) - # 3) Create ACl Item - self.createACLItem() + # 3) Create ACL Item + aclitem = NetworkACL.create(apiclient=self.apiclient, services={}, + protocol="TCP", number="10", action="Deny", aclid=aclgroup.id, cidrlist=["0.0.0.0/0"]) + self.assertIsNotNone(aclitem, "Network failed to aclItem") + self.debug("Added a network ACL %s to ACL list %s" % (aclitem.id, aclgroup.name)) # 4) Create network with ACL - self.createNetwork() + self.services["vpcnetwork"] = {} + self.services["vpcnetwork"]["name"] = "vpcntwk" + self.services["vpcnetwork"]["displaytext"] = "vpcntwk" + ntwk = Network.create( + apiclient=self.apiclient, + services=self.services["vpcnetwork"], + accountid=self.account.name, + domainid=self.domain.id, + networkofferingid=networkOffering[0].id, + zoneid=self.zone.id, + vpcid=vpc.id, + aclid=aclgroup.id, + gateway="10.1.1.1", + netmask="255.255.255.192" + ) + self.assertIsNotNone(ntwk, "Network failed to create") + self.debug("Network %s created in VPC %s" %(ntwk.id, vpc.id)) + # 5) Deploy a vm - self.deployVm() + self.services["virtual_machine"]["networkids"] = ntwk.id + vm = VirtualMachine.create(self.apiclient, services=self.services["virtual_machine"], + templateid=self.template.id, + zoneid=self.zone.id, + accountid=self.account.name, + domainid= self.domain.id, + serviceofferingid=self.service_offering.id, + ) + self.assert_(vm is not None, "VM failed to deploy") + self.assert_(vm.state == 'Running', "VM is not running") + self.debug("VM %s deployed in VPC %s" %(vm.id, vpc.id)) - def createACL(self): - createAclCmd = createNetworkACLList.createNetworkACLListCmd() - createAclCmd.name = "acl1" - createAclCmd.description = "new acl" - createAclCmd.vpcId = TestNetworkACL.vpcId - createAclResponse = self.apiClient.createNetworkACLList(createAclCmd) - TestNetworkACL.aclId = createAclResponse.id - - def createACLItem(self): - createAclItemCmd = createNetworkACL.createNetworkACLCmd() - createAclItemCmd.cidr = "0.0.0.0/0" - createAclItemCmd.protocol = "TCP" - createAclItemCmd.number = "10" - createAclItemCmd.action = "Deny" - createAclItemCmd.aclId = TestNetworkACL.aclId - createAclItemResponse = self.apiClient.createNetworkACL(createAclItemCmd) - self.assertIsNotNone(createAclItemResponse.id, "Network failed to aclItem") - - def createVPC(self): - createVPCCmd = createVPC.createVPCCmd() - createVPCCmd.name = "new vpc" - createVPCCmd.cidr = "10.1.1.0/24" - createVPCCmd.displaytext = "new vpc" - createVPCCmd.vpcofferingid = 1 - createVPCCmd.zoneid = self.zoneId - createVPCResponse = self.apiClient.createVPC(createVPCCmd) - TestNetworkACL.vpcId = createVPCResponse.id - - - def createNetwork(self): - createNetworkCmd = createNetwork.createNetworkCmd() - createNetworkCmd.name = "vpc network" - createNetworkCmd.displaytext = "vpc network" - createNetworkCmd.netmask = "255.255.255.0" - createNetworkCmd.gateway = "10.1.1.1" - createNetworkCmd.zoneid = self.zoneId - createNetworkCmd.vpcid = TestNetworkACL.vpcId - createNetworkCmd.networkofferingid = TestNetworkACL.networkOfferingId - createNetworkCmd.aclId = TestNetworkACL.aclId - createNetworkResponse = self.apiClient.createNetwork(createNetworkCmd) - TestNetworkACL.networkId = createNetworkResponse.id - - self.assertIsNotNone(createNetworkResponse.id, "Network failed to create") - - def deployVm(self): - deployVirtualMachineCmd = deployVirtualMachine.deployVirtualMachineCmd() - deployVirtualMachineCmd.networkids = TestNetworkACL.networkId - deployVirtualMachineCmd.serviceofferingid = TestNetworkACL.serviceOfferingId - deployVirtualMachineCmd.zoneid = TestNetworkACL.zoneId - deployVirtualMachineCmd.templateid = TestNetworkACL.templateId - deployVirtualMachineCmd.hypervisor = "XenServer" - deployVMResponse = self.apiClient.deployVirtualMachine(deployVirtualMachineCmd) - TestNetworkACL.vmId = deployVMResponse.id - - def tearDown(self): - #destroy the vm - if TestNetworkACL.vmId is not None: - destroyVirtualMachineCmd = destroyVirtualMachine.destroyVirtualMachineCmd() - destroyVirtualMachineCmd.id = TestNetworkACL.vmId - destroyVirtualMachineResponse = self.apiClient.destroyVirtualMachine(destroyVirtualMachineCmd) + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.apiclient, cls.cleanup) + except Exception, e: + raise Exception("Cleanup failed with %s" % e) diff --git a/test/integration/smoke/test_service_offerings.py b/test/integration/smoke/test_service_offerings.py index 3d3b94684e8..a56e34d2874 100644 --- a/test/integration/smoke/test_service_offerings.py +++ b/test/integration/smoke/test_service_offerings.py @@ -34,6 +34,15 @@ class Services: def __init__(self): self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended in create account to + # ensure unique username generated each time + "password": "password", + }, "off": { "name": "Service Offering", diff --git a/test/integration/smoke/test_templates.py b/test/integration/smoke/test_templates.py index 8b83f5e6e43..9478440f77e 100644 --- a/test/integration/smoke/test_templates.py +++ b/test/integration/smoke/test_templates.py @@ -665,7 +665,7 @@ class TestTemplates(cloudstackTestCase): if len(self.zones) <= 1: self.skipTest("Not enough zones available to perform copy template") - self.services["destzoneid"] = filter(lambda z: z.id != self.services["sourcezoneid"], self.zones)[0] + self.services["destzoneid"] = filter(lambda z: z.id != self.services["sourcezoneid"], self.zones)[0].id self.debug("Copy template from Zone: %s to %s" % ( self.services["sourcezoneid"], diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py index 793f7209449..3dd526a0e3b 100644 --- a/tools/apidoc/gen_toc.py +++ b/tools/apidoc/gen_toc.py @@ -86,6 +86,7 @@ known_categories = { 'Pod': 'Pod', 'PublicIpRange': 'Network', 'Zone': 'Zone', + 'Vmware' : 'Zone', 'NetworkOffering': 'Network Offering', 'NetworkACL': 'Network ACL', 'Network': 'Network', @@ -143,7 +144,9 @@ known_categories = { 'AffinityGroup': 'Affinity Group', 'InternalLoadBalancer': 'Internal LB', 'DeploymentPlanners': 'Configuration', - 'PortableIp': 'Portable IP' + 'PortableIp': 'Portable IP', + 'dedicateHost': 'Dedicate Resources', + 'releaseDedicatedHost': 'Dedicate Resources' } diff --git a/tools/appliance/definitions/systemvmtemplate/postinstall.sh b/tools/appliance/definitions/systemvmtemplate/postinstall.sh index f532f88537c..e052cf9c1c3 100644 --- a/tools/appliance/definitions/systemvmtemplate/postinstall.sh +++ b/tools/appliance/definitions/systemvmtemplate/postinstall.sh @@ -42,6 +42,9 @@ install_packages() { apt-get --no-install-recommends -q -y --force-yes install dnsmasq dnsmasq-utils # nfs client apt-get --no-install-recommends -q -y --force-yes install nfs-common + # nfs irqbalance + apt-get --no-install-recommends -q -y --force-yes install irqbalance + # vpn stuff apt-get --no-install-recommends -q -y --force-yes install xl2tpd bcrelay ppp ipsec-tools tdb-tools @@ -110,7 +113,7 @@ fix_nameserver() { # Replace /etc/resolv.conf also cat > /etc/resolv.conf << EOF nameserver 8.8.8.8 -nameserver 4.4.4.4 +nameserver 8.8.4.4 EOF } diff --git a/tools/appliance/definitions/systemvmtemplate64/postinstall.sh b/tools/appliance/definitions/systemvmtemplate64/postinstall.sh index 3ccf3cefdef..786d38d4ef0 100644 --- a/tools/appliance/definitions/systemvmtemplate64/postinstall.sh +++ b/tools/appliance/definitions/systemvmtemplate64/postinstall.sh @@ -42,6 +42,8 @@ install_packages() { apt-get --no-install-recommends -q -y --force-yes install dnsmasq dnsmasq-utils # nfs client apt-get --no-install-recommends -q -y --force-yes install nfs-common + # nfs irqbalance + apt-get --no-install-recommends -q -y --force-yes install irqbalance # vpn stuff apt-get --no-install-recommends -q -y --force-yes install xl2tpd bcrelay ppp ipsec-tools tdb-tools @@ -110,7 +112,7 @@ fix_nameserver() { # Replace /etc/resolv.conf also cat > /etc/resolv.conf << EOF nameserver 8.8.8.8 -nameserver 4.4.4.4 +nameserver 8.8.4.4 EOF } diff --git a/tools/devcloud-kvm/devcloud-kvm.cfg b/tools/devcloud-kvm/devcloud-kvm.cfg index b3f048aac97..9f310e32755 100644 --- a/tools/devcloud-kvm/devcloud-kvm.cfg +++ b/tools/devcloud-kvm/devcloud-kvm.cfg @@ -46,7 +46,7 @@ ] } ], - "dns2": "4.4.4.4", + "dns2": "8.8.4.4", "dns1": "8.8.8.8", "securitygroupenabled": "true", "localstorageenabled": "true", diff --git a/tools/devcloud/devcloud.cfg b/tools/devcloud/devcloud.cfg index e6ab71b5ebf..f665e82c4c9 100644 --- a/tools/devcloud/devcloud.cfg +++ b/tools/devcloud/devcloud.cfg @@ -45,7 +45,7 @@ ] } ], - "dns2": "4.4.4.4", + "dns2": "8.8.4.4", "dns1": "8.8.8.8", "securitygroupenabled": "true", "localstorageenabled": "true", diff --git a/tools/devcloud/devcloud_internal-mgt.cfg b/tools/devcloud/devcloud_internal-mgt.cfg index fe3dd1b41da..beae34547a8 100644 --- a/tools/devcloud/devcloud_internal-mgt.cfg +++ b/tools/devcloud/devcloud_internal-mgt.cfg @@ -44,7 +44,7 @@ ] } ], - "dns2": "4.4.4.4", + "dns2": "8.8.4.4", "dns1": "8.8.8.8", "securitygroupenabled": "true", "localstorageenabled": "true", diff --git a/tools/devcloud/quickcloud.cfg b/tools/devcloud/quickcloud.cfg index a2613d22bdb..77bc114f401 100644 --- a/tools/devcloud/quickcloud.cfg +++ b/tools/devcloud/quickcloud.cfg @@ -49,7 +49,7 @@ ] } ], - "dns2": "4.4.4.4", + "dns2": "8.8.4.4", "dns1": "8.8.8.8", "securitygroupenabled": "true", "localstorageenabled": "true", diff --git a/tools/marvin/marvin/configGenerator.py b/tools/marvin/marvin/configGenerator.py index c970ada850a..bd83efbc126 100644 --- a/tools/marvin/marvin/configGenerator.py +++ b/tools/marvin/marvin/configGenerator.py @@ -269,7 +269,7 @@ def describe_setup_in_basic_mode(): for l in range(1): z = zone() z.dns1 = "8.8.8.8" - z.dns2 = "4.4.4.4" + z.dns2 = "8.8.4.4" z.internaldns1 = "192.168.110.254" z.internaldns2 = "192.168.110.253" z.name = "test"+str(l) @@ -390,7 +390,7 @@ def describe_setup_in_eip_mode(): for l in range(1): z = zone() z.dns1 = "8.8.8.8" - z.dns2 = "4.4.4.4" + z.dns2 = "8.8.4.4" z.internaldns1 = "192.168.110.254" z.internaldns2 = "192.168.110.253" z.name = "test"+str(l) @@ -519,7 +519,7 @@ def describe_setup_in_advanced_mode(): for l in range(1): z = zone() z.dns1 = "8.8.8.8" - z.dns2 = "4.4.4.4" + z.dns2 = "8.8.4.4" z.internaldns1 = "192.168.110.254" z.internaldns2 = "192.168.110.253" z.name = "test"+str(l) @@ -645,7 +645,7 @@ def describe_setup_in_advancedsg_mode(): for l in range(1): z = zone() z.dns1 = "8.8.8.8" - z.dns2 = "4.4.4.4" + z.dns2 = "8.8.4.4" z.internaldns1 = "192.168.110.254" z.internaldns2 = "192.168.110.253" z.name = "test"+str(l) diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py index ec1c34e12c7..503ed6446f5 100755 --- a/tools/marvin/marvin/integration/lib/base.py +++ b/tools/marvin/marvin/integration/lib/base.py @@ -527,6 +527,19 @@ class VirtualMachine: if isinstance(response, list): return response[0].password + def assign_virtual_machine(self, apiclient, account, domainid): + """Move a user VM to another user under same domain.""" + + cmd = assignVirtualMachine.assignVirtualMachineCmd() + cmd.virtualmachineid = self.id + cmd.account = account + cmd.domainid = domainid + try: + response = apiclient.assignVirtualMachine(cmd) + return response + except Exception as e: + raise Exception("assignVirtualMachine failed - %s" %e) + class Volume: """Manage Volume Life cycle @@ -1358,18 +1371,18 @@ class NetworkOffering: if "useVpc" in services: cmd.useVpc = services["useVpc"] - cmd.serviceProviderList = [] + cmd.serviceproviderlist = [] if "serviceProviderList" in services: for service, provider in services["serviceProviderList"].items(): - cmd.serviceProviderList.append({ + cmd.serviceproviderlist.append({ 'service': service, 'provider': provider }) - if "servicecapabilitylist" in services: - cmd.serviceCapabilityList = [] - for service, capability in services["servicecapabilitylist"].items(): + if "serviceCapabilityList" in services: + cmd.servicecapabilitylist = [] + for service, capability in services["serviceCapabilityList"].items(): for ctype, value in capability.items(): - cmd.serviceCapabilityList.append({ + cmd.servicecapabilitylist.append({ 'service': service, 'capabilitytype': ctype, 'capabilityvalue': value @@ -1787,7 +1800,7 @@ class Network: def create(cls, apiclient, services, accountid=None, domainid=None, networkofferingid=None, projectid=None, subdomainaccess=None, zoneid=None, - gateway=None, netmask=None, vpcid=None, guestcidr=None): + gateway=None, netmask=None, vpcid=None, aclid=None, guestcidr=None): """Create Network for account""" cmd = createNetwork.createNetworkCmd() cmd.name = services["name"] @@ -1833,6 +1846,8 @@ class Network: cmd.guestcidr = guestcidr if vpcid: cmd.vpcid = vpcid + if aclid: + cmd.aclid = aclid return Network(apiclient.createNetwork(cmd).__dict__) def delete(self, apiclient): @@ -1875,25 +1890,55 @@ class NetworkACL: self.__dict__.update(items) @classmethod - def create(cls, apiclient, networkid, services, traffictype=None): + def create(cls, apiclient, services, networkid=None, protocol=None, + number=None, aclid=None, action='Allow', traffictype=None, cidrlist=[]): """Create network ACL rules(Ingress/Egress)""" cmd = createNetworkACL.createNetworkACLCmd() - cmd.networkid = networkid + if "networkid" in services: + cmd.networkid = services["networkid"] + elif networkid: + cmd.networkid = networkid + if "protocol" in services: cmd.protocol = services["protocol"] + if services["protocol"] == 'ICMP': + cmd.icmptype = -1 + cmd.icmpcode = -1 + elif protocol: + cmd.protocol = protocol - if services["protocol"] == 'ICMP': - cmd.icmptype = -1 - cmd.icmpcode = -1 - else: + if "startport" in services: cmd.startport = services["startport"] + if "endport" in services: cmd.endport = services["endport"] - cmd.cidrlist = services["cidrlist"] - if traffictype: + if "cidrlist" in services: + cmd.cidrlist = services["cidrlist"] + elif cidrlist: + cmd.cidrlist = cidrlist + + if "traffictype" in services: + cmd.traffictype = services["traffictype"] + elif traffictype: cmd.traffictype = traffictype - # Defaulted to Ingress + + if "action" in services: + cmd.action = services["action"] + elif action: + cmd.action = action + + if "number" in services: + cmd.number = services["number"] + elif number: + cmd.number = number + + if "aclid" in services: + cmd.aclid = services["aclid"] + elif aclid: + cmd.aclid = aclid + + # Defaulted to Ingress return NetworkACL(apiclient.createNetworkACL(cmd).__dict__) def delete(self, apiclient): @@ -1912,6 +1957,50 @@ class NetworkACL: return(apiclient.listNetworkACLs(cmd)) +class NetworkACLList: + """Manage Network ACL lists lifecycle""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(cls, apiclient, services, name=None, description=None, vpcid=None): + """Create network ACL container list""" + + cmd = createNetworkACLList.createNetworkACLListCmd() + if "name" in services: + cmd.name = services["name"] + elif name: + cmd.name = name + + if "description" in services: + cmd.description = services["description"] + elif description: + cmd.description = description + + if "vpcid" in services: + cmd.vpcid = services["vpcid"] + elif vpcid: + cmd.vpcid = vpcid + + return NetworkACLList(apiclient.createNetworkACLList(cmd).__dict__) + + def delete(self, apiclient): + """Delete network acl list""" + + cmd = deleteNetworkACLList.deleteNetworkACLListCmd() + cmd.id = self.id + return apiclient.deleteNetworkACLList(cmd) + + @classmethod + def list(cls, apiclient, **kwargs): + """List Network ACL lists""" + + cmd = listNetworkACLLists.listNetworkACLListsCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listNetworkACLLists(cmd)) + + class Vpn: """Manage VPN life cycle""" @@ -2785,7 +2874,7 @@ class VPC: @classmethod def create(cls, apiclient, services, vpcofferingid, - zoneid, networkDomain=None, account=None, domainid=None): + zoneid, networkDomain=None, account=None, domainid=None, **kwargs): """Creates the virtual private connection (VPC)""" cmd = createVPC.createVPCCmd() @@ -2793,13 +2882,15 @@ class VPC: cmd.displaytext = "-".join([services["displaytext"], random_gen()]) cmd.vpcofferingid = vpcofferingid cmd.zoneid = zoneid - cmd.cidr = services["cidr"] + if "cidr" in services: + cmd.cidr = services["cidr"] if account: cmd.account = account if domainid: cmd.domainid = domainid if networkDomain: cmd.networkDomain = networkDomain + [setattr(cmd, k, v) for k, v in kwargs.items()] return VPC(apiclient.createVPC(cmd).__dict__) def update(self, apiclient, name=None, displaytext=None): @@ -3203,3 +3294,83 @@ class Region: cmd.id = self.id region = apiclient.removeRegion(cmd) return region + + +class ApplicationLoadBalancer: + """Manage Application Load Balancers in VPC""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(cls, apiclient, services, name=None, sourceport=None, instanceport=22, + algorithm="roundrobin", scheme="internal", sourcenetworkid=None, networkid=None): + """Create Application Load Balancer""" + cmd = createLoadBalancer.createLoadBalancerCmd() + + if "name" in services: + cmd.name = services["name"] + elif name: + cmd.name = name + + if "sourceport" in services: + cmd.sourceport = services["sourceport"] + elif sourceport: + cmd.sourceport = sourceport + + if "instanceport" in services: + cmd.instanceport = services["instanceport"] + elif instanceport: + cmd.instanceport = instanceport + + if "algorithm" in services: + cmd.algorithm = services["algorithm"] + elif algorithm: + cmd.algorithm = algorithm + + if "scheme" in services: + cmd.scheme = services["scheme"] + elif scheme: + cmd.scheme = scheme + + if "sourceipaddressnetworkid" in services: + cmd.sourceipaddressnetworkid = services["sourceipaddressnetworkid"] + elif sourcenetworkid: + cmd.sourceipaddressnetworkid = sourcenetworkid + + if "networkid" in services: + cmd.networkid = services["networkid"] + elif networkid: + cmd.networkid = networkid + + return LoadBalancerRule(apiclient.createLoadBalancer(cmd).__dict__) + + def delete(self, apiclient): + """Delete application load balancer""" + cmd = deleteLoadBalancer.deleteLoadBalancerCmd() + cmd.id = self.id + apiclient.deleteLoadBalancerRule(cmd) + return + + def assign(self, apiclient, vms): + """Assign virtual machines to load balancing rule""" + cmd = assignToLoadBalancerRule.assignToLoadBalancerRuleCmd() + cmd.id = self.id + cmd.virtualmachineids = [str(vm.id) for vm in vms] + apiclient.assignToLoadBalancerRule(cmd) + return + + def remove(self, apiclient, vms): + """Remove virtual machines from load balancing rule""" + cmd = removeFromLoadBalancerRule.removeFromLoadBalancerRuleCmd() + cmd.id = self.id + cmd.virtualmachineids = [str(vm.id) for vm in vms] + apiclient.removeFromLoadBalancerRule(cmd) + return + + @classmethod + def list(cls, apiclient, **kwargs): + """List all appln load balancers""" + cmd = listLoadBalancers.listLoadBalancersCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listLoadBalancerRules(cmd)) \ No newline at end of file diff --git a/tools/marvin/marvin/jsonHelper.py b/tools/marvin/marvin/jsonHelper.py index 37363bc8c91..79a6369499c 100644 --- a/tools/marvin/marvin/jsonHelper.py +++ b/tools/marvin/marvin/jsonHelper.py @@ -142,7 +142,7 @@ if __name__ == "__main__": nsp = getResultObj(result) print nsp[0].id - result = '{ "listzonesresponse" : { "count":1 ,"zone" : [ {"id":1,"name":"test0","dns1":"8.8.8.8","dns2":"4.4.4.4","internaldns1":"192.168.110.254","internaldns2":"192.168.110.253","networktype":"Basic","securitygroupsenabled":true,"allocationstate":"Enabled","zonetoken":"5e818a11-6b00-3429-9a07-e27511d3169a","dhcpprovider":"DhcpServer"} ] } }' + result = '{ "listzonesresponse" : { "count":1 ,"zone" : [ {"id":1,"name":"test0","dns1":"8.8.8.8","dns2":"8.8.4.4","internaldns1":"192.168.110.254","internaldns2":"192.168.110.253","networktype":"Basic","securitygroupsenabled":true,"allocationstate":"Enabled","zonetoken":"5e818a11-6b00-3429-9a07-e27511d3169a","dhcpprovider":"DhcpServer"} ] } }' zones = getResultObj(result) print zones[0].id res = authorizeSecurityGroupIngress.authorizeSecurityGroupIngressResponse() @@ -165,7 +165,7 @@ if __name__ == "__main__": asynJob = getResultObj(result) print asynJob - result = '{ "createzoneresponse" : { "zone" : {"id":1,"name":"test0","dns1":"8.8.8.8","dns2":"4.4.4.4","internaldns1":"192.168.110.254","internaldns2":"192.168.110.253","networktype":"Basic","securitygroupsenabled":true,"allocationstate":"Enabled","zonetoken":"3442f287-e932-3111-960b-514d1f9c4610","dhcpprovider":"DhcpServer"} } }' + result = '{ "createzoneresponse" : { "zone" : {"id":1,"name":"test0","dns1":"8.8.8.8","dns2":"8.8.4.4","internaldns1":"192.168.110.254","internaldns2":"192.168.110.253","networktype":"Basic","securitygroupsenabled":true,"allocationstate":"Enabled","zonetoken":"3442f287-e932-3111-960b-514d1f9c4610","dhcpprovider":"DhcpServer"} } }' res = createZone.createZoneResponse() zone = getResultObj(result, res) print zone.id diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index da647877f27..a86b2a25ca5 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -38,9 +38,9 @@ div.toolbar, div.toolbar, .multi-wizard .progress ul li, .multi-wizard.zone-wizard .select-container .field .select-array-item { -/*\*/ + /*\*/ display: block; -/**/ + /**/ -height: 1px; } @@ -1762,22 +1762,51 @@ div.list-view td.state.off span { .detail-group .main-groups table td.value .view-all { cursor: pointer; /*[empty]height:;*/ - border-left: 1px solid #9FA2A5; /*+border-radius:4px 0 0 4px;*/ -moz-border-radius: 4px 0 0 4px; -webkit-border-radius: 4px 0 0 4px; -khtml-border-radius: 4px 0 0 4px; border-radius: 4px 0 0 4px; - background: url(../images/sprites.png) no-repeat 100% -398px; float: right; - margin: 1px 0 0; - padding: 8px 33px 6px 15px; + margin: 7px 0 0; + padding: 0px; +} + +.detail-group .main-groups table td.value .view-all span { + display: block; + float: left; + padding: 5px 2px 8px 4px; + background: url(../images/gradients.png) repeat-x 0px -529px; + border-left: 1px solid #9FA2A6; + /*+border-radius:4px 0 0 4px;*/ + -moz-border-radius: 4px 0 0 4px; + -webkit-border-radius: 4px 0 0 4px; + -khtml-border-radius: 4px 0 0 4px; + border-radius: 4px 0 0 4px; + margin-top: -5px; +} + +.detail-group .main-groups table td.value .view-all .end { + background: url(../images/sprites.png) no-repeat 100% -397px; + float: right; + width: 22px; + height: 25px; + padding: 0px; + margin: -6px 0px 0px; } .detail-group .main-groups table td.value .view-all:hover { background-position: 100% -431px; } +.detail-group .main-groups table td.value .view-all:hover span { + background-position: 0px -566px; +} + +.detail-group .main-groups table td.value .view-all:hover div.end { + background-position: -618px -430px; +} + .detail-view .detail-group .button.add { clear: both; margin: 0px 21px 13px 0 !important; @@ -3461,7 +3490,7 @@ div.view table td.editable div.action.cancel { /*** Actions*/ table td.actions { cursor: default; -/*Make fixed*/ + /*Make fixed*/ width: 200px; min-width: 200px; max-width: 200px; @@ -3748,6 +3777,10 @@ Dialogs*/ font-size: 15px; } +.ui-dialog div.form-container span.message br { + margin-bottom: 13px; +} + .ui-dialog div.form-container div.form-item { width: 100%; display: inline-block; @@ -4329,7 +4362,7 @@ Dialogs*/ margin: 6px 9px 9px; padding: 9px; color: #FFFFFF; -/*Adjusting the font size for proper display*/ + /*Adjusting the font size for proper display*/ font-size: 10px; border-left: 1px solid #6A6A6A; border-right: 1px solid #6A6A6A; @@ -7857,6 +7890,13 @@ div.ui-dialog div.multi-edit-add-list div.view div.data-table table.body tbody t font-weight: bold; } +.multi-edit .data .data-body .data-item tr td.add-vm p { + text-indent: 0; + padding-left: 9px; + margin-top: 3px; + margin-bottom: 6px; +} + .multi-edit .data .data-body .data-item tr td.multi-actions .icon { /*+placement:shift -3px -2px;*/ position: relative; @@ -7975,7 +8015,7 @@ div.ui-dialog div.multi-edit-add-list div.view div.data-table table.body tbody t .multi-edit .header-fields input[type=submit] { } -/* Sortable */ +/*Sortable*/ .multi-edit table tbody tr td.reorder, .multi-edit table thead tr th.reorder { width: 30px !important; @@ -7983,7 +8023,6 @@ div.ui-dialog div.multi-edit-add-list div.view div.data-table table.body tbody t max-width: 30px !important; } - /*Security Rules*/ .security-rules .multi-edit input { width: 69px; @@ -11725,11 +11764,13 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it background-position: 0px -613px; } -.restart .icon { +.restart .icon, +.releaseDedicatedZone .icon { background-position: 0px -63px; } -.restart:hover .icon { +.restart:hover .icon, +.releaseDedicatedZone:hover .icon { background-position: 0px -645px; } @@ -11885,14 +11926,16 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it .create .icon, .createTemplate .icon, .enableSwift .icon, -.addVM .icon { +.addVM .icon, +.dedicateZone .icon { background-position: -69px -63px; } .create:hover .icon, .createTemplate:hover .icon, .enableSwift:hover .icon, -.addVM:hover .icon { +.addVM:hover .icon, +.dedicateZone:hover .icon { background-position: -69px -645px; } diff --git a/ui/dictionary.jsp b/ui/dictionary.jsp index 13206c37a8d..dd24aa2e12c 100644 --- a/ui/dictionary.jsp +++ b/ui/dictionary.jsp @@ -25,6 +25,9 @@ under the License. <% long now = System.currentTimeMillis(); %>