diff --git a/api/src/com/cloud/agent/api/VgpuTypesInfo.java b/api/src/com/cloud/agent/api/VgpuTypesInfo.java new file mode 100644 index 0000000000..ed54c5af0f --- /dev/null +++ b/api/src/com/cloud/agent/api/VgpuTypesInfo.java @@ -0,0 +1,80 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.api; +public class VgpuTypesInfo { + + private String modelName; + private Long maxHeads; + private Long videoRam; + private Long maxResolutionX; + private Long maxResolutionY; + private Long maxVgpuPerGpu; + private Long remainingCapacity; + private Long maxCapacity; + + public String getModelName() { + return modelName; + } + + public Long getVideoRam() { + return videoRam; + } + + public Long getMaxHeads() { + return maxHeads; + } + + public Long getMaxResolutionX() { + return maxResolutionX; + } + + public Long getMaxResolutionY() { + return maxResolutionY; + } + + public Long getMaxVpuPerGpu() { + return maxVgpuPerGpu; + } + + public Long getRemainingCapacity() { + return remainingCapacity; + } + + public void setRemainingCapacity(Long remainingCapacity) { + this.remainingCapacity = remainingCapacity; + } + + public Long getMaxCapacity() { + return maxCapacity; + } + + public void setMaxVmCapacity(Long maxCapacity) { + this.maxCapacity = maxCapacity; + } + + public VgpuTypesInfo(String modelName, Long videoRam, Long maxHeads, Long maxResolutionX, Long maxResolutionY, Long maxVgpuPerGpu, + Long remainingCapacity, Long maxCapacity) { + this.modelName = modelName; + this.videoRam = videoRam; + this.maxHeads = maxHeads; + this.maxResolutionX = maxResolutionX; + this.maxResolutionY = maxResolutionY; + this.maxVgpuPerGpu = maxVgpuPerGpu; + this.remainingCapacity = remainingCapacity; + this.maxCapacity = maxCapacity; + } +} diff --git a/api/src/com/cloud/agent/api/to/GPUDeviceTO.java b/api/src/com/cloud/agent/api/to/GPUDeviceTO.java index 8bc9e5229d..4afe080477 100644 --- a/api/src/com/cloud/agent/api/to/GPUDeviceTO.java +++ b/api/src/com/cloud/agent/api/to/GPUDeviceTO.java @@ -18,13 +18,15 @@ import java.util.HashMap; +import com.cloud.agent.api.VgpuTypesInfo; + public class GPUDeviceTO { private String gpuGroup; private String vgpuType; - private HashMap> groupDetails = new HashMap>(); + private HashMap> groupDetails = new HashMap>(); - public GPUDeviceTO( String gpuGroup, String vgpuType, HashMap> groupDetails) { + public GPUDeviceTO( String gpuGroup, String vgpuType, HashMap> groupDetails) { this.gpuGroup = gpuGroup; this.vgpuType = vgpuType; this.groupDetails = groupDetails; @@ -46,11 +48,12 @@ public void setVgpuType(String vgpuType) { this.vgpuType = vgpuType; } - public HashMap> getGroupDetails() { + public HashMap> getGroupDetails() { return groupDetails; } - public void setGroupDetails(HashMap> groupDetails) { + public void setGroupDetails(HashMap> groupDetails) { this.groupDetails = groupDetails; } + } diff --git a/api/src/com/cloud/gpu/GPU.java b/api/src/com/cloud/gpu/GPU.java index 0eb466758f..9177edbf9c 100644 --- a/api/src/com/cloud/gpu/GPU.java +++ b/api/src/com/cloud/gpu/GPU.java @@ -23,15 +23,13 @@ public enum Keys { pciDevice, vgpuType } - public enum Type { - GPU_Passthrough, - VGPU - } public enum vGPUType { GRID_K100("GRID K100"), + GRID_K120Q("GRID K120Q"), GRID_K140Q("GRID K140Q"), GRID_K200("GRID K200"), + GRID_K220Q("GRID K220Q"), GRID_K240Q("GRID K240Q"), GRID_K260("GRID K260Q"), passthrough("passthrough"); diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index 3283a55bfe..ef3bcdf51c 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -57,7 +57,7 @@ public static class Service { public static final Service PortForwarding = new Service("PortForwarding"); public static final Service SecurityGroup = new Service("SecurityGroup"); public static final Service NetworkACL = new Service("NetworkACL", Capability.SupportedProtocols); - public static final Service Connectivity = new Service("Connectivity", Capability.DistributedRouter); + public static final Service Connectivity = new Service("Connectivity", Capability.DistributedRouter, Capability.RegionLevelVpc, Capability.StretchedL2Subnet); private final String name; private final Capability[] caps; @@ -187,6 +187,8 @@ public static class Capability { public static final Capability LbSchemes = new Capability("LbSchemes"); public static final Capability DhcpAccrossMultipleSubnets = new Capability("DhcpAccrossMultipleSubnets"); public static final Capability DistributedRouter = new Capability("DistributedRouter"); + public static final Capability StretchedL2Subnet = new Capability("StretchedL2Subnet"); + public static final Capability RegionLevelVpc = new Capability("RegionLevelVpc"); private final String name; @@ -337,4 +339,6 @@ public void setIp6Address(String ip6Address) { Long getNetworkACLId(); void setNetworkACLId(Long networkACLId); + + boolean isStrechedL2Network(); } diff --git a/api/src/com/cloud/network/NetworkModel.java b/api/src/com/cloud/network/NetworkModel.java index f6555db565..1e0a8e88e4 100644 --- a/api/src/com/cloud/network/NetworkModel.java +++ b/api/src/com/cloud/network/NetworkModel.java @@ -22,6 +22,8 @@ import java.util.Map; import java.util.Set; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; + import com.cloud.dc.Vlan; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InvalidParameterValueException; @@ -273,4 +275,6 @@ public interface NetworkModel { boolean isNetworkReadyForGc(long networkId); boolean getNetworkEgressDefaultPolicy(Long networkId); + + void checkNetworkPermissions(Account owner, Network network, AccessType accessType); } \ No newline at end of file diff --git a/api/src/com/cloud/network/NetworkProfile.java b/api/src/com/cloud/network/NetworkProfile.java index 3f576945a5..db3cba56e1 100644 --- a/api/src/com/cloud/network/NetworkProfile.java +++ b/api/src/com/cloud/network/NetworkProfile.java @@ -18,8 +18,6 @@ import java.net.URI; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; @@ -57,6 +55,7 @@ public class NetworkProfile implements Network { private final boolean displayNetwork; private Long networkAclId; private final String guruName; + private boolean strechedL2Subnet; public NetworkProfile(Network network) { id = network.getId(); @@ -89,6 +88,7 @@ public NetworkProfile(Network network) { displayNetwork = network.getDisplayNetwork(); networkAclId = network.getNetworkACLId(); guruName = network.getGuruName(); + strechedL2Subnet = network.isStrechedL2Network(); } public String getDns1() { @@ -279,7 +279,13 @@ public String getIp6Cidr() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Network; + public Class getEntityType() { + return Network.class; + } + + @Override + public boolean isStrechedL2Network() { + return false; } + } diff --git a/api/src/com/cloud/network/lb/LoadBalancingRulesService.java b/api/src/com/cloud/network/lb/LoadBalancingRulesService.java index 4c87d342db..98d29c5718 100644 --- a/api/src/com/cloud/network/lb/LoadBalancingRulesService.java +++ b/api/src/com/cloud/network/lb/LoadBalancingRulesService.java @@ -92,13 +92,13 @@ LoadBalancer createPublicLoadBalancerRule(String xId, String name, String descri boolean deleteLBHealthCheckPolicy(long healthCheckPolicyId, boolean apply); /** - * Assign a virtual machine, or list of virtual machines, to a load balancer. + * Assign a virtual machine or list of virtual machines, or Map of to a load balancer. */ - boolean assignToLoadBalancer(long lbRuleId, List vmIds); + boolean assignToLoadBalancer(long lbRuleId, List vmIds, Map> vmIdIpMap); boolean assignSSLCertToLoadBalancerRule(Long lbRuleId, String certName, String publicCert, String privateKey); - boolean removeFromLoadBalancer(long lbRuleId, List vmIds); + boolean removeFromLoadBalancer(long lbRuleId, List vmIds, Map> vmIdIpMap); boolean applyLoadBalancerConfig(long lbRuleId) throws ResourceUnavailableException; @@ -151,4 +151,8 @@ LoadBalancer createPublicLoadBalancerRule(String xId, String name, String descri public void updateLBHealthChecks(Scheme scheme) throws ResourceUnavailableException; Map getLbInstances(long lbId); + + boolean isLbRuleMappedToVmGuestIp(String vmSecondaryIp); + + List listLbVmIpAddress(long id, long vmId); } diff --git a/api/src/com/cloud/network/vpc/StaticRouteProfile.java b/api/src/com/cloud/network/vpc/StaticRouteProfile.java index b5bd5f7af5..737541f0a4 100644 --- a/api/src/com/cloud/network/vpc/StaticRouteProfile.java +++ b/api/src/com/cloud/network/vpc/StaticRouteProfile.java @@ -16,7 +16,6 @@ // under the License. package com.cloud.network.vpc; -import org.apache.cloudstack.acl.IAMEntityType; public class StaticRouteProfile implements StaticRoute { private long id; @@ -104,7 +103,7 @@ public String getNetmask() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.StaticRoute; + public Class getEntityType() { + return StaticRoute.class; } } diff --git a/api/src/com/cloud/network/vpc/Vpc.java b/api/src/com/cloud/network/vpc/Vpc.java index 4bc8c98872..23388787d2 100644 --- a/api/src/com/cloud/network/vpc/Vpc.java +++ b/api/src/com/cloud/network/vpc/Vpc.java @@ -79,4 +79,10 @@ public enum State { * @return true if VPC is configured to use distributed router to provides one-hop forwarding and hypervisor based ACL */ boolean usesDistributedRouter(); + + /** + * + * @return true if VPC spans multiple zones in the region + */ + boolean isRegionLevelVpc(); } diff --git a/api/src/com/cloud/network/vpc/VpcOffering.java b/api/src/com/cloud/network/vpc/VpcOffering.java index a0a1b1528c..660c79dc1e 100644 --- a/api/src/com/cloud/network/vpc/VpcOffering.java +++ b/api/src/com/cloud/network/vpc/VpcOffering.java @@ -56,8 +56,12 @@ public enum State { Long getServiceOfferingId(); /** - * * @return true if the offering provides a distributed router capable of one-hop forwarding */ boolean supportsDistributedRouter(); + + /** + * @return true if VPC created with the offering can span multiple zones in the region + */ + boolean offersRegionLevelVPC(); } diff --git a/api/src/com/cloud/network/vpc/VpcProvisioningService.java b/api/src/com/cloud/network/vpc/VpcProvisioningService.java index e545275217..82a7baae95 100644 --- a/api/src/com/cloud/network/vpc/VpcProvisioningService.java +++ b/api/src/com/cloud/network/vpc/VpcProvisioningService.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.network.vpc; + import java.util.List; import java.util.Map; diff --git a/api/src/com/cloud/offering/NetworkOffering.java b/api/src/com/cloud/offering/NetworkOffering.java index b4f3863293..f1ef69c2f6 100644 --- a/api/src/com/cloud/offering/NetworkOffering.java +++ b/api/src/com/cloud/offering/NetworkOffering.java @@ -129,4 +129,6 @@ public enum Detail { Integer getConcurrentConnections(); boolean isKeepAliveEnabled(); + + boolean getSupportsStrechedL2(); } diff --git a/api/src/com/cloud/storage/StoragePool.java b/api/src/com/cloud/storage/StoragePool.java index 6ede960c1f..8e03c3348f 100644 --- a/api/src/com/cloud/storage/StoragePool.java +++ b/api/src/com/cloud/storage/StoragePool.java @@ -21,6 +21,7 @@ import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; +import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.Storage.StoragePoolType; public interface StoragePool extends Identity, InternalIdentity { @@ -98,10 +99,9 @@ public interface StoragePool extends Identity, InternalIdentity { Long getPodId(); - /** - * @return - */ String getStorageProviderName(); boolean isInMaintenance(); + + Hypervisor.HypervisorType getHypervisor(); } diff --git a/api/src/com/cloud/storage/VolumeApiService.java b/api/src/com/cloud/storage/VolumeApiService.java index beaa29096e..5487a4bf9b 100644 --- a/api/src/com/cloud/storage/VolumeApiService.java +++ b/api/src/com/cloud/storage/VolumeApiService.java @@ -96,4 +96,6 @@ public interface VolumeApiService { String extractVolume(ExtractVolumeCmd cmd); boolean isDisplayResourceEnabled(Long id); + + void updateDisplay(Volume volume, Boolean displayVolume); } diff --git a/api/src/com/cloud/user/AccountService.java b/api/src/com/cloud/user/AccountService.java index 7e37b386b9..71136bf836 100755 --- a/api/src/com/cloud/user/AccountService.java +++ b/api/src/com/cloud/user/AccountService.java @@ -74,7 +74,7 @@ UserAccount createUserAccount(String userName, String password, String firstName User createUser(String userName, String password, String firstName, String lastName, String email, String timeZone, String accountName, Long domainId, String userUUID); - boolean isAdmin(short accountType); + boolean isAdmin(Long accountId); Account finalizeOwner(Account caller, String accountName, Long domainId, Long projectId); @@ -104,15 +104,14 @@ UserAccount createUserAccount(String userName, String password, String firstName RoleType getRoleType(Account account); - void checkAccess(Account account, Domain domain) throws PermissionDeniedException; + void checkAccess(Account caller, Domain domain) throws PermissionDeniedException; - void checkAccess(Account account, AccessType accessType, boolean sameOwner, ControlledEntity... entities) throws PermissionDeniedException; + void checkAccess(Account caller, AccessType accessType, ControlledEntity... entities) throws PermissionDeniedException; - void checkAccess(Account account, AccessType accessType, boolean sameOwner, String apiName, - ControlledEntity... entities) throws PermissionDeniedException; + void checkAccess(Account caller, AccessType accessType, String apiName, ControlledEntity... entities) throws PermissionDeniedException; //TO be implemented, to check accessibility for an entity owned by domain - void checkAccess(Account account, AccessType accessType, boolean sameOwner, PartOf... entities) throws PermissionDeniedException; + void checkAccess(Account caller, AccessType accessType, boolean sameOwner, PartOf... entities) throws PermissionDeniedException; Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly); } diff --git a/api/src/com/cloud/vm/VirtualMachine.java b/api/src/com/cloud/vm/VirtualMachine.java index b085d4a7c4..e7cfd64c4e 100755 --- a/api/src/com/cloud/vm/VirtualMachine.java +++ b/api/src/com/cloud/vm/VirtualMachine.java @@ -102,6 +102,7 @@ public static StateMachine2 getStat s_fsm.addTransition(State.Running, VirtualMachine.Event.StopRequested, State.Stopping); s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportShutdowned, State.Stopped); s_fsm.addTransition(State.Running, VirtualMachine.Event.AgentReportMigrated, State.Running); + s_fsm.addTransition(State.Running, VirtualMachine.Event.OperationSucceeded, State.Running); s_fsm.addTransition(State.Migrating, VirtualMachine.Event.MigrationRequested, State.Migrating); s_fsm.addTransition(State.Migrating, VirtualMachine.Event.OperationSucceeded, State.Running); s_fsm.addTransition(State.Migrating, VirtualMachine.Event.OperationFailed, State.Running); @@ -320,4 +321,6 @@ public boolean isUsedBySystem() { long getUpdated(); + boolean isDisplay(); + } diff --git a/api/src/org/apache/cloudstack/acl/ControlledEntity.java b/api/src/org/apache/cloudstack/acl/ControlledEntity.java index 2572705daa..b8a244f3bd 100644 --- a/api/src/org/apache/cloudstack/acl/ControlledEntity.java +++ b/api/src/org/apache/cloudstack/acl/ControlledEntity.java @@ -29,5 +29,5 @@ public enum ACLType { Account, Domain } - IAMEntityType getEntityType(); + Class getEntityType(); } diff --git a/api/src/org/apache/cloudstack/acl/IAMEntityType.java b/api/src/org/apache/cloudstack/acl/IAMEntityType.java deleted file mode 100644 index c1703ea5c3..0000000000 --- a/api/src/org/apache/cloudstack/acl/IAMEntityType.java +++ /dev/null @@ -1,61 +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.acl; - -public enum IAMEntityType { - // currently supported entity, to be added one by one after we support acl on the entity - VirtualMachine, - Volume, - ResourceTag, - Account, - AffinityGroup, - AutoScalePolicy, - AutoScaleVmGroup, - AutoScaleVmProfile, - Condition, - Vpc, - VpcGateway, - PrivateGateway, - VpnUser, - VMSnapshot, - VirtualMachineTemplate, - UserIpv6Address, - StaticRoute, - SSHKeyPair, - Snapshot, - Site2SiteVpnGateway, - Site2SiteVpnConnection, - Site2SiteCustomerGateway, - SecurityGroup, - RemoteAccessVpn, - PublicIpAddress, - ProjectInvitation, - NicSecondaryIp, - NicIpAlias, - Network, - IpAddress, - InstanceGroup, - GlobalLoadBalancerRule, - FirewallRule, - PortForwardingRule, - Event, - AsyncJob, - IAMPolicy, - IAMGroup, - MonitorService, - SSLCert -} diff --git a/api/src/org/apache/cloudstack/acl/QuerySelector.java b/api/src/org/apache/cloudstack/acl/QuerySelector.java index b89aa4e9ef..229ce9866f 100644 --- a/api/src/org/apache/cloudstack/acl/QuerySelector.java +++ b/api/src/org/apache/cloudstack/acl/QuerySelector.java @@ -18,6 +18,8 @@ import java.util.List; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; + import com.cloud.user.Account; import com.cloud.utils.component.Adapter; @@ -33,7 +35,7 @@ public interface QuerySelector extends Adapter { * @param action action * @return list of domain Ids granted to the caller account. */ - List getAuthorizedDomains(Account caller, String action); + List getAuthorizedDomains(Account caller, String action, AccessType accessType); /** * List granted accounts for the caller, given a specific action. @@ -42,7 +44,7 @@ public interface QuerySelector extends Adapter { * @param action action. * @return list of domain Ids granted to the caller account. */ - List getAuthorizedAccounts(Account caller, String action); + List getAuthorizedAccounts(Account caller, String action, AccessType accessType); /** @@ -52,7 +54,7 @@ public interface QuerySelector extends Adapter { * @param action action. * @return list of domain Ids granted to the caller account. */ - List getAuthorizedResources(Account caller, String action); + List getAuthorizedResources(Account caller, String action, AccessType accessType); /** * Check if this account is associated with a policy with scope of ALL @@ -60,7 +62,7 @@ public interface QuerySelector extends Adapter { * @param action action. * @return true if this account is attached with a policy for the given action of ALL scope. */ - boolean isGrantedAll(Account caller, String action); + boolean isGrantedAll(Account caller, String action, AccessType accessType); /** * List of ACL group the given account belongs to diff --git a/api/src/org/apache/cloudstack/acl/SecurityChecker.java b/api/src/org/apache/cloudstack/acl/SecurityChecker.java index 614f604aec..79366bdc97 100644 --- a/api/src/org/apache/cloudstack/acl/SecurityChecker.java +++ b/api/src/org/apache/cloudstack/acl/SecurityChecker.java @@ -31,9 +31,10 @@ public interface SecurityChecker extends Adapter { public enum AccessType { - ModifyProject, + ListEntry, + UseEntry, OperateEntry, - UseEntry + ModifyProject, } /** @@ -99,6 +100,26 @@ boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessTy */ boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType, String action) throws PermissionDeniedException; + /** + * Checks if the account can access multiple objects. + * + * @param caller + * account to check against. + * @param entities + * objects that the account is trying to access. + * @param accessType + * TODO + * @param action + * name of the API + * @return true if access allowed. false if this adapter cannot provide + * permission. + * @throws PermissionDeniedException + * if this adapter is suppose to authenticate ownership and the + * check failed. + */ + boolean checkAccess(Account caller, AccessType accessType, String action, ControlledEntity... entities) + throws PermissionDeniedException; + /** * Checks if the user belongs to an account that can access the object. diff --git a/api/src/org/apache/cloudstack/api/APICommand.java b/api/src/org/apache/cloudstack/api/APICommand.java index 9b4dfafdb6..d451e4b10a 100644 --- a/api/src/org/apache/cloudstack/api/APICommand.java +++ b/api/src/org/apache/cloudstack/api/APICommand.java @@ -22,7 +22,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.ResponseObject.ResponseView; @@ -49,5 +48,5 @@ RoleType[] authorized() default {}; - IAMEntityType[] entityType() default {}; + Class[] entityType() default {}; } diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index 32107edf84..70e1984420 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -26,6 +26,7 @@ public class ApiConstants { public static final String API_KEY = "apikey"; public static final String USER_API_KEY = "userapikey"; public static final String APPLIED = "applied"; + public static final String LIST_LB_VMIPS = "lbvmips"; public static final String AVAILABLE = "available"; public static final String BITS = "bits"; public static final String BOOTABLE = "bootable"; @@ -262,6 +263,8 @@ public class ApiConstants { public static final String VALUE = "value"; public static final String VIRTUAL_MACHINE_ID = "virtualmachineid"; public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids"; + public static final String VIRTUAL_MACHINE_ID_IP = "vmidipmap"; + public static final String VLAN = "vlan"; public static final String VLAN_RANGE = "vlanrange"; public static final String REMOVE_VLAN = "removevlan"; @@ -417,6 +420,7 @@ public class ApiConstants { public static final String INSTANCE_NAME = "instancename"; public static final String START_VM = "startvm"; public static final String HA_HOST = "hahost"; + public static final String CUSTOM_DISK_OFF_MIN_SIZE = "customdiskofferingminsize"; public static final String CUSTOM_DISK_OFF_MAX_SIZE = "customdiskofferingmaxsize"; public static final String DEFAULT_ZONE_ID = "defaultzoneid"; public static final String LIVE_MIGRATE = "livemigrate"; @@ -587,9 +591,20 @@ public class ApiConstants { public static final String GPUGROUPNAME = "gpugroupname"; public static final String VGPU = "vgpu"; public static final String VGPUTYPE = "vgputype"; + public static final String VIDEORAM = "videoram"; + public static final String MAXHEADS = "maxheads"; + public static final String MAXRESOLUTIONX = "maxresolutionx"; + public static final String MAXRESOLUTIONY = "maxresolutiony"; + public static final String MAXVGPUPERPGPU = "maxvgpuperpgpu"; public static final String REMAININGCAPACITY = "remainingcapacity"; + public static final String MAXCAPACITY = "maxcapacity"; public static final String DISTRIBUTED_VPC_ROUTER = "distributedvpcrouter"; - + public static final String SUPPORTS_REGION_LEVEL_VPC = "supportsregionLevelvpc"; + public static final String SUPPORTS_STRECHED_L2_SUBNET = "supportsstrechedl2subnet"; + public static final String REGION_LEVEL_VPC = "regionlevelvpc"; + public static final String READ_ONLY = "readonly"; + public static final String STRECHED_L2_SUBNET = "strechedl2subnet"; + public static final String NETWORK_SPANNED_ZONES = "zonesnetworkspans"; public enum HostDetails { all, capacity, events, stats, min; diff --git a/api/src/org/apache/cloudstack/api/BaseListAccountResourcesCmd.java b/api/src/org/apache/cloudstack/api/BaseListAccountResourcesCmd.java index 63d2b7f761..d494f6403f 100644 --- a/api/src/org/apache/cloudstack/api/BaseListAccountResourcesCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseListAccountResourcesCmd.java @@ -16,9 +16,6 @@ // under the License. package org.apache.cloudstack.api; -import org.apache.cloudstack.context.CallContext; - -import com.cloud.user.Account; public abstract class BaseListAccountResourcesCmd extends BaseListDomainResourcesCmd { @@ -30,10 +27,6 @@ public String getAccountName() { } public Boolean getDisplay() { - Account caller = CallContext.current().getCallingAccount(); - if (caller.getType() == Account.ACCOUNT_TYPE_NORMAL) { - return true; - } - return null; + return true; } } diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java index 0c46d501bd..50d67d993d 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/account/CreateAccountCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -37,7 +36,7 @@ import com.cloud.user.UserAccount; -@APICommand(name = "createAccount", description = "Creates an account", responseObject = AccountResponse.class, entityType = {IAMEntityType.Account}, +@APICommand(name = "createAccount", description = "Creates an account", responseObject = AccountResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = true, responseHasSensitiveInfo = true) public class CreateAccountCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateAccountCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java index 8cc87c2884..5754ec5010 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/account/DeleteAccountCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,7 +38,7 @@ import com.cloud.user.Account; import com.cloud.user.User; -@APICommand(name = "deleteAccount", description = "Deletes a account, and all users associated with this account", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Account}, +@APICommand(name = "deleteAccount", description = "Deletes a account, and all users associated with this account", responseObject = SuccessResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAccountCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteAccountCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java index 1e810091ee..3e5e1d3d01 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/account/DisableAccountCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -41,7 +40,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; -@APICommand(name = "disableAccount", description = "Disables an account", responseObject = AccountResponse.class, entityType = {IAMEntityType.Account}, +@APICommand(name = "disableAccount", description = "Disables an account", responseObject = AccountResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class DisableAccountCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DisableAccountCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java index 1bfd71c804..f30c985c96 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/account/EnableAccountCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.user.Account; -@APICommand(name = "enableAccount", description = "Enables an account", responseObject = AccountResponse.class, entityType = {IAMEntityType.Account}, +@APICommand(name = "enableAccount", description = "Enables an account", responseObject = AccountResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class EnableAccountCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(EnableAccountCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/LockAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/LockAccountCmd.java index 780dac1d7a..3c185e41bd 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/account/LockAccountCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/account/LockAccountCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; @@ -28,7 +27,7 @@ import com.cloud.user.Account; -@APICommand(name = "lockAccount", description = "Locks an account", responseObject = AccountResponse.class, entityType = {IAMEntityType.Account}, +@APICommand(name = "lockAccount", description = "Locks an account", responseObject = AccountResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class LockAccountCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(LockAccountCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java b/api/src/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java index 8d9fe261f9..a7ce74a129 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/account/UpdateAccountCmd.java @@ -23,7 +23,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,7 +38,7 @@ import com.cloud.user.Account; -@APICommand(name = "updateAccount", description = "Updates account information for the authenticated user", responseObject = AccountResponse.class, entityType = {IAMEntityType.Account}, +@APICommand(name = "updateAccount", description = "Updates account information for the authenticated user", responseObject = AccountResponse.class, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpdateAccountCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(UpdateAccountCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/address/AssociateIPAddrCmdByAdmin.java b/api/src/org/apache/cloudstack/api/command/admin/address/AssociateIPAddrCmdByAdmin.java index dbff93f222..494a6d66e4 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/address/AssociateIPAddrCmdByAdmin.java +++ b/api/src/org/apache/cloudstack/api/command/admin/address/AssociateIPAddrCmdByAdmin.java @@ -31,8 +31,11 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.IpAddress; +import com.cloud.network.vpc.Vpc; -@APICommand(name = "associateIpAddress", description = "Acquires and associates a public IP to an account.", responseObject = IPAddressResponse.class, responseView = ResponseView.Full) +@APICommand(name = "associateIpAddress", description = "Acquires and associates a public IP to an account.", responseObject = IPAddressResponse.class, responseView = ResponseView.Full, + entityType = {IpAddress.class, Vpc.class}, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AssociateIPAddrCmdByAdmin extends AssociateIPAddrCmd { public static final Logger s_logger = Logger.getLogger(AssociateIPAddrCmdByAdmin.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java index e6ea519778..0b59b73f9d 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLBVMsCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -34,8 +33,9 @@ import org.apache.cloudstack.api.response.ZoneResponse; import com.cloud.network.router.VirtualRouter.Role; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "listInternalLoadBalancerVMs", description = "List internal LB VMs.", responseObject = DomainRouterResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "listInternalLoadBalancerVMs", description = "List internal LB VMs.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListInternalLBVMsCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListInternalLBVMsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLoadBalancerElementsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLoadBalancerElementsCmd.java index 489b64325f..8f62b41969 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLoadBalancerElementsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/internallb/ListInternalLoadBalancerElementsCmd.java @@ -47,7 +47,7 @@ responseHasSensitiveInfo = false) public class ListInternalLoadBalancerElementsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListInternalLoadBalancerElementsCmd.class.getName()); - private static final String Name = "listinternalloadbalancerelementsresponse"; + private static final String s_name = "listinternalloadbalancerelementsresponse"; @Inject private InternalLoadBalancerElementService _service; @@ -88,7 +88,7 @@ public Boolean getEnabled() { @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/internallb/StartInternalLBVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/internallb/StartInternalLBVMCmd.java index 54d7621600..7040e7cf29 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/internallb/StartInternalLBVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/internallb/StartInternalLBVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -38,8 +37,9 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VirtualRouter.Role; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "startInternalLoadBalancerVM", responseObject = DomainRouterResponse.class, description = "Starts an existing internal lb vm.", entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "startInternalLoadBalancerVM", responseObject = DomainRouterResponse.class, description = "Starts an existing internal lb vm.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StartInternalLBVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(StartInternalLBVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/internallb/StopInternalLBVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/internallb/StopInternalLBVMCmd.java index aa946bee31..51a3d9f8fa 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/internallb/StopInternalLBVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/internallb/StopInternalLBVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -37,8 +36,9 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VirtualRouter.Role; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "stopInternalLoadBalancerVM", description = "Stops an Internal LB vm.", responseObject = DomainRouterResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "stopInternalLoadBalancerVM", description = "Stops an Internal LB vm.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StopInternalLBVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(StopInternalLBVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/iso/CopyIsoCmdByAdmin.java b/api/src/org/apache/cloudstack/api/command/admin/iso/CopyIsoCmdByAdmin.java new file mode 100644 index 0000000000..0475b37155 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/iso/CopyIsoCmdByAdmin.java @@ -0,0 +1,12 @@ +package org.apache.cloudstack.api.command.admin.iso; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ResponseObject.ResponseView; +import org.apache.cloudstack.api.command.user.iso.CopyIsoCmd; +import org.apache.cloudstack.api.response.TemplateResponse; + +@APICommand(name = "copyIso", description = "Copies an iso from one zone to another.", responseObject = TemplateResponse.class, responseView = ResponseView.Full, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +public class CopyIsoCmdByAdmin extends CopyIsoCmd { + +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/loadbalancer/ListLoadBalancerRuleInstancesCmdByAdmin.java b/api/src/org/apache/cloudstack/api/command/admin/loadbalancer/ListLoadBalancerRuleInstancesCmdByAdmin.java index 26202b9bae..6c0d8a4888 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/loadbalancer/ListLoadBalancerRuleInstancesCmdByAdmin.java +++ b/api/src/org/apache/cloudstack/api/command/admin/loadbalancer/ListLoadBalancerRuleInstancesCmdByAdmin.java @@ -19,6 +19,8 @@ import java.util.ArrayList; import java.util.List; +import com.cloud.vm.VirtualMachine; +import org.apache.cloudstack.api.response.LoadBalancerRuleVmMapResponse; import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; @@ -30,7 +32,7 @@ import com.cloud.uservm.UserVm; import com.cloud.utils.Pair; -@APICommand(name = "listLoadBalancerRuleInstances", description = "List all virtual machine instances that are assigned to a load balancer rule.", responseObject = UserVmResponse.class, responseView = ResponseView.Full) +@APICommand(name = "listLoadBalancerRuleInstances", description = "List all virtual machine instances that are assigned to a load balancer rule.", responseObject = LoadBalancerRuleVmMapResponse.class, responseView = ResponseView.Full) public class ListLoadBalancerRuleInstancesCmdByAdmin extends ListLoadBalancerRuleInstancesCmd { public static final Logger s_logger = Logger.getLogger (ListLoadBalancerRuleInstancesCmdByAdmin.class.getName()); @@ -41,17 +43,50 @@ public void execute(){ Pair, List> vmServiceMap = _lbService.listLoadBalancerInstances(this); List result = vmServiceMap.first(); List serviceStates = vmServiceMap.second(); - ListResponse response = new ListResponse(); - List vmResponses = new ArrayList(); - if (result != null) { - vmResponses = _responseGenerator.createUserVmResponse(ResponseView.Full, "loadbalancerruleinstance", result.toArray(new UserVm[result.size()])); - } - for (int i=0;i response = new ListResponse(); + List vmResponses = new ArrayList(); + if (result != null) { + vmResponses = _responseGenerator.createUserVmResponse(ResponseView.Restricted, "loadbalancerruleinstance", result.toArray(new UserVm[result.size()])); + + + for (int i = 0; i < result.size(); i++) { + vmResponses.get(i).setServiceState(serviceStates.get(i)); + } + } + response.setResponses(vmResponses); + response.setResponseName(getCommandName()); + setResponseObject(response); + + } else { + ListResponse lbRes = new ListResponse(); + + List vmResponses = new ArrayList(); + List listlbVmRes = new ArrayList(); + + if (result != null) { + vmResponses = _responseGenerator.createUserVmResponse(ResponseView.Full, "loadbalancerruleinstance", result.toArray(new UserVm[result.size()])); + + List ipaddr = null; + + for (int i=0;i getDetails() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/network/ListSupportedNetworkServicesCmd.java b/api/src/org/apache/cloudstack/api/command/admin/network/ListSupportedNetworkServicesCmd.java index 612c733a34..39e99a43a6 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/network/ListSupportedNetworkServicesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/network/ListSupportedNetworkServicesCmd.java @@ -41,7 +41,7 @@ responseHasSensitiveInfo = false) public class ListSupportedNetworkServicesCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListSupportedNetworkServicesCmd.class.getName()); - private static final String Name = "listsupportednetworkservicesresponse"; + private static final String s_name = "listsupportednetworkservicesresponse"; @Parameter(name = ApiConstants.PROVIDER, type = CommandType.STRING, description = "network service provider name") private String providerName; @@ -74,7 +74,7 @@ public String getServiceName() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java b/api/src/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java index f650b4ffb0..411da4fd36 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/network/UpdateNetworkOfferingCmd.java @@ -33,7 +33,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateNetworkOfferingCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(UpdateNetworkOfferingCmd.class.getName()); - private static final String Name = "updatenetworkofferingresponse"; + private static final String s_name = "updatenetworkofferingresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -110,7 +110,7 @@ public Boolean getKeepAliveEnabled() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java b/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java index 78101fb11a..6cd5d84a07 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java @@ -38,7 +38,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateServiceOfferingCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateServiceOfferingCmd.class.getName()); - private static final String Name = "createserviceofferingresponse"; + private static final String s_name = "createserviceofferingresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -118,19 +118,20 @@ public class CreateServiceOfferingCmd extends BaseCmd { @Parameter(name = ApiConstants.IOPS_WRITE_RATE, type = CommandType.LONG, required = false, description = "io requests write rate of the disk offering") private Long iopsWriteRate; - @Parameter(name = ApiConstants.CUSTOMIZED_IOPS, type = CommandType.BOOLEAN, required = false, description = "whether compute offering iops is custom or not") + @Parameter(name = ApiConstants.CUSTOMIZED_IOPS, type = CommandType.BOOLEAN, required = false, description = "whether compute offering iops is custom or not", since = "4.4") private Boolean customizedIops; - @Parameter(name = ApiConstants.MIN_IOPS, type = CommandType.LONG, required = false, description = "min iops of the compute offering") + @Parameter(name = ApiConstants.MIN_IOPS, type = CommandType.LONG, required = false, description = "min iops of the compute offering", since = "4.4") private Long minIops; - @Parameter(name = ApiConstants.MAX_IOPS, type = CommandType.LONG, required = false, description = "max iops of the compute offering") + @Parameter(name = ApiConstants.MAX_IOPS, type = CommandType.LONG, required = false, description = "max iops of the compute offering", since = "4.4") private Long maxIops; @Parameter(name = ApiConstants.HYPERVISOR_SNAPSHOT_RESERVE, type = CommandType.INTEGER, required = false, - description = "Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)") + description = "Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)", + since = "4.4") private Integer hypervisorSnapshotReserve; ///////////////////////////////////////////////////// @@ -257,7 +258,7 @@ public Integer getHypervisorSnapshotReserve() { @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/DestroyRouterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/DestroyRouterCmd.java index 26440d4be9..4513e2e85e 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/router/DestroyRouterCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/router/DestroyRouterCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -34,8 +33,9 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.router.VirtualRouter; import com.cloud.user.Account; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "destroyRouter", description = "Destroys a router.", responseObject = DomainRouterResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "destroyRouter", description = "Destroys a router.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DestroyRouterCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DestroyRouterCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java index d55a5f3ed9..121fc5bc14 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -35,8 +34,9 @@ import org.apache.cloudstack.api.response.ZoneResponse; import com.cloud.network.router.VirtualRouter.Role; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "listRouters", description = "List routers.", responseObject = DomainRouterResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "listRouters", description = "List routers.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListRoutersCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/ListVirtualRouterElementsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/ListVirtualRouterElementsCmd.java index 62c6da5ee2..24bbf5ae2e 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/router/ListVirtualRouterElementsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/router/ListVirtualRouterElementsCmd.java @@ -44,7 +44,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVirtualRouterElementsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListNetworkOfferingsCmd.class.getName()); - private static final String Name = "listvirtualrouterelementsresponse"; + private static final String s_name = "listvirtualrouterelementsresponse"; // TODO, VirtualRouterElementServer is not singleton in system! @Inject @@ -95,7 +95,7 @@ public Boolean getEnabled() { @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java index 3a8938812b..4b138f3cfc 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/router/RebootRouterCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -35,8 +34,9 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.router.VirtualRouter; import com.cloud.user.Account; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "rebootRouter", description = "Starts a router.", responseObject = DomainRouterResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "rebootRouter", description = "Starts a router.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RebootRouterCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RebootRouterCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/StartRouterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/StartRouterCmd.java index f83466b1dc..173833cb42 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/router/StartRouterCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/router/StartRouterCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -37,8 +36,9 @@ import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VirtualRouter.Role; import com.cloud.user.Account; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "startRouter", responseObject = DomainRouterResponse.class, description = "Starts a router.", entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "startRouter", responseObject = DomainRouterResponse.class, description = "Starts a router.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StartRouterCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(StartRouterCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/StopRouterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/StopRouterCmd.java index e2d420073d..2592cae545 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/router/StopRouterCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/router/StopRouterCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -36,8 +35,9 @@ import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VirtualRouter.Role; import com.cloud.user.Account; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "stopRouter", description = "Stops a router.", responseObject = DomainRouterResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "stopRouter", description = "Stops a router.", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StopRouterCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(StopRouterCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/UpgradeRouterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/UpgradeRouterCmd.java index 0b67db9cef..067d344337 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/router/UpgradeRouterCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/router/UpgradeRouterCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -30,8 +29,9 @@ import com.cloud.network.router.VirtualRouter; import com.cloud.user.Account; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "changeServiceForRouter", description = "Upgrades domain router to a new service offering", responseObject = DomainRouterResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "changeServiceForRouter", description = "Upgrades domain router to a new service offering", responseObject = DomainRouterResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpgradeRouterCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(UpgradeRouterCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java index 8a82e89d7a..4164394f5e 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/storage/AddS3Cmd.java @@ -57,7 +57,7 @@ public final class AddS3Cmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(AddS3Cmd.class.getName()); - private static final String COMMAND_NAME = "adds3response"; + private static final String s_name = "adds3response"; @Parameter(name = S3_ACCESS_KEY, type = STRING, required = true, description = "S3 access key") private String accessKey; @@ -190,7 +190,7 @@ public int hashCode() { @Override public String getCommandName() { - return COMMAND_NAME; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/DestroySystemVmCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/DestroySystemVmCmd.java index bc977a456e..47dfe8b724 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/DestroySystemVmCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/DestroySystemVmCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -35,7 +34,7 @@ import com.cloud.user.Account; import com.cloud.vm.VirtualMachine; -@APICommand(name = "destroySystemVm", responseObject = SystemVmResponse.class, description = "Destroyes a system virtual machine.", entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "destroySystemVm", responseObject = SystemVmResponse.class, description = "Destroyes a system virtual machine.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DestroySystemVmCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DestroySystemVmCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/ListSystemVMsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/ListSystemVMsCmd.java index bfecd1857f..2b2faf5011 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/ListSystemVMsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/ListSystemVMsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,7 @@ import com.cloud.utils.Pair; import com.cloud.vm.VirtualMachine; -@APICommand(name = "listSystemVms", description = "List system virtual machines.", responseObject = SystemVmResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "listSystemVms", description = "List system virtual machines.", responseObject = SystemVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSystemVMsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListSystemVMsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/MigrateSystemVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/MigrateSystemVMCmd.java index 994635a1b7..97acfe0c46 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/MigrateSystemVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/MigrateSystemVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -41,7 +40,7 @@ import com.cloud.user.Account; import com.cloud.vm.VirtualMachine; -@APICommand(name = "migrateSystemVm", description = "Attempts Migration of a system virtual machine to the host specified.", responseObject = SystemVmResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "migrateSystemVm", description = "Attempts Migration of a system virtual machine to the host specified.", responseObject = SystemVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class MigrateSystemVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(MigrateSystemVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java index 0031d60351..f439ddf4de 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/RebootSystemVmCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -35,7 +34,7 @@ import com.cloud.user.Account; import com.cloud.vm.VirtualMachine; -@APICommand(name = "rebootSystemVm", description = "Reboots a system VM.", responseObject = SystemVmResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "rebootSystemVm", description = "Reboots a system VM.", responseObject = SystemVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RebootSystemVmCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RebootSystemVmCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java index f50b2c4b2c..68e9f94a8b 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/ScaleSystemVMCmd.java @@ -23,7 +23,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -48,7 +47,7 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "scaleSystemVm", responseObject = SystemVmResponse.class, description = "Scale the service offering for a system vm (console proxy or secondary storage). " - + "The system vm must be in a \"Stopped\" state for " + "this command to take effect.", entityType = {IAMEntityType.VirtualMachine}, + + "The system vm must be in a \"Stopped\" state for " + "this command to take effect.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ScaleSystemVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(UpgradeVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/StartSystemVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/StartSystemVMCmd.java index 6aecc9117c..c456592d10 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/StartSystemVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/StartSystemVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -35,7 +34,7 @@ import com.cloud.user.Account; import com.cloud.vm.VirtualMachine; -@APICommand(name = "startSystemVm", responseObject = SystemVmResponse.class, description = "Starts a system virtual machine.", entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "startSystemVm", responseObject = SystemVmResponse.class, description = "Starts a system virtual machine.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StartSystemVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(StartSystemVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/StopSystemVmCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/StopSystemVmCmd.java index 9a049c2afe..d60460ced1 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/StopSystemVmCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/StopSystemVmCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -37,7 +36,7 @@ import com.cloud.user.Account; import com.cloud.vm.VirtualMachine; -@APICommand(name = "stopSystemVm", description = "Stops a system VM.", responseObject = SystemVmResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "stopSystemVm", description = "Stops a system VM.", responseObject = SystemVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class StopSystemVmCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(StopSystemVmCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java index 033709aca4..d71ef03244 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/systemvm/UpgradeSystemVMCmd.java @@ -23,7 +23,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -43,7 +42,7 @@ import com.cloud.vm.VirtualMachine; @APICommand(name = "changeServiceForSystemVm", responseObject = SystemVmResponse.class, description = "Changes the service offering for a system vm (console proxy or secondary storage). " - + "The system vm must be in a \"Stopped\" state for " + "this command to take effect.", entityType = {IAMEntityType.VirtualMachine}, + + "The system vm must be in a \"Stopped\" state for " + "this command to take effect.", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpgradeSystemVMCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(UpgradeVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdmin.java b/api/src/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdmin.java index b2e9ef54e2..4e2bb018d0 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdmin.java +++ b/api/src/org/apache/cloudstack/api/command/admin/template/ListTemplatesCmdByAdmin.java @@ -16,13 +16,14 @@ // under the License. package org.apache.cloudstack.api.command.admin.template; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.command.user.template.ListTemplatesCmd; import org.apache.cloudstack.api.response.TemplateResponse; -@APICommand(name = "listTemplates", description = "List all public, private, and privileged templates.", responseObject = TemplateResponse.class, entityType = {IAMEntityType.VirtualMachineTemplate}, responseView = ResponseView.Full) +import com.cloud.template.VirtualMachineTemplate; + +@APICommand(name = "listTemplates", description = "List all public, private, and privileged templates.", responseObject = TemplateResponse.class, entityType = {VirtualMachineTemplate.class}, responseView = ResponseView.Full) public class ListTemplatesCmdByAdmin extends ListTemplatesCmd { } diff --git a/api/src/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java index ce432430e1..d4c26966d9 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/template/PrepareTemplateCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -35,7 +34,7 @@ import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; -@APICommand(name = "prepareTemplate", responseObject = TemplateResponse.class, description = "load template into primary storage", entityType = {IAMEntityType.VirtualMachineTemplate}, +@APICommand(name = "prepareTemplate", responseObject = TemplateResponse.class, description = "load template into primary storage", entityType = {VirtualMachineTemplate.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class PrepareTemplateCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(PrepareTemplateCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypeImplementorsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypeImplementorsCmd.java index a1ff29fd00..bd634bbe5c 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypeImplementorsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypeImplementorsCmd.java @@ -45,7 +45,7 @@ responseHasSensitiveInfo = false) public class ListTrafficTypeImplementorsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListTrafficTypeImplementorsCmd.class); - private static final String Name = "listtraffictypeimplementorsresponse"; + private static final String s_name = "listtraffictypeimplementorsresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -89,6 +89,6 @@ public long getEntityOwnerId() { @Override public String getCommandName() { - return Name; + return s_name; } } diff --git a/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java b/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java index 33ee29611d..fd0635959b 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/usage/ListTrafficTypesCmd.java @@ -38,7 +38,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListTrafficTypesCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListTrafficTypesCmd.class.getName()); - private static final String Name = "listtraffictypesresponse"; + private static final String s_name = "listtraffictypesresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -67,7 +67,7 @@ public Long getPhysicalNetworkId() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java index 51e218d7de..bd67436f6e 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/user/CreateUserCmd.java @@ -31,7 +31,7 @@ import com.cloud.user.User; @APICommand(name = "createUser", description = "Creates a user for an account that already exists", responseObject = UserResponse.class, - requestHasSensitiveInfo = true, responseHasSensitiveInfo = true) + requestHasSensitiveInfo = true, responseHasSensitiveInfo = true, entityType = { Account.class }) public class CreateUserCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateUserCmd.class.getName()); @@ -131,7 +131,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java index 08ba521ed6..f90a48043d 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/user/DeleteUserCmd.java @@ -35,7 +35,7 @@ import com.cloud.user.User; @APICommand(name = "deleteUser", description = "Deletes a user for an account", responseObject = SuccessResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, entityType = { Account.class }) public class DeleteUserCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(DeleteUserCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java index c6e09ef0f9..3a9676e246 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/user/DisableUserCmd.java @@ -37,7 +37,7 @@ import com.cloud.user.UserAccount; @APICommand(name = "disableUser", description = "Disables a user account", responseObject = UserResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) + requestHasSensitiveInfo = false, responseHasSensitiveInfo = true, entityType = { Account.class }) public class DisableUserCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DisableUserCmd.class.getName()); private static final String s_name = "disableuserresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java index d69eccf934..e4f4477103 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/user/EnableUserCmd.java @@ -35,7 +35,7 @@ import com.cloud.user.UserAccount; @APICommand(name = "enableUser", description = "Enables a user account", responseObject = UserResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) + requestHasSensitiveInfo = false, responseHasSensitiveInfo = true, entityType = { Account.class }) public class EnableUserCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(EnableUserCmd.class.getName()); private static final String s_name = "enableuserresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/GetUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/GetUserCmd.java index b2c6734c9e..f8c7589e78 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/user/GetUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/user/GetUserCmd.java @@ -25,10 +25,11 @@ import org.apache.cloudstack.api.response.UserResponse; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.user.Account; import com.cloud.user.UserAccount; @APICommand(name = "getUser", description = "Find user account by API key", responseObject = UserResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) + requestHasSensitiveInfo = false, responseHasSensitiveInfo = true, entityType = { Account.class }) public class GetUserCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(GetUserCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/ListUsersCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/ListUsersCmd.java index c0c2b24814..14cbb26602 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/user/ListUsersCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/user/ListUsersCmd.java @@ -25,8 +25,10 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.UserResponse; +import com.cloud.user.Account; + @APICommand(name = "listUsers", description = "Lists user accounts", responseObject = UserResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) + requestHasSensitiveInfo = false, responseHasSensitiveInfo = true, entityType = { Account.class }) public class ListUsersCmd extends BaseListAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListUsersCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java b/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java index cf5d355e26..46b01aa3b7 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java @@ -35,7 +35,7 @@ import com.cloud.user.UserAccount; @APICommand(name = "updateUser", description = "Updates a user account", responseObject = UserResponse.class, - requestHasSensitiveInfo = true, responseHasSensitiveInfo = true) + requestHasSensitiveInfo = true, responseHasSensitiveInfo = true, entityType = { Account.class }) public class UpdateUserCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(UpdateUserCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/AddNicToVMCmdByAdmin.java b/api/src/org/apache/cloudstack/api/command/admin/vm/AddNicToVMCmdByAdmin.java index 996d1bd49e..ee6d0e78e0 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vm/AddNicToVMCmdByAdmin.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vm/AddNicToVMCmdByAdmin.java @@ -32,8 +32,8 @@ import com.cloud.uservm.UserVm; -@APICommand(name = "addNicToVirtualMachine", description = "Adds VM to specified network by creating a NIC", responseObject = UserVmResponse.class, responseView = ResponseView.Full) - +@APICommand(name = "addNicToVirtualMachine", description = "Adds VM to specified network by creating a NIC", responseObject = UserVmResponse.class, responseView = ResponseView.Full, + requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class AddNicToVMCmdByAdmin extends AddNicToVMCmd { public static final Logger s_logger = Logger.getLogger(AddNicToVMCmdByAdmin.class); diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java index dd84ec2a60..435b7f1848 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vm/AssignVMCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -35,11 +34,12 @@ import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; @APICommand(name = "assignVirtualMachine", description = "Change ownership of a VM from one account to another. This API is available for Basic zones with security groups and Advanced zones with guest networks. A root administrator can reassign a VM from any account to any other account in any domain. A domain administrator can reassign a VM to any account in the same domain.", responseObject = UserVmResponse.class, - since = "3.0.0", entityType = {IAMEntityType.VirtualMachine}, + since = "3.0.0", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class AssignVMCmd extends BaseCmd { diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/ExpungeVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vm/ExpungeVMCmd.java index 623ddb6779..40b9bb8256 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vm/ExpungeVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vm/ExpungeVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,8 +38,9 @@ import com.cloud.user.Account; import com.cloud.uservm.UserVm; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "expungeVirtualMachine", description = "Expunge a virtual machine. Once expunged, it cannot be recoverd.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "expungeVirtualMachine", description = "Expunge a virtual machine. Once expunged, it cannot be recoverd.", responseObject = SuccessResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ExpungeVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(ExpungeVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVMCmd.java index fe8446859c..ef9619effa 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -45,7 +44,7 @@ @APICommand(name = "migrateVirtualMachine", description = "Attempts Migration of a VM to a different host or Root volume of the vm to a different storage pool", - responseObject = UserVmResponse.class, entityType = {IAMEntityType.VirtualMachine}, + responseObject = UserVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class MigrateVMCmd extends BaseAsyncCmd { diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java index b5d1ae9315..f1d3fe975f 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java @@ -23,7 +23,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -47,7 +46,7 @@ @APICommand(name = "migrateVirtualMachineWithVolume", description = "Attempts Migration of a VM with its volumes to a different host", - responseObject = UserVmResponse.class, entityType = {IAMEntityType.VirtualMachine}, + responseObject = UserVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class MigrateVirtualMachineWithVolumeCmd extends BaseAsyncCmd { diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/RecoverVMCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vm/RecoverVMCmd.java index e7fbbdb784..4ad0917154 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vm/RecoverVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vm/RecoverVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -31,8 +30,9 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "recoverVirtualMachine", description = "Recovers a virtual machine.", responseObject = UserVmResponse.class, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "recoverVirtualMachine", description = "Recovers a virtual machine.", responseObject = UserVmResponse.class, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class RecoverVMCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(RecoverVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayCmd.java index ff88ada781..01db44e25d 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vpc/CreatePrivateGatewayCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -41,9 +40,10 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.vpc.PrivateGateway; import com.cloud.network.vpc.Vpc; +import com.cloud.network.vpc.VpcGateway; import com.cloud.user.Account; -@APICommand(name = "createPrivateGateway", description = "Creates a private gateway", responseObject = PrivateGatewayResponse.class, entityType = {IAMEntityType.PrivateGateway}, +@APICommand(name = "createPrivateGateway", description = "Creates a private gateway", responseObject = PrivateGatewayResponse.class, entityType = {VpcGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreatePrivateGatewayCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java index 5b3090bd75..13e4c0e04b 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vpc/CreateVPCOfferingCmd.java @@ -43,7 +43,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateVPCOfferingCmd.class.getName()); - private static final String Name = "createvpcofferingresponse"; + private static final String s_name = "createvpcofferingresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -66,7 +66,7 @@ public class CreateVPCOfferingCmd extends BaseAsyncCreateCmd { + "If not specified, the provider for the service will be mapped to the default provider on the physical network") private Map serviceProviderList; - @Parameter(name = ApiConstants.SERVICE_CAPABILITY_LIST, type = CommandType.MAP, description = "desired service capabilities as part of vpc offering") + @Parameter(name = ApiConstants.SERVICE_CAPABILITY_LIST, type = CommandType.MAP, description = "desired service capabilities as part of vpc offering", since = "4.4") private Map serviceCapabilitystList; @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, @@ -159,7 +159,7 @@ public String getEventDescription() { @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/admin/vpc/DeletePrivateGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vpc/DeletePrivateGatewayCmd.java index dcce58e227..8d67a4ed8c 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/vpc/DeletePrivateGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/vpc/DeletePrivateGatewayCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,7 @@ import com.cloud.network.vpc.VpcGateway; import com.cloud.user.Account; -@APICommand(name = "deletePrivateGateway", description = "Deletes a Private gateway", responseObject = SuccessResponse.class, entityType = {IAMEntityType.PrivateGateway}, +@APICommand(name = "deletePrivateGateway", description = "Deletes a Private gateway", responseObject = SuccessResponse.class, entityType = {VpcGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeletePrivateGatewayCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeletePrivateGatewayCmd.class.getName()); 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 8b05a7a5a2..5af47d3a4c 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 @@ -34,7 +34,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVPCOfferingCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(UpdateVPCOfferingCmd.class.getName()); - private static final String Name = "updatevpcofferingresponse"; + private static final String s_name = "updatevpcofferingresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -77,7 +77,7 @@ public String getState() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java b/api/src/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java index 65331e4c4a..0b5ae7c0ba 100644 --- a/api/src/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/account/ListAccountsCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListDomainResourcesCmd; @@ -27,7 +26,9 @@ import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.ListResponse; -@APICommand(name = "listAccounts", description = "Lists accounts and provides detailed account information for listed accounts", responseObject = AccountResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.Account}, +import com.cloud.user.Account; + +@APICommand(name = "listAccounts", description = "Lists accounts and provides detailed account information for listed accounts", responseObject = AccountResponse.class, responseView = ResponseView.Restricted, entityType = {Account.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ListAccountsCmd extends BaseListDomainResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListAccountsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java index 3f0d2467bf..091229f681 100644 --- a/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java @@ -58,6 +58,7 @@ import com.cloud.user.Account; @APICommand(name = "associateIpAddress", description = "Acquires and associates a public IP to an account.", responseObject = IPAddressResponse.class, responseView = ResponseView.Restricted, + entityType = {IpAddress.class, Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(AssociateIPAddrCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java index 269fcb552b..ba4184434e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java @@ -37,7 +37,7 @@ import com.cloud.user.Account; @APICommand(name = "disassociateIpAddress", description = "Disassociates an ip address from the account.", responseObject = SuccessResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, entityType = { IpAddress.class }) public class DisassociateIPAddrCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DisassociateIPAddrCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/address/ListPublicIpAddressesCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/ListPublicIpAddressesCmd.java index 321871380d..07ccfe9918 100644 --- a/api/src/org/apache/cloudstack/api/command/user/address/ListPublicIpAddressesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/address/ListPublicIpAddressesCmd.java @@ -40,7 +40,7 @@ import com.cloud.utils.Pair; @APICommand(name = "listPublicIpAddresses", description = "Lists all public ip addresses", responseObject = IPAddressResponse.class, responseView = ResponseView.Restricted, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, entityType = { IpAddress.class }) public class ListPublicIpAddressesCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListPublicIpAddressesCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/address/UpdateIPAddrCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/UpdateIPAddrCmd.java index cc736d0d64..99bb1afd5f 100644 --- a/api/src/org/apache/cloudstack/api/command/user/address/UpdateIPAddrCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/address/UpdateIPAddrCmd.java @@ -39,7 +39,7 @@ import com.cloud.user.Account; @APICommand(name = "updatePublicIpAddress", description = "Updates an ip address", responseObject = IPAddressResponse.class, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) + requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, entityType = { IpAddress.class }) public class UpdateIPAddrCmd extends BaseAsyncCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdateIPAddrCmd.class.getName()); private static final String s_name = "updateipaddressresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java index 50573e9683..96d8bec96d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.APICommand; @@ -35,7 +34,7 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.user.Account; -@APICommand(name = "createAffinityGroup", responseObject = AffinityGroupResponse.class, description = "Creates an affinity/anti-affinity group", entityType = {IAMEntityType.AffinityGroup}, +@APICommand(name = "createAffinityGroup", responseObject = AffinityGroupResponse.class, description = "Creates an affinity/anti-affinity group", entityType = {AffinityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateAffinityGroupCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateAffinityGroupCmd.class.getName()); @@ -103,7 +102,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { 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 378a826ef8..21c2fa86d0 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 @@ -19,8 +19,8 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -38,7 +38,7 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.user.Account; -@APICommand(name = "deleteAffinityGroup", description = "Deletes affinity group", responseObject = SuccessResponse.class, entityType = {IAMEntityType.AffinityGroup}, +@APICommand(name = "deleteAffinityGroup", description = "Deletes affinity group", responseObject = SuccessResponse.class, entityType = {AffinityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAffinityGroupCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteAffinityGroupCmd.class.getName()); @@ -110,7 +110,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java index e469eab2c1..6313c4812e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java @@ -18,7 +18,7 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; +import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; @@ -28,7 +28,7 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.UserVmResponse; -@APICommand(name = "listAffinityGroups", description = "Lists affinity groups", responseObject = AffinityGroupResponse.class, entityType = {IAMEntityType.AffinityGroup}, +@APICommand(name = "listAffinityGroups", description = "Lists affinity groups", responseObject = AffinityGroupResponse.class, entityType = {AffinityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListAffinityGroupsCmd extends BaseListAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListAffinityGroupsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java index 4bfcddb3a6..66201477b9 100644 --- a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java @@ -22,7 +22,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.ACL; @@ -44,13 +43,14 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; @APICommand(name = "updateVMAffinityGroup", description = "Updates the affinity/anti-affinity group associations of a virtual machine. The VM has to be stopped and restarted for the " + "new properties to take effect.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, - entityType = {IAMEntityType.VirtualMachine}, + entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpdateVMAffinityGroupCmd extends BaseAsyncCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java index 8b5708d072..4541efa798 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScalePolicyCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -40,7 +39,7 @@ @APICommand(name = "createAutoScalePolicy", description = "Creates an autoscale policy for a provision or deprovision action, the action is taken when the all the conditions evaluates to true for the specified duration. The policy is in effect once it is attached to a autscale vm group.", - responseObject = AutoScalePolicyResponse.class, entityType = {IAMEntityType.AutoScalePolicy}, + responseObject = AutoScalePolicyResponse.class, entityType = {AutoScalePolicy.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateAutoScalePolicyCmd extends BaseAsyncCreateCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java index 43a7f18189..1fd0029e34 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmGroupCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; @@ -42,7 +41,7 @@ @APICommand(name = "createAutoScaleVmGroup", description = "Creates and automatically starts a virtual machine based on a service offering, disk offering, and template.", - responseObject = AutoScaleVmGroupResponse.class, entityType = { IAMEntityType.AutoScaleVmGroup }, + responseObject = AutoScaleVmGroupResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateAutoScaleVmGroupCmd extends BaseAsyncCreateCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java index 5d78593832..189217a202 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateAutoScaleVmProfileCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; @@ -46,7 +45,7 @@ @APICommand(name = "createAutoScaleVmProfile", description = "Creates a profile that contains information about the virtual machine which will be provisioned automatically by autoscale feature.", - responseObject = AutoScaleVmProfileResponse.class, entityType = { IAMEntityType.AutoScaleVmProfile }, + responseObject = AutoScaleVmProfileResponse.class, entityType = {AutoScaleVmProfile.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) @SuppressWarnings("rawtypes") diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java index b603a152d5..847866ef3a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/CreateConditionCmd.java @@ -19,7 +19,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,7 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.network.as.Condition; -@APICommand(name = "createCondition", description = "Creates a condition", responseObject = ConditionResponse.class, entityType = {IAMEntityType.Condition}, +@APICommand(name = "createCondition", description = "Creates a condition", responseObject = ConditionResponse.class, entityType = {Condition.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateConditionCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateConditionCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScalePolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScalePolicyCmd.java index 779ee0a392..c0a3a00f7d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScalePolicyCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScalePolicyCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.network.as.AutoScalePolicy; import com.cloud.user.Account; -@APICommand(name = "deleteAutoScalePolicy", description = "Deletes a autoscale policy.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.AutoScalePolicy}, +@APICommand(name = "deleteAutoScalePolicy", description = "Deletes a autoscale policy.", responseObject = SuccessResponse.class, entityType = {AutoScalePolicy.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAutoScalePolicyCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteAutoScalePolicyCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmGroupCmd.java index 5a43abe866..a9d2f4e232 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmGroupCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.network.as.AutoScaleVmGroup; import com.cloud.user.Account; -@APICommand(name = "deleteAutoScaleVmGroup", description = "Deletes a autoscale vm group.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.AutoScaleVmGroup}, +@APICommand(name = "deleteAutoScaleVmGroup", description = "Deletes a autoscale vm group.", responseObject = SuccessResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAutoScaleVmGroupCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteAutoScaleVmGroupCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmProfileCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmProfileCmd.java index 2391a938d8..779315a96d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmProfileCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteAutoScaleVmProfileCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.network.as.AutoScaleVmProfile; import com.cloud.user.Account; -@APICommand(name = "deleteAutoScaleVmProfile", description = "Deletes a autoscale vm profile.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.AutoScaleVmProfile}, +@APICommand(name = "deleteAutoScaleVmProfile", description = "Deletes a autoscale vm profile.", responseObject = SuccessResponse.class, entityType = {AutoScaleVmProfile.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteAutoScaleVmProfileCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteAutoScaleVmProfileCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteConditionCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteConditionCmd.java index 9a7d2d7df8..24f4cc6878 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteConditionCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/DeleteConditionCmd.java @@ -19,7 +19,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -37,7 +36,7 @@ import com.cloud.network.as.Condition; import com.cloud.user.Account; -@APICommand(name = "deleteCondition", description = "Removes a condition", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Condition}, +@APICommand(name = "deleteCondition", description = "Removes a condition", responseObject = SuccessResponse.class, entityType = {Condition.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteConditionCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteConditionCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/DisableAutoScaleVmGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/DisableAutoScaleVmGroupCmd.java index 6575d27ba7..8eb1809f88 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/DisableAutoScaleVmGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/DisableAutoScaleVmGroupCmd.java @@ -19,7 +19,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -35,7 +34,7 @@ import com.cloud.network.as.AutoScaleVmGroup; import com.cloud.user.Account; -@APICommand(name = "disableAutoScaleVmGroup", description = "Disables an AutoScale Vm Group", responseObject = AutoScaleVmGroupResponse.class, entityType = {IAMEntityType.AutoScaleVmGroup}, +@APICommand(name = "disableAutoScaleVmGroup", description = "Disables an AutoScale Vm Group", responseObject = AutoScaleVmGroupResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DisableAutoScaleVmGroupCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DisableAutoScaleVmGroupCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/EnableAutoScaleVmGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/EnableAutoScaleVmGroupCmd.java index 6b9f2c3ac0..59c9f7a9aa 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/EnableAutoScaleVmGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/EnableAutoScaleVmGroupCmd.java @@ -19,7 +19,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -35,7 +34,7 @@ import com.cloud.network.as.AutoScaleVmGroup; import com.cloud.user.Account; -@APICommand(name = "enableAutoScaleVmGroup", description = "Enables an AutoScale Vm Group", responseObject = AutoScaleVmGroupResponse.class, entityType = {IAMEntityType.AutoScaleVmGroup}, +@APICommand(name = "enableAutoScaleVmGroup", description = "Enables an AutoScale Vm Group", responseObject = AutoScaleVmGroupResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class EnableAutoScaleVmGroupCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(EnableAutoScaleVmGroupCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScalePoliciesCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScalePoliciesCmd.java index 43c4c72a80..c2b244f2a7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScalePoliciesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScalePoliciesCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListAccountResourcesCmd; @@ -33,7 +32,7 @@ import com.cloud.network.as.AutoScalePolicy; -@APICommand(name = "listAutoScalePolicies", description = "Lists autoscale policies.", responseObject = AutoScalePolicyResponse.class, entityType = {IAMEntityType.AutoScalePolicy}, +@APICommand(name = "listAutoScalePolicies", description = "Lists autoscale policies.", responseObject = AutoScalePolicyResponse.class, entityType = {AutoScalePolicy.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListAutoScalePoliciesCmd extends BaseListAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListAutoScalePoliciesCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmGroupsCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmGroupsCmd.java index 2e88c27b7d..37c90b9bfd 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmGroupsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmGroupsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,7 +36,7 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.as.AutoScaleVmGroup; -@APICommand(name = "listAutoScaleVmGroups", description = "Lists autoscale vm groups.", responseObject = AutoScaleVmGroupResponse.class, entityType = { IAMEntityType.AutoScaleVmGroup }, +@APICommand(name = "listAutoScaleVmGroups", description = "Lists autoscale vm groups.", responseObject = AutoScaleVmGroupResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListAutoScaleVmGroupsCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListAutoScaleVmGroupsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmProfilesCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmProfilesCmd.java index 94f0eee7f5..554b48854a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmProfilesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListAutoScaleVmProfilesCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,7 @@ import com.cloud.network.as.AutoScaleVmProfile; -@APICommand(name = "listAutoScaleVmProfiles", description = "Lists autoscale vm profiles.", responseObject = AutoScaleVmProfileResponse.class, entityType = { IAMEntityType.AutoScaleVmProfile }, +@APICommand(name = "listAutoScaleVmProfiles", description = "Lists autoscale vm profiles.", responseObject = AutoScaleVmProfileResponse.class, entityType = {AutoScaleVmProfile.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListAutoScaleVmProfilesCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListAutoScaleVmProfilesCmd.class.getName()); @@ -52,7 +51,7 @@ public class ListAutoScaleVmProfilesCmd extends BaseListProjectAndAccountResourc @Parameter(name = ApiConstants.TEMPLATE_ID, type = CommandType.UUID, entityType = TemplateResponse.class, description = "the templateid of the autoscale vm profile") private Long templateId; - @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, type = CommandType.UUID, entityType = ServiceOfferingResponse.class, description = "list profiles by service offering id") + @Parameter(name = ApiConstants.SERVICE_OFFERING_ID, type = CommandType.UUID, entityType = ServiceOfferingResponse.class, description = "list profiles by service offering id", since = "4.4") private Long serviceOffId; @Parameter(name = ApiConstants.OTHER_DEPLOY_PARAMS, type = CommandType.STRING, description = "the otherdeployparameters of the autoscale vm profile") diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScalePolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScalePolicyCmd.java index 8cd7211a2f..24858f4656 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScalePolicyCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScalePolicyCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,7 +38,7 @@ import com.cloud.network.as.AutoScalePolicy; import com.cloud.user.Account; -@APICommand(name = "updateAutoScalePolicy", description = "Updates an existing autoscale policy.", responseObject = AutoScalePolicyResponse.class, entityType = {IAMEntityType.AutoScalePolicy}, +@APICommand(name = "updateAutoScalePolicy", description = "Updates an existing autoscale policy.", responseObject = AutoScalePolicyResponse.class, entityType = {AutoScalePolicy.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateAutoScalePolicyCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(UpdateAutoScalePolicyCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmGroupCmd.java index 60ea51efc9..76fa3d75d1 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmGroupCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -40,7 +39,7 @@ import com.cloud.network.as.AutoScaleVmGroup; import com.cloud.user.Account; -@APICommand(name = "updateAutoScaleVmGroup", description = "Updates an existing autoscale vm group.", responseObject = AutoScaleVmGroupResponse.class, entityType = { IAMEntityType.AutoScaleVmGroup }, +@APICommand(name = "updateAutoScaleVmGroup", description = "Updates an existing autoscale vm group.", responseObject = AutoScaleVmGroupResponse.class, entityType = {AutoScaleVmGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateAutoScaleVmGroupCmd extends BaseAsyncCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdateAutoScaleVmGroupCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmProfileCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmProfileCmd.java index 54e34da196..deebe2ecc9 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmProfileCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/UpdateAutoScaleVmProfileCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -41,7 +40,7 @@ import com.cloud.network.as.AutoScaleVmProfile; import com.cloud.user.Account; -@APICommand(name = "updateAutoScaleVmProfile", description = "Updates an existing autoscale vm profile.", responseObject = AutoScaleVmProfileResponse.class, entityType = { IAMEntityType.AutoScaleVmProfile }, +@APICommand(name = "updateAutoScaleVmProfile", description = "Updates an existing autoscale vm profile.", responseObject = AutoScaleVmProfileResponse.class, entityType = {AutoScaleVmProfile.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateAutoScaleVmProfileCmd extends BaseAsyncCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdateAutoScaleVmProfileCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java b/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java index d47645b956..e6696e17ff 100644 --- a/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/config/ListCapabilitiesCmd.java @@ -53,6 +53,7 @@ public void execute() { response.setSupportELB((String)capabilities.get("supportELB")); response.setProjectInviteRequired((Boolean)capabilities.get("projectInviteRequired")); response.setAllowUsersCreateProjects((Boolean)capabilities.get("allowusercreateprojects")); + response.setDiskOffMinSize((Long)capabilities.get("customDiskOffMinSize")); response.setDiskOffMaxSize((Long)capabilities.get("customDiskOffMaxSize")); response.setRegionSecondaryEnabled((Boolean)capabilities.get("regionSecondaryEnabled")); response.setKVMSnapshotEnabled((Boolean)capabilities.get("KVMSnapshotEnabled")); diff --git a/api/src/org/apache/cloudstack/api/command/user/event/ArchiveEventsCmd.java b/api/src/org/apache/cloudstack/api/command/user/event/ArchiveEventsCmd.java index 8ff2c3e445..e4970d6530 100644 --- a/api/src/org/apache/cloudstack/api/command/user/event/ArchiveEventsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/event/ArchiveEventsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -32,10 +31,11 @@ import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.context.CallContext; +import com.cloud.event.Event; import com.cloud.exception.InvalidParameterValueException; import com.cloud.user.Account; -@APICommand(name = "archiveEvents", description = "Archive one or more events.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Event}, +@APICommand(name = "archiveEvents", description = "Archive one or more events.", responseObject = SuccessResponse.class, entityType = {Event.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ArchiveEventsCmd extends BaseCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/event/DeleteEventsCmd.java b/api/src/org/apache/cloudstack/api/command/user/event/DeleteEventsCmd.java index 10c1c0c860..defb009696 100644 --- a/api/src/org/apache/cloudstack/api/command/user/event/DeleteEventsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/event/DeleteEventsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -32,10 +31,11 @@ import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.context.CallContext; +import com.cloud.event.Event; import com.cloud.exception.InvalidParameterValueException; import com.cloud.user.Account; -@APICommand(name = "deleteEvents", description = "Delete one or more events.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Event}, +@APICommand(name = "deleteEvents", description = "Delete one or more events.", responseObject = SuccessResponse.class, entityType = {Event.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteEventsCmd extends BaseCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/event/ListEventsCmd.java b/api/src/org/apache/cloudstack/api/command/user/event/ListEventsCmd.java index b420cf1ed2..a4934fa1dd 100644 --- a/api/src/org/apache/cloudstack/api/command/user/event/ListEventsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/event/ListEventsCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; @@ -28,7 +27,9 @@ import org.apache.cloudstack.api.response.EventResponse; import org.apache.cloudstack.api.response.ListResponse; -@APICommand(name = "listEvents", description = "A command to list events.", responseObject = EventResponse.class, entityType = {IAMEntityType.Event}, +import com.cloud.event.Event; + +@APICommand(name = "listEvents", description = "A command to list events.", responseObject = EventResponse.class, entityType = {Event.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListEventsCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListEventsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java index 8ef1b89518..579cccbfb2 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java @@ -22,7 +22,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; @@ -45,7 +44,7 @@ import com.cloud.user.Account; import com.cloud.utils.net.NetUtils; -@APICommand(name = "createEgressFirewallRule", description = "Creates a egress firewall rule for a given network ", responseObject = FirewallResponse.class, entityType = { IAMEntityType.FirewallRule }, +@APICommand(name = "createEgressFirewallRule", description = "Creates a egress firewall rule for a given network ", responseObject = FirewallResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateEgressFirewallRuleCmd extends BaseAsyncCreateCmd implements FirewallRule { public static final Logger s_logger = Logger.getLogger(CreateEgressFirewallRuleCmd.class.getName()); @@ -357,8 +356,8 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.FirewallRule; + public Class getEntityType() { + return FirewallRule.class; } } diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java index 21e680ae62..b09d3a73a7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; @@ -44,7 +43,7 @@ import com.cloud.user.Account; import com.cloud.utils.net.NetUtils; -@APICommand(name = "createFirewallRule", description = "Creates a firewall rule for a given ip address", responseObject = FirewallResponse.class, entityType = { IAMEntityType.FirewallRule }, +@APICommand(name = "createFirewallRule", description = "Creates a firewall rule for a given ip address", responseObject = FirewallResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateFirewallRuleCmd extends BaseAsyncCreateCmd implements FirewallRule { public static final Logger s_logger = Logger.getLogger(CreateFirewallRuleCmd.class.getName()); @@ -350,8 +349,8 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.FirewallRule; + public Class getEntityType() { + return FirewallRule.class; } } diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java index 7328374f5c..f18767e1da 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; @@ -41,12 +40,15 @@ import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.IpAddress; +import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.PortForwardingRule; import com.cloud.user.Account; import com.cloud.utils.net.Ip; import com.cloud.utils.net.NetUtils; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "createPortForwardingRule", description = "Creates a port forwarding rule", responseObject = FirewallRuleResponse.class, entityType = { IAMEntityType.PortForwardingRule }, +@APICommand(name = "createPortForwardingRule", description = "Creates a port forwarding rule", responseObject = FirewallRuleResponse.class, entityType = {FirewallRule.class, + VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements PortForwardingRule { public static final Logger s_logger = Logger.getLogger(CreatePortForwardingRuleCmd.class.getName()); @@ -432,8 +434,8 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.FirewallRule; + public Class getEntityType() { + return FirewallRule.class; } } diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteEgressFirewallRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteEgressFirewallRuleCmd.java index ebed335ba3..4d227722f8 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteEgressFirewallRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteEgressFirewallRuleCmd.java @@ -19,7 +19,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,7 +38,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.rules.FirewallRule; -@APICommand(name = "deleteEgressFirewallRule", description = "Deletes an ggress firewall rule", responseObject = SuccessResponse.class, entityType = {IAMEntityType.FirewallRule}, +@APICommand(name = "deleteEgressFirewallRule", description = "Deletes an ggress firewall rule", responseObject = SuccessResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteEgressFirewallRuleCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteEgressFirewallRuleCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java index 3f61e640c8..66dcc039c3 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/DeleteFirewallRuleCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -38,7 +37,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.rules.FirewallRule; -@APICommand(name = "deleteFirewallRule", description = "Deletes a firewall rule", responseObject = SuccessResponse.class, entityType = {IAMEntityType.FirewallRule}, +@APICommand(name = "deleteFirewallRule", description = "Deletes a firewall rule", responseObject = SuccessResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteFirewallRuleCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteFirewallRuleCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java index 551885d017..4c7b07f14f 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/DeletePortForwardingRuleCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -37,7 +36,7 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.rules.PortForwardingRule; -@APICommand(name = "deletePortForwardingRule", description = "Deletes a port forwarding rule", responseObject = SuccessResponse.class, entityType = {IAMEntityType.PortForwardingRule}, +@APICommand(name = "deletePortForwardingRule", description = "Deletes a port forwarding rule", responseObject = SuccessResponse.class, entityType = {PortForwardingRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeletePortForwardingRuleCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeletePortForwardingRuleCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/ListEgressFirewallRulesCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/ListEgressFirewallRulesCmd.java index ece2201a89..e31496e474 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/ListEgressFirewallRulesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/ListEgressFirewallRulesCmd.java @@ -22,7 +22,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.Parameter; @@ -34,7 +33,7 @@ import com.cloud.network.rules.FirewallRule; import com.cloud.utils.Pair; -@APICommand(name = "listEgressFirewallRules", description = "Lists all egress firewall rules for network id.", responseObject = FirewallResponse.class, entityType = { IAMEntityType.FirewallRule }, +@APICommand(name = "listEgressFirewallRules", description = "Lists all egress firewall rules for network id.", responseObject = FirewallResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListEgressFirewallRulesCmd extends ListFirewallRulesCmd { public static final Logger s_logger = Logger.getLogger(ListEgressFirewallRulesCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java index 870f81d914..9c9fbc8397 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/ListFirewallRulesCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,7 @@ import com.cloud.network.rules.FirewallRule; import com.cloud.utils.Pair; -@APICommand(name = "listFirewallRules", description = "Lists all firewall rules for an IP address.", responseObject = FirewallResponse.class, entityType = {IAMEntityType.FirewallRule}, +@APICommand(name = "listFirewallRules", description = "Lists all firewall rules for an IP address.", responseObject = FirewallResponse.class, entityType = {FirewallRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListFirewallRulesCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListFirewallRulesCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/ListPortForwardingRulesCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/ListPortForwardingRulesCmd.java index 681da333f0..cde2563f9a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/ListPortForwardingRulesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/ListPortForwardingRulesCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,7 @@ import com.cloud.network.rules.PortForwardingRule; import com.cloud.utils.Pair; -@APICommand(name = "listPortForwardingRules", description = "Lists all port forwarding rules for an IP address.", responseObject = FirewallRuleResponse.class, entityType = {IAMEntityType.PortForwardingRule}, +@APICommand(name = "listPortForwardingRules", description = "Lists all port forwarding rules for an IP address.", responseObject = FirewallRuleResponse.class, entityType = {PortForwardingRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListPortForwardingRulesCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListPortForwardingRulesCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java index 55b378a21a..78525ba0d8 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/UpdatePortForwardingRuleCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -38,7 +37,7 @@ @APICommand(name = "updatePortForwardingRule", responseObject = FirewallRuleResponse.class, - description = "Updates a port forwarding rule. Only the private port and the virtual machine can be updated.", entityType = {IAMEntityType.PortForwardingRule}, + description = "Updates a port forwarding rule. Only the private port and the virtual machine can be updated.", entityType = {PortForwardingRule.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdatePortForwardingRuleCmd extends BaseAsyncCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdatePortForwardingRuleCmd.class.getName()); @@ -47,7 +46,7 @@ public class UpdatePortForwardingRuleCmd extends BaseAsyncCustomIdCmd { ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = FirewallRuleResponse.class, required = true, description = "the ID of the port forwarding rule") + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = FirewallRuleResponse.class, required = true, description = "the ID of the port forwarding rule", since = "4.4") private Long id; @Parameter(name = ApiConstants.PRIVATE_IP, type = CommandType.STRING, description = "the private IP address of the port forwarding rule") diff --git a/api/src/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java b/api/src/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java index 21196bcb65..9002624c48 100644 --- a/api/src/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/iso/CopyIsoCmd.java @@ -19,10 +19,11 @@ import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.command.user.template.CopyTemplateCmd; import org.apache.cloudstack.api.response.TemplateResponse; -@APICommand(name = "copyIso", description = "Copies an iso from one zone to another.", responseObject = TemplateResponse.class, +@APICommand(name = "copyIso", description = "Copies an iso from one zone to another.", responseObject = TemplateResponse.class, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CopyIsoCmd extends CopyTemplateCmd { public static final Logger s_logger = Logger.getLogger(CopyIsoCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java b/api/src/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java index 3aabf926fc..88e4326c7d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/iso/ListIsosCmd.java @@ -121,7 +121,7 @@ public Boolean getShowRemoved() { public boolean listInReadyState() { Account account = CallContext.current().getCallingAccount(); // It is account specific if account is admin type and domainId and accountName are not null - boolean isAccountSpecific = (account == null || _accountService.isAdmin(account.getType())) && (getAccountName() != null) && (getDomainId() != null); + boolean isAccountSpecific = (account == null || _accountService.isAdmin(account.getId())) && (getAccountName() != null) && (getDomainId() != null); // Show only those that are downloaded. TemplateFilter templateFilter = TemplateFilter.valueOf(getIsoFilter()); boolean onlyReady = diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java index 6bd7537827..db4d70e685 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java @@ -16,10 +16,18 @@ // under the License. package org.apache.cloudstack.api.command.user.loadbalancer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.Map; +import com.cloud.utils.net.NetUtils; import org.apache.log4j.Logger; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -33,13 +41,15 @@ import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.LoadBalancer; import com.cloud.user.Account; import com.cloud.utils.StringUtils; +import com.cloud.vm.VirtualMachine; @APICommand(name = "assignToLoadBalancerRule", description = "Assigns virtual machine or a list of virtual machines to a load balancer rule.", - responseObject = SuccessResponse.class, + responseObject = SuccessResponse.class, entityType = {FirewallRule.class, VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd { @@ -51,6 +61,7 @@ public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// + @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = FirewallRuleResponse.class, @@ -58,14 +69,20 @@ public class AssignToLoadBalancerRuleCmd extends BaseAsyncCmd { description = "the ID of the load balancer rule") private Long id; + @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.VIRTUAL_MACHINE_IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = UserVmResponse.class, - required = true, description = "the list of IDs of the virtual machine that are being assigned to the load balancer rule(i.e. virtualMachineIds=1,2,3)") private List virtualMachineIds; + @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID_IP, + type = CommandType.MAP, + description = "VM ID and IP map, vmidipmap[0].vmid=1 vmidipmap[0].ip=10.1.1.75", + since = "4.4") + private Map vmIdIpMap; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -78,6 +95,10 @@ public List getVirtualMachineIds() { return virtualMachineIds; } + public Map getVmIdIpMap() { + return vmIdIpMap; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -106,13 +127,54 @@ public String getEventDescription() { return "applying instances for load balancer: " + getLoadBalancerId() + " (ids: " + StringUtils.join(getVirtualMachineIds(), ",") + ")"; } + + public Map> getVmIdIpListMap() { + Map> vmIdIpsMap = new HashMap>(); + if (vmIdIpMap != null && !vmIdIpMap.isEmpty()) { + Collection idIpsCollection = vmIdIpMap.values(); + Iterator iter = idIpsCollection.iterator(); + while (iter.hasNext()) { + HashMap idIpsMap = (HashMap)iter.next(); + String vmId = idIpsMap.get("vmid"); + String vmIp = idIpsMap.get("vmip"); + + VirtualMachine lbvm = _entityMgr.findByUuid(VirtualMachine.class, vmId); + if (lbvm == null) { + throw new InvalidParameterValueException("Unable to find virtual machine ID: " + vmId); + } + + //check wether the given ip is valid ip or not + if (vmIp == null || !NetUtils.isValidIp(vmIp)) { + throw new InvalidParameterValueException("Invalid ip address "+ vmIp +" passed in vmidipmap for " + + "vmid " + vmId); + } + Long longVmId = lbvm.getId(); + + List ipsList = null; + if (vmIdIpsMap.containsKey(longVmId)) { + ipsList = vmIdIpsMap.get(longVmId); + } else { + ipsList = new ArrayList(); + } + ipsList.add(vmIp); + vmIdIpsMap.put(longVmId, ipsList); + + } + } + + return vmIdIpsMap; + } + @Override public void execute() { CallContext.current().setEventDetails("Load balancer Id: " + getLoadBalancerId() + " VmIds: " + StringUtils.join(getVirtualMachineIds(), ",")); - boolean result = _lbService.assignToLoadBalancer(getLoadBalancerId(), virtualMachineIds); + + Map> vmIdIpsMap = getVmIdIpListMap(); + + boolean result = _lbService.assignToLoadBalancer(getLoadBalancerId(), virtualMachineIds, vmIdIpsMap); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); - this.setResponseObject(response); + setResponseObject(response); } else { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to assign load balancer rule"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLBStickinessPoliciesCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLBStickinessPoliciesCmd.java index 2e7ae3c5e1..1ceb214b30 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLBStickinessPoliciesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLBStickinessPoliciesCmd.java @@ -76,7 +76,7 @@ public void execute() { if (lb != null) { //check permissions Account caller = CallContext.current().getCallingAccount(); - _accountService.checkAccess(caller, null, true, lb); + _accountService.checkAccess(caller, null, lb); List stickinessPolicies = _lbService.searchForLBStickinessPolicies(this); LBStickinessResponse spResponse = _responseGenerator.createLBStickinessPolicyResponse(stickinessPolicies, lb); spResponses.add(spResponse); @@ -84,7 +84,7 @@ public void execute() { } response.setResponseName(getCommandName()); - this.setResponseObject(response); + setResponseObject(response); } } diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRuleInstancesCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRuleInstancesCmd.java index 2d458a7408..cc4203c359 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRuleInstancesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRuleInstancesCmd.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; +import org.apache.cloudstack.api.response.LoadBalancerRuleVmMapResponse; import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; @@ -33,7 +34,7 @@ import com.cloud.uservm.UserVm; import com.cloud.utils.Pair; -@APICommand(name = "listLoadBalancerRuleInstances", description = "List all virtual machine instances that are assigned to a load balancer rule.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, +@APICommand(name = "listLoadBalancerRuleInstances", description = "List all virtual machine instances that are assigned to a load balancer rule.", responseObject = LoadBalancerRuleVmMapResponse.class, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ListLoadBalancerRuleInstancesCmd extends BaseListCmd { @@ -57,6 +58,13 @@ public class ListLoadBalancerRuleInstancesCmd extends BaseListCmd { description = "the ID of the load balancer rule") private Long id; + + @Parameter(name = ApiConstants.LIST_LB_VMIPS, + type = CommandType.BOOLEAN, + description = "true if lb rule vm ip information to be included; default is false") + private boolean isListLbVmip; + + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -69,6 +77,10 @@ public Long getId() { return id; } + public boolean isListLbVmip() { + return isListLbVmip; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -83,17 +95,49 @@ public void execute() { Pair, List> vmServiceMap = _lbService.listLoadBalancerInstances(this); List result = vmServiceMap.first(); List serviceStates = vmServiceMap.second(); - ListResponse response = new ListResponse(); - List vmResponses = new ArrayList(); - if (result != null) { - vmResponses = _responseGenerator.createUserVmResponse(ResponseView.Restricted, "loadbalancerruleinstance", result.toArray(new UserVm[result.size()])); - } - for (int i = 0; i < result.size(); i++) { - vmResponses.get(i).setServiceState(serviceStates.get(i)); + if (!isListLbVmip()) { + // list lb instances + ListResponse response = new ListResponse(); + List vmResponses = new ArrayList(); + if (result != null) { + vmResponses = _responseGenerator.createUserVmResponse(ResponseView.Restricted, "loadbalancerruleinstance", result.toArray(new UserVm[result.size()])); + + + for (int i = 0; i < result.size(); i++) { + vmResponses.get(i).setServiceState(serviceStates.get(i)); + } + } + response.setResponses(vmResponses); + response.setResponseName(getCommandName()); + setResponseObject(response); + + + } else { + ListResponse lbRes = new ListResponse(); + + List vmResponses = new ArrayList(); + List listlbVmRes = new ArrayList(); + + if (result != null) { + vmResponses = _responseGenerator.createUserVmResponse(ResponseView.Full, "loadbalancerruleinstance", result.toArray(new UserVm[result.size()])); + + + List ipaddr = null; + + for (int i=0;i virtualMachineIds; + @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID_IP, + type = CommandType.MAP, + description = "VM ID and IP map, vmidipmap[0].vmid=1 vmidipmap[0].ip=10.1.1.75", + since = "4.4") + private Map vmIdIpMap; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -78,6 +89,10 @@ public List getVirtualMachineIds() { return virtualMachineIds; } + public Map getVmIdIpMap() { + return vmIdIpMap; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -101,20 +116,58 @@ public String getEventType() { return EventTypes.EVENT_REMOVE_FROM_LOAD_BALANCER_RULE; } + + public Map> getVmIdIpListMap() { + Map> vmIdIpsMap = new HashMap>(); + if (vmIdIpMap != null && !vmIdIpMap.isEmpty()) { + Collection idIpsCollection = vmIdIpMap.values(); + Iterator iter = idIpsCollection.iterator(); + while (iter.hasNext()) { + HashMap idIpsMap = (HashMap)iter.next(); + String vmId = idIpsMap.get("vmid"); + String vmIp = idIpsMap.get("vmip"); + + VirtualMachine lbvm = _entityMgr.findByUuid(VirtualMachine.class, vmId); + if (lbvm == null) { + throw new InvalidParameterValueException("Unable to find virtual machine ID: " + vmId); + } + + Long longVmId = lbvm.getId(); + + List ipsList = null; + if (vmIdIpsMap.containsKey(longVmId)) { + ipsList = vmIdIpsMap.get(longVmId); + } else { + ipsList = new ArrayList(); + } + ipsList.add(vmIp); + vmIdIpsMap.put(longVmId, ipsList); + + } + } + + return vmIdIpsMap; + } + @Override public String getEventDescription() { return "removing instances from load balancer: " + getId() + " (ids: " + StringUtils.join(getVirtualMachineIds(), ",") + ")"; } @Override - public void execute() { + public void execute() { CallContext.current().setEventDetails("Load balancer Id: " + getId() + " VmIds: " + StringUtils.join(getVirtualMachineIds(), ",")); - boolean result = _lbService.removeFromLoadBalancer(id, virtualMachineIds); - if (result) { - SuccessResponse response = new SuccessResponse(getCommandName()); - this.setResponseObject(response); - } else { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove instance from load balancer rule"); + Map> vmIdIpsMap = getVmIdIpListMap(); + try { + boolean result = _lbService.removeFromLoadBalancer(id, virtualMachineIds, vmIdIpsMap); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove instance from load balancer rule"); + } + }catch (InvalidParameterValueException ex) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Failed to remove instance from load balancer rule"); } } diff --git a/api/src/org/apache/cloudstack/api/command/user/nat/CreateIpForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/nat/CreateIpForwardingRuleCmd.java index 77edbfccca..8925d066fe 100644 --- a/api/src/org/apache/cloudstack/api/command/user/nat/CreateIpForwardingRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/nat/CreateIpForwardingRuleCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -325,8 +324,8 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.FirewallRule; + public Class getEntityType() { + return FirewallRule.class; } } diff --git a/api/src/org/apache/cloudstack/api/command/user/nat/DisableStaticNatCmd.java b/api/src/org/apache/cloudstack/api/command/user/nat/DisableStaticNatCmd.java index 1df77ec0fd..2a9311e963 100644 --- a/api/src/org/apache/cloudstack/api/command/user/nat/DisableStaticNatCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/nat/DisableStaticNatCmd.java @@ -34,8 +34,11 @@ import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.IpAddress; +import com.cloud.network.vpc.Vpc; +import com.cloud.vm.VirtualMachine; @APICommand(name = "disableStaticNat", description = "Disables static rule for given ip address", responseObject = SuccessResponse.class, + entityType = {IpAddress.class, VirtualMachine.class, Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DisableStaticNatCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeletePortForwardingRuleCmd.class.getName()); @@ -89,7 +92,7 @@ public void execute() throws ResourceUnavailableException, NetworkRuleConflictEx if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); - this.setResponseObject(response); + setResponseObject(response); } else { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to disable static nat"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/nat/EnableStaticNatCmd.java b/api/src/org/apache/cloudstack/api/command/user/nat/EnableStaticNatCmd.java index aa4e28768a..9d888760fa 100644 --- a/api/src/org/apache/cloudstack/api/command/user/nat/EnableStaticNatCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/nat/EnableStaticNatCmd.java @@ -18,6 +18,8 @@ import org.apache.log4j.Logger; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -33,10 +35,13 @@ import com.cloud.exception.NetworkRuleConflictException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.IpAddress; +import com.cloud.network.vpc.Vpc; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; @APICommand(name = "enableStaticNat", description = "Enables static nat for given ip address", responseObject = SuccessResponse.class, + entityType = {IpAddress.class, VirtualMachine.class, Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class EnableStaticNatCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateIpForwardingRuleCmd.class.getName()); @@ -47,10 +52,12 @@ public class EnableStaticNatCmd extends BaseCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// + @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.IP_ADDRESS_ID, type = CommandType.UUID, entityType = IPAddressResponse.class, required = true, description = "the public IP " + "address id for which static nat feature is being enabled") private Long ipAddressId; + @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, required = true, description = "the ID of " + "the virtual machine for enabling static nat feature") private Long virtualMachineId; @@ -133,7 +140,7 @@ public void execute() throws ResourceUnavailableException { boolean result = _rulesService.enableStaticNat(ipAddressId, virtualMachineId, getNetworkId(), getVmSecondaryIp()); if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); - this.setResponseObject(response); + setResponseObject(response); } else { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to enable static nat"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java index 3ecec7bde8..43c3d1b09e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -45,7 +44,7 @@ import com.cloud.network.Network.GuestType; import com.cloud.offering.NetworkOffering; -@APICommand(name = "createNetwork", description = "Creates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.Network}, +@APICommand(name = "createNetwork", description = "Creates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateNetworkCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateNetworkCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkCmd.java index 50bc94a126..4c3a292c4a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/DeleteNetworkCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.network.Network; -@APICommand(name = "deleteNetwork", description = "Deletes a network", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Network}, +@APICommand(name = "deleteNetwork", description = "Deletes a network", responseObject = SuccessResponse.class, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteNetworkCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteNetworkOfferingCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkOfferingsCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkOfferingsCmd.java index a08e28fb6d..6ac0f395b7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkOfferingsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworkOfferingsCmd.java @@ -36,7 +36,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListNetworkOfferingsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListNetworkOfferingsCmd.class.getName()); - private static final String Name = "listnetworkofferingsresponse"; + private static final String s_name = "listnetworkofferingsresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -182,7 +182,7 @@ public Boolean getForVpc() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworksCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworksCmd.java index 455d8dc6a0..86f3ba2ad6 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/ListNetworksCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/ListNetworksCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,11 +36,11 @@ import com.cloud.network.Network; import com.cloud.utils.Pair; -@APICommand(name = "listNetworks", description = "Lists all available networks.", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = { IAMEntityType.Network }, +@APICommand(name = "listNetworks", description = "Lists all available networks.", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListNetworksCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListNetworksCmd.class.getName()); - private static final String Name = "listnetworksresponse"; + private static final String s_name = "listnetworksresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -156,7 +155,7 @@ public Boolean getDisplay() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java index 6baafda7c8..eba8310421 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/RestartNetworkCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -41,7 +40,7 @@ @APICommand(name = "restartNetwork", description = "Restarts the network; includes 1) restarting network elements - virtual routers, dhcp servers 2) reapplying all public ips 3) reapplying loadBalancing/portForwarding rules", - responseObject = IPAddressResponse.class, entityType = {IAMEntityType.Network}, + responseObject = IPAddressResponse.class, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RestartNetworkCmd extends BaseAsyncCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java index aea7448ab3..0f73ddef93 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -43,7 +42,7 @@ import com.cloud.user.Account; import com.cloud.user.User; -@APICommand(name = "updateNetwork", description = "Updates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.Network}, +@APICommand(name = "updateNetwork", description = "Updates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateNetworkCmd extends BaseAsyncCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdateNetworkCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java b/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java index 5a417496eb..81d725b919 100644 --- a/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/resource/UpdateResourceCountCmd.java @@ -106,7 +106,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupEgressCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupEgressCmd.java index 96509f1081..aef0a7c738 100644 --- a/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupEgressCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupEgressCmd.java @@ -24,7 +24,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -42,10 +41,11 @@ import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityRule; import com.cloud.utils.StringUtils; -@APICommand(name = "authorizeSecurityGroupEgress", responseObject = SecurityGroupRuleResponse.class, description = "Authorizes a particular egress rule for this security group", since = "3.0.0", entityType = {IAMEntityType.SecurityGroup}, +@APICommand(name = "authorizeSecurityGroupEgress", responseObject = SecurityGroupRuleResponse.class, description = "Authorizes a particular egress rule for this security group", since = "3.0.0", entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) @SuppressWarnings("rawtypes") diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java index 1e324e2a1e..188df6e111 100644 --- a/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/AuthorizeSecurityGroupIngressCmd.java @@ -24,7 +24,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -42,10 +41,11 @@ import com.cloud.event.EventTypes; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityRule; import com.cloud.utils.StringUtils; -@APICommand(name = "authorizeSecurityGroupIngress", responseObject = SecurityGroupRuleResponse.class, description = "Authorizes a particular ingress rule for this security group", entityType = {IAMEntityType.SecurityGroup}, +@APICommand(name = "authorizeSecurityGroupIngress", responseObject = SecurityGroupRuleResponse.class, description = "Authorizes a particular ingress rule for this security group", entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) @SuppressWarnings("rawtypes") diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.java index 1f7f872f1e..d3d35bc0b3 100644 --- a/api/src/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/CreateSecurityGroupCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -33,7 +32,7 @@ import com.cloud.network.security.SecurityGroup; import com.cloud.user.Account; -@APICommand(name = "createSecurityGroup", responseObject = SecurityGroupResponse.class, description = "Creates a security group", entityType = {IAMEntityType.SecurityGroup}, +@APICommand(name = "createSecurityGroup", responseObject = SecurityGroupResponse.class, description = "Creates a security group", entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateSecurityGroupCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateSecurityGroupCmd.class.getName()); @@ -98,7 +97,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java index 827c7d7389..87e6df41b6 100644 --- a/api/src/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/DeleteSecurityGroupCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -35,8 +34,9 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.ResourceInUseException; +import com.cloud.network.security.SecurityGroup; -@APICommand(name = "deleteSecurityGroup", description = "Deletes security group", responseObject = SuccessResponse.class, entityType = {IAMEntityType.SecurityGroup}, +@APICommand(name = "deleteSecurityGroup", description = "Deletes security group", responseObject = SuccessResponse.class, entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteSecurityGroupCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(DeleteSecurityGroupCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java index 02be63d0b4..4a8081a350 100644 --- a/api/src/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/ListSecurityGroupsCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -28,7 +27,9 @@ import org.apache.cloudstack.api.response.SecurityGroupResponse; import org.apache.cloudstack.api.response.UserVmResponse; -@APICommand(name = "listSecurityGroups", description = "Lists security groups", responseObject = SecurityGroupResponse.class, entityType = {IAMEntityType.SecurityGroup}, +import com.cloud.network.security.SecurityGroup; + +@APICommand(name = "listSecurityGroups", description = "Lists security groups", responseObject = SecurityGroupResponse.class, entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSecurityGroupsCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListSecurityGroupsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java index d1ffc1e5ea..a28a220b53 100644 --- a/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupEgressCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,7 @@ import com.cloud.user.Account; -@APICommand(name = "revokeSecurityGroupEgress", responseObject = SuccessResponse.class, description = "Deletes a particular egress rule from this security group", since = "3.0.0", entityType = {IAMEntityType.SecurityGroup}, +@APICommand(name = "revokeSecurityGroupEgress", responseObject = SuccessResponse.class, description = "Deletes a particular egress rule from this security group", since = "3.0.0", entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RevokeSecurityGroupEgressCmd extends BaseAsyncCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java b/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java index 8543e0e1de..9e81d0bc4e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/securitygroup/RevokeSecurityGroupIngressCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.network.security.SecurityRule; import com.cloud.user.Account; -@APICommand(name = "revokeSecurityGroupIngress", responseObject = SuccessResponse.class, description = "Deletes a particular ingress rule from this security group", entityType = {IAMEntityType.SecurityGroup}, +@APICommand(name = "revokeSecurityGroupIngress", responseObject = SuccessResponse.class, description = "Deletes a particular ingress rule from this security group", entityType = {SecurityGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RevokeSecurityGroupIngressCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RevokeSecurityGroupIngressCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java index 2020518528..bd8662e146 100644 --- a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java @@ -18,7 +18,7 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; +import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -42,7 +42,7 @@ import com.cloud.storage.Volume; import com.cloud.user.Account; -@APICommand(name = "createSnapshot", description = "Creates an instant snapshot of a volume.", responseObject = SnapshotResponse.class, entityType = {IAMEntityType.Snapshot}, +@APICommand(name = "createSnapshot", description = "Creates an instant snapshot of a volume.", responseObject = SnapshotResponse.class, entityType = {Snapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateSnapshotCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateSnapshotCmd.class.getName()); @@ -63,6 +63,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { description = "The domain ID of the snapshot. If used with the account parameter, specifies a domain for the account associated with the disk volume.") private Long domainId; + @ACL @Parameter(name = ApiConstants.VOLUME_ID, type = CommandType.UUID, entityType = VolumeResponse.class, required = true, description = "The ID of the disk volume") private Long volumeId; diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java index 7d57c21459..64a432d0bc 100644 --- a/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/DeleteSnapshotCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.storage.Snapshot; import com.cloud.user.Account; -@APICommand(name = "deleteSnapshot", description = "Deletes a snapshot of a disk volume.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Snapshot}, +@APICommand(name = "deleteSnapshot", description = "Deletes a snapshot of a disk volume.", responseObject = SuccessResponse.class, entityType = {Snapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteSnapshotCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteSnapshotCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java index ed26e7ff6f..47a6876d09 100644 --- a/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,7 @@ import com.cloud.storage.Snapshot; import com.cloud.utils.Pair; -@APICommand(name = "listSnapshots", description = "Lists all available snapshots for the account.", responseObject = SnapshotResponse.class, entityType = {IAMEntityType.Snapshot}, +@APICommand(name = "listSnapshots", description = "Lists all available snapshots for the account.", responseObject = SnapshotResponse.class, entityType = {Snapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSnapshotsCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListSnapshotsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java index ab83812262..0c79f81564 100644 --- a/api/src/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/RevertSnapshotCmd.java @@ -18,7 +18,6 @@ */ package org.apache.cloudstack.api.command.user.snapshot; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -37,7 +36,7 @@ import com.cloud.storage.Snapshot; import com.cloud.user.Account; -@APICommand(name = "revertSnapshot", description = "revert a volume snapshot.", responseObject = SnapshotResponse.class, entityType = {IAMEntityType.Snapshot}, +@APICommand(name = "revertSnapshot", description = "revert a volume snapshot.", responseObject = SnapshotResponse.class, entityType = {Snapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RevertSnapshotCmd extends BaseAsyncCmd { private static final String s_name = "revertsnapshotresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java b/api/src/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java index a0f05d18d3..bd7f613f89 100644 --- a/api/src/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/ssh/CreateSSHKeyPairCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; @@ -30,7 +29,7 @@ import com.cloud.user.SSHKeyPair; -@APICommand(name = "createSSHKeyPair", description = "Create a new keypair and returns the private key", responseObject = CreateSSHKeyPairResponse.class, entityType = {IAMEntityType.SSHKeyPair}, +@APICommand(name = "createSSHKeyPair", description = "Create a new keypair and returns the private key", responseObject = CreateSSHKeyPairResponse.class, entityType = {SSHKeyPair.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class CreateSSHKeyPairCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateSSHKeyPairCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/ssh/DeleteSSHKeyPairCmd.java b/api/src/org/apache/cloudstack/api/command/user/ssh/DeleteSSHKeyPairCmd.java index d0a5234e05..9258587735 100644 --- a/api/src/org/apache/cloudstack/api/command/user/ssh/DeleteSSHKeyPairCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/ssh/DeleteSSHKeyPairCmd.java @@ -19,7 +19,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; @@ -30,8 +29,9 @@ import org.apache.cloudstack.context.CallContext; import com.cloud.user.Account; +import com.cloud.user.SSHKeyPair; -@APICommand(name = "deleteSSHKeyPair", description = "Deletes a keypair by name", responseObject = SuccessResponse.class, entityType = {IAMEntityType.SSHKeyPair}, +@APICommand(name = "deleteSSHKeyPair", description = "Deletes a keypair by name", responseObject = SuccessResponse.class, entityType = {SSHKeyPair.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteSSHKeyPairCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateSSHKeyPairCmd.class.getName()); @@ -93,7 +93,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { diff --git a/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java b/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java index f02bf9f4f5..022cbc5068 100644 --- a/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/ssh/ListSSHKeyPairsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; @@ -32,7 +31,7 @@ import com.cloud.user.SSHKeyPair; import com.cloud.utils.Pair; -@APICommand(name = "listSSHKeyPairs", description = "List registered keypairs", responseObject = SSHKeyPairResponse.class, entityType = {IAMEntityType.SSHKeyPair}, +@APICommand(name = "listSSHKeyPairs", description = "List registered keypairs", responseObject = SSHKeyPairResponse.class, entityType = {SSHKeyPair.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListSSHKeyPairsCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListSSHKeyPairsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java b/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java index e095227d98..c7cbc56ae6 100644 --- a/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/ssh/RegisterSSHKeyPairCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseCmd; @@ -30,7 +29,7 @@ import com.cloud.user.SSHKeyPair; -@APICommand(name = "registerSSHKeyPair", description = "Register a public key in a keypair under a certain name", responseObject = SSHKeyPairResponse.class, entityType = {IAMEntityType.SSHKeyPair}, +@APICommand(name = "registerSSHKeyPair", description = "Register a public key in a keypair under a certain name", responseObject = SSHKeyPairResponse.class, entityType = {SSHKeyPair.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RegisterSSHKeyPairCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(RegisterSSHKeyPairCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java b/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java index eab114fea8..6aecc05548 100644 --- a/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java @@ -25,7 +25,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -38,7 +37,7 @@ import com.cloud.server.ResourceTag; import com.cloud.server.ResourceTag.ResourceObjectType; -@APICommand(name = "createTags", description = "Creates resource tag(s)", responseObject = SuccessResponse.class, since = "4.0.0", entityType = {IAMEntityType.ResourceTag}, +@APICommand(name = "createTags", description = "Creates resource tag(s)", responseObject = SuccessResponse.class, since = "4.0.0", entityType = {ResourceTag.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateTagsCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(CreateTagsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java b/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java index 39b6630b61..e42cfce4d9 100644 --- a/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java @@ -25,7 +25,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -35,9 +34,10 @@ import org.apache.cloudstack.api.response.SuccessResponse; import com.cloud.event.EventTypes; +import com.cloud.server.ResourceTag; import com.cloud.server.ResourceTag.ResourceObjectType; -@APICommand(name = "deleteTags", description = "Deleting resource tag(s)", responseObject = SuccessResponse.class, since = "4.0.0", entityType = {IAMEntityType.ResourceTag}, +@APICommand(name = "deleteTags", description = "Deleting resource tag(s)", responseObject = SuccessResponse.class, since = "4.0.0", entityType = {ResourceTag.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteTagsCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteTagsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java b/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java index b2249104ac..e02b25c446 100644 --- a/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.tag; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; @@ -25,7 +24,9 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ResourceTagResponse; -@APICommand(name = "listTags", description = "List resource tag(s)", responseObject = ResourceTagResponse.class, since = "4.0.0", entityType = {IAMEntityType.ResourceTag}, +import com.cloud.server.ResourceTag; + +@APICommand(name = "listTags", description = "List resource tag(s)", responseObject = ResourceTagResponse.class, since = "4.0.0", entityType = {ResourceTag.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListTagsCmd extends BaseListProjectAndAccountResourcesCmd { private static final String s_name = "listtagsresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java index 0be9ab8007..7a2a15834a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/template/ListTemplatesCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -30,10 +29,11 @@ import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.context.CallContext; +import com.cloud.template.VirtualMachineTemplate; import com.cloud.template.VirtualMachineTemplate.TemplateFilter; import com.cloud.user.Account; -@APICommand(name = "listTemplates", description = "List all public, private, and privileged templates.", responseObject = TemplateResponse.class, entityType = {IAMEntityType.VirtualMachineTemplate}, responseView = ResponseView.Restricted, +@APICommand(name = "listTemplates", description = "List all public, private, and privileged templates.", responseObject = TemplateResponse.class, entityType = {VirtualMachineTemplate.class}, responseView = ResponseView.Restricted, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListTemplatesCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListTemplatesCmd.class.getName()); @@ -103,7 +103,7 @@ public boolean listInReadyState() { Account account = CallContext.current().getCallingAccount(); // It is account specific if account is admin type and domainId and accountName are not null - boolean isAccountSpecific = (account == null || _accountService.isAdmin(account.getType())) && (getAccountName() != null) && (getDomainId() != null); + boolean isAccountSpecific = (account == null || _accountService.isAdmin(account.getId())) && (getAccountName() != null) && (getDomainId() != null); // Show only those that are downloaded. TemplateFilter templateFilter = TemplateFilter.valueOf(getTemplateFilter()); boolean onlyReady = diff --git a/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java index d5d0c58742..2029156837 100644 --- a/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/template/UpdateTemplatePermissionsCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoPermissionsCmd; import org.apache.cloudstack.api.response.SuccessResponse; @@ -28,7 +27,7 @@ @APICommand(name = "updateTemplatePermissions", responseObject = SuccessResponse.class, description = "Updates a template visibility permissions. " + "A public template is visible to all accounts within the same domain. " + "A private template is visible only to the owner of the template. " - + "A priviledged template is a private template with account permissions added. " + "Only accounts specified under the template permissions are visible to them.", entityType = {IAMEntityType.VirtualMachineTemplate}, + + "A priviledged template is a private template with account permissions added. " + "Only accounts specified under the template permissions are visible to them.", entityType = {VirtualMachineTemplate.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateTemplatePermissionsCmd extends BaseUpdateTemplateOrIsoPermissionsCmd { @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java index a7f94368dc..870bbbf01e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java @@ -92,6 +92,12 @@ private NetworkType getNetworkType() { return dc.getNetworkType(); } + private boolean isZoneSGEnabled() { + Network ntwk = _entityMgr.findById(Network.class, getNetworkId()); + DataCenter dc = _entityMgr.findById(DataCenter.class, ntwk.getDataCenterId()); + return dc.isSecurityGroupEnabled(); + } + @Override public String getEventType() { return EventTypes.EVENT_NET_IP_ASSIGN; @@ -136,7 +142,7 @@ public void execute() throws ResourceUnavailableException, ResourceAllocationExc if (result != null) { secondaryIp = result.getIp4Address(); - if (getNetworkType() == NetworkType.Basic) { + if (isZoneSGEnabled()) { // add security group rules for the secondary ip addresses boolean success = false; success = _securityGroupService.securityGroupRulesForVmSecIp(getNicId(), secondaryIp, true); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java index a1bbe2a45b..fd30152ae0 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/AddNicToVMCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,8 +38,9 @@ import com.cloud.event.EventTypes; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "addNicToVirtualMachine", description = "Adds VM to specified network by creating a NIC", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "addNicToVirtualMachine", description = "Adds VM to specified network by creating a NIC", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class AddNicToVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(AddNicToVMCmd.class); @@ -54,6 +54,7 @@ public class AddNicToVMCmd extends BaseAsyncCmd { required=true, description="Virtual Machine ID") private Long vmId; + @ACL @Parameter(name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class, required = true, description = "Network ID") private Long netId; diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java index 0235fcc305..cc91013d5f 100755 --- a/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java @@ -26,7 +26,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.affinity.AffinityGroupResponse; @@ -68,8 +67,9 @@ import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "deployVirtualMachine", description = "Creates and automatically starts a virtual machine based on a service offering, disk offering, and template.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = { IAMEntityType.VirtualMachine }, +@APICommand(name = "deployVirtualMachine", description = "Creates and automatically starts a virtual machine based on a service offering, disk offering, and template.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd { public static final Logger s_logger = Logger.getLogger(DeployVMCmd.class.getName()); @@ -121,6 +121,12 @@ public class DeployVMCmd extends BaseAsyncCreateCustomIdCmd { @Parameter(name = ApiConstants.SIZE, type = CommandType.LONG, description = "the arbitrary size for the DATADISK volume. Mutually exclusive with diskOfferingId") private Long size; + @Parameter(name = ApiConstants.ROOT_DISK_SIZE, + type = CommandType.LONG, + description = "Optional field to resize root disk on deploy. Only applies to template-based deployments. Analogous to details[0].rootdisksize, which takes precedence over this parameter if both are provided", + since = "4.4") + private Long rootdisksize; + @Parameter(name = ApiConstants.GROUP, type = CommandType.STRING, description = "an optional group for the virtual machine") private String group; @@ -226,6 +232,9 @@ public Map getDetails() { } } } + if (rootdisksize != null && !customparameterMap.containsKey("rootdisksize")) { + customparameterMap.put("rootdisksize", rootdisksize.toString()); + } return customparameterMap; } @@ -482,41 +491,50 @@ private void verifyDetails() { String minIops = (String)map.get("minIops"); String maxIops = (String)map.get("maxIops"); - if ((minIops != null && maxIops == null) || (minIops == null && maxIops != null)) { - throw new InvalidParameterValueException("Either 'Min IOPS' and 'Max IOPS' must both be specified or neither be specified."); - } + verifyMinAndMaxIops(minIops, maxIops); - long lMinIops; + minIops = (String)map.get("minIopsDo"); + maxIops = (String)map.get("maxIopsDo"); - try { - if (minIops != null) { - lMinIops = Long.valueOf(minIops); - } - else { - lMinIops = 0; - } + verifyMinAndMaxIops(minIops, maxIops); + } + } + + private void verifyMinAndMaxIops(String minIops, String maxIops) { + if ((minIops != null && maxIops == null) || (minIops == null && maxIops != null)) { + throw new InvalidParameterValueException("Either 'Min IOPS' and 'Max IOPS' must both be specified or neither be specified."); + } + + long lMinIops; + + try { + if (minIops != null) { + lMinIops = Long.valueOf(minIops); } - catch (NumberFormatException ex) { - throw new InvalidParameterValueException("'Min IOPS' must be a whole number."); + else { + lMinIops = 0; } + } + catch (NumberFormatException ex) { + throw new InvalidParameterValueException("'Min IOPS' must be a whole number."); + } - long lMaxIops; + long lMaxIops; - try { - if (maxIops != null) { - lMaxIops = Long.valueOf(maxIops); - } - else { - lMaxIops = 0; - } + try { + if (maxIops != null) { + lMaxIops = Long.valueOf(maxIops); } - catch (NumberFormatException ex) { - throw new InvalidParameterValueException("'Max IOPS' must be a whole number."); + else { + lMaxIops = 0; } + } + catch (NumberFormatException ex) { + throw new InvalidParameterValueException("'Max IOPS' must be a whole number."); + } - if (lMinIops > lMaxIops) { - throw new InvalidParameterValueException("'Min IOPS' must be less than or equal to 'Max IOPS'."); - } + if (lMinIops > lMaxIops) { + throw new InvalidParameterValueException("'Min IOPS' must be less than or equal to 'Max IOPS'."); } } diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/DestroyVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/DestroyVMCmd.java index 4c3a41589c..f2caa15d55 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/DestroyVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/DestroyVMCmd.java @@ -18,16 +18,15 @@ import java.util.List; -import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -39,8 +38,9 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "destroyVirtualMachine", description = "Destroys a virtual machine. Once destroyed, only the administrator can recover it.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "destroyVirtualMachine", description = "Destroys a virtual machine. Once destroyed, only the administrator can recover it.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class DestroyVMCmd extends BaseAsyncVMCmd { @@ -67,6 +67,7 @@ public class DestroyVMCmd extends BaseAsyncVMCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// + @Override public Long getId() { return id; } diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/GetVMPasswordCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/GetVMPasswordCmd.java index ebee189d35..0ba9db538a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/GetVMPasswordCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/GetVMPasswordCmd.java @@ -20,7 +20,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -32,8 +31,9 @@ import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "getVMPassword", responseObject = GetVMPasswordResponse.class, description = "Returns an encrypted password for the VM", entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "getVMPassword", responseObject = GetVMPasswordResponse.class, description = "Returns an encrypted password for the VM", entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class GetVMPasswordCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(GetVMPasswordCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java index 6c95a1215e..76e3db07b7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java @@ -22,7 +22,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.APICommand; @@ -46,9 +45,10 @@ import org.apache.cloudstack.api.response.ZoneResponse; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "listVirtualMachines", description = "List the virtual machines owned by the account.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = { IAMEntityType.VirtualMachine }, +@APICommand(name = "listVirtualMachines", description = "List the virtual machines owned by the account.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ListVMsCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVMsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java index 0f041148cd..2bafc739fa 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/RebootVMCmd.java @@ -16,16 +16,15 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; -import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -37,8 +36,9 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "rebootVirtualMachine", description = "Reboots a virtual machine.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "rebootVirtualMachine", description = "Reboots a virtual machine.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class RebootVMCmd extends BaseAsyncVMCmd { public static final Logger s_logger = Logger.getLogger(RebootVMCmd.class.getName()); @@ -56,6 +56,7 @@ public class RebootVMCmd extends BaseAsyncVMCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// + @Override public Long getId() { return id; } diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java index 75eafa9503..70d5b48a16 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/RemoveIpFromVmNicCmd.java @@ -131,6 +131,13 @@ public NetworkType getNetworkType() { return null; } + + private boolean isZoneSGEnabled() { + Network ntwk = _entityMgr.findById(Network.class, getNetworkId()); + DataCenter dc = _entityMgr.findById(DataCenter.class, ntwk.getDataCenterId()); + return dc.isSecurityGroupEnabled(); + } + @Override public void execute() throws InvalidParameterValueException { CallContext.current().setEventDetails("Ip Id: " + id); @@ -140,7 +147,7 @@ public void execute() throws InvalidParameterValueException { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Invalid IP id is passed"); } - if (getNetworkType() == NetworkType.Basic) { + if (isZoneSGEnabled()) { //remove the security group rules for this secondary ip boolean success = false; success = _securityGroupService.securityGroupRulesForVmSecIp(nicSecIp.getNicId(), nicSecIp.getIp4Address(), false); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java index 44dfcf61af..d740260fc6 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/RemoveNicFromVMCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,8 +38,9 @@ import com.cloud.event.EventTypes; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "removeNicFromVirtualMachine", description = "Removes VM from specified network by deleting a NIC", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "removeNicFromVirtualMachine", description = "Removes VM from specified network by deleting a NIC", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class RemoveNicFromVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RemoveNicFromVMCmd.class); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMPasswordCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMPasswordCmd.java index 615ef69369..d15ea47875 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMPasswordCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMPasswordCmd.java @@ -16,16 +16,15 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; -import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -37,10 +36,11 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; @APICommand(name = "resetPasswordForVirtualMachine", responseObject=UserVmResponse.class, description="Resets the password for virtual machine. " + "The virtual machine must be in a \"Stopped\" state and the template must already " + - "support this feature for this command to take effect. [async]", responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, + "support this feature for this command to take effect. [async]", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ResetVMPasswordCmd extends BaseAsyncVMCmd { public static final Logger s_logger = Logger.getLogger(ResetVMPasswordCmd.class.getName()); @@ -64,6 +64,7 @@ public class ResetVMPasswordCmd extends BaseAsyncVMCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// + @Override public Long getId() { return id; } diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMSSHKeyCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMSSHKeyCmd.java index 7d43853149..6b4ce5c998 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMSSHKeyCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/ResetVMSSHKeyCmd.java @@ -17,16 +17,15 @@ package org.apache.cloudstack.api.command.user.vm; -import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -40,9 +39,10 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; @APICommand(name = "resetSSHKeyForVirtualMachine", responseObject = UserVmResponse.class, description = "Resets the SSH Key for virtual machine. " + - "The virtual machine must be in a \"Stopped\" state. [async]", responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, + "The virtual machine must be in a \"Stopped\" state. [async]", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class ResetVMSSHKeyCmd extends BaseAsyncVMCmd { @@ -81,6 +81,7 @@ public String getName() { return name; } + @Override public Long getId() { return id; } diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java index 0d5ef70bee..b1cc602173 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java @@ -16,15 +16,14 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; -import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -39,8 +38,9 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "restoreVirtualMachine", description = "Restore a VM to original template/ISO or new template/ISO", responseObject = UserVmResponse.class, since = "3.0.0", responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "restoreVirtualMachine", description = "Restore a VM to original template/ISO or new template/ISO", responseObject = UserVmResponse.class, since = "3.0.0", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class RestoreVMCmd extends BaseAsyncVMCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java index d668ad4fed..76f9472dac 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/ScaleVMCmd.java @@ -24,7 +24,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -46,9 +45,10 @@ import com.cloud.exception.VirtualMachineMigrationException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "scaleVirtualMachine", description = "Scales the virtual machine to a new service offering.", responseObject = SuccessResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "scaleVirtualMachine", description = "Scales the virtual machine to a new service offering.", responseObject = SuccessResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ScaleVMCmd extends BaseAsyncVMCmd { public static final Logger s_logger = Logger.getLogger(ScaleVMCmd.class.getName()); @@ -73,6 +73,7 @@ public class ScaleVMCmd extends BaseAsyncVMCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// + @Override public Long getId() { return id; } diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java index 13b7442eaf..7b1cf8fd6b 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/StartVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -44,8 +43,9 @@ import com.cloud.user.Account; import com.cloud.uservm.UserVm; import com.cloud.utils.exception.ExecutionException; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "startVirtualMachine", responseObject = UserVmResponse.class, description = "Starts a virtual machine.", responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "startVirtualMachine", responseObject = UserVmResponse.class, description = "Starts a virtual machine.", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class StartVMCmd extends BaseAsyncVMCmd { public static final Logger s_logger = Logger.getLogger(StartVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/StopVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/StopVMCmd.java index 6db5d18d30..d02fd7d47a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/StopVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/StopVMCmd.java @@ -16,16 +16,15 @@ // under the License. package org.apache.cloudstack.api.command.user.vm; -import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncVMCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; @@ -36,8 +35,9 @@ import com.cloud.exception.ConcurrentOperationException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "stopVirtualMachine", responseObject = UserVmResponse.class, description = "Stops a virtual machine.", responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "stopVirtualMachine", responseObject = UserVmResponse.class, description = "Stops a virtual machine.", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class StopVMCmd extends BaseAsyncVMCmd { public static final Logger s_logger = Logger.getLogger(StopVMCmd.class.getName()); @@ -61,6 +61,7 @@ public class StopVMCmd extends BaseAsyncVMCmd { // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// + @Override public Long getId() { return id; } diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java index c70f7e502d..cffd903792 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/UpdateDefaultNicForVMCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -39,8 +38,9 @@ import com.cloud.event.EventTypes; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "updateDefaultNicForVirtualMachine", description = "Changes the default NIC on a VM", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "updateDefaultNicForVirtualMachine", description = "Changes the default NIC on a VM", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpdateDefaultNicForVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(UpdateDefaultNicForVMCmd.class); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java index fac82aac9b..1d0e68dfc3 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/UpdateVMCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -37,10 +36,11 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; @APICommand(name = "updateVirtualMachine", description="Updates properties of a virtual machine. The VM has to be stopped and restarted for the " + "new properties to take effect. UpdateVirtualMachine does not first check whether the VM is stopped. " + - "Therefore, stop the VM manually before issuing this call.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, + "Therefore, stop the VM manually before issuing this call.", responseObject = UserVmResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpdateVMCmd extends BaseCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdateVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java index 3560b04098..1923198eb5 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/UpgradeVMCmd.java @@ -23,7 +23,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -42,10 +41,11 @@ import com.cloud.offering.ServiceOffering; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; @APICommand(name = "changeServiceForVirtualMachine", responseObject=UserVmResponse.class, description="Changes the service offering for a virtual machine. " + "The virtual machine must be in a \"Stopped\" state for " + - "this command to take effect.", responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, + "this command to take effect.", responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = true) public class UpgradeVMCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(UpgradeVMCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vmgroup/CreateVMGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmgroup/CreateVMGroupCmd.java index 104cfa3672..6947f15059 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmgroup/CreateVMGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmgroup/CreateVMGroupCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -32,7 +31,7 @@ import com.cloud.vm.InstanceGroup; -@APICommand(name = "createInstanceGroup", description = "Creates a vm group", responseObject = InstanceGroupResponse.class, entityType = {IAMEntityType.InstanceGroup}, +@APICommand(name = "createInstanceGroup", description = "Creates a vm group", responseObject = InstanceGroupResponse.class, entityType = {InstanceGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVMGroupCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateVMGroupCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vmgroup/DeleteVMGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmgroup/DeleteVMGroupCmd.java index 0bc52369d2..8311eccf99 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmgroup/DeleteVMGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmgroup/DeleteVMGroupCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -33,7 +32,7 @@ import com.cloud.user.Account; import com.cloud.vm.InstanceGroup; -@APICommand(name = "deleteInstanceGroup", description = "Deletes a vm group", responseObject = SuccessResponse.class, entityType = {IAMEntityType.InstanceGroup}, +@APICommand(name = "deleteInstanceGroup", description = "Deletes a vm group", responseObject = SuccessResponse.class, entityType = {InstanceGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVMGroupCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(DeleteVMGroupCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vmgroup/ListVMGroupsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmgroup/ListVMGroupsCmd.java index e9844dd19a..73fdb8aa18 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmgroup/ListVMGroupsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmgroup/ListVMGroupsCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; @@ -26,7 +25,9 @@ import org.apache.cloudstack.api.response.InstanceGroupResponse; import org.apache.cloudstack.api.response.ListResponse; -@APICommand(name = "listInstanceGroups", description = "Lists vm groups", responseObject = InstanceGroupResponse.class, entityType = {IAMEntityType.InstanceGroup}, +import com.cloud.vm.InstanceGroup; + +@APICommand(name = "listInstanceGroups", description = "Lists vm groups", responseObject = InstanceGroupResponse.class, entityType = {InstanceGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVMGroupsCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVMGroupsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vmgroup/UpdateVMGroupCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmgroup/UpdateVMGroupCmd.java index e06ec52e1a..befa46c9ce 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmgroup/UpdateVMGroupCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmgroup/UpdateVMGroupCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -32,7 +31,7 @@ import com.cloud.user.Account; import com.cloud.vm.InstanceGroup; -@APICommand(name = "updateInstanceGroup", description = "Updates a vm group", responseObject = InstanceGroupResponse.class, entityType = {IAMEntityType.InstanceGroup}, +@APICommand(name = "updateInstanceGroup", description = "Updates a vm group", responseObject = InstanceGroupResponse.class, entityType = {InstanceGroup.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVMGroupCmd extends BaseCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java index fae0e61723..1310ba5b75 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java @@ -19,8 +19,6 @@ import java.util.logging.Logger; -import org.apache.cloudstack.acl.IAMEntityType; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,14 +35,14 @@ import com.cloud.uservm.UserVm; import com.cloud.vm.snapshot.VMSnapshot; -@APICommand(name = "createVMSnapshot", description = "Creates snapshot for a vm.", responseObject = VMSnapshotResponse.class, since = "4.2.0", entityType = {IAMEntityType.VMSnapshot}, +@APICommand(name = "createVMSnapshot", description = "Creates snapshot for a vm.", responseObject = VMSnapshotResponse.class, since = "4.2.0", entityType = {VMSnapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVMSnapshotCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateVMSnapshotCmd.class.getName()); private static final String s_name = "createvmsnapshotresponse"; - @ACL(accessType = AccessType.OperateEntry) + @ACL @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, required = true, entityType = UserVmResponse.class, description = "The ID of the vm") private Long vmId; diff --git a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java index af076cff57..7baad7cd59 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java @@ -19,7 +19,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.user.Account; import com.cloud.vm.snapshot.VMSnapshot; -@APICommand(name = "deleteVMSnapshot", description = "Deletes a vmsnapshot.", responseObject = SuccessResponse.class, since = "4.2.0", entityType = {IAMEntityType.VMSnapshot}, +@APICommand(name = "deleteVMSnapshot", description = "Deletes a vmsnapshot.", responseObject = SuccessResponse.class, since = "4.2.0", entityType = {VMSnapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVMSnapshotCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteVMSnapshotCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/ListVMSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/ListVMSnapshotCmd.java index 3167d09f01..c9bc2430d2 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/ListVMSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/ListVMSnapshotCmd.java @@ -20,7 +20,6 @@ import java.util.ArrayList; import java.util.List; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; @@ -31,7 +30,7 @@ import com.cloud.vm.snapshot.VMSnapshot; -@APICommand(name = "listVMSnapshot", description = "List virtual machine snapshot by conditions", responseObject = VMSnapshotResponse.class, since = "4.2.0", entityType = {IAMEntityType.VMSnapshot}, +@APICommand(name = "listVMSnapshot", description = "List virtual machine snapshot by conditions", responseObject = VMSnapshotResponse.class, since = "4.2.0", entityType = {VMSnapshot.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVMSnapshotCmd extends BaseListTaggedResourcesCmd { diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java index f9d9081f36..b3bb37e4c7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/AttachVolumeCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,8 +35,10 @@ import com.cloud.event.EventTypes; import com.cloud.storage.Volume; import com.cloud.user.Account; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "attachVolume", description = "Attaches a disk volume to a virtual machine.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.VirtualMachine}, +@APICommand(name = "attachVolume", description = "Attaches a disk volume to a virtual machine.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = { + VirtualMachine.class, Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AttachVolumeCmd extends BaseAsyncVolumeCmd { public static final Logger s_logger = Logger.getLogger(AttachVolumeCmd.class.getName()); @@ -52,6 +53,7 @@ public class AttachVolumeCmd extends BaseAsyncVolumeCmd { + "* 4 - /dev/xvde" + "* 5 - /dev/xvdf" + "* 6 - /dev/xvdg" + "* 7 - /dev/xvdh" + "* 8 - /dev/xvdi" + "* 9 - /dev/xvdj") private Long deviceId; + @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = VolumeResponse.class, required = true, description = "the ID of the disk volume") private Long id; diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java index 9b83f61b0b..2a651599b5 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/CreateVolumeCmd.java @@ -18,8 +18,8 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; +import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -43,7 +43,7 @@ import com.cloud.storage.Snapshot; import com.cloud.storage.Volume; -@APICommand(name = "createVolume", responseObject = VolumeResponse.class, description = "Creates a disk volume from a disk offering. This disk volume must still be attached to a virtual machine to make use of it.", responseView = ResponseView.Restricted, entityType = {IAMEntityType.Volume}, +@APICommand(name = "createVolume", responseObject = VolumeResponse.class, description = "Creates a disk volume from a disk offering. This disk volume must still be attached to a virtual machine to make use of it.", responseView = ResponseView.Restricted, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVolumeCmd extends BaseAsyncCreateCustomIdCmd { public static final Logger s_logger = Logger.getLogger(CreateVolumeCmd.class.getName()); @@ -90,6 +90,7 @@ public class CreateVolumeCmd extends BaseAsyncCreateCustomIdCmd { @Parameter(name = ApiConstants.MAX_IOPS, type = CommandType.LONG, description = "max iops") private Long maxIops; + @ACL @Parameter(name = ApiConstants.SNAPSHOT_ID, type = CommandType.UUID, entityType = SnapshotResponse.class, @@ -102,6 +103,7 @@ public class CreateVolumeCmd extends BaseAsyncCreateCustomIdCmd { @Parameter(name = ApiConstants.DISPLAY_VOLUME, type = CommandType.BOOLEAN, description = "an optional field, whether to display the volume to the end user or not.", authorized = {RoleType.Admin}) private Boolean displayVolume; + @ACL @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java index 6ca96b08b0..02b80d983d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/DeleteVolumeCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.volume; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -34,7 +33,7 @@ import com.cloud.storage.Volume; import com.cloud.user.Account; -@APICommand(name = "deleteVolume", description = "Deletes a detached disk volume.", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Volume}, +@APICommand(name = "deleteVolume", description = "Deletes a detached disk volume.", responseObject = SuccessResponse.class, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVolumeCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(DeleteVolumeCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java index bfd032203c..270931c261 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/DetachVolumeCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -37,8 +36,9 @@ import com.cloud.storage.Volume; import com.cloud.user.Account; import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; -@APICommand(name = "detachVolume", description = "Detaches a disk volume from a virtual machine.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.Volume}, +@APICommand(name = "detachVolume", description = "Detaches a disk volume from a virtual machine.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {VirtualMachine.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DetachVolumeCmd extends BaseAsyncVolumeCmd { public static final Logger s_logger = Logger.getLogger(DetachVolumeCmd.class.getName()); @@ -48,7 +48,6 @@ public class DetachVolumeCmd extends BaseAsyncVolumeCmd { //////////////// API parameters ///////////////////// ///////////////////////////////////////////////////// - @ACL(accessType = AccessType.OperateEntry) @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=VolumeResponse.class, description="the ID of the disk volume") private Long id; @@ -56,6 +55,7 @@ public class DetachVolumeCmd extends BaseAsyncVolumeCmd { @Parameter(name = ApiConstants.DEVICE_ID, type = CommandType.LONG, description = "the device ID on the virtual machine where volume is detached from") private Long deviceId; + @ACL(accessType = AccessType.OperateEntry) @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java index cc7f56cc7b..d560fc2e89 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/ExtractVolumeCmd.java @@ -16,16 +16,15 @@ // under the License. package org.apache.cloudstack.api.command.user.volume; -import org.apache.cloudstack.api.BaseAsyncVolumeCmd; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncVolumeCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.ExtractResponse; @@ -39,7 +38,7 @@ import com.cloud.storage.Volume; import com.cloud.user.Account; -@APICommand(name = "extractVolume", description = "Extracts volume", responseObject = ExtractResponse.class, entityType = {IAMEntityType.Volume}, +@APICommand(name = "extractVolume", description = "Extracts volume", responseObject = ExtractResponse.class, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ExtractVolumeCmd extends BaseAsyncVolumeCmd { public static final Logger s_logger = Logger.getLogger(ExtractVolumeCmd.class.getName()); @@ -72,6 +71,7 @@ public class ExtractVolumeCmd extends BaseAsyncVolumeCmd { /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// + @Override public Long getId() { return id; } diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/ListResourceDetailsCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/ListResourceDetailsCmd.java index 0aeff0c63c..ebec4b1f66 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/ListResourceDetailsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/ListResourceDetailsCmd.java @@ -62,7 +62,7 @@ public String getCommandName() { } public Boolean forDisplay() { - if (!_accountService.isAdmin(CallContext.current().getCallingAccount().getType())) { + if (!_accountService.isAdmin(CallContext.current().getCallingAccount().getId())) { return true; } diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java index b4ac4ae64c..cc218f7197 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/ListVolumesCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; @@ -35,7 +34,9 @@ import org.apache.cloudstack.api.response.VolumeResponse; import org.apache.cloudstack.api.response.ZoneResponse; -@APICommand(name = "listVolumes", description = "Lists all volumes.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = { IAMEntityType.Volume }, +import com.cloud.storage.Volume; + +@APICommand(name = "listVolumes", description = "Lists all volumes.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVolumesCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVolumesCmd.class.getName()); @@ -75,7 +76,11 @@ public class ListVolumesCmd extends BaseListTaggedResourcesCmd { authorized = {RoleType.Admin}) private Long storageId; - @Parameter(name = ApiConstants.DISK_OFFERING_ID, type = CommandType.UUID, entityType = DiskOfferingResponse.class, description = "list volumes by disk offering") + @Parameter(name = ApiConstants.DISK_OFFERING_ID, + type = CommandType.UUID, + entityType = DiskOfferingResponse.class, + description = "list volumes by disk offering", + since = "4.4") private Long diskOfferingId; @Parameter(name = ApiConstants.DISPLAY_VOLUME, type = CommandType.BOOLEAN, description = "list resources by display flag; only ROOT admin is eligible to pass this parameter", since = "4.4", authorized = {RoleType.Admin}) diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java index d80595a78f..3cfcdc831a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.api.command.user.volume; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -31,7 +30,7 @@ import com.cloud.storage.Volume; import com.cloud.user.Account; -@APICommand(name = "migrateVolume", description = "Migrate volume", responseObject = VolumeResponse.class, since = "3.0.0", responseView = ResponseView.Restricted, entityType = {IAMEntityType.Volume}, +@APICommand(name = "migrateVolume", description = "Migrate volume", responseObject = VolumeResponse.class, since = "3.0.0", responseView = ResponseView.Restricted, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class MigrateVolumeCmd extends BaseAsyncVolumeCmd { private static final String s_name = "migratevolumeresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java index d5cd62bbc3..dd887ac5ad 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/ResizeVolumeCmd.java @@ -17,7 +17,6 @@ package org.apache.cloudstack.api.command.user.volume; import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -41,7 +40,7 @@ import com.cloud.user.Account; -@APICommand(name = "resizeVolume", description = "Resizes a volume", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.Volume}, +@APICommand(name = "resizeVolume", description = "Resizes a volume", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ResizeVolumeCmd extends BaseAsyncVolumeCmd { public static final Logger s_logger = Logger.getLogger(ResizeVolumeCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/UpdateVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/UpdateVolumeCmd.java index 05e461e5ec..3ad6f47d27 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/UpdateVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/UpdateVolumeCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -38,7 +37,7 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.storage.Volume; -@APICommand(name = "updateVolume", description = "Updates the volume.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = { IAMEntityType.Volume }, +@APICommand(name = "updateVolume", description = "Updates the volume.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVolumeCmd extends BaseAsyncCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdateVolumeCmd.class.getName()); @@ -55,7 +54,10 @@ public class UpdateVolumeCmd extends BaseAsyncCustomIdCmd { @Parameter(name = ApiConstants.PATH, type = CommandType.STRING, description = "The path of the volume") private String path; - @Parameter(name = ApiConstants.CHAIN_INFO, type = CommandType.STRING, description = "The chain info of the volume") + @Parameter(name = ApiConstants.CHAIN_INFO, + type = CommandType.STRING, + description = "The chain info of the volume", + since = "4.4") private String chainInfo; @Parameter(name = ApiConstants.STORAGE_ID, diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java index e992759224..7a08abf276 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -40,7 +39,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.storage.Volume; -@APICommand(name = "uploadVolume", description = "Uploads a data disk.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.Volume}, +@APICommand(name = "uploadVolume", description = "Uploads a data disk.", responseObject = VolumeResponse.class, responseView = ResponseView.Restricted, entityType = {Volume.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UploadVolumeCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(UploadVolumeCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java index f2c9e2c2e2..e2f2029ce0 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateStaticRouteCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiCommandJobType; import org.apache.cloudstack.api.ApiConstants; @@ -40,7 +39,7 @@ import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.VpcGateway; -@APICommand(name = "createStaticRoute", description = "Creates a static route", responseObject = StaticRouteResponse.class, entityType = {IAMEntityType.StaticRoute}, +@APICommand(name = "createStaticRoute", description = "Creates a static route", responseObject = StaticRouteResponse.class, entityType = {StaticRoute.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateStaticRouteCmd extends BaseAsyncCreateCmd { private static final String s_name = "createstaticrouteresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java index c179ec857f..e2f261e1ba 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -41,7 +40,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.vpc.Vpc; -@APICommand(name = "createVPC", description = "Creates a VPC", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = {IAMEntityType.Vpc}, +@APICommand(name = "createVPC", description = "Creates a VPC", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = {Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVPCCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateVPCCmd.class.getName()); @@ -65,7 +64,7 @@ public class CreateVPCCmd extends BaseAsyncCreateCmd { private Long projectId; @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, - required = true, description = "the ID of the availability zone") + required = true, description = "the ID of the availability zone") private Long zoneId; @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "the name of the VPC") diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java index 0017753e33..9449e6d534 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteStaticRouteCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -38,7 +37,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.vpc.StaticRoute; -@APICommand(name = "deleteStaticRoute", description = "Deletes a static route", responseObject = SuccessResponse.class, entityType = {IAMEntityType.StaticRoute}, +@APICommand(name = "deleteStaticRoute", description = "Deletes a static route", responseObject = SuccessResponse.class, entityType = {StaticRoute.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteStaticRouteCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteStaticRouteCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.java index 5928aabff6..9d13b63e6a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/DeleteVPCCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -36,7 +35,7 @@ import com.cloud.network.vpc.Vpc; import com.cloud.user.Account; -@APICommand(name = "deleteVPC", description = "Deletes a VPC", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Vpc}, +@APICommand(name = "deleteVPC", description = "Deletes a VPC", responseObject = SuccessResponse.class, entityType = {Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVPCCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteVPCCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java index 160355a481..a985e7633c 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/ListPrivateGatewaysCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; @@ -31,9 +30,10 @@ import org.apache.cloudstack.api.response.VpcResponse; import com.cloud.network.vpc.PrivateGateway; +import com.cloud.network.vpc.VpcGateway; import com.cloud.utils.Pair; -@APICommand(name = "listPrivateGateways", description = "List private gateways", responseObject = PrivateGatewayResponse.class, entityType = {IAMEntityType.VpcGateway}, +@APICommand(name = "listPrivateGateways", description = "List private gateways", responseObject = PrivateGatewayResponse.class, entityType = {VpcGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListPrivateGatewaysCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListPrivateGatewaysCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/ListStaticRoutesCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/ListStaticRoutesCmd.java index b2cdf87911..3dba84c8a7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/ListStaticRoutesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/ListStaticRoutesCmd.java @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.List; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListTaggedResourcesCmd; @@ -32,7 +31,7 @@ import com.cloud.network.vpc.StaticRoute; import com.cloud.utils.Pair; -@APICommand(name = "listStaticRoutes", description = "Lists all static routes", responseObject = StaticRouteResponse.class, entityType = {IAMEntityType.StaticRoute}, +@APICommand(name = "listStaticRoutes", description = "Lists all static routes", responseObject = StaticRouteResponse.class, entityType = {StaticRoute.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListStaticRoutesCmd extends BaseListTaggedResourcesCmd { private static final String s_name = "liststaticroutesresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCOfferingsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCOfferingsCmd.java index 66ea17654a..e76afc92cd 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCOfferingsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCOfferingsCmd.java @@ -34,7 +34,7 @@ requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVPCOfferingsCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(ListVPCOfferingsCmd.class.getName()); - private static final String Name = "listvpcofferingsresponse"; + private static final String s_name = "listvpcofferingsresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -110,7 +110,7 @@ public void execute() { @Override public String getCommandName() { - return Name; + return s_name; } } diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCsCmd.java index fa60f6f773..9079dff11d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/ListVPCsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -36,7 +35,7 @@ import com.cloud.network.vpc.Vpc; -@APICommand(name = "listVPCs", description = "Lists VPCs", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = { IAMEntityType.Vpc }, +@APICommand(name = "listVPCs", description = "Lists VPCs", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = {Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVPCsCmd extends BaseListTaggedResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVPCsCmd.class.getName()); 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 d1d805ae48..84e790c3b2 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 @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -37,11 +36,11 @@ import com.cloud.network.vpc.Vpc; import com.cloud.user.Account; -@APICommand(name = "restartVPC", description = "Restarts a VPC", responseObject = VpcResponse.class, entityType = {IAMEntityType.Vpc}, +@APICommand(name = "restartVPC", description = "Restarts a VPC", responseObject = VpcResponse.class, entityType = {Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RestartVPCCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RestartVPCCmd.class.getName()); - private static final String Name = "restartvpcresponse"; + private static final String s_name = "restartvpcresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -63,7 +62,7 @@ public Long getId() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override 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 76244233b9..94d0e6efcd 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 @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; @@ -36,11 +35,11 @@ import com.cloud.network.vpc.Vpc; import com.cloud.user.Account; -@APICommand(name = "updateVPC", description = "Updates a VPC", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = { IAMEntityType.Vpc }, +@APICommand(name = "updateVPC", description = "Updates a VPC", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = {Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVPCCmd extends BaseAsyncCustomIdCmd { public static final Logger s_logger = Logger.getLogger(UpdateVPCCmd.class.getName()); - private static final String Name = "updatevpcresponse"; + private static final String s_name = "updatevpcresponse"; ///////////////////////////////////////////////////// //////////////// API parameters ///////////////////// @@ -83,7 +82,7 @@ public Boolean getDisplayVpc() { ///////////////////////////////////////////////////// @Override public String getCommandName() { - return Name; + return s_name; } @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java index e839f9feff..9993102eca 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/AddVpnUserCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -35,7 +34,7 @@ import com.cloud.network.VpnUser; import com.cloud.user.Account; -@APICommand(name = "addVpnUser", description = "Adds vpn users", responseObject = VpnUsersResponse.class, entityType = {IAMEntityType.VpnUser}, +@APICommand(name = "addVpnUser", description = "Adds vpn users", responseObject = VpnUsersResponse.class, entityType = {VpnUser.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class AddVpnUserCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(AddVpnUserCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java index 4df21345ec..2883b1999d 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateRemoteAccessVpnCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -38,7 +37,7 @@ import com.cloud.network.IpAddress; import com.cloud.network.RemoteAccessVpn; -@APICommand(name = "createRemoteAccessVpn", description = "Creates a l2tp/ipsec remote access vpn", responseObject = RemoteAccessVpnResponse.class, entityType = { IAMEntityType.RemoteAccessVpn }, +@APICommand(name = "createRemoteAccessVpn", description = "Creates a l2tp/ipsec remote access vpn", responseObject = RemoteAccessVpnResponse.class, entityType = {RemoteAccessVpn.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateRemoteAccessVpnCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateRemoteAccessVpnCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java index d405c17ac3..71245c340a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnConnectionCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -39,7 +38,7 @@ import com.cloud.network.vpc.Vpc; -@APICommand(name = "createVpnConnection", description = "Create site to site vpn connection", responseObject = Site2SiteVpnConnectionResponse.class, entityType = { IAMEntityType.Site2SiteVpnConnection }, +@APICommand(name = "createVpnConnection", description = "Create site to site vpn connection", responseObject = Site2SiteVpnConnectionResponse.class, entityType = {Site2SiteVpnConnection.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVpnConnectionCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateVpnConnectionCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java index 5da46f0ada..6967ff4978 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnCustomerGatewayCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -32,7 +31,7 @@ import com.cloud.event.EventTypes; import com.cloud.network.Site2SiteCustomerGateway; -@APICommand(name = "createVpnCustomerGateway", description = "Creates site to site vpn customer gateway", responseObject = Site2SiteCustomerGatewayResponse.class, entityType = {IAMEntityType.Site2SiteCustomerGateway}, +@APICommand(name = "createVpnCustomerGateway", description = "Creates site to site vpn customer gateway", responseObject = Site2SiteCustomerGatewayResponse.class, entityType = {Site2SiteCustomerGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVpnCustomerGatewayCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(CreateVpnCustomerGatewayCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java index 12abfb6e35..d5b5edbeee 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/CreateVpnGatewayCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -33,7 +32,7 @@ import com.cloud.network.Site2SiteVpnGateway; import com.cloud.network.vpc.Vpc; -@APICommand(name = "createVpnGateway", description = "Creates site to site vpn local gateway", responseObject = Site2SiteVpnGatewayResponse.class, entityType = { IAMEntityType.Site2SiteVpnGateway }, +@APICommand(name = "createVpnGateway", description = "Creates site to site vpn local gateway", responseObject = Site2SiteVpnGatewayResponse.class, entityType = {Site2SiteVpnGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVpnGatewayCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(CreateVpnGatewayCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java index 7d0c5aa5a4..f8941246d6 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseAsyncCmd; @@ -33,7 +32,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.RemoteAccessVpn; -@APICommand(name = "deleteRemoteAccessVpn", description = "Destroys a l2tp/ipsec remote access vpn", responseObject = SuccessResponse.class, entityType = {IAMEntityType.RemoteAccessVpn}, +@APICommand(name = "deleteRemoteAccessVpn", description = "Destroys a l2tp/ipsec remote access vpn", responseObject = SuccessResponse.class, entityType = {RemoteAccessVpn.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteRemoteAccessVpnCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteRemoteAccessVpnCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java index 6034bcb0de..a76b0c804e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnConnectionCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -33,7 +32,7 @@ import com.cloud.network.Site2SiteVpnConnection; import com.cloud.user.Account; -@APICommand(name = "deleteVpnConnection", description = "Delete site to site vpn connection", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Site2SiteVpnConnection}, +@APICommand(name = "deleteVpnConnection", description = "Delete site to site vpn connection", responseObject = SuccessResponse.class, entityType = {Site2SiteVpnConnection.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVpnConnectionCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteVpnConnectionCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java index 3faf5fd201..aad69ce0a9 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnCustomerGatewayCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; @@ -34,7 +33,7 @@ import com.cloud.network.Site2SiteCustomerGateway; import com.cloud.user.Account; -@APICommand(name = "deleteVpnCustomerGateway", description = "Delete site to site vpn customer gateway", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Site2SiteCustomerGateway}, +@APICommand(name = "deleteVpnCustomerGateway", description = "Delete site to site vpn customer gateway", responseObject = SuccessResponse.class, entityType = {Site2SiteCustomerGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVpnCustomerGatewayCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteVpnCustomerGatewayCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java index 66fd55bba2..ff927408a2 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteVpnGatewayCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -32,7 +31,7 @@ import com.cloud.network.Site2SiteVpnGateway; import com.cloud.user.Account; -@APICommand(name = "deleteVpnGateway", description = "Delete site to site vpn gateway", responseObject = SuccessResponse.class, entityType = {IAMEntityType.Site2SiteVpnGateway}, +@APICommand(name = "deleteVpnGateway", description = "Delete site to site vpn gateway", responseObject = SuccessResponse.class, entityType = {Site2SiteVpnGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class DeleteVpnGatewayCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(DeleteVpnGatewayCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/ListRemoteAccessVpnsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/ListRemoteAccessVpnsCmd.java index 61a3a2993b..492eaccefa 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/ListRemoteAccessVpnsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/ListRemoteAccessVpnsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -35,7 +34,7 @@ import com.cloud.network.RemoteAccessVpn; import com.cloud.utils.Pair; -@APICommand(name = "listRemoteAccessVpns", description = "Lists remote access vpns", responseObject = RemoteAccessVpnResponse.class, entityType = { IAMEntityType.RemoteAccessVpn }, +@APICommand(name = "listRemoteAccessVpns", description = "Lists remote access vpns", responseObject = RemoteAccessVpnResponse.class, entityType = {RemoteAccessVpn.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListRemoteAccessVpnsCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListRemoteAccessVpnsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnConnectionsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnConnectionsCmd.java index f8e81c2f01..74b9325eb2 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnConnectionsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnConnectionsCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,7 @@ import com.cloud.network.Site2SiteVpnConnection; import com.cloud.utils.Pair; -@APICommand(name = "listVpnConnections", description = "Lists site to site vpn connection gateways", responseObject = Site2SiteVpnConnectionResponse.class, entityType = { IAMEntityType.Site2SiteVpnConnection }, +@APICommand(name = "listVpnConnections", description = "Lists site to site vpn connection gateways", responseObject = Site2SiteVpnConnectionResponse.class, entityType = {Site2SiteVpnConnection.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVpnConnectionsCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVpnConnectionsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnCustomerGatewaysCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnCustomerGatewaysCmd.java index fed96a72b3..6b870be138 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnCustomerGatewaysCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnCustomerGatewaysCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; @@ -32,7 +31,7 @@ import com.cloud.network.Site2SiteCustomerGateway; import com.cloud.utils.Pair; -@APICommand(name = "listVpnCustomerGateways", description = "Lists site to site vpn customer gateways", responseObject = Site2SiteCustomerGatewayResponse.class, entityType = {IAMEntityType.Site2SiteCustomerGateway}, +@APICommand(name = "listVpnCustomerGateways", description = "Lists site to site vpn customer gateways", responseObject = Site2SiteCustomerGatewayResponse.class, entityType = {Site2SiteCustomerGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVpnCustomerGatewaysCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVpnCustomerGatewaysCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnGatewaysCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnGatewaysCmd.java index 17702252e8..3eade02880 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnGatewaysCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnGatewaysCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -34,7 +33,7 @@ import com.cloud.network.Site2SiteVpnGateway; import com.cloud.utils.Pair; -@APICommand(name = "listVpnGateways", description = "Lists site 2 site vpn gateways", responseObject = Site2SiteVpnGatewayResponse.class, entityType = { IAMEntityType.Site2SiteVpnGateway }, +@APICommand(name = "listVpnGateways", description = "Lists site 2 site vpn gateways", responseObject = Site2SiteVpnGatewayResponse.class, entityType = {Site2SiteVpnGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVpnGatewaysCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVpnGatewaysCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnUsersCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnUsersCmd.java index 1d8ea85cbb..9af060ac00 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnUsersCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/ListVpnUsersCmd.java @@ -21,7 +21,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListProjectAndAccountResourcesCmd; @@ -32,7 +31,7 @@ import com.cloud.network.VpnUser; import com.cloud.utils.Pair; -@APICommand(name = "listVpnUsers", description = "Lists vpn users", responseObject = VpnUsersResponse.class, entityType = {IAMEntityType.VpnUser}, +@APICommand(name = "listVpnUsers", description = "Lists vpn users", responseObject = VpnUsersResponse.class, entityType = {VpnUser.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ListVpnUsersCmd extends BaseListProjectAndAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListVpnUsersCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/RemoveVpnUserCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/RemoveVpnUserCmd.java index 068746945c..f552b14fbf 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/RemoveVpnUserCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/RemoveVpnUserCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -31,9 +30,10 @@ import org.apache.cloudstack.context.CallContext; import com.cloud.event.EventTypes; +import com.cloud.network.VpnUser; import com.cloud.user.Account; -@APICommand(name = "removeVpnUser", description = "Removes vpn user", responseObject = SuccessResponse.class, entityType = {IAMEntityType.VpnUser}, +@APICommand(name = "removeVpnUser", description = "Removes vpn user", responseObject = SuccessResponse.class, entityType = {VpnUser.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class RemoveVpnUserCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RemoveVpnUserCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java index 21eb182d0b..75e74adcda 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/ResetVpnConnectionCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -34,7 +33,7 @@ import com.cloud.network.Site2SiteVpnConnection; import com.cloud.user.Account; -@APICommand(name = "resetVpnConnection", description = "Reset site to site vpn connection", responseObject = Site2SiteVpnConnectionResponse.class, entityType = {IAMEntityType.Site2SiteVpnConnection}, +@APICommand(name = "resetVpnConnection", description = "Reset site to site vpn connection", responseObject = Site2SiteVpnConnectionResponse.class, entityType = {Site2SiteVpnConnection.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class ResetVpnConnectionCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(ResetVpnConnectionCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java index 9e178efc0e..ceb67d510a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/UpdateVpnCustomerGatewayCmd.java @@ -18,7 +18,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -32,7 +31,7 @@ import com.cloud.event.EventTypes; import com.cloud.network.Site2SiteCustomerGateway; -@APICommand(name = "updateVpnCustomerGateway", description = "Update site to site vpn customer gateway", responseObject = Site2SiteCustomerGatewayResponse.class, entityType = {IAMEntityType.Site2SiteCustomerGateway}, +@APICommand(name = "updateVpnCustomerGateway", description = "Update site to site vpn customer gateway", responseObject = Site2SiteCustomerGatewayResponse.class, entityType = {Site2SiteCustomerGateway.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class UpdateVpnCustomerGatewayCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(UpdateVpnCustomerGatewayCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/response/AccountResponse.java b/api/src/org/apache/cloudstack/api/response/AccountResponse.java index 991b162ac1..2e50c51858 100644 --- a/api/src/org/apache/cloudstack/api/response/AccountResponse.java +++ b/api/src/org/apache/cloudstack/api/response/AccountResponse.java @@ -240,7 +240,7 @@ public class AccountResponse extends BaseResponse implements ResourceLimitAndCou private Boolean isDefault; @SerializedName(ApiConstants.IAM_GROUPS) - @Param(description = "the list of acl groups that account belongs to") + @Param(description = "the list of acl groups that account belongs to", since = "4.4") private List groups; @Override diff --git a/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java b/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java index c8de587336..f7fdb95fb6 100644 --- a/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java +++ b/api/src/org/apache/cloudstack/api/response/CapabilitiesResponse.java @@ -49,6 +49,10 @@ public class CapabilitiesResponse extends BaseResponse { @Param(description = "true if regular user is allowed to create projects") private Boolean allowUsersCreateProjects; + @SerializedName(ApiConstants.CUSTOM_DISK_OFF_MIN_SIZE) + @Param(description = "minimum size that can be specified when " + "create disk from disk offering with custom size") + private Long diskOffMinSize; + @SerializedName(ApiConstants.CUSTOM_DISK_OFF_MAX_SIZE) @Param(description = "maximum size that can be specified when " + "create disk from disk offering with custom size") private Long diskOffMaxSize; @@ -93,6 +97,10 @@ public void setAllowUsersCreateProjects(Boolean allowUsersCreateProjects) { this.allowUsersCreateProjects = allowUsersCreateProjects; } + public void setDiskOffMinSize(Long diskOffMinSize) { + this.diskOffMinSize = diskOffMinSize; + } + public void setDiskOffMaxSize(Long diskOffMaxSize) { this.diskOffMaxSize = diskOffMaxSize; } diff --git a/api/src/org/apache/cloudstack/api/response/DiskOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/DiskOfferingResponse.java index 0894eeced3..91bd441353 100644 --- a/api/src/org/apache/cloudstack/api/response/DiskOfferingResponse.java +++ b/api/src/org/apache/cloudstack/api/response/DiskOfferingResponse.java @@ -74,7 +74,7 @@ public class DiskOfferingResponse extends BaseResponse { private Long maxIops; @SerializedName(ApiConstants.HYPERVISOR_SNAPSHOT_RESERVE) - @Param(description = "Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)") + @Param(description = "Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)", since = "4.4") private Integer hypervisorSnapshotReserve; @SerializedName(ApiConstants.TAGS) @@ -102,7 +102,7 @@ public class DiskOfferingResponse extends BaseResponse { private Long iopsWriteRate; @SerializedName("cacheMode") - @Param(description = "the cache mode to use for this disk offering. none, writeback or writethrough") + @Param(description = "the cache mode to use for this disk offering. none, writeback or writethrough", since = "4.4") private String cacheMode; @SerializedName("displayoffering") diff --git a/api/src/org/apache/cloudstack/api/response/GetVMPasswordResponse.java b/api/src/org/apache/cloudstack/api/response/GetVMPasswordResponse.java index c72031b822..7a4543d437 100644 --- a/api/src/org/apache/cloudstack/api/response/GetVMPasswordResponse.java +++ b/api/src/org/apache/cloudstack/api/response/GetVMPasswordResponse.java @@ -25,7 +25,7 @@ public class GetVMPasswordResponse extends BaseResponse { @SerializedName("encryptedpassword") - @Param(description = "The encrypted password of the VM") + @Param(description = "The base64 encoded encrypted password of the VM") private String encryptedPassword; public GetVMPasswordResponse() { diff --git a/api/src/org/apache/cloudstack/api/response/HostResponse.java b/api/src/org/apache/cloudstack/api/response/HostResponse.java index 1fbc6684e1..008631ff7d 100644 --- a/api/src/org/apache/cloudstack/api/response/HostResponse.java +++ b/api/src/org/apache/cloudstack/api/response/HostResponse.java @@ -137,7 +137,7 @@ public class HostResponse extends BaseResponse { private Long memoryUsed; @SerializedName(ApiConstants.GPUGROUP) - @Param(description = "GPU cards present in the host", responseObject = GpuResponse.class) + @Param(description = "GPU cards present in the host", responseObject = GpuResponse.class, since = "4.4") private List gpuGroup; @SerializedName("disksizetotal") diff --git a/api/src/org/apache/cloudstack/api/response/LoadBalancerRuleVmMapResponse.java b/api/src/org/apache/cloudstack/api/response/LoadBalancerRuleVmMapResponse.java new file mode 100644 index 0000000000..57c45e6432 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/LoadBalancerRuleVmMapResponse.java @@ -0,0 +1,54 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.response; + +import com.cloud.network.router.VirtualRouter; +import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; +import com.google.gson.annotations.SerializedName; + +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import com.cloud.serializer.Param; + +import java.util.List; + +@EntityReference(value = {VirtualMachine.class, UserVm.class, VirtualRouter.class}) +@SuppressWarnings("unused") +public class LoadBalancerRuleVmMapResponse extends BaseResponse { + + + @SerializedName("loadbalancerruleinstance") + @Param(description = "the user vm set for lb rule") + private UserVmResponse UserVmResponse; + + @SerializedName("lbvmipaddresses") + @Param(description = "IP addresses of the vm set of lb rule") + private List ipAddr; + + public void setIpAddr(List ipAddr) { + this.ipAddr = ipAddr; + } + + public void setUserVmResponse(UserVmResponse userVmResponse) { + this.UserVmResponse = userVmResponse; + } + + + +} diff --git a/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java index 8219147726..775c9a8fdd 100644 --- a/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java +++ b/api/src/org/apache/cloudstack/api/response/NetworkOfferingResponse.java @@ -109,13 +109,17 @@ public class NetworkOfferingResponse extends BaseResponse { private Map details; @SerializedName(ApiConstants.EGRESS_DEFAULT_POLICY) - @Param(description = "true if network offering supports persistent networks, false otherwise") + @Param(description = "true if guest network default egress policy is allow; false if default egress policy is deny") private Boolean egressDefaultPolicy; @SerializedName(ApiConstants.MAX_CONNECTIONS) @Param(description = "maximum number of concurrents connections to be handled by lb") private Integer concurrentConnections; + @SerializedName(ApiConstants.SUPPORTS_STRECHED_L2_SUBNET) + @Param(description = "true if network offering supports network that span multiple zones", since = "4.4") + private Boolean supportsStrechedL2Subnet; + public void setId(String id) { this.id = id; } @@ -200,4 +204,7 @@ public void setConcurrentConnections(Integer concurrentConnections) { this.concurrentConnections = concurrentConnections; } + public void setSupportsStrechedL2Subnet(Boolean supportsStrechedL2Subnet) { + this.supportsStrechedL2Subnet = supportsStrechedL2Subnet; + } } diff --git a/api/src/org/apache/cloudstack/api/response/NetworkResponse.java b/api/src/org/apache/cloudstack/api/response/NetworkResponse.java index bf92aa4f78..40c90729cd 100644 --- a/api/src/org/apache/cloudstack/api/response/NetworkResponse.java +++ b/api/src/org/apache/cloudstack/api/response/NetworkResponse.java @@ -18,6 +18,7 @@ import java.util.List; +import java.util.Set; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; @@ -216,6 +217,14 @@ public class NetworkResponse extends BaseResponse implements ControlledEntityRes @Param(description = "ACL Id associated with the VPC network") private String aclId; + @SerializedName(ApiConstants.STRECHED_L2_SUBNET) + @Param(description = "true if network can span multiple zones", since = "4.4") + private Boolean strechedL2Subnet; + + @SerializedName(ApiConstants.NETWORK_SPANNED_ZONES) + @Param(description = "If a network is enabled for 'streched l2 subnet' then represents zones on which network currently spans", since = "4.4") + private Set networkSpannedZones; + public Boolean getDisplayNetwork() { return displayNetwork; } @@ -412,4 +421,12 @@ public String getAclId() { public void setAclId(String aclId) { this.aclId = aclId; } + + public void setStrechedL2Subnet(Boolean strechedL2Subnet) { + this.strechedL2Subnet = strechedL2Subnet; + } + + public void setNetworkSpannedZones(Set networkSpannedZones) { + this.networkSpannedZones = networkSpannedZones; + } } diff --git a/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java index d371f9a925..764ade510a 100644 --- a/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java +++ b/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java @@ -107,19 +107,19 @@ public class ServiceOfferingResponse extends BaseResponse { private Integer networkRate; @SerializedName("iscustomizediops") - @Param(description = "true if disk offering uses custom iops, false otherwise") + @Param(description = "true if disk offering uses custom iops, false otherwise", since = "4.4") private Boolean customizedIops; @SerializedName(ApiConstants.MIN_IOPS) - @Param(description = "the min iops of the disk offering") + @Param(description = "the min iops of the disk offering", since = "4.4") private Long minIops; @SerializedName(ApiConstants.MAX_IOPS) - @Param(description = "the max iops of the disk offering") + @Param(description = "the max iops of the disk offering", since = "4.4") private Long maxIops; @SerializedName(ApiConstants.HYPERVISOR_SNAPSHOT_RESERVE) - @Param(description = "Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)") + @Param(description = "Hypervisor snapshot reserve space as a percent of a volume (for managed storage using Xen or VMware)", since = "4.4") private Integer hypervisorSnapshotReserve; @SerializedName("diskBytesReadRate") diff --git a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java index 98c90e2fd3..3571866fe7 100644 --- a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java +++ b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java @@ -108,8 +108,8 @@ public class StoragePoolResponse extends BaseResponse { private String scope; @SerializedName("overprovisionfactor") - @Param(description = "the overprovisionfactor for the storage pool") - private String overprovisionfactor; + @Param(description = "the overprovisionfactor for the storage pool", since = "4.4") + private String overProvisionFactor; @SerializedName(ApiConstants.HYPERVISOR) @Param(description = "the hypervisor type of the storage pool") @@ -307,6 +307,6 @@ public void setSuitableForMigration(Boolean suitableForMigration) { } public void setOverProvisionFactor(String overProvisionFactor) { - this.overprovisionfactor = overProvisionFactor; + this.overProvisionFactor = overProvisionFactor; } } diff --git a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java index d6ce84f495..9fe3475f57 100644 --- a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java +++ b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java @@ -141,11 +141,11 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp private String serviceOfferingName; @SerializedName(ApiConstants.DISK_OFFERING_ID) - @Param(description = "the ID of the disk offering of the virtual machine") + @Param(description = "the ID of the disk offering of the virtual machine", since = "4.4") private String diskOfferingId; @SerializedName("diskofferingname") - @Param(description = "the name of the disk offering of the virtual machine") + @Param(description = "the name of the disk offering of the virtual machine", since = "4.4") private String diskOfferingName; @SerializedName("forvirtualnetwork") @@ -165,7 +165,7 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp private Integer memory; @SerializedName(ApiConstants.VGPU) - @Param(description = "the vgpu type used by the virtual machine") + @Param(description = "the vgpu type used by the virtual machine", since = "4.4") private String vgpu; @SerializedName("cpuused") diff --git a/api/src/org/apache/cloudstack/api/response/VgpuResponse.java b/api/src/org/apache/cloudstack/api/response/VgpuResponse.java index 17e194be5b..c51dc8d0f6 100644 --- a/api/src/org/apache/cloudstack/api/response/VgpuResponse.java +++ b/api/src/org/apache/cloudstack/api/response/VgpuResponse.java @@ -29,24 +29,63 @@ public class VgpuResponse extends BaseResponse { @Param(description = "Model Name of vGPU") private String name; + @SerializedName(ApiConstants.VIDEORAM) + @Param(description = "Video RAM for this vGPU type") + private Long videoRam; + + @SerializedName(ApiConstants.MAXHEADS) + @Param(description = "Maximum displays per user") + private Long maxHeads; + + @SerializedName(ApiConstants.MAXRESOLUTIONX) + @Param(description = "Maximum X resolution per display") + private Long maxResolutionX; + + @SerializedName(ApiConstants.MAXRESOLUTIONY) + @Param(description = "Maximum Y resolution per display") + private Long maxResolutionY; + + @SerializedName(ApiConstants.MAXVGPUPERPGPU) + @Param(description = "Maximum no. of vgpu per gpu card (pgpu)") + private Long maxVgpuPerPgpu; + @SerializedName(ApiConstants.REMAININGCAPACITY) - @Param(description = "No. of more VMs can be deployped with this vGPU type") - private Long capacity; + @Param(description = "Remaining capacity in terms of no. of more VMs that can be deployped with this vGPU type") + private Long remainingCapacity; - public String getName() { - return name; - } + @SerializedName(ApiConstants.MAXCAPACITY) + @Param(description = "Maximum vgpu can be created with this vgpu type on the given gpu group") + private Long maxCapacity; public void setName(String name) { this.name = name; } - public Long getCapacity() { - return capacity; + public void setVideoRam(Long videoRam) { + this.videoRam = videoRam; + } + + public void setMaxHeads(Long maxHeads) { + this.maxHeads = maxHeads; } - public void setCapacity(Long capacity) { - this.capacity = capacity; + public void setMaxResolutionX(Long maxResolutionX) { + this.maxResolutionX = maxResolutionX; } + public void setMaxResolutionY(Long maxResolutionY) { + this.maxResolutionY = maxResolutionY; + } + + public void setMaxVgpuPerPgpu(Long maxVgpuPerPgpu) { + this.maxVgpuPerPgpu = maxVgpuPerPgpu; + } + + public void setRemainingCapacity(Long remainingCapacity) { + this.remainingCapacity = remainingCapacity; + } + + public void setmaxCapacity(Long maxCapacity) { + this.maxCapacity = maxCapacity; + } } diff --git a/api/src/org/apache/cloudstack/api/response/VolumeResponse.java b/api/src/org/apache/cloudstack/api/response/VolumeResponse.java index 27e95def02..45c15daa6a 100644 --- a/api/src/org/apache/cloudstack/api/response/VolumeResponse.java +++ b/api/src/org/apache/cloudstack/api/response/VolumeResponse.java @@ -204,6 +204,11 @@ public class VolumeResponse extends BaseResponse implements ControlledViewEntity @Param(description = "the chain info of the volume", since = "4.4") String chainInfo; + @SerializedName(ApiConstants.SNAPSHOT_QUIESCEVM) + @Param(description = "need quiesce vm or not when taking snapshot", since="4.3") + private boolean needQuiescevm; + + public String getPath() { return path; } @@ -425,4 +430,18 @@ public String getChainInfo() { public void setChainInfo(String chainInfo) { this.chainInfo = chainInfo; } + + public String getStoragePoolId() { + return storagePoolId; + } + + public void setNeedQuiescevm(boolean quiescevm) { + this.needQuiescevm = quiescevm; + } + + public boolean isNeedQuiescevm() { + return this.needQuiescevm; + } + + } diff --git a/api/src/org/apache/cloudstack/api/response/VpcOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/VpcOfferingResponse.java index 89697f04ad..512746fb6a 100644 --- a/api/src/org/apache/cloudstack/api/response/VpcOfferingResponse.java +++ b/api/src/org/apache/cloudstack/api/response/VpcOfferingResponse.java @@ -60,9 +60,13 @@ public class VpcOfferingResponse extends BaseResponse { private List services; @SerializedName(ApiConstants.DISTRIBUTED_VPC_ROUTER) - @Param(description = " indicates if the vpc offering supports distributed router for one-hop forwarding") + @Param(description = " indicates if the vpc offering supports distributed router for one-hop forwarding", since = "4.4") private Boolean supportsDistributedRouter; + @SerializedName((ApiConstants.SUPPORTS_REGION_LEVEL_VPC)) + @Param(description = " indicated if the offering can support region level vpc", since = "4.4") + private Boolean supportsRegionLevelVpc; + public void setId(String id) { this.id = id; } @@ -94,4 +98,8 @@ public void setState(String state) { public void setSupportsDistributedRouter(Boolean supportsDistributedRouter) { this.supportsDistributedRouter = supportsDistributedRouter; } + + public void setSupportsRegionLevelVpc(Boolean supports) { + this.supportsRegionLevelVpc = supports; + } } diff --git a/api/src/org/apache/cloudstack/api/response/VpcResponse.java b/api/src/org/apache/cloudstack/api/response/VpcResponse.java index e3b44f2113..d1afdfb816 100644 --- a/api/src/org/apache/cloudstack/api/response/VpcResponse.java +++ b/api/src/org/apache/cloudstack/api/response/VpcResponse.java @@ -111,11 +111,14 @@ public class VpcResponse extends BaseResponse implements ControlledEntityRespons @Param(description = "is vpc for display to the regular user", since = "4.4", authorized = {RoleType.Admin}) private Boolean forDisplay; - @SerializedName(ApiConstants.DISTRIBUTED_VPC_ROUTER) - @Param(description = "is VPC uses distributed router for one hop forwarding and host based network ACL's") + @Param(description = "is VPC uses distributed router for one hop forwarding and host based network ACL's", since = "4.4") private boolean usesDistributedRouter; + @SerializedName((ApiConstants.REGION_LEVEL_VPC)) + @Param(description = "true if VPC is region level", since = "4.4") + private Boolean regionLevelVpc; + public void setId(String id) { this.id = id; } @@ -205,6 +208,10 @@ public void setForDisplay(Boolean forDisplay) { this.forDisplay = forDisplay; } + public void setRegionLevelVpc(Boolean regionLevelVpc) { + this.regionLevelVpc = regionLevelVpc; + } + public void setUsesDistributedRouter(Boolean usesDistributedRouter) { this.usesDistributedRouter = usesDistributedRouter; } diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties index c46361a12e..9f2baa104f 100644 --- a/client/WEB-INF/classes/resources/messages.properties +++ b/client/WEB-INF/classes/resources/messages.properties @@ -14,6 +14,12 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. +message.listView.subselect.multi=(Ctrl/Cmd-click) +label.use.vm.ips=Use VM IPs +label.reinstall.vm=Reinstall VM +message.reinstall.vm=NOTE: Proceed with caution. This will cause the VM to be reinstalled from the template; data on the root disk will be lost. Extra data volumes, if any, will not be touched. +label.recover.vm=Recover VM +message.recover.vm=Please confirm that you would like to recover this VM. label.port=Port label.remove.ldap=Remove LDAP label.configure.ldap=Configure LDAP @@ -1481,6 +1487,12 @@ label.allow=Allow label.deny=Deny label.default.egress.policy=Default egress policy label.xenserver.tools.version.61.plus=XenServer Tools Version 6.1\+ +label.gpu=GPU +label.vgpu.type=vGPU type +label.vgpu.video.ram=Video RAM +label.vgpu.max.resolution=Max resolution +label.vgpu.max.vgpu.per.gpu=vGPUs per GPU +label.vgpu.remaining.capacity=Remaining capacity managed.state=Managed State message.acquire.new.ip.vpc=Please confirm that you would like to acquire a new IP for this VPC. message.acquire.new.ip=Please confirm that you would like to acquire a new IP for this network. @@ -1780,7 +1792,7 @@ message.tooltip.reserved.system.netmask=The network prefix that defines the pod message.tooltip.zone.name=A name for the zone. message.update.os.preference=Please choose a OS preference for this host. All virtual instances with similar preferences will be first allocated to this host before choosing another. message.update.resource.count=Please confirm that you want to update resource counts for this account. -message.update.ssl=Please submit a new X.509 compliant SSL certificate to be updated to each console proxy virtual instance\: +message.update.ssl=Please submit a new X.509 compliant SSL certificate to be updated to each console proxy and secondary storage virtual instance\: message.validate.instance.name=Instance name can not be longer than 63 characters. Only ASCII letters a~z, A~Z, digits 0~9, hyphen are allowed. Must start with a letter and end with a letter or a digit. message.virtual.network.desc=A dedicated virtualized network for your account. The broadcast domain is contained within a VLAN and all public network access is routed out by a virtual router. message.vm.create.template.confirm=Create Template will reboot the VM automatically. @@ -1793,7 +1805,7 @@ message.zone.no.network.selection=The zone you selected does not have any choice message.zone.step.1.desc=Please select a network model for your zone. message.zone.step.2.desc=Please enter the following info to add a new zone message.zone.step.3.desc=Please enter the following info to add a new pod -message.zoneWizard.enable.local.storage=WARNING\: If you enable local storage for this zone, you must do the following, depending on where you would like your system VMs to launch\:

1. If system VMs need to be launched in primary storage, primary storage needs to be added to the zone after creation. You must also start the zone in a disabled state.

2. If system VMs need to be launched in local storage, system.vm.use.local.storage needs to be set to true before you enable the zone.


Would you like to continue? +message.zoneWizard.enable.local.storage=WARNING\: If you enable local storage for this zone, you must do the following, depending on where you would like your system VMs to launch\:

1. If system VMs need to be launched in shared primary storage, shared primary storage needs to be added to the zone after creation. You must also start the zone in a disabled state.

2. If system VMs need to be launched in local primary storage, system.vm.use.local.storage needs to be set to true before you enable the zone.


Would you like to continue? message.validate.fieldrequired=This field is required. message.validate.fixfield=Please fix this field. message.validate.email.address=Please enter a valid email address. diff --git a/client/pom.xml b/client/pom.xml index 74c459e769..eda8a8560f 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -35,6 +35,11 @@ cloud-plugin-storage-volume-solidfire ${project.version} + + org.apache.cloudstack + cloud-plugin-storage-volume-cloudbyte + ${project.version} + org.apache.cloudstack cloud-server diff --git a/core/src/com/cloud/agent/api/GetGPUStatsAnswer.java b/core/src/com/cloud/agent/api/GetGPUStatsAnswer.java index 566eed5ab6..583326b839 100644 --- a/core/src/com/cloud/agent/api/GetGPUStatsAnswer.java +++ b/core/src/com/cloud/agent/api/GetGPUStatsAnswer.java @@ -23,14 +23,14 @@ @LogLevel(Log4jLevel.Trace) public class GetGPUStatsAnswer extends Answer { - private HashMap> groupDetails; + private HashMap> groupDetails; - public GetGPUStatsAnswer(GetGPUStatsCommand cmd, HashMap> groupDetails) { + public GetGPUStatsAnswer(GetGPUStatsCommand cmd, HashMap> groupDetails) { super(cmd); this.groupDetails = groupDetails; } - public HashMap> getGroupDetails() { + public HashMap> getGroupDetails() { return this.groupDetails; } } diff --git a/core/src/com/cloud/agent/api/GetRouterAlertsAnswer.java b/core/src/com/cloud/agent/api/GetRouterAlertsAnswer.java index 06a7a7a84e..31485396f4 100644 --- a/core/src/com/cloud/agent/api/GetRouterAlertsAnswer.java +++ b/core/src/com/cloud/agent/api/GetRouterAlertsAnswer.java @@ -22,7 +22,6 @@ public class GetRouterAlertsAnswer extends Answer { - String routerName; String[] alerts; String timeStamp; @@ -36,8 +35,8 @@ public GetRouterAlertsAnswer(GetRouterAlertsCommand cmd, String alerts[], String } - public GetRouterAlertsAnswer(GetRouterAlertsCommand cmd, Exception ex) { - super(cmd, ex); + public GetRouterAlertsAnswer(GetRouterAlertsCommand cmd, String details) { + super(cmd, false, details); } public void setAlerts(String[] alerts) { @@ -56,7 +55,4 @@ public String getTimeStamp() { return timeStamp; } - public String getRouterName() { - return routerName; - } } diff --git a/core/src/com/cloud/agent/api/PoolEjectCommand.java b/core/src/com/cloud/agent/api/PoolEjectCommand.java deleted file mode 100644 index fa6b651797..0000000000 --- a/core/src/com/cloud/agent/api/PoolEjectCommand.java +++ /dev/null @@ -1,44 +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.agent.api; - -public class PoolEjectCommand extends Command { - private String hostuuid; - - public String getHostuuid() { - return hostuuid; - } - - public void setHostuuid(String hostuuid) { - this.hostuuid = hostuuid; - } - - public PoolEjectCommand() { - super(); - } - - public PoolEjectCommand(String hostuuid) { - super(); - setHostuuid(hostuuid); - } - - @Override - public boolean executeInSequence() { - return true; - } - -} diff --git a/core/src/com/cloud/agent/api/StartupRoutingCommand.java b/core/src/com/cloud/agent/api/StartupRoutingCommand.java index dc37113386..52814eac9a 100755 --- a/core/src/com/cloud/agent/api/StartupRoutingCommand.java +++ b/core/src/com/cloud/agent/api/StartupRoutingCommand.java @@ -70,7 +70,7 @@ public String getHost() { HypervisorType hypervisorType; Map hostDetails; //stuff like host os, cpu capabilities String hypervisorVersion; - HashMap> groupDetails = new HashMap>(); + HashMap> groupDetails = new HashMap>(); public StartupRoutingCommand() { super(Host.Type.Routing); @@ -246,11 +246,11 @@ public void setHostVmStateReport(Map hostVmState this._hostVmStateReport = hostVmStateReport; } - public HashMap> getGpuGroupDetails() { + public HashMap> getGpuGroupDetails() { return groupDetails; } - public void setGpuGroupDetails(HashMap> groupDetails) { + public void setGpuGroupDetails(HashMap> groupDetails) { this.groupDetails = groupDetails; } } diff --git a/core/src/com/cloud/agent/api/StopCommand.java b/core/src/com/cloud/agent/api/StopCommand.java index 00d7f5fff6..61d13e0f8e 100755 --- a/core/src/com/cloud/agent/api/StopCommand.java +++ b/core/src/com/cloud/agent/api/StopCommand.java @@ -25,26 +25,30 @@ public class StopCommand extends RebootCommand { private String publicConsoleProxyIpAddress = null; boolean executeInSequence = false; private GPUDeviceTO gpuDevice; + boolean checkBeforeCleanup = false; protected StopCommand() { } - public StopCommand(VirtualMachine vm, boolean isProxy, String urlPort, String publicConsoleProxyIpAddress, boolean executeInSequence) { + public StopCommand(VirtualMachine vm, boolean isProxy, String urlPort, String publicConsoleProxyIpAddress, boolean executeInSequence, boolean checkBeforeCleanup) { super(vm); this.isProxy = isProxy; this.urlPort = urlPort; this.publicConsoleProxyIpAddress = publicConsoleProxyIpAddress; this.executeInSequence = executeInSequence; + this.checkBeforeCleanup = checkBeforeCleanup; } - public StopCommand(VirtualMachine vm, boolean executeInSequence) { + public StopCommand(VirtualMachine vm, boolean executeInSequence, boolean checkBeforeCleanup) { super(vm); this.executeInSequence = executeInSequence; + this.checkBeforeCleanup = checkBeforeCleanup; } - public StopCommand(String vmName, boolean executeInSequence) { + public StopCommand(String vmName, boolean executeInSequence, boolean checkBeforeCleanup) { super(vmName); this.executeInSequence = executeInSequence; + this.checkBeforeCleanup = checkBeforeCleanup; } @Override @@ -71,4 +75,8 @@ public GPUDeviceTO getGpuDevice() { public void setGpuDevice(GPUDeviceTO gpuDevice) { this.gpuDevice = gpuDevice; } + + public boolean checkBeforeCleanup() { + return this.checkBeforeCleanup; + } } diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRouterDeployer.java b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRouterDeployer.java index 243098abea..1feaaead9f 100644 --- a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRouterDeployer.java +++ b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRouterDeployer.java @@ -21,6 +21,8 @@ public interface VirtualRouterDeployer { ExecutionResult executeInVR(String routerIp, String script, String args); + /* timeout in seconds */ + ExecutionResult executeInVR(String routerIp, String script, String args, int timeout); ExecutionResult createFileInVR(String routerIp, String path, String filename, String content); ExecutionResult prepareCommand(NetworkElementCommand cmd); ExecutionResult cleanupCommand(NetworkElementCommand cmd); diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index e13fbf651c..3b43853343 100755 --- a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -649,25 +649,23 @@ private CheckS2SVpnConnectionsAnswer execute(CheckS2SVpnConnectionsCommand cmd) private GetRouterAlertsAnswer execute(GetRouterAlertsCommand cmd) { - String args = null; String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); - if (cmd.getPreviousAlertTimeStamp() != null) { - args = cmd.getPreviousAlertTimeStamp(); - } + String args = cmd.getPreviousAlertTimeStamp(); ExecutionResult result = _vrDeployer.executeInVR(routerIp, VRScripts.ROUTER_ALERTS, args); String alerts[] = null; String lastAlertTimestamp = null; - // CallHostPlugin results "success" when there are no alerts on virtual router + if (result.isSuccess()) { - if (!result.getDetails().isEmpty() && !result.getDetails().equals("No Alerts")) { - alerts = result.getDetails().split("\\\\n"); - String[] lastAlert = alerts[alerts.length - 1].split(" "); - lastAlertTimestamp = lastAlert[0] + " " + lastAlert[1]; + if (!result.getDetails().isEmpty() && !result.getDetails().trim().equals("No Alerts")) { + alerts = result.getDetails().trim().split("\\\\n"); + String[] lastAlert = alerts[alerts.length - 1].split(","); + lastAlertTimestamp = lastAlert[0]; } + return new GetRouterAlertsAnswer(cmd, alerts, lastAlertTimestamp); + } else { + return new GetRouterAlertsAnswer(cmd, result.getDetails()); } - - return new GetRouterAlertsAnswer(cmd, alerts, lastAlertTimestamp); } protected Answer execute(CheckRouterCommand cmd) { @@ -760,21 +758,6 @@ protected List generateConfig(SetMonitorServiceCommand cmd) { return cfg; } - protected List generateConfig(GetRouterAlertsCommand cmd) { - LinkedList cfg = new LinkedList<>(); - - String args = null; - String routerIp = cmd.getAccessDetail(NetworkElementCommand.ROUTER_IP); - if (cmd.getPreviousAlertTimeStamp() != null) { - args = "getRouterAlerts.sh " + routerIp + " " + cmd.getPreviousAlertTimeStamp(); - } else { - args = "getRouterAlerts.sh " + routerIp; - } - - cfg.add(new ConfigItem(VRScripts.ROUTER_ALERTS, args)); - return cfg; - } - protected List generateConfig(SetupGuestNetworkCommand cmd) { LinkedList cfg = new LinkedList<>(); @@ -1137,11 +1120,13 @@ private Answer execute(AggregationControlCommand cmd) { return new Answer(cmd); } else if (action == Action.Finish) { Queue queue = _vrAggregateCommandsSet.get(routerName); + int answerCounts = 0; try { StringBuilder sb = new StringBuilder(); sb.append("#Apache CloudStack Virtual Router Config File\n"); sb.append("\n" + _cfgVersion + "\n\n"); for (NetworkElementCommand command : queue) { + answerCounts += command.getAnswersCount(); List cfg = generateCommandCfg(command); if (cfg == null) { s_logger.warn("Unknown commands for VirtualRoutingResource, but continue: " + cmd.toString()); @@ -1168,7 +1153,12 @@ private Answer execute(AggregationControlCommand cmd) { return new Answer(cmd, false, result.getDetails()); } - result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), VRScripts.VR_CFG, "-c " + cfgFilePath + cfgFileName); + // 3 second for each answer should be enough, and 120s is the minimal timeout + int timeout = answerCounts * 3; + if (timeout < 120) { + timeout = 120; + } + result = _vrDeployer.executeInVR(cmd.getRouterAccessIp(), VRScripts.VR_CFG, "-c " + cfgFilePath + cfgFileName, timeout); if (!result.isSuccess()) { return new Answer(cmd, false, result.getDetails()); } diff --git a/core/src/org/apache/cloudstack/storage/command/AttachCommand.java b/core/src/org/apache/cloudstack/storage/command/AttachCommand.java index 7e47ba4e31..303457b4a4 100644 --- a/core/src/org/apache/cloudstack/storage/command/AttachCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/AttachCommand.java @@ -24,6 +24,7 @@ public final class AttachCommand extends Command implements StorageSubSystemCommand { private DiskTO disk; private String vmName; + private boolean inSeq = false; public AttachCommand(DiskTO disk, String vmName) { super(); @@ -51,4 +52,9 @@ public String getVmName() { public void setVmName(String vmName) { this.vmName = vmName; } + + @Override + public void setExecuteInSequence(boolean inSeq) { + this.inSeq = inSeq; + } } diff --git a/core/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java b/core/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java index 2083876b56..25679ba28c 100644 --- a/core/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java +++ b/core/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java @@ -21,6 +21,11 @@ import com.cloud.agent.api.Command; public final class AttachPrimaryDataStoreCmd extends Command implements StorageSubSystemCommand { + @Override + public void setExecuteInSequence(boolean inSeq) { + + } + private final String dataStore; public AttachPrimaryDataStoreCmd(String uri) { diff --git a/core/src/org/apache/cloudstack/storage/command/CopyCommand.java b/core/src/org/apache/cloudstack/storage/command/CopyCommand.java index 446c61f9a7..96822a4ff2 100644 --- a/core/src/org/apache/cloudstack/storage/command/CopyCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/CopyCommand.java @@ -78,4 +78,8 @@ public Map getOptions() { return options; } + @Override + public void setExecuteInSequence(boolean inSeq) { + this.executeInSequence = inSeq; + } } diff --git a/core/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java b/core/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java index 121a7ee449..8c239b5304 100644 --- a/core/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/CreateObjectCommand.java @@ -42,4 +42,8 @@ public DataTO getData() { return this.data; } + @Override + public void setExecuteInSequence(boolean inSeq) { + + } } diff --git a/core/src/org/apache/cloudstack/storage/command/CreatePrimaryDataStoreCmd.java b/core/src/org/apache/cloudstack/storage/command/CreatePrimaryDataStoreCmd.java index b536028927..21716cf111 100644 --- a/core/src/org/apache/cloudstack/storage/command/CreatePrimaryDataStoreCmd.java +++ b/core/src/org/apache/cloudstack/storage/command/CreatePrimaryDataStoreCmd.java @@ -35,4 +35,8 @@ public boolean executeInSequence() { return false; } + @Override + public void setExecuteInSequence(boolean inSeq) { + + } } diff --git a/core/src/org/apache/cloudstack/storage/command/DeleteCommand.java b/core/src/org/apache/cloudstack/storage/command/DeleteCommand.java index 76696da30a..7445050763 100644 --- a/core/src/org/apache/cloudstack/storage/command/DeleteCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/DeleteCommand.java @@ -42,4 +42,8 @@ public DataTO getData() { return this.data; } + @Override + public void setExecuteInSequence(boolean inSeq) { + + } } diff --git a/core/src/org/apache/cloudstack/storage/command/DettachCommand.java b/core/src/org/apache/cloudstack/storage/command/DettachCommand.java index 61cb88b284..1e501d9600 100644 --- a/core/src/org/apache/cloudstack/storage/command/DettachCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/DettachCommand.java @@ -87,4 +87,9 @@ public void setStoragePort(int storagePort) { public int getStoragePort() { return _storagePort; } + + @Override + public void setExecuteInSequence(boolean inSeq) { + + } } diff --git a/core/src/org/apache/cloudstack/storage/command/ForgetObjectCmd.java b/core/src/org/apache/cloudstack/storage/command/ForgetObjectCmd.java index ffee0ab921..981a098102 100644 --- a/core/src/org/apache/cloudstack/storage/command/ForgetObjectCmd.java +++ b/core/src/org/apache/cloudstack/storage/command/ForgetObjectCmd.java @@ -36,4 +36,9 @@ public DataTO getDataTO() { public boolean executeInSequence() { return false; } + + @Override + public void setExecuteInSequence(boolean inSeq) { + + } } diff --git a/core/src/org/apache/cloudstack/storage/command/IntroduceObjectCmd.java b/core/src/org/apache/cloudstack/storage/command/IntroduceObjectCmd.java index c6c6d23726..b463b2c5f0 100644 --- a/core/src/org/apache/cloudstack/storage/command/IntroduceObjectCmd.java +++ b/core/src/org/apache/cloudstack/storage/command/IntroduceObjectCmd.java @@ -36,4 +36,9 @@ public DataTO getDataTO() { public boolean executeInSequence() { return false; } + + @Override + public void setExecuteInSequence(boolean inSeq) { + + } } diff --git a/core/src/org/apache/cloudstack/storage/command/StorageSubSystemCommand.java b/core/src/org/apache/cloudstack/storage/command/StorageSubSystemCommand.java index d14161ae4c..fb7b373684 100644 --- a/core/src/org/apache/cloudstack/storage/command/StorageSubSystemCommand.java +++ b/core/src/org/apache/cloudstack/storage/command/StorageSubSystemCommand.java @@ -19,5 +19,5 @@ package org.apache.cloudstack.storage.command; public interface StorageSubSystemCommand { - + void setExecuteInSequence(boolean inSeq); } diff --git a/core/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java b/core/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java index 6a5d679331..29e53b0d95 100644 --- a/core/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java +++ b/core/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java @@ -27,6 +27,7 @@ public class PrimaryDataStoreTO implements DataStoreTO { public static final String MANAGED = PrimaryDataStore.MANAGED; public static final String STORAGE_HOST = PrimaryDataStore.STORAGE_HOST; + public static final String STORAGE_PORT = PrimaryDataStore.STORAGE_PORT; public static final String MANAGED_STORE_TARGET = PrimaryDataStore.MANAGED_STORE_TARGET; public static final String MANAGED_STORE_TARGET_ROOT_VOLUME = PrimaryDataStore.MANAGED_STORE_TARGET_ROOT_VOLUME; public static final String CHAP_INITIATOR_USERNAME = PrimaryDataStore.CHAP_INITIATOR_USERNAME; diff --git a/core/test/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResourceTest.java b/core/test/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResourceTest.java index 48da1bb58b..531c71854d 100644 --- a/core/test/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResourceTest.java +++ b/core/test/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResourceTest.java @@ -91,6 +91,11 @@ public class VirtualRoutingResourceTest implements VirtualRouterDeployer { @Override public ExecutionResult executeInVR(String routerIp, String script, String args) { + return executeInVR(routerIp, script, args, 60); + } + + @Override + public ExecutionResult executeInVR(String routerIp, String script, String args, int timeout) { assertEquals(routerIp, ROUTERIP); verifyCommand(_currentCmd, script, args); return new ExecutionResult(true, null); diff --git a/core/test/org/apache/cloudstack/api/agent/test/BackupSnapshotCommandTest.java b/core/test/org/apache/cloudstack/api/agent/test/BackupSnapshotCommandTest.java index eaa9b94fee..33361e8726 100644 --- a/core/test/org/apache/cloudstack/api/agent/test/BackupSnapshotCommandTest.java +++ b/core/test/org/apache/cloudstack/api/agent/test/BackupSnapshotCommandTest.java @@ -28,6 +28,7 @@ import com.cloud.agent.api.BackupSnapshotCommand; import com.cloud.agent.api.to.SwiftTO; +import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolStatus; @@ -145,7 +146,14 @@ public String getStorageProviderName() { public boolean isInMaintenance() { // TODO Auto-generated method stub return false; - }; + } + + @Override + public Hypervisor.HypervisorType getHypervisor() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + ; }; BackupSnapshotCommand bsc = new BackupSnapshotCommand("http://secondary.Storage.Url", 101L, 102L, 103L, 104L, 105L, "vPath", pool, diff --git a/core/test/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java b/core/test/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java index b0872bfc52..66feaecb5e 100644 --- a/core/test/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java +++ b/core/test/org/apache/cloudstack/api/agent/test/CheckNetworkAnswerTest.java @@ -32,6 +32,7 @@ import com.cloud.agent.api.CheckNetworkCommand; import com.cloud.agent.api.storage.ResizeVolumeCommand; import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.Storage; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolStatus; @@ -184,7 +185,14 @@ public String getStorageProviderName() { public boolean isInMaintenance() { // TODO Auto-generated method stub return false; - }; + } + + @Override + public Hypervisor.HypervisorType getHypervisor() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + ; }; Long newSize = 4194304L; diff --git a/core/test/org/apache/cloudstack/api/agent/test/SnapshotCommandTest.java b/core/test/org/apache/cloudstack/api/agent/test/SnapshotCommandTest.java index 8339a98b9f..114c8854d1 100644 --- a/core/test/org/apache/cloudstack/api/agent/test/SnapshotCommandTest.java +++ b/core/test/org/apache/cloudstack/api/agent/test/SnapshotCommandTest.java @@ -28,6 +28,7 @@ import org.junit.Test; import com.cloud.agent.api.SnapshotCommand; +import com.cloud.hypervisor.Hypervisor; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StoragePool; import com.cloud.storage.StoragePoolStatus; @@ -146,7 +147,14 @@ public String getStorageProviderName() { public boolean isInMaintenance() { // TODO Auto-generated method stub return false; - }; + } + + @Override + public Hypervisor.HypervisorType getHypervisor() { + return null; //To change body of implemented methods use File | Settings | File Templates. + } + + ; }; SnapshotCommand ssc = new SnapshotCommand(pool, "http://secondary.Storage.Url", "420fa39c-4ef1-a83c-fd93-46dc1ff515ae", "snapshotName", 101L, 102L, 103L); diff --git a/debian/control b/debian/control index ab4644badd..504ef99f31 100644 --- a/debian/control +++ b/debian/control @@ -15,7 +15,7 @@ Description: A common package which contains files which are shared by several C Package: cloudstack-management Architecture: all -Depends: cloudstack-common (= ${source:Version}), tomcat6, sysvinit-utils, sudo, jsvc, python-mysqldb, python-paramiko, augeas-tools +Depends: cloudstack-common (= ${source:Version}), tomcat6, sysvinit-utils, sudo, jsvc, python-mysqldb, libmysql-java, python-paramiko, augeas-tools Conflicts: cloud-server, cloud-client, cloud-client-ui Description: CloudStack server library The CloudStack management server diff --git a/debian/rules b/debian/rules index 4edf893060..197e243bcf 100755 --- a/debian/rules +++ b/debian/rules @@ -35,7 +35,7 @@ build: build-indep build-indep: build-indep-stamp build-indep-stamp: configure - mvn clean package -Pawsapi -DskipTests -Dsystemvm \ + mvn -T C1.5 clean package -Pawsapi -DskipTests -Dsystemvm \ -Dcs.replace.properties=replace.properties.tmp \ ${ACS_BUILD_OPTS} touch $@ diff --git a/engine/api/src/com/cloud/vm/VirtualMachineManager.java b/engine/api/src/com/cloud/vm/VirtualMachineManager.java index 99f5595579..f070210b75 100644 --- a/engine/api/src/com/cloud/vm/VirtualMachineManager.java +++ b/engine/api/src/com/cloud/vm/VirtualMachineManager.java @@ -36,7 +36,6 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.Network; -import com.cloud.offering.DiskOffering; import com.cloud.offering.DiskOfferingInfo; import com.cloud.offering.ServiceOffering; import com.cloud.storage.StoragePool; @@ -77,7 +76,7 @@ public interface Topics { * @throws InsufficientCapacityException If there are insufficient capacity to deploy this vm. */ void allocate(String vmInstanceName, VirtualMachineTemplate template, ServiceOffering serviceOffering, DiskOfferingInfo rootDiskOfferingInfo, - LinkedHashMap dataDiskOfferings, LinkedHashMap> auxiliaryNetworks, DeploymentPlan plan, + List dataDiskOfferings, LinkedHashMap> auxiliaryNetworks, DeploymentPlan plan, HypervisorType hyperType) throws InsufficientCapacityException; void allocate(String vmInstanceName, VirtualMachineTemplate template, ServiceOffering serviceOffering, diff --git a/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java b/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java index 2531074029..3b555e55be 100644 --- a/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java +++ b/engine/api/src/org/apache/cloudstack/engine/orchestration/service/VolumeOrchestrationService.java @@ -21,6 +21,7 @@ import java.util.Map; import java.util.Set; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import com.cloud.agent.api.to.VirtualMachineTO; @@ -86,7 +87,7 @@ VolumeInfo moveVolume(VolumeInfo volume, long destPoolDcId, Long destPoolPodId, void destroyVolume(Volume volume); - DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, VirtualMachine vm, VirtualMachineTemplate template, Account owner); + DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template, Account owner); VolumeInfo createVolumeOnPrimaryStorage(VirtualMachine vm, Volume rootVolumeOfVm, VolumeInfo volume, HypervisorType rootDiskHyperType) throws NoTransitionException; @@ -94,6 +95,8 @@ VolumeInfo moveVolume(VolumeInfo volume, long destPoolDcId, Long destPoolPodId, void cleanupVolumes(long vmId) throws ConcurrentOperationException; + void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore); + void disconnectVolumesFromHost(long vmId, long hostId); void migrateVolumes(VirtualMachine vm, VirtualMachineTO vmTo, Host srcHost, Host destHost, Map volumeToPool); @@ -118,4 +121,5 @@ DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering offerin StoragePool findStoragePool(DiskProfile dskCh, DataCenter dc, Pod pod, Long clusterId, Long hostId, VirtualMachine vm, Set avoid); void updateVolumeDiskChain(long volumeId, String path, String chainInfo); + } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java index bb9f2dad1f..f08d9a4550 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/PrimaryDataStoreInfo.java @@ -29,6 +29,7 @@ public interface PrimaryDataStoreInfo extends StoragePool { static final String MANAGED = "managed"; static final String STORAGE_HOST= "storageHost"; + static final String STORAGE_PORT = "storagePort"; static final String MANAGED_STORE_TARGET = "managedStoreTarget"; static final String MANAGED_STORE_TARGET_ROOT_VOLUME = "managedStoreTargetRootVolume"; static final String CHAP_INITIATOR_USERNAME = "chapInitiatorUsername"; diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java index 801c4427f5..fd22da12e4 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateDataFactory.java @@ -25,6 +25,8 @@ public interface TemplateDataFactory { TemplateInfo getTemplate(long templateId, DataStore store); + TemplateInfo getReadyTemplateOnImageStore(long templateId, Long zoneId); + TemplateInfo getTemplate(DataObject obj, DataStore store); TemplateInfo getTemplate(long templateId, DataStoreRole storeRole); diff --git a/engine/components-api/src/com/cloud/event/UsageEventUtils.java b/engine/components-api/src/com/cloud/event/UsageEventUtils.java index 4f32cb3263..f1707bd45d 100644 --- a/engine/components-api/src/com/cloud/event/UsageEventUtils.java +++ b/engine/components-api/src/com/cloud/event/UsageEventUtils.java @@ -70,6 +70,15 @@ public static void publishUsageEvent(String usageType, long accountId, long zone publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID); } + public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId, + Long size, String entityType, String entityUUID, boolean displayResource) { + if(displayResource){ + saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, size); + } + publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID); + + } + public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId, Long size, Long virtualSize, String entityType, String entityUUID) { saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, size, virtualSize); @@ -81,6 +90,13 @@ public static void publishUsageEvent(String usageType, long accountId, long zone publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID); } + public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, String entityType, String entityUUID, boolean diplayResource) { + if (diplayResource){ + saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName); + publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID); + } + } + public static void publishUsageEvent(String usageType, long accountId, long zoneId, long ipAddressId, String ipAddress, boolean isSourceNat, String guestType, boolean isSystem, String entityType, String entityUUID) { saveUsageEvent(usageType, accountId, zoneId, ipAddressId, ipAddress, isSourceNat, guestType, isSystem); @@ -88,9 +104,12 @@ public static void publishUsageEvent(String usageType, long accountId, long zone } public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId, - String resourceType, String entityType, String entityUUID) { - saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, resourceType); + String resourceType, String entityType, String entityUUID, boolean displayResource) { + if(displayResource){ + saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, resourceType); + } publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID); + } public static void publishUsageEvent(String usageType, long accountId, long zoneId, long vmId, long securityGroupId, String entityType, String entityUUID) { @@ -99,9 +118,12 @@ public static void publishUsageEvent(String usageType, long accountId, long zone } public static void publishUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId, - String resourceType, String entityType, String entityUUID, Map details) { - saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, resourceType, details); + String resourceType, String entityType, String entityUUID, Map details, boolean displayResource) { + if(displayResource){ + saveUsageEvent(usageType, accountId, zoneId, resourceId, resourceName, offeringId, templateId, resourceType, details); + } publishUsageEvent(usageType, accountId, zoneId, entityType, entityUUID); + } private static void saveUsageEvent(String usageType, long accountId, long zoneId, long resourceId, String resourceName, Long offeringId, Long templateId, diff --git a/engine/components-api/src/com/cloud/network/addr/PublicIp.java b/engine/components-api/src/com/cloud/network/addr/PublicIp.java index ff11b3349a..a20e3459e7 100644 --- a/engine/components-api/src/com/cloud/network/addr/PublicIp.java +++ b/engine/components-api/src/com/cloud/network/addr/PublicIp.java @@ -18,9 +18,8 @@ import java.util.Date; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.dc.VlanVO; +import com.cloud.network.IpAddress; import com.cloud.network.PublicIpAddress; import com.cloud.network.dao.IPAddressVO; import com.cloud.utils.net.Ip; @@ -240,7 +239,7 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.PublicIpAddress; + public Class getEntityType() { + return IpAddress.class; } } diff --git a/engine/components-api/src/com/cloud/network/rules/StaticNatRuleImpl.java b/engine/components-api/src/com/cloud/network/rules/StaticNatRuleImpl.java index bdaf2bc1b2..9a49db0ca1 100644 --- a/engine/components-api/src/com/cloud/network/rules/StaticNatRuleImpl.java +++ b/engine/components-api/src/com/cloud/network/rules/StaticNatRuleImpl.java @@ -18,8 +18,6 @@ import java.util.List; -import org.apache.cloudstack.acl.IAMEntityType; - public class StaticNatRuleImpl implements StaticNatRule { long id; String xid; @@ -152,7 +150,7 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.FirewallRule; + public Class getEntityType() { + return FirewallRule.class; } } diff --git a/engine/components-api/src/com/cloud/resource/ResourceManager.java b/engine/components-api/src/com/cloud/resource/ResourceManager.java index 5a9bddb186..4f43adb3f5 100755 --- a/engine/components-api/src/com/cloud/resource/ResourceManager.java +++ b/engine/components-api/src/com/cloud/resource/ResourceManager.java @@ -23,6 +23,7 @@ import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.agent.api.to.GPUDeviceTO; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; @@ -141,41 +142,51 @@ public interface ResourceManager extends ResourceService { */ List listAllUpAndEnabledNonHAHosts(Type type, Long clusterId, Long podId, long dcId); + /** + * Check if host is GPU enabled + * @param hostId the host to be checked + * @return true if host contains GPU card else false + */ + boolean isHostGpuEnabled(long hostId); + /** * Check if host has GPU devices available * @param hostId the host to be checked + * @param groupName: gpuCard name * @param vgpuType the VGPU type * @return true when the host has the capacity with given VGPU type */ - boolean isGPUDeviceAvailable(long hostId, String vgpuType); + boolean isGPUDeviceAvailable(long hostId, String groupName, String vgpuType); /** * Get available GPU device * @param hostId the host to be checked + * @param groupName: gpuCard name * @param vgpuType the VGPU type * @return GPUDeviceTO[] */ - GPUDeviceTO getGPUDevice(long hostId, String vgpuType); + GPUDeviceTO getGPUDevice(long hostId, String groupName, String vgpuType); /** * Return listof available GPU devices * @param hostId, the host to be checked + * @param groupName: gpuCard name * @param vgpuType the VGPU type * @return List of HostGpuGroupsVO. */ - List listAvailableGPUDevice(long hostId, String vgpuType); + List listAvailableGPUDevice(long hostId, String groupName, String vgpuType); /** * Update GPU device details (post VM deployment) * @param hostId, the dest host Id * @param groupDetails, capacity of GPU group. */ - void updateGPUDetails(long hostId, HashMap> groupDetails); + void updateGPUDetails(long hostId, HashMap> groupDetails); /** * Get GPU details for a host * @param host, the Host object * @return Details of groupNames and enabled VGPU type with remaining capacity. */ - HashMap> getGPUStatistics(HostVO host); + HashMap> getGPUStatistics(HostVO host); } diff --git a/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java b/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java index 0d41bc1b3b..f43086fab9 100755 --- a/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java +++ b/engine/orchestration/src/com/cloud/agent/manager/AgentManagerImpl.java @@ -185,8 +185,15 @@ public class AgentManagerImpl extends ManagerBase implements AgentManager, Handl "The number of direct agents to load each time", false); protected final ConfigKey DirectAgentPoolSize = new ConfigKey(Integer.class, "direct.agent.pool.size", "Advanced", "500", "Default size for DirectAgentPool", false); - protected final ConfigKey DirectAgentThreadCap = new ConfigKey(Float.class, "direct.agent.thread.cap", "Advanced", "0.1", + protected final ConfigKey DirectAgentThreadCap = new ConfigKey(Float.class, "direct.agent.thread.cap", "Advanced", "1", "Percentage (as a value between 0 and 1) of direct.agent.pool.size to be used as upper thread cap for a single direct agent to process requests", false); + protected final ConfigKey CheckTxnBeforeSending = new ConfigKey( + "Developer", + Boolean.class, + "check.txn.before.sending.agent.commands", + "false", + "This parameter allows developers to enable a check to see if a transaction wraps commands that are sent to the resource. This is not to be enabled on production systems.", + true); @Override public boolean configure(final String name, final Map params) throws ConfigurationException { @@ -378,7 +385,16 @@ public Answer[] send(Long hostId, Commands commands, int timeout) throws AgentUn if (timeout <= 0) { timeout = Wait.value(); } - assert noDbTxn() : "I know, I know. Why are we so strict as to not allow txn across an agent call? ... Why are we so cruel ... Why are we such a dictator .... Too bad... Sorry...but NO AGENT COMMANDS WRAPPED WITHIN DB TRANSACTIONS!"; + + if (CheckTxnBeforeSending.value()) { + if (!noDbTxn()) { + throw new CloudRuntimeException("We do not allow transactions to be wrapped around commands sent to be executed on remote agents. " + + "We cannot predict how long it takes a command to complete. " + + "The transaction may be rolled back because the connection took too long."); + } + } else { + assert noDbTxn() : "I know, I know. Why are we so strict as to not allow txn across an agent call? ... Why are we so cruel ... Why are we such a dictator .... Too bad... Sorry...but NO AGENT COMMANDS WRAPPED WITHIN DB TRANSACTIONS!"; + } Command[] cmds = commands.toCommands(); @@ -1582,7 +1598,7 @@ public String getConfigComponentName() { @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[] {Workers, Port, PingInterval, PingTimeout, Wait, AlertWait, DirectAgentLoadSize, DirectAgentPoolSize, DirectAgentThreadCap}; + return new ConfigKey[] {CheckTxnBeforeSending, Workers, Port, PingInterval, PingTimeout, Wait, AlertWait, DirectAgentLoadSize, DirectAgentPoolSize, DirectAgentThreadCap}; } } diff --git a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java index e9d2fd2073..07c4558667 100755 --- a/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/engine/orchestration/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation (ASF) under one +// Licensed to the Apacohe 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 @@ -154,7 +154,6 @@ import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.rules.RulesManager; -import com.cloud.offering.DiskOffering; import com.cloud.offering.DiskOfferingInfo; import com.cloud.offering.ServiceOffering; import com.cloud.org.Cluster; @@ -376,7 +375,7 @@ public void registerGuru(VirtualMachine.Type type, VirtualMachineGuru guru) { @Override @DB public void allocate(String vmInstanceName, final VirtualMachineTemplate template, ServiceOffering serviceOffering, - final DiskOfferingInfo rootDiskOfferingInfo, LinkedHashMap dataDiskOfferings, + final DiskOfferingInfo rootDiskOfferingInfo, final List dataDiskOfferings, final LinkedHashMap> auxiliaryNetworks, DeploymentPlan plan, HypervisorType hyperType) throws InsufficientCapacityException { @@ -393,8 +392,6 @@ public void allocate(String vmInstanceName, final VirtualMachineTemplate templat } assert (plan.getClusterId() == null && plan.getPoolId() == null) : "We currently don't support cluster and pool preset yet"; final VMInstanceVO vmFinal = _vmDao.persist(vm); - final LinkedHashMap dataDiskOfferingsFinal = - dataDiskOfferings == null ? new LinkedHashMap() : dataDiskOfferings; final VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmFinal, template, serviceOffering, null, null); @@ -416,8 +413,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Insuff } if (template.getFormat() == ImageFormat.ISO) { - volumeMgr.allocateRawVolume(Type.ROOT, "ROOT-" + vmFinal.getId(), rootDiskOfferingInfo.getDiskOffering(), rootDiskOfferingInfo.getSize(), vmFinal, - template, owner); + volumeMgr.allocateRawVolume(Type.ROOT, "ROOT-" + vmFinal.getId(), rootDiskOfferingInfo.getDiskOffering(), rootDiskOfferingInfo.getSize(), + rootDiskOfferingInfo.getMinIops(), rootDiskOfferingInfo.getMaxIops(), vmFinal, template, owner); } else if (template.getFormat() == ImageFormat.BAREMETAL) { // Do nothing } else { @@ -425,8 +422,11 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Insuff rootDiskOfferingInfo.getMinIops(), rootDiskOfferingInfo.getMaxIops(), template, vmFinal, owner); } - for (Map.Entry offering : dataDiskOfferingsFinal.entrySet()) { - volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vmFinal.getId(), offering.getKey(), offering.getValue(), vmFinal, template, owner); + if (dataDiskOfferings != null) { + for (DiskOfferingInfo dataDiskOfferingInfo : dataDiskOfferings) { + volumeMgr.allocateRawVolume(Type.DATADISK, "DATA-" + vmFinal.getId(), dataDiskOfferingInfo.getDiskOffering(), dataDiskOfferingInfo.getSize(), + dataDiskOfferingInfo.getMinIops(), dataDiskOfferingInfo.getMaxIops(), vmFinal, template, owner); + } } } }); @@ -439,7 +439,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Insuff @Override public void allocate(String vmInstanceName, VirtualMachineTemplate template, ServiceOffering serviceOffering, LinkedHashMap> networks, DeploymentPlan plan, HypervisorType hyperType) throws InsufficientCapacityException { - allocate(vmInstanceName, template, serviceOffering, new DiskOfferingInfo(serviceOffering), null, networks, plan, hyperType); + allocate(vmInstanceName, template, serviceOffering, new DiskOfferingInfo(serviceOffering), new ArrayList(), networks, plan, hyperType); } private VirtualMachineGuru getVmGuru(VirtualMachine vm) { @@ -569,8 +569,8 @@ protected void advanceExpunge(VMInstanceVO vm) throws ResourceUnavailableExcepti @Override public boolean start() { // TODO, initial delay is hardcoded - _executor.scheduleAtFixedRate(new TransitionTask(), 5000, VmJobStateReportInterval.value(), TimeUnit.SECONDS); - _executor.scheduleAtFixedRate(new CleanupTask(), VmOpCleanupInterval.value(), VmOpCleanupInterval.value(), TimeUnit.SECONDS); + _executor.scheduleAtFixedRate(new CleanupTask(), 5, VmJobStateReportInterval.value(), TimeUnit.SECONDS); + _executor.scheduleAtFixedRate(new TransitionTask(), VmOpCleanupInterval.value(), VmOpCleanupInterval.value(), TimeUnit.SECONDS); cancelWorkItems(_nodeId); // cleanup left over place holder works @@ -996,7 +996,9 @@ public void orchestrateStart(String vmUuid, Map vmmetadata = new HashMap(); + vmmetadata.put(vm.getInstanceName(), platform); + syncVMMetaData(vmmetadata); } } } @@ -1214,9 +1216,18 @@ public void stop(String vmUuid) throws ResourceUnavailableException { } } - protected boolean sendStop(VirtualMachineGuru guru, VirtualMachineProfile profile, boolean force) { + + protected boolean getExecuteInSequence(HypervisorType hypervisorType) { + if (HypervisorType.KVM == hypervisorType) { + return false; + } else { + return ExecuteInSequence.value(); + } + } + + protected boolean sendStop(VirtualMachineGuru guru, VirtualMachineProfile profile, boolean force, boolean checkBeforeCleanup) { VirtualMachine vm = profile.getVirtualMachine(); - StopCommand stop = new StopCommand(vm, ExecuteInSequence.value()); + StopCommand stop = new StopCommand(vm, getExecuteInSequence(vm.getHypervisorType()), checkBeforeCleanup); try { StopAnswer answer = (StopAnswer)_agentMgr.send(vm.getHostId(), stop); if (answer != null) { @@ -1271,7 +1282,7 @@ protected boolean cleanup(VirtualMachineGuru guru, VirtualMachineProfile profile if (step == Step.Started || step == Step.Starting || step == Step.Release) { if (vm.getHostId() != null) { - if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop)) { + if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop, false)) { s_logger.warn("Failed to stop vm " + vm + " in " + State.Starting + " state as a part of cleanup process"); return false; } @@ -1284,26 +1295,26 @@ protected boolean cleanup(VirtualMachineGuru guru, VirtualMachineProfile profile } } else if (state == State.Stopping) { if (vm.getHostId() != null) { - if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop)) { + if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop, false)) { s_logger.warn("Failed to stop vm " + vm + " in " + State.Stopping + " state as a part of cleanup process"); return false; } } } else if (state == State.Migrating) { if (vm.getHostId() != null) { - if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop)) { + if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop, false)) { s_logger.warn("Failed to stop vm " + vm + " in " + State.Migrating + " state as a part of cleanup process"); return false; } } if (vm.getLastHostId() != null) { - if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop)) { + if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop, false)) { s_logger.warn("Failed to stop vm " + vm + " in " + State.Migrating + " state as a part of cleanup process"); return false; } } } else if (state == State.Running) { - if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop)) { + if (!sendStop(guru, profile, cleanUpEvenIfUnableToStop, false)) { s_logger.warn("Failed to stop vm " + vm + " in " + State.Running + " state as a part of cleanup process"); return false; } @@ -1476,7 +1487,9 @@ private void advanceStop(VMInstanceVO vm, boolean cleanUpEvenIfUnableToStop) thr } vmGuru.prepareStop(profile); - StopCommand stop = new StopCommand(vm, ExecuteInSequence.value()); + + StopCommand stop = new StopCommand(vm, getExecuteInSequence(vm.getHypervisorType()), false); + boolean stopped = false; StopAnswer answer = null; try { @@ -2451,11 +2464,12 @@ private void orchestrateReboot(String vmUuid, Map vmMetadatum) { } VMInstanceVO vm = _vmDao.findVMByInstanceName(name); if (vm != null && vm.getType() == VirtualMachine.Type.User) { - // track platform info + boolean changed = false; UserVmVO userVm = _userVmDao.findById(vm.getId()); _userVmDao.loadDetails(userVm); - userVm.setDetail("platform", platform); + if ( userVm.details.containsKey("timeoffset")) { + userVm.details.remove("timeoffset"); + changed = true; + } + if (!userVm.details.containsKey("platform") || !userVm.details.get("platform").equals(platform)) { + userVm.setDetail("platform", platform); + changed = true; + } String pvdriver = "xenserver56"; if ( platform.contains("device_id")) { pvdriver = "xenserver61"; } - userVm.setDetail("hypervisortoolsversion", pvdriver); - _userVmDao.saveDetails(userVm); + if (!userVm.details.containsKey("hypervisortoolsversion") || !userVm.details.get("hypervisortoolsversion").equals(pvdriver)) { + userVm.setDetail("hypervisortoolsversion", pvdriver); + changed = true; + } + if ( changed ) { + _userVmDao.saveDetails(userVm); + } } } } - public void deltaSync(Map> newStates) { Map states = convertToInfos(newStates); @@ -3243,9 +3268,9 @@ protected class AgentVmInfo { @SuppressWarnings("unchecked") public AgentVmInfo(String name, VMInstanceVO vm, State state, String host) { - this.name = name; - this.state = state; - this.vm = vm; + name = name; + state = state; + vm = vm; hostUuid = host; } @@ -3422,7 +3447,7 @@ private NicProfile orchestrateAddVmToNetwork(VirtualMachine vm, Network network, 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()), network.getNetworkOfferingId(), null, isDefault, VirtualMachine.class.getName(), vmVO.getUuid()); + Long.toString(nic.getId()), network.getNetworkOfferingId(), null, isDefault, VirtualMachine.class.getName(), vmVO.getUuid(), vm.isDisplay()); return nic; } else { s_logger.warn("Failed to plug nic to the vm " + vm + " in network " + network); @@ -3537,7 +3562,7 @@ private boolean orchestrateRemoveNicFromVm(VirtualMachine vm, Nic nic) throws Co s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network); long isDefault = (nic.isDefaultNic()) ? 1 : 0; UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), - Long.toString(nic.getId()), network.getNetworkOfferingId(), null, isDefault, VirtualMachine.class.getName(), vm.getUuid()); + Long.toString(nic.getId()), network.getNetworkOfferingId(), null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay()); } else { s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network); return false; @@ -4100,7 +4125,7 @@ private void HandlePowerStateReport(String subject, String senderAddress, Object List pendingWorkJobs = _workJobDao.listPendingWorkJobs( VirtualMachine.Type.Instance, vmId); - if (pendingWorkJobs.size() == 0 || !_haMgr.hasPendingHaWork(vmId)) { + if (pendingWorkJobs.size() == 0 && !_haMgr.hasPendingHaWork(vmId)) { // there is no pending operation job VMInstanceVO vm = _vmDao.findById(vmId); if (vm != null) { @@ -4221,9 +4246,18 @@ private void handlePowerOffReportWithNoPendingJobsOnVM(VMInstanceVO vm) { case Stopped: case Migrating: s_logger.info("VM " + vm.getInstanceName() + " is at " + vm.getState() + " and we received a power-off report while there is no pending jobs on it"); + if(vm.isHaEnabled() && vm.getState() == State.Running && vm.getHypervisorType() != HypervisorType.VMware && vm.getHypervisorType() != HypervisorType.Hyperv) { + s_logger.info("Detected out-of-band stop of a HA enabled VM " + vm.getInstanceName() + ", will schedule restart"); + if(!_haMgr.hasPendingHaWork(vm.getId())) + _haMgr.scheduleRestart(vm, true); + else + s_logger.info("VM " + vm.getInstanceName() + " already has an pending HA task working on it"); + return; + } + VirtualMachineGuru vmGuru = getVmGuru(vm); VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); - sendStop(vmGuru, profile, true); + sendStop(vmGuru, profile, true, true); try { stateTransitTo(vm, VirtualMachine.Event.FollowAgentPowerOffReport, null); @@ -4406,8 +4440,9 @@ public VmStateSyncOutcome(final AsyncJob job, final PowerState desiredPowerState super(VirtualMachine.class, job, VmJobCheckInterval.value(), new Predicate() { @Override public boolean checkCondition() { - VMInstanceVO instance = _vmDao.findById(vmId); - if (instance.getPowerState() == desiredPowerState && (srcHostIdForMigration != null && srcHostIdForMigration.equals(instance.getPowerHostId()))) + AsyncJobVO jobVo = _entityMgr.findById(AsyncJobVO.class, job.getId()); + assert (jobVo != null); + if (jobVo == null || jobVo.getStatus() != JobInfo.Status.IN_PROGRESS) return true; return false; } diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/CloudOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/CloudOrchestrator.java index fc1b85c080..2b4995466b 100755 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/CloudOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/CloudOrchestrator.java @@ -45,7 +45,6 @@ import com.cloud.network.Network; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; -import com.cloud.offering.DiskOffering; import com.cloud.offering.DiskOfferingInfo; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; @@ -181,14 +180,14 @@ public VirtualMachineEntity createVirtualMachine(String id, String owner, String // Else, a disk offering is optional, and if present will be used to create the data disk DiskOfferingInfo rootDiskOfferingInfo = new DiskOfferingInfo(); - LinkedHashMap dataDiskOfferings = new LinkedHashMap(); + List dataDiskOfferings = new ArrayList(); - ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); + ServiceOfferingVO computeOffering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); - rootDiskOfferingInfo.setDiskOffering(offering); + rootDiskOfferingInfo.setDiskOffering(computeOffering); rootDiskOfferingInfo.setSize(rootDiskSize); - if (offering.isCustomizedIops() != null && offering.isCustomizedIops()) { + if (computeOffering.isCustomizedIops() != null && computeOffering.isCustomizedIops()) { Map userVmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId()); if (userVmDetails != null) { @@ -213,10 +212,28 @@ public VirtualMachineEntity createVirtualMachine(String id, String owner, String } _volumeMgr.validateVolumeSizeRange(size * 1024 * 1024 * 1024); } - dataDiskOfferings.put(diskOffering, size); + + DiskOfferingInfo dataDiskOfferingInfo = new DiskOfferingInfo(); + + dataDiskOfferingInfo.setDiskOffering(diskOffering); + dataDiskOfferingInfo.setSize(size); + + if (diskOffering.isCustomizedIops() != null && diskOffering.isCustomizedIops()) { + Map userVmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId()); + + if (userVmDetails != null) { + String minIops = userVmDetails.get("minIopsDo"); + String maxIops = userVmDetails.get("maxIopsDo"); + + dataDiskOfferingInfo.setMinIops(minIops != null && minIops.trim().length() > 0 ? Long.parseLong(minIops) : null); + dataDiskOfferingInfo.setMaxIops(maxIops != null && maxIops.trim().length() > 0 ? Long.parseLong(maxIops) : null); + } + } + + dataDiskOfferings.add(dataDiskOfferingInfo); } - _itMgr.allocate(vm.getInstanceName(), _templateDao.findById(new Long(templateId)), offering, rootDiskOfferingInfo, dataDiskOfferings, networkIpMap, plan, + _itMgr.allocate(vm.getInstanceName(), _templateDao.findById(new Long(templateId)), computeOffering, rootDiskOfferingInfo, dataDiskOfferings, networkIpMap, plan, hypervisorType); return vmEntity; @@ -234,13 +251,12 @@ public VirtualMachineEntity createVirtualMachineFromScratch(String id, String ow //load vm instance and offerings and call virtualMachineManagerImpl VMInstanceVO vm = _vmDao.findByUuid(id); - ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); + ServiceOfferingVO computeOffering = _serviceOfferingDao.findById(vm.getId(), vm.getServiceOfferingId()); DiskOfferingInfo rootDiskOfferingInfo = new DiskOfferingInfo(); - rootDiskOfferingInfo.setDiskOffering(offering); + rootDiskOfferingInfo.setDiskOffering(computeOffering); - LinkedHashMap dataDiskOfferings = new LinkedHashMap(); Long diskOfferingId = vm.getDiskOfferingId(); if (diskOfferingId == null) { throw new InvalidParameterValueException("Installing from ISO requires a disk offering to be specified for the root disk."); @@ -261,6 +277,18 @@ public VirtualMachineEntity createVirtualMachineFromScratch(String id, String ow rootDiskOfferingInfo.setDiskOffering(diskOffering); rootDiskOfferingInfo.setSize(size); + if (diskOffering.isCustomizedIops() != null && diskOffering.isCustomizedIops()) { + Map userVmDetails = _userVmDetailsDao.listDetailsKeyPairs(vm.getId()); + + if (userVmDetails != null) { + String minIops = userVmDetails.get("minIopsDo"); + String maxIops = userVmDetails.get("maxIopsDo"); + + rootDiskOfferingInfo.setMinIops(minIops != null && minIops.trim().length() > 0 ? Long.parseLong(minIops) : null); + rootDiskOfferingInfo.setMaxIops(maxIops != null && maxIops.trim().length() > 0 ? Long.parseLong(maxIops) : null); + } + } + LinkedHashMap> networkIpMap = new LinkedHashMap>(); for (String uuid : networkNicMap.keySet()) { NetworkVO network = _networkDao.findByUuid(uuid); @@ -271,7 +299,7 @@ public VirtualMachineEntity createVirtualMachineFromScratch(String id, String ow HypervisorType hypervisorType = HypervisorType.valueOf(hypervisor); - _itMgr.allocate(vm.getInstanceName(), _templateDao.findById(new Long(isoId)), offering, rootDiskOfferingInfo, dataDiskOfferings, networkIpMap, plan, hypervisorType); + _itMgr.allocate(vm.getInstanceName(), _templateDao.findById(new Long(isoId)), computeOffering, rootDiskOfferingInfo, new ArrayList(), networkIpMap, plan, hypervisorType); return vmEntity; } diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index 6aa1e36ccd..96dafe947d 100755 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -40,7 +40,6 @@ import org.apache.log4j.Logger; import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; @@ -668,6 +667,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { NetworkVO vo = new NetworkVO(id, network, offering.getId(), guru.getName(), owner.getDomainId(), owner.getId(), relatedFile, name, displayText, predefined .getNetworkDomain(), offering.getGuestType(), plan.getDataCenterId(), plan.getPhysicalNetworkId(), aclType, offering.getSpecifyIpRanges(), vpcId); vo.setDisplayNetwork(isDisplayNetworkEnabled == null ? true : isDisplayNetworkEnabled); + vo.setStrechedL2Network(offering.getSupportsStrechedL2()); networks.add(_networksDao.persist(vo, vo.getGuestType() == Network.GuestType.Isolated, finalizeServicesAndProvidersForNetwork(offering, plan.getPhysicalNetworkId()))); @@ -675,7 +675,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { _networksDao.addDomainToNetwork(id, domainId, subdomainAccess == null ? true : subdomainAccess); //send event for storing the domain wide resource access Map params = new HashMap(); - params.put(ApiConstants.ENTITY_TYPE, IAMEntityType.Network); + params.put(ApiConstants.ENTITY_TYPE, Network.class); params.put(ApiConstants.ENTITY_ID, id); params.put(ApiConstants.DOMAIN_ID, domainId); params.put(ApiConstants.SUBDOMAIN_ACCESS, subdomainAccess == null ? true : subdomainAccess); @@ -2245,7 +2245,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { _networkAccountDao.remove(networkAccount.getId()); // remove its related ACL permission - Pair networkMsg = new Pair(IAMEntityType.Network, networkFinal.getId()); + Pair, Long> networkMsg = new Pair, Long>(Network.class, networkFinal.getId()); _messageBus.publish(_name, EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, PublishScope.LOCAL, networkMsg); } diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java index f3753a7417..064ffca6db 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/VolumeOrchestrator.java @@ -35,8 +35,10 @@ import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotService; @@ -109,10 +111,12 @@ import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.StateMachine2; import com.cloud.vm.DiskProfile; +import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.VirtualMachineProfileImpl; +import com.cloud.vm.dao.UserVmDao; public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrationService, Configurable { private static final Logger s_logger = Logger.getLogger(VolumeOrchestrator.class); @@ -149,6 +153,8 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati HostDao _hostDao; @Inject SnapshotService _snapshotSrv; + @Inject + protected UserVmDao _userVmDao; private final StateMachine2 _volStateMachine; protected List _storagePoolAllocators; @@ -569,14 +575,17 @@ protected DiskProfile toDiskProfile(Volume vol, DiskOffering offering) { } @Override - public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, VirtualMachine vm, VirtualMachineTemplate template, Account owner) { + public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offering, Long size, Long minIops, Long maxIops, VirtualMachine vm, VirtualMachineTemplate template, Account owner) { if (size == null) { size = offering.getDiskSize(); } else { size = (size * 1024 * 1024 * 1024); } - VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), size, offering.getMinIops(), offering.getMaxIops(), - null); + + minIops = minIops != null ? minIops : offering.getMinIops(); + maxIops = maxIops != null ? maxIops : offering.getMaxIops(); + + VolumeVO vol = new VolumeVO(type, name, vm.getDataCenterId(), owner.getDomainId(), owner.getId(), offering.getId(), size, minIops, maxIops, null); if (vm != null) { vol.setInstanceId(vm.getId()); } @@ -589,6 +598,11 @@ public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offeri if (template.getFormat() == ImageFormat.ISO) { vol.setIsoId(template.getId()); } + // display flag matters only for the User vms + if (vm.getType() == VirtualMachine.Type.User) { + UserVmVO userVm = _userVmDao.findById(vm.getId()); + vol.setDisplayVolume(userVm.isDisplayVm()); + } vol.setFormat(getSupportedImageFormatForCluster(vm.getHypervisorType())); vol = _volsDao.persist(vol); @@ -596,10 +610,10 @@ public DiskProfile allocateRawVolume(Type type, String name, DiskOffering offeri // Save usage event and update resource count for user vm volumes if (vm.getType() == VirtualMachine.Type.User) { UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offering.getId(), null, size, - Volume.class.getName(), vol.getUuid()); + Volume.class.getName(), vol.getUuid(), vol.isDisplayVolume()); - _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume); - _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.primary_storage, new Long(vol.getSize())); + _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume, vol.isDisplayVolume()); + _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.primary_storage, vol.isDisplayVolume(), new Long(vol.getSize())); } return toDiskProfile(vol, offering); } @@ -609,8 +623,14 @@ public DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering assert (template.getFormat() != ImageFormat.ISO) : "ISO is not a template really...."; Long size = _tmpltMgr.getTemplateSize(template.getId(), vm.getDataCenterId()); - if (rootDisksize != null) { - size = (rootDisksize * 1024 * 1024 * 1024); + if (rootDisksize != null ) { + rootDisksize = rootDisksize * 1024 * 1024 * 1024; + if (rootDisksize > size) { + s_logger.debug("Using root disk size of " + rootDisksize + " for volume " + name); + size = rootDisksize; + } else { + s_logger.debug("Using root disk size of " + size + " for volume " + name + "since specified root disk size of " + rootDisksize + " is smaller than template"); + } } minIops = minIops != null ? minIops : offering.getMinIops(); @@ -633,6 +653,12 @@ public DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering vol.setDeviceId(1l); } + if (vm.getType() == VirtualMachine.Type.User) { + UserVmVO userVm = _userVmDao.findById(vm.getId()); + vol.setDisplayVolume(userVm.isDisplayVm()); + } + + vol = _volsDao.persist(vol); // Create event and update resource count for volumes if vm is a user vm @@ -643,10 +669,10 @@ public DiskProfile allocateTemplatedVolume(Type type, String name, DiskOffering offeringId = offering.getId(); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, vol.getAccountId(), vol.getDataCenterId(), vol.getId(), vol.getName(), offeringId, null, size, - Volume.class.getName(), vol.getUuid()); + Volume.class.getName(), vol.getUuid(), vol.isDisplayVolume()); - _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume); - _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.primary_storage, new Long(vol.getSize())); + _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.volume, vol.isDisplayVolume()); + _resourceLimitMgr.incrementResourceCount(vm.getAccountId(), ResourceType.primary_storage, vol.isDisplayVolume(), new Long(vol.getSize())); } return toDiskProfile(vol, offering); } @@ -661,16 +687,29 @@ private ImageFormat getSupportedImageFormatForCluster(HypervisorType hyperType) } else if (hyperType == HypervisorType.Ovm) { return ImageFormat.RAW; } else if (hyperType == HypervisorType.Hyperv) { - return ImageFormat.VHD; + return ImageFormat.VHDX; } else { return null; } } + private boolean isSupportedImageFormatForCluster(VolumeInfo volume, HypervisorType rootDiskHyperType) { + ImageFormat volumeFormat = volume.getFormat(); + if (rootDiskHyperType == HypervisorType.Hyperv) { + if (volumeFormat.equals(ImageFormat.VHDX) || volumeFormat.equals(ImageFormat.VHD)) { + return true; + } else { + return false; + } + } else { + return volume.getFormat().equals(getSupportedImageFormatForCluster(rootDiskHyperType)); + } + } + private VolumeInfo copyVolume(StoragePool rootDiskPool, VolumeInfo volume, VirtualMachine vm, VirtualMachineTemplate rootDiskTmplt, DataCenter dcVO, Pod pod, DiskOffering diskVO, ServiceOffering svo, HypervisorType rootDiskHyperType) throws NoTransitionException { - if (!volume.getFormat().equals(getSupportedImageFormatForCluster(rootDiskHyperType))) { + if (!isSupportedImageFormatForCluster(volume, rootDiskHyperType)) { throw new InvalidParameterValueException("Failed to attach volume to VM since volumes format " + volume.getFormat().getFileExtension() + " is not compatible with the vm hypervisor type"); } @@ -807,6 +846,15 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } } + @Override + public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) { + DataStoreDriver dataStoreDriver = dataStore != null ? dataStore.getDriver() : null; + + if (dataStoreDriver instanceof PrimaryDataStoreDriver) { + ((PrimaryDataStoreDriver)dataStoreDriver).disconnectVolumeFromHost(volumeInfo, host, dataStore); + } + } + @Override public void disconnectVolumesFromHost(long vmId, long hostId) { HostVO host = _hostDao.findById(hostId); @@ -1117,7 +1165,12 @@ private Pair recreateVolume(VolumeVO vol, VirtualMachinePro future = volService.createVolumeAsync(volume, destPool); } else { - TemplateInfo templ = tmplFactory.getTemplate(templateId, DataStoreRole.Image); + + TemplateInfo templ = tmplFactory.getReadyTemplateOnImageStore(templateId, dest.getDataCenter().getId()); + if (templ == null) { + s_logger.debug("can't find ready template: " + templateId + " for data center " + dest.getDataCenter().getId()); + throw new CloudRuntimeException("can't find ready template: " + templateId + " for data center " + dest.getDataCenter().getId()); + } PrimaryDataStore primaryDataStore = (PrimaryDataStore)destPool; @@ -1151,7 +1204,7 @@ private Pair recreateVolume(VolumeVO vol, VirtualMachinePro StoragePoolVO storagePool = _storagePoolDao.findById(destPool.getId()); - if (newVol.getVolumeType() == Type.DATADISK && storagePool.isManaged()) { + if (storagePool.isManaged()) { long hostId = vm.getVirtualMachine().getHostId(); Host host = _hostDao.findById(hostId); diff --git a/engine/orchestration/test/com/cloud/vm/VirtualMachineManagerImplTest.java b/engine/orchestration/test/com/cloud/vm/VirtualMachineManagerImplTest.java index 49b2fc5fb1..a8cf6c0150 100644 --- a/engine/orchestration/test/com/cloud/vm/VirtualMachineManagerImplTest.java +++ b/engine/orchestration/test/com/cloud/vm/VirtualMachineManagerImplTest.java @@ -465,12 +465,12 @@ public void testSendStopWithOkAnswer() throws Exception { VirtualMachineGuru guru = mock(VirtualMachineGuru.class); VirtualMachine vm = mock(VirtualMachine.class); VirtualMachineProfile profile = mock(VirtualMachineProfile.class); - StopAnswer answer = new StopAnswer(new StopCommand(vm, false), "ok", true); + StopAnswer answer = new StopAnswer(new StopCommand(vm, false, false), "ok", true); when(profile.getVirtualMachine()).thenReturn(vm); when(vm.getHostId()).thenReturn(1L); when(_agentMgr.send(anyLong(), (Command)any())).thenReturn(answer); - boolean actual = _vmMgr.sendStop(guru, profile, false); + boolean actual = _vmMgr.sendStop(guru, profile, false, false); Assert.assertTrue(actual); } @@ -480,12 +480,12 @@ public void testSendStopWithFailAnswer() throws Exception { VirtualMachineGuru guru = mock(VirtualMachineGuru.class); VirtualMachine vm = mock(VirtualMachine.class); VirtualMachineProfile profile = mock(VirtualMachineProfile.class); - StopAnswer answer = new StopAnswer(new StopCommand(vm, false), "fail", false); + StopAnswer answer = new StopAnswer(new StopCommand(vm, false, false), "fail", false); when(profile.getVirtualMachine()).thenReturn(vm); when(vm.getHostId()).thenReturn(1L); when(_agentMgr.send(anyLong(), (Command)any())).thenReturn(answer); - boolean actual = _vmMgr.sendStop(guru, profile, false); + boolean actual = _vmMgr.sendStop(guru, profile, false, false); Assert.assertFalse(actual); } @@ -499,7 +499,7 @@ public void testSendStopWithNullAnswer() throws Exception { when(vm.getHostId()).thenReturn(1L); when(_agentMgr.send(anyLong(), (Command)any())).thenReturn(null); - boolean actual = _vmMgr.sendStop(guru, profile, false); + boolean actual = _vmMgr.sendStop(guru, profile, false, false); Assert.assertFalse(actual); } diff --git a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml index 489b37d04b..bd9226ee53 100644 --- a/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml +++ b/engine/schema/resources/META-INF/cloudstack/core/spring-engine-schema-core-daos-context.xml @@ -221,6 +221,7 @@ + @@ -258,7 +259,6 @@ - diff --git a/engine/schema/src/com/cloud/event/EventVO.java b/engine/schema/src/com/cloud/event/EventVO.java index 3ae46d6244..9be37ddb96 100644 --- a/engine/schema/src/com/cloud/event/EventVO.java +++ b/engine/schema/src/com/cloud/event/EventVO.java @@ -29,8 +29,6 @@ import javax.persistence.Table; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -223,7 +221,7 @@ public void setDisplay(boolean display) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Event; + public Class getEntityType() { + return Event.class; } } diff --git a/engine/schema/src/com/cloud/gpu/VGPUTypesVO.java b/engine/schema/src/com/cloud/gpu/VGPUTypesVO.java index 586a0c9279..fa6674c2c7 100644 --- a/engine/schema/src/com/cloud/gpu/VGPUTypesVO.java +++ b/engine/schema/src/com/cloud/gpu/VGPUTypesVO.java @@ -33,22 +33,55 @@ public class VGPUTypesVO implements InternalIdentity { @Column(name="id") private long id; + @Column(name="gpu_group_id") + private long gpuGroupId; + @Column(name="vgpu_type") private String vgpuType; - @Column(name="gpu_group_id") - private long gpuGroupId; + @Column(name="video_ram") + private long videoRam; + + @Column(name="max_heads") + private long maxHeads; - @Column(name="remaining_vm_capacity") + @Column(name="max_resolution_x") + private long maxResolutionX; + + @Column(name="max_resolution_y") + private long maxResolutionY; + + @Column(name="max_vgpu_per_pgpu") + private long maxVgpuPerPgpu; + + @Column(name="remaining_capacity") private long remainingCapacity; + @Column(name="max_capacity") + private long maxCapacity; + protected VGPUTypesVO() { } - public VGPUTypesVO(String vgpuType, long gpuGroupId, long remainingCapacity) { - this.vgpuType = vgpuType; + public VGPUTypesVO(long gpuGroupId, String vgpuType, long videoRam, long maxHeads, long maxResolutionX, long maxResolutionY, long maxVgpuPerPgpu, + long remainingCapacity, long maxCapacity) { this.gpuGroupId = gpuGroupId; + this.vgpuType = vgpuType; + this.videoRam = videoRam; + this.maxHeads = maxHeads; + this.maxResolutionX = maxResolutionX; + this.maxResolutionY = maxResolutionY; + this.maxVgpuPerPgpu = maxVgpuPerPgpu; this.remainingCapacity = remainingCapacity; + this.maxCapacity = maxCapacity; + } + + public long getGpuGroupId() { + return gpuGroupId; + } + + public void setGpuGroupId(long gpuGroupId) { + this.gpuGroupId = gpuGroupId; } public String getVgpuType() { @@ -59,12 +92,44 @@ public void setVgpuType(String vgpuType) { this.vgpuType = vgpuType; } - public long getGpuGroupId() { - return gpuGroupId; + public long getVideoRam() { + return videoRam; } - public void setGpuGroupId(long gpuGroupId) { - this.gpuGroupId = gpuGroupId; + public void setVideoRam(long videoRam) { + this.videoRam = videoRam; + } + + public long getMaxHeads() { + return maxHeads; + } + + public void setMaxHeads(long maxHeads) { + this.maxHeads = maxHeads; + } + + public long getMaxResolutionX() { + return maxResolutionX; + } + + public void setMaxResolutionX(long maxResolutionX) { + this.maxResolutionX = maxResolutionX; + } + + public long getMaxResolutionY() { + return maxResolutionY; + } + + public void setMaxResolutionY(long maxResolutionY) { + this.maxResolutionY = maxResolutionY; + } + + public long getMaxVgpuPerPgpu() { + return maxVgpuPerPgpu; + } + + public void setMaxVgpuPerPgpu(long maxVgpuPerPgpu) { + this.maxVgpuPerPgpu = maxVgpuPerPgpu; } public long getRemainingCapacity() { @@ -75,6 +140,14 @@ public void setRemainingCapacity(long remainingCapacity) { this.remainingCapacity = remainingCapacity; } + public long getMaxCapacity() { + return maxCapacity; + } + + public void setMaxCapacity(long maxCapacity) { + this.maxCapacity = maxCapacity; + } + @Override public long getId() { return id; diff --git a/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDao.java b/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDao.java index 2872cfda88..25f3085ed3 100644 --- a/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDao.java +++ b/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDao.java @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.List; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.gpu.VGPUTypesVO; import com.cloud.utils.db.GenericDao; @@ -44,5 +45,5 @@ public interface VGPUTypesDao extends GenericDao { * @param hostId the host * @param groupDetails with enabled VGPU types */ - void persist(long hostId, HashMap> groupDetails); + void persist(long hostId, HashMap> groupDetails); } diff --git a/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDaoImpl.java b/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDaoImpl.java index 7cc83cc9eb..81a1945ac7 100644 --- a/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDaoImpl.java +++ b/engine/schema/src/com/cloud/gpu/dao/VGPUTypesDaoImpl.java @@ -27,6 +27,7 @@ import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.gpu.HostGpuGroupsVO; import com.cloud.gpu.VGPUTypesVO; import com.cloud.utils.db.GenericDaoBase; @@ -73,20 +74,23 @@ public VGPUTypesVO findByGroupIdVGPUType(long groupId, String vgpuType) { } @Override - public void persist(long hostId, HashMap> groupDetails) { - Iterator>> it1 = groupDetails.entrySet().iterator(); + public void persist(long hostId, HashMap> groupDetails) { + Iterator>> it1 = groupDetails.entrySet().iterator(); while (it1.hasNext()) { - Entry> entry = it1.next(); + Entry> entry = it1.next(); HostGpuGroupsVO gpuGroup = _hostGpuGroupsDao.findByHostIdGroupName(hostId, entry.getKey()); - HashMap values = entry.getValue(); - Iterator> it2 = values.entrySet().iterator(); + HashMap values = entry.getValue(); + Iterator> it2 = values.entrySet().iterator(); while (it2.hasNext()) { - Entry record = it2.next(); + Entry record = it2.next(); + VgpuTypesInfo details = record.getValue(); VGPUTypesVO vgpuType = null; if ((vgpuType = findByGroupIdVGPUType(gpuGroup.getId(), record.getKey())) == null) { - persist(new VGPUTypesVO(record.getKey(), gpuGroup.getId(), record.getValue())); + persist(new VGPUTypesVO(gpuGroup.getId(), record.getKey(), details.getVideoRam(), details.getMaxHeads(), details.getMaxResolutionX(), + details.getMaxResolutionY(), details.getMaxVpuPerGpu(), details.getRemainingCapacity(), details.getMaxCapacity())); } else { - vgpuType.setRemainingCapacity(record.getValue()); + vgpuType.setRemainingCapacity(details.getRemainingCapacity()); + vgpuType.setMaxCapacity(details.getMaxCapacity()); update(vgpuType.getId(), vgpuType); } } diff --git a/engine/schema/src/com/cloud/host/HostVO.java b/engine/schema/src/com/cloud/host/HostVO.java index 25cc9544da..4af8fb73d8 100755 --- a/engine/schema/src/com/cloud/host/HostVO.java +++ b/engine/schema/src/com/cloud/host/HostVO.java @@ -38,6 +38,7 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.resource.ResourceState; import com.cloud.storage.Storage.StoragePoolType; @@ -156,7 +157,7 @@ public class HostVO implements Host { // This value is only for saving and current cannot be loaded. @Transient - HashMap> groupDetails = new HashMap>(); + HashMap> groupDetails = new HashMap>(); @Override public String getStorageIpAddressDeux() { @@ -318,11 +319,11 @@ public void setHostTags(List hostTags) { this.hostTags = hostTags; } - public HashMap> getGpuGroupDetails() { + public HashMap> getGpuGroupDetails() { return groupDetails; } - public void setGpuGroups(HashMap> groupDetails) { + public void setGpuGroups(HashMap> groupDetails) { this.groupDetails = groupDetails; } diff --git a/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java b/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java index c2a9826405..4d7e83de59 100755 --- a/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java +++ b/engine/schema/src/com/cloud/host/dao/HostDaoImpl.java @@ -34,6 +34,7 @@ import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.cluster.agentlb.HostTransferMapVO; import com.cloud.cluster.agentlb.dao.HostTransferMapDao; import com.cloud.dc.ClusterVO; @@ -782,7 +783,7 @@ protected void saveHostTags(HostVO host) { } protected void saveGpuRecords(HostVO host) { - HashMap> groupDetails = host.getGpuGroupDetails(); + HashMap> groupDetails = host.getGpuGroupDetails(); if (groupDetails != null) { // Create/Update GPU group entries _hostGpuGroupsDao.persist(host.getId(), new ArrayList(groupDetails.keySet())); @@ -899,7 +900,8 @@ public long countRoutingHostsByDataCenter(long dcId) { @Override public boolean updateState(Status oldStatus, Event event, Status newStatus, Host vo, Object data) { - HostVO host = findById(vo.getId()); + // lock target row from beginning to avoid lock-promotion caused deadlock + HostVO host = lockRow(vo.getId(), true); if (host == null) { if (event == Event.Remove && newStatus == Status.Removed) { host = findByIdIncludingRemoved(vo.getId()); @@ -953,46 +955,49 @@ public boolean updateState(Status oldStatus, Event event, Status newStatus, Host int result = update(ub, sc, null); assert result <= 1 : "How can this update " + result + " rows? "; - if (status_logger.isDebugEnabled() && result == 0) { + if (result == 0) { HostVO ho = findById(host.getId()); assert ho != null : "How how how? : " + host.getId(); - StringBuilder str = new StringBuilder("Unable to update host for event:").append(event.toString()); - str.append(". Name=").append(host.getName()); - str.append("; New=[status=") - .append(newStatus.toString()) - .append(":msid=") - .append(newStatus.lostConnection() ? "null" : host.getManagementServerId()) - .append(":lastpinged=") - .append(host.getLastPinged()) - .append("]"); - str.append("; Old=[status=") - .append(oldStatus.toString()) - .append(":msid=") - .append(host.getManagementServerId()) - .append(":lastpinged=") - .append(oldPingTime) - .append("]"); - str.append("; DB=[status=") - .append(vo.getStatus().toString()) - .append(":msid=") - .append(vo.getManagementServerId()) - .append(":lastpinged=") - .append(vo.getLastPinged()) - .append(":old update count=") - .append(oldUpdateCount) - .append("]"); - status_logger.debug(str.toString()); - } else { - StringBuilder msg = new StringBuilder("Agent status update: ["); - msg.append("id = " + host.getId()); - msg.append("; name = " + host.getName()); - msg.append("; old status = " + oldStatus); - msg.append("; event = " + event); - msg.append("; new status = " + newStatus); - msg.append("; old update count = " + oldUpdateCount); - msg.append("; new update count = " + newUpdateCount + "]"); - status_logger.debug(msg.toString()); + if (status_logger.isDebugEnabled()) { + + StringBuilder str = new StringBuilder("Unable to update host for event:").append(event.toString()); + str.append(". Name=").append(host.getName()); + str.append("; New=[status=") + .append(newStatus.toString()) + .append(":msid=") + .append(newStatus.lostConnection() ? "null" : host.getManagementServerId()) + .append(":lastpinged=") + .append(host.getLastPinged()) + .append("]"); + str.append("; Old=[status=").append(oldStatus.toString()).append(":msid=").append(host.getManagementServerId()).append(":lastpinged=").append(oldPingTime) + .append("]"); + str.append("; DB=[status=") + .append(vo.getStatus().toString()) + .append(":msid=") + .append(vo.getManagementServerId()) + .append(":lastpinged=") + .append(vo.getLastPinged()) + .append(":old update count=") + .append(oldUpdateCount) + .append("]"); + status_logger.debug(str.toString()); + } else { + StringBuilder msg = new StringBuilder("Agent status update: ["); + msg.append("id = " + host.getId()); + msg.append("; name = " + host.getName()); + msg.append("; old status = " + oldStatus); + msg.append("; event = " + event); + msg.append("; new status = " + newStatus); + msg.append("; old update count = " + oldUpdateCount); + msg.append("; new update count = " + newUpdateCount + "]"); + status_logger.debug(msg.toString()); + } + + if (ho.getState() == newStatus) { + status_logger.debug("Host " + ho.getName() + " state has already been updated to " + newStatus); + return true; + } } return result > 0; diff --git a/engine/schema/src/com/cloud/network/UserIpv6AddressVO.java b/engine/schema/src/com/cloud/network/UserIpv6AddressVO.java index 9314993620..397c7b3b31 100644 --- a/engine/schema/src/com/cloud/network/UserIpv6AddressVO.java +++ b/engine/schema/src/com/cloud/network/UserIpv6AddressVO.java @@ -28,8 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -188,7 +186,7 @@ public void setCreated(Date created) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.UserIpv6Address; + public Class getEntityType() { + return UserIpv6Address.class; } } diff --git a/engine/schema/src/com/cloud/network/VpnUserVO.java b/engine/schema/src/com/cloud/network/VpnUserVO.java index 695aac0a9d..d6c4b60352 100644 --- a/engine/schema/src/com/cloud/network/VpnUserVO.java +++ b/engine/schema/src/com/cloud/network/VpnUserVO.java @@ -27,8 +27,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.Encrypt; @Entity @@ -129,7 +127,7 @@ public void setUuid(String uuid) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VpnUser; + public Class getEntityType() { + return VpnUser.class; } } diff --git a/engine/schema/src/com/cloud/network/as/AutoScalePolicyVO.java b/engine/schema/src/com/cloud/network/as/AutoScalePolicyVO.java index bde38f83d9..1842533000 100644 --- a/engine/schema/src/com/cloud/network/as/AutoScalePolicyVO.java +++ b/engine/schema/src/com/cloud/network/as/AutoScalePolicyVO.java @@ -30,7 +30,6 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.InternalIdentity; import com.cloud.utils.db.GenericDao; @@ -153,8 +152,8 @@ public void setLastQuiteTime(Date lastQuiteTime) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.AutoScalePolicy; + public Class getEntityType() { + return AutoScalePolicy.class; } } diff --git a/engine/schema/src/com/cloud/network/as/AutoScaleVmGroupVO.java b/engine/schema/src/com/cloud/network/as/AutoScaleVmGroupVO.java index 3a05a7b909..d32e7f873a 100644 --- a/engine/schema/src/com/cloud/network/as/AutoScaleVmGroupVO.java +++ b/engine/schema/src/com/cloud/network/as/AutoScaleVmGroupVO.java @@ -30,7 +30,6 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.InternalIdentity; import com.cloud.utils.db.GenericDao; @@ -227,7 +226,7 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.AutoScaleVmGroup; + public Class getEntityType() { + return AutoScaleVmGroup.class; } } diff --git a/engine/schema/src/com/cloud/network/as/AutoScaleVmProfileVO.java b/engine/schema/src/com/cloud/network/as/AutoScaleVmProfileVO.java index 0b59394ddd..69e4c8190f 100644 --- a/engine/schema/src/com/cloud/network/as/AutoScaleVmProfileVO.java +++ b/engine/schema/src/com/cloud/network/as/AutoScaleVmProfileVO.java @@ -33,7 +33,6 @@ import javax.persistence.InheritanceType; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; @@ -235,8 +234,8 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.AutoScaleVmProfile; + public Class getEntityType() { + return AutoScaleVmProfile.class; } } diff --git a/engine/schema/src/com/cloud/network/as/ConditionVO.java b/engine/schema/src/com/cloud/network/as/ConditionVO.java index e8c1d0bc59..5035f731b5 100644 --- a/engine/schema/src/com/cloud/network/as/ConditionVO.java +++ b/engine/schema/src/com/cloud/network/as/ConditionVO.java @@ -29,7 +29,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; @@ -130,8 +129,8 @@ public Date getRemoved() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Condition; + public Class getEntityType() { + return Condition.class; } } diff --git a/engine/schema/src/com/cloud/network/dao/IPAddressVO.java b/engine/schema/src/com/cloud/network/dao/IPAddressVO.java index d06b8c51d7..de2d934630 100644 --- a/engine/schema/src/com/cloud/network/dao/IPAddressVO.java +++ b/engine/schema/src/com/cloud/network/dao/IPAddressVO.java @@ -31,8 +31,6 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.IpAddress; import com.cloud.utils.net.Ip; @@ -350,7 +348,7 @@ public void setDisplay(boolean display) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.IpAddress; + public Class getEntityType() { + return IpAddress.class; } } diff --git a/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDao.java b/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDao.java index 79eaf8e16b..a25534b701 100644 --- a/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDao.java +++ b/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDao.java @@ -34,4 +34,12 @@ public interface LoadBalancerVMMapDao extends GenericDao listByInstanceIp(String instanceIp); + + List listByLoadBalancerIdAndVmId(long loadBalancerId, long instanceId); + + LoadBalancerVMMapVO findByLoadBalancerIdAndVmIdVmIp(long loadBalancerId, long instanceId, String instanceIp); + + void remove(long id, long instanceId, String instanceIp, Boolean revoke); } diff --git a/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDaoImpl.java b/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDaoImpl.java index b0b14fc23c..cbfda8fadb 100644 --- a/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDaoImpl.java +++ b/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapDaoImpl.java @@ -51,6 +51,21 @@ public void remove(long loadBalancerId, List instanceIds, Boolean revoke) expunge(sc); } + @Override + public void remove(long loadBalancerId, long instanceId, String instanceIp, Boolean revoke) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("loadBalancerId", SearchCriteria.Op.EQ, loadBalancerId); + sc.addAnd("instanceId", SearchCriteria.Op.IN, instanceId); + sc.addAnd("instanceIp", SearchCriteria.Op.EQ, instanceIp); + + if (revoke != null) { + sc.addAnd("revoke", SearchCriteria.Op.EQ, revoke); + } + + expunge(sc); + } + + @Override public List listByInstanceId(long instanceId) { SearchCriteria sc = createSearchCriteria(); @@ -59,6 +74,14 @@ public List listByInstanceId(long instanceId) { return listBy(sc); } + @Override + public List listByInstanceIp(String instanceIp) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("instanceIp", SearchCriteria.Op.EQ, instanceIp); + + return listBy(sc); + } + @Override public List listByLoadBalancerId(long loadBalancerId) { SearchCriteria sc = createSearchCriteria(); @@ -84,6 +107,18 @@ public LoadBalancerVMMapVO findByLoadBalancerIdAndVmId(long loadBalancerId, long return findOneBy(sc); } + + @Override + public LoadBalancerVMMapVO findByLoadBalancerIdAndVmIdVmIp(long loadBalancerId, long instanceId, String instanceIp) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("loadBalancerId", SearchCriteria.Op.EQ, loadBalancerId); + sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId); + sc.addAnd("instanceIp", SearchCriteria.Op.EQ, instanceIp); + + return findOneBy(sc); + } + + @Override public boolean isVmAttachedToLoadBalancer(long loadBalancerId) { GenericSearchBuilder CountByAccount = createSearchBuilder(Long.class); @@ -94,4 +129,12 @@ public boolean isVmAttachedToLoadBalancer(long loadBalancerId) { sc.setParameters("loadBalancerId", loadBalancerId); return customSearch(sc, null).get(0) > 0; } + + @Override + public List listByLoadBalancerIdAndVmId(long loadBalancerId, long instanceId) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("loadBalancerId", SearchCriteria.Op.EQ, loadBalancerId); + sc.addAnd("instanceId", SearchCriteria.Op.EQ, instanceId); + return listBy(sc); + } } diff --git a/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapVO.java b/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapVO.java index 0a67106dc9..08b918475c 100644 --- a/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapVO.java +++ b/engine/schema/src/com/cloud/network/dao/LoadBalancerVMMapVO.java @@ -39,6 +39,9 @@ public class LoadBalancerVMMapVO implements InternalIdentity { @Column(name = "instance_id") private long instanceId; + @Column(name = "instance_ip") + private String instanceIp; + @Column(name = "revoke") private boolean revoke = false; @@ -59,6 +62,13 @@ public LoadBalancerVMMapVO(long loadBalancerId, long instanceId, boolean revoke) this.revoke = revoke; } + public LoadBalancerVMMapVO(long loadBalancerId, long instanceId, String vmIp, boolean revoke) { + this.loadBalancerId = loadBalancerId; + this.instanceId = instanceId; + this.instanceIp = vmIp; + this.revoke = revoke; + } + @Override public long getId() { return id; @@ -87,4 +97,13 @@ public String getState() { public void setState(String state) { this.state = state; } + + public String getInstanceIp() { + return instanceIp; + } + + public void setInstanceIp(String instanceIp) { + this.instanceIp = instanceIp; + } + } diff --git a/engine/schema/src/com/cloud/network/dao/MonitoringServiceVO.java b/engine/schema/src/com/cloud/network/dao/MonitoringServiceVO.java index 999fdfc649..01fba00d0b 100644 --- a/engine/schema/src/com/cloud/network/dao/MonitoringServiceVO.java +++ b/engine/schema/src/com/cloud/network/dao/MonitoringServiceVO.java @@ -25,8 +25,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.MonitoringService; @Entity @@ -120,7 +118,7 @@ public String getProcessName() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.MonitorService; + public Class getEntityType() { + return MonitoringService.class; } } diff --git a/engine/schema/src/com/cloud/network/dao/NetworkVO.java b/engine/schema/src/com/cloud/network/dao/NetworkVO.java index 13e8dbff09..6bb3902394 100644 --- a/engine/schema/src/com/cloud/network/dao/NetworkVO.java +++ b/engine/schema/src/com/cloud/network/dao/NetworkVO.java @@ -30,7 +30,6 @@ import javax.persistence.Transient; import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.acl.IAMEntityType; import com.cloud.network.Network; import com.cloud.network.Networks.BroadcastDomainType; @@ -167,6 +166,9 @@ public class NetworkVO implements Network { @Column(name = "network_acl_id") Long networkACLId; + @Column(name = "streched_l2") + boolean strechedL2Network = false; + public NetworkVO() { uuid = UUID.randomUUID().toString(); } @@ -511,7 +513,7 @@ public boolean equals(Object obj) { @Override public String toString() { StringBuilder buf = new StringBuilder("Ntwk["); - buf.append(id).append("|").append(trafficType).append("|").append(networkOfferingId).append("]"); + buf.append(uuid).append("|").append(trafficType).append("|").append(networkOfferingId).append("]"); return buf.toString(); } @@ -586,7 +588,16 @@ public Long getNetworkACLId() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Network; + public Class getEntityType() { + return Network.class; + } + + @Override + public boolean isStrechedL2Network() { + return strechedL2Network; + } + + public void setStrechedL2Network(boolean strechedL2Network) { + this.strechedL2Network = strechedL2Network; } } diff --git a/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnVO.java b/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnVO.java index 8f95f184c4..0616939fc2 100644 --- a/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnVO.java +++ b/engine/schema/src/com/cloud/network/dao/RemoteAccessVpnVO.java @@ -25,8 +25,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.RemoteAccessVpn; @Entity @@ -168,7 +166,7 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.RemoteAccessVpn; + public Class getEntityType() { + return RemoteAccessVpn.class; } } diff --git a/engine/schema/src/com/cloud/network/dao/Site2SiteCustomerGatewayVO.java b/engine/schema/src/com/cloud/network/dao/Site2SiteCustomerGatewayVO.java index 6de4d429ce..5bcf361836 100644 --- a/engine/schema/src/com/cloud/network/dao/Site2SiteCustomerGatewayVO.java +++ b/engine/schema/src/com/cloud/network/dao/Site2SiteCustomerGatewayVO.java @@ -26,8 +26,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.Site2SiteCustomerGateway; import com.cloud.utils.db.Encrypt; import com.cloud.utils.db.GenericDao; @@ -211,7 +209,7 @@ public long getAccountId() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Site2SiteCustomerGateway; + public Class getEntityType() { + return Site2SiteCustomerGateway.class; } } diff --git a/engine/schema/src/com/cloud/network/dao/Site2SiteVpnConnectionVO.java b/engine/schema/src/com/cloud/network/dao/Site2SiteVpnConnectionVO.java index f0074c04dc..85643fc043 100644 --- a/engine/schema/src/com/cloud/network/dao/Site2SiteVpnConnectionVO.java +++ b/engine/schema/src/com/cloud/network/dao/Site2SiteVpnConnectionVO.java @@ -28,7 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.InternalIdentity; import com.cloud.network.Site2SiteVpnConnection; @@ -175,7 +174,7 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Site2SiteVpnConnection; + public Class getEntityType() { + return Site2SiteVpnConnection.class; } } diff --git a/engine/schema/src/com/cloud/network/dao/Site2SiteVpnGatewayVO.java b/engine/schema/src/com/cloud/network/dao/Site2SiteVpnGatewayVO.java index 33236b9d68..260e5fc4c0 100644 --- a/engine/schema/src/com/cloud/network/dao/Site2SiteVpnGatewayVO.java +++ b/engine/schema/src/com/cloud/network/dao/Site2SiteVpnGatewayVO.java @@ -26,8 +26,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.Site2SiteVpnGateway; import com.cloud.utils.db.GenericDao; @@ -133,7 +131,7 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Site2SiteVpnGateway; + public Class getEntityType() { + return Site2SiteVpnGateway.class; } } diff --git a/engine/schema/src/com/cloud/network/dao/SslCertVO.java b/engine/schema/src/com/cloud/network/dao/SslCertVO.java index 6ef7afd1c7..2676d611bd 100644 --- a/engine/schema/src/com/cloud/network/dao/SslCertVO.java +++ b/engine/schema/src/com/cloud/network/dao/SslCertVO.java @@ -23,8 +23,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.lb.SslCert; import com.cloud.utils.db.Encrypt; @@ -124,8 +122,8 @@ public String getFingerPrint() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.SSLCert; + public Class getEntityType() { + return SslCert.class; } } \ No newline at end of file diff --git a/engine/schema/src/com/cloud/network/rules/FirewallRuleVO.java b/engine/schema/src/com/cloud/network/rules/FirewallRuleVO.java index 5e22dd4f4e..169102af8c 100644 --- a/engine/schema/src/com/cloud/network/rules/FirewallRuleVO.java +++ b/engine/schema/src/com/cloud/network/rules/FirewallRuleVO.java @@ -34,8 +34,6 @@ import javax.persistence.Table; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; import com.cloud.utils.net.NetUtils; @@ -285,7 +283,7 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.FirewallRule; + public Class getEntityType() { + return FirewallRule.class; } } diff --git a/engine/schema/src/com/cloud/network/security/SecurityGroupVO.java b/engine/schema/src/com/cloud/network/security/SecurityGroupVO.java index 26859f704e..4a4c83ae74 100644 --- a/engine/schema/src/com/cloud/network/security/SecurityGroupVO.java +++ b/engine/schema/src/com/cloud/network/security/SecurityGroupVO.java @@ -25,8 +25,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - @Entity @Table(name = ("security_group")) public class SecurityGroupVO implements SecurityGroup { @@ -97,7 +95,7 @@ public void setUuid(String uuid) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.SecurityGroup; + public Class getEntityType() { + return SecurityGroup.class; } } diff --git a/engine/schema/src/com/cloud/network/vpc/StaticRouteVO.java b/engine/schema/src/com/cloud/network/vpc/StaticRouteVO.java index a9ba05154b..2c2d53edb2 100644 --- a/engine/schema/src/com/cloud/network/vpc/StaticRouteVO.java +++ b/engine/schema/src/com/cloud/network/vpc/StaticRouteVO.java @@ -28,8 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -139,7 +137,7 @@ public String toString() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.StaticRoute; + public Class getEntityType() { + return StaticRoute.class; } } \ No newline at end of file diff --git a/engine/schema/src/com/cloud/network/vpc/VpcGatewayVO.java b/engine/schema/src/com/cloud/network/vpc/VpcGatewayVO.java index 48238b1971..23568b4923 100644 --- a/engine/schema/src/com/cloud/network/vpc/VpcGatewayVO.java +++ b/engine/schema/src/com/cloud/network/vpc/VpcGatewayVO.java @@ -28,8 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -219,7 +217,7 @@ public long getNetworkACLId() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VpcGateway; + public Class getEntityType() { + return VpcGateway.class; } } diff --git a/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java b/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java index 53f6f6055e..a7d61b3692 100644 --- a/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java +++ b/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java @@ -70,6 +70,9 @@ public class VpcOfferingVO implements VpcOffering { @Column(name = "supports_distributed_router") boolean supportsDistributedRouter=false; + @Column(name = "supports_region_level_vpc") + boolean offersRegionLevelVPC = false; + public VpcOfferingVO() { this.uuid = UUID.randomUUID().toString(); } @@ -84,10 +87,11 @@ public VpcOfferingVO(String name, String displayText, Long serviceOfferingId) { } public VpcOfferingVO(String name, String displayText, boolean isDefault, Long serviceOfferingId, - boolean supportsDistributedRouter) { + boolean supportsDistributedRouter, boolean offersRegionLevelVPC) { this(name, displayText, serviceOfferingId); this.isDefault = isDefault; this.supportsDistributedRouter = supportsDistributedRouter; + this.offersRegionLevelVPC = offersRegionLevelVPC; } @Override @@ -155,4 +159,9 @@ public Long getServiceOfferingId() { public boolean supportsDistributedRouter() { return supportsDistributedRouter; } + + @Override + public boolean offersRegionLevelVPC() { + return offersRegionLevelVPC; + } } diff --git a/engine/schema/src/com/cloud/network/vpc/VpcVO.java b/engine/schema/src/com/cloud/network/vpc/VpcVO.java index dea8c314bc..22d51dd542 100644 --- a/engine/schema/src/com/cloud/network/vpc/VpcVO.java +++ b/engine/schema/src/com/cloud/network/vpc/VpcVO.java @@ -26,8 +26,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -84,12 +82,15 @@ public class VpcVO implements Vpc { @Column(name="uses_distributed_router") boolean usesDistributedRouter = false; + @Column(name = "region_level_vpc") + boolean regionLevelVpc = false; + public VpcVO() { uuid = UUID.randomUUID().toString(); } public VpcVO(long zoneId, String name, String displayText, long accountId, long domainId, long vpcOffId, String cidr, - String networkDomain, boolean useDistributedRouter) { + String networkDomain, boolean useDistributedRouter, boolean regionLevelVpc) { this.zoneId = zoneId; this.name = name; this.displayText = displayText; @@ -99,8 +100,9 @@ public VpcVO(long zoneId, String name, String displayText, long accountId, long uuid = UUID.randomUUID().toString(); state = State.Enabled; this.networkDomain = networkDomain; - this.vpcOfferingId = vpcOffId; - this.usesDistributedRouter = useDistributedRouter; + vpcOfferingId = vpcOffId; + usesDistributedRouter = useDistributedRouter; + this.regionLevelVpc = regionLevelVpc; } @Override @@ -193,6 +195,11 @@ public void setUuid(String uuid) { this.uuid = uuid; } + @Override + public boolean isRegionLevelVpc() { + return regionLevelVpc; + } + public void setDisplay(boolean display) { this.display = display; @@ -204,8 +211,8 @@ public boolean isDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Vpc; + public Class getEntityType() { + return Vpc.class; } @Override diff --git a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java index bf07807494..c3d849d134 100755 --- a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java +++ b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java @@ -139,6 +139,9 @@ public class NetworkOfferingVO implements NetworkOffering { @Column(name = "keep_alive_enabled") boolean keepAliveEnabled = false; + @Column(name="supports_streched_l2") + boolean supportsStrechedL2 = false; + @Override public String getDisplayText() { return displayText; @@ -331,7 +334,7 @@ public NetworkOfferingVO(String name, String displayText, TrafficType trafficTyp public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps, Integer multicastRateMbps, boolean isDefault, Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, boolean dedicatedLb, boolean sharedSourceNat, boolean redundantRouter, boolean elasticIp, boolean elasticLb, boolean specifyIpRanges, boolean inline, boolean isPersistent, - boolean associatePublicIP, boolean publicLb, boolean internalLb, boolean egressdefaultpolicy) { + boolean associatePublicIP, boolean publicLb, boolean internalLb, boolean egressdefaultpolicy, boolean supportsStrechedL2) { this(name, displayText, trafficType, @@ -356,6 +359,7 @@ public NetworkOfferingVO(String name, String displayText, TrafficType trafficTyp this.inline = inline; this.eipAssociatePublicIp = associatePublicIP; this.egressdefaultpolicy = egressdefaultpolicy; + this.supportsStrechedL2 = supportsStrechedL2; } public NetworkOfferingVO() { @@ -486,4 +490,9 @@ public void setConcurrentConnections(Integer concurrentConnections) { public void setPublicLb(boolean publicLb) { this.publicLb = publicLb; } + + @Override + public boolean getSupportsStrechedL2() { + return supportsStrechedL2; + } } diff --git a/engine/schema/src/com/cloud/projects/ProjectInvitationVO.java b/engine/schema/src/com/cloud/projects/ProjectInvitationVO.java index 885c148c2b..9775135bea 100644 --- a/engine/schema/src/com/cloud/projects/ProjectInvitationVO.java +++ b/engine/schema/src/com/cloud/projects/ProjectInvitationVO.java @@ -28,8 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -149,7 +147,7 @@ public long getAccountId() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.ProjectInvitation; + public Class getEntityType() { + return ProjectInvitation.class; } } diff --git a/engine/schema/src/com/cloud/service/ServiceOfferingVO.java b/engine/schema/src/com/cloud/service/ServiceOfferingVO.java index 3873dd272f..3be0aaa774 100755 --- a/engine/schema/src/com/cloud/service/ServiceOfferingVO.java +++ b/engine/schema/src/com/cloud/service/ServiceOfferingVO.java @@ -173,6 +173,7 @@ public ServiceOfferingVO(ServiceOfferingVO offering) { offering.getUseLocalStorage(), offering.getSystemUse(), true, + offering.isCustomizedIops(), offering.getDomainId()); cpu = offering.getCpu(); ramSize = offering.getRamSize(); diff --git a/engine/schema/src/com/cloud/storage/DiskOfferingVO.java b/engine/schema/src/com/cloud/storage/DiskOfferingVO.java index d1a48d20c9..99214b2190 100755 --- a/engine/schema/src/com/cloud/storage/DiskOfferingVO.java +++ b/engine/schema/src/com/cloud/storage/DiskOfferingVO.java @@ -207,7 +207,7 @@ public DiskOfferingVO(String name, String displayText, boolean mirrored, String } public DiskOfferingVO(long id, String name, String displayText, boolean mirrored, String tags, boolean recreatable, - boolean useLocalStorage, boolean systemUse, boolean customized, Long domainId) { + boolean useLocalStorage, boolean systemUse, boolean customized, boolean customizedIops, Long domainId) { this.id = id; type = Type.Service; this.name = name; @@ -217,6 +217,7 @@ public DiskOfferingVO(long id, String name, String displayText, boolean mirrored this.useLocalStorage = useLocalStorage; this.systemUse = systemUse; this.customized = customized; + this.customizedIops = customizedIops; this.domainId = domainId; uuid = UUID.randomUUID().toString(); state = State.Active; diff --git a/engine/schema/src/com/cloud/storage/SnapshotVO.java b/engine/schema/src/com/cloud/storage/SnapshotVO.java index 4c8ceb7cdd..dae049f604 100644 --- a/engine/schema/src/com/cloud/storage/SnapshotVO.java +++ b/engine/schema/src/com/cloud/storage/SnapshotVO.java @@ -30,8 +30,6 @@ import com.google.gson.annotations.Expose; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.utils.db.GenericDao; @@ -239,7 +237,7 @@ public void setUuid(String uuid) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Snapshot; + public Class getEntityType() { + return Snapshot.class; } } diff --git a/engine/schema/src/com/cloud/storage/VMTemplateVO.java b/engine/schema/src/com/cloud/storage/VMTemplateVO.java index c0b7d0fc02..9a77cbf873 100755 --- a/engine/schema/src/com/cloud/storage/VMTemplateVO.java +++ b/engine/schema/src/com/cloud/storage/VMTemplateVO.java @@ -31,8 +31,6 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; @@ -635,7 +633,7 @@ public void setUpdated(Date updated) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VirtualMachineTemplate; + public Class getEntityType() { + return VirtualMachineTemplate.class; } } diff --git a/engine/schema/src/com/cloud/storage/VolumeVO.java b/engine/schema/src/com/cloud/storage/VolumeVO.java index af99a16ffa..9f27c231f0 100755 --- a/engine/schema/src/com/cloud/storage/VolumeVO.java +++ b/engine/schema/src/com/cloud/storage/VolumeVO.java @@ -32,8 +32,6 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.storage.Storage.StoragePoolType; import com.cloud.utils.NumbersUtil; import com.cloud.utils.db.GenericDao; @@ -601,7 +599,7 @@ public Integer getHypervisorSnapshotReserve() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Volume; + public Class getEntityType() { + return Volume.class; } } diff --git a/engine/schema/src/com/cloud/tags/ResourceTagVO.java b/engine/schema/src/com/cloud/tags/ResourceTagVO.java index 6b743ffd23..eadddd1e31 100644 --- a/engine/schema/src/com/cloud/tags/ResourceTagVO.java +++ b/engine/schema/src/com/cloud/tags/ResourceTagVO.java @@ -27,8 +27,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.server.ResourceTag; @@ -166,7 +164,7 @@ public String getResourceUuid() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.ResourceTag; + public Class getEntityType() { + return ResourceTag.class; } } diff --git a/engine/schema/src/com/cloud/user/AccountVO.java b/engine/schema/src/com/cloud/user/AccountVO.java index 674cdb9101..0f5a0446e9 100644 --- a/engine/schema/src/com/cloud/user/AccountVO.java +++ b/engine/schema/src/com/cloud/user/AccountVO.java @@ -28,8 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -190,7 +188,7 @@ public boolean isDefault() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Account; + public Class getEntityType() { + return Account.class; } } diff --git a/engine/schema/src/com/cloud/user/SSHKeyPairVO.java b/engine/schema/src/com/cloud/user/SSHKeyPairVO.java index 4dc03c45b0..fd7173ee7a 100644 --- a/engine/schema/src/com/cloud/user/SSHKeyPairVO.java +++ b/engine/schema/src/com/cloud/user/SSHKeyPairVO.java @@ -24,8 +24,6 @@ import javax.persistence.Table; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - @Entity @Table(name = "ssh_keypairs") public class SSHKeyPairVO implements SSHKeyPair { @@ -117,7 +115,7 @@ public void setPrivateKey(String privateKey) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.SSHKeyPair; + public Class getEntityType() { + return SSHKeyPair.class; } } diff --git a/engine/schema/src/com/cloud/vm/InstanceGroupVO.java b/engine/schema/src/com/cloud/vm/InstanceGroupVO.java index 9b463d3428..395751b705 100644 --- a/engine/schema/src/com/cloud/vm/InstanceGroupVO.java +++ b/engine/schema/src/com/cloud/vm/InstanceGroupVO.java @@ -28,8 +28,6 @@ import javax.persistence.SecondaryTable; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; @Entity @@ -120,7 +118,7 @@ public Short getAccountType() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.InstanceGroup; + public Class getEntityType() { + return InstanceGroup.class; } } diff --git a/engine/schema/src/com/cloud/vm/VMInstanceVO.java b/engine/schema/src/com/cloud/vm/VMInstanceVO.java index ddeebfeb75..3d4337f374 100644 --- a/engine/schema/src/com/cloud/vm/VMInstanceVO.java +++ b/engine/schema/src/com/cloud/vm/VMInstanceVO.java @@ -36,8 +36,6 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.utils.db.Encrypt; import com.cloud.utils.db.GenericDao; @@ -386,10 +384,16 @@ public boolean isHaEnabled() { return haEnabled; } + //FIXME - Remove this and use isDisplay() instead public boolean isDisplayVm() { return displayVm; } + @Override + public boolean isDisplay() { + return displayVm; + } + public void setDisplayVm(boolean displayVm) { this.displayVm = displayVm; } @@ -413,8 +417,8 @@ public Long getPodIdToDeployIn() { return podIdToDeployIn; } - public void setPodId(long podId) { - podIdToDeployIn = podId; + public void setPodId(Long podId) { + this.podIdToDeployIn = podId; } public void setPrivateMacAddress(String privateMacAddress) { @@ -461,7 +465,7 @@ public void setDetails(Map details) { @Override public String toString() { if (toString == null) { - toString = new StringBuilder("VM[").append(type.toString()).append("|").append(hostName).append("]").toString(); + toString = new StringBuilder("VM[").append(type.toString()).append("|").append(getInstanceName()).append("]").toString(); } return toString; } @@ -506,8 +510,8 @@ public Boolean isDynamicallyScalable() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VirtualMachine; + public Class getEntityType() { + return VirtualMachine.class; } public VirtualMachine.PowerState getPowerState() { diff --git a/engine/schema/src/com/cloud/vm/dao/DomainRouterDao.java b/engine/schema/src/com/cloud/vm/dao/DomainRouterDao.java index e3f75fabd7..72ff8a91dd 100755 --- a/engine/schema/src/com/cloud/vm/dao/DomainRouterDao.java +++ b/engine/schema/src/com/cloud/vm/dao/DomainRouterDao.java @@ -108,6 +108,8 @@ public interface DomainRouterDao extends GenericDao { */ List listByStateAndNetworkType(State state, Network.GuestType type, long mgmtSrvrId); + List listByStateAndManagementServer(State state, long mgmtSrvrId); + List findByNetworkOutsideThePod(long networkId, long podId, State state, Role role); List listByNetworkAndPodAndRole(long networkId, long podId, Role role); diff --git a/engine/schema/src/com/cloud/vm/dao/DomainRouterDaoImpl.java b/engine/schema/src/com/cloud/vm/dao/DomainRouterDaoImpl.java index 6b62f56873..ea919ac536 100755 --- a/engine/schema/src/com/cloud/vm/dao/DomainRouterDaoImpl.java +++ b/engine/schema/src/com/cloud/vm/dao/DomainRouterDaoImpl.java @@ -60,6 +60,7 @@ public class DomainRouterDaoImpl extends GenericDaoBase im protected SearchBuilder StateNetworkTypeSearch; protected SearchBuilder OutsidePodSearch; protected SearchBuilder clusterSearch; + protected SearchBuilder SearchByStateAndManagementServerId; @Inject HostDao _hostsDao; @Inject @@ -130,6 +131,14 @@ protected void init() { StateNetworkTypeSearch.join("host", joinHost, joinHost.entity().getId(), StateNetworkTypeSearch.entity().getHostId(), JoinType.INNER); StateNetworkTypeSearch.done(); + SearchByStateAndManagementServerId = createSearchBuilder(); + SearchByStateAndManagementServerId.and("state", SearchByStateAndManagementServerId.entity().getState(), Op.EQ); + + SearchBuilder joinHost2 = _hostsDao.createSearchBuilder(); + joinHost2.and("mgmtServerId", joinHost2.entity().getManagementServerId(), Op.EQ); + SearchByStateAndManagementServerId.join("host", joinHost2, joinHost2.entity().getId(), SearchByStateAndManagementServerId.entity().getHostId(), JoinType.INNER); + SearchByStateAndManagementServerId.done(); + OutsidePodSearch = createSearchBuilder(); SearchBuilder joinRouterNetwork2 = _routerNetworkDao.createSearchBuilder(); joinRouterNetwork2.and("networkId", joinRouterNetwork2.entity().getNetworkId(), Op.EQ); @@ -293,6 +302,15 @@ public List listByStateAndNetworkType(State state, Network.Guest return routers; } + @Override + public List listByStateAndManagementServer(State state, long mgmtSrvrId) { + SearchCriteria sc = SearchByStateAndManagementServerId.create(); + sc.setParameters("state", state); + sc.setJoinParameters("host", "mgmtServerId", mgmtSrvrId); + + return listBy(sc); + } + @Override public List findByNetworkOutsideThePod(long networkId, long podId, State state, Role role) { SearchCriteria sc = OutsidePodSearch.create(); diff --git a/engine/schema/src/com/cloud/vm/dao/NicIpAliasVO.java b/engine/schema/src/com/cloud/vm/dao/NicIpAliasVO.java index 3df9909620..2f000fde8a 100644 --- a/engine/schema/src/com/cloud/vm/dao/NicIpAliasVO.java +++ b/engine/schema/src/com/cloud/vm/dao/NicIpAliasVO.java @@ -28,8 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; import com.cloud.utils.net.NetUtils; import com.cloud.vm.NicIpAlias; @@ -235,7 +233,7 @@ public String getStartIpOfSubnet() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.NicIpAlias; + public Class getEntityType() { + return NicIpAlias.class; } } diff --git a/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpVO.java b/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpVO.java index 995da17ddc..f8730aac5d 100644 --- a/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpVO.java +++ b/engine/schema/src/com/cloud/vm/dao/NicSecondaryIpVO.java @@ -26,8 +26,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; import com.cloud.vm.NicSecondaryIp; @@ -128,7 +126,7 @@ public long getVmId() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.NicSecondaryIp; + public Class getEntityType() { + return NicSecondaryIp.class; } } diff --git a/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java b/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java index 2f25f577f4..cc05f53605 100644 --- a/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java +++ b/engine/schema/src/com/cloud/vm/dao/VMInstanceDaoImpl.java @@ -437,6 +437,9 @@ public boolean updateState(State oldState, Event event, State newState, VirtualM return true; } + // lock the target row at beginning to avoid lock-promotion caused deadlock + lockRow(vm.getId(), true); + SearchCriteria sc = StateChangeSearch.create(); sc.setParameters("id", vmi.getId()); sc.setParameters("states", oldState); @@ -452,41 +455,29 @@ public boolean updateState(State oldState, Event event, State newState, VirtualM ub.set(vmi, _updateTimeAttr, new Date()); int result = update(vmi, sc); - if (result == 0 && s_logger.isDebugEnabled()) { - + if (result == 0) { VMInstanceVO vo = findByIdIncludingRemoved(vm.getId()); - if (vo != null) { - StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); - str.append(": DB Data={Host=") - .append(vo.getHostId()) - .append("; State=") - .append(vo.getState().toString()) - .append("; updated=") - .append(vo.getUpdated()) - .append("; time=") - .append(vo.getUpdateTime()); - str.append("} New Data: {Host=") - .append(vm.getHostId()) - .append("; State=") - .append(vm.getState().toString()) - .append("; updated=") - .append(vmi.getUpdated()) - .append("; time=") - .append(vo.getUpdateTime()); - str.append("} Stale Data: {Host=") - .append(oldHostId) - .append("; State=") - .append(oldState) - .append("; updated=") - .append(oldUpdated) - .append("; time=") - .append(oldUpdateDate) - .append("}"); - s_logger.debug(str.toString()); - - } else { - s_logger.debug("Unable to update the vm id=" + vm.getId() + "; the vm either doesn't exist or already removed"); + if (s_logger.isDebugEnabled()) { + if (vo != null) { + StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString()); + str.append(": DB Data={Host=").append(vo.getHostId()).append("; State=").append(vo.getState().toString()).append("; updated=").append(vo.getUpdated()) + .append("; time=").append(vo.getUpdateTime()); + str.append("} New Data: {Host=").append(vm.getHostId()).append("; State=").append(vm.getState().toString()).append("; updated=").append(vmi.getUpdated()) + .append("; time=").append(vo.getUpdateTime()); + str.append("} Stale Data: {Host=").append(oldHostId).append("; State=").append(oldState).append("; updated=").append(oldUpdated).append("; time=") + .append(oldUpdateDate).append("}"); + s_logger.debug(str.toString()); + + } else { + s_logger.debug("Unable to update the vm id=" + vm.getId() + "; the vm either doesn't exist or already removed"); + } + } + + if (vo != null && vo.getState() == newState) { + // allow for concurrent update if target state has already been matched + s_logger.debug("VM " + vo.getInstanceName() + " state has been already been updated to " + newState); + return true; } } return result > 0; diff --git a/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotVO.java b/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotVO.java index 042b276fe4..df2966d45b 100644 --- a/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotVO.java +++ b/engine/schema/src/com/cloud/vm/snapshot/VMSnapshotVO.java @@ -33,7 +33,6 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.engine.subsystem.api.storage.VMSnapshotOptions; import com.cloud.utils.db.GenericDao; @@ -246,7 +245,7 @@ public void setRemoved(Date removed) { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VMSnapshot; + public Class getEntityType() { + return VMSnapshot.class; } } diff --git a/engine/schema/src/org/apache/cloudstack/affinity/AffinityGroupVO.java b/engine/schema/src/org/apache/cloudstack/affinity/AffinityGroupVO.java index b9fda8e9e3..03274ad438 100644 --- a/engine/schema/src/org/apache/cloudstack/affinity/AffinityGroupVO.java +++ b/engine/schema/src/org/apache/cloudstack/affinity/AffinityGroupVO.java @@ -28,7 +28,6 @@ import javax.persistence.Table; import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.acl.IAMEntityType; @Entity @Table(name = ("affinity_group")) @@ -126,8 +125,8 @@ public String toString() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.AffinityGroup; + public Class getEntityType() { + return AffinityGroup.class; } } diff --git a/engine/schema/src/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java b/engine/schema/src/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java index 7403d62fcf..b20cae320e 100644 --- a/engine/schema/src/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java +++ b/engine/schema/src/org/apache/cloudstack/engine/cloud/entity/api/db/VMEntityVO.java @@ -37,8 +37,6 @@ import javax.persistence.TemporalType; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.utils.db.Encrypt; import com.cloud.utils.db.GenericDao; @@ -175,6 +173,9 @@ public class VMEntityVO implements VirtualMachine, FiniteStateObject getEntityType() { + return VirtualMachine.class; + } + + @Override + public boolean isDisplay() { + return display; + } + + public void setDisplay(boolean display) { + this.display = display; } } diff --git a/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleVO.java b/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleVO.java index a37fec2d51..88cd0003a2 100644 --- a/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleVO.java +++ b/engine/schema/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancerRuleVO.java @@ -28,8 +28,6 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.region.ha.GlobalLoadBalancerRule; @Entity @@ -191,7 +189,7 @@ public GlobalLoadBalancerRule.State getState() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.GlobalLoadBalancerRule; + public Class getEntityType() { + return GlobalLoadBalancerRule.class; } } diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java index 2c4369d047..a976bfbf6f 100644 --- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java +++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDao.java @@ -113,4 +113,6 @@ public interface PrimaryDataStoreDao extends GenericDao { List findZoneWideStoragePoolsByTags(long dcId, String[] tags); List findZoneWideStoragePoolsByHypervisor(long dataCenterId, HypervisorType hypervisorType); + + List findLocalStoragePoolsByHostAndTags(long hostId, String[] tags); } diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java index 57afa16b50..7e558f81ea 100644 --- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java +++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/PrimaryDataStoreDaoImpl.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; +import javax.annotation.PostConstruct; import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; @@ -31,10 +32,13 @@ import com.cloud.host.Status; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.ScopeType; +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.GenericDaoBase; import com.cloud.utils.db.GenericSearchBuilder; +import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.QueryBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @@ -51,9 +55,14 @@ public class PrimaryDataStoreDaoImpl extends GenericDaoBase protected final SearchBuilder DcPodAnyClusterSearch; protected final SearchBuilder DeleteLvmSearch; protected final GenericSearchBuilder StatusCountSearch; + protected SearchBuilder HostSearch; + protected SearchBuilder HostPoolSearch; + protected SearchBuilder TagPoolSearch; @Inject protected StoragePoolDetailsDao _detailsDao; + @Inject + protected StoragePoolHostDao _hostDao; private final String DetailsSqlPrefix = "SELECT storage_pool.* from storage_pool LEFT JOIN storage_pool_details ON storage_pool.id = storage_pool_details.pool_id WHERE storage_pool.removed is null and storage_pool.status = 'Up' and storage_pool.data_center_id = ? and (storage_pool.pod_id = ? or storage_pool.pod_id is null) and storage_pool.scope = ? and ("; @@ -111,6 +120,26 @@ public PrimaryDataStoreDaoImpl() { } + @PostConstruct + void init() { + HostSearch = createSearchBuilder(); + TagPoolSearch = _detailsDao.createSearchBuilder(); + HostPoolSearch = _hostDao.createSearchBuilder(); + // Search for pools on the host + HostPoolSearch.and("hostId", HostPoolSearch.entity().getHostId(), Op.EQ); + // Set criteria for pools + HostSearch.and("scope", HostSearch.entity().getScope(), Op.EQ); + HostSearch.and("removed", HostSearch.entity().getRemoved(), Op.NULL); + HostSearch.and("status", HostSearch.entity().getStatus(), Op.EQ); + HostSearch.join("hostJoin", HostPoolSearch, HostSearch.entity().getId(), HostPoolSearch.entity().getPoolId(), JoinBuilder.JoinType.INNER); + // Set criteria for tags + TagPoolSearch.and("name", TagPoolSearch.entity().getName(), Op.EQ); + TagPoolSearch.and("value", TagPoolSearch.entity().getValue(), Op.EQ); + + HostSearch.join("tagJoin", TagPoolSearch, HostSearch.entity().getId(), TagPoolSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER); + HostSearch.done(); + } + @Override public List findPoolByName(String name) { SearchCriteria sc = AllFieldSearch.create(); @@ -314,6 +343,23 @@ public List findLocalStoragePoolsByTags(long dcId, long podId, Lo return storagePools; } + @Override + public List findLocalStoragePoolsByHostAndTags(long hostId, String[] tags) { + + SearchCriteria sc = HostSearch.create(); + sc.setJoinParameters("hostJoin", "hostId", hostId ); + sc.setParameters("scope", ScopeType.HOST.toString()); + sc.setParameters("status", Status.Up.toString()); + if (!(tags == null || tags.length == 0 )) { + Map details = tagsToDetails(tags); + for (Map.Entry detail : details.entrySet()) { + sc.setJoinParameters("tagJoin","name", detail.getKey()); + sc.setJoinParameters("tagJoin", "value", detail.getValue()); + } + } + return listBy(sc); + } + @Override public List findZoneWideStoragePoolsByTags(long dcId, String[] tags) { List storagePools = null; diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java index ab458895e4..271bbcae14 100644 --- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java +++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java @@ -65,6 +65,8 @@ public interface TemplateDataStoreDao extends GenericDao listByTemplate(long templateId); + TemplateDataStoreVO findByTemplateZoneReady(long templateId, Long zoneId); + void duplicateCacheRecordsOnRegionStore(long storeId); TemplateDataStoreVO findReadyOnCache(long templateId); diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java index db28a053c1..134e74d58f 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateDataFactoryImpl.java @@ -23,9 +23,6 @@ import javax.inject.Inject; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - 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.DataStoreManager; @@ -34,6 +31,8 @@ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.cloudstack.storage.image.store.TemplateObject; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; import com.cloud.storage.DataStoreRole; import com.cloud.storage.VMTemplateStoragePoolVO; @@ -106,6 +105,17 @@ public TemplateInfo getTemplate(long templateId, DataStoreRole storeRole, Long z return this.getTemplate(templateId, store); } + @Override + public TemplateInfo getReadyTemplateOnImageStore(long templateId, Long zoneId) { + TemplateDataStoreVO tmplStore = templateStoreDao.findByTemplateZoneReady(templateId, zoneId); + if (tmplStore != null) { + DataStore store = storeMgr.getDataStore(tmplStore.getDataStoreId(), DataStoreRole.Image); + return this.getTemplate(templateId, store); + } else { + return null; + } + } + @Override public TemplateInfo getTemplate(DataObject obj, DataStore store) { TemplateObject tmpObj = (TemplateObject)this.getTemplate(obj.getId(), store); diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java index bd14df59b0..7288d454c3 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java @@ -23,7 +23,8 @@ import javax.inject.Inject; -import org.apache.cloudstack.acl.IAMEntityType; +import org.apache.log4j.Logger; + import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; @@ -35,7 +36,6 @@ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao; import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO; import org.apache.cloudstack.storage.to.TemplateObjectTO; -import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; import com.cloud.agent.api.to.DataObjectType; @@ -50,6 +50,7 @@ import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplatePoolDao; +import com.cloud.template.VirtualMachineTemplate; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.fsm.NoTransitionException; @@ -452,7 +453,7 @@ public boolean delete() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VirtualMachineTemplate; + public Class getEntityType() { + return VirtualMachineTemplate.class; } } diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java index a8f1a56735..da8d341e49 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java @@ -24,7 +24,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; @@ -383,7 +382,7 @@ public boolean delete() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Snapshot; + public Class getEntityType() { + return Snapshot.class; } } diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java index 8331012d1e..684b5bd29c 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotServiceImpl.java @@ -302,6 +302,10 @@ protected Void copySnapshotAsyncCallback(AsyncCallbackDispatcher select(DiskProfile dskCh, VirtualMachineProfile vmPr // data disk and host identified from deploying vm (attach volume case) if (dskCh.getType() == Volume.Type.DATADISK && plan.getHostId() != null) { - List hostPools = _poolHostDao.listByHostId(plan.getHostId()); - for (StoragePoolHostVO hostPool : hostPools) { - StoragePoolVO pool = _storagePoolDao.findById(hostPool.getPoolId()); + List hostTagsPools = null; + hostTagsPools =_storagePoolDao.findLocalStoragePoolsByHostAndTags(plan.getHostId(), dskCh.getTags()); + for (StoragePoolVO pool : hostTagsPools) { if (pool != null && pool.isLocal()) { StoragePool storagePool = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(pool.getId()); if (filter(avoid, storagePool, dskCh, plan)) { diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java index fde13e17c8..c1aa8c2f0d 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java @@ -23,7 +23,6 @@ import java.util.List; import java.util.Map; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.engine.cloud.entity.api.TemplateEntity; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.storage.image.datastore.ImageStoreInfo; @@ -31,6 +30,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.TemplateType; +import com.cloud.template.VirtualMachineTemplate; public class TemplateEntityImpl implements TemplateEntity { protected TemplateInfo templateInfo; @@ -287,7 +287,7 @@ public long getVirtualSize() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VirtualMachineTemplate; + public Class getEntityType() { + return VirtualMachineTemplate.class; } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java index d4b0445be7..cce7f08244 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java @@ -400,6 +400,22 @@ public TemplateDataStoreVO findByTemplateZone(long templateId, Long zoneId, Data return null; } + @Override + public TemplateDataStoreVO findByTemplateZoneReady(long templateId, Long zoneId) { + List imgStores = null; + imgStores = _storeMgr.getImageStoresByScope(new ZoneScope(zoneId)); + if (imgStores != null) { + Collections.shuffle(imgStores); + for (DataStore store : imgStores) { + List sRes = listByTemplateStoreStatus(templateId, store.getId(), State.Ready); + if (sRes != null && sRes.size() > 0) { + return sRes.get(0); + } + } + } + return null; + } + /** * Duplicate all image cache store entries */ diff --git a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java b/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java index 848b165893..a660f41211 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/snapshot/SnapshotEntityImpl.java @@ -21,10 +21,10 @@ import java.util.List; import java.util.Map; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.engine.cloud.entity.api.SnapshotEntity; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.Snapshot; public class SnapshotEntityImpl implements SnapshotEntity { @@ -185,7 +185,7 @@ public Type getRecurringType() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Snapshot; + public Class getEntityType() { + return Snapshot.class; } } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java index 4fb37e2a18..f3c9e79027 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java @@ -24,8 +24,6 @@ import javax.inject.Inject; -import org.apache.log4j.Logger; - import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; @@ -47,6 +45,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; import org.apache.cloudstack.storage.volume.VolumeObject; +import org.apache.log4j.Logger; import com.cloud.agent.api.to.DataObjectType; import com.cloud.agent.api.to.DataStoreTO; @@ -391,6 +390,11 @@ public boolean isInMaintenance() { getStatus() == StoragePoolStatus.ErrorInMaintenance || getRemoved() != null; } + @Override + public HypervisorType getHypervisor() { + return pdsv.getHypervisor(); + } + @Override public String getStorageProviderName() { return pdsv.getStorageProviderName(); diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java index 1f05be21f2..385f8e63e9 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java @@ -22,7 +22,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; @@ -670,7 +669,7 @@ public Long getVmSnapshotChainSize() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Volume; + public Class getEntityType() { + return Volume.class; } } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index 68e5a5680e..3a71147f8a 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -527,7 +527,10 @@ protected Void managedCopyBaseImageCallback(AsyncCallbackDispatcher createManagedStorageAndVolumeFromTemplat details.put(PrimaryDataStore.MANAGED, Boolean.TRUE.toString()); details.put(PrimaryDataStore.STORAGE_HOST, destPrimaryDataStore.getHostAddress()); + details.put(PrimaryDataStore.STORAGE_PORT, String.valueOf(destPrimaryDataStore.getPort())); // for managed storage, the storage repository (XenServer) or datastore (ESX) name is based off of the iScsiName property of a volume details.put(PrimaryDataStore.MANAGED_STORE_TARGET, volumeInfo.get_iScsiName()); details.put(PrimaryDataStore.MANAGED_STORE_TARGET_ROOT_VOLUME, volumeInfo.getName()); diff --git a/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageBusBase.java b/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageBusBase.java index a9c433c62c..9432da0a72 100644 --- a/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageBusBase.java +++ b/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageBusBase.java @@ -58,10 +58,13 @@ public void subscribe(String subject, MessageSubscriber subscriber) { assert (subject != null); assert (subscriber != null); if (_gate.enter()) { - SubscriptionNode current = locate(subject, null, true); - assert (current != null); - current.addSubscriber(subscriber); - _gate.leave(); + try { + SubscriptionNode current = locate(subject, null, true); + assert (current != null); + current.addSubscriber(subscriber); + } finally { + _gate.leave(); + } } else { synchronized (_pendingActions) { _pendingActions.add(new ActionRecord(ActionType.Subscribe, subject, subscriber)); @@ -72,14 +75,17 @@ public void subscribe(String subject, MessageSubscriber subscriber) { @Override public void unsubscribe(String subject, MessageSubscriber subscriber) { if (_gate.enter()) { - if (subject != null) { - SubscriptionNode current = locate(subject, null, false); - if (current != null) - current.removeSubscriber(subscriber, false); - } else { - _subscriberRoot.removeSubscriber(subscriber, true); + try { + if (subject != null) { + SubscriptionNode current = locate(subject, null, false); + if (current != null) + current.removeSubscriber(subscriber, false); + } else { + _subscriberRoot.removeSubscriber(subscriber, true); + } + } finally { + _gate.leave(); } - _gate.leave(); } else { synchronized (_pendingActions) { _pendingActions.add(new ActionRecord(ActionType.Unsubscribe, subject, subscriber)); @@ -90,9 +96,12 @@ public void unsubscribe(String subject, MessageSubscriber subscriber) { @Override public void clearAll() { if (_gate.enter()) { - _subscriberRoot.clearAll(); - doPrune(); - _gate.leave(); + try { + _subscriberRoot.clearAll(); + doPrune(); + } finally { + _gate.leave(); + } } else { synchronized (_pendingActions) { _pendingActions.add(new ActionRecord(ActionType.ClearAll, null, null)); @@ -103,8 +112,11 @@ public void clearAll() { @Override public void prune() { if (_gate.enter()) { - doPrune(); - _gate.leave(); + try { + doPrune(); + } finally { + _gate.leave(); + } } else { synchronized (_pendingActions) { _pendingActions.add(new ActionRecord(ActionType.Prune, null, null)); @@ -132,18 +144,19 @@ private void doPrune() { public void publish(String senderAddress, String subject, PublishScope scope, Object args) { if (_gate.enter(true)) { + try { + List chainFromTop = new ArrayList(); + SubscriptionNode current = locate(subject, chainFromTop, false); - List chainFromTop = new ArrayList(); - SubscriptionNode current = locate(subject, chainFromTop, false); - - if (current != null) - current.notifySubscribers(senderAddress, subject, args); - - Collections.reverse(chainFromTop); - for (SubscriptionNode node : chainFromTop) - node.notifySubscribers(senderAddress, subject, args); + if (current != null) + current.notifySubscribers(senderAddress, subject, args); - _gate.leave(); + Collections.reverse(chainFromTop); + for (SubscriptionNode node : chainFromTop) + node.notifySubscribers(senderAddress, subject, args); + } finally { + _gate.leave(); + } } } diff --git a/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageDetector.java b/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageDetector.java index 3fb620c1b3..fae9bf3120 100644 --- a/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageDetector.java +++ b/framework/ipc/src/org/apache/cloudstack/framework/messagebus/MessageDetector.java @@ -31,8 +31,10 @@ public MessageDetector() { } public boolean waitAny(long timeoutInMiliseconds) { - _signalled = false; synchronized (this) { + if (_signalled) + return true; + try { wait(timeoutInMiliseconds); } catch (InterruptedException e) { diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDaoImpl.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDaoImpl.java index cf3e17392b..ee8748adee 100644 --- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDaoImpl.java +++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/VmWorkJobDaoImpl.java @@ -20,9 +20,10 @@ import java.sql.SQLException; import java.util.Date; import java.util.List; -import java.util.TimeZone; - import javax.annotation.PostConstruct; +import javax.inject.Inject; + +import org.apache.log4j.Logger; import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO; import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO.Step; @@ -41,9 +42,14 @@ import com.cloud.vm.VirtualMachine; public class VmWorkJobDaoImpl extends GenericDaoBase implements VmWorkJobDao { + private static final Logger s_logger = Logger.getLogger(VmWorkJobDaoImpl.class); protected SearchBuilder PendingWorkJobSearch; protected SearchBuilder PendingWorkJobByCommandSearch; + protected SearchBuilder ExpungingWorkJobSearch; + + @Inject + protected AsyncJobDao _baseJobDao; public VmWorkJobDaoImpl() { } @@ -63,6 +69,12 @@ public void init() { PendingWorkJobByCommandSearch.and("step", PendingWorkJobByCommandSearch.entity().getStep(), Op.NEQ); PendingWorkJobByCommandSearch.and("cmd", PendingWorkJobByCommandSearch.entity().getCmd(), Op.EQ); PendingWorkJobByCommandSearch.done(); + + ExpungingWorkJobSearch = createSearchBuilder(); + ExpungingWorkJobSearch.and("jobStatus", ExpungingWorkJobSearch.entity().getStatus(), Op.NEQ); + ExpungingWorkJobSearch.and("cutDate", ExpungingWorkJobSearch.entity().getLastUpdated(), Op.LT); + ExpungingWorkJobSearch.and("dispatcher", ExpungingWorkJobSearch.entity().getDispatcher(), Op.EQ); + ExpungingWorkJobSearch.done(); } @Override @@ -124,33 +136,19 @@ public void expungeCompletedWorkJobs(final Date cutDate) { expunge(sc); */ - Transaction.execute(new TransactionCallbackNoReturn() { - @Override - public void doInTransactionWithoutResult(TransactionStatus status) { - TransactionLegacy txn = TransactionLegacy.currentTxn(); - PreparedStatement pstmt = null; - try { - pstmt = txn.prepareAutoCloseStatement( - "DELETE FROM vm_work_job WHERE id IN (SELECT id FROM async_job WHERE job_dispatcher='VmWorkJobDispatcher' AND job_status != 0 AND last_updated < ?)"); - pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), cutDate)); - - pstmt.execute(); - } catch (SQLException e) { - } catch (Throwable e) { - } - - try { - pstmt = txn.prepareAutoCloseStatement( - "DELETE FROM async_job WHERE job_dispatcher='VmWorkJobDispatcher' AND job_status != 0 AND last_updated < ?"); - pstmt.setString(1, DateUtil.getDateDisplayString(TimeZone.getTimeZone("GMT"), cutDate)); - - pstmt.execute(); - } catch (SQLException e) { - } catch (Throwable e) { - } - } - }); + // loop at application level to avoid mysql deadlock issues + SearchCriteria sc = ExpungingWorkJobSearch.create(); + sc.setParameters("jobStatus", JobInfo.Status.IN_PROGRESS); + sc.setParameters("lastUpdated", cutDate); + sc.setParameters("dispatcher", "VmWorkJobDispatcher"); + List expungeList = listBy(sc); + for (VmWorkJobVO job : expungeList) { + if (s_logger.isDebugEnabled()) + s_logger.debug("Expunge completed work job-" + job.getId()); + expunge(job.getId()); + _baseJobDao.expunge(job.getId()); + } } @Override diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java index 49c3032b12..42148bebae 100644 --- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java +++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/impl/AsyncJobManagerImpl.java @@ -256,13 +256,17 @@ public List doInTransaction(TransactionStatus status) { } }); - for (Long id : wakeupList) { - // TODO, we assume that all jobs in this category is API job only - AsyncJobVO jobToWakeup = _jobDao.findById(id); - if (jobToWakeup != null && (jobToWakeup.getPendingSignals() & AsyncJob.Constants.SIGNAL_MASK_WAKEUP) != 0) - scheduleExecution(jobToWakeup, false); - } - + // + // disable wakeup scheduling now, since all API jobs are currently using block-waiting for sub-jobs + // + /* + for (Long id : wakeupList) { + // TODO, we assume that all jobs in this category is API job only + AsyncJobVO jobToWakeup = _jobDao.findById(id); + if (jobToWakeup != null && (jobToWakeup.getPendingSignals() & AsyncJob.Constants.SIGNAL_MASK_WAKEUP) != 0) + scheduleExecution(jobToWakeup, false); + } + */ _messageBus.publish(null, AsyncJob.Topics.JOB_STATE, PublishScope.GLOBAL, jobId); } @@ -441,9 +445,9 @@ public void run() { CallContext.registerPlaceHolderContext(); if (job.getRelated() != null && !job.getRelated().isEmpty()) - NDC.push("Job-" + job.getRelated() + "/" + "Job-" + job.getId()); + NDC.push("job-" + job.getRelated() + "/" + "job-" + job.getId()); else - NDC.push("Job-" + job.getId()); + NDC.push("job-" + job.getId()); try { super.run(); } finally { @@ -556,17 +560,41 @@ private void executeQueueItem(SyncQueueItemVO item, boolean fromPreviousSession) job.setSyncSource(item); - job.setExecutingMsid(getMsid()); - _jobDao.update(job.getId(), job); + // + // TODO: a temporary solution to work-around DB deadlock situation + // + // to live with DB deadlocks, we will give a chance for job to be rescheduled + // in case of exceptions (most-likely DB deadlock exceptions) + try { + job.setExecutingMsid(getMsid()); + _jobDao.update(job.getId(), job); + } catch (Exception e) { + s_logger.warn("Unexpected exception while dispatching job-" + item.getContentId(), e); + + try { + _queueMgr.returnItem(item.getId()); + } catch (Throwable thr) { + s_logger.error("Unexpected exception while returning job-" + item.getContentId() + " to queue", thr); + } + } try { scheduleExecution(job); } catch (RejectedExecutionException e) { s_logger.warn("Execution for job-" + job.getId() + " is rejected, return it to the queue for next turn"); - _queueMgr.returnItem(item.getId()); - job.setExecutingMsid(null); - _jobDao.update(job.getId(), job); + try { + _queueMgr.returnItem(item.getId()); + } catch (Exception e2) { + s_logger.error("Unexpected exception while returning job-" + item.getContentId() + " to queue", e2); + } + + try { + job.setExecutingMsid(null); + _jobDao.update(job.getId(), job); + } catch (Exception e3) { + s_logger.warn("Unexpected exception while update job-" + item.getContentId() + " msid for bookkeeping"); + } } } else { diff --git a/framework/security/src/org/apache/cloudstack/framework/security/keys/KeysManagerImpl.java b/framework/security/src/org/apache/cloudstack/framework/security/keys/KeysManagerImpl.java index 550bd155c9..15bb49c65f 100644 --- a/framework/security/src/org/apache/cloudstack/framework/security/keys/KeysManagerImpl.java +++ b/framework/security/src/org/apache/cloudstack/framework/security/keys/KeysManagerImpl.java @@ -61,7 +61,7 @@ public class KeysManagerImpl implements KeysManager, Configurable { public String getHashKey() { String value = HashKey.value(); if (value == null) { - _configDepot.set(HashKey, getBase64EncodedRandomKey(128)); + _configDao.getValueAndInitIfNotExist(HashKey.key(), HashKey.category(), getBase64EncodedRandomKey(128), HashKey.description()); } return HashKey.value(); @@ -71,7 +71,8 @@ public String getHashKey() { public String getEncryptionKey() { String value = EncryptionKey.value(); if (value == null) { - _configDepot.set(EncryptionKey, getBase64EncodedRandomKey(128)); + _configDao.getValueAndInitIfNotExist(EncryptionKey.key(), EncryptionKey.category(), getBase64EncodedRandomKey(128), + EncryptionKey.description()); } return EncryptionKey.value(); } @@ -80,7 +81,8 @@ public String getEncryptionKey() { public String getEncryptionIV() { String value = EncryptionIV.value(); if (value == null) { - _configDepot.set(EncryptionIV, getBase64EncodedRandomKey(128)); + _configDao.getValueAndInitIfNotExist(EncryptionIV.key(), EncryptionIV.category(), getBase64EncodedRandomKey(128), + EncryptionIV.description()); } return EncryptionIV.value(); } diff --git a/packaging/centos63/cloud-usage.rc b/packaging/centos63/cloud-usage.rc index a9b6047887..7768d2b7ac 100755 --- a/packaging/centos63/cloud-usage.rc +++ b/packaging/centos63/cloud-usage.rc @@ -47,7 +47,7 @@ unset OPTIONS [ -r /etc/sysconfig/default/"$SHORTNAME" ] && source /etc/sysconfig/default/"$SHORTNAME" # The first existing directory is used for JAVA_HOME (if JAVA_HOME is not defined in $DEFAULT) -JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-openjdk-i386 /usr/lib/jvm/java-6-openjdk-amd64 /usr/lib/jvm/java-6-sun /usr/lib/jvm/jre-1.6.0 /usr/lib/j2sdk1.5-sun /usr/lib/jre-openjdk" +JDK_DIRS="/usr/lib/jvm/java-7-openjdk /usr/lib/jvm/java-7-openjdk-i386 /usr/lib/jvm/java-7-openjdk-amd64 /usr/lib/jvm/java-7-sun /usr/lib/jvm/jre-1.7.0 /usr/lib/j2sdk1.5-sun /usr/lib/jre-openjdk" for jdir in $JDK_DIRS; do if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then @@ -59,9 +59,9 @@ export JAVA_HOME SCP="" DCP="" UCP=`ls /usr/share/cloudstack-usage/cloud-usage-*.jar`":"`ls /usr/share/cloudstack-usage/lib/*.jar | tr '\n' ':'` -JCP="/usr/share/java/commons-daemon.jar" +JCP="/usr/share/java/commons-daemon.jar":"/usr/share/java/mysql-connector-java.jar" -# We need to append the JSVC daemon JAR to the classpath +# We need to append the JSVC daemon and mysql-connector JAR to the classpath # AgentShell implements the JSVC daemon methods export CLASSPATH="$SCP:$DCP:$UCP:$JCP:/etc/cloudstack/usage" diff --git a/packaging/centos63/cloud.spec b/packaging/centos63/cloud.spec index 83c598b07a..4a5a6d65ec 100644 --- a/packaging/centos63/cloud.spec +++ b/packaging/centos63/cloud.spec @@ -136,6 +136,18 @@ Group: System Environment/Libraries %description agent The CloudStack agent for KVM hypervisors +%package baremetal-agent +Summary: CloudStack baremetal agent +Requires: tftp-server +Requires: xinetd +Requires: syslinux +Requires: chkconfig +Requires: dhcp +Requires: httpd +Group: System Environment/Libraries +%description baremetal-agent +The CloudStack baremetal agent + %package usage Summary: CloudStack Usage calculation server Requires: java >= 1.7.0 @@ -244,6 +256,7 @@ install -D client/target/utilities/bin/cloud-set-guest-sshkey ${RPM_BUILD_ROOT}% install -D client/target/utilities/bin/cloud-setup-databases ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-databases install -D client/target/utilities/bin/cloud-setup-encryption ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-encryption install -D client/target/utilities/bin/cloud-setup-management ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-management +install -D client/target/utilities/bin/cloud-setup-baremetal ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-baremetal install -D client/target/utilities/bin/cloud-sysvmadm ${RPM_BUILD_ROOT}%{_bindir}/%{name}-sysvmadm install -D client/target/utilities/bin/cloud-update-xenserver-licenses ${RPM_BUILD_ROOT}%{_bindir}/%{name}-update-xenserver-licenses @@ -633,6 +646,9 @@ fi %{_defaultdocdir}/%{name}-awsapi-%{version}/LICENSE %{_defaultdocdir}/%{name}-awsapi-%{version}/NOTICE +%files baremetal-agent +%attr(0755,root,root) %{_bindir}/cloudstack-setup-baremetal + %changelog * Fri Oct 03 2012 Hugo Trippaers 4.1.0 diff --git a/packaging/debian/init/cloud-agent b/packaging/debian/init/cloud-agent index e7338752f3..ff550bb8f6 100755 --- a/packaging/debian/init/cloud-agent +++ b/packaging/debian/init/cloud-agent @@ -96,7 +96,7 @@ start() { wait_for_network - if start_daemon -p $PIDFILE $DAEMON -cp "$CLASSPATH" -pidfile "$PIDFILE" -errfile SYSLOG $CLASS + if start_daemon -p $PIDFILE $DAEMON -cp "$CLASSPATH" -Djna.nosys=true -pidfile "$PIDFILE" -errfile SYSLOG $CLASS RETVAL=$? then rc=0 diff --git a/plugins/database/mysql-ha/pom.xml b/plugins/database/mysql-ha/pom.xml index 5ce6d6f52b..28f136c5af 100644 --- a/plugins/database/mysql-ha/pom.xml +++ b/plugins/database/mysql-ha/pom.xml @@ -16,7 +16,7 @@ org.apache.cloudstack cloudstack-plugins 4.4.0-SNAPSHOT - ../pom.xml + ../../pom.xml diff --git a/plugins/event-bus/rabbitmq/src/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java b/plugins/event-bus/rabbitmq/src/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java index 8403271af8..a1f4c2b8b2 100644 --- a/plugins/event-bus/rabbitmq/src/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java +++ b/plugins/event-bus/rabbitmq/src/org/apache/cloudstack/mom/rabbitmq/RabbitMQEventBus.java @@ -60,6 +60,18 @@ public class RabbitMQEventBus extends ManagerBase implements EventBus { private static String username; private static String password; + public static void setVirtualHost(String virtualHost) { + RabbitMQEventBus.virtualHost = virtualHost; + } + + private static String virtualHost; + + public static void setUseSsl(String useSsl) { + RabbitMQEventBus.useSsl = useSsl; + } + + private static String useSsl; + // AMQP exchange name where all CloudStack events will be published private static String amqpExchangeName; @@ -104,6 +116,12 @@ public boolean configure(String name, Map params) throws Configu throw new ConfigurationException("Unable to get the port details of AMQP server"); } + if (useSsl != null && !useSsl.isEmpty()) { + if (!useSsl.equalsIgnoreCase("true") && !useSsl.equalsIgnoreCase("false")) { + throw new ConfigurationException("Invalid configuration parameter for 'ssl'."); + } + } + if (retryInterval == null) { retryInterval = 10000;// default to 10s to try out reconnect } @@ -345,9 +363,18 @@ private synchronized Connection createConnection() throws Exception { ConnectionFactory factory = new ConnectionFactory(); factory.setUsername(username); factory.setPassword(password); - factory.setVirtualHost("/"); factory.setHost(amqpHost); factory.setPort(port); + + if (virtualHost != null && !virtualHost.isEmpty()) { + factory.setVirtualHost(virtualHost); + } else { + factory.setVirtualHost("/"); + } + + if (useSsl != null && !useSsl.isEmpty() && useSsl.equalsIgnoreCase("true")) { + factory.useSslProtocol(); + } Connection connection = factory.newConnection(); connection.addShutdownListener(disconnectHandler); s_connection = connection; diff --git a/plugins/hypervisors/baremetal/pom.xml b/plugins/hypervisors/baremetal/pom.xml index eb2a0d1870..8f1237e480 100755 --- a/plugins/hypervisors/baremetal/pom.xml +++ b/plugins/hypervisors/baremetal/pom.xml @@ -27,11 +27,11 @@ cloud-plugin-hypervisor-baremetal Apache CloudStack Plugin - Hypervisor Baremetal - - commons-lang - commons-lang - 2.6 - + + commons-lang + commons-lang + 2.6 + diff --git a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-compute/spring-baremetal-compute-context.xml b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-compute/spring-baremetal-compute-context.xml index cce6805123..d0b52a1bb0 100644 --- a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-compute/spring-baremetal-compute-context.xml +++ b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-compute/spring-baremetal-compute-context.xml @@ -31,5 +31,5 @@ - + diff --git a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-discoverer/spring-baremetal-discoverer-context.xml b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-discoverer/spring-baremetal-discoverer-context.xml index 8792909ffe..c01d9c62af 100644 --- a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-discoverer/spring-baremetal-discoverer-context.xml +++ b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-discoverer/spring-baremetal-discoverer-context.xml @@ -30,5 +30,5 @@ - + diff --git a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-network/spring-baremetal-network-context.xml b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-network/spring-baremetal-network-context.xml index 40d9f50577..c5068e7b14 100644 --- a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-network/spring-baremetal-network-context.xml +++ b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-network/spring-baremetal-network-context.xml @@ -42,5 +42,5 @@ - + diff --git a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-planner/spring-baremetal-planner-context.xml b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-planner/spring-baremetal-planner-context.xml index 8c14c3e290..046aca67e8 100644 --- a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-planner/spring-baremetal-planner-context.xml +++ b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/baremetal-planner/spring-baremetal-planner-context.xml @@ -30,5 +30,5 @@ - + diff --git a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml index 11cc6c89e3..a77406d98d 100644 --- a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml +++ b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml @@ -38,5 +38,5 @@ - + diff --git a/plugins/hypervisors/baremetal/resources/security_group_agent/cs-sgagent b/plugins/hypervisors/baremetal/resources/security_group_agent/cs-sgagent index 02426d0aa1..f8a5d7d2c9 100755 --- a/plugins/hypervisors/baremetal/resources/security_group_agent/cs-sgagent +++ b/plugins/hypervisors/baremetal/resources/security_group_agent/cs-sgagent @@ -18,9 +18,9 @@ # 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 @@ -29,31 +29,31 @@ # under the License. check_status() { - pidfile='/var/run/cssgagent.pid' - if [ ! -f $pidfile ]; then - echo "cloudstack baremetal security group agent is stopped" - exit 1 - else - pid=`cat $pidfile` - ps -p $pid > /dev/null - if [ $? -eq 0 ]; then - echo "cloudstack baremetal security group agent is running, pid is $pid" - exit 0 - else - echo "cloudstack baremetal security group agent is stopped, but pidfile at $pidfile is not cleaned. It may be caused by the agent crashed at last time, manually cleaning it would be ok" - exit 1 - fi - fi + pidfile='/var/run/cssgagent.pid' + if [ ! -f $pidfile ]; then + echo "cloudstack baremetal security group agent is stopped" + exit 1 + else + pid=`cat $pidfile` + ps -p $pid > /dev/null + if [ $? -eq 0 ]; then + echo "cloudstack baremetal security group agent is running, pid is $pid" + exit 0 + else + echo "cloudstack baremetal security group agent is stopped, but pidfile at $pidfile is not cleaned. It may be caused by the agent crashed at last time, manually cleaning it would be ok" + exit 1 + fi + fi } if [ $# -eq 0 ]; then - echo "usage: $0 + echo "usage: $0 [start|stop|restart|status]" - exit 1 + exit 1 fi if [ "$@" = "status" ]; then - check_status + check_status else python -c "from security_group_agent import cs_sg_agent; cs_sg_agent.main()" $@ fi diff --git a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/__init__.py b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/__init__.py index f7f5f60ff0..76bd5c1b21 100644 --- a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/__init__.py +++ b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/__init__.py @@ -5,14 +5,14 @@ # 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. -# +# # Automatically generated by addcopyright.py at 01/29/2013 diff --git a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/cs_sg_agent.py b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/cs_sg_agent.py index a292c0bcfb..0c49a3f786 100755 --- a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/cs_sg_agent.py +++ b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/cs_sg_agent.py @@ -5,16 +5,16 @@ # 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. -# +# # Automatically generated by addcopyright.py at 01/29/2013 ''' Created on Jan 2, 2013 @@ -234,4 +234,3 @@ def main(): agentdaemon.restart() sys.exit(0) - \ No newline at end of file diff --git a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/sglib.py b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/sglib.py index bf64effa19..bc675b540a 100755 --- a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/sglib.py +++ b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/sglib.py @@ -6,16 +6,16 @@ # 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. -# +# # Automatically generated by addcopyright.py at 01/29/2013 import sys, os, time, atexit @@ -31,7 +31,7 @@ def __init__(self): self.body = None self.method = None self.query_string = None - + @staticmethod def from_cherrypy_request(creq): req = Request() @@ -40,10 +40,10 @@ def from_cherrypy_request(creq): req.method = copy.copy(creq.method) req.query_string = copy.copy(creq.query_string) if creq.query_string else None return req - + class ShellError(Exception): '''shell error''' - + class ShellCmd(object): ''' classdocs @@ -57,11 +57,11 @@ def __init__(self, cmd, workdir=None, pipe=True): self.process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, executable='/bin/sh', cwd=workdir) else: self.process = subprocess.Popen(cmd, shell=True, executable='/bin/sh', cwd=workdir) - + self.stdout = None self.stderr = None self.return_code = None - + def __call__(self, is_exception=True): (self.stdout, self.stderr) = self.process.communicate() if is_exception and self.process.returncode != 0: @@ -71,18 +71,18 @@ def __call__(self, is_exception=True): err.append('stdout: %s' % self.stdout) err.append('stderr: %s' % self.stderr) raise ShellError('\n'.join(err)) - + self.return_code = self.process.returncode return self.stdout class Daemon(object): """ A generic daemon class. - + Usage: subclass the Daemon class and override the run() method """ atexit_hooks = [] - + def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): self.stdin = stdin self.stdout = stdout @@ -102,37 +102,37 @@ def _atexit(): content = traceback.format_exc() err = 'Exception when calling atexit hook[%s]\n%s' % (hook.__name__, content) #logger.error(err) - + def daemonize(self): """ - do the UNIX double-fork magic, see Stevens' "Advanced + do the UNIX double-fork magic, see Stevens' "Advanced Programming in the UNIX Environment" for details (ISBN 0201563177) http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16 """ - try: - pid = os.fork() + try: + pid = os.fork() if pid > 0: # exit first parent - sys.exit(0) - except OSError, e: + sys.exit(0) + except OSError, e: sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(1) - + # decouple from parent environment - os.chdir("/") - os.setsid() - os.umask(0) - + os.chdir("/") + os.setsid() + os.umask(0) + # do second fork - try: - pid = os.fork() + try: + pid = os.fork() if pid > 0: # exit from second parent - sys.exit(0) - except OSError, e: + sys.exit(0) + except OSError, e: sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) - sys.exit(1) - + sys.exit(1) + # redirect standard file descriptors sys.stdout.flush() sys.stderr.flush() @@ -142,13 +142,13 @@ def daemonize(self): os.dup2(si.fileno(), sys.stdin.fileno()) os.dup2(so.fileno(), sys.stdout.fileno()) os.dup2(se.fileno(), sys.stderr.fileno()) - + # write pidfile Daemon.register_atexit_hook(self.delpid) atexit.register(Daemon._atexit) pid = str(os.getpid()) file(self.pidfile,'w').write("%s\n" % pid) - + def delpid(self): os.remove(self.pidfile) @@ -163,7 +163,7 @@ def start(self): pf.close() except IOError: pid = None - + if pid: pscmd = ShellCmd('ps -p %s > /dev/null' % pid) pscmd(is_exception=False) @@ -171,7 +171,7 @@ def start(self): message = "Daemon already running, pid is %s\n" sys.stderr.write(message % pid) sys.exit(0) - + # Start the daemon self.daemonize() try: @@ -192,13 +192,13 @@ def stop(self): pf.close() except IOError: pid = None - + if not pid: message = "pidfile %s does not exist. Daemon not running?\n" sys.stderr.write(message % self.pidfile) return # not an error in a restart - # Try killing the daemon process + # Try killing the daemon process try: while 1: os.kill(pid, SIGTERM) diff --git a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/xmlobject.py b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/xmlobject.py index cb66d265a5..175349958c 100755 --- a/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/xmlobject.py +++ b/plugins/hypervisors/baremetal/resources/security_group_agent/security_group_agent/xmlobject.py @@ -5,16 +5,16 @@ # 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. -# +# # Automatically generated by addcopyright.py at 01/29/2013 ''' Created on Dec 25, 2012 diff --git a/plugins/hypervisors/baremetal/resources/security_group_agent/setup.py b/plugins/hypervisors/baremetal/resources/security_group_agent/setup.py index 384e04d6a9..ed106313ff 100755 --- a/plugins/hypervisors/baremetal/resources/security_group_agent/setup.py +++ b/plugins/hypervisors/baremetal/resources/security_group_agent/setup.py @@ -5,16 +5,16 @@ # 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. -# +# # Automatically generated by addcopyright.py at 01/29/2013 from setuptools import setup, find_packages import sys, os diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalDiscoverer.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalDiscoverer.java index c312df7b79..8b4b45348f 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalDiscoverer.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BareMetalDiscoverer.java @@ -80,8 +80,8 @@ public boolean stop() { } @Override - public Map> - find(long dcId, Long podId, Long clusterId, URI url, String username, String password, List hostTags) throws DiscoveryException { + public Map> find(long dcId, Long podId, Long clusterId, URI url, String username, String password, List hostTags) + throws DiscoveryException { /* Enable this after we decide to use addBaremetalHostCmd instead of addHostCmd String discoverName = _params.get(ApiConstants.BAREMETAL_DISCOVER_NAME); @@ -130,18 +130,18 @@ public boolean stop() { String injectScript = "scripts/util/ipmi.py"; String scriptPath = Script.findScript("", injectScript); if (scriptPath == null) { - throw new CloudRuntimeException("Unable to find key ipmi script " + injectScript); + throw new CloudRuntimeException("Unable to find key ipmi script " + + injectScript); } final Script2 command = new Script2(scriptPath, s_logger); command.add("ping"); - command.add("hostname=" + ipmiIp); - command.add("usrname=" + username); - command.add("password=" + password, ParamType.PASSWORD); + command.add("hostname="+ipmiIp); + command.add("usrname="+username); + command.add("password="+password, ParamType.PASSWORD); final String result = command.execute(); if (result != null) { - s_logger.warn(String.format("Can not set up ipmi connection(ip=%1$s, username=%2$s, password=%3$s, args) because %4$s", ipmiIp, username, "******", - result)); + s_logger.warn(String.format("Can not set up ipmi connection(ip=%1$s, username=%2$s, password=%3$s, args) because %4$s", ipmiIp, username, "******", result)); return null; } @@ -155,21 +155,22 @@ public boolean stop() { params.putAll(_params); params.put("zone", Long.toString(dcId)); params.put("pod", Long.toString(podId)); - params.put("cluster", Long.toString(clusterId)); + params.put("cluster", Long.toString(clusterId)); params.put("guid", guid); params.put(ApiConstants.PRIVATE_IP, ipmiIp); params.put(ApiConstants.USERNAME, username); params.put(ApiConstants.PASSWORD, password); + params.put("vmDao", _vmDao); + params.put("configDao", _configDao); String resourceClassName = _configDao.getValue(Config.ExternalBaremetalResourceClassName.key()); BareMetalResourceBase resource = null; if (resourceClassName != null) { Class clazz = Class.forName(resourceClassName); - resource = (BareMetalResourceBase)clazz.newInstance(); + resource = (BareMetalResourceBase) clazz.newInstance(); String externalUrl = _configDao.getValue(Config.ExternalBaremetalSystemUrl.key()); if (externalUrl == null) { - throw new IllegalArgumentException( - String.format("You must specify ExternalBaremetalSystemUrl in global config page as ExternalBaremetalResourceClassName is not null")); + throw new IllegalArgumentException(String.format("You must specify ExternalBaremetalSystemUrl in global config page as ExternalBaremetalResourceClassName is not null")); } details.put(BaremetalManager.ExternalBaremetalSystemUrl, externalUrl); } else { @@ -206,8 +207,8 @@ public boolean stop() { zone.setDhcpProvider(Network.Provider.ExternalDhcpServer.getName()); _dcDao.update(zone.getId(), zone); - s_logger.debug(String.format("Discover Bare Metal host successfully(ip=%1$s, username=%2$s, password=%3%s," - + "cpuNum=%4$s, cpuCapacity-%5$s, memCapacity=%6$s)", ipmiIp, username, "******", cpuNum, cpuCapacity, memCapacity)); + s_logger.debug(String.format("Discover Bare Metal host successfully(ip=%1$s, username=%2$s, password=%3%s," + + "cpuNum=%4$s, cpuCapacity-%5$s, memCapacity=%6$s)", ipmiIp, username, "******", cpuNum, cpuCapacity, memCapacity)); return resources; } catch (Exception e) { s_logger.warn("Can not set up bare metal agent", e); @@ -217,7 +218,8 @@ public boolean stop() { } @Override - public void postDiscovery(List hosts, long msId) throws DiscoveryException { + public void postDiscovery(List hosts, long msId) + throws DiscoveryException { } @Override @@ -273,6 +275,8 @@ protected HashMap buildConfigParams(HostVO host) { HashMap params = super.buildConfigParams(host); params.put("hostId", host.getId()); params.put("ipaddress", host.getPrivateIpAddress()); + params.put("vmDao", _vmDao); + params.put("configDao", _configDao); return params; } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java index b729d9bb3e..828533708e 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java @@ -22,18 +22,6 @@ // Automatically generated by addcopyright.py at 04/03/2012 package com.cloud.baremetal.networkservice; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import javax.ejb.Local; -import javax.naming.ConfigurationException; - -import org.apache.log4j.Logger; - -import org.apache.cloudstack.api.ApiConstants; - import com.cloud.agent.IAgentControl; import com.cloud.agent.api.Answer; import com.cloud.agent.api.CheckNetworkAnswer; @@ -48,6 +36,7 @@ import com.cloud.agent.api.MigrateCommand; import com.cloud.agent.api.PingCommand; import com.cloud.agent.api.PingRoutingCommand; +import com.cloud.agent.api.PingRoutingWithNwGroupsCommand; import com.cloud.agent.api.PrepareForMigrationAnswer; import com.cloud.agent.api.PrepareForMigrationCommand; import com.cloud.agent.api.ReadyAnswer; @@ -66,10 +55,11 @@ import com.cloud.agent.api.baremetal.IpmiBootorResetCommand; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.baremetal.manager.BaremetalManager; +import com.cloud.configuration.Config; import com.cloud.host.Host.Type; import com.cloud.hypervisor.Hypervisor; import com.cloud.resource.ServerResource; -import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.Pair; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.OutputInterpreter; @@ -81,6 +71,16 @@ import com.cloud.vm.VirtualMachine.PowerState; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.dao.VMInstanceDao; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.log4j.Logger; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; @Local(value = ServerResource.class) public class BareMetalResourceBase extends ManagerBase implements ServerResource { @@ -111,6 +111,9 @@ public class BareMetalResourceBase extends ManagerBase implements ServerResource protected Script2 _forcePowerOffCommand; protected Script2 _bootOrRebootCommand; protected String _vmName; + protected int ipmiRetryTimes = 5; + + protected ConfigurationDao configDao; protected VMInstanceDao vmDao; private void changeVmState(String vmName, VirtualMachine.State state) { @@ -128,27 +131,29 @@ private State removeVmState(String vmName) { @Override public boolean configure(String name, Map params) throws ConfigurationException { _name = name; - _uuid = (String)params.get("guid"); + _uuid = (String) params.get("guid"); try { - _memCapacity = Long.parseLong((String)params.get(ApiConstants.MEMORY)) * 1024L * 1024L; - _cpuCapacity = Long.parseLong((String)params.get(ApiConstants.CPU_SPEED)); - _cpuNum = Long.parseLong((String)params.get(ApiConstants.CPU_NUMBER)); + _memCapacity = Long.parseLong((String) params.get(ApiConstants.MEMORY)) * 1024L * 1024L; + _cpuCapacity = Long.parseLong((String) params.get(ApiConstants.CPU_SPEED)); + _cpuNum = Long.parseLong((String) params.get(ApiConstants.CPU_NUMBER)); } catch (NumberFormatException e) { throw new ConfigurationException(String.format("Unable to parse number of CPU or memory capacity " - + "or cpu capacity(cpu number = %1$s memCapacity=%2$s, cpuCapacity=%3$s", params.get(ApiConstants.CPU_NUMBER), params.get(ApiConstants.MEMORY), - params.get(ApiConstants.CPU_SPEED))); + + "or cpu capacity(cpu number = %1$s memCapacity=%2$s, cpuCapacity=%3$s", params.get(ApiConstants.CPU_NUMBER), + params.get(ApiConstants.MEMORY), params.get(ApiConstants.CPU_SPEED))); } - _zone = (String)params.get("zone"); - _pod = (String)params.get("pod"); - _cluster = (String)params.get("cluster"); - hostId = (Long)params.get("hostId"); - _ip = (String)params.get(ApiConstants.PRIVATE_IP); - _mac = (String)params.get(ApiConstants.HOST_MAC); - _username = (String)params.get(ApiConstants.USERNAME); - _password = (String)params.get(ApiConstants.PASSWORD); - _vmName = (String)params.get("vmName"); - String echoScAgent = (String)params.get(BaremetalManager.EchoSecurityGroupAgent); + _zone = (String) params.get("zone"); + _pod = (String) params.get("pod"); + _cluster = (String) params.get("cluster"); + hostId = (Long) params.get("hostId"); + _ip = (String) params.get(ApiConstants.PRIVATE_IP); + _mac = (String) params.get(ApiConstants.HOST_MAC); + _username = (String) params.get(ApiConstants.USERNAME); + _password = (String) params.get(ApiConstants.PASSWORD); + _vmName = (String) params.get("vmName"); + String echoScAgent = (String) params.get(BaremetalManager.EchoSecurityGroupAgent); + vmDao = (VMInstanceDao) params.get("vmDao"); + configDao = (ConfigurationDao) params.get("configDao"); if (_pod == null) { throw new ConfigurationException("Unable to get the pod"); @@ -167,7 +172,8 @@ public boolean configure(String name, Map params) throws Configu } if (_mac.split(":").length != 6) { - throw new ConfigurationException("Wrong MAC format(" + _mac + "). It must be in format of for example 00:11:ba:33:aa:dd which is not case sensitive"); + throw new ConfigurationException("Wrong MAC format(" + _mac + + "). It must be in format of for example 00:11:ba:33:aa:dd which is not case sensitive"); } if (_uuid == null) { @@ -178,6 +184,19 @@ public boolean configure(String name, Map params) throws Configu _isEchoScAgent = Boolean.valueOf(echoScAgent); } + String ipmiIface = "default"; + try { + ipmiIface = configDao.getValue(Config.BaremetalIpmiLanInterface.key()); + } catch (Exception e) { + s_logger.debug(e.getMessage(), e); + } + + try { + ipmiRetryTimes = Integer.valueOf(configDao.getValue(Config.BaremetalIpmiRetryTimes.key())); + } catch (Exception e) { + s_logger.debug(e.getMessage(), e); + } + String injectScript = "scripts/util/ipmi.py"; String scriptPath = Script.findScript("", injectScript); if (scriptPath == null) { @@ -187,6 +206,7 @@ public boolean configure(String name, Map params) throws Configu _pingCommand = new Script2(pythonPath, s_logger); _pingCommand.add(scriptPath); _pingCommand.add("ping"); + _pingCommand.add("interface=" + ipmiIface); _pingCommand.add("hostname=" + _ip); _pingCommand.add("usrname=" + _username); _pingCommand.add("password=" + _password, ParamType.PASSWORD); @@ -194,6 +214,7 @@ public boolean configure(String name, Map params) throws Configu _setPxeBootCommand = new Script2(pythonPath, s_logger); _setPxeBootCommand.add(scriptPath); _setPxeBootCommand.add("boot_dev"); + _setPxeBootCommand.add("interface=" + ipmiIface); _setPxeBootCommand.add("hostname=" + _ip); _setPxeBootCommand.add("usrname=" + _username); _setPxeBootCommand.add("password=" + _password, ParamType.PASSWORD); @@ -202,6 +223,7 @@ public boolean configure(String name, Map params) throws Configu _setDiskBootCommand = new Script2(pythonPath, s_logger); _setDiskBootCommand.add(scriptPath); _setDiskBootCommand.add("boot_dev"); + _setDiskBootCommand.add("interface=" + ipmiIface); _setDiskBootCommand.add("hostname=" + _ip); _setDiskBootCommand.add("usrname=" + _username); _setDiskBootCommand.add("password=" + _password, ParamType.PASSWORD); @@ -210,6 +232,7 @@ public boolean configure(String name, Map params) throws Configu _rebootCommand = new Script2(pythonPath, s_logger); _rebootCommand.add(scriptPath); _rebootCommand.add("reboot"); + _rebootCommand.add("interface=" + ipmiIface); _rebootCommand.add("hostname=" + _ip); _rebootCommand.add("usrname=" + _username); _rebootCommand.add("password=" + _password, ParamType.PASSWORD); @@ -217,6 +240,7 @@ public boolean configure(String name, Map params) throws Configu _getStatusCommand = new Script2(pythonPath, s_logger); _getStatusCommand.add(scriptPath); _getStatusCommand.add("ping"); + _getStatusCommand.add("interface=" + ipmiIface); _getStatusCommand.add("hostname=" + _ip); _getStatusCommand.add("usrname=" + _username); _getStatusCommand.add("password=" + _password, ParamType.PASSWORD); @@ -224,6 +248,7 @@ public boolean configure(String name, Map params) throws Configu _powerOnCommand = new Script2(pythonPath, s_logger); _powerOnCommand.add(scriptPath); _powerOnCommand.add("power"); + _powerOnCommand.add("interface=" + ipmiIface); _powerOnCommand.add("hostname=" + _ip); _powerOnCommand.add("usrname=" + _username); _powerOnCommand.add("password=" + _password, ParamType.PASSWORD); @@ -232,6 +257,7 @@ public boolean configure(String name, Map params) throws Configu _powerOffCommand = new Script2(pythonPath, s_logger); _powerOffCommand.add(scriptPath); _powerOffCommand.add("power"); + _powerOffCommand.add("interface=" + ipmiIface); _powerOffCommand.add("hostname=" + _ip); _powerOffCommand.add("usrname=" + _username); _powerOffCommand.add("password=" + _password, ParamType.PASSWORD); @@ -240,6 +266,7 @@ public boolean configure(String name, Map params) throws Configu _forcePowerOffCommand = new Script2(pythonPath, s_logger); _forcePowerOffCommand.add(scriptPath); _forcePowerOffCommand.add("power"); + _forcePowerOffCommand.add("interface=" + ipmiIface); _forcePowerOffCommand.add("hostname=" + _ip); _forcePowerOffCommand.add("usrname=" + _username); _forcePowerOffCommand.add("password=" + _password, ParamType.PASSWORD); @@ -248,6 +275,7 @@ public boolean configure(String name, Map params) throws Configu _bootOrRebootCommand = new Script2(pythonPath, s_logger); _bootOrRebootCommand.add(scriptPath); _bootOrRebootCommand.add("boot_or_reboot"); + _bootOrRebootCommand.add("interface=" + ipmiIface); _bootOrRebootCommand.add("hostname=" + _ip); _bootOrRebootCommand.add("usrname=" + _username); _bootOrRebootCommand.add("password=" + _password, ParamType.PASSWORD); @@ -259,8 +287,15 @@ protected boolean doScript(Script cmd) { return doScript(cmd, null); } + protected boolean doScript(Script cmd, int retry) { + return doScript(cmd, null, retry); + } + protected boolean doScript(Script cmd, OutputInterpreter interpreter) { - int retry = 5; + return doScript(cmd, interpreter, ipmiRetryTimes); + } + + protected boolean doScript(Script cmd, OutputInterpreter interpreter, int retry) { String res = null; while (retry-- > 0) { if (interpreter == null) { @@ -270,6 +305,10 @@ protected boolean doScript(Script cmd, OutputInterpreter interpreter) { } if (res != null && res.startsWith("Error: Unable to establish LAN")) { s_logger.warn("IPMI script timeout(" + cmd.toString() + "), will retry " + retry + " times"); + try { + TimeUnit.SECONDS.sleep(1); + } catch (InterruptedException e) { + } continue; } else if (res == null) { return true; @@ -318,7 +357,6 @@ protected State getVmState() { protected Map fullSync() { Map states = new HashMap(); if (hostId != null) { - vmDao = ComponentContext.getComponent(VMInstanceDao.class); final List vms = vmDao.listByHostId(hostId); for (VMInstanceVO vm : vms) { states.put(vm.getInstanceName(), vm.getState()); @@ -337,10 +375,14 @@ protected Map fullSync() { protected Map getHostVmStateReport() { Map states = new HashMap(); if (hostId != null) { - vmDao = ComponentContext.getComponent(VMInstanceDao.class); final List vms = vmDao.listByHostId(hostId); for (VMInstanceVO vm : vms) { - states.put(vm.getInstanceName(), new HostVmStateReportEntry(vm.getState() == State.Running ? PowerState.PowerOn : PowerState.PowerOff, "host-" + hostId)); + states.put( + vm.getInstanceName(), + new HostVmStateReportEntry( + vm.getState() == State.Running ? PowerState.PowerOn : PowerState.PowerOff, "host-" + hostId + ) + ); } } /* @@ -355,7 +397,8 @@ protected Map getHostVmStateReport() { @Override public StartupCommand[] initialize() { - StartupRoutingCommand cmd = new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.BareMetal, new HashMap(), null, null); + StartupRoutingCommand cmd = new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.BareMetal, + new HashMap(), null, null); cmd.setDataCenter(_zone); cmd.setPod(_pod); @@ -365,13 +408,13 @@ public StartupCommand[] initialize() { cmd.setPrivateIpAddress(_ip); cmd.setStorageIpAddress(_ip); cmd.setVersion(BareMetalResourceBase.class.getPackage().getImplementationVersion()); - cmd.setCpus((int)_cpuNum); + cmd.setCpus((int) _cpuNum); cmd.setSpeed(_cpuCapacity); cmd.setMemory(_memCapacity); cmd.setPrivateMacAddress(_mac); cmd.setPublicMacAddress(_mac); cmd.setStateChanges(fullSync()); - return new StartupCommand[] {cmd}; + return new StartupCommand[] { cmd }; } private boolean ipmiPing() { @@ -393,7 +436,19 @@ public PingCommand getCurrentStatus(long id) { return null; } - return new PingRoutingCommand(getType(), id, deltaSync(), getHostVmStateReport()); + if (hostId != null) { + final List vms = vmDao.listByHostId(hostId); + if (vms.isEmpty()) { + return new PingRoutingCommand(getType(), id, deltaSync(), getHostVmStateReport()); + } else { + VMInstanceVO vm = vms.get(0); + SecurityGroupHttpClient client = new SecurityGroupHttpClient(); + HashMap> nwGrpStates = client.sync(vm.getInstanceName(), vm.getId(), vm.getPrivateIpAddress()); + return new PingRoutingWithNwGroupsCommand(getType(), id, null, getHostVmStateReport(), nwGrpStates); + } + } else { + return new PingRoutingCommand(getType(), id, deltaSync(), getHostVmStateReport()); + } } protected Answer execute(IpmISetBootDevCommand cmd) { @@ -456,29 +511,29 @@ protected Answer execute(SecurityGroupRulesCmd cmd) { public Answer executeRequest(Command cmd) { try { if (cmd instanceof ReadyCommand) { - return execute((ReadyCommand)cmd); + return execute((ReadyCommand) cmd); } else if (cmd instanceof StartCommand) { - return execute((StartCommand)cmd); + return execute((StartCommand) cmd); } else if (cmd instanceof StopCommand) { - return execute((StopCommand)cmd); + return execute((StopCommand) cmd); } else if (cmd instanceof RebootCommand) { - return execute((RebootCommand)cmd); + return execute((RebootCommand) cmd); } else if (cmd instanceof IpmISetBootDevCommand) { - return execute((IpmISetBootDevCommand)cmd); + return execute((IpmISetBootDevCommand) cmd); } else if (cmd instanceof MaintainCommand) { - return execute((MaintainCommand)cmd); + return execute((MaintainCommand) cmd); } else if (cmd instanceof PrepareForMigrationCommand) { - return execute((PrepareForMigrationCommand)cmd); + return execute((PrepareForMigrationCommand) cmd); } else if (cmd instanceof MigrateCommand) { - return execute((MigrateCommand)cmd); + return execute((MigrateCommand) cmd); } else if (cmd instanceof CheckVirtualMachineCommand) { - return execute((CheckVirtualMachineCommand)cmd); + return execute((CheckVirtualMachineCommand) cmd); } else if (cmd instanceof IpmiBootorResetCommand) { - return execute((IpmiBootorResetCommand)cmd); + return execute((IpmiBootorResetCommand) cmd); } else if (cmd instanceof SecurityGroupRulesCmd) { - return execute((SecurityGroupRulesCmd)cmd); + return execute((SecurityGroupRulesCmd) cmd); } else if (cmd instanceof CheckNetworkCommand) { - return execute((CheckNetworkCommand)cmd); + return execute((CheckNetworkCommand) cmd); } else { return Answer.createUnsupportedCommandAnswer(cmd); } @@ -499,8 +554,17 @@ protected boolean isPowerOn(String str) { } protected RebootAnswer execute(final RebootCommand cmd) { - if (!doScript(_rebootCommand)) { - return new RebootAnswer(cmd, "IPMI reboot failed", false); + String infoStr = "Command not supported in present state"; + OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser(); + if (!doScript(_rebootCommand, interpreter, 10)) { + if (interpreter.getLines().contains(infoStr)) { + // try again, this error should be temporary + if (!doScript(_rebootCommand, interpreter, 10)) { + return new RebootAnswer(cmd, "IPMI reboot failed", false); + } + } else { + return new RebootAnswer(cmd, "IPMI reboot failed", false); + } } return new RebootAnswer(cmd, "reboot succeeded", true); @@ -524,7 +588,8 @@ protected StopAnswer execute(final StopCommand cmd) { OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser(); if (!doScript(_getStatusCommand, interpreter)) { - s_logger.warn("Cannot get power status of " + _name + ", assume VM state was not changed"); + success = true; + s_logger.warn("Cannot get power status of " + _name + ", assume VM state changed successfully"); break; } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java index ca2f8fe703..261534a3dd 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java @@ -193,7 +193,7 @@ public List listPxeServers(ListBaremetalPxeServersCmd cmd) @Override public boolean addUserData(NicProfile nic, VirtualMachineProfile profile) { - UserVmVO vm = (UserVmVO)profile.getVirtualMachine(); + UserVmVO vm = _vmDao.findById(profile.getVirtualMachine().getId()); _vmDao.loadDetails(vm); String serviceOffering = _serviceOfferingDao.findByIdIncludingRemoved(vm.getId(), vm.getServiceOfferingId()).getDisplayText(); diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/SecurityGroupHttpClient.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/SecurityGroupHttpClient.java index a3998a3bc7..b9e4858895 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/SecurityGroupHttpClient.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/SecurityGroupHttpClient.java @@ -1,38 +1,205 @@ -// 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. -// -// Automatically generated by addcopyright.py at 01/29/2013 -// Apache License, Version 2.0 (the "License"); you may not use this -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -package com.cloud.baremetal.networkservice; - -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.SecurityGroupRulesCmd; - -public class SecurityGroupHttpClient { - - public Answer call(String guestIp, SecurityGroupRulesCmd cmd) { - // TODO Auto-generated method stub - return null; - } - - public boolean echo(String ip, long millis, long millis2) { - // TODO Auto-generated method stub - return false; - } - -} +// 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. +// +// Automatically generated by addcopyright.py at 01/29/2013 +// Apache License, Version 2.0 (the "License"); you may not use this +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// Automatically generated by addcopyright.py at 04/03/2012 + +package com.cloud.baremetal.networkservice; + +import com.cloud.agent.api.SecurityGroupRuleAnswer; +import com.cloud.agent.api.SecurityGroupRulesCmd; +import com.cloud.agent.api.SecurityGroupRulesCmd.IpPortAndProto; +import com.cloud.baremetal.networkservice.schema.SecurityGroupRule; +import com.cloud.baremetal.networkservice.schema.SecurityGroupVmRuleSet; +import com.cloud.utils.Pair; +import com.cloud.utils.exception.CloudRuntimeException; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.StringRequestEntity; +import org.apache.log4j.Logger; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import java.io.StringWriter; +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class SecurityGroupHttpClient { + private static final Logger logger = Logger.getLogger(SecurityGroupHttpClient.class); + private static final String ARG_NAME = "args"; + private static final String COMMAND = "command"; + private JAXBContext context; + private int port; + private static HttpClient httpClient; + static { + MultiThreadedHttpConnectionManager connman = new MultiThreadedHttpConnectionManager(); + httpClient = new HttpClient(connman); + httpClient.setConnectionTimeout(5000); + } + + private enum OpConstant { + setRules, echo, + } + + public SecurityGroupHttpClient() { + try { + context = JAXBContext.newInstance(SecurityGroupRule.class, SecurityGroupVmRuleSet.class); + port = 9988; + } catch (Exception e) { + throw new CloudRuntimeException( + "Unable to create JAXBContext for security group", e); + } + } + + private List generateRules(IpPortAndProto[] ipps) { + List rules = new ArrayList( + ipps.length); + for (SecurityGroupRulesCmd.IpPortAndProto ipp : ipps) { + SecurityGroupRule r = new SecurityGroupRule(); + r.setProtocol(ipp.getProto()); + r.setStartPort(ipp.getStartPort()); + r.setEndPort(ipp.getEndPort()); + for (String cidr : ipp.getAllowedCidrs()) { + r.getIp().add(cidr); + } + rules.add(r); + } + return rules; + } + + public HashMap> sync(String vmName, Long vmId, String agentIp) { + HashMap> states = new HashMap>(); + PostMethod post = new PostMethod(String.format("http://%s:%s/", agentIp, getPort())); + try { + post.addRequestHeader("command", "sync"); + if (httpClient.executeMethod(post) != 200) { + logger.debug(String.format("echoing baremetal security group agent on %s got error: %s", agentIp, post.getResponseBodyAsString())); + } else { + String res = post.getResponseBodyAsString(); + // res = ';'.join([vmName, vmId, seqno]) + String[] rulelogs = res.split(","); + if (rulelogs.length != 6) { + logger.debug(String.format("host[%s] returns invalid security group sync document[%s], reset rules", agentIp, res)); + states.put(vmName, new Pair(vmId, -1L)); + return states; + } + Pair p = new Pair(Long.valueOf(rulelogs[1]), Long.valueOf(rulelogs[5])); + states.put(rulelogs[0], p); + return states; + } + } catch (SocketTimeoutException se) { + logger.warn(String.format("unable to sync security group rules on host[%s], %s", agentIp, se.getMessage())); + } catch (Exception e) { + logger.warn(String.format("unable to sync security group rules on host[%s]", agentIp), e); + } finally { + if (post != null) { + post.releaseConnection(); + } + } + return states; + } + + + public boolean echo(String agentIp, long l, long m) { + boolean ret = false; + int count = 1; + while (true) { + try { + Thread.sleep(m); + count++; + } catch (InterruptedException e1) { + logger.warn("", e1); + break; + } + PostMethod post = new PostMethod(String.format("http://%s:%s/", agentIp, getPort())); + try { + post.addRequestHeader("command", "echo"); + if (httpClient.executeMethod(post) != 200) { + logger.debug(String.format("echoing baremetal security group agent on %s got error: %s", agentIp, post.getResponseBodyAsString())); + } else { + ret = true; + } + break; + } catch (Exception e) { + if (count*m >= l) { + logger.debug(String.format("ping security group agent on vm[%s] timeout after %s minutes, starting vm failed, count=%s", agentIp, TimeUnit.MILLISECONDS.toSeconds(l), count)); + break; + } else { + logger.debug(String.format("Having pinged security group agent on vm[%s] %s times, continue to wait...", agentIp, count)); + } + } finally { + if (post != null) { + post.releaseConnection(); + } + } + } + return ret; + } + + public SecurityGroupRuleAnswer call(String agentIp, SecurityGroupRulesCmd cmd) { + PostMethod post = new PostMethod(String.format( + "http://%s:%s", agentIp, getPort())); + try { + SecurityGroupVmRuleSet rset = new SecurityGroupVmRuleSet(); + rset.getEgressRules().addAll(generateRules(cmd.getEgressRuleSet())); + rset.getIngressRules().addAll( + generateRules(cmd.getIngressRuleSet())); + rset.setVmName(cmd.getVmName()); + rset.setVmIp(cmd.getGuestIp()); + rset.setVmMac(cmd.getGuestMac()); + rset.setVmId(cmd.getVmId()); + rset.setSignature(cmd.getSignature()); + rset.setSequenceNumber(cmd.getSeqNum()); + Marshaller marshaller = context.createMarshaller(); + StringWriter writer = new StringWriter(); + marshaller.marshal(rset, writer); + String xmlContents = writer.toString(); + logger.debug(xmlContents); + + post.addRequestHeader("command", "set_rules"); + StringRequestEntity entity = new StringRequestEntity(xmlContents); + post.setRequestEntity(entity); + if (httpClient.executeMethod(post) != 200) { + return new SecurityGroupRuleAnswer(cmd, false, + post.getResponseBodyAsString()); + } else { + return new SecurityGroupRuleAnswer(cmd); + } + } catch (Exception e) { + return new SecurityGroupRuleAnswer(cmd, false, e.getMessage()); + } finally { + if (post != null) { + post.releaseConnection(); + } + } + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } +} diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/ObjectFactory.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/ObjectFactory.java new file mode 100644 index 0000000000..b5bc694516 --- /dev/null +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/ObjectFactory.java @@ -0,0 +1,55 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2012.07.11 at 03:24:15 PM PDT +// + + +package com.cloud.baremetal.networkservice.schema; + +import javax.xml.bind.annotation.XmlRegistry; + + +/** + * This object contains factory methods for each + * Java content interface and Java element interface + * generated in the com.cloud.network.security.schema package. + *

An ObjectFactory allows you to programatically + * construct new instances of the Java representation + * for XML content. The Java representation of XML + * content can consist of schema derived interfaces + * and classes representing the binding of schema + * type definitions, element declarations and model + * groups. Factory methods for each of these are + * provided in this class. + * + */ +@XmlRegistry +public class ObjectFactory { + + + /** + * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.cloud.network.security.schema + * + */ + public ObjectFactory() { + } + + /** + * Create an instance of {@link SecurityGroupRule } + * + */ + public SecurityGroupRule createSecurityGroupRule() { + return new SecurityGroupRule(); + } + + /** + * Create an instance of {@link SecurityGroupVmRuleSet } + * + */ + public SecurityGroupVmRuleSet createSecurityGroupVmRuleSet() { + return new SecurityGroupVmRuleSet(); + } + +} diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/SecurityGroupRule.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/SecurityGroupRule.java new file mode 100644 index 0000000000..050c3fdee7 --- /dev/null +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/SecurityGroupRule.java @@ -0,0 +1,146 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2012.07.11 at 03:24:15 PM PDT +// + + +package com.cloud.baremetal.networkservice.schema; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for SecurityGroupRule complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="SecurityGroupRule">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="protocol" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="startPort" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <element name="endPort" type="{http://www.w3.org/2001/XMLSchema}unsignedInt"/>
+ *         <sequence maxOccurs="unbounded" minOccurs="0">
+ *           <element name="ip" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         </sequence>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "SecurityGroupRule", propOrder = { + "protocol", + "startPort", + "endPort", + "ip" +}) +public class SecurityGroupRule { + + @XmlElement(required = true) + protected String protocol; + @XmlSchemaType(name = "unsignedInt") + protected long startPort; + @XmlSchemaType(name = "unsignedInt") + protected long endPort; + protected List ip; + + /** + * Gets the value of the protocol property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getProtocol() { + return protocol; + } + + /** + * Sets the value of the protocol property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setProtocol(String value) { + this.protocol = value; + } + + /** + * Gets the value of the startPort property. + * + */ + public long getStartPort() { + return startPort; + } + + /** + * Sets the value of the startPort property. + * + */ + public void setStartPort(long value) { + this.startPort = value; + } + + /** + * Gets the value of the endPort property. + * + */ + public long getEndPort() { + return endPort; + } + + /** + * Sets the value of the endPort property. + * + */ + public void setEndPort(long value) { + this.endPort = value; + } + + /** + * Gets the value of the ip property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the ip property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getIp().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link String } + * + * + */ + public List getIp() { + if (ip == null) { + ip = new ArrayList(); + } + return this.ip; + } + +} diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/SecurityGroupVmRuleSet.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/SecurityGroupVmRuleSet.java new file mode 100644 index 0000000000..2c50c0e24d --- /dev/null +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/schema/SecurityGroupVmRuleSet.java @@ -0,0 +1,263 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2012.07.11 at 03:24:15 PM PDT +// + + +package com.cloud.baremetal.networkservice.schema; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType>
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="vmName" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="vmId" type="{http://www.w3.org/2001/XMLSchema}long"/>
+ *         <element name="vmIp" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="vmMac" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="signature" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *         <element name="sequenceNumber" type="{http://www.w3.org/2001/XMLSchema}long"/>
+ *         <sequence maxOccurs="unbounded" minOccurs="0">
+ *           <element name="ingressRules" type="{}SecurityGroupRule"/>
+ *         </sequence>
+ *         <sequence maxOccurs="unbounded" minOccurs="0">
+ *           <element name="egressRules" type="{}SecurityGroupRule"/>
+ *         </sequence>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "vmName", + "vmId", + "vmIp", + "vmMac", + "signature", + "sequenceNumber", + "ingressRules", + "egressRules" +}) +@XmlRootElement(name = "SecurityGroupVmRuleSet") +public class SecurityGroupVmRuleSet { + + @XmlElement(required = true) + protected String vmName; + protected long vmId; + @XmlElement(required = true) + protected String vmIp; + @XmlElement(required = true) + protected String vmMac; + @XmlElement(required = true) + protected String signature; + protected long sequenceNumber; + protected List ingressRules; + protected List egressRules; + + /** + * Gets the value of the vmName property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getVmName() { + return vmName; + } + + /** + * Sets the value of the vmName property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setVmName(String value) { + this.vmName = value; + } + + /** + * Gets the value of the vmId property. + * + */ + public long getVmId() { + return vmId; + } + + /** + * Sets the value of the vmId property. + * + */ + public void setVmId(long value) { + this.vmId = value; + } + + /** + * Gets the value of the vmIp property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getVmIp() { + return vmIp; + } + + /** + * Sets the value of the vmIp property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setVmIp(String value) { + this.vmIp = value; + } + + /** + * Gets the value of the vmMac property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getVmMac() { + return vmMac; + } + + /** + * Sets the value of the vmMac property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setVmMac(String value) { + this.vmMac = value; + } + + /** + * Gets the value of the signature property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getSignature() { + return signature; + } + + /** + * Sets the value of the signature property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setSignature(String value) { + this.signature = value; + } + + /** + * Gets the value of the sequenceNumber property. + * + */ + public long getSequenceNumber() { + return sequenceNumber; + } + + /** + * Sets the value of the sequenceNumber property. + * + */ + public void setSequenceNumber(long value) { + this.sequenceNumber = value; + } + + /** + * Gets the value of the ingressRules property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the ingressRules property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getIngressRules().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link SecurityGroupRule } + * + * + */ + public List getIngressRules() { + if (ingressRules == null) { + ingressRules = new ArrayList(); + } + return this.ingressRules; + } + + /** + * Gets the value of the egressRules property. + * + *

+ * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a set method for the egressRules property. + * + *

+ * For example, to add a new item, do as follows: + *

+     *    getEgressRules().add(newItem);
+     * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list + * {@link SecurityGroupRule } + * + * + */ + public List getEgressRules() { + if (egressRules == null) { + egressRules = new ArrayList(); + } + return this.egressRules; + } + +} diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.Config b/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.Config index 5181cb8103..3bdbf2e7f0 100644 --- a/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.Config +++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/.nuget/NuGet.Config @@ -1,13 +1,4 @@ - - + diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.settings b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.settings index fb5b962fca..695ebe2ce9 100644 --- a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.settings +++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentSettings.settings @@ -1,23 +1,4 @@ - - - + diff --git a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentShell.csproj b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentShell.csproj index a4c6b1fc07..f804ef6f67 100644 --- a/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentShell.csproj +++ b/plugins/hypervisors/hyperv/DotNet/ServerResource/AgentShell/AgentShell.csproj @@ -137,6 +137,10 @@ + + + + + + 4.0.0 + cloud-plugin-storage-volume-cloudbyte + Apache CloudStack Plugin - Storage Volume CloudByte Provider + + org.apache.cloudstack + cloudstack-plugins + 4.4.0-SNAPSHOT + ../../../pom.xml + + + + org.apache.cloudstack + cloud-plugin-storage-volume-default + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-volume + ${project.version} + + + mysql + mysql-connector-java + ${cs.mysql.version} + provided + + + com.google.code.gson + gson + ${cs.gson.version} + + + com.sun.jersey + jersey-bundle + 1.17.1 + + + + install + src + test + + + maven-surefire-plugin + + true + + + + integration-test + + test + + + + + + + diff --git a/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/module.properties b/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/module.properties new file mode 100755 index 0000000000..730e376c92 --- /dev/null +++ b/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/module.properties @@ -0,0 +1,18 @@ +# 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. +name=storage-volume-cloudbyte +parent=storage \ No newline at end of file diff --git a/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/spring-storage-volume-cloudbyte-context.xml b/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/spring-storage-volume-cloudbyte-context.xml new file mode 100755 index 0000000000..87c5f51393 --- /dev/null +++ b/plugins/storage/volume/cloudbyte/resources/META-INF/cloudstack/storage-volume-cloudbyte/spring-storage-volume-cloudbyte-context.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/driver/ElastistorPrimaryDataStoreDriver.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/driver/ElastistorPrimaryDataStoreDriver.java new file mode 100755 index 0000000000..99d1e2aaa4 --- /dev/null +++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/driver/ElastistorPrimaryDataStoreDriver.java @@ -0,0 +1,97 @@ +/* + * 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.datastore.driver; + + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; +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.PrimaryDataStoreDriver; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.storage.command.CommandResult; +import org.apache.log4j.Logger; + +import com.cloud.agent.api.to.DataStoreTO; +import com.cloud.agent.api.to.DataTO; +import com.cloud.storage.dao.DiskOfferingDao; +import com.cloud.user.AccountManager; + +public class ElastistorPrimaryDataStoreDriver extends CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver{ + + private static final Logger s_logger = Logger.getLogger(ElastistorPrimaryDataStoreDriver.class); + + @Inject + AccountManager _accountMgr; + @Inject + DiskOfferingDao _diskOfferingDao; + @Override + public DataTO getTO(DataObject data) { + return null; + } + + @Override + public DataStoreTO getStoreTO(DataStore store) { + return null; + } + + public void createAsync(DataStore dataStore, DataObject dataObject, AsyncCompletionCallback callback) { + super.createAsync(dataStore, dataObject, callback); + } + + public void deleteAsync(DataStore dataStore, DataObject dataObject, AsyncCompletionCallback callback) { + super.deleteAsync(dataStore, dataObject, callback); + } + + @Override + public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback callback) { + throw new UnsupportedOperationException(); + + } + + @Override + public boolean canCopy(DataObject srcData, DataObject destData) { + return false; + } + + @Override + public void resize(DataObject data, AsyncCompletionCallback callback) { + throw new UnsupportedOperationException(); + } + + public ChapInfo getChapInfo(VolumeInfo volumeInfo) { + return super.getChapInfo(volumeInfo); + } + + @Override + public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) { + throw new UnsupportedOperationException(); + } + + @Override + public void revertSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) { + throw new UnsupportedOperationException(); + } + +} diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java new file mode 100755 index 0000000000..aa33b2f1d1 --- /dev/null +++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/lifecycle/ElastistorPrimaryDataStoreLifeCycle.java @@ -0,0 +1,497 @@ +/* + * 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.datastore.lifecycle; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.HostScope; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreParameters; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import org.apache.cloudstack.storage.datastore.util.ElastistorUtil; +import org.apache.cloudstack.storage.datastore.util.ElastistorUtil.CreateTsmCmdResponse; +import org.apache.cloudstack.storage.datastore.util.ElastistorUtil.CreateVolumeCmdResponse; +import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper; +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CreateStoragePoolCommand; +import com.cloud.agent.api.DeleteStoragePoolCommand; +import com.cloud.agent.api.StoragePoolInfo; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.ResourceManager; +import com.cloud.storage.Storage.StoragePoolType; +import com.cloud.storage.StorageManager; +import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolAutomation; +import com.cloud.storage.StoragePoolHostVO; +import com.cloud.storage.dao.StoragePoolHostDao; +import com.cloud.utils.exception.CloudRuntimeException; + +public class ElastistorPrimaryDataStoreLifeCycle implements PrimaryDataStoreLifeCycle { + private static final Logger s_logger = Logger.getLogger(ElastistorPrimaryDataStoreLifeCycle.class); + + @Inject + HostDao _hostDao; + @Inject + StoragePoolHostDao _storagePoolHostDao; + @Inject + protected ResourceManager _resourceMgr; + @Inject + PrimaryDataStoreDao primaryDataStoreDao; + @Inject + AgentManager agentMgr; + @Inject + StorageManager storageMgr; + @Inject + PrimaryDataStoreHelper dataStoreHelper; + @Inject + PrimaryDataStoreDao _storagePoolDao; + @Inject + PrimaryDataStoreHelper _dataStoreHelper; + @Inject + StoragePoolAutomation _storagePoolAutomation; + @Inject + StoragePoolDetailsDao _storagePoolDetailsDao; + @Inject + DataCenterDao _zoneDao; + + @Override + public DataStore initialize(Map dsInfos) { + + String url = (String) dsInfos.get("url"); + Long zoneId = (Long) dsInfos.get("zoneId"); + Long podId = (Long) dsInfos.get("podId"); + Long clusterId = (Long) dsInfos.get("clusterId"); + String storagePoolName = (String) dsInfos.get("name"); + String providerName = (String) dsInfos.get("providerName"); + Long capacityBytes = (Long) dsInfos.get("capacityBytes"); + Long capacityIops = (Long) dsInfos.get("capacityIops"); + String tags = (String) dsInfos.get("tags"); + Map details = (Map) dsInfos.get("details"); + String storageIp = getStorageIp(url); + int storagePort = getDefaultStoragePort(url); + StoragePoolType storagetype = getStorageType(url); + String accesspath = getAccessPath(url); + String protocoltype = getProtocolType(url); + String[] mp = accesspath.split("/"); + String mountpoint = mp[1]; + String uuid = null ; + + /** + * if the elastistor params which are required for plugin configuration + * are not injected through spring-storage-volume-cloudbyte-context.xml, it can be set from details map. + */ + if(details.get("esaccountid") != null) + ElastistorUtil.setElastistorAccountId(details.get("esaccountid")); + if(details.get("esapikey") != null) + ElastistorUtil.setElastistorApiKey(details.get("esapikey")); + if(details.get("esdefaultgateway") != null) + ElastistorUtil.setElastistorGateway(details.get("esdefaultgateway")); + if(details.get("estntinterface") != null) + ElastistorUtil.setElastistorInterface(details.get("estntinterface")); + if(details.get("esmanagementip") != null) + ElastistorUtil.setElastistorManagementIp(details.get("esmanagementip")); + if(details.get("espoolid") != null) + ElastistorUtil.setElastistorPoolId(details.get("espoolid")); + if(details.get("essubnet") != null) + ElastistorUtil.setElastistorSubnet(details.get("essubnet")); + + if (capacityBytes == null || capacityBytes <= 0) { + throw new IllegalArgumentException("'capacityBytes' must be present and greater than 0."); + } + + if (capacityIops == null || capacityIops <= 0) { + throw new IllegalArgumentException("'capacityIops' must be present and greater than 0."); + } + + // elastistor does not allow same name and ip pools. + List storagePoolVO = _storagePoolDao.listAll(); + for(StoragePoolVO poolVO : storagePoolVO){ + if (storagePoolName.equals(poolVO.getName())) { + throw new IllegalArgumentException("storage pool with that name already exists in elastistor,please specify a unique name ."); + } + if (storageIp.equals(poolVO.getHostAddress())) { + throw new IllegalArgumentException("storage pool with that ip already exists in elastistor,please specify a unique ip ."); + } + } + + PrimaryDataStoreParameters parameters = new PrimaryDataStoreParameters(); + + // creates the volume in elastistor + parameters = createElastistorVolume(parameters, storagePoolName, storageIp, capacityBytes, capacityIops, protocoltype, mountpoint); + + parameters.setHost(storageIp); + parameters.setPort(storagePort); + if(protocoltype.contentEquals("nfs")){ + parameters.setPath(accesspath); + } + parameters.setType(storagetype); + parameters.setZoneId(zoneId); + parameters.setPodId(podId); + parameters.setName(storagePoolName); + parameters.setProviderName(providerName); + parameters.setManaged(false); + parameters.setCapacityBytes(capacityBytes); + parameters.setUsedBytes(0); + parameters.setCapacityIops(capacityIops); + parameters.setHypervisorType(HypervisorType.Any); + parameters.setTags(tags); + parameters.setDetails(details); + parameters.setClusterId(clusterId); + + return _dataStoreHelper.createPrimaryDataStore(parameters); + } + + private PrimaryDataStoreParameters createElastistorVolume(PrimaryDataStoreParameters parameters, String storagePoolName, String storageIp, Long capacityBytes, Long capacityIops, String protocoltype, String mountpoint){ + + s_logger.info("creation of elastistor volume started"); + try { + + CreateTsmCmdResponse tsmCmdResponse = ElastistorUtil.createElastistorTsm(storagePoolName, storageIp, capacityBytes, capacityIops); + + String uuid = tsmCmdResponse.getTsm().getUuid(); + parameters.setUuid(uuid); + + CreateVolumeCmdResponse volumeCmdResponse = ElastistorUtil.createElastistorVolume(storagePoolName, tsmCmdResponse, capacityBytes, capacityIops, protocoltype ,mountpoint); + + if(protocoltype.contentEquals("iscsi")){ + String accesspath = "/"+volumeCmdResponse.getFileSystem().getIqn()+"/0"; + parameters.setPath(accesspath); + } + s_logger.info("creation of elastistor volume complete"); + + return parameters; + } catch (Throwable e) { + throw new CloudRuntimeException("Failed to create volume in elastistor" + e.toString()); + } + + } + + private String getAccessPath(String url) { + StringTokenizer st = new StringTokenizer(url ,"/"); + int count = 0; + while (st.hasMoreElements()) { + if(count == 2) + { String s = "/" ; + return s.concat(st.nextElement().toString()); + } + st.nextElement(); + count++; + } + return null; + } + + + private StoragePoolType getStorageType(String url) { + + StringTokenizer st = new StringTokenizer(url ,":"); + + while (st.hasMoreElements()) + { + String accessprotocol = st.nextElement().toString(); + + if(accessprotocol.contentEquals("nfs")) + { + return StoragePoolType.NetworkFilesystem; + } + else if(accessprotocol.contentEquals("iscsi")) + { + return StoragePoolType.IscsiLUN; + } + + else + + break; + + } + return null; + } + + private String getProtocolType(String url) { + StringTokenizer st = new StringTokenizer(url ,":"); + + while (st.hasMoreElements()) + { + String accessprotocol = st.nextElement().toString(); + + if(accessprotocol.contentEquals("nfs")){ + return "nfs"; + }else if(accessprotocol.contentEquals("iscsi")){ + return "iscsi"; + } else + break; + } + return null; + } + + // this method parses the url and gets the default storage port based on access protocol + private int getDefaultStoragePort(String url) { + + StringTokenizer st = new StringTokenizer(url ,":"); + + while (st.hasMoreElements()) + { + + String accessprotocol = st.nextElement().toString(); + + if(accessprotocol.contentEquals("nfs")){ + return 2049; + } + else if(accessprotocol.contentEquals("iscsi")){ + return 3260; + } + else + break; + + } + return -1; + + } + + // parses the url and returns the storage volume ip + private String getStorageIp(String url) { + + StringTokenizer st = new StringTokenizer(url ,"/"); + int count = 0; + + while (st.hasMoreElements()) { + if(count == 1) + return st.nextElement().toString(); + + st.nextElement(); + count++; + } + return null; + } + + @Override + public boolean attachCluster(DataStore store, ClusterScope scope) { + + dataStoreHelper.attachCluster(store); + + PrimaryDataStoreInfo primarystore = (PrimaryDataStoreInfo) store; + // Check if there is host up in this cluster + List allHosts = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.Routing, primarystore.getClusterId(), + primarystore.getPodId(), primarystore.getDataCenterId()); + if (allHosts.isEmpty()) { + primaryDataStoreDao.expunge(primarystore.getId()); + throw new CloudRuntimeException("No host up to associate a storage pool with in cluster " + + primarystore.getClusterId()); + } + + + boolean success = false; + for (HostVO h : allHosts) { + success = createStoragePool(h.getId(), primarystore); + if (success) { + break; + } + } + + s_logger.debug("In createPool Adding the pool to each of the hosts"); + List poolHosts = new ArrayList(); + for (HostVO h : allHosts) { + try { + storageMgr.connectHostToSharedPool(h.getId(), primarystore.getId()); + poolHosts.add(h); + } catch (Exception e) { + s_logger.warn("Unable to establish a connection between " + h + " and " + primarystore, e); + } + + if (poolHosts.isEmpty()) { + s_logger.warn("No host can access storage pool " + primarystore + " on cluster " + + primarystore.getClusterId()); + primaryDataStoreDao.expunge(primarystore.getId()); + throw new CloudRuntimeException("Failed to access storage pool"); + } + } + + return true; + } + + private boolean createStoragePool(long hostId, StoragePool pool) { + s_logger.debug("creating pool " + pool.getName() + " on host " + hostId); + if (pool.getPoolType() != StoragePoolType.NetworkFilesystem && pool.getPoolType() != StoragePoolType.Filesystem + && pool.getPoolType() != StoragePoolType.IscsiLUN && pool.getPoolType() != StoragePoolType.Iscsi + && pool.getPoolType() != StoragePoolType.VMFS && pool.getPoolType() != StoragePoolType.SharedMountPoint + && pool.getPoolType() != StoragePoolType.PreSetup && pool.getPoolType() != StoragePoolType.OCFS2 + && pool.getPoolType() != StoragePoolType.RBD && pool.getPoolType() != StoragePoolType.CLVM) { + s_logger.warn(" Doesn't support storage pool type " + pool.getPoolType()); + return false; + } + CreateStoragePoolCommand cmd = new CreateStoragePoolCommand(true, pool); + final Answer answer = agentMgr.easySend(hostId, cmd); + if (answer != null && answer.getResult()) { + return true; + } else { + primaryDataStoreDao.expunge(pool.getId()); + String msg = ""; + if (answer != null) { + msg = "Can not create storage pool through host " + hostId + " due to " + answer.getDetails(); + s_logger.warn(msg); + } else { + msg = "Can not create storage pool through host " + hostId + " due to CreateStoragePoolCommand returns null"; + s_logger.warn(msg); + } + throw new CloudRuntimeException(msg); + } + } + + + @Override + public boolean attachHost(DataStore store, HostScope scope, StoragePoolInfo existingInfo) { + _dataStoreHelper.attachHost(store, scope, existingInfo); + return true; + } + + @Override + public boolean attachZone(DataStore dataStore, ZoneScope scope, HypervisorType hypervisorType) { + List hosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByHypervisor(hypervisorType, scope.getScopeId()); + s_logger.debug("In createPool. Attaching the pool to each of the hosts."); + List poolHosts = new ArrayList(); + for (HostVO host : hosts) { + try { + storageMgr.connectHostToSharedPool(host.getId(), dataStore.getId()); + poolHosts.add(host); + } catch (Exception e) { + s_logger.warn("Unable to establish a connection between " + host + " and " + dataStore, e); + } + } + if (poolHosts.isEmpty()) { + s_logger.warn("No host can access storage pool " + dataStore + " in this zone."); + primaryDataStoreDao.expunge(dataStore.getId()); + throw new CloudRuntimeException("Failed to create storage pool as it is not accessible to hosts."); + } + dataStoreHelper.attachZone(dataStore, hypervisorType); + return true; + } + + @Override + public boolean maintain(DataStore store) { + _storagePoolAutomation.maintain(store); + _dataStoreHelper.maintain(store); + return true; + } + + @Override + public boolean cancelMaintain(DataStore store) { + _dataStoreHelper.cancelMaintain(store); + _storagePoolAutomation.cancelMaintain(store); + return true; + } + + @SuppressWarnings("finally") + @Override + public boolean deleteDataStore(DataStore store) { + List hostPoolRecords = _storagePoolHostDao.listByPoolId(store.getId()); + StoragePool pool = (StoragePool) store; + + // find the hypervisor where the storage is attached to. + HypervisorType hType = null; + if(hostPoolRecords.size() > 0 ){ + hType = getHypervisorType(hostPoolRecords.get(0).getHostId()); + } + + // Remove the SR associated with the Xenserver + for (StoragePoolHostVO host : hostPoolRecords) { + DeleteStoragePoolCommand deleteCmd = new DeleteStoragePoolCommand(pool); + final Answer answer = agentMgr.easySend(host.getHostId(), deleteCmd); + + if (answer != null && answer.getResult()) { + // if host is KVM hypervisor then send deleteStoragepoolcmd to all the kvm hosts. + if (HypervisorType.KVM != hType) { + break; + } + } else { + if (answer != null) { + s_logger.error("Failed to delete storage pool: " + answer.getResult()); + } + } + } + + //delete the Elastistor volume at backend + deleteElastistorVolume(pool); + + return _dataStoreHelper.deletePrimaryDataStore(store); + } + + private void deleteElastistorVolume(StoragePool pool){ + + String poolip = pool.getHostAddress(); + String esip = null; + String apikey = null; + + // check if apikey and managentip is empty, if so getting it from stragepooldetails + if(ElastistorUtil.s_esIPVAL == "" && ElastistorUtil.s_esAPIKEYVAL == ""){ + Map detailsMap = _storagePoolDetailsDao.listDetailsKeyPairs(pool.getId()); + ElastistorUtil.setElastistorManagementIp(detailsMap.get("esmanagementip")); + esip=ElastistorUtil.s_esIPVAL; + ElastistorUtil.setElastistorApiKey(detailsMap.get("esapikey")); + apikey = ElastistorUtil.s_esAPIKEYVAL; + }else{ + esip = ElastistorUtil.s_esIPVAL; + apikey = ElastistorUtil.s_esAPIKEYVAL; + } + + boolean status; + try { + status = ElastistorUtil.deleteElastistorVolume(poolip,esip,apikey); + } catch (Throwable e) { + throw new CloudRuntimeException("Failed to delete primary storage on elastistor" + e); + } + + if(status == true){ + s_logger.info("deletion of elastistor primary storage complete"); + }else{ + s_logger.error("deletion of elastistor volume failed"); + } + + } + + private HypervisorType getHypervisorType(long hostId) { + HostVO host = _hostDao.findById(hostId); + if (host != null) + return host.getHypervisorType(); + return HypervisorType.None; + } + + @Override + public boolean migrateToObjectStore(DataStore store) { + return false; + } + + +} diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorHostListener.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorHostListener.java new file mode 100755 index 0000000000..de4711a140 --- /dev/null +++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorHostListener.java @@ -0,0 +1,87 @@ +/* + * 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.datastore.provider; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.ModifyStoragePoolAnswer; +import com.cloud.agent.api.ModifyStoragePoolCommand; +import com.cloud.alert.AlertManager; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolHostVO; +import com.cloud.storage.dao.StoragePoolHostDao; +import com.cloud.utils.exception.CloudRuntimeException; + +public class ElastistorHostListener implements HypervisorHostListener { + private static final Logger s_logger = Logger.getLogger(DefaultHostListener.class); + @Inject + AgentManager agentMgr; + @Inject + DataStoreManager dataStoreMgr; + @Inject + AlertManager alertMgr; + @Inject + StoragePoolHostDao storagePoolHostDao; + @Inject + PrimaryDataStoreDao primaryStoreDao; + + @Override + public boolean hostConnect(long hostId, long poolId) { + StoragePool pool = (StoragePool) this.dataStoreMgr.getDataStore(poolId, DataStoreRole.Primary); + ModifyStoragePoolCommand cmd = new ModifyStoragePoolCommand(true, pool); + final Answer answer = agentMgr.easySend(hostId, cmd); + + if (answer == null) { + throw new CloudRuntimeException("Unable to get an answer to the modify storage pool command" + pool.getId()); + } + + if (!answer.getResult()) { + String msg = "Unable to attach storage pool" + poolId + " to the host" + hostId; + + alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST,pool.getDataCenterId(), pool.getPodId(), msg, msg); + + throw new CloudRuntimeException("Unable establish connection from storage head to storage pool " + pool.getId() + " due to " + answer.getDetails() + pool.getId()); + } + + assert (answer instanceof ModifyStoragePoolAnswer) : "Well, now why won't you actually return the ModifyStoragePoolAnswer when it's ModifyStoragePoolCommand? Pool=" + pool.getId() + "Host=" + hostId; + + s_logger.info("Connection established between " + pool + " host + " + hostId); + return true; + } + + @Override + public boolean hostDisconnected(long hostId, long poolId) { + StoragePoolHostVO storagePoolHost = storagePoolHostDao.findByPoolHost( + poolId, hostId); + + if (storagePoolHost != null) { + storagePoolHostDao.deleteStoragePoolHostDetails(hostId, poolId); + } + return false; + } + +} diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorPrimaryDataStoreProvider.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorPrimaryDataStoreProvider.java new file mode 100755 index 0000000000..e59108299a --- /dev/null +++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/provider/ElastistorPrimaryDataStoreProvider.java @@ -0,0 +1,175 @@ +/* + * 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.datastore.provider; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreLifeCycle; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.HypervisorHostListener; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver; +import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreProvider; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.driver.ElastistorPrimaryDataStoreDriver; +import org.apache.cloudstack.storage.datastore.lifecycle.ElastistorPrimaryDataStoreLifeCycle; +import org.apache.cloudstack.storage.datastore.util.ElastistorUtil; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.agent.AgentManager; +import com.cloud.alert.AlertManager; +import com.cloud.storage.dao.StoragePoolHostDao; +import com.cloud.utils.component.ComponentContext; + +@Component +public class ElastistorPrimaryDataStoreProvider implements PrimaryDataStoreProvider { + + private static final Logger s_logger = Logger.getLogger(DefaultHostListener.class); + + //these classes will be injected by spring + private ElastistorPrimaryDataStoreLifeCycle lifecycle; + private PrimaryDataStoreDriver driver; + private HypervisorHostListener listener; + + // these params will be initialized with respective values given in spring-storage-volume-cloudbyte-context.xml bean for the elastistor porpose only. + private String esmanagementip; + private String esapikey; + private String esaccountid; + private String espoolid; + private String esdefaultgateway; + private String essubnet; + private String estntinterface; + + @Inject + AgentManager agentMgr; + @Inject + DataStoreManager dataStoreMgr; + @Inject + AlertManager alertMgr; + @Inject + StoragePoolHostDao storagePoolHostDao; + @Inject + PrimaryDataStoreDao primaryStoreDao; + + + @Override + public String getName() { + return ElastistorUtil.ES_PROVIDER_NAME; + } + + @Override + public DataStoreLifeCycle getDataStoreLifeCycle() { + return lifecycle; + } + + @Override + public PrimaryDataStoreDriver getDataStoreDriver() { + return driver; + } + + @Override + public HypervisorHostListener getHostListener() { + return listener; + } + + @Override + public boolean configure(Map params) { + + lifecycle = ComponentContext.inject(ElastistorPrimaryDataStoreLifeCycle.class); + driver = ComponentContext.inject(ElastistorPrimaryDataStoreDriver.class); + listener = ComponentContext.inject(ElastistorHostListener.class); + + ElastistorUtil.setElastistorAccountId(esaccountid); + ElastistorUtil.setElastistorApiKey(esapikey); + ElastistorUtil.setElastistorManagementIp(esmanagementip); + ElastistorUtil.setElastistorPoolId(espoolid); + ElastistorUtil.setElastistorGateway(esdefaultgateway); + ElastistorUtil.setElastistorInterface(estntinterface); + ElastistorUtil.setElastistorSubnet(essubnet); + + return true; + } + + @Override + public Set getTypes() { + Set types = new HashSet(); + + types.add(DataStoreProviderType.PRIMARY); + + return types; + } + public String getEspoolid() { + return espoolid; + } + + public void setEspoolid(String espoolid) { + this.espoolid = espoolid; + } + + public String getEsmanagementip() { + return esmanagementip; + } + + public void setEsmanagementip(String esmanagementip) { + this.esmanagementip = esmanagementip; + } + + public String getEsaccountid() { + return esaccountid; + } + + public void setEsaccountid(String esaccountid) { + this.esaccountid = esaccountid; + } + + public String getEsapikey() { + return esapikey; + } + + public void setEsapikey(String esapikey) { + this.esapikey = esapikey; + } + + public String getesdefaultgateway() { + return esdefaultgateway; + } + + public void setesdefaultgateway(String esdefaultgateway) { + this.esdefaultgateway = esdefaultgateway; + } + public String getEssubnet() { + return essubnet; + } + + public void setEssubnet(String essubnet) { + this.essubnet = essubnet; + } + + public String getEstntinterface(){ + return estntinterface; + } + + public void setEstntinterface(String estntinterface){ + this.estntinterface = estntinterface; + } +} diff --git a/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/util/ElastistorUtil.java b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/util/ElastistorUtil.java new file mode 100755 index 0000000000..b75d12a6a4 --- /dev/null +++ b/plugins/storage/volume/cloudbyte/src/org/apache/cloudstack/storage/datastore/util/ElastistorUtil.java @@ -0,0 +1,1156 @@ +/* + * 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.datastore.util; + +import java.net.ConnectException; +import java.security.InvalidParameterException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.HashMap; + +import javax.naming.ServiceUnavailableException; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriBuilder; + +import org.apache.http.auth.InvalidCredentialsException; +import org.apache.log4j.Logger; + +import com.cloud.utils.exception.CloudRuntimeException; +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.config.ClientConfig; +import com.sun.jersey.api.client.config.DefaultClientConfig; +import com.sun.jersey.core.util.MultivaluedMapImpl; + +public class ElastistorUtil { + + private static final Logger s_logger = Logger.getLogger(ElastistorUtil.class); + + + /** + * Elastistor REST API Param Keys. These should match exactly with the + * elastistor API commands' params. + */ + public static final String REST_PARAM_COMMAND = "command"; + public static final String REST_PARAM_APIKEY = "apikey"; + public static final String REST_PARAM_KEYWORD = "keyword"; + public static final String REST_PARAM_ID = "id"; + public static final String REST_PARAM_QUOTA_SIZE = "quotasize"; + public static final String REST_PARAM_READONLY = "readonly"; + public static final String REST_PARAM_RESPONSE = "response"; + public static final String REST_PARAM_POOLID = "poolid"; + public static final String REST_PARAM_ACCOUNTID = "accountid"; + public static final String REST_PARAM_GATEWAY = "router"; + public static final String REST_PARAM_SUBNET = "subnet"; + public static final String REST_PARAM_INTERFACE = "tntinterface"; + public static final String REST_PARAM_IPADDRESS = "ipaddress"; + public static final String REST_PARAM_JOBID = "jobId"; + public static final String REST_PARAM_FORECEDELETE = "forcedelete"; + public static final String REST_PARAM_TSM_THROUGHPUT = "totalthroughput"; + public static final String REST_PARAM_NAME = "name"; + public static final String REST_PARAM_NOOFCOPIES = "noofcopies"; + public static final String REST_PARAM_RECORDSIZE = "recordsize"; + public static final String REST_PARAM_TOTALIOPS = "totaliops"; + public static final String REST_PARAM_LATENCY = "latency"; + public static final String REST_PARAM_BLOCKSIZE = "blocksize"; + public static final String REST_PARAM_GRACEALLOWED = "graceallowed"; + public static final String REST_PARAM_IOPS = "iops"; + public static final String REST_PARAM_THROUGHPUT = "throughput"; + public static final String REST_PARAM_MEMLIMIT= "memlimit"; + public static final String REST_PARAM_NETWORKSPEED = "networkspeed"; + public static final String REST_PARAM_TSMID = "tsmid"; + public static final String REST_PARAM_DATASETID = "datasetid"; + public static final String REST_PARAM_QOSGROUPID = "qosgroupid"; + public static final String REST_PARAM_DEDUPLICATION = "deduplication"; + public static final String REST_PARAM_COMPRESSION = "compression"; + public static final String REST_PARAM_SYNC = "sync"; + public static final String REST_PARAM_MOUNTPOINT= "mountpoint"; + public static final String REST_PARAM_CASESENSITIVITY = "casesensitivity"; + public static final String REST_PARAM_UNICODE = "unicode"; + public static final String REST_PARAM_PROTOCOLTYPE= "protocoltype"; + public static final String REST_PARAM_AUTHNETWORK = "authnetwork"; + public static final String REST_PARAM_MAPUSERSTOROOT = "mapuserstoroot"; + + /** + * Constants related to elastistor which are persisted in cloudstack + * databases as keys. + */ + public static final String ES_SUBNET = "essubnet"; + public static final String ES_INTERFACE = "estntinterface"; + public static final String ES_GATEWAY = "esdefaultgateway"; + public static final String ES_PROVIDER_NAME = "elastistor"; + public static final String ES_ACCOUNT_ID = "esAccountId"; + public static final String ES_POOL_ID = "esPoolId"; + public static final String ES_ACCOUNT_NAME = "esAccountName"; + public static final String ES_STORAGE_IP = "esStorageIp"; + public static final String ES_STORAGE_PORT = "esStoragePort"; + public static final String ES_STORAGE_TYPE = "esStorageType"; + public static final String ES_MANAGEMENT_IP = "esMgmtIp"; + public static final String ES_MANAGEMENT_PORT = "esMgmtPort"; + public static final String ES_API_KEY = "esApiKey"; + public static final String ES_VOLUME_ID = "esVolumeId"; + public static final String ES_VOLUME_GROUP_ID = "esVolumeGroupId"; + public static final String ES_FILE_SYSTEM_ID = "esFilesystemId"; + + /** + * Values from configuration that are required for every invocation of + * ElastiCenter API. These might in turn be saved as DB updates along with + * above keys. + */ + public static String s_esIPVAL = ""; + public static String s_esAPIKEYVAL = ""; + public static String s_esACCOUNTIDVAL = ""; + public static String s_esPOOLIDVAL = ""; + public static String s_esSUBNETVAL = ""; + public static String s_esINTERFACEVAL = ""; + public static String s_esGATEWAYVAL = ""; + + /** + * hardcoded constants for elastistor api calls. + */ + private static final String ES_NOOFCOPIES_VAL = "1"; + private static final String ES_BLOCKSIZE_VAL = "4K"; + private static final String ES_LATENCY_VAL = "15"; + private static final String ES_GRACEALLOWED_VAL = "false"; + private static final String ES_MEMLIMIT_VAL = "0"; + private static final String ES_NETWORKSPEED_VAL = "0"; + private static final String ES_DEDUPLICATION_VAL = "off"; + private static final String ES_COMPRESSION_VAL = "off"; + private static final String ES_CASESENSITIVITY_VAL = "sensitive"; + private static final String ES_READONLY_VAL = "off"; + private static final String ES_UNICODE_VAL = "off"; + private static final String ES_AUTHNETWORK_VAL = "all"; + private static final String ES_MAPUSERSTOROOT_VAL = "yes"; + private static final String ES_SYNC_VAL = "always"; + + + /** + * Private constructor s.t. its never instantiated. + */ + private ElastistorUtil() { + + } + + /** + * This intializes a new jersey restclient for http call with elasticenter + */ + public static ElastiCenterClient getElastistorRestClient(String managementIp , String apiKey) { + ElastiCenterClient restclient = null; + try { + + restclient = new ElastiCenterClient(managementIp, apiKey); + + } catch (InvalidCredentialsException e) { + throw new CloudRuntimeException("InvalidCredentialsException", e); + } catch (InvalidParameterException e) { + throw new CloudRuntimeException("InvalidParameterException", e); + } catch (SSLHandshakeException e) { + throw new CloudRuntimeException("SSLHandshakeException", e); + } catch (ServiceUnavailableException e) { + throw new CloudRuntimeException("ServiceUnavailableException", e); + } + return restclient; + } + + public static void setElastistorApiKey(String value) { + s_esAPIKEYVAL = value; + } + + public static void setElastistorManagementIp(String value) { + s_esIPVAL = value; + } + + public static void setElastistorPoolId(String value) { + s_esPOOLIDVAL = value; + } + + public static void setElastistorAccountId(String value) { + s_esACCOUNTIDVAL = value; + } + + public static void setElastistorGateway(String value) { + s_esGATEWAYVAL = value; + } + + public static void setElastistorInterface(String value) { + s_esINTERFACEVAL = value; + } + + public static void setElastistorSubnet(String value) { + s_esSUBNETVAL = value; + } + + /** + * This creates a new tenant storage machine(TSM) for the given storagepool ip in elastistor. + */ + public static CreateTsmCmdResponse createElastistorTsm(String storagePoolName, String storageIp, Long capacityBytes, Long capacityIops) throws Throwable { + + String totalthroughput = String.valueOf(capacityIops*4); + String totaliops = String.valueOf(capacityIops); + + String quotasize = convertCapacityBytes(capacityBytes); + + CreateTsmCmd createTsmCmd = new CreateTsmCmd(); + + if ( null != ElastistorUtil.s_esACCOUNTIDVAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ACCOUNTID, ElastistorUtil.s_esACCOUNTIDVAL); + if ( null != totalthroughput ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_TSM_THROUGHPUT, totalthroughput); + if ( null != ElastistorUtil.s_esPOOLIDVAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_POOLID, ElastistorUtil.s_esPOOLIDVAL); + if ( null != storagePoolName ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NAME, "TSM"+storagePoolName); + if ( null != quotasize ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_QUOTA_SIZE, quotasize); + if ( null != storageIp ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_IPADDRESS, storageIp); + if ( null != ElastistorUtil.s_esSUBNETVAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_SUBNET, ElastistorUtil.s_esSUBNETVAL); + if ( null != ElastistorUtil.s_esGATEWAYVAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_GATEWAY, ElastistorUtil.s_esGATEWAYVAL); + if ( null != ElastistorUtil.s_esINTERFACEVAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_INTERFACE, ElastistorUtil.s_esINTERFACEVAL); + if ( null != ElastistorUtil.ES_NOOFCOPIES_VAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NOOFCOPIES, ElastistorUtil.ES_NOOFCOPIES_VAL); + if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_RECORDSIZE, ElastistorUtil.ES_BLOCKSIZE_VAL); + if ( null != totaliops ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_TOTALIOPS, totaliops); + if ( null != ElastistorUtil.ES_LATENCY_VAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_LATENCY, ElastistorUtil.ES_LATENCY_VAL); + if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_BLOCKSIZE, ElastistorUtil.ES_BLOCKSIZE_VAL); + if ( null != ElastistorUtil.ES_GRACEALLOWED_VAL ) createTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_GRACEALLOWED, ElastistorUtil.ES_GRACEALLOWED_VAL); + + CreateTsmCmdResponse cmdResponse; + + try { + cmdResponse = (CreateTsmCmdResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(createTsmCmd); + + if ( cmdResponse.getTsm().getUuid() == null ){ + throw new CloudRuntimeException("tsm creation failed , contact elatistor admin"); + } + return cmdResponse; + } catch (Exception e) { + throw new CloudRuntimeException("tsm creation failed , contact elatistor admin" + e.toString()); + } + + } + + /** + * This creates the specified volume on the created tsm. + */ + public static CreateVolumeCmdResponse createElastistorVolume(String storagePoolName, CreateTsmCmdResponse cmdResponse, Long capacityBytes, Long capacityIops,String protocoltype, String mountpoint) throws Throwable { + + String datasetid; + String tsmid; + String qosgroupid; + String VolumeName = storagePoolName; + String totaliops = String.valueOf(capacityIops); + String totalthroughput = String.valueOf(capacityIops*4); + + String quotasize = convertCapacityBytes(capacityBytes); + + AddQosGroupCmd addQosGroupCmd = new AddQosGroupCmd(); + + + tsmid = cmdResponse.getTsm().getUuid(); + datasetid = cmdResponse.getTsm().getDatasetid(); + + if (null != VolumeName)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NAME, "QOS_" + VolumeName); + if (null != totaliops)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_IOPS, totaliops); + if (null != ElastistorUtil.ES_LATENCY_VAL)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_LATENCY, ElastistorUtil.ES_LATENCY_VAL); + if (null != ElastistorUtil.ES_BLOCKSIZE_VAL)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_BLOCKSIZE, ElastistorUtil.ES_BLOCKSIZE_VAL); + if (null != totalthroughput)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_THROUGHPUT, totalthroughput); + if (null != ElastistorUtil.ES_MEMLIMIT_VAL)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_MEMLIMIT, ElastistorUtil.ES_MEMLIMIT_VAL); + if (null != ElastistorUtil.ES_NETWORKSPEED_VAL)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NETWORKSPEED, ElastistorUtil.ES_NETWORKSPEED_VAL); + if (null != tsmid)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_TSMID, tsmid); + if (null != datasetid)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_DATASETID, datasetid); + if (null != ElastistorUtil.ES_GRACEALLOWED_VAL)addQosGroupCmd.putCommandParameter(ElastistorUtil.REST_PARAM_GRACEALLOWED, ElastistorUtil.ES_GRACEALLOWED_VAL); + + AddQosGroupCmdResponse addQosGroupCmdResponse = (AddQosGroupCmdResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(addQosGroupCmd); + + if (addQosGroupCmdResponse.getQoSGroup().getUuid() == null) { + + throw new CloudRuntimeException("adding qos group failed , contact elatistor admin"); + + } + + else { + + CreateVolumeCmd createVolumeCmd = new CreateVolumeCmd(); + + qosgroupid = addQosGroupCmdResponse.getQoSGroup().getUuid(); + + if (null != ElastistorUtil.s_esACCOUNTIDVAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ACCOUNTID,ElastistorUtil.s_esACCOUNTIDVAL); + if (null != qosgroupid)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_QOSGROUPID, qosgroupid); + if (null != tsmid)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_TSMID, tsmid); + if (null != ElastistorUtil.s_esPOOLIDVAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_POOLID,ElastistorUtil.s_esPOOLIDVAL); + if (null != VolumeName)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NAME, VolumeName); + if (null != quotasize)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_QUOTA_SIZE, quotasize); + if(protocoltype.equalsIgnoreCase("nfs")){ + if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_BLOCKSIZE, ElastistorUtil.ES_BLOCKSIZE_VAL); + if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_RECORDSIZE, ElastistorUtil.ES_BLOCKSIZE_VAL); + } + else{ + if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_BLOCKSIZE, "512B"); + if ( null != ElastistorUtil.ES_BLOCKSIZE_VAL ) createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_RECORDSIZE, "512B"); + } + if (null != ElastistorUtil.ES_DEDUPLICATION_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_DEDUPLICATION, ElastistorUtil.ES_DEDUPLICATION_VAL); + if (null != ElastistorUtil.ES_SYNC_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_SYNC, ElastistorUtil.ES_SYNC_VAL); + if (null != ElastistorUtil.ES_COMPRESSION_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_COMPRESSION, ElastistorUtil.ES_COMPRESSION_VAL); + if (null != ElastistorUtil.ES_NOOFCOPIES_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_NOOFCOPIES, ElastistorUtil.ES_NOOFCOPIES_VAL); + createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_MOUNTPOINT, mountpoint); + if (null != ElastistorUtil.ES_CASESENSITIVITY_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_CASESENSITIVITY, ElastistorUtil.ES_CASESENSITIVITY_VAL); + if (null != ElastistorUtil.ES_READONLY_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_READONLY, ElastistorUtil.ES_READONLY_VAL); + if (null != datasetid)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_DATASETID, datasetid); + if (null != ElastistorUtil.ES_UNICODE_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_UNICODE, ElastistorUtil.ES_UNICODE_VAL); + createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_PROTOCOLTYPE, protocoltype); + if (null != ElastistorUtil.ES_AUTHNETWORK_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_AUTHNETWORK, ElastistorUtil.ES_AUTHNETWORK_VAL); + if (null != ElastistorUtil.ES_MAPUSERSTOROOT_VAL)createVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_MAPUSERSTOROOT, ElastistorUtil.ES_MAPUSERSTOROOT_VAL); + + CreateVolumeCmdResponse createVolumeCmdResponse; + try { + createVolumeCmdResponse = (CreateVolumeCmdResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(createVolumeCmd); + + if (createVolumeCmdResponse.getFileSystem().getUuid() == null) { + + throw new CloudRuntimeException("creating volume failed , contact elatistor admin"); + + } else { + return createVolumeCmdResponse; + } + + } catch (Exception e) { + throw new CloudRuntimeException("creating volume failed , contact elatistor admin", e); + } + + } + + } + + /** + * This deletes both the volume and the tsm in elastistor. + */ + public static boolean deleteElastistorVolume(String poolip, String esmanagementip, String esapikey) throws Throwable { + + String esvolumeid = null; + String estsmid = null; + + ListTsmsResponse listTsmsResponse = listTsm(poolip); + + if (listTsmsResponse.getTsmsCount() != 0) { + int i; + + for (i = 0; i < listTsmsResponse.getTsmsCount(); i++) { + if (poolip.compareTo(listTsmsResponse.getTsms().getTsm(i).getIpaddress()) == 0) { + estsmid = listTsmsResponse.getTsms().getTsm(i).getUuid(); + break; + } + } + + if (listTsmsResponse.getTsms().getTsm(i).checkvolume()) { + esvolumeid = listTsmsResponse.getTsms().getTsm(i).getVolumeProperties(0).getid(); + DeleteVolumeResponse deleteVolumeResponse = deleteVolume(esvolumeid, null); + + if (deleteVolumeResponse != null) { + String jobid = deleteVolumeResponse.getJobId(); + int jobstatus = queryAsyncJobResult(jobid); + + if (jobstatus == 1) { + s_logger.info("elastistor volume successfully deleted"); + } else { + s_logger.info("now farce deleting the volume"); + + while (jobstatus != 1) { + DeleteVolumeResponse deleteVolumeResponse1 = deleteVolume(esvolumeid, "true"); + + if (deleteVolumeResponse1 != null) { + String jobid1 = deleteVolumeResponse1.getJobId(); + jobstatus = queryAsyncJobResult(jobid1); + } + } + s_logger.info("elastistor volume successfully deleted"); + } + } + } else { + s_logger.info("no volume present in on the given tsm"); + } + s_logger.info("now trying to delete elastistor tsm"); + + if (estsmid != null) { + DeleteTsmCmd deleteTsmCmd = new DeleteTsmCmd(); + deleteTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ID,estsmid); + DeleteTsmResponse deleteTsmResponse = (DeleteTsmResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(deleteTsmCmd); + + if (deleteTsmResponse != null) { + String jobstatus = deleteTsmResponse.getJobStatus(); + + if (jobstatus.equalsIgnoreCase("true")) { + s_logger.info("deletion of elastistor tsm successful"); + return true; + } else { + s_logger.info("failed to delete elastistor tsm"); + return false; + } + } else { + s_logger.info("elastistor tsm id not present"); + } + } + else { + s_logger.error("no volume is present in the tsm"); + } + } else { + s_logger.error("List tsm failed, no tsm present in the eastistor for the given IP "); + return false; + } + return false; + + } + + /** + * This give a json response containing the list of tsm's in elastistor. + */ + private static ListTsmsResponse listTsm(String poolip) throws Throwable { + + ListTsmCmd listTsmCmd = new ListTsmCmd(); + + listTsmCmd.putCommandParameter(ElastistorUtil.REST_PARAM_IPADDRESS,poolip); + + ListTsmsResponse listTsmsResponse = (ListTsmsResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(listTsmCmd); + + return listTsmsResponse; + } + + private static DeleteVolumeResponse deleteVolume(String esvolumeid, String forcedelete)throws Throwable { + + DeleteVolumeCmd deleteVolumeCmd = new DeleteVolumeCmd(); + + deleteVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_ID,esvolumeid); + deleteVolumeCmd.putCommandParameter(ElastistorUtil.REST_PARAM_FORECEDELETE, forcedelete); + + DeleteVolumeResponse deleteVolumeResponse = (DeleteVolumeResponse) getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL).executeCommand(deleteVolumeCmd); + + return deleteVolumeResponse; + } + + private static int queryAsyncJobResult(String jobid) throws Throwable { + + QueryAsyncJobResultCmd asyncJobResultCmd = new QueryAsyncJobResultCmd(); + ElastiCenterClient restclient = getElastistorRestClient(s_esIPVAL, s_esAPIKEYVAL); + + asyncJobResultCmd.putCommandParameter(ElastistorUtil.REST_PARAM_JOBID, jobid); + + QueryAsyncJobResultResponse asyncJobResultResponse = (QueryAsyncJobResultResponse) restclient.executeCommand(asyncJobResultCmd); + + if (asyncJobResultResponse != null) { + int jobstatus = asyncJobResultResponse.getAsync().getJobStatus(); + + while (jobstatus == 0) { + + QueryAsyncJobResultResponse jobResultResponse = (QueryAsyncJobResultResponse) restclient.executeCommand(asyncJobResultCmd); + + jobstatus = jobResultResponse.getAsync().getJobStatus(); + } + return jobstatus; + } + return 0; + + } + + /** + * this method converts the long capacitybytes to string format, which is feasible for elastistor rest api + * 214748364800 = 200G. + */ + private static String convertCapacityBytes(Long capacityBytes){ + + String quotasize; + + if((1099511627776L)>capacityBytes &&(capacityBytes>(1073741824))){ + return quotasize =(String.valueOf(capacityBytes/(1024*1024*1024))+"G"); + }else + { int temp1 = (int) (capacityBytes/(1024*1024*1024)); + int temp2 = temp1/1024; + return quotasize =(String.valueOf(temp2)+"T"); + } + } + + static interface ElastiCenterCommand { + + /* + * Returns the command string to be sent to the ElastiCenter + */ + public String getCommandName(); + + /* + * Utility method to allow the client to validate the input parameters + * before sending to the ElastiCenter. + * + * This command will be executed by the ElastiCenterClient only this method + * returns true. + */ + public boolean validate(); + + /* + * Returns the query parameters that have to be passed to execute the + * command. + * + * Returns null if there are query parameters associated with the command + */ + public MultivaluedMap getCommandParameters(); + + /* + * Adds new key-value pair to the query paramters lists. + */ + public void putCommandParameter(String key, String value); + + /* + * Return an instance of the Response Object Type. + * + * Return null if no response is expected. + */ + public Object getResponseObject(); + } + + private static class BaseCommand implements ElastiCenterCommand { + + private String commandName = null; + private MultivaluedMap commandParameters = null; + private Object responseObject = null; + + /* + * Enforce the Commands to be initialized with command name and optional + * response object + */ + protected BaseCommand(String cmdName, Object responseObj) { + commandName = cmdName; + responseObject = responseObj; + } + + @Override + public String getCommandName() { + return commandName; + } + + @Override + public boolean validate() { + // TODO This method can be extended to do some generic + // validations. + return true; + } + + @Override + public MultivaluedMap getCommandParameters() { + return commandParameters; + } + + @Override + public void putCommandParameter(String key, String value) { + if (null == commandParameters) { + commandParameters = new MultivaluedMapImpl(); + } + commandParameters.add(key, value); + } + + @Override + public Object getResponseObject() { + return responseObject; + } + + } + +/** + * this is a rest client which is used to call the http rest calls to elastistor + * @author punith + * + */ + private static final class ElastiCenterClient { + + public static boolean debug = false; + + private boolean initialized = false; + + private String apiKey = null; + private String elastiCenterAddress = null; + private String responseType = "json"; + private boolean ignoreSSLCertificate = false; + + private String restprotocol = "https://"; + private String restpath = "/client/api"; + private String restdefaultcommand = "listCapabilities"; + + private String queryparamcommand = "command"; + private String queryparamapikey = "apikey"; + private String queryparamresponse = "response"; + + public ElastiCenterClient(String address, String key)throws InvalidCredentialsException, InvalidParameterException,SSLHandshakeException, ServiceUnavailableException { + this.elastiCenterAddress = address; + this.apiKey = key; + this.initialize(); + } + + public void initialize() throws InvalidParameterException, + SSLHandshakeException, InvalidCredentialsException, + ServiceUnavailableException { + + if (apiKey == null || apiKey.trim().isEmpty()) { + throw new InvalidParameterException("Unable to initialize. Please specify a valid API Key."); + } + + if (elastiCenterAddress == null || elastiCenterAddress.trim().isEmpty()) { + // TODO : Validate the format, like valid IP address or hostname. + throw new InvalidParameterException("Unable to initialize. Please specify a valid ElastiCenter IP Address or Hostname."); + } + + if (ignoreSSLCertificate) { + // Create a trust manager that does not validate certificate chains + TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted(X509Certificate[] certs, + String authType) { + } + + public void checkServerTrusted(X509Certificate[] certs, + String authType) { + } + } }; + + HostnameVerifier hv = new HostnameVerifier() { + @Override + public boolean verify(String urlHostName, SSLSession session) { + return true; + } + }; + + // Install the all-trusting trust manager + try { + SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(null, trustAllCerts, new SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + HttpsURLConnection.setDefaultHostnameVerifier(hv); + } catch (Exception e) { + ; + } + } + + ListCapabilitiesResponse listCapabilitiesResponse = null; + try { + initialized = true; + listCapabilitiesResponse = (ListCapabilitiesResponse) executeCommand(restdefaultcommand, null, new ListCapabilitiesResponse()); + + } catch (Throwable t) { + initialized = false; + if (t instanceof InvalidCredentialsException) { + throw (InvalidCredentialsException) t; + } else if (t instanceof ServiceUnavailableException) { + throw (ServiceUnavailableException) t; + } else if (t.getCause() instanceof SSLHandshakeException) { + throw new SSLHandshakeException( + "Unable to initialize. An untrusted SSL Certificate was received from " + + elastiCenterAddress + + ". Please verify your truststore or configure ElastiCenterClient to skip the SSL Validation. "); + } else if (t.getCause() instanceof ConnectException) { + throw new ServiceUnavailableException( + "Unable to initialize. Failed to connect to " + + elastiCenterAddress + + ". Please verify the IP Address, Network Connectivity and ensure that Services are running on the ElastiCenter Server. "); + } + throw new ServiceUnavailableException("Unable to initialize. Please contact your ElastiCenter Administrator. Exception " + t.getMessage()); + } + + if (null == listCapabilitiesResponse || null == listCapabilitiesResponse.getCapabilities() || null == listCapabilitiesResponse.getCapabilities().getVersion()) { + initialized = false; + throw new ServiceUnavailableException("Unable to execute command on the server"); + } + + } + + public Object executeCommand(ElastiCenterCommand cmd) throws Throwable { + return executeCommand(cmd.getCommandName(), cmd.getCommandParameters(),cmd.getResponseObject()); + } + + public Object executeCommand(String command,MultivaluedMap params, Object responeObj) throws Throwable { + + if (!initialized) { + throw new IllegalStateException("Error : ElastiCenterClient is not initialized."); + } + + if (command == null || command.trim().isEmpty()) { + throw new InvalidParameterException("No command to execute."); + } + + try { + ClientConfig config = new DefaultClientConfig(); + Client client = Client.create(config); + WebResource webResource = client.resource(UriBuilder.fromUri(restprotocol + elastiCenterAddress + restpath).build()); + + MultivaluedMap queryParams = new MultivaluedMapImpl(); + queryParams.add(queryparamapikey, apiKey); + queryParams.add(queryparamresponse, responseType); + + queryParams.add(queryparamcommand, command); + + if (null != params) { + for (String key : params.keySet()) { + queryParams.add(key, params.getFirst(key)); + } + } + if (debug) { + System.out.println("Command Sent " + command + " : "+ queryParams); + } + ClientResponse response = webResource.queryParams(queryParams).accept(MediaType.APPLICATION_JSON).get(ClientResponse.class); + + if (response.getStatus() >= 300) { + if (debug) + System.out.println("ElastiCenter returned error code : " + response.getStatus()); + if (401 == response.getStatus()) { + throw new InvalidCredentialsException("Please specify a valid API Key."); + } else if (431 == response.getStatus()) { + throw new InvalidParameterException(response.getHeaders().getFirst("X-Description")); + } else if (432 == response.getStatus()) { + throw new InvalidParameterException(command + " does not exist on the ElastiCenter server. Please specify a valid command or contact your ElastiCenter Administrator."); + } else { + throw new ServiceUnavailableException("Internal Error. Please contact your ElastiCenter Administrator."); + } + } else if (null != responeObj) { + String jsonResponse = response.getEntity(String.class); + if (debug) { + System.out.println("Command Response : " + jsonResponse); + } + Gson gson = new Gson(); + return gson.fromJson(jsonResponse, responeObj.getClass()); + } else { + return "Success"; + } + } catch (Throwable t) { + throw t; + } + } + } + + /** + * these are the list of Elastistor rest commands being called from the plugin. + * + */ + private static final class CreateTsmCmd extends BaseCommand { + + public CreateTsmCmd() { + super("createTsm", new CreateTsmCmdResponse()); + + } + + } + + private static final class AddQosGroupCmd extends BaseCommand { + + public AddQosGroupCmd() { + + super("addQosGroup", new AddQosGroupCmdResponse()); + + } + + } + + private static final class CreateVolumeCmd extends BaseCommand { + + public CreateVolumeCmd() { + super("createVolume", new CreateVolumeCmdResponse()); + + } + + } + + private static final class DeleteTsmCmd extends BaseCommand { + + public DeleteTsmCmd() { + super("deleteTsm", new DeleteTsmResponse()); + } + + } + + private static final class DeleteVolumeCmd extends BaseCommand { + + public DeleteVolumeCmd() { + super("deleteFileSystem", new DeleteVolumeResponse()); + } + + } + + private static final class QueryAsyncJobResultCmd extends BaseCommand { + + public QueryAsyncJobResultCmd() { + super("queryAsyncJobResult", new QueryAsyncJobResultResponse()); + } + + } + + private static final class ListTsmCmd extends BaseCommand { + + public ListTsmCmd() { + super("listTsm", new ListTsmsResponse()); + } + + } + + /** + * these are the list of Elastistor rest json response classes for parsing the json response sent by elastistor. + * + */ + public static final class CreateTsmCmdResponse { + + @SerializedName("createTsmResponse") + private TsmWrapper tsmWrapper; + + public Tsm getTsm() { + return tsmWrapper.getTsm(); + } + + } + + public static final class Tsm { + + @SerializedName("id") + private String uuid; + + @SerializedName("name") + private String name; + + @SerializedName("datasetid") + private String datasetid; + + @SerializedName("ipaddress") + private String ipaddress; + + @SerializedName("volumes") + private VolumeProperties[] volumeProperties; + + public String getUuid() { + return uuid; + } + + public String getName() { + return name; + } + + public String getIpaddress() { + return ipaddress; + } + + public String getDatasetid() { + return datasetid; + } + + public boolean checkvolume() { + + if(volumeProperties != null){ + return true; + } + else{ + return false; + } + + } + + public VolumeProperties getVolumeProperties(int i) { + return volumeProperties[i]; + } + + } + + public static final class VolumeProperties { + + @SerializedName("id") + private String id; + + @SerializedName("groupid") + private String groupid; + + @SerializedName("iops") + private String iops; + + @SerializedName("name") + private String name; + + public String getid() { + return id; + } + + public String getQosgroupid() { + return groupid; + } + + public String getName() { + return name; + } + + public String getIops() { + return iops; + } + } + + public static final class TsmWrapper { + + @SerializedName("tsm") + private Tsm tsm; + + public Tsm getTsm() { + return tsm; + } + + } + + public static final class AddQosGroupCmdResponse { + + @SerializedName("addqosgroupresponse") + private QoSGroupWrapper qosGroupWrapper; + + public QoSGroup getQoSGroup() { + return qosGroupWrapper.getQosGroup(); + } + } + + public static final class QoSGroupWrapper { + + @SerializedName("qosgroup") + private QoSGroup qoSGroup; + + public QoSGroup getQosGroup() { + + return qoSGroup; + } + + } + + public static final class QoSGroup { + + @SerializedName("id") + private String uuid; + + @SerializedName("name") + private String name; + + @SerializedName("qosgroupproperties") + private HashMap qosGroupProperties; + + public String getName() { + return name; + } + + public String getUuid() { + return uuid; + } + + public String getIops() { + return qosGroupProperties.get("iops"); + } + + public String getThroughput() { + return qosGroupProperties.get("throughput"); + } + + public String getLatency() { + return qosGroupProperties.get("latency"); + } + } + + public static final class CreateVolumeCmdResponse { + + @SerializedName("adddatasetresponse") + private FileSystemWrapper fileSystemWrapper; + + public FileSystem getFileSystem() { + + return fileSystemWrapper.getFileSystem(); + } + + } + + public static final class FileSystemWrapper { + + @SerializedName("filesystem") + private FileSystem fileSystem; + + public FileSystem getFileSystem() { + return fileSystem; + } + + } + + public static final class FileSystem { + + @SerializedName("id") + private String uuid; + + @SerializedName("name") + private String name; + + @SerializedName("quota") + private String quota; + + @SerializedName("timestamp") + private String timestamp; + + @SerializedName("iqnname") + private String iqnname; + + @SerializedName("filesystemproperties") + private HashMap[] filesystemproperties; + + public String getUuid() { + return uuid; + } + + public String getName() { + return name; + } + + public String getIqn() { + return iqnname; + } + + public String getQuota() { + return quota; + } + + public String getTimestamp() { + return timestamp; + } + + } + + public static final class DeleteTsmResponse { + + @SerializedName("deleteTsmResponse") + private JobId jobId; + + public String getJobStatus() { + return jobId.getJobStatus(); + } + + } + + public static final class JobId { + + @SerializedName("jobid") + private String jobid; + + @SerializedName("success") + private String jobStatus; + + public String getJobid() { + return jobid; + } + + public String getJobStatus() { + return jobStatus; + } + + } + + public static final class DeleteVolumeResponse { + + @SerializedName("deleteFileSystemResponse") + private JobId jobId; + + public String getJobId() { + return jobId.getJobid(); + } + + } + + public static final class ListCapabilitiesResponse { + + @SerializedName("listcapabilitiesresponse") + private Capabilities capabilities; + + public Capabilities getCapabilities() { + return capabilities; + } + } + + public static final class ListTsmsResponse { + + @SerializedName("listTsmResponse") + private Tsms tsms; + + public int getTsmsCount() { + return tsms.getCount(); + } + + public Tsms getTsms() { + return tsms; + } + } + + public static final class Tsms { + + @SerializedName("count") + private int count; + + @SerializedName("listTsm") + private Tsm[] tsms; + + public int getCount() { + return count; + } + + public Tsm getTsm(int i) { + return tsms[i]; + } + } + + public static final class QueryAsyncJobResultResponse { + + @SerializedName("queryasyncjobresultresponse") + private Async async; + + public Async getAsync() { + return async; + } + } + + public static final class Async { + + @SerializedName("jobstatus") + private int jobstatus; + + @SerializedName("cmd") + private String cmd; + + public int getJobStatus() { + return jobstatus; + } + + public String getCmd() { + return cmd; + } + + } + + public static final class Capabilities { + + @SerializedName("capability") + private HashMap capabilites; + + public String getVersion() { + return capabilites.get("cloudByteVersion"); + } + } +} diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java index ae217b6359..5983a05a53 100644 --- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java +++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java @@ -24,7 +24,6 @@ import javax.inject.Inject; -import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; import org.apache.cloudstack.engine.subsystem.api.storage.ChapInfo; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; @@ -99,8 +98,6 @@ public Map getCapabilities() { @Inject StorageManager storageMgr; @Inject - VolumeOrchestrationService volumeMgr; - @Inject VMInstanceDao vmDao; @Inject SnapshotDao snapshotDao; @@ -151,10 +148,13 @@ public ChapInfo getChapInfo(VolumeInfo volumeInfo) { } @Override - public boolean connectVolumeToHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) { return false; } + public boolean connectVolumeToHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) { + return false; + } @Override - public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) {} + public void disconnectVolumeFromHost(VolumeInfo volumeInfo, Host host, DataStore dataStore) { + } @Override public long getVolumeSizeIncludingHypervisorSnapshotReserve(Volume volume, StoragePool pool) { @@ -168,7 +168,7 @@ public void createAsync(DataStore dataStore, DataObject data, AsyncCompletionCal CreateCmdResult result = new CreateCmdResult(null, null); if (data.getType() == DataObjectType.VOLUME) { try { - answer = createVolume((VolumeInfo)data); + answer = createVolume((VolumeInfo) data); if ((answer == null) || (!answer.getResult())) { result.setSuccess(false); if (answer != null) { @@ -260,7 +260,7 @@ public boolean canCopy(DataObject srcData, DataObject destData) { DataStore store = destData.getDataStore(); if (store.getRole() == DataStoreRole.Primary) { if ((srcData.getType() == DataObjectType.TEMPLATE && destData.getType() == DataObjectType.TEMPLATE) || - (srcData.getType() == DataObjectType.TEMPLATE && destData.getType() == DataObjectType.VOLUME)) { + (srcData.getType() == DataObjectType.TEMPLATE && destData.getType() == DataObjectType.VOLUME)) { StoragePoolVO storagePoolVO = primaryStoreDao.findById(store.getId()); if (storagePoolVO != null && storagePoolVO.getPoolType() == Storage.StoragePoolType.CLVM) { return true; @@ -274,10 +274,10 @@ public boolean canCopy(DataObject srcData, DataObject destData) { public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) { CreateCmdResult result = null; try { - SnapshotObjectTO snapshotTO = (SnapshotObjectTO)snapshot.getTO(); + SnapshotObjectTO snapshotTO = (SnapshotObjectTO) snapshot.getTO(); Object payload = snapshot.getPayload(); if (payload != null && payload instanceof CreateSnapshotPayload) { - CreateSnapshotPayload snapshotPayload = (CreateSnapshotPayload)payload; + CreateSnapshotPayload snapshotPayload = (CreateSnapshotPayload) payload; snapshotTO.setQuiescevm(snapshotPayload.getQuiescevm()); } @@ -285,7 +285,7 @@ public void takeSnapshot(SnapshotInfo snapshot, AsyncCompletionCallback callback) { - VolumeObject vol = (VolumeObject)data; - StoragePool pool = (StoragePool)data.getDataStore(); - ResizeVolumePayload resizeParameter = (ResizeVolumePayload)vol.getpayload(); + VolumeObject vol = (VolumeObject) data; + StoragePool pool = (StoragePool) data.getDataStore(); + ResizeVolumePayload resizeParameter = (ResizeVolumePayload) vol.getpayload(); ResizeVolumeCommand resizeCmd = - new ResizeVolumeCommand(vol.getPath(), new StorageFilerTO(pool), vol.getSize(), resizeParameter.newSize, resizeParameter.shrinkOk, - resizeParameter.instanceName); + new ResizeVolumeCommand(vol.getPath(), new StorageFilerTO(pool), vol.getSize(), resizeParameter.newSize, resizeParameter.shrinkOk, + resizeParameter.instanceName); CreateCmdResult result = new CreateCmdResult(null, null); try { - ResizeVolumeAnswer answer = (ResizeVolumeAnswer)storageMgr.sendToPool(pool, resizeParameter.hosts, resizeCmd); + ResizeVolumeAnswer answer = (ResizeVolumeAnswer) storageMgr.sendToPool(pool, resizeParameter.hosts, resizeCmd); if (answer != null && answer.getResult()) { long finalSize = answer.getNewSize(); s_logger.debug("Resize: volume started at size " + vol.getSize() + " and ended at size " + finalSize); diff --git a/pom.xml b/pom.xml index 02b1808727..b9067575d3 100644 --- a/pom.xml +++ b/pom.xml @@ -58,7 +58,7 @@ 1.9.0 build213-svnkit-1.3-patch 2.6.6 - 1.7.1 + 1.7.2 14.0-rc1 6.2.0-1-SNAPSHOT 3.1 @@ -86,7 +86,7 @@ 0.10 build/replace.properties 0.5.1 - 0.1.3 + 0.1.4 target 1.0.10 4.0.0 @@ -746,6 +746,7 @@ plugins/hypervisors/hyperv/DotNet/ServerResource/**/packages.config plugins/hypervisors/hyperv/DotNet/ServerResource/**/App.config plugins/hypervisors/hyperv/DotNet/ServerResource/**/*.csproj + plugins/hypervisors/hyperv/DotNet/ServerResource/**/*.settings plugins/hypervisors/hyperv/conf/agent.properties scripts/vm/systemvm/id_rsa.cloud services/console-proxy/server/conf/agent.properties diff --git a/scripts/vm/hypervisor/xenserver/check_heartbeat.sh b/scripts/vm/hypervisor/xenserver/check_heartbeat.sh index 22befe9165..e1b18278dd 100755 --- a/scripts/vm/hypervisor/xenserver/check_heartbeat.sh +++ b/scripts/vm/hypervisor/xenserver/check_heartbeat.sh @@ -72,3 +72,4 @@ do done echo "=====> DEAD <======" +exit 1 diff --git a/scripts/vm/hypervisor/xenserver/cloudstack_pluginlib.py b/scripts/vm/hypervisor/xenserver/cloudstack_pluginlib.py index 4ebb435a82..85daa864c2 100644 --- a/scripts/vm/hypervisor/xenserver/cloudstack_pluginlib.py +++ b/scripts/vm/hypervisor/xenserver/cloudstack_pluginlib.py @@ -358,7 +358,7 @@ def configure_bridge_for_network_topology(bridge, this_host_id, json_config): for host in vpc_spanning_hosts: if str(this_host_id) == str(host.hostid): continue - other_host_vms = get_vms_on_host(vpconfig, host.hostid) + other_host_vms = get_vms_on_host(vpconfig, str(host.hostid)) for vm in other_host_vms: for nic in vm.nics: mac_addr = nic.macaddress @@ -397,8 +397,9 @@ def configure_ovs_bridge_for_routing_policies(bridge, json_config): return "FAILURE:IMPROPER_JSON_CONFG_FILE" try: - # First flush current egress ACL's before re-applying the ACL's + # First flush current ingress and egress ACL's before re-applying the ACL's del_flows(bridge, table=3) + del_flows(bridge, table=5) egress_rules_added = False ingress_rules_added = False @@ -419,15 +420,22 @@ def configure_ovs_bridge_for_routing_policies(bridge, json_config): source_cidrs = acl_item.sourcecidrs acl_priority = 1000 + number for source_cidr in source_cidrs: - if direction is "ingress": + if direction == "ingress": ingress_rules_added = True - if source_port_start is None and source_port_end is None: - if action is "deny": - add_flow(bridge, priority= acl_priority, table=5, nw_src=source_cidr, nw_dst=tier_cidr, + if source_cidr.startswith('0.0.0.0'): + if action == "deny": + add_flow(bridge, priority= acl_priority, table=5, nw_dst=tier_cidr, + nw_proto=protocol, actions='drop') + if action == "allow": + add_flow(bridge, priority= acl_priority,table=5, nw_dst=tier_cidr, + nw_proto=protocol, actions='resubmit(,1)') + else: + if action == "deny": + add_flow(bridge, priority= acl_priority, table=5, nw_src=source_cidr, nw_dst=tier_cidr, nw_proto=protocol, actions='drop') - if action is "allow": - add_flow(bridge, priority= acl_priority,table=5, nw_src=source_cidr, nw_dst=tier_cidr, + if action == "allow": + add_flow(bridge, priority= acl_priority,table=5, nw_src=source_cidr, nw_dst=tier_cidr, nw_proto=protocol, actions='resubmit(,1)') continue @@ -435,36 +443,59 @@ def configure_ovs_bridge_for_routing_policies(bridge, json_config): # source_cidr and destination ip is in tier_cidr port = source_port_start while (port < source_port_end): - if action is "deny": - add_flow(bridge, priority= acl_priority, table=5, nw_src=source_cidr, nw_dst=tier_cidr, tp_dst=port, + if source_cidr.startswith('0.0.0.0'): + if action == "deny": + add_flow(bridge, priority= acl_priority, table=5, nw_dst=tier_cidr, tp_dst=port, nw_proto=protocol, actions='drop') - if action is "allow": - add_flow(bridge, priority= acl_priority,table=5, nw_src=source_cidr, nw_dst=tier_cidr, tp_dst=port, + if action == "allow": + add_flow(bridge, priority= acl_priority,table=5, nw_dst=tier_cidr, tp_dst=port, + nw_proto=protocol, actions='resubmit(,1)') + else: + if action == "deny": + add_flow(bridge, priority= acl_priority, table=5, nw_src=source_cidr, nw_dst=tier_cidr, tp_dst=port, + nw_proto=protocol, actions='drop') + if action == "allow": + add_flow(bridge, priority= acl_priority,table=5, nw_src=source_cidr, nw_dst=tier_cidr, tp_dst=port, nw_proto=protocol, actions='resubmit(,1)') port = port + 1 - elif direction in "egress": + elif direction == "egress": egress_rules_added = True - if source_port_start is None and source_port_end is None: - if action is "deny": - add_flow(bridge, priority= acl_priority, table=3, nw_src=source_cidr, nw_dst=tier_cidr, + if source_cidr.startswith('0.0.0.0'): + if action == "deny": + add_flow(bridge, priority= acl_priority, table=3, nw_dst=tier_cidr, nw_proto=protocol, actions='drop') - if action is "allow": - add_flow(bridge, priority= acl_priority,table=3, nw_src=source_cidr, nw_dst=tier_cidr, - nw_proto=protocol, actions='resubmit(,1)') + if action == "allow": + add_flow(bridge, priority= acl_priority,table=3, nw_dst=tier_cidr, + nw_proto=protocol, actions='resubmit(,4)') + else: + if action == "deny": + add_flow(bridge, priority= acl_priority, table=3, nw_src=source_cidr, nw_dst=tier_cidr, + nw_proto=protocol, actions='drop') + if action == "allow": + add_flow(bridge, priority= acl_priority,table=3, nw_src=source_cidr, nw_dst=tier_cidr, + nw_proto=protocol, actions='resubmit(,4)') continue # add flow rule to do action (allow/deny) for flows where destination IP of the packet is in # source_cidr and source ip is in tier_cidr port = source_port_start while (port < source_port_end): - if action is "deny": - add_flow(bridge, priority= acl_priority, table=3, nw_src=tier_cidr, nw_dst=source_cidr, tp_dst=port, - nw_proto=protocol, actions='drop') - if action is "allow": - add_flow(bridge, priority= acl_priority, table=3, nw_src=tier_cidr, nw_dst=source_cidr, tp_dst=port, - nw_proto=protocol, actions='resubmit(,1)') + if source_cidr.startswith('0.0.0.0'): + if action == "deny": + add_flow(bridge, priority= acl_priority, table=3, nw_dst=source_cidr, tp_dst=port, + nw_proto=protocol, actions='drop') + if action == "allow": + add_flow(bridge, priority= acl_priority, table=3, nw_dst=source_cidr, tp_dst=port, + nw_proto=protocol, actions='resubmit(,4)') + else: + if action == "deny": + add_flow(bridge, priority= acl_priority, table=3, nw_src=tier_cidr, nw_dst=source_cidr, tp_dst=port, + nw_proto=protocol, actions='drop') + if action == "allow": + add_flow(bridge, priority= acl_priority, table=3, nw_src=tier_cidr, nw_dst=source_cidr, tp_dst=port, + nw_proto=protocol, actions='resubmit(,4)') port = port + 1 if egress_rules_added is False: @@ -472,8 +503,11 @@ def configure_ovs_bridge_for_routing_policies(bridge, json_config): add_flow(bridge, priority=0, table=3, actions='resubmit(,4)') if ingress_rules_added is False: - # add a default rule in egress table drop packets + # add a default rule in ingress table drop packets add_flow(bridge, priority=0, table=5, actions='drop') + + return "SUCCESS: successfully configured bridge as per the latest routing policies of the VPC" + except: logging.debug("An unexpected error occurred while configuring bridge as per VPC's routing policies.") raise \ No newline at end of file diff --git a/scripts/vm/hypervisor/xenserver/hostvmstats.py b/scripts/vm/hypervisor/xenserver/hostvmstats.py deleted file mode 100644 index 61cf2de99f..0000000000 --- a/scripts/vm/hypervisor/xenserver/hostvmstats.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/python -# 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: hostvmstats.py 10054 2010-06-29 22:09:31Z abhishek $ $HeadURL: svn://svn.lab.vmops.com/repos/vmdev/java/scripts/vm/hypervisor/xenserver/hostvmstats.py $ - -import XenAPI -import urllib -import time -import logging -import logging.handlers - -LOG_FILENAME = '/tmp/xapilog' -logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG) -stats_logger = logging.getLogger('statsLogger') -stats_logger.setLevel(logging.DEBUG) - -#handler with maxBytes=10MiB -handler = logging.handlers.RotatingFileHandler(LOG_FILENAME, maxBytes=10*1024*1024, backupCount=5) -stats_logger.addHandler(handler) - -def get_stats(session, collect_host_stats, consolidation_function, interval, start_time): - try: - - if collect_host_stats == "true" : - url = "http://localhost/rrd_updates?" - url += "session_id=" + session._session - url += "&host=" + collect_host_stats - url += "&cf=" + consolidation_function - url += "&interval=" + str(interval) - url += "&start=" + str(int(time.time())-100) - else : - url = "http://localhost/rrd_updates?" - url += "session_id=" + session._session - url += "&host=" + collect_host_stats - url += "&cf=" + consolidation_function - url += "&interval=" + str(interval) - url += "&start=" + str(int(time.time())-100) - - stats_logger.debug("Calling URL: %s",url) - sock = urllib.URLopener().open(url) - xml = sock.read() - sock.close() - stats_logger.debug("Size of returned XML: %s",len(xml)) - return xml - except Exception,e: - stats_logger.exception("get_stats() failed") - raise diff --git a/scripts/vm/hypervisor/xenserver/ovs-vif-flows.py b/scripts/vm/hypervisor/xenserver/ovs-vif-flows.py index 1445d940ef..b2fe11c78f 100644 --- a/scripts/vm/hypervisor/xenserver/ovs-vif-flows.py +++ b/scripts/vm/hypervisor/xenserver/ovs-vif-flows.py @@ -102,7 +102,7 @@ def main(command, vif_raw): ovs_vpc_distributed_vr_network = pluginlib.do_cmd([pluginlib.XE_PATH,"network-param-get", "uuid=%s" % xs_nw_uuid, "param-name=other-config", - "param-key=is-ovs_vpc_distributed_vr_network", "--minimal"]) + "param-key=is-ovs-vpc-distributed-vr-network", "--minimal"]) except: pass @@ -131,7 +131,7 @@ def main(command, vif_raw): apply_flows(bridge, this_vif_ofport, vif_ofports) - # handle case where brdige is setup for VPC and VPC is enabled for distributed routing + # handle case where bridge is setup for VPC which is enabled for distributed routing if ovs_vpc_distributed_vr_network == 'True': vlan = pluginlib.do_cmd([pluginlib.VSCTL_PATH, 'br-to-vlan', bridge]) if vlan != '0': @@ -157,7 +157,7 @@ def main(command, vif_raw): if port.startswith('t'): # check tunnel port is in same network as that of plugged vif - if vif_network_id != pluginlib.get_network_id_for_tunnel_port(port): + if vif_network_id != pluginlib.get_network_id_for_tunnel_port(port)[1:-1]: continue vnet_tunnelif_ofports.append(if_ofport) vnet_all_ofports.append(if_ofport) diff --git a/scripts/vm/hypervisor/xenserver/ovstunnel b/scripts/vm/hypervisor/xenserver/ovstunnel index 98a9d0b82f..f9673023a9 100755 --- a/scripts/vm/hypervisor/xenserver/ovstunnel +++ b/scripts/vm/hypervisor/xenserver/ovstunnel @@ -156,7 +156,7 @@ def setup_ovs_bridge_for_distributed_routing(session, args): xs_nw_uuid = lib.do_cmd([lib.XE_PATH, "network-list", "bridge=%s" % bridge, "--minimal"]) lib.do_cmd([lib.XE_PATH, "network-param-set", "uuid=%s" % xs_nw_uuid, - "other-config:is-ovs_vpc_distributed_vr_network=True"]) + "other-config:is-ovs-vpc-distributed-vr-network=True"]) conf_hosts = lib.do_cmd([lib.XE_PATH, "network-param-get", "uuid=%s" % xs_nw_uuid, "param-name=other-config", @@ -291,14 +291,24 @@ def create_tunnel(session, args): # find xs network for this bridge, verify is used for ovs tunnel network xs_nw_uuid = lib.do_cmd([lib.XE_PATH, "network-list", "bridge=%s" % bridge, "--minimal"]) - ovs_tunnel_network = lib.do_cmd([lib.XE_PATH,"network-param-get", + ovs_tunnel_network = False + try: + ovs_tunnel_network = lib.do_cmd([lib.XE_PATH,"network-param-get", "uuid=%s" % xs_nw_uuid, "param-name=other-config", "param-key=is-ovs-tun-network", "--minimal"]) - ovs_vpc_distributed_vr_network = lib.do_cmd([lib.XE_PATH,"network-param-get", + except: + pass + + ovs_vpc_distributed_vr_network = False + try: + ovs_vpc_distributed_vr_network = lib.do_cmd([lib.XE_PATH,"network-param-get", "uuid=%s" % xs_nw_uuid, "param-name=other-config", - "param-key=is-ovs_vpc_distributed_vr_network", "--minimal"]) + "param-key=is-ovs-vpc-distributed-vr-network", "--minimal"]) + except: + pass + if ovs_tunnel_network == 'True': # add flow entryies for dropping broadcast coming in from gre tunnel lib.add_flow(bridge, priority=1000, in_port=tun_ofport, @@ -398,7 +408,7 @@ def configure_ovs_bridge_for_routing_policies(session, args): bridge = args.pop("bridge") json_config = args.pop("config") - return lib.configure_ovs_bridge_for_router_policies(bridge, json_config) + return lib.configure_ovs_bridge_for_routing_policies(bridge, json_config) if __name__ == "__main__": XenAPIPlugin.dispatch({"create_tunnel": create_tunnel, @@ -409,4 +419,4 @@ if __name__ == "__main__": "getLabel": getLabel, "setup_ovs_bridge_for_distributed_routing": setup_ovs_bridge_for_distributed_routing, "configure_ovs_bridge_for_network_topology": configure_ovs_bridge_for_network_topology, - "configure_ovs_bridge_for_routing_policies": "configure_ovs_bridge_for_routing_policies"}) + "configure_ovs_bridge_for_routing_policies": configure_ovs_bridge_for_routing_policies}) diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index 4174ef24f7..3f25a2e7f9 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -27,7 +27,6 @@ if os.path.exists("/opt/xensource/sm"): if os.path.exists("/usr/lib/xcp/sm"): sys.path.extend(["/usr/lib/xcp/sm/", "/usr/local/sbin/", "/sbin/"]) import base64 -import hostvmstats import socket import stat import tempfile @@ -61,15 +60,6 @@ def add_to_VCPUs_params_live(session, args): return 'false' return 'true' -@echo -def gethostvmstats(session, args): - collect_host_stats = args['collectHostStats'] - consolidation_function = args['consolidationFunction'] - interval = args['interval'] - start_time = args['startTime'] - result = hostvmstats.get_stats(session, collect_host_stats, consolidation_function, interval, start_time) - return result - @echo def setup_iscsi(session, args): uuid=args['uuid'] @@ -207,20 +197,6 @@ def setLinkLocalIP(session, args): txt = 'success' return txt -@echo -def routerProxy(session, args): - sargs = args['args'] - cmd = sargs.split(' ') - cmd.insert(0, "/opt/cloud/bin/router_proxy.sh") - cmd.insert(0, "/bin/bash") - try: - txt = util.pread2(cmd) - txt = 'succ#' + txt - except: - logging.debug("routerProxy command " + sargs + " failed " ) - txt = 'fail#' + txt - return txt - @echo def createFile(session, args): file_path = args['filepath'] @@ -1502,10 +1478,9 @@ def network_rules(session, args): logging.debug("Failed to network rule !") if __name__ == "__main__": - XenAPIPlugin.dispatch({"pingtest": pingtest, "setup_iscsi":setup_iscsi, "gethostvmstats": gethostvmstats, + XenAPIPlugin.dispatch({"pingtest": pingtest, "setup_iscsi":setup_iscsi, "getgateway": getgateway, "preparemigration": preparemigration, "setIptables": setIptables, "pingdomr": pingdomr, "pingxenserver": pingxenserver, - "routerProxy": routerProxy, "createFile": createFile, "deleteFile": deleteFile, "network_rules":network_rules, "can_bridge_firewall":can_bridge_firewall, "default_network_rules":default_network_rules, diff --git a/scripts/vm/hypervisor/xenserver/vmopspremium b/scripts/vm/hypervisor/xenserver/vmopspremium index 06b0a51f7e..2887436670 100755 --- a/scripts/vm/hypervisor/xenserver/vmopspremium +++ b/scripts/vm/hypervisor/xenserver/vmopspremium @@ -123,18 +123,7 @@ def setup_heartbeat_file(session, args): txt = '' return txt -@echo -def check_heartbeat(session, args): - host = args['host'] - interval = args['interval'] - try: - cmd = ["bash", "/opt/cloud/bin/check_heartbeat.sh", host, interval] - txt = util.pread2(cmd) - except: - txt='' - return txt - - + @echo def heartbeat(session, args): host = args['host'] @@ -156,5 +145,4 @@ def asmonitor(session, args): return 'fail' if __name__ == "__main__": - XenAPIPlugin.dispatch({"forceShutdownVM":forceShutdownVM, "upgrade_snapshot":upgrade_snapshot, "create_privatetemplate_from_snapshot":create_privatetemplate_from_snapshot, "copy_vhd_to_secondarystorage":copy_vhd_to_secondarystorage, "copy_vhd_from_secondarystorage":copy_vhd_from_secondarystorage, "setup_heartbeat_sr":setup_heartbeat_sr, "setup_heartbeat_file":setup_heartbeat_file, "check_heartbeat":check_heartbeat, "heartbeat": heartbeat, "asmonitor": asmonitor}) - + XenAPIPlugin.dispatch({"forceShutdownVM":forceShutdownVM, "upgrade_snapshot":upgrade_snapshot, "create_privatetemplate_from_snapshot":create_privatetemplate_from_snapshot, "copy_vhd_to_secondarystorage":copy_vhd_to_secondarystorage, "copy_vhd_from_secondarystorage":copy_vhd_from_secondarystorage, "setup_heartbeat_sr":setup_heartbeat_sr, "setup_heartbeat_file":setup_heartbeat_file, "heartbeat": heartbeat, "asmonitor": asmonitor}) diff --git a/scripts/vm/hypervisor/xenserver/xcposs/copy_vhd_from_secondarystorage.sh b/scripts/vm/hypervisor/xenserver/xcposs/copy_vhd_from_secondarystorage.sh new file mode 100755 index 0000000000..a4e977bdd5 --- /dev/null +++ b/scripts/vm/hypervisor/xenserver/xcposs/copy_vhd_from_secondarystorage.sh @@ -0,0 +1,188 @@ +#!/bin/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. + +#set -x + +usage() { + printf "Usage: %s [vhd file in secondary storage] [uuid of the source sr] [name label] \n" $(basename $0) +} + +cleanup() +{ + if [ ! -z $localmp ]; then + umount -fl $localmp + if [ $? -eq 0 ]; then + rmdir $localmp + fi + fi +} + +if [ -z $1 ]; then + usage + echo "2#no mountpoint" + exit 0 +else + mountpoint=${1%/*} + vhdfilename=${1##*/} +fi + +if [ -z $2 ]; then + usage + echo "3#no uuid of the source sr" + exit 0 +else + sruuid=$2 +fi + +type=$(xe sr-param-get uuid=$sruuid param-name=type) +if [ $? -ne 0 ]; then + echo "4#sr $sruuid doesn't exist" + exit 0 +fi + +if [ -z $3 ]; then + usage + echo "3#no namelabel" + exit 0 +else + namelabel=$3 +fi + +localmp=/var/run/cloud_mount/$(uuidgen -r) + +mkdir -p $localmp +if [ $? -ne 0 ]; then + echo "5#can't make dir $localmp" + exit 0 +fi + +mount -o tcp,soft,ro,timeo=133,retrans=1 $mountpoint $localmp +if [ $? -ne 0 ]; then + echo "6#can't mount $mountpoint to $localmp" + exit 0 +fi + +vhdfile=$localmp/$vhdfilename +if [ ${vhdfile%.vhd} == ${vhdfile} ] ; then + vhdfile=$(ls $vhdfile/*.vhd) + if [ $? -ne 0 ]; then + echo "7#There is no vhd file under $mountpoint" + cleanup + exit 0 + fi +fi + + + +VHDUTIL="/usr/bin/vhd-util" + +copyvhd() +{ + local desvhd=$1 + local srcvhd=$2 + local vsize=$3 + local type=$4 + local parent=`$VHDUTIL query -p -n $srcvhd` + if [ $? -ne 0 ]; then + echo "30#failed to query $srcvhd" + cleanup + exit 0 + fi + if [ "${parent##*vhd has}" = " no parent" ]; then + dd if=$srcvhd of=$desvhd bs=2M + if [ $? -ne 0 ]; then + echo "31#failed to dd $srcvhd to $desvhd" + cleanup + exit 0 + fi + if [ $type != "nfs" -a $type != "ext" -a $type != "file" ]; then + dd if=$srcvhd of=$desvhd bs=512 seek=$(($(($vsize/512))-1)) count=1 + $VHDUTIL modify -s $vsize -n $desvhd + if [ $? -ne 0 ]; then + echo "32#failed to set new vhd physical size for vdi vdi $uuid" + cleanup + exit 0 + fi + fi + else + copyvhd $desvhd $parent $vsize $type + $VHDUTIL coalesce -p $desvhd -n $srcvhd + if [ $? -ne 0 ]; then + echo "32#failed to coalesce $desvhd to $srcvhd" + cleanup + exit 0 + fi + fi +} + +size=$($VHDUTIL query -v -n $vhdfile) +uuid=$(xe vdi-create sr-uuid=$sruuid virtual-size=${size}MiB type=user name-label=$namelabel) +if [ $? -ne 0 ]; then + echo "9#can not create vdi in sr $sruuid" + cleanup + exit 0 +fi + + +if [ $type == "nfs" -o $type == "ext" ]; then + desvhd=/run/sr-mount/$sruuid/$uuid.vhd + copyvhd $desvhd $vhdfile 0 $type + +elif [ $type == "lvmoiscsi" -o $type == "lvm" -o $type == "lvmohba" ]; then + lvsize=$(xe vdi-param-get uuid=$uuid param-name=physical-utilisation) + if [ $? -ne 0 ]; then + echo "12#failed to get physical size of vdi $uuid" + cleanup + exit 0 + fi + desvhd=/dev/VG_XenStorage-$sruuid/VHD-$uuid + lvchange -ay $desvhd + if [ $? -ne 0 ]; then + echo "10#lvm can not make VDI $uuid visible" + cleanup + exit 0 + fi + copyvhd $desvhd $vhdfile $lvsize $type +elif [ $type == "file" ]; then + pbd=`xe sr-param-list uuid=$sruuid |grep PBDs | awk '{print $3}'` + path=`xe pbd-param-list uuid=$pbd |grep device-config |awk '{print $4}'` + desvhd=$path/$uuid.vhd + copyvhd $desvhd $vhdfile 0 $type + +else + echo "15#doesn't support sr type $type" + cleanup + exit 0 +fi + +$VHDUTIL set -n $desvhd -f "hidden" -v "0" > /dev/null +if [ $? -ne 0 ]; then + echo "21#failed to set hidden to 0 $desvhd" + cleanup + exit 0 +fi +xe sr-scan uuid=$sruuid +if [ $? -ne 0 ]; then + echo "14#failed to scan sr $sruuid" + cleanup + exit 0 +fi + +echo "0#$uuid" +cleanup +exit 0 diff --git a/scripts/vm/hypervisor/xenserver/xcposs/copy_vhd_to_secondarystorage.sh b/scripts/vm/hypervisor/xenserver/xcposs/copy_vhd_to_secondarystorage.sh new file mode 100755 index 0000000000..b315c07b35 --- /dev/null +++ b/scripts/vm/hypervisor/xenserver/xcposs/copy_vhd_to_secondarystorage.sh @@ -0,0 +1,130 @@ +#!/bin/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. + +#set -x + +usage() { + printf "Usage: %s [mountpoint in secondary storage] [uuid of the source vdi] [uuid of the source sr]\n" $(basename $0) +} + +cleanup() +{ + if [ ! -z $localmp ]; then + umount $localmp + if [ $? -eq 0 ]; then + rmdir $localmp + fi + fi +} + +if [ -z $1 ]; then + usage + echo "1#no mountpoint" + exit 0 +else + mountpoint=$1 +fi + +if [ -z $2 ]; then + usage + echo "2#no uuid of the source sr" + exit 0 +else + vdiuuid=$2 +fi + + +if [ -z $3 ]; then + usage + echo "3#no uuid of the source sr" + exit 0 +else + sruuid=$3 +fi + +type=$(xe sr-param-get uuid=$sruuid param-name=type) +if [ $? -ne 0 ]; then + echo "4#sr $sruuid doesn't exist" + exit 0 +fi + +localmp=/var/run/cloud_mount/$(uuidgen -r) + +mkdir -p $localmp +if [ $? -ne 0 ]; then + echo "5#can't make dir $localmp" + exit 0 +fi + +mount -o tcp,soft,timeo=133,retrans=1 $mountpoint $localmp +if [ $? -ne 0 ]; then + echo "6#can't mount $mountpoint to $localmp" + exit 0 +fi + +vhdfile=$localmp/${vdiuuid}.vhd + +if [ $type == "nfs" -o $type == "ext" ]; then + dd if=/var/run/sr-mount/$sruuid/${vdiuuid}.vhd of=$vhdfile bs=2M + if [ $? -ne 0 ]; then + rm -f $vhdfile + echo "8#failed to copy /var/run/sr-mount/$sruuid/${vdiuuid}.vhd to secondarystorage" + cleanup + exit 0 + fi +elif [ $type == "lvmoiscsi" -o $type == "lvm" -o $type == "lvmohba" ]; then + lvchange -ay /dev/VG_XenStorage-$sruuid/VHD-$vdiuuid + if [ $? -ne 0 ]; then + echo "9#lvm can not make VDI $vdiuuid visible" + cleanup + exit 0 + fi + size=$(vhd-util query -s -n /dev/VG_XenStorage-$sruuid/VHD-$vdiuuid) + if [ $? -ne 0 ]; then + echo "10#can not get physical size of /dev/VG_XenStorage-$sruuid/VHD-$vdiuuid" + cleanup + exit 0 + fi +#in 2M unit + size=$((size>>21)) + size=$((size+1)) + dd if=/dev/VG_XenStorage-$sruuid/VHD-$vdiuuid of=$vhdfile bs=2M count=$size + if [ $? -ne 0 ]; then + rm -f $vhdfile + echo "8#failed to copy /dev/VG_XenStorage-$sruuid/VHD-$vdiuuid to secondarystorage" + cleanup + exit 0 + fi +#in byte unit + size=$((size<<21)) + vhd-util modify -s $size -n $vhdfile + if [ $? -ne 0 ]; then + rm -f $vhdfile + echo "11#failed to change $vhdfile physical size" + cleanup + exit 0 + fi +else + echo "15#doesn't support sr type $type" + cleanup + exit 0 +fi + +echo "0#$vdiuuid" +cleanup +exit 0 diff --git a/scripts/vm/hypervisor/xenserver/xcposs/patch b/scripts/vm/hypervisor/xenserver/xcposs/patch index 08da883e54..ac04a3e14d 100644 --- a/scripts/vm/hypervisor/xenserver/xcposs/patch +++ b/scripts/vm/hypervisor/xenserver/xcposs/patch @@ -27,11 +27,12 @@ # If [source path] starts with '~', then it is path relative to management server home directory. # If [source path] does not start with '/' or '~', then it is relative path to the location of the patch file. NFSSR.py=/usr/lib/xcp/sm -vmops=..,0755,/usr/lib/xcp/plugins +vmops=,0755,/usr/lib/xcp/plugins +cloudstack_pluginlib.py=..,0755,/usr/lib/xcp/plugins +cloudstack_plugins.conf=..,0644,/etc/xcp ovsgre=..,0755,/usr/lib/xcp/plugins ovstunnel=..,0755,/usr/lib/xcp/plugins -vmopsSnapshot=..,0755,/usr/lib/xcp/plugins -hostvmstats.py=..,0755,/usr/lib/xcp/sm +vmopsSnapshot=,0755,/usr/lib/xcp/plugins systemvm.iso=../../../../../vms,0644,/usr/share/xcp/packages/iso/ id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin @@ -40,8 +41,8 @@ make_migratable.sh=..,0755,/opt/cloud/bin setup_iscsi.sh=..,0755,/opt/cloud/bin pingtest.sh=../../..,0755,/opt/cloud/bin cloud-setup-bonding.sh=..,0755,/opt/cloud/bin -copy_vhd_to_secondarystorage.sh=..,0755,/opt/cloud/bin -copy_vhd_from_secondarystorage.sh=..,0755,/opt/cloud/bin +copy_vhd_to_secondarystorage.sh=,0755,/opt/cloud/bin +copy_vhd_from_secondarystorage.sh=,0755,/opt/cloud/bin setup_heartbeat_sr.sh=..,0755,/opt/cloud/bin setup_heartbeat_file.sh=..,0755,/opt/cloud/bin check_heartbeat.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xcposs/vmops b/scripts/vm/hypervisor/xenserver/xcposs/vmops new file mode 100644 index 0000000000..1792a46773 --- /dev/null +++ b/scripts/vm/hypervisor/xenserver/xcposs/vmops @@ -0,0 +1,1476 @@ +#!/usr/bin/python +# 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. + +# Version @VERSION@ +# +# A plugin for executing script needed by vmops cloud + +import os, sys, time +import XenAPIPlugin +sys.path.extend(["/usr/lib/xcp/sm/", "/usr/local/sbin/", "/sbin/"]) +import base64 +import hostvmstats +import socket +import stat +import tempfile +import util +import subprocess +import zlib +from util import CommandException + +def echo(fn): + def wrapped(*v, **k): + name = fn.__name__ + util.SMlog("#### VMOPS enter %s ####" % name ) + res = fn(*v, **k) + util.SMlog("#### VMOPS exit %s ####" % name ) + return res + return wrapped + +@echo +def gethostvmstats(session, args): + collect_host_stats = args['collectHostStats'] + consolidation_function = args['consolidationFunction'] + interval = args['interval'] + start_time = args['startTime'] + result = hostvmstats.get_stats(session, collect_host_stats, consolidation_function, interval, start_time) + return result + +@echo +def setup_iscsi(session, args): + uuid=args['uuid'] + try: + cmd = ["b", "/opt/cloud/bin/setup_iscsi.sh", uuid] + txt = util.pread2(cmd) + except: + txt = '' + return '> DONE <' + + +@echo +def getgateway(session, args): + mgmt_ip = args['mgmtIP'] + try: + cmd = ["bash", "/opt/cloud/bin/network_info.sh", "-g", mgmt_ip] + txt = util.pread2(cmd) + except: + txt = '' + + return txt + +@echo +def preparemigration(session, args): + uuid = args['uuid'] + try: + cmd = ["/opt/cloud/bin/make_migratable.sh", uuid] + util.pread2(cmd) + txt = 'success' + except: + util.SMlog("Catch prepare migration exception" ) + txt = '' + + return txt + +@echo +def setIptables(session, args): + try: + '''cmd = ["/bin/bash", "/opt/cloud/bin/setupxenserver.sh"] + txt = util.pread2(cmd)''' + txt = 'success' + except: + util.SMlog(" setIptables execution failed " ) + txt = '' + + return txt + +@echo +def pingdomr(session, args): + host = args['host'] + port = args['port'] + socket.setdefaulttimeout(3) + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + s.connect((host,int(port))) + txt = 'success' + except: + txt = '' + + s.close() + + return txt + +@echo +def kill_copy_process(session, args): + namelabel = args['namelabel'] + try: + cmd = ["bash", "/opt/cloud/bin/kill_copy_process.sh", namelabel] + txt = util.pread2(cmd) + except: + txt = 'false' + return txt + +@echo +def pingxenserver(session, args): + txt = 'success' + return txt + +@echo +def ipassoc(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/ipassoc.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog(" ip associate failed " ) + txt = '' + + return txt + +def pingtest(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/pingtest.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog(" pingtest failed " ) + txt = '' + + return txt + +@echo +def savePassword(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/save_password_to_domr.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog(" save password to domr failed " ) + txt = '' + + return txt + +@echo +def saveDhcpEntry(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/dhcp_entry.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog(" save dhcp entry failed " ) + txt = '' + + return txt + +@echo +def lt2p_vpn(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/l2tp_vpn.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog("l2tp vpn failed " ) + txt = '' + + return txt + +@echo +def setLinkLocalIP(session, args): + brName = args['brName'] + try: + cmd = ["ip", "route", "del", "169.254.0.0/16"] + txt = util.pread2(cmd) + except: + txt = '' + try: + cmd = ["ifconfig", brName, "169.254.0.1", "netmask", "255.255.0.0"] + txt = util.pread2(cmd) + except: + + try: + cmd = ["brctl", "addbr", brName] + txt = util.pread2(cmd) + except: + pass + + try: + cmd = ["ifconfig", brName, "169.254.0.1", "netmask", "255.255.0.0"] + txt = util.pread2(cmd) + except: + pass + try: + cmd = ["ip", "route", "add", "169.254.0.0/16", "dev", brName, "src", "169.254.0.1"] + txt = util.pread2(cmd) + except: + txt = '' + txt = 'success' + return txt + +@echo +def setFirewallRule(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/call_firewall.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog(" set firewall rule failed " ) + txt = '' + + return txt + +@echo +def setLoadBalancerRule(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/call_loadbalancer.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog(" set loadbalancer rule failed " ) + txt = '' + + return txt + +@echo +def createFile(session, args): + file_path = args['filepath'] + file_contents = args['filecontents'] + + try: + f = open(file_path, "w") + f.write(file_contents) + f.close() + txt = 'success' + except: + util.SMlog(" failed to create HA proxy cfg file ") + txt = '' + + return txt + +@echo +def deleteFile(session, args): + file_path = args["filepath"] + + try: + if os.path.isfile(file_path): + os.remove(file_path) + txt = 'success' + except: + util.SMlog(" failed to remove HA proxy cfg file ") + txt = '' + + return txt + + +@echo +def networkUsage(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/networkUsage.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + except: + util.SMlog(" network usage error " ) + txt = '' + + return txt + +def get_private_nic(session, args): + vms = session.xenapi.VM.get_all() + host_uuid = args.get('host_uuid') + host = session.xenapi.host.get_by_uuid(host_uuid) + piflist = session.xenapi.host.get_PIFs(host) + mgmtnic = 'eth0' + for pif in piflist: + pifrec = session.xenapi.PIF.get_record(pif) + network = pifrec.get('network') + nwrec = session.xenapi.network.get_record(network) + if nwrec.get('name_label') == 'cloud-guest': + return pifrec.get('device') + if pifrec.get('management'): + mgmtnic = pifrec.get('device') + + return mgmtnic + +def chain_name(vm_name): + if vm_name.startswith('i-') or vm_name.startswith('r-'): + if vm_name.endswith('untagged'): + return '-'.join(vm_name.split('-')[:-1]) + return vm_name + +def chain_name_def(vm_name): + if vm_name.startswith('i-'): + if vm_name.endswith('untagged'): + return '-'.join(vm_name.split('-')[:-2]) + "-def" + return '-'.join(vm_name.split('-')[:-1]) + "-def" + return vm_name + +def egress_chain_name(vm_name): + return chain_name(vm_name) + "-eg" + +@echo +def can_bridge_firewall(session, args): + try: + util.pread2(['ebtables', '-V']) + util.pread2(['ipset', '-V']) + except: + return 'false' + + host_uuid = args.get('host_uuid') + try: + util.pread2(['iptables', '-N', 'BRIDGE-FIREWALL']) + util.pread2(['iptables', '-I', 'BRIDGE-FIREWALL', '-m', 'state', '--state', 'RELATED,ESTABLISHED', '-j', 'ACCEPT']) + util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '-p', 'udp', '--dport', '67', '--sport', '68', '-j', 'ACCEPT']) + util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '-p', 'udp', '--dport', '68', '--sport', '67', '-j', 'ACCEPT']) + util.pread2(['iptables', '-D', 'FORWARD', '-j', 'RH-Firewall-1-INPUT']) + except: + util.SMlog('Chain BRIDGE-FIREWALL already exists') + privnic = get_private_nic(session, args) + result = 'true' + try: + util.pread2(['/bin/bash', '-c', 'iptables -n -L FORWARD | grep BRIDGE-FIREWALL']) + except: + try: + util.pread2(['iptables', '-I', 'FORWARD', '-m', 'physdev', '--physdev-is-bridged', '-j', 'BRIDGE-FIREWALL']) + util.pread2(['iptables', '-A', 'FORWARD', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', privnic, '-j', 'ACCEPT']) + util.pread2(['iptables', '-A', 'FORWARD', '-j', 'DROP']) + except: + return 'false' + default_ebtables_rules() + allow_egress_traffic(session) + if not os.path.exists('/var/run/cloud'): + os.makedirs('/var/run/cloud') + if not os.path.exists('/var/cache/cloud'): + os.makedirs('/var/cache/cloud') + #get_ipset_keyword() + + cleanup_rules_for_dead_vms(session) + cleanup_rules(session, args) + + return result + +@echo +def default_ebtables_rules(): + try: + 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', 'ARP', '--arp-op', 'Request', '-j', 'ACCEPT']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'ARP', '--arp-op', 'Reply', '-j', 'ACCEPT']) + # deny mac broadcast and multicast + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '-d', 'Broadcast', '-j', 'DROP']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '-d', 'Multicast', '-j', 'DROP']) + # deny ip broadcast and multicast + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '--ip-dst', '255.255.255.255', '-j', 'DROP']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '--ip-dst', '224.0.0.0/4', '-j', 'DROP']) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv4', '-j', 'RETURN']) + # deny ipv6 + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', 'IPv6', '-j', 'DROP']) + # deny vlan + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-p', '802_1Q', '-j', 'DROP']) + # deny all others (e.g., 802.1d, CDP) + util.pread2(['ebtables', '-A', 'DEFAULT_EBTABLES', '-j', 'DROP']) + except: + util.SMlog('Chain DEFAULT_EBTABLES already exists') + + +@echo +def allow_egress_traffic(session): + devs = [] + for pif in session.xenapi.PIF.get_all(): + pif_rec = session.xenapi.PIF.get_record(pif) + vlan = pif_rec.get('VLAN') + dev = pif_rec.get('device') + if vlan == '-1': + devs.append(dev) + else: + devs.append(dev + "." + vlan) + for d in devs: + try: + util.pread2(['/bin/bash', '-c', "iptables -n -L FORWARD | grep '%s '" % d]) + except: + try: + util.pread2(['iptables', '-I', 'FORWARD', '2', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', d, '-j', 'ACCEPT']) + except: + util.SMlog("Failed to add FORWARD rule through to %s" % d) + return 'false' + return 'true' + + +def ipset(ipsetname, proto, start, end, ips): + try: + util.pread2(['ipset', '-N', ipsetname, 'iptreemap']) + except: + util.SMlog("ipset chain already exists" + ipsetname) + + result = True + ipsettmp = ''.join(''.join(ipsetname.split('-')).split('_')) + str(int(time.time()) % 1000) + + try: + util.pread2(['ipset', '-N', ipsettmp, 'iptreemap']) + except: + util.SMlog("Failed to create temp ipset, reusing old name= " + ipsettmp) + try: + util.pread2(['ipset', '-F', ipsettmp]) + except: + util.SMlog("Failed to clear old temp ipset name=" + ipsettmp) + return False + + try: + for ip in ips: + try: + util.pread2(['ipset', '-A', ipsettmp, ip]) + except CommandException, cex: + if cex.reason.rfind('already in set') == -1: + raise + except: + util.SMlog("Failed to program ipset " + ipsetname) + util.pread2(['ipset', '-F', ipsettmp]) + util.pread2(['ipset', '-X', ipsettmp]) + return False + + try: + util.pread2(['ipset', '-W', ipsettmp, ipsetname]) + except: + util.SMlog("Failed to swap ipset " + ipsetname) + result = False + + try: + util.pread2(['ipset', '-F', ipsettmp]) + util.pread2(['ipset', '-X', ipsettmp]) + except: + # if the temporary name clashes next time we'll just reuse it + util.SMlog("Failed to delete temp ipset " + ipsettmp) + + return result + +@echo +def destroy_network_rules_for_vm(session, args): + vm_name = args.pop('vmName') + vmchain = chain_name(vm_name) + vmchain_egress = egress_chain_name(vm_name) + vmchain_default = chain_name_def(vm_name) + + delete_rules_for_vm_in_bridge_firewall_chain(vm_name) + if vm_name.startswith('i-') or vm_name.startswith('r-') or vm_name.startswith('l-'): + try: + util.pread2(['iptables', '-F', vmchain_default]) + util.pread2(['iptables', '-X', vmchain_default]) + except: + util.SMlog("Ignoring failure to delete chain " + vmchain_default) + + destroy_ebtables_rules(vmchain) + + try: + util.pread2(['iptables', '-F', vmchain]) + util.pread2(['iptables', '-X', vmchain]) + except: + util.SMlog("Ignoring failure to delete ingress chain " + vmchain) + + + try: + util.pread2(['iptables', '-F', vmchain_egress]) + util.pread2(['iptables', '-X', vmchain_egress]) + except: + util.SMlog("Ignoring failure to delete egress chain " + vmchain_egress) + + remove_rule_log_for_vm(vm_name) + + if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-', 'l-'] ]: + return 'true' + + try: + setscmd = "ipset --save | grep " + vmchain + " | grep '^-N' | awk '{print $2}'" + setsforvm = util.pread2(['/bin/bash', '-c', setscmd]).split('\n') + for set in setsforvm: + if set != '': + util.pread2(['ipset', '-F', set]) + util.pread2(['ipset', '-X', set]) + except: + util.SMlog("Failed to destroy ipsets for %" % vm_name) + + + return 'true' + +@echo +def destroy_ebtables_rules(vm_chain): + + delcmd = "ebtables-save | grep " + vm_chain + " | sed 's/-A/-D/'" + delcmds = util.pread2(['/bin/bash', '-c', delcmd]).split('\n') + delcmds.pop() + for cmd in delcmds: + try: + dc = cmd.split(' ') + dc.insert(0, 'ebtables') + util.pread2(dc) + except: + util.SMlog("Ignoring failure to delete ebtables rules for vm " + vm_chain) + try: + util.pread2(['ebtables', '-F', vm_chain]) + util.pread2(['ebtables', '-X', vm_chain]) + except: + util.SMlog("Ignoring failure to delete ebtables chain for vm " + vm_chain) + +@echo +def destroy_arptables_rules(vm_chain): + delcmd = "arptables -vL FORWARD | grep " + vm_chain + " | sed 's/-i any//' | sed 's/-o any//' | awk '{print $1,$2,$3,$4}' " + delcmds = util.pread2(['/bin/bash', '-c', delcmd]).split('\n') + delcmds.pop() + for cmd in delcmds: + try: + dc = cmd.split(' ') + dc.insert(0, 'arptables') + dc.insert(1, '-D') + dc.insert(2, 'FORWARD') + util.pread2(dc) + except: + util.SMlog("Ignoring failure to delete arptables rules for vm " + vm_chain) + + try: + util.pread2(['arptables', '-F', vm_chain]) + util.pread2(['arptables', '-X', vm_chain]) + except: + util.SMlog("Ignoring failure to delete arptables chain for vm " + vm_chain) + +@echo +def default_ebtables_antispoof_rules(vm_chain, vifs, vm_ip, vm_mac): + if vm_mac == 'ff:ff:ff:ff:ff:ff': + util.SMlog("Ignoring since mac address is not valid") + return 'true' + + try: + util.pread2(['ebtables', '-N', vm_chain]) + except: + try: + util.pread2(['ebtables', '-F', vm_chain]) + except: + util.SMlog("Failed to create ebtables antispoof chain, skipping") + return 'true' + + # note all rules for packets into the bridge (-i) precede all output rules (-o) + # always start after the first rule in the FORWARD chain that jumps to DEFAULT_EBTABLES chain + try: + for vif in vifs: + util.pread2(['ebtables', '-I', 'FORWARD', '2', '-i', vif, '-j', vm_chain]) + util.pread2(['ebtables', '-A', 'FORWARD', '-o', vif, '-j', vm_chain]) + except: + util.SMlog("Failed to program default ebtables FORWARD rules for %s" % vm_chain) + return 'false' + + try: + for vif in vifs: + # only allow source mac that belongs to the vm + util.pread2(['ebtables', '-A', vm_chain, '-i', vif, '-s', '!', vm_mac, '-j', 'DROP']) + # do not allow fake dhcp responses + util.pread2(['ebtables', '-A', vm_chain, '-i', vif, '-p', 'IPv4', '--ip-proto', 'udp', '--ip-dport', '68', '-j', 'DROP']) + # do not allow snooping of dhcp requests + util.pread2(['ebtables', '-A', vm_chain, '-o', vif, '-p', 'IPv4', '--ip-proto', 'udp', '--ip-dport', '67', '-j', 'DROP']) + except: + util.SMlog("Failed to program default ebtables antispoof rules for %s" % vm_chain) + return 'false' + + return 'true' + +@echo +def default_arp_antispoof(vm_chain, vifs, vm_ip, vm_mac): + if vm_mac == 'ff:ff:ff:ff:ff:ff': + util.SMlog("Ignoring since mac address is not valid") + return 'true' + + try: + util.pread2(['arptables', '-N', vm_chain]) + except: + try: + util.pread2(['arptables', '-F', vm_chain]) + except: + util.SMlog("Failed to create arptables rule, skipping") + return 'true' + + # note all rules for packets into the bridge (-i) precede all output rules (-o) + try: + for vif in vifs: + util.pread2(['arptables', '-I', 'FORWARD', '-i', vif, '-j', vm_chain]) + util.pread2(['arptables', '-A', 'FORWARD', '-o', vif, '-j', vm_chain]) + except: + util.SMlog("Failed to program default arptables rules in FORWARD chain vm=" + vm_chain) + return 'false' + + try: + for vif in vifs: + #accept arp replies into the bridge as long as the source mac and ips match the vm + util.pread2(['arptables', '-A', vm_chain, '-i', vif, '--opcode', 'Reply', '--source-mac', vm_mac, '--source-ip', vm_ip, '-j', 'ACCEPT']) + #accept any arp requests from this vm. In the future this can be restricted to deny attacks on hosts + #also important to restrict source ip and src mac in these requests as they can be used to update arp tables on destination + util.pread2(['arptables', '-A', vm_chain, '-i', vif, '--opcode', 'Request', '--source-mac', vm_mac, '--source-ip', vm_ip, '-j', 'RETURN']) + #accept any arp requests to this vm as long as the request is for this vm's ip + util.pread2(['arptables', '-A', vm_chain, '-o', vif, '--opcode', 'Request', '--destination-ip', vm_ip, '-j', 'ACCEPT']) + #accept any arp replies to this vm as long as the mac and ip matches + util.pread2(['arptables', '-A', vm_chain, '-o', vif, '--opcode', 'Reply', '--destination-mac', vm_mac, '--destination-ip', vm_ip, '-j', 'ACCEPT']) + util.pread2(['arptables', '-A', vm_chain, '-j', 'DROP']) + + except: + util.SMlog("Failed to program default arptables rules") + return 'false' + + return 'true' + +@echo +def default_network_rules_systemvm(session, args): + vm_name = args.pop('vmName') + try: + vm = session.xenapi.VM.get_by_name_label(vm_name) + if len(vm) != 1: + return 'false' + vm_rec = session.xenapi.VM.get_record(vm[0]) + vm_vifs = vm_rec.get('VIFs') + vifnums = [session.xenapi.VIF.get_record(vif).get('device') for vif in vm_vifs] + domid = vm_rec.get('domid') + except: + util.SMlog("### Failed to get domid or vif list for vm ##" + vm_name) + return 'false' + + if domid == '-1': + util.SMlog("### Failed to get domid for vm (-1): " + vm_name) + return 'false' + + vifs = ["vif" + domid + "." + v for v in vifnums] + #vm_name = '-'.join(vm_name.split('-')[:-1]) + vmchain = chain_name(vm_name) + + + delete_rules_for_vm_in_bridge_firewall_chain(vm_name) + + try: + util.pread2(['iptables', '-N', vmchain]) + except: + util.pread2(['iptables', '-F', vmchain]) + + allow_egress_traffic(session) + + for vif in vifs: + try: + util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', vif, '-j', vmchain]) + util.pread2(['iptables', '-I', 'BRIDGE-FIREWALL', '4', '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', vif, '-j', vmchain]) + util.pread2(['iptables', '-I', vmchain, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', vif, '-j', 'RETURN']) + except: + util.SMlog("Failed to program default rules") + return 'false' + + + util.pread2(['iptables', '-A', vmchain, '-j', 'ACCEPT']) + + if write_rule_log_for_vm(vm_name, '-1', '_ignore_', domid, '_initial_', '-1') == False: + util.SMlog("Failed to log default network rules for systemvm, ignoring") + return 'true' + + +@echo +def default_network_rules(session, args): + vm_name = args.pop('vmName') + vm_ip = args.pop('vmIP') + vm_id = args.pop('vmID') + vm_mac = args.pop('vmMAC') + + try: + vm = session.xenapi.VM.get_by_name_label(vm_name) + if len(vm) != 1: + util.SMlog("### Failed to get record for vm " + vm_name) + return 'false' + vm_rec = session.xenapi.VM.get_record(vm[0]) + domid = vm_rec.get('domid') + except: + util.SMlog("### Failed to get domid for vm " + vm_name) + return 'false' + if domid == '-1': + util.SMlog("### Failed to get domid for vm (-1): " + vm_name) + return 'false' + + vif = "vif" + domid + ".0" + tap = "tap" + domid + ".0" + vifs = [vif] + try: + util.pread2(['ifconfig', tap]) + vifs.append(tap) + except: + pass + + delete_rules_for_vm_in_bridge_firewall_chain(vm_name) + + + vmchain = chain_name(vm_name) + vmchain_egress = egress_chain_name(vm_name) + vmchain_default = chain_name_def(vm_name) + + destroy_ebtables_rules(vmchain) + + + try: + util.pread2(['iptables', '-N', vmchain]) + except: + util.pread2(['iptables', '-F', vmchain]) + + try: + util.pread2(['iptables', '-N', vmchain_egress]) + except: + util.pread2(['iptables', '-F', vmchain_egress]) + + try: + util.pread2(['iptables', '-N', vmchain_default]) + except: + util.pread2(['iptables', '-F', vmchain_default]) + + try: + for v in vifs: + util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '-j', vmchain_default]) + util.pread2(['iptables', '-I', 'BRIDGE-FIREWALL', '2', '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '-j', vmchain_default]) + util.pread2(['iptables', '-A', vmchain_default, '-m', 'state', '--state', 'RELATED,ESTABLISHED', '-j', 'ACCEPT']) + #allow dhcp + for v in vifs: + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '-p', 'udp', '--dport', '67', '--sport', '68', '-j', 'ACCEPT']) + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '-p', 'udp', '--dport', '68', '--sport', '67', '-j', 'ACCEPT']) + + #don't let vm spoof its ip address + for v in vifs: + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '--source', vm_ip,'-p', 'udp', '--dport', '53', '-j', 'RETURN']) + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '--source', '!', vm_ip, '-j', 'DROP']) + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '--destination', '!', vm_ip, '-j', 'DROP']) + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '--source', vm_ip, '-j', vmchain_egress]) + + for v in vifs: + util.pread2(['iptables', '-A', vmchain_default, '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '-j', vmchain]) + except: + util.SMlog("Failed to program default rules for vm " + vm_name) + return 'false' + + default_arp_antispoof(vmchain, vifs, vm_ip, vm_mac) + default_ebtables_antispoof_rules(vmchain, vifs, vm_ip, vm_mac) + + if write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, '_initial_', '-1', vm_mac) == False: + util.SMlog("Failed to log default network rules, ignoring") + + util.SMlog("Programmed default rules for vm " + vm_name) + return 'true' + +@echo +def check_domid_changed(session, vmName): + curr_domid = '-1' + try: + vm = session.xenapi.VM.get_by_name_label(vmName) + if len(vm) != 1: + util.SMlog("### Could not get record for vm ## " + vmName) + else: + vm_rec = session.xenapi.VM.get_record(vm[0]) + curr_domid = vm_rec.get('domid') + except: + util.SMlog("### Failed to get domid for vm ## " + vmName) + + + logfilename = "/var/run/cloud/" + vmName +".log" + if not os.path.exists(logfilename): + return ['-1', curr_domid] + + lines = (line.rstrip() for line in open(logfilename)) + + [_vmName,_vmID,_vmIP,old_domid,_signature,_seqno, _vmMac] = ['_', '-1', '_', '-1', '_', '-1', 'ff:ff:ff:ff:ff:ff'] + for line in lines: + try: + [_vmName,_vmID,_vmIP,old_domid,_signature,_seqno,_vmMac] = line.split(',') + except ValueError,v: + [_vmName,_vmID,_vmIP,old_domid,_signature,_seqno] = line.split(',') + break + + return [curr_domid, old_domid] + +@echo +def delete_rules_for_vm_in_bridge_firewall_chain(vmName): + vm_name = vmName + vmchain = chain_name_def(vm_name) + + delcmd = "iptables-save | grep '\-A BRIDGE-FIREWALL' | grep " + vmchain + " | sed 's/-A/-D/'" + delcmds = util.pread2(['/bin/bash', '-c', delcmd]).split('\n') + delcmds.pop() + for cmd in delcmds: + try: + dc = cmd.split(' ') + dc.insert(0, 'iptables') + dc.pop() + util.pread2(filter(None, dc)) + except: + util.SMlog("Ignoring failure to delete rules for vm " + vmName) + + +@echo +def network_rules_for_rebooted_vm(session, vmName): + vm_name = vmName + [curr_domid, old_domid] = check_domid_changed(session, vm_name) + + if curr_domid == old_domid: + return True + + if old_domid == '-1': + return True + + if curr_domid == '-1': + return True + + util.SMlog("Found a rebooted VM -- reprogramming rules for " + vm_name) + + delete_rules_for_vm_in_bridge_firewall_chain(vm_name) + if 1 in [ vm_name.startswith(c) for c in ['r-', 's-', 'v-', 'l-'] ]: + default_network_rules_systemvm(session, {"vmName":vm_name}) + return True + + vif = "vif" + curr_domid + ".0" + tap = "tap" + curr_domid + ".0" + vifs = [vif] + try: + util.pread2(['ifconfig', tap]) + vifs.append(tap) + except: + pass + vmchain = chain_name(vm_name) + vmchain_default = chain_name_def(vm_name) + + for v in vifs: + util.pread2(['iptables', '-A', 'BRIDGE-FIREWALL', '-m', 'physdev', '--physdev-is-bridged', '--physdev-out', v, '-j', vmchain_default]) + util.pread2(['iptables', '-I', 'BRIDGE-FIREWALL', '2', '-m', 'physdev', '--physdev-is-bridged', '--physdev-in', v, '-j', vmchain_default]) + + #change antispoof rule in vmchain + try: + delcmd = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-in | sed 's/-A/-D/'" + delcmd2 = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-out | sed 's/-A/-D/'" + inscmd = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-in | grep vif | sed -r 's/vif[0-9]+.0/" + vif + "/' " + inscmd2 = "iptables-save| grep '\-A " + vmchain_default + "' | grep physdev-in | grep tap | sed -r 's/tap[0-9]+.0/" + tap + "/' " + inscmd3 = "iptables-save | grep '\-A " + vmchain_default + "' | grep physdev-out | grep vif | sed -r 's/vif[0-9]+.0/" + vif + "/' " + inscmd4 = "iptables-save| grep '\-A " + vmchain_default + "' | grep physdev-out | grep tap | sed -r 's/tap[0-9]+.0/" + tap + "/' " + + ipts = [] + for cmd in [delcmd, delcmd2, inscmd, inscmd2, inscmd3, inscmd4]: + cmds = util.pread2(['/bin/bash', '-c', cmd]).split('\n') + cmds.pop() + for c in cmds: + ipt = c.split(' ') + ipt.insert(0, 'iptables') + ipt.pop() + ipts.append(ipt) + + for ipt in ipts: + try: + util.pread2(filter(None,ipt)) + except: + util.SMlog("Failed to rewrite antispoofing rules for vm " + vm_name) + + util.pread2(['/bin/bash', '-c', 'iptables -D ' + vmchain_default + " -j " + vmchain]) + util.pread2(['/bin/bash', '-c', 'iptables -A ' + vmchain_default + " -j " + vmchain]) + except: + util.SMlog("No rules found for vm " + vm_name) + + destroy_ebtables_rules(vmchain) + destroy_arptables_rules(vmchain) + [vm_ip, vm_mac] = get_vm_mac_ip_from_log(vmchain) + default_arp_antispoof(vmchain, vifs, vm_ip, vm_mac) + default_ebtables_antispoof_rules(vmchain, vifs, vm_ip, vm_mac) + rewrite_rule_log_for_vm(vm_name, curr_domid) + return True + +def rewrite_rule_log_for_vm(vm_name, new_domid): + logfilename = "/var/run/cloud/" + vm_name +".log" + if not os.path.exists(logfilename): + return + lines = (line.rstrip() for line in open(logfilename)) + + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = ['_', '-1', '_', '-1', '_', '-1','ff:ff:ff:ff:ff:ff'] + for line in lines: + try: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = line.split(',') + break + except ValueError,v: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') + + write_rule_log_for_vm(_vmName, _vmID, _vmIP, new_domid, _signature, '-1', _vmMac) + +def get_rule_log_for_vm(session, vmName): + vm_name = vmName; + logfilename = "/var/run/cloud/" + vm_name +".log" + if not os.path.exists(logfilename): + return '' + + lines = (line.rstrip() for line in open(logfilename)) + + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = ['_', '-1', '_', '-1', '_', '-1', 'ff:ff:ff:ff:ff:ff'] + for line in lines: + try: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = line.split(',') + break + except ValueError,v: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') + + return ','.join([_vmName, _vmID, _vmIP, _domID, _signature, _seqno]) + +@echo +def get_vm_mac_ip_from_log(vm_name): + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = ['_', '-1', '0.0.0.0', '-1', '_', '-1','ff:ff:ff:ff:ff:ff'] + logfilename = "/var/run/cloud/" + vm_name +".log" + if not os.path.exists(logfilename): + return ['_', '_'] + + lines = (line.rstrip() for line in open(logfilename)) + for line in lines: + try: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = line.split(',') + break + except ValueError,v: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') + + return [ _vmIP, _vmMac] + +@echo +def get_rule_logs_for_vms(session, args): + host_uuid = args.pop('host_uuid') + try: + thishost = session.xenapi.host.get_by_uuid(host_uuid) + hostrec = session.xenapi.host.get_record(thishost) + vms = hostrec.get('resident_VMs') + except: + util.SMlog("Failed to get host from uuid " + host_uuid) + return ' ' + + result = [] + try: + for name in [session.xenapi.VM.get_name_label(x) for x in vms]: + if 1 not in [ name.startswith(c) for c in ['r-', 's-', 'v-', 'i-', 'l-'] ]: + continue + network_rules_for_rebooted_vm(session, name) + if name.startswith('i-'): + log = get_rule_log_for_vm(session, name) + result.append(log) + except: + util.SMlog("Failed to get rule logs, better luck next time!") + + return ";".join(result) + +@echo +def cleanup_rules_for_dead_vms(session): + try: + vms = session.xenapi.VM.get_all() + cleaned = 0 + for vm_name in [session.xenapi.VM.get_name_label(x) for x in vms]: + if 1 in [ vm_name.startswith(c) for c in ['r-', 'i-', 's-', 'v-', 'l-'] ]: + vm = session.xenapi.VM.get_by_name_label(vm_name) + if len(vm) != 1: + continue + vm_rec = session.xenapi.VM.get_record(vm[0]) + state = vm_rec.get('power_state') + if state != 'Running' and state != 'Paused': + util.SMlog("vm " + vm_name + " is not running, cleaning up") + destroy_network_rules_for_vm(session, {'vmName':vm_name}) + cleaned = cleaned+1 + + util.SMlog("Cleaned up rules for " + str(cleaned) + " vms") + except: + util.SMlog("Failed to cleanup rules for dead vms!") + + +@echo +def cleanup_rules(session, args): + instance = args.get('instance') + if not instance: + instance = 'VM' + resident_vms = [] + try: + hostname = util.pread2(['/bin/bash', '-c', 'hostname']).split('\n') + if len(hostname) < 1: + raise Exception('Could not find hostname of this host') + thishost = session.xenapi.host.get_by_name_label(hostname[0]) + if len(thishost) < 1: + raise Exception("Could not find host record from hostname %s of this host"%hostname[0]) + hostrec = session.xenapi.host.get_record(thishost[0]) + vms = hostrec.get('resident_VMs') + resident_vms = [session.xenapi.VM.get_name_label(x) for x in vms] + util.SMlog('cleanup_rules: found %s resident vms on this host %s' % (len(resident_vms)-1, hostname[0])) + + chainscmd = "iptables-save | grep '^:' | awk '{print $1}' | cut -d':' -f2 | sed 's/-def/-%s/'| sed 's/-eg//' | sort|uniq" % instance + chains = util.pread2(['/bin/bash', '-c', chainscmd]).split('\n') + vmchains = [ch for ch in chains if 1 in [ ch.startswith(c) for c in ['r-', 'i-', 's-', 'v-', 'l-']]] + util.SMlog('cleanup_rules: found %s iptables chains for vms on this host %s' % (len(vmchains), hostname[0])) + cleaned = 0 + cleanup = [] + for chain in vmchains: + vm = session.xenapi.VM.get_by_name_label(chain) + if len(vm) != 1: + vm = session.xenapi.VM.get_by_name_label(chain + "-untagged") + if len(vm) != 1: + util.SMlog("chain " + chain + " does not correspond to a vm, cleaning up") + cleanup.append(chain) + continue + if chain not in resident_vms: + util.SMlog("vm " + chain + " is not running, cleaning up") + cleanup.append(chain) + + for vm_name in cleanup: + destroy_network_rules_for_vm(session, {'vmName':vm_name}) + + util.SMlog("Cleaned up rules for " + str(len(cleanup)) + " chains") + return str(len(cleanup)) + except Exception, ex: + util.SMlog("Failed to cleanup rules, reason= " + str(ex)) + return '-1'; + +@echo +def check_rule_log_for_vm(vmName, vmID, vmIP, domID, signature, seqno): + vm_name = vmName; + logfilename = "/var/run/cloud/" + vm_name +".log" + if not os.path.exists(logfilename): + util.SMlog("Failed to find logfile %s" %logfilename) + return [True, True, True] + + lines = (line.rstrip() for line in open(logfilename)) + + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno,_vmMac] = ['_', '-1', '_', '-1', '_', '-1', 'ff:ff:ff:ff:ff:ff'] + try: + for line in lines: + try: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno, _vmMac] = line.split(',') + except ValueError,v: + [_vmName,_vmID,_vmIP,_domID,_signature,_seqno] = line.split(',') + break + except: + util.SMlog("Failed to parse log file for vm " + vmName) + remove_rule_log_for_vm(vmName) + return [True, True, True] + + reprogramDefault = False + if (domID != _domID) or (vmID != _vmID) or (vmIP != _vmIP): + util.SMlog("Change in default info set of vm %s" % vmName) + return [True, True, True] + else: + util.SMlog("No change in default info set of vm %s" % vmName) + + reprogramChain = False + rewriteLog = True + if (int(seqno) > int(_seqno)): + if (_signature != signature): + reprogramChain = True + util.SMlog("Seqno increased from %s to %s: reprogamming "\ + "ingress rules for vm %s" % (_seqno, seqno, vmName)) + else: + util.SMlog("Seqno increased from %s to %s: but no change "\ + "in signature for vm: skip programming ingress "\ + "rules %s" % (_seqno, seqno, vmName)) + elif (int(seqno) < int(_seqno)): + util.SMlog("Seqno decreased from %s to %s: ignoring these "\ + "ingress rules for vm %s" % (_seqno, seqno, vmName)) + rewriteLog = False + elif (signature != _signature): + util.SMlog("Seqno %s stayed the same but signature changed from "\ + "%s to %s for vm %s" % (seqno, _signature, signature, vmName)) + rewriteLog = True + reprogramChain = True + else: + util.SMlog("Seqno and signature stayed the same: %s : ignoring these "\ + "ingress rules for vm %s" % (seqno, vmName)) + rewriteLog = False + + return [reprogramDefault, reprogramChain, rewriteLog] + + +@echo +def write_rule_log_for_vm(vmName, vmID, vmIP, domID, signature, seqno, vmMac='ff:ff:ff:ff:ff:ff'): + vm_name = vmName + logfilename = "/var/run/cloud/" + vm_name +".log" + util.SMlog("Writing log to " + logfilename) + logf = open(logfilename, 'w') + output = ','.join([vmName, vmID, vmIP, domID, signature, seqno, vmMac]) + result = True + try: + logf.write(output) + logf.write('\n') + except: + util.SMlog("Failed to write to rule log file " + logfilename) + result = False + + logf.close() + + return result + +@echo +def remove_rule_log_for_vm(vmName): + vm_name = vmName + logfilename = "/var/run/cloud/" + vm_name +".log" + + result = True + try: + os.remove(logfilename) + except: + util.SMlog("Failed to delete rule log file " + logfilename) + result = False + + return result + +@echo +def inflate_rules (zipped): + return zlib.decompress(base64.b64decode(zipped)) + +@echo +def cache_ipset_keyword(): + tmpname = 'ipsetqzvxtmp' + try: + util.pread2(['/bin/bash', '-c', 'ipset -N ' + tmpname + ' iptreemap']) + except: + util.pread2(['/bin/bash', '-c', 'ipset -F ' + tmpname]) + + try: + util.pread2(['/bin/bash', '-c', 'iptables -A INPUT -m set --set ' + tmpname + ' src' + ' -j ACCEPT']) + util.pread2(['/bin/bash', '-c', 'iptables -D INPUT -m set --set ' + tmpname + ' src' + ' -j ACCEPT']) + keyword = 'set' + except: + keyword = 'match-set' + + try: + util.pread2(['/bin/bash', '-c', 'ipset -X ' + tmpname]) + except: + pass + + cachefile = "/var/cache/cloud/ipset.keyword" + util.SMlog("Writing ipset keyword to " + cachefile) + cachef = open(cachefile, 'w') + try: + cachef.write(keyword) + cachef.write('\n') + except: + util.SMlog("Failed to write to cache file " + cachef) + + cachef.close() + return keyword + +@echo +def get_ipset_keyword(): + cachefile = "/var/cache/cloud/ipset.keyword" + keyword = 'match-set' + + if not os.path.exists(cachefile): + util.SMlog("Failed to find ipset keyword cachefile %s" %cachefile) + keyword = cache_ipset_keyword() + else: + lines = (line.rstrip() for line in open(cachefile)) + for line in lines: + keyword = line + break + + return keyword + +@echo +def network_rules(session, args): + try: + vm_name = args.get('vmName') + vm_ip = args.get('vmIP') + vm_id = args.get('vmID') + vm_mac = args.get('vmMAC') + signature = args.pop('signature') + seqno = args.pop('seqno') + deflated = 'false' + if 'deflated' in args: + deflated = args.pop('deflated') + + try: + vm = session.xenapi.VM.get_by_name_label(vm_name) + if len(vm) != 1: + util.SMlog("### Could not get record for vm ## " + vm_name) + return 'false' + vm_rec = session.xenapi.VM.get_record(vm[0]) + domid = vm_rec.get('domid') + except: + util.SMlog("### Failed to get domid for vm ## " + vm_name) + return 'false' + if domid == '-1': + util.SMlog("### Failed to get domid for vm (-1): " + vm_name) + return 'false' + + vif = "vif" + domid + ".0" + tap = "tap" + domid + ".0" + vifs = [vif] + try: + util.pread2(['ifconfig', tap]) + vifs.append(tap) + except: + pass + + + reason = 'seqno_change_or_sig_change' + [reprogramDefault, reprogramChain, rewriteLog] = \ + check_rule_log_for_vm (vm_name, vm_id, vm_ip, domid, signature, seqno) + + if not reprogramDefault and not reprogramChain: + util.SMlog("No changes detected between current state and received state") + reason = 'seqno_same_sig_same' + if rewriteLog: + reason = 'seqno_increased_sig_same' + write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, signature, seqno, vm_mac) + util.SMlog("Programming network rules for vm %s seqno=%s signature=%s guestIp=%s,"\ + " do nothing, reason=%s" % (vm_name, seqno, signature, vm_ip, reason)) + return 'true' + + if not reprogramChain: + util.SMlog("###Not programming any ingress rules since no changes detected?") + return 'true' + + if reprogramDefault: + util.SMlog("Change detected in vmId or vmIp or domId, resetting default rules") + default_network_rules(session, args) + reason = 'domid_change' + + rules = args.pop('rules') + if deflated.lower() == 'true': + rules = inflate_rules (rules) + keyword = '--' + get_ipset_keyword() + lines = rules.split(' ') + + util.SMlog("Programming network rules for vm %s seqno=%s numrules=%s signature=%s guestIp=%s,"\ + " update iptables, reason=%s" % (vm_name, seqno, len(lines), signature, vm_ip, reason)) + + cmds = [] + egressrules = 0 + for line in lines: + tokens = line.split(':') + if len(tokens) != 5: + continue + type = tokens[0] + protocol = tokens[1] + start = tokens[2] + end = tokens[3] + cidrs = tokens.pop(); + ips = cidrs.split(",") + ips.pop() + allow_any = False + + if type == 'E': + vmchain = egress_chain_name(vm_name) + action = "RETURN" + direction = "dst" + egressrules = egressrules + 1 + else: + vmchain = chain_name(vm_name) + action = "ACCEPT" + direction = "src" + if '0.0.0.0/0' in ips: + i = ips.index('0.0.0.0/0') + del ips[i] + allow_any = True + range = start + ":" + end + if ips: + ipsetname = vmchain + "_" + protocol + "_" + start + "_" + end + if start == "-1": + ipsetname = vmchain + "_" + protocol + "_any" + + if ipset(ipsetname, protocol, start, end, ips) == False: + util.SMlog(" failed to create ipset for rule " + str(tokens)) + + if protocol == 'all': + iptables = ['iptables', '-I', vmchain, '-m', 'state', '--state', 'NEW', '-m', 'set', keyword, ipsetname, direction, '-j', action] + elif protocol != 'icmp': + iptables = ['iptables', '-I', vmchain, '-p', protocol, '-m', protocol, '--dport', range, '-m', 'state', '--state', 'NEW', '-m', 'set', keyword, ipsetname, direction, '-j', action] + else: + range = start + "/" + end + if start == "-1": + range = "any" + iptables = ['iptables', '-I', vmchain, '-p', 'icmp', '--icmp-type', range, '-m', 'set', keyword, ipsetname, direction, '-j', action] + + cmds.append(iptables) + util.SMlog(iptables) + + if allow_any and protocol != 'all': + if protocol != 'icmp': + iptables = ['iptables', '-I', vmchain, '-p', protocol, '-m', protocol, '--dport', range, '-m', 'state', '--state', 'NEW', '-j', action] + else: + range = start + "/" + end + if start == "-1": + range = "any" + iptables = ['iptables', '-I', vmchain, '-p', 'icmp', '--icmp-type', range, '-j', action] + cmds.append(iptables) + util.SMlog(iptables) + + vmchain = chain_name(vm_name) + util.pread2(['iptables', '-F', vmchain]) + egress_vmchain = egress_chain_name(vm_name) + util.pread2(['iptables', '-F', egress_vmchain]) + + for cmd in cmds: + util.pread2(cmd) + + if egressrules == 0 : + util.pread2(['iptables', '-A', egress_vmchain, '-j', 'RETURN']) + else: + util.pread2(['iptables', '-A', egress_vmchain, '-j', 'DROP']) + + util.pread2(['iptables', '-A', vmchain, '-j', 'DROP']) + + if write_rule_log_for_vm(vm_name, vm_id, vm_ip, domid, signature, seqno, vm_mac) == False: + return 'false' + + return 'true' + except: + util.SMlog("Failed to network rule !") + +@echo +def checkRouter(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/getRouterStatus.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + except: + util.SMlog(" check router status fail! ") + txt = '' + + return txt + +@echo +def bumpUpPriority(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/bumpUpPriority.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + txt = 'success' + except: + util.SMlog("bump up priority fail! ") + txt = '' + + return txt + +@echo +def setDNATRule(session, args): + add = args["add"] + if add == "false": + util.pread2(["iptables", "-t", "nat", "-F"]) + else: + ip = args["ip"] + port = args["port"] + util.pread2(["iptables", "-t", "nat", "-F"]) + util.pread2(["iptables", "-t", "nat", "-A", "PREROUTING", "-i", "xenbr0", "-p", "tcp", "--dport", port, "-m", "state", "--state", "NEW", "-j", "DNAT", "--to-destination", ip +":443"]) + return "" + +@echo +def createISOVHD(session, args): + # Should not create the VDI if the systemvm.iso does not exist + if not os.path.exists('/usr/share/xcp/packages/iso/systemvm.iso'): + return "Failed" + #hack for XCP on ubuntu 12.04, as can't attach iso to a vm + vdis = session.xenapi.VDI.get_by_name_label("systemvm-vdi"); + util.SMlog(vdis) + if len(vdis) > 0: + vdi_record = session.xenapi.VDI.get_record(vdis[0]) + vdi_uuid = vdi_record['uuid'] + return vdi_uuid + localsrUUid = args['uuid']; + sr = session.xenapi.SR.get_by_uuid(localsrUUid) + data = {'name_label': "systemvm-vdi", + 'SR': sr, + 'virtual_size': '50000000', + 'type': 'user', + 'sharable':False, + 'read_only':False, + 'other_config':{}, + } + vdi = session.xenapi.VDI.create(data); + vdi_record = session.xenapi.VDI.get_record(vdi) + + vdi_uuid = vdi_record['uuid'] + + vms = session.xenapi.VM.get_all() + ctrldom = None + for vm in vms: + dom0 = session.xenapi.VM.get_is_control_domain(vm) + if dom0 is False: + continue + else: + ctrldom = vm + + if ctrldom is None: + return "Failed" + + vbds = session.xenapi.VM.get_VBDs(ctrldom) + if len(vbds) == 0: + vbd = session.xenapi.VBD.create({"VDI": vdi, "VM": ctrldom, "type":"Disk", "device": "xvda4", "bootable": False, "mode": "RW", "userdevice": "4", "empty":False, + "other_config":{}, "qos_algorithm_type":"", "qos_algorithm_params":{}}) + else: + vbd = vbds[0] + + vbdr = session.xenapi.VBD.get_record(vbd) + if session.xenapi.VBD.get_currently_attached(vbd) is False: + session.xenapi.VBD.plug(vbd) + vbdr = session.xenapi.VBD.get_record(vbd) + util.pread2(["dd", "if=/usr/share/xcp/packages/iso/systemvm.iso", "of=" + "/dev/" + vbdr["device"]]) + session.xenapi.VBD.unplug(vbd) + session.xenapi.VBD.destroy(vbd) + return vdi_uuid + +@echo +def getDomRVersion(session, args): + sargs = args['args'] + cmd = sargs.split(' ') + cmd.insert(0, "/opt/cloud/bin/getDomRVersion.sh") + cmd.insert(0, "/bin/bash") + try: + txt = util.pread2(cmd) + except: + util.SMlog(" get domR version fail! ") + txt = '' + + return txt + +if __name__ == "__main__": + XenAPIPlugin.dispatch({"pingtest": pingtest, "setup_iscsi":setup_iscsi, "gethostvmstats": gethostvmstats, + "getgateway": getgateway, "preparemigration": preparemigration, + "setIptables": setIptables, "pingdomr": pingdomr, "pingxenserver": pingxenserver, + "ipassoc": ipassoc, "savePassword": savePassword, + "saveDhcpEntry": saveDhcpEntry, "setFirewallRule": setFirewallRule, + "setLoadBalancerRule": setLoadBalancerRule, "createFile": createFile, "deleteFile": deleteFile, + "networkUsage": networkUsage, "network_rules":network_rules, + "can_bridge_firewall":can_bridge_firewall, "default_network_rules":default_network_rules, + "destroy_network_rules_for_vm":destroy_network_rules_for_vm, + "default_network_rules_systemvm":default_network_rules_systemvm, + "get_rule_logs_for_vms":get_rule_logs_for_vms, + "setLinkLocalIP":setLinkLocalIP, "lt2p_vpn":lt2p_vpn, + "cleanup_rules":cleanup_rules, "checkRouter":checkRouter, + "bumpUpPriority":bumpUpPriority, "getDomRVersion":getDomRVersion, + "kill_copy_process":kill_copy_process, + "createISOVHD":createISOVHD, + "setDNATRule":setDNATRule}) diff --git a/scripts/vm/hypervisor/xenserver/xcposs/vmopsSnapshot b/scripts/vm/hypervisor/xenserver/xcposs/vmopsSnapshot new file mode 100644 index 0000000000..53f31a99ee --- /dev/null +++ b/scripts/vm/hypervisor/xenserver/xcposs/vmopsSnapshot @@ -0,0 +1,601 @@ +#!/usr/bin/python +# 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. + +# Version @VERSION@ +# +# A plugin for executing script needed by vmops cloud + +import os, sys, time +import XenAPIPlugin +sys.path.append("/usr/lib/xcp/sm/") +import SR, VDI, SRCommand, util, lvutil +from util import CommandException +import vhdutil +import shutil +import lvhdutil +import errno +import subprocess +import xs_errors +import cleanup +import stat +import random + +VHD_UTIL = 'vhd-util' +VHD_PREFIX = 'VHD-' +CLOUD_DIR = '/run/cloud_mount' + +def echo(fn): + def wrapped(*v, **k): + name = fn.__name__ + util.SMlog("#### VMOPS enter %s ####" % name ) + res = fn(*v, **k) + util.SMlog("#### VMOPS exit %s ####" % name ) + return res + return wrapped + + +@echo +def create_secondary_storage_folder(session, args): + local_mount_path = None + + util.SMlog("create_secondary_storage_folder, args: " + str(args)) + + try: + try: + # Mount the remote resource folder locally + remote_mount_path = args["remoteMountPath"] + local_mount_path = os.path.join(CLOUD_DIR, util.gen_uuid()) + mount(remote_mount_path, local_mount_path) + + # Create the new folder + new_folder = local_mount_path + "/" + args["newFolder"] + if not os.path.isdir(new_folder): + current_umask = os.umask(0) + os.makedirs(new_folder) + os.umask(current_umask) + except OSError, (errno, strerror): + errMsg = "create_secondary_storage_folder failed: errno: " + str(errno) + ", strerr: " + strerror + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + except: + errMsg = "create_secondary_storage_folder failed." + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + finally: + if local_mount_path != None: + # Unmount the local folder + umount(local_mount_path) + # Remove the local folder + os.system("rmdir " + local_mount_path) + + return "1" + +@echo +def delete_secondary_storage_folder(session, args): + local_mount_path = None + + util.SMlog("delete_secondary_storage_folder, args: " + str(args)) + + try: + try: + # Mount the remote resource folder locally + remote_mount_path = args["remoteMountPath"] + local_mount_path = os.path.join(CLOUD_DIR, util.gen_uuid()) + mount(remote_mount_path, local_mount_path) + + # Delete the specified folder + folder = local_mount_path + "/" + args["folder"] + if os.path.isdir(folder): + os.system("rm -f " + folder + "/*") + os.system("rmdir " + folder) + except OSError, (errno, strerror): + errMsg = "delete_secondary_storage_folder failed: errno: " + str(errno) + ", strerr: " + strerror + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + except: + errMsg = "delete_secondary_storage_folder failed." + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + finally: + if local_mount_path != None: + # Unmount the local folder + umount(local_mount_path) + # Remove the local folder + os.system("rmdir " + local_mount_path) + + return "1" + +@echo +def post_create_private_template(session, args): + local_mount_path = None + try: + try: + # get local template folder + templatePath = args["templatePath"] + local_mount_path = os.path.join(CLOUD_DIR, util.gen_uuid()) + mount(templatePath, local_mount_path) + # Retrieve args + filename = args["templateFilename"] + name = args["templateName"] + description = args["templateDescription"] + checksum = args["checksum"] + file_size = args["size"] + virtual_size = args["virtualSize"] + template_id = args["templateId"] + + # Create the template.properties file + template_properties_install_path = local_mount_path + "/template.properties" + f = open(template_properties_install_path, "w") + f.write("filename=" + filename + "\n") + f.write("vhd=true\n") + f.write("id=" + template_id + "\n") + f.write("vhd.filename=" + filename + "\n") + f.write("public=false\n") + f.write("uniquename=" + name + "\n") + f.write("vhd.virtualsize=" + virtual_size + "\n") + f.write("virtualsize=" + virtual_size + "\n") + f.write("checksum=" + checksum + "\n") + f.write("hvm=true\n") + f.write("description=" + description + "\n") + f.write("vhd.size=" + str(file_size) + "\n") + f.write("size=" + str(file_size) + "\n") + f.close() + util.SMlog("Created template.properties file") + + # Set permissions + permissions = stat.S_IREAD | stat.S_IWRITE | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH + os.chmod(template_properties_install_path, permissions) + util.SMlog("Set permissions on template and template.properties") + + except: + errMsg = "post_create_private_template failed." + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + + finally: + if local_mount_path != None: + # Unmount the local folder + umount(local_mount_path) + # Remove the local folder + os.system("rmdir " + local_mount_path) + return "1" + +def isfile(path, isISCSI): + errMsg = '' + exists = True + if isISCSI: + exists = checkVolumeAvailablility(path) + else: + exists = os.path.isfile(path) + + if not exists: + errMsg = "File " + path + " does not exist." + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + return errMsg + +def copyfile(fromFile, toFile, isISCSI): + util.SMlog("Starting to copy " + fromFile + " to " + toFile) + errMsg = '' + try: + cmd = ['dd', 'if=' + fromFile, 'of=' + toFile, 'bs=4M'] + txt = util.pread2(cmd) + except: + try: + os.system("rm -f " + toFile) + except: + txt = '' + txt = '' + errMsg = "Error while copying " + fromFile + " to " + toFile + " in secondary storage" + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + + util.SMlog("Successfully copied " + fromFile + " to " + toFile) + return errMsg + +def chdir(path): + try: + os.chdir(path) + except OSError, (errno, strerror): + errMsg = "Unable to chdir to " + path + " because of OSError with errno: " + str(errno) + " and strerr: " + strerror + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + util.SMlog("Chdired to " + path) + return + +def scanParent(path): + # Do a scan for the parent for ISCSI volumes + # Note that the parent need not be visible on the XenServer + parentUUID = '' + try: + lvName = os.path.basename(path) + dirname = os.path.dirname(path) + vgName = os.path.basename(dirname) + vhdInfo = vhdutil.getVHDInfoLVM(lvName, lvhdutil.extractUuid, vgName) + parentUUID = vhdInfo.parentUuid + except: + errMsg = "Could not get vhd parent of " + path + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + return parentUUID + +def getParent(path, isISCSI): + parentUUID = '' + try : + if isISCSI: + parentUUID = vhdutil.getParent(path, lvhdutil.extractUuid) + else: + parentUUID = vhdutil.getParent(path, cleanup.FileVDI.extractUuid) + except: + errMsg = "Could not get vhd parent of " + path + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + return parentUUID + +def getParentOfSnapshot(snapshotUuid, primarySRPath, isISCSI): + snapshotVHD = getVHD(snapshotUuid, isISCSI) + snapshotPath = os.path.join(primarySRPath, snapshotVHD) + + baseCopyUuid = '' + if isISCSI: + checkVolumeAvailablility(snapshotPath) + baseCopyUuid = scanParent(snapshotPath) + else: + baseCopyUuid = getParent(snapshotPath, isISCSI) + + util.SMlog("Base copy of snapshotUuid: " + snapshotUuid + " is " + baseCopyUuid) + return baseCopyUuid + +def setParent(parent, child): + try: + cmd = [VHD_UTIL, "modify", "-p", parent, "-n", child] + txt = util.pread2(cmd) + except: + errMsg = "Unexpected error while trying to set parent of " + child + " to " + parent + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + util.SMlog("Successfully set parent of " + child + " to " + parent) + return + +def rename(originalVHD, newVHD): + try: + os.rename(originalVHD, newVHD) + except OSError, (errno, strerror): + errMsg = "OSError while renaming " + origiinalVHD + " to " + newVHD + "with errno: " + str(errno) + " and strerr: " + strerror + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + return + +def makedirs(path): + if not os.path.isdir(path): + try: + os.makedirs(path) + except OSError, (errno, strerror): + umount(path) + if os.path.isdir(path): + return + errMsg = "OSError while creating " + path + " with errno: " + str(errno) + " and strerr: " + strerror + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + return + +def mount(remoteDir, localDir): + makedirs(localDir) + options = "soft,tcp,timeo=133,retrans=1" + try: + cmd = ['mount', '-o', options, remoteDir, localDir] + txt = util.pread2(cmd) + except: + txt = '' + errMsg = "Unexpected error while trying to mount " + remoteDir + " to " + localDir + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + util.SMlog("Successfully mounted " + remoteDir + " to " + localDir) + + return + +def umount(localDir): + try: + cmd = ['umount', localDir] + util.pread2(cmd) + except CommandException: + errMsg = "CommandException raised while trying to umount " + localDir + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + + util.SMlog("Successfully unmounted " + localDir) + return + +def mountSnapshotsDir(secondaryStorageMountPath, localMountPointPath, path): + # The aim is to mount secondaryStorageMountPath on + # And create / dir on it, if it doesn't exist already. + # Assuming that secondaryStorageMountPath exists remotely + + # Just mount secondaryStorageMountPath//SecondaryStorageHost/ everytime + # Never unmount. + # path is like "snapshots/account/volumeId", we mount secondary_storage:/snapshots + relativeDir = path.split("/")[0] + restDir = "/".join(path.split("/")[1:]) + snapshotsDir = os.path.join(secondaryStorageMountPath, relativeDir) + + makedirs(localMountPointPath) + # if something is not mounted already on localMountPointPath, + # mount secondaryStorageMountPath on localMountPath + if os.path.ismount(localMountPointPath): + # There is more than one secondary storage per zone. + # And we are mounting each sec storage under a zone-specific directory + # So two secondary storage snapshot dirs will never get mounted on the same point on the same XenServer. + util.SMlog("The remote snapshots directory has already been mounted on " + localMountPointPath) + else: + mount(snapshotsDir, localMountPointPath) + + # Create accountId/instanceId dir on localMountPointPath, if it doesn't exist + backupsDir = os.path.join(localMountPointPath, restDir) + makedirs(backupsDir) + return backupsDir + +def unmountAll(path): + try: + for dir in os.listdir(path): + if dir.isdigit(): + util.SMlog("Unmounting Sub-Directory: " + dir) + localMountPointPath = os.path.join(path, dir) + umount(localMountPointPath) + except: + util.SMlog("Ignoring the error while trying to unmount the snapshots dir") + +@echo +def unmountSnapshotsDir(session, args): + dcId = args['dcId'] + localMountPointPath = os.path.join(CLOUD_DIR, dcId) + localMountPointPath = os.path.join(localMountPointPath, "snapshots") + unmountAll(localMountPointPath) + try: + umount(localMountPointPath) + except: + util.SMlog("Ignoring the error while trying to unmount the snapshots dir.") + + return "1" + +def getPrimarySRPath(session, primaryStorageSRUuid, isISCSI): + sr = session.xenapi.SR.get_by_uuid(primaryStorageSRUuid) + srrec = session.xenapi.SR.get_record(sr) + srtype = srrec["type"] + if srtype == "file": + pbd = session.xenapi.SR.get_PBDs(sr)[0] + pbdrec = session.xenapi.PBD.get_record(pbd) + primarySRPath = pbdrec["device_config"]["location"] + return primarySRPath + elif isISCSI: + primarySRDir = lvhdutil.VG_PREFIX + primaryStorageSRUuid + return os.path.join(lvhdutil.VG_LOCATION, primarySRDir) + else: + return os.path.join(SR.MOUNT_BASE, primaryStorageSRUuid) + +def getBackupVHD(UUID): + return UUID + '.' + SR.DEFAULT_TAP + +def getVHD(UUID, isISCSI): + if isISCSI: + return VHD_PREFIX + UUID + else: + return UUID + '.' + SR.DEFAULT_TAP + +def getIsTrueString(stringValue): + booleanValue = False + if (stringValue and stringValue == 'true'): + booleanValue = True + return booleanValue + +def makeUnavailable(uuid, primarySRPath, isISCSI): + if not isISCSI: + return + VHD = getVHD(uuid, isISCSI) + path = os.path.join(primarySRPath, VHD) + manageAvailability(path, '-an') + return + +def manageAvailability(path, value): + if path.__contains__("/var/run/sr-mount"): + return + util.SMlog("Setting availability of " + path + " to " + value) + try: + cmd = ['/usr/sbin/lvchange', value, path] + util.pread2(cmd) + except: #CommandException, (rc, cmdListStr, stderr): + #errMsg = "CommandException thrown while executing: " + cmdListStr + " with return code: " + str(rc) + " and stderr: " + stderr + errMsg = "Unexpected exception thrown by lvchange" + util.SMlog(errMsg) + if value == "-ay": + # Raise an error only if we are trying to make it available. + # Just warn if we are trying to make it unavailable after the + # snapshot operation is done. + raise xs_errors.XenError(errMsg) + return + + +def checkVolumeAvailablility(path): + try: + if not isVolumeAvailable(path): + # The VHD file is not available on XenSever. The volume is probably + # inactive or detached. + # Do lvchange -ay to make it available on XenServer + manageAvailability(path, '-ay') + except: + errMsg = "Could not determine status of ISCSI path: " + path + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + + success = False + i = 0 + while i < 6: + i = i + 1 + # Check if the vhd is actually visible by checking for the link + # set isISCSI to true + success = isVolumeAvailable(path) + if success: + util.SMlog("Made vhd: " + path + " available and confirmed that it is visible") + break + + # Sleep for 10 seconds before checking again. + time.sleep(10) + + # If not visible within 1 min fail + if not success: + util.SMlog("Could not make vhd: " + path + " available despite waiting for 1 minute. Does it exist?") + + return success + +def isVolumeAvailable(path): + # Check if iscsi volume is available on this XenServer. + status = "0" + try: + p = subprocess.Popen(["/bin/bash", "-c", "if [ -L " + path + " ]; then echo 1; else echo 0;fi"], stdout=subprocess.PIPE) + status = p.communicate()[0].strip("\n") + except: + errMsg = "Could not determine status of ISCSI path: " + path + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + + return (status == "1") + +def getVhdParent(session, args): + util.SMlog("getParent with " + str(args)) + primaryStorageSRUuid = args['primaryStorageSRUuid'] + snapshotUuid = args['snapshotUuid'] + isISCSI = getIsTrueString(args['isISCSI']) + + primarySRPath = getPrimarySRPath(session, primaryStorageSRUuid, isISCSI) + util.SMlog("primarySRPath: " + primarySRPath) + + baseCopyUuid = getParentOfSnapshot(snapshotUuid, primarySRPath, isISCSI) + + return baseCopyUuid + + +def backupSnapshot(session, args): + util.SMlog("Called backupSnapshot with " + str(args)) + primaryStorageSRUuid = args['primaryStorageSRUuid'] + secondaryStorageMountPath = args['secondaryStorageMountPath'] + snapshotUuid = args['snapshotUuid'] + prevBackupUuid = args['prevBackupUuid'] + backupUuid = args['backupUuid'] + isISCSI = getIsTrueString(args['isISCSI']) + path = args['path'] + localMountPoint = args['localMountPoint'] + primarySRPath = getPrimarySRPath(session, primaryStorageSRUuid, isISCSI) + util.SMlog("primarySRPath: " + primarySRPath) + + baseCopyUuid = getParentOfSnapshot(snapshotUuid, primarySRPath, isISCSI) + baseCopyVHD = getVHD(baseCopyUuid, isISCSI) + baseCopyPath = os.path.join(primarySRPath, baseCopyVHD) + util.SMlog("Base copy path: " + baseCopyPath) + + + # Mount secondary storage mount path on XenServer along the path + # /var/run/sr-mount//snapshots/ and create / dir + # on it. + backupsDir = mountSnapshotsDir(secondaryStorageMountPath, localMountPoint, path) + util.SMlog("Backups dir " + backupsDir) + prevBackupUuid = prevBackupUuid.split("/")[-1] + # Check existence of snapshot on primary storage + isfile(baseCopyPath, isISCSI) + if prevBackupUuid: + # Check existence of prevBackupFile + prevBackupVHD = getBackupVHD(prevBackupUuid) + prevBackupFile = os.path.join(backupsDir, prevBackupVHD) + isfile(prevBackupFile, False) + + # copy baseCopyPath to backupsDir with new uuid + backupVHD = getBackupVHD(backupUuid) + backupFile = os.path.join(backupsDir, backupVHD) + util.SMlog("Back up " + baseCopyUuid + " to Secondary Storage as " + backupUuid) + copyfile(baseCopyPath, backupFile, isISCSI) + vhdutil.setHidden(backupFile, False) + + # Because the primary storage is always scanned, the parent of this base copy is always the first base copy. + # We don't want that, we want a chain of VHDs each of which is a delta from the previous. + # So set the parent of the current baseCopyVHD to prevBackupVHD + if prevBackupUuid: + # If there was a previous snapshot + setParent(prevBackupFile, backupFile) + + txt = "1#" + backupUuid + return txt + +@echo +def deleteSnapshotBackup(session, args): + util.SMlog("Calling deleteSnapshotBackup with " + str(args)) + secondaryStorageMountPath = args['secondaryStorageMountPath'] + backupUUID = args['backupUUID'] + path = args['path'] + localMountPoint = args['localMountPoint'] + + backupsDir = mountSnapshotsDir(secondaryStorageMountPath, localMountPoint, path) + # chdir to the backupsDir for convenience + chdir(backupsDir) + + backupVHD = getBackupVHD(backupUUID) + util.SMlog("checking existence of " + backupVHD) + + # The backupVHD is on secondary which is NFS and not ISCSI. + if not os.path.isfile(backupVHD): + util.SMlog("backupVHD " + backupVHD + "does not exist. Not trying to delete it") + return "1" + util.SMlog("backupVHD " + backupVHD + " exists.") + + # Just delete the backupVHD + try: + os.remove(backupVHD) + except OSError, (errno, strerror): + errMsg = "OSError while removing " + backupVHD + " with errno: " + str(errno) + " and strerr: " + strerror + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + + return "1" + +@echo +def revert_memory_snapshot(session, args): + util.SMlog("Calling revert_memory_snapshot with " + str(args)) + vmName = args['vmName'] + snapshotUUID = args['snapshotUUID'] + oldVmUuid = args['oldVmUuid'] + snapshotMemory = args['snapshotMemory'] + hostUUID = args['hostUUID'] + try: + cmd = '''xe vbd-list vm-uuid=%s | grep 'vdi-uuid' | grep -v 'not in database' | sed -e 's/vdi-uuid ( RO)://g' ''' % oldVmUuid + vdiUuids = os.popen(cmd).read().split() + cmd2 = '''xe vm-param-get param-name=power-state uuid=''' + oldVmUuid + if os.popen(cmd2).read().split()[0] != 'halted': + os.system("xe vm-shutdown force=true vm=" + vmName) + os.system("xe vm-destroy uuid=" + oldVmUuid) + os.system("xe snapshot-revert snapshot-uuid=" + snapshotUUID) + if snapshotMemory == 'true': + os.system("xe vm-resume vm=" + vmName + " on=" + hostUUID) + for vdiUuid in vdiUuids: + os.system("xe vdi-destroy uuid=" + vdiUuid) + except OSError, (errno, strerror): + errMsg = "OSError while reverting vm " + vmName + " to snapshot " + snapshotUUID + " with errno: " + str(errno) + " and strerr: " + strerror + util.SMlog(errMsg) + raise xs_errors.XenError(errMsg) + return "0" + +if __name__ == "__main__": + XenAPIPlugin.dispatch({"getVhdParent":getVhdParent, "create_secondary_storage_folder":create_secondary_storage_folder, "delete_secondary_storage_folder":delete_secondary_storage_folder, "post_create_private_template":post_create_private_template, "backupSnapshot": backupSnapshot, "deleteSnapshotBackup": deleteSnapshotBackup, "unmountSnapshotsDir": unmountSnapshotsDir, "revert_memory_snapshot":revert_memory_snapshot}) + + diff --git a/scripts/vm/hypervisor/xenserver/xcpserver/patch b/scripts/vm/hypervisor/xenserver/xcpserver/patch index 2376424ff5..0f9d9a0cec 100644 --- a/scripts/vm/hypervisor/xenserver/xcpserver/patch +++ b/scripts/vm/hypervisor/xenserver/xcpserver/patch @@ -31,7 +31,6 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins -hostvmstats.py=..,0755,/opt/xensource/sm systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver56/patch b/scripts/vm/hypervisor/xenserver/xenserver56/patch index 16dcb5746a..e24136d8ea 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56/patch @@ -30,7 +30,6 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins -hostvmstats.py=..,0755,/opt/xensource/sm systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch index 11bda07369..5e1559898d 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver56fp1/patch @@ -30,7 +30,6 @@ NFSSR.py=/opt/xensource/sm vmops=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins -hostvmstats.py=..,0755,/opt/xensource/sm systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver60/patch b/scripts/vm/hypervisor/xenserver/xenserver60/patch index 662327b6a8..84472a608d 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver60/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver60/patch @@ -34,7 +34,6 @@ cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins vmopsSnapshot=..,0755,/etc/xapi.d/plugins -hostvmstats.py=..,0755,/opt/xensource/sm systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/hypervisor/xenserver/xenserver62/patch b/scripts/vm/hypervisor/xenserver/xenserver62/patch index 05c619b70c..13f4f939c5 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver62/patch +++ b/scripts/vm/hypervisor/xenserver/xenserver62/patch @@ -34,7 +34,6 @@ cloudstack_plugins.conf=..,0644,/etc/xensource cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins ovstunnel=..,0755,/etc/xapi.d/plugins cloud-plugin-storage=,0755,/etc/xapi.d/plugins -hostvmstats.py=..,0755,/opt/xensource/sm systemvm.iso=../../../../../vms,0644,/opt/xensource/packages/iso id_rsa.cloud=../../../systemvm,0600,/root/.ssh network_info.sh=..,0755,/opt/cloud/bin @@ -50,7 +49,6 @@ setup_heartbeat_file.sh=..,0755,/opt/cloud/bin check_heartbeat.sh=..,0755,/opt/cloud/bin xenheartbeat.sh=..,0755,/opt/cloud/bin launch_hb.sh=..,0755,/opt/cloud/bin -vhd-util=..,0755,/opt/cloud/bin upgrade_snapshot.sh=..,0755,/opt/cloud/bin cloud-clean-vlan.sh=..,0755,/opt/cloud/bin cloud-prepare-upgrade.sh=..,0755,/opt/cloud/bin diff --git a/scripts/vm/network/security_group.py b/scripts/vm/network/security_group.py index 1d94de3d60..704b279820 100755 --- a/scripts/vm/network/security_group.py +++ b/scripts/vm/network/security_group.py @@ -978,7 +978,7 @@ def addFWFramework(brname): execute("iptables -N " + brfwin) try: - refs = execute("""iptables -n -L " + brfw + " | awk '/%s(.*)references/ {gsub(/\(/, "") ;print $3}'""" % brfw).strip() + refs = execute("""iptables -n -L %s | awk '/%s(.*)references/ {gsub(/\(/, "") ;print $3}'""" % (brfw,brfw)).strip() if refs == "0": execute("iptables -I FORWARD -i " + brname + " -j DROP") execute("iptables -I FORWARD -o " + brname + " -j DROP") diff --git a/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml b/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml index 91401e3354..479dc9ce96 100644 --- a/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml +++ b/server/resources/META-INF/cloudstack/core/spring-server-core-misc-context.xml @@ -52,7 +52,9 @@ - + + + diff --git a/server/src/com/cloud/acl/DomainChecker.java b/server/src/com/cloud/acl/DomainChecker.java index cb6921d9fa..9ee65db935 100755 --- a/server/src/com/cloud/acl/DomainChecker.java +++ b/server/src/com/cloud/acl/DomainChecker.java @@ -19,6 +19,7 @@ import javax.ejb.Local; import javax.inject.Inject; +import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import org.apache.cloudstack.acl.ControlledEntity; @@ -50,6 +51,8 @@ @Local(value = SecurityChecker.class) public class DomainChecker extends AdapterBase implements SecurityChecker { + public static final Logger s_logger = Logger.getLogger(DomainChecker.class); + @Inject DomainDao _domainDao; @Inject @@ -101,6 +104,15 @@ public boolean checkAccess(User user, Domain domain) throws PermissionDeniedExce @Override public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType) throws PermissionDeniedException { + + if (caller.getId() == Account.ACCOUNT_ID_SYSTEM || _accountService.isRootAdmin(caller.getId())) { + // no need to make permission checks if the system/root admin makes the call + if (s_logger.isTraceEnabled()) { + s_logger.trace("No need to make permission check for System/RootAdmin account, returning true"); + } + return true; + } + if (entity instanceof VirtualMachineTemplate) { VirtualMachineTemplate template = (VirtualMachineTemplate)entity; @@ -328,6 +340,34 @@ else if (_accountService.isDomainAdmin(account.getId())) { @Override public boolean checkAccess(Account caller, ControlledEntity entity, AccessType accessType, String action) throws PermissionDeniedException { + + if (action != null && ("SystemCapability".equals(action))) { + if (caller != null && caller.getType() == Account.ACCOUNT_TYPE_ADMIN) { + return true; + } + + } else if (action != null && ("DomainCapability".equals(action))) { + if (caller != null && caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) { + return true; + } + } else if (action != null && ("DomainResourceCapability".equals(action))) { + if (caller != null && caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { + return true; + } + } return checkAccess(caller, entity, accessType); } + + @Override + public boolean checkAccess(Account caller, AccessType accessType, String action, ControlledEntity... entities) + throws PermissionDeniedException { + + // returns true only if access to all entities is granted + for (ControlledEntity entity : entities) { + if (!checkAccess(caller, entity, accessType, action)) { + return false; + } + } + return true; + } } diff --git a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java index 37368846da..3bd5c94377 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java @@ -243,7 +243,7 @@ protected List allocateTo(DeploymentPlan plan, ServiceOffering offering, V // We will try to reorder the host lists such that we give priority to hosts that have // the minimums to support a VM's requirements - hosts = prioritizeHosts(template, hosts); + hosts = prioritizeHosts(template, offering, hosts); if (s_logger.isDebugEnabled()) { s_logger.debug("Found " + hosts.size() + " hosts for allocation after prioritization: " + hosts); @@ -278,10 +278,12 @@ protected List allocateTo(DeploymentPlan plan, ServiceOffering offering, V } // Check if GPU device is required by offering and host has the availability - if ((offeringDetails = _serviceOfferingDetailsDao.findDetail(serviceOfferingId, GPU.Keys.vgpuType.toString())) != null - && !_resourceMgr.isGPUDeviceAvailable(host.getId(), offeringDetails.getValue())){ - s_logger.info("Host name: " + host.getName() + ", hostId: "+ host.getId() +" does not have required GPU devices available"); - continue; + if ((offeringDetails = _serviceOfferingDetailsDao.findDetail(serviceOfferingId, GPU.Keys.vgpuType.toString())) != null) { + ServiceOfferingDetailsVO groupName = _serviceOfferingDetailsDao.findDetail(serviceOfferingId, GPU.Keys.pciDevice.toString()); + if(!_resourceMgr.isGPUDeviceAvailable(host.getId(), groupName.getValue(), offeringDetails.getValue())){ + s_logger.info("Host name: " + host.getName() + ", hostId: "+ host.getId() +" does not have required GPU devices available"); + continue; + } } int cpu_requested = offering.getCpu() * offering.getSpeed(); @@ -353,7 +355,7 @@ public boolean isVirtualMachineUpgradable(VirtualMachine vm, ServiceOffering off return true; } - protected List prioritizeHosts(VMTemplateVO template, List hosts) { + protected List prioritizeHosts(VMTemplateVO template, ServiceOffering offering, List hosts) { if (template == null) { return hosts; } @@ -416,6 +418,22 @@ protected List prioritizeHosts(VMTemplateVO template, List gpuEnabledHosts = new ArrayList(); + // Check for GPU enabled hosts. + for (Host host : prioritizedHosts) { + if (_resourceMgr.isHostGpuEnabled(host.getId())) { + gpuEnabledHosts.add(host); + } + } + // Move GPU enabled hosts to the end of list + if(!gpuEnabledHosts.isEmpty()) { + prioritizedHosts.removeAll(gpuEnabledHosts); + prioritizedHosts.addAll(gpuEnabledHosts); + } + } return prioritizedHosts; } diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 432eb941ab..2da107f24f 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -1091,6 +1091,16 @@ public static List listUserVMsByHostId(long hostId) { return s_userVmDao.listByHostId(hostId); } + public static List listUserVMsByNetworkId(long networkId) { + return s_userVmDao.listByNetworkIdAndStates(networkId, VirtualMachine.State.Running, + VirtualMachine.State.Starting, VirtualMachine.State.Stopping, VirtualMachine.State.Unknown, + VirtualMachine.State.Migrating); + } + + public static List listDomainRoutersByNetworkId(long networkId) { + return s_domainRouterDao.findByNetwork(networkId); + } + public static List listZones() { return s_zoneDao.listAll(); } @@ -1819,7 +1829,7 @@ public static Map getResourceDetails(long resourceId, ResourceOb } public static boolean isAdmin(Account account) { - return s_accountService.isAdmin(account.getType()); + return s_accountService.isAdmin(account.getId()); } public static List listResourceTagViewByResourceUUID(String resourceUUID, ResourceObjectType resourceType) { diff --git a/server/src/com/cloud/api/ApiDispatcher.java b/server/src/com/cloud/api/ApiDispatcher.java index 95074e24bb..3026beeba1 100755 --- a/server/src/com/cloud/api/ApiDispatcher.java +++ b/server/src/com/cloud/api/ApiDispatcher.java @@ -23,10 +23,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.acl.InfrastructureEntity; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.BaseAsyncCreateCmd; @@ -41,7 +37,6 @@ import com.cloud.api.dispatch.DispatchChainFactory; import com.cloud.api.dispatch.DispatchTask; import com.cloud.event.EventTypes; -import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.utils.ReflectUtil; import com.cloud.vm.VirtualMachine; @@ -83,23 +78,6 @@ public void dispatchCreateCmd(final BaseAsyncCreateCmd cmd, final Map entitiesToAccess) { - Account caller = CallContext.current().getCallingAccount(); - - APICommand commandAnnotation = cmd.getClass().getAnnotation(APICommand.class); - String apiName = commandAnnotation != null ? commandAnnotation.name() : null; - - if (!entitiesToAccess.isEmpty()) { - for (Object entity : entitiesToAccess.keySet()) { - if (entity instanceof ControlledEntity) { - _accountMgr.checkAccess(caller, entitiesToAccess.get(entity), false, apiName, (ControlledEntity) entity); - } else if (entity instanceof InfrastructureEntity) { - //FIXME: Move this code in adapter, remove code from Account manager - } - } - } - } - public void dispatch(final BaseCmd cmd, final Map params, final boolean execute) throws Exception { // Let the chain of responsibility dispatch gradually standardDispatchChain.dispatch(new DispatchTask(cmd, params)); diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index a37bf7b2d4..1155d1ffc1 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -1811,7 +1811,7 @@ public AsyncJobResponse queryJobResult(QueryAsyncJobResultCmd cmd) { throw new PermissionDeniedException("Account " + caller + " is not authorized to see job id=" + job.getId()); } } else if (_accountMgr.isDomainAdmin(caller.getId())) { - _accountMgr.checkAccess(caller, null, true, jobOwner); + _accountMgr.checkAccess(caller, null, jobOwner); } return createAsyncJobResponse(_jobMgr.queryJob(cmd.getId(), true)); @@ -1901,6 +1901,7 @@ public NetworkOfferingResponse createNetworkOfferingResponse(NetworkOffering off response.setNetworkRate(ApiDBUtils.getNetworkRate(offering.getId())); response.setEgressDefaultPolicy(offering.getEgressDefaultPolicy()); response.setConcurrentConnections(offering.getConcurrentConnections()); + response.setSupportsStrechedL2Subnet(offering.getSupportsStrechedL2()); Long so = null; if (offering.getServiceOfferingId() != null) { so = offering.getServiceOfferingId(); @@ -2204,6 +2205,18 @@ public NetworkResponse createNetworkResponse(ResponseView view, Network network) } } + response.setStrechedL2Subnet(network.isStrechedL2Network()); + if (network.isStrechedL2Network()) { + Set networkSpannedZones = new HashSet(); + List vmInstances = new ArrayList(); + vmInstances.addAll(ApiDBUtils.listUserVMsByNetworkId(network.getId())); + vmInstances.addAll(ApiDBUtils.listDomainRoutersByNetworkId(network.getId())); + for (VirtualMachine vm : vmInstances) { + DataCenter vmZone = ApiDBUtils.findZoneById(vm.getDataCenterId()); + networkSpannedZones.add(vmZone.getUuid()); + } + response.setNetworkSpannedZones(networkSpannedZones); + } response.setObjectName("network"); return response; } @@ -2766,6 +2779,7 @@ public VpcOfferingResponse createVpcOfferingResponse(VpcOffering offering) { response.setIsDefault(offering.isDefault()); response.setState(offering.getState().name()); response.setSupportsDistributedRouter(offering.supportsDistributedRouter()); + response.setSupportsRegionLevelVpc(offering.offersRegionLevelVPC()); Map> serviceProviderMap = ApiDBUtils.listVpcOffServices(offering.getId()); List serviceResponses = new ArrayList(); @@ -2809,6 +2823,7 @@ public VpcResponse createVpcResponse(ResponseView view, Vpc vpc) { response.setNetworkDomain(vpc.getNetworkDomain()); response.setForDisplay(vpc.isDisplay()); response.setUsesDistributedRouter(vpc.usesDistributedRouter()); + response.setRegionLevelVpc(vpc.isRegionLevelVpc()); Map> serviceProviderMap = ApiDBUtils.listVpcOffServices(vpc.getVpcOfferingId()); List serviceResponses = new ArrayList(); diff --git a/server/src/com/cloud/api/dispatch/ParamGenericValidationWorker.java b/server/src/com/cloud/api/dispatch/ParamGenericValidationWorker.java index 7a73b8aef9..d6b0cf26bf 100644 --- a/server/src/com/cloud/api/dispatch/ParamGenericValidationWorker.java +++ b/server/src/com/cloud/api/dispatch/ParamGenericValidationWorker.java @@ -80,9 +80,17 @@ public void handle(final DispatchTask task) { final StringBuilder errorMsg = new StringBuilder(ERROR_MSG_PREFIX); boolean foundUnknownParam = false; - for (final Object paramName : params.keySet()) { - if (!expectedParamNames.contains(paramName)) { - errorMsg.append(" ").append(paramName); + for (final Object actualParamName : params.keySet()) { + // If none of the expected params matches, we have an unknown param + boolean matchedCurrentParam = false; + for (final String expectedName : expectedParamNames) { + if (expectedName.equalsIgnoreCase((String) actualParamName)) { + matchedCurrentParam = true; + break; + } + } + if (!matchedCurrentParam) { + errorMsg.append(" ").append(actualParamName); foundUnknownParam= true; } } diff --git a/server/src/com/cloud/api/dispatch/ParamProcessWorker.java b/server/src/com/cloud/api/dispatch/ParamProcessWorker.java index e9bdd8b107..6eef3d6aca 100644 --- a/server/src/com/cloud/api/dispatch/ParamProcessWorker.java +++ b/server/src/com/cloud/api/dispatch/ParamProcessWorker.java @@ -37,16 +37,17 @@ import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.InfrastructureEntity; +import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ACL; +import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseAsyncCreateCmd; import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.BaseCmd.CommandType; import org.apache.cloudstack.api.EntityReference; import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.BaseCmd.CommandType; import org.apache.cloudstack.api.command.admin.resource.ArchiveAlertsCmd; import org.apache.cloudstack.api.command.admin.resource.DeleteAlertsCmd; import org.apache.cloudstack.api.command.user.event.ArchiveEventsCmd; @@ -54,7 +55,11 @@ import org.apache.cloudstack.api.command.user.event.ListEventsCmd; import org.apache.cloudstack.context.CallContext; +import com.cloud.dc.DataCenter; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.PermissionDeniedException; +import com.cloud.offering.DiskOffering; +import com.cloud.offering.ServiceOffering; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.utils.DateUtil; @@ -71,6 +76,17 @@ public class ParamProcessWorker implements DispatchWorker { @Inject protected EntityManager _entityMgr; + List _secChecker; + + public List getSecChecker() { + return _secChecker; + } + + @Inject + public void setSecChecker(List secChecker) { + _secChecker = secChecker; + } + @Override public void handle(final DispatchTask task) { processParameters(task.getCmd(), task.getParams()); @@ -130,71 +146,62 @@ public void processParameters(final BaseCmd cmd, final Map params) { final CommandType fieldType = parameterAnnotation.type(); if (checkAccess != null) { - // Verify that caller can perform actions in behalf of vm owner - //acumulate all Controlled Entities together. - - //parse the array of resource types and in case of map check access on key or value or both as specified in @acl - //implement external dao for classes that need findByName - //for maps, specify access to be checkd on key or value. + // Verify that caller can perform actions in behalf of vm + // owner acumulate all Controlled Entities together. + // parse the array of resource types and in case of map + // check access on key or value or both as specified in @acl + // implement external dao for classes that need findByName + // for maps, specify access to be checkd on key or value. + // Find the controlled entity DBid by uuid - // find the controlled entity DBid by uuid if (parameterAnnotation.entityType() != null) { final Class[] entityList = parameterAnnotation.entityType()[0].getAnnotation(EntityReference.class).value(); - for (final Class entity : entityList) { - // Check if the parameter type is a single - // Id or list of id's/name's - switch (fieldType) { - case LIST: - final CommandType listType = parameterAnnotation.collectionType(); - switch (listType) { - case LONG: - case UUID: - final List listParam = (List)field.get(cmd); - for (final Long entityId : listParam) { + // Check if the parameter type is a single + // Id or list of id's/name's + switch (fieldType) { + case LIST: + final CommandType listType = parameterAnnotation.collectionType(); + switch (listType) { + case LONG: + case UUID: + final List listParam = (List) field.get(cmd); + for (final Long entityId : listParam) { + for (final Class entity : entityList) { final Object entityObj = _entityMgr.findById(entity, entityId); - entitiesToAccess.put(entityObj, checkAccess.accessType()); + if(entityObj != null){ + entitiesToAccess.put(entityObj, checkAccess.accessType()); + break; + } } - break; - /* - * case STRING: List listParam = - * new ArrayList(); listParam = - * (List)field.get(cmd); for(String - * entityName: listParam){ - * ControlledEntity entityObj = - * (ControlledEntity - * )daoClassInstance(entityId); - * entitiesToAccess.add(entityObj); } - * break; - */ - default: - break; - } - break; - case LONG: - case UUID: - final Object entityObj = _entityMgr.findById(entity, (Long)field.get(cmd)); - entitiesToAccess.put(entityObj, checkAccess.accessType()); - break; - default: - break; - } - - if (ControlledEntity.class.isAssignableFrom(entity)) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("ControlledEntity name is:" + entity.getName()); + } + break; + /* + * case STRING: List listParam = new + * ArrayList(); listParam = + * (List)field.get(cmd); for(String entityName: + * listParam){ ControlledEntity entityObj = + * (ControlledEntity )daoClassInstance(entityId); + * entitiesToAccess.add(entityObj); } break; + */ + default: + break; } - } - - if (InfrastructureEntity.class.isAssignableFrom(entity)) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("InfrastructureEntity name is:" + entity.getName()); + break; + case LONG: + case UUID: + for (final Class entity : entityList) { + final Object entityObj = _entityMgr.findById(entity, (Long) field.get(cmd)); + if(entityObj != null){ + entitiesToAccess.put(entityObj, checkAccess.accessType()); + break; + } } - } + break; + default: + break; } - } - } } catch (final IllegalArgumentException e) { @@ -214,27 +221,100 @@ public void processParameters(final BaseCmd cmd, final Map params) { private void doAccessChecks(final BaseCmd cmd, final Map entitiesToAccess) { - final Account caller = CallContext.current().getCallingAccount(); - final Account owner = _accountMgr.getActiveAccountById(cmd.getEntityOwnerId()); - - if (cmd instanceof BaseAsyncCreateCmd) { - //check that caller can access the owner account. - _accountMgr.checkAccess(caller, null, true, owner); + Account caller = CallContext.current().getCallingAccount(); + Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); + if (owner == null) { + owner = caller; } + APICommand commandAnnotation = cmd.getClass().getAnnotation(APICommand.class); + + String apiName = commandAnnotation != null ? commandAnnotation.name() : null; + if (!entitiesToAccess.isEmpty()) { - //check that caller can access the owner account. - _accountMgr.checkAccess(caller, null, true, owner); - for (final Object entity : entitiesToAccess.keySet()) { + List entitiesToOperate = new ArrayList(); + for (Object entity : entitiesToAccess.keySet()) { if (entity instanceof ControlledEntity) { - _accountMgr.checkAccess(caller, entitiesToAccess.get(entity), true, (ControlledEntity)entity); + + if (AccessType.OperateEntry == entitiesToAccess.get(entity)) { + entitiesToOperate.add((ControlledEntity) entity); + } else { + _accountMgr.checkAccess(owner, entitiesToAccess.get(entity), apiName, + (ControlledEntity) entity); + } } else if (entity instanceof InfrastructureEntity) { - //FIXME: Move this code in adapter, remove code from Account manager + if (entity instanceof DataCenter) { + checkZoneAccess(owner, (DataCenter)entity); + } else if (entity instanceof ServiceOffering) { + checkServiceOfferingAccess(owner, (ServiceOffering)entity); + } else if (entity instanceof DiskOffering) { + checkDiskOfferingAccess(owner, (DiskOffering)entity); + } + } + } + + if (!entitiesToOperate.isEmpty()) { + _accountMgr.checkAccess(owner, AccessType.OperateEntry, apiName, + entitiesToOperate.toArray(new ControlledEntity[entitiesToOperate.size()])); + } + + } + } + + private void checkDiskOfferingAccess(Account caller, DiskOffering dof) { + for (SecurityChecker checker : _secChecker) { + if (checker.checkAccess(caller, dof)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Access granted to " + caller + " to disk offering:" + dof.getId() + " by " + + checker.getName()); } + return; + } else { + throw new PermissionDeniedException("Access denied to " + caller + " by " + checker.getName()); } } + + assert false : "How can all of the security checkers pass on checking this caller?"; + throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to disk offering:" + + dof.getId()); } + private void checkServiceOfferingAccess(Account caller, ServiceOffering sof) { + for (SecurityChecker checker : _secChecker) { + if (checker.checkAccess(caller, sof)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Access granted to " + caller + " to service offering:" + sof.getId() + " by " + + checker.getName()); + } + return; + } else { + throw new PermissionDeniedException("Access denied to " + caller + " by " + checker.getName()); + } + } + + assert false : "How can all of the security checkers pass on checking this caller?"; + throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to service offering:" + + sof.getId()); + } + + private void checkZoneAccess(Account caller, DataCenter zone) { + for (SecurityChecker checker : _secChecker) { + if (checker.checkAccess(caller, zone)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Access granted to " + caller + " to zone:" + zone.getId() + " by " + + checker.getName()); + } + return; + } else { + throw new PermissionDeniedException("Access denied to " + caller + " by " + checker.getName() + + " for zone " + zone.getId()); + } + } + + assert false : "How can all of the security checkers pass on checking this caller?"; + throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to zone:" + + zone.getId()); + } @SuppressWarnings({"unchecked", "rawtypes"}) private void setFieldValue(final Field field, final BaseCmd cmdObj, final Object paramObj, final Parameter annotation) throws IllegalArgumentException, ParseException { diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index b932d422db..5fb8a3eb02 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -92,6 +92,7 @@ import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreCapabilities; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateState; @@ -684,7 +685,7 @@ private Pair, Integer> searchForVmGroupsInternal(ListV cmd.getDomainId(), cmd.isRecursive(), null); _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedDomains, permittedAccounts, permittedResources, domainIdRecursiveListProject, cmd.listAll(), false, "listInstanceGroups"); - Long domainId = domainIdRecursiveListProject.first(); + // Long domainId = domainIdRecursiveListProject.first(); Boolean isRecursive = domainIdRecursiveListProject.second(); ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); @@ -776,7 +777,7 @@ private Pair, Integer> searchForUserVMsInternal(ListVMsCmd cm Object keyword = cmd.getKeyword(); boolean isAdmin = false; boolean isRootAdmin = false; - if (_accountMgr.isAdmin(caller.getType())) { + if (_accountMgr.isAdmin(caller.getId())) { isAdmin = true; } if (_accountMgr.isRootAdmin(caller.getId())) { @@ -1005,7 +1006,7 @@ private Pair, Integer> searchForSecurityGroupsInternal if (userVM == null) { throw new InvalidParameterValueException("Unable to list network groups for virtual machine instance " + instanceId + "; instance not found."); } - _accountMgr.checkAccess(caller, null, true, userVM); + _accountMgr.checkAccess(caller, null, userVM); return listSecurityGroupRulesByVM(instanceId.longValue(), cmd.getStartIndex(), cmd.getPageSizeVal()); } @@ -1278,7 +1279,7 @@ private Pair, Integer> listProjectsInternal(ListProjectsCmd sb.select(null, Func.DISTINCT, sb.entity().getId()); // select distinct // ids - if (_accountMgr.isAdmin(caller.getType())) { + if (_accountMgr.isAdmin(caller.getId())) { if (domainId != null) { DomainVO domain = _domainDao.findById(domainId); if (domain == null) { @@ -1482,7 +1483,7 @@ public Pair, Integer> listProjectAccountsInternal(Lis // verify permissions - only accounts belonging to the project can list // project's account - if (!_accountMgr.isAdmin(caller.getType()) && _projectAccountDao.findByProjectIdAccountId(projectId, caller.getAccountId()) == null) { + if (!_accountMgr.isAdmin(caller.getId()) && _projectAccountDao.findByProjectIdAccountId(projectId, caller.getAccountId()) == null) { throw new PermissionDeniedException("Account " + caller + " is not authorized to list users of the project id=" + projectId); } @@ -1643,6 +1644,28 @@ public ListResponse searchForVolumes(ListVolumesCmd cmd) { List volumeResponses = ViewResponseHelper.createVolumeResponse(respView, result.first().toArray( new VolumeJoinVO[result.first().size()])); + for(VolumeResponse vr : volumeResponses) { + String poolId = vr.getStoragePoolId(); + if (poolId == null) { + continue; + } + + DataStore store = dataStoreManager.getPrimaryDataStore(poolId); + if (store == null) { + continue; + } + + DataStoreDriver driver = store.getDriver(); + if (driver == null) { + continue; + } + + Map caps = driver.getCapabilities(); + if (caps != null) { + boolean quiescevm = Boolean.parseBoolean(caps.get(DataStoreCapabilities.VOLUME_SNAPSHOT_QUIESCEVM.toString())); + vr.setNeedQuiescevm(quiescevm); + } + } response.setResponses(volumeResponses, result.second()); return response; } @@ -1825,7 +1848,7 @@ private Pair, Integer> searchForAccountsInternal(ListAccount throw new InvalidParameterValueException("Unable to find account by id " + accountId); } - _accountMgr.checkAccess(caller, null, true, account); + _accountMgr.checkAccess(caller, null, account); } if (domainId != null) { @@ -1841,18 +1864,18 @@ private Pair, Integer> searchForAccountsInternal(ListAccount if (account == null || account.getId() == Account.ACCOUNT_ID_SYSTEM) { throw new InvalidParameterValueException("Unable to find account by name " + accountName + " in domain " + domainId); } - _accountMgr.checkAccess(caller, null, true, account); + _accountMgr.checkAccess(caller, null, account); } } if (accountId == null) { - if (_accountMgr.isAdmin(caller.getType()) && listAll && domainId == null) { + if (_accountMgr.isAdmin(caller.getId()) && listAll && domainId == null) { listForDomain = true; isRecursive = true; if (domainId == null) { domainId = caller.getDomainId(); } - } else if (_accountMgr.isAdmin(caller.getType()) && domainId != null) { + } else if (_accountMgr.isAdmin(caller.getId()) && domainId != null) { listForDomain = true; } else { accountId = caller.getAccountId(); @@ -2466,7 +2489,7 @@ private Pair, Integer> searchForServiceOfferingsInte throw ex; } - _accountMgr.checkAccess(caller, null, true, vmInstance); + _accountMgr.checkAccess(caller, null, vmInstance); ServiceOfferingVO offering = _srvOfferingDao.findByIdIncludingRemoved(vmInstance.getId(), vmInstance.getServiceOfferingId()); sc.addAnd("id", SearchCriteria.Op.NEQ, offering.getId()); @@ -2891,7 +2914,7 @@ private Pair, Integer> searchForTemplatesInternal(Long temp // if template is not public, perform permission check here if (!template.isPublicTemplate() && !_accountMgr.isRootAdmin(caller.getId())) { Account owner = _accountMgr.getAccount(template.getAccountId()); - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); } // if templateId is specified, then we will just use the id to @@ -3159,7 +3182,7 @@ public Pair, Integer> listAffinityGroupsInternal(Long if (userVM == null) { throw new InvalidParameterValueException("Unable to list affinity groups for virtual machine instance " + vmId + "; instance not found."); } - _accountMgr.checkAccess(caller, null, true, userVM); + _accountMgr.checkAccess(caller, null, userVM); return listAffinityGroupsByVM(vmId.longValue(), startIndex, pageSize); } diff --git a/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java index 6c890fc830..9a4b38efbb 100644 --- a/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java @@ -108,7 +108,13 @@ public HostResponse newHostResponse(HostJoinVO host, EnumSet detail for (VGPUTypesVO vgpuType : vgpuTypes) { VgpuResponse vgpuResponse = new VgpuResponse(); vgpuResponse.setName(vgpuType.getVgpuType()); - vgpuResponse.setCapacity(vgpuType.getRemainingCapacity()); + vgpuResponse.setVideoRam(vgpuType.getVideoRam()); + vgpuResponse.setMaxHeads(vgpuType.getMaxHeads()); + vgpuResponse.setMaxResolutionX(vgpuType.getMaxResolutionX()); + vgpuResponse.setMaxResolutionY(vgpuType.getMaxResolutionY()); + vgpuResponse.setMaxVgpuPerPgpu(vgpuType.getMaxVgpuPerPgpu()); + vgpuResponse.setRemainingCapacity(vgpuType.getRemainingCapacity()); + vgpuResponse.setmaxCapacity(vgpuType.getMaxCapacity()); vgpus.add(vgpuResponse); } gpuResponse.setVgpu(vgpus); diff --git a/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java index 1cab6e8040..80ef0f6ed7 100644 --- a/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/TemplateJoinDaoImpl.java @@ -302,7 +302,7 @@ public TemplateResponse newIsoResponse(TemplateJoinVO iso) { Account caller = CallContext.current().getCallingAccount(); boolean isAdmin = false; - if ((caller == null) || _accountService.isAdmin(caller.getType())) { + if ((caller == null) || _accountService.isAdmin(caller.getId())) { isAdmin = true; } diff --git a/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java b/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java index f659ed95bb..bcd0fdcbb9 100644 --- a/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java +++ b/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java @@ -24,7 +24,7 @@ import javax.persistence.Table; import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.acl.IAMEntityType; +import org.apache.cloudstack.affinity.AffinityGroup; import com.cloud.vm.VirtualMachine; @@ -194,8 +194,8 @@ public ControlledEntity.ACLType getAclType() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.AffinityGroup; + public Class getEntityType() { + return AffinityGroup.class; } } diff --git a/server/src/com/cloud/api/query/vo/AsyncJobJoinVO.java b/server/src/com/cloud/api/query/vo/AsyncJobJoinVO.java index 7889b760a1..be85c2a62b 100644 --- a/server/src/com/cloud/api/query/vo/AsyncJobJoinVO.java +++ b/server/src/com/cloud/api/query/vo/AsyncJobJoinVO.java @@ -25,8 +25,8 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.ApiCommandJobType; +import org.apache.cloudstack.framework.jobs.AsyncJob; import com.cloud.utils.db.GenericDao; @@ -203,8 +203,8 @@ public String getInstanceUuid() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.AsyncJob; + public Class getEntityType() { + return AsyncJob.class; } @Override diff --git a/server/src/com/cloud/api/query/vo/DomainRouterJoinVO.java b/server/src/com/cloud/api/query/vo/DomainRouterJoinVO.java index ac32859ea1..79eb3bfb70 100644 --- a/server/src/com/cloud/api/query/vo/DomainRouterJoinVO.java +++ b/server/src/com/cloud/api/query/vo/DomainRouterJoinVO.java @@ -26,13 +26,12 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.network.Network.GuestType; import com.cloud.network.Networks.TrafficType; import com.cloud.network.router.VirtualRouter; import com.cloud.network.router.VirtualRouter.RedundantState; import com.cloud.utils.db.GenericDao; +import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; @Entity @@ -514,7 +513,7 @@ public VirtualRouter.Role getRole() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VirtualMachine; + public Class getEntityType() { + return VirtualMachine.class; } } diff --git a/server/src/com/cloud/api/query/vo/EventJoinVO.java b/server/src/com/cloud/api/query/vo/EventJoinVO.java index b6b023ef6e..8fba938876 100644 --- a/server/src/com/cloud/api/query/vo/EventJoinVO.java +++ b/server/src/com/cloud/api/query/vo/EventJoinVO.java @@ -25,8 +25,7 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - +import com.cloud.event.Event; import com.cloud.event.Event.State; import com.cloud.utils.db.GenericDao; @@ -227,7 +226,7 @@ public boolean getDisplay() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Event; + public Class getEntityType() { + return Event.class; } } diff --git a/server/src/com/cloud/api/query/vo/InstanceGroupJoinVO.java b/server/src/com/cloud/api/query/vo/InstanceGroupJoinVO.java index 98d1a523e7..857cebf75f 100644 --- a/server/src/com/cloud/api/query/vo/InstanceGroupJoinVO.java +++ b/server/src/com/cloud/api/query/vo/InstanceGroupJoinVO.java @@ -23,9 +23,8 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.utils.db.GenericDao; +import com.cloud.vm.InstanceGroup; @Entity @Table(name = "instance_group_view") @@ -160,7 +159,7 @@ public Date getCreated() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.InstanceGroup; + public Class getEntityType() { + return InstanceGroup.class; } } diff --git a/server/src/com/cloud/api/query/vo/ProjectInvitationJoinVO.java b/server/src/com/cloud/api/query/vo/ProjectInvitationJoinVO.java index ba619a9a08..8b4918561c 100644 --- a/server/src/com/cloud/api/query/vo/ProjectInvitationJoinVO.java +++ b/server/src/com/cloud/api/query/vo/ProjectInvitationJoinVO.java @@ -25,8 +25,7 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - +import com.cloud.projects.ProjectInvitation; import com.cloud.projects.ProjectInvitation.State; import com.cloud.utils.db.GenericDao; @@ -164,7 +163,7 @@ public String getDomainPath() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.ProjectInvitation; + public Class getEntityType() { + return ProjectInvitation.class; } } diff --git a/server/src/com/cloud/api/query/vo/ResourceTagJoinVO.java b/server/src/com/cloud/api/query/vo/ResourceTagJoinVO.java index e1b8b812ae..2c1ff47509 100644 --- a/server/src/com/cloud/api/query/vo/ResourceTagJoinVO.java +++ b/server/src/com/cloud/api/query/vo/ResourceTagJoinVO.java @@ -23,8 +23,7 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - +import com.cloud.server.ResourceTag; import com.cloud.server.ResourceTag.ResourceObjectType; @Entity @@ -182,7 +181,7 @@ public String getCustomer() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.ResourceTag; + public Class getEntityType() { + return ResourceTag.class; } } diff --git a/server/src/com/cloud/api/query/vo/SecurityGroupJoinVO.java b/server/src/com/cloud/api/query/vo/SecurityGroupJoinVO.java index 3c9e3bf87a..69604e8286 100644 --- a/server/src/com/cloud/api/query/vo/SecurityGroupJoinVO.java +++ b/server/src/com/cloud/api/query/vo/SecurityGroupJoinVO.java @@ -23,8 +23,7 @@ import javax.persistence.Id; import javax.persistence.Table; -import org.apache.cloudstack.acl.IAMEntityType; - +import com.cloud.network.security.SecurityGroup; import com.cloud.network.security.SecurityRule.SecurityRuleType; import com.cloud.server.ResourceTag.ResourceObjectType; @@ -306,7 +305,7 @@ public String getTagCustomer() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.SecurityGroup; + public Class getEntityType() { + return SecurityGroup.class; } } diff --git a/server/src/com/cloud/api/query/vo/TemplateJoinVO.java b/server/src/com/cloud/api/query/vo/TemplateJoinVO.java index de0da2f1e5..834a9cedd0 100644 --- a/server/src/com/cloud/api/query/vo/TemplateJoinVO.java +++ b/server/src/com/cloud/api/query/vo/TemplateJoinVO.java @@ -27,7 +27,6 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; import com.cloud.hypervisor.Hypervisor.HypervisorType; @@ -35,6 +34,7 @@ import com.cloud.storage.ScopeType; import com.cloud.storage.Storage; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.template.VirtualMachineTemplate; import com.cloud.template.VirtualMachineTemplate.State; import com.cloud.utils.db.GenericDao; @@ -544,7 +544,7 @@ public State getTemplateState() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VirtualMachineTemplate; + public Class getEntityType() { + return VirtualMachineTemplate.class; } } diff --git a/server/src/com/cloud/api/query/vo/UserVmJoinVO.java b/server/src/com/cloud/api/query/vo/UserVmJoinVO.java index fcee393207..f3f48fc9ae 100644 --- a/server/src/com/cloud/api/query/vo/UserVmJoinVO.java +++ b/server/src/com/cloud/api/query/vo/UserVmJoinVO.java @@ -28,8 +28,6 @@ import javax.persistence.Table; import javax.persistence.Transient; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.Network.GuestType; import com.cloud.network.Networks.TrafficType; @@ -913,7 +911,7 @@ public String getDetailValue() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.VirtualMachine; + public Class getEntityType() { + return VirtualMachine.class; } } diff --git a/server/src/com/cloud/api/query/vo/VolumeJoinVO.java b/server/src/com/cloud/api/query/vo/VolumeJoinVO.java index 289b0b85af..8165d68f80 100644 --- a/server/src/com/cloud/api/query/vo/VolumeJoinVO.java +++ b/server/src/com/cloud/api/query/vo/VolumeJoinVO.java @@ -27,8 +27,6 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; -import org.apache.cloudstack.acl.IAMEntityType; - import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.server.ResourceTag.ResourceObjectType; import com.cloud.storage.Storage; @@ -578,7 +576,7 @@ public String getChainInfo() { } @Override - public IAMEntityType getEntityType() { - return IAMEntityType.Volume; + public Class getEntityType() { + return Volume.class; } } diff --git a/server/src/com/cloud/api/response/SecurityGroupResultObject.java b/server/src/com/cloud/api/response/SecurityGroupResultObject.java index 66ba487641..c2cd423bef 100644 --- a/server/src/com/cloud/api/response/SecurityGroupResultObject.java +++ b/server/src/com/cloud/api/response/SecurityGroupResultObject.java @@ -22,7 +22,6 @@ import java.util.Map; import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.InternalIdentity; import com.cloud.api.ApiDBUtils; @@ -212,7 +211,7 @@ public static List transposeNetworkGroups(List getEntityType() { + return SecurityGroup.class; } } diff --git a/server/src/com/cloud/capacity/CapacityManagerImpl.java b/server/src/com/cloud/capacity/CapacityManagerImpl.java index 69e8cfa169..cef019ddff 100755 --- a/server/src/com/cloud/capacity/CapacityManagerImpl.java +++ b/server/src/com/cloud/capacity/CapacityManagerImpl.java @@ -182,6 +182,10 @@ public boolean stop() { @DB @Override public boolean releaseVmCapacity(VirtualMachine vm, final boolean moveFromReserved, final boolean moveToReservered, final Long hostId) { + if (hostId == null) { + return true; + } + final ServiceOfferingVO svo = _offeringsDao.findById(vm.getId(), vm.getServiceOfferingId()); CapacityVO capacityCpu = _capacityDao.findByHostIdType(hostId, Capacity.CAPACITY_TYPE_CPU); CapacityVO capacityMemory = _capacityDao.findByHostIdType(hostId, Capacity.CAPACITY_TYPE_MEMORY); diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index f2fe68a78a..a02050ff54 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -1803,6 +1803,23 @@ public enum Config { "Timeout to echo baremetal security group agent, in seconds, the provisioning process will be treated as a failure", null), + BaremetalIpmiLanInterface( + "Advanced", + ManagementServer.class, + String.class, + "baremetal.ipmi.lan.interface", + "default", + "option specified in -I option of impitool. candidates are: open/bmc/lipmi/lan/lanplus/free/imb, see ipmitool man page for details. default valule 'default' means using default option of ipmitool", + null), + + BaremetalIpmiRetryTimes("Advanced", + ManagementServer.class, + String.class, + "baremetal.ipmi.fail.retry", + "5", + "ipmi interface will be temporary out of order after power opertions(e.g. cycle, on), it leads following commands fail immediately. The value specifies retry times before accounting it as real failure", + null), + ApiLimitEnabled("Advanced", ManagementServer.class, Boolean.class, "api.throttling.enabled", "false", "Enable/disable Api rate limit", null), ApiLimitInterval("Advanced", ManagementServer.class, Integer.class, "api.throttling.interval", "1", "Time interval (in seconds) to reset API count", null), ApiLimitMax("Advanced", ManagementServer.class, Integer.class, "api.throttling.max", "25", "Max allowed number of APIs within fixed interval", null), @@ -1898,6 +1915,15 @@ public enum Config { "the interval cloudstack sync with UCS manager for available blades in case user remove blades from chassis without notifying CloudStack", null), + RedundantRouterVrrpInterval( + "Advanced", + NetworkOrchestrationService.class, + Integer.class, + "router.redundant.vrrp.interval", + "1", + "seconds between VRRP broadcast. It would 3 times broadcast fail to trigger fail-over mechanism of redundant router", + null), + ManagementServerVendor("Advanced", ManagementServer.class, String.class, "mgt.server.vendor", "ACS", "the vendor of management server", null); private final String _category; diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 9b9bd13d26..30afd7bab6 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -153,6 +153,7 @@ import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao; import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO; import com.cloud.network.dao.PhysicalNetworkVO; +import com.cloud.network.element.NetworkElement; import com.cloud.network.rules.LoadBalancerContainer.Scheme; import com.cloud.network.vpc.VpcManager; import com.cloud.offering.DiskOffering; @@ -2083,47 +2084,33 @@ protected ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, offering.setHypervisorSnapshotReserve(hypervisorSnapshotReserve); List detailsVO = null; - if (details != null) { + if (details != null) { // Check if the user has passed the gpu-type before passing the VGPU type - if (!details.containsKey(GPU.Keys.pciDevice.toString()) && details.containsKey(GPU.Keys.vgpuType.toString())) { - throw new InvalidParameterValueException("Please specify the gpu type"); + if (!details.containsKey(GPU.Keys.pciDevice.toString()) || !details.containsKey(GPU.Keys.vgpuType.toString())) { + throw new InvalidParameterValueException("Please specify the pciDevice and vgpuType correctly."); } detailsVO = new ArrayList(); - for (Entry detailEntry : details.entrySet()) { + for (Entry detailEntry : details.entrySet()) { String value = null; if (detailEntry.getKey().equals(GPU.Keys.pciDevice.toString())) { - for (GPU.Type type : GPU.Type.values()) { - if (detailEntry.getValue().equals(type.toString())) { - value = detailEntry.getValue(); - } - } - if (value == null) { - throw new InvalidParameterValueException("Please specify valid gpu type"); + if (detailEntry.getValue() == null) { + throw new InvalidParameterValueException("Please specify a GPU Card."); } } if (detailEntry.getKey().equals(GPU.Keys.vgpuType.toString())) { - if (details.get(GPU.Keys.pciDevice.toString()).equals(GPU.Type.GPU_Passthrough.toString())) { - throw new InvalidParameterValueException("vgpuTypes are supported only with vGPU pciDevice"); - } if (detailEntry.getValue() == null) { - throw new InvalidParameterValueException("With vGPU as pciDevice, vGPUType value cannot be null"); + throw new InvalidParameterValueException("vGPUType value cannot be null"); } for (GPU.vGPUType entry : GPU.vGPUType.values()) { if (detailEntry.getValue().equals(entry.getType())) { value = entry.getType(); } } - if (value == null || detailEntry.getValue().equals(GPU.vGPUType.passthrough.getType())) { + if (value == null) { throw new InvalidParameterValueException("Please specify valid vGPU type"); } } - detailsVO.add(new ServiceOfferingDetailsVO(offering.getId(), detailEntry.getKey(), detailEntry.getValue(), true)); - } - // If pciDevice type is passed, put the default VGPU type as 'passthrough' - if (details.containsKey(GPU.Keys.pciDevice.toString()) - && !details.containsKey(GPU.Keys.vgpuType.toString())) { - detailsVO.add(new ServiceOfferingDetailsVO(offering.getId(), - GPU.Keys.vgpuType.toString(), GPU.vGPUType.passthrough.getType(), true)); + detailsVO.add(new ServiceOfferingDetailsVO(offering.getId(), detailEntry.getKey(), detailEntry.getValue(), true)); } } @@ -3814,10 +3801,21 @@ public NetworkOffering createNetworkOffering(CreateNetworkOfferingCmd cmd) { } validateStaticNatServiceCapablities(staticNatServiceCapabilityMap); + // validate the 'Connectivity' service capabilities specified in the network offering, if 'Connectivity' service + // is in the supported services of network offering + Map connectivityServiceCapabilityMap = cmd.getServiceCapabilities(Service.Connectivity); + if (!serviceProviderMap.containsKey(Service.Connectivity) && + (connectivityServiceCapabilityMap != null && !connectivityServiceCapabilityMap.isEmpty())) { + throw new InvalidParameterValueException("Capabilities for 'Connectivity' service can be specified " + + "only when Connectivity service is enabled for network offering."); + } + validateConnectivityServiceCapablities(serviceProviderMap.get(Service.Connectivity), connectivityServiceCapabilityMap); + Map> serviceCapabilityMap = new HashMap>(); serviceCapabilityMap.put(Service.Lb, lbServiceCapabilityMap); serviceCapabilityMap.put(Service.SourceNat, sourceNatServiceCapabilityMap); serviceCapabilityMap.put(Service.StaticNat, staticNatServiceCapabilityMap); + serviceCapabilityMap.put(Service.Connectivity, connectivityServiceCapabilityMap); // if Firewall service is missing, add Firewall service/provider // combination @@ -3952,6 +3950,36 @@ void validateStaticNatServiceCapablities(Map staticNatServic } } + void validateConnectivityServiceCapablities(Set providers, Map connectivityServiceCapabilityMap) { + if (connectivityServiceCapabilityMap != null && !connectivityServiceCapabilityMap.isEmpty()) { + for (Capability capability: connectivityServiceCapabilityMap.keySet()) { + if (capability == Capability.StretchedL2Subnet) { + String value = connectivityServiceCapabilityMap.get(capability).toLowerCase(); + if (!(value.contains("true") ^ value.contains("false"))) { + throw new InvalidParameterValueException("Invalid value (" + value + ") for " + capability + + " should be true/false"); + } + } else { + throw new InvalidParameterValueException("Capability " + capability.getName() + " can not be " + + " specified with connectivity service."); + } + } + } + + if (providers != null && !providers.isEmpty()) { + for (Provider provider: providers) { + NetworkElement element = _networkModel.getElementImplementingProvider(provider.getName()); + Map> capabilities = element.getCapabilities(); + if (capabilities != null && !capabilities.isEmpty()) { + Map connectivityCapabilities = capabilities.get(Service.Connectivity); + if (connectivityCapabilities == null || (connectivityCapabilities != null && !connectivityCapabilities.keySet().contains(Capability.StretchedL2Subnet))) { + throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support " + + Capability.StretchedL2Subnet.getName()); + } + } + } + } + } @Override @DB public NetworkOfferingVO createNetworkOffering(String name, String displayText, TrafficType trafficType, String tags, boolean specifyVlan, Availability availability, @@ -4012,6 +4040,8 @@ public NetworkOfferingVO createNetworkOffering(String name, String displayText, boolean inline = false; boolean publicLb = false; boolean internalLb = false; + boolean strechedL2Subnet = false; + if (serviceCapabilityMap != null && !serviceCapabilityMap.isEmpty()) { Map lbServiceCapabilityMap = serviceCapabilityMap.get(Service.Lb); @@ -4079,6 +4109,14 @@ public NetworkOfferingVO createNetworkOffering(String name, String displayText, } } } + + Map connectivityServiceCapabilityMap = serviceCapabilityMap.get(Service.Connectivity); + if (connectivityServiceCapabilityMap != null && !connectivityServiceCapabilityMap.isEmpty()) { + String value = connectivityServiceCapabilityMap.get(Capability.StretchedL2Subnet); + if ("true".equalsIgnoreCase(value)) { + strechedL2Subnet = true; + } + } } if (serviceProviderMap != null && serviceProviderMap.containsKey(Service.Lb) && !internalLb && !publicLb) { @@ -4088,7 +4126,7 @@ public NetworkOfferingVO createNetworkOffering(String name, String displayText, final NetworkOfferingVO offeringFinal = new NetworkOfferingVO(name, displayText, trafficType, systemOnly, specifyVlan, networkRate, multicastRate, isDefault, availability, tags, type, conserveMode, dedicatedLb, sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline, isPersistent, associatePublicIp, publicLb, - internalLb, egressDefaultPolicy); + internalLb, egressDefaultPolicy, strechedL2Subnet); if (serviceOfferingId != null) { offeringFinal.setServiceOfferingId(serviceOfferingId); @@ -4285,7 +4323,7 @@ public List searchForNetworkOfferings(ListNetworkOffe throw new InvalidParameterValueException("Can't update system networks"); } - _accountMgr.checkAccess(caller, null, true, network); + _accountMgr.checkAccess(caller, null, network); List offeringIds = _networkModel.listNetworkOfferingsForUpgrade(networkId); diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java index 9cbbb10c84..f9546156ab 100644 --- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -316,6 +316,15 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym host.getClusterId()); } + Pod pod = _podDao.findById(host.getPodId()); + Cluster cluster = _clusterDao.findById(host.getClusterId()); + + if (vm.getHypervisorType() == HypervisorType.BareMetal) { + DeployDestination dest = new DeployDestination(dc, pod, cluster, host, new HashMap()); + s_logger.debug("Returning Deployment Destination: " + dest); + return dest; + } + // search for storage under the zone, pod, cluster of the host. DataCenterDeployment lastPlan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(), host.getClusterId(), hostIdSpecified, plan.getPoolId(), null, @@ -333,8 +342,6 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym suitableHosts, suitableVolumeStoragePools, avoids, getPlannerUsage(planner, vmProfile, plan, avoids), readyAndReusedVolumes); if (potentialResources != null) { - Pod pod = _podDao.findById(host.getPodId()); - Cluster cluster = _clusterDao.findById(host.getClusterId()); Map storageVolMap = potentialResources.second(); // remove the reused vol<->pool from destination, since // we don't have to prepare this volume. @@ -363,9 +370,11 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym } else if (_capacityMgr.checkIfHostReachMaxGuestLimit(host)) { s_logger.debug("The last Host, hostId: " + host.getId() + " already has max Running VMs(count includes system VMs), skipping this and trying other available hosts"); - } else if ((offeringDetails = _serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.vgpuType.toString())) != null - && !_resourceMgr.isGPUDeviceAvailable(host.getId(), offeringDetails.getValue())){ - s_logger.debug("The last host of this VM does not have required GPU devices available"); + } else if ((offeringDetails = _serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.vgpuType.toString())) != null) { + ServiceOfferingDetailsVO groupName = _serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.pciDevice.toString()); + if(!_resourceMgr.isGPUDeviceAvailable(host.getId(), groupName.getValue(), offeringDetails.getValue())){ + s_logger.debug("The last host of this VM does not have required GPU devices available"); + } } else { if (host.getStatus() == Status.Up && host.getResourceState() == ResourceState.Enabled) { boolean hostTagsMatch = true; @@ -393,10 +402,22 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym // search for storage under the zone, pod, cluster // of // the last host. - DataCenterDeployment lastPlan = new DataCenterDeployment(host.getDataCenterId(), - host.getPodId(), host.getClusterId(), host.getId(), plan.getPoolId(), null); - Pair>, List> result = findSuitablePoolsForVolumes( - vmProfile, lastPlan, avoids, HostAllocator.RETURN_UPTO_ALL); + + + Pod pod = _podDao.findById(host.getPodId()); + Cluster cluster = _clusterDao.findById(host.getClusterId()); + + if (vm.getHypervisorType() == HypervisorType.BareMetal) { + DeployDestination dest = new DeployDestination(dc, pod, cluster, host, new HashMap()); + s_logger.debug("Returning Deployment Destination: " + dest); + return dest; + } + + DataCenterDeployment lastPlan = new DataCenterDeployment(host.getDataCenterId(), + host.getPodId(), host.getClusterId(), host.getId(), plan.getPoolId(), null); + Pair>, List> result = findSuitablePoolsForVolumes( + vmProfile, lastPlan, avoids, HostAllocator.RETURN_UPTO_ALL); + Map> suitableVolumeStoragePools = result.first(); List readyAndReusedVolumes = result.second(); @@ -409,8 +430,6 @@ public DeployDestination planDeployment(VirtualMachineProfile vmProfile, Deploym suitableHosts, suitableVolumeStoragePools, avoids, getPlannerUsage(planner, vmProfile, plan, avoids), readyAndReusedVolumes); if (potentialResources != null) { - Pod pod = _podDao.findById(host.getPodId()); - Cluster cluster = _clusterDao.findById(host.getClusterId()); Map storageVolMap = potentialResources.second(); // remove the reused vol<->pool from // destination, since we don't have to diff --git a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java index 48d998a53d..1318d9b8c7 100755 --- a/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java +++ b/server/src/com/cloud/ha/HighAvailabilityManagerImpl.java @@ -72,7 +72,6 @@ import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.fsm.StateListener; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.State; @@ -103,8 +102,7 @@ * before retrying the stop | seconds | 120 || * } **/ @Local(value = { HighAvailabilityManager.class }) -public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvailabilityManager, ClusterManagerListener, - StateListener { +public class HighAvailabilityManagerImpl extends ManagerBase implements HighAvailabilityManager, ClusterManagerListener { protected static final Logger s_logger = Logger.getLogger(HighAvailabilityManagerImpl.class); WorkerThread[] _workers; @@ -236,7 +234,7 @@ public void scheduleRestartForVmsOnHost(final HostVO host, boolean investigate) return; } - s_logger.warn("Scheduling restart for VMs on host " + host.getId()); + s_logger.warn("Scheduling restart for VMs on host " + host.getId() + "-" + host.getName()); final List vms = _instanceDao.listByHostId(host.getId()); final DataCenterVO dcVO = _dcDao.findById(host.getDataCenterId()); @@ -269,12 +267,12 @@ public void scheduleRestartForVmsOnHost(final HostVO host, boolean investigate) for (VMInstanceVO vm : vms) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Notifying HA Mgr of to restart vm " + vm.getId() + "-" + vm.getHostName()); + s_logger.debug("Notifying HA Mgr of to restart vm " + vm.getId() + "-" + vm.getInstanceName()); } vm = _instanceDao.findByUuid(vm.getUuid()); Long hostId = vm.getHostId(); if ( hostId != null && !hostId.equals(host.getId()) ) { - s_logger.debug("VM " + vm.getHostName() + " is not on down host " + host.getId() + " it is on other host " + s_logger.debug("VM " + vm.getInstanceName() + " is not on down host " + host.getId() + " it is on other host " + hostId + " VM HA is done"); continue; } @@ -503,7 +501,7 @@ protected Long restart(HaWorkVO work) { } else if (!alive) { fenced = true; } else { - s_logger.debug("VM " + vm.getHostName() + " is found to be alive by " + investigator.getName()); + s_logger.debug("VM " + vm.getInstanceName() + " is found to be alive by " + investigator.getName()); if (host.getStatus() == Status.Up) { s_logger.info(vm + " is alive and host is up. No need to restart it."); return null; @@ -806,7 +804,6 @@ public boolean configure(final String name, final Map xmlParams) _stopped = true; _executor = Executors.newScheduledThreadPool(count, new NamedThreadFactory("HA")); - VirtualMachine.State.getStateMachine().registerListener(this); return true; } @@ -921,6 +918,12 @@ private void runWithContext() { work.setTimeToTry(nextTime); work.setServerId(null); work.setDateTaken(null); + + // if restart failed in the middle due to exception, VM state may has been changed + // recapture into the HA worker so that it can really continue in it next turn + VMInstanceVO vm = _instanceDao.findById(work.getInstanceId()); + work.setUpdateTime(vm.getUpdated()); + work.setPreviousState(vm.getState()); } _haDao.update(work.getId(), work); } catch (final Throwable th) { @@ -962,38 +965,9 @@ public DeploymentPlanner getHAPlanner() { return _haPlanners.get(0); } - @Override - public boolean preStateTransitionEvent(State oldState, VirtualMachine.Event event, State newState, VirtualMachine vo, boolean status, Object opaque) { - return true; - } - - @Override - public boolean postStateTransitionEvent(State oldState, VirtualMachine.Event event, State newState, VirtualMachine vo, boolean status, Object opaque) { - if (oldState == State.Running && event == VirtualMachine.Event.FollowAgentPowerOffReport && newState == State.Stopped) { - final VMInstanceVO vm = _instanceDao.findById(vo.getId()); - if (vm.isHaEnabled()) { - if (vm.getState() != State.Stopped) - s_logger.warn("Sanity check failed. postStateTransitionEvent reports transited to Stopped but VM " + vm + " is still at state " + vm.getState()); - - s_logger.info("Detected out-of-band stop of a HA enabled VM " + vm.getInstanceName() + ", will schedule restart"); - _executor.submit(new ManagedContextRunnable() { - @Override - protected void runInContext() { - try { - scheduleRestart(vm, false); - } catch (Exception e) { - s_logger.warn("Unexpected exception when scheduling a HA restart", e); - } - } - }); - } - } - return true; - } - @Override public boolean hasPendingHaWork(long vmId) { - List haWorks = _haDao.listRunningHaWorkForVm(vmId); + List haWorks = _haDao.listPendingHaWorkForVm(vmId); return haWorks.size() > 0; } } diff --git a/server/src/com/cloud/ha/dao/HighAvailabilityDao.java b/server/src/com/cloud/ha/dao/HighAvailabilityDao.java index 7f532f2ae1..85135bb979 100644 --- a/server/src/com/cloud/ha/dao/HighAvailabilityDao.java +++ b/server/src/com/cloud/ha/dao/HighAvailabilityDao.java @@ -81,4 +81,6 @@ public interface HighAvailabilityDao extends GenericDao { * @return List of work items */ List listRunningHaWorkForVm(long vmId); + + List listPendingHaWorkForVm(long vmId); } diff --git a/server/src/com/cloud/ha/dao/HighAvailabilityDaoImpl.java b/server/src/com/cloud/ha/dao/HighAvailabilityDaoImpl.java index c0da88396c..d25c6a7937 100644 --- a/server/src/com/cloud/ha/dao/HighAvailabilityDaoImpl.java +++ b/server/src/com/cloud/ha/dao/HighAvailabilityDaoImpl.java @@ -49,6 +49,7 @@ public class HighAvailabilityDaoImpl extends GenericDaoBase impl private final SearchBuilder ReleaseSearch; private final SearchBuilder FutureHaWorkSearch; private final SearchBuilder RunningHaWorkSearch; + private final SearchBuilder PendingHaWorkSearch; protected HighAvailabilityDaoImpl() { super(); @@ -106,6 +107,22 @@ protected HighAvailabilityDaoImpl() { RunningHaWorkSearch.and("taken", RunningHaWorkSearch.entity().getDateTaken(), Op.NNULL); RunningHaWorkSearch.and("step", RunningHaWorkSearch.entity().getStep(), Op.NIN); RunningHaWorkSearch.done(); + + PendingHaWorkSearch = createSearchBuilder(); + PendingHaWorkSearch.and("instance", PendingHaWorkSearch.entity().getInstanceId(), Op.EQ); + PendingHaWorkSearch.and("type", PendingHaWorkSearch.entity().getType(), Op.EQ); + PendingHaWorkSearch.and("step", PendingHaWorkSearch.entity().getStep(), Op.NIN); + PendingHaWorkSearch.done(); + } + + @Override + public List listPendingHaWorkForVm(long vmId) { + SearchCriteria sc = PendingHaWorkSearch.create(); + sc.setParameters("instance", vmId); + sc.setParameters("type", WorkType.HA); + sc.setParameters("step", Step.Done, Step.Error, Step.Cancelled); + + return search(sc, null); } @Override diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java index b643ec41fa..e2520d26ff 100644 --- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java +++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java @@ -144,7 +144,8 @@ protected VirtualMachineTO toVirtualMachineTO(VirtualMachineProfile vmProfile) { // Set GPU details ServiceOfferingDetailsVO offeringDetail = null; if ((offeringDetail = _serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.vgpuType.toString())) != null) { - to.setGpuDevice(_resourceMgr.getGPUDevice(vm.getHostId(), offeringDetail.getValue())); + ServiceOfferingDetailsVO groupName = _serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.pciDevice.toString()); + to.setGpuDevice(_resourceMgr.getGPUDevice(vm.getHostId(), groupName.getValue(), offeringDetail.getValue())); } // Workaround to make sure the TO has the UUID we need for Niciri integration diff --git a/server/src/com/cloud/hypervisor/KVMGuru.java b/server/src/com/cloud/hypervisor/KVMGuru.java index e47e699b02..174b32db57 100644 --- a/server/src/com/cloud/hypervisor/KVMGuru.java +++ b/server/src/com/cloud/hypervisor/KVMGuru.java @@ -19,11 +19,14 @@ import javax.ejb.Local; import javax.inject.Inject; +import com.cloud.agent.api.Command; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.GuestOSVO; import com.cloud.storage.dao.GuestOSDao; +import com.cloud.utils.Pair; import com.cloud.vm.VirtualMachineProfile; +import org.apache.cloudstack.storage.command.StorageSubSystemCommand; @Local(value = HypervisorGuru.class) public class KVMGuru extends HypervisorGuruBase implements HypervisorGuru { @@ -40,6 +43,7 @@ protected KVMGuru() { } @Override + public VirtualMachineTO implement(VirtualMachineProfile vm) { VirtualMachineTO to = toVirtualMachineTO(vm); @@ -50,6 +54,15 @@ public VirtualMachineTO implement(VirtualMachineProfile vm) { return to; } + @Override + public Pair getCommandHostDelegation(long hostId, Command cmd) { + if (cmd instanceof StorageSubSystemCommand) { + StorageSubSystemCommand c = (StorageSubSystemCommand)cmd; + c.setExecuteInSequence(false); + } + return new Pair(false, new Long(hostId)); + } + @Override public boolean trackVmHostChange() { return false; diff --git a/server/src/com/cloud/network/IpAddressManagerImpl.java b/server/src/com/cloud/network/IpAddressManagerImpl.java index 9b1f9bd7ed..746221fca1 100644 --- a/server/src/com/cloud/network/IpAddressManagerImpl.java +++ b/server/src/com/cloud/network/IpAddressManagerImpl.java @@ -29,6 +29,8 @@ import javax.inject.Inject; +import org.apache.log4j.Logger; + import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.context.CallContext; @@ -40,7 +42,6 @@ import org.apache.cloudstack.region.PortableIpDao; import org.apache.cloudstack.region.PortableIpVO; import org.apache.cloudstack.region.Region; -import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.alert.AlertManager; @@ -409,7 +410,7 @@ private IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) thr Account caller = CallContext.current().getCallingAccount(); long callerUserId = CallContext.current().getCallingUserId(); // check permissions - _accountMgr.checkAccess(caller, null, false, ipOwner); + _accountMgr.checkAccess(caller, null, ipOwner); DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId); @@ -1164,15 +1165,14 @@ public IPAddressVO associateIPToGuestNetwork(long ipId, long networkId, boolean if (zone.getNetworkType() == NetworkType.Advanced) { if (network.getGuestType() == Network.GuestType.Shared) { if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) { - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.UseEntry, false, - network); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.UseEntry, network); } else { throw new InvalidParameterValueException("IP can be associated with guest network of 'shared' type only if " + "network services Source Nat, Static Nat, Port Forwarding, Load balancing, firewall are enabled in the network"); } } } else { - _accountMgr.checkAccess(caller, null, true, ipToAssoc); + _accountMgr.checkAccess(caller, null, ipToAssoc); } owner = _accountMgr.getAccount(ipToAssoc.getAllocatedToAccountId()); } else { @@ -1187,7 +1187,7 @@ public IPAddressVO associateIPToGuestNetwork(long ipId, long networkId, boolean Network network = _networksDao.findById(networkId); if (network != null) { - _accountMgr.checkAccess(owner, AccessType.UseEntry, false, network); + _accountMgr.checkAccess(owner, AccessType.UseEntry, network); } else { s_logger.debug("Unable to find ip address by id: " + ipId); return null; @@ -1319,11 +1319,10 @@ public IPAddressVO disassociatePortableIPToGuestNetwork(long ipId, long networkI if (zone.getNetworkType() == NetworkType.Advanced) { if (network.getGuestType() == Network.GuestType.Shared) { assert (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())); - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.UseEntry, false, - network); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.UseEntry, network); } } else { - _accountMgr.checkAccess(caller, null, true, ipToAssoc); + _accountMgr.checkAccess(caller, null, ipToAssoc); } owner = _accountMgr.getAccount(ipToAssoc.getAllocatedToAccountId()); } else { diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java index 7b4b2bebdb..4267967f5a 100755 --- a/server/src/com/cloud/network/NetworkModelImpl.java +++ b/server/src/com/cloud/network/NetworkModelImpl.java @@ -35,6 +35,7 @@ import org.apache.log4j.Logger; import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao; @@ -97,6 +98,7 @@ import com.cloud.projects.dao.ProjectAccountDao; import com.cloud.server.ConfigurationServer; import com.cloud.user.Account; +import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; import com.cloud.user.DomainManager; import com.cloud.user.dao.AccountDao; @@ -173,7 +175,8 @@ public void setNetworkElements(List networkElements) { FirewallRulesDao _firewallDao; @Inject DomainManager _domainMgr; - + @Inject + AccountManager _accountMgr; @Inject NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao; @Inject @@ -1566,6 +1569,27 @@ public void checkNetworkPermissions(Account owner, Network network) { } } + @Override + public void checkNetworkPermissions(Account owner, Network network, AccessType accessType) { + if (network == null) { + throw new CloudRuntimeException("cannot check permissions on (Network) "); + } + + AccountVO networkOwner = _accountDao.findById(network.getAccountId()); + if (networkOwner == null) { + throw new PermissionDeniedException("Unable to use network with id= " + ((NetworkVO) network).getUuid() + + ", network does not have an owner"); + } + if (owner.getType() != Account.ACCOUNT_TYPE_PROJECT && networkOwner.getType() == Account.ACCOUNT_TYPE_PROJECT) { + if (!_projectAccountDao.canAccessProjectAccount(owner.getAccountId(), network.getAccountId())) { + throw new PermissionDeniedException("Unable to use network with id= " + ((NetworkVO) network).getUuid() + + ", permission denied"); + } + } else { + _accountMgr.checkAccess(owner, accessType, network); + } + } + @Override public String getDefaultPublicTrafficLabel(long dcId, HypervisorType hypervisorType) { try { diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 9238a1e8ce..bdba1569ff 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -105,9 +105,9 @@ import com.cloud.network.dao.FirewallRulesDao; import com.cloud.network.dao.IPAddressDao; import com.cloud.network.dao.IPAddressVO; +import com.cloud.network.dao.LoadBalancerVMMapDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkDomainDao; -import com.cloud.network.dao.NetworkDomainVO; import com.cloud.network.dao.NetworkServiceMapDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.OvsProviderDao; @@ -122,6 +122,7 @@ import com.cloud.network.element.VirtualRouterElement; import com.cloud.network.element.VpcVirtualRouterElement; import com.cloud.network.guru.NetworkGuru; +import com.cloud.network.lb.LoadBalancingRulesService; import com.cloud.network.rules.FirewallRule.Purpose; import com.cloud.network.rules.FirewallRuleVO; import com.cloud.network.rules.RulesManager; @@ -139,13 +140,13 @@ import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; import com.cloud.org.Grouping; import com.cloud.projects.Project; +import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.projects.ProjectManager; import com.cloud.server.ResourceTag.ResourceObjectType; import com.cloud.tags.ResourceTagVO; import com.cloud.tags.dao.ResourceTagDao; import com.cloud.user.Account; import com.cloud.user.AccountManager; -import com.cloud.user.AccountVO; import com.cloud.user.DomainManager; import com.cloud.user.ResourceLimitService; import com.cloud.user.User; @@ -155,6 +156,7 @@ import com.cloud.utils.Journal; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; +import com.cloud.utils.Ternary; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.DB; import com.cloud.utils.db.EntityManager; @@ -307,6 +309,11 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { IpAddressManager _ipAddrMgr; @Inject EntityManager _entityMgr; + @Inject + LoadBalancerVMMapDao _lbVmMapDao; + + @Inject + LoadBalancingRulesService _lbService; int _cidrLimit; boolean _allowSubdomainNetworkAccess; @@ -535,7 +542,7 @@ public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolea // if shared network in the advanced zone, then check the caller against the network for 'AccessType.UseNetwork' if (zone.getNetworkType() == NetworkType.Advanced) { if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) { - _accountMgr.checkAccess(caller, AccessType.UseEntry, false, network); + _accountMgr.checkAccess(caller, AccessType.UseEntry, network); if (s_logger.isDebugEnabled()) { s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId()); } @@ -547,7 +554,7 @@ public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolea } } } else { - _accountMgr.checkAccess(caller, null, false, ipOwner); + _accountMgr.checkAccess(caller, null, ipOwner); } return _ipAddrMgr.allocateIp(ipOwner, false, caller, callerUserId, zone, displayIp); @@ -578,7 +585,7 @@ public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, // if shared network in the advanced zone, then check the caller against the network for 'AccessType.UseNetwork' if (zone.getNetworkType() == NetworkType.Advanced) { if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) { - _accountMgr.checkAccess(caller, AccessType.UseEntry, false, network); + _accountMgr.checkAccess(caller, AccessType.UseEntry, network); if (s_logger.isDebugEnabled()) { s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId()); } @@ -598,7 +605,7 @@ public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, } } - _accountMgr.checkAccess(caller, null, false, ipOwner); + _accountMgr.checkAccess(caller, null, ipOwner); return _ipAddrMgr.allocatePortableIp(ipOwner, caller, zoneId, null, null); } @@ -664,7 +671,7 @@ public NicSecondaryIp allocateSecondaryGuestIP(final long nicId, String requeste final Account ipOwner = _accountMgr.getAccount(vm.getAccountId()); // verify permissions - _accountMgr.checkAccess(caller, null, true, vm); + _accountMgr.checkAccess(caller, null, vm); Network network = _networksDao.findById(networkId); if (network == null) { @@ -760,7 +767,7 @@ public boolean releaseSecondaryIpFromNic(long ipAddressId) { throw new InvalidParameterValueException("There is no vm with the given secondary ip"); } // verify permissions - _accountMgr.checkAccess(caller, null, true, vm); + _accountMgr.checkAccess(caller, null, vm); Network network = _networksDao.findById(secIpVO.getNetworkId()); @@ -806,7 +813,13 @@ public boolean releaseSecondaryIpFromNic(long ipAddressId) { s_logger.debug("VM nic IP " + secondaryIp + " is associated with the static NAT rule public IP address id " + publicIpVO.getId()); throw new InvalidParameterValueException("Can' remove the ip " + secondaryIp + "is associate with static NAT rule public IP address id " + publicIpVO.getId()); } - } else if (dc.getNetworkType() == NetworkType.Basic || ntwkOff.getGuestType() == Network.GuestType.Shared) { + + if (_lbService.isLbRuleMappedToVmGuestIp(secondaryIp)) { + s_logger.debug("VM nic IP " + secondaryIp + " is mapped to load balancing rule"); + throw new InvalidParameterValueException("Can't remove the secondary ip " + secondaryIp + " is mapped to load balancing rule"); + } + + } else if (dc.getNetworkType() == NetworkType.Basic || ntwkOff.getGuestType() == Network.GuestType.Shared) { final IPAddressVO ip = _ipAddressDao.findByIpAndSourceNetworkId(secIpVO.getNetworkId(), secIpVO.getIp4Address()); if (ip != null) { Transaction.execute(new TransactionCallbackNoReturn() { @@ -878,7 +891,7 @@ private boolean releaseIpAddressInternal(long ipAddressId) throws InsufficientAd // verify permissions if (ipVO.getAllocatedToAccountId() != null) { - _accountMgr.checkAccess(caller, null, true, ipVO); + _accountMgr.checkAccess(caller, null, ipVO); } if (ipVO.isSourceNat()) { @@ -1072,14 +1085,14 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac } // Only Admin can create Shared networks - if (ntwkOff.getGuestType() == GuestType.Shared && !_accountMgr.isAdmin(caller.getType())) { + if (ntwkOff.getGuestType() == GuestType.Shared && !_accountMgr.isAdmin(caller.getId())) { throw new InvalidParameterValueException("Only Admins can create network with guest type " + GuestType.Shared); } // Check if the network is domain specific if (aclType == ACLType.Domain) { // only Admin can create domain with aclType=Domain - if (!_accountMgr.isAdmin(caller.getType())) { + if (!_accountMgr.isAdmin(caller.getId())) { throw new PermissionDeniedException("Only admin can create networks with aclType=Domain"); } @@ -1378,14 +1391,10 @@ public Pair, Integer> searchForNetworks(ListNetworksCmd String trafficType = cmd.getTrafficType(); Boolean isSystem = cmd.getIsSystem(); String aclType = cmd.getAclType(); - Long projectId = cmd.getProjectId(); - List permittedAccounts = new ArrayList(); - String path = null; Long physicalNetworkId = cmd.getPhysicalNetworkId(); List supportedServicesStr = cmd.getSupportedServices(); Boolean restartRequired = cmd.getRestartRequired(); boolean listAll = cmd.listAll(); - boolean isRecursive = cmd.isRecursive(); Boolean specifyIpRanges = cmd.getSpecifyIpRanges(); Long vpcId = cmd.getVpcId(); Boolean canUseForDeploy = cmd.canUseForDeploy(); @@ -1404,66 +1413,16 @@ public Pair, Integer> searchForNetworks(ListNetworksCmd throw new InvalidParameterValueException("System network belongs to system, account and domainId parameters can't be specified"); } - if (domainId != null) { - DomainVO domain = _domainDao.findById(domainId); - if (domain == null) { - // see DomainVO.java - throw new InvalidParameterValueException("Specified domain id doesn't exist in the system"); - } - - _accountMgr.checkAccess(caller, domain); - if (accountName != null) { - Account owner = _accountMgr.getActiveAccountByName(accountName, domainId); - if (owner == null) { - // see DomainVO.java - throw new InvalidParameterValueException("Unable to find account " + accountName + " in specified domain"); - } - - _accountMgr.checkAccess(caller, null, true, owner); - permittedAccounts.add(owner.getId()); - } - } - - if (!_accountMgr.isAdmin(caller.getType()) || (projectId != null && projectId.longValue() != -1 && domainId == null)) { - permittedAccounts.add(caller.getId()); - domainId = caller.getDomainId(); - } - - // set project information - boolean skipProjectNetworks = true; - if (projectId != null) { - if (projectId.longValue() == -1) { - if (!_accountMgr.isAdmin(caller.getType())) { - 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 specified id"); - } - if (!_projectMgr.canAccessProjectAccount(caller, project.getProjectAccountId())) { - // getProject() returns type ProjectVO. - InvalidParameterValueException ex = new InvalidParameterValueException("Account " + caller + " cannot access specified project id"); - ex.addProxyObject(project.getUuid(), "projectId"); - throw ex; - } - - //add project account - permittedAccounts.add(project.getProjectAccountId()); - //add caller account (if admin) - if (_accountMgr.isAdmin(caller.getType())) { - permittedAccounts.add(caller.getId()); - } - } - skipProjectNetworks = false; - } + List permittedDomains = new ArrayList(); + List permittedAccounts = new ArrayList(); + List permittedResources = new ArrayList(); + Ternary domainIdRecursiveListProject = new Ternary(cmd.getDomainId(), + cmd.isRecursive(), null); + _accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedDomains, permittedAccounts, permittedResources, + domainIdRecursiveListProject, cmd.listAll(), false, "listNetworks"); + Boolean isRecursive = domainIdRecursiveListProject.second(); + ListProjectResourcesCriteria listProjectResourcesCriteria = domainIdRecursiveListProject.third(); - if (domainId != null) { - path = _domainDao.findById(domainId).getPath(); - } else { - path = _domainDao.findById(caller.getDomainId()).getPath(); - } if (listAll && domainId == null) { isRecursive = true; @@ -1471,6 +1430,7 @@ public Pair, Integer> searchForNetworks(ListNetworksCmd Filter searchFilter = new Filter(NetworkVO.class, "id", false, null, null); SearchBuilder sb = _networksDao.createSearchBuilder(); + _accountMgr.buildACLSearchBuilder(sb, isRecursive, permittedDomains, permittedAccounts, permittedResources, listProjectResourcesCriteria); if (forVpc != null) { if (forVpc) { @@ -1505,122 +1465,9 @@ public Pair, Integer> searchForNetworks(ListNetworksCmd sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER); } - if (permittedAccounts.isEmpty()) { - SearchBuilder domainSearch = _domainDao.createSearchBuilder(); - domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE); - sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER); - } - - SearchBuilder accountSearch = _accountDao.createSearchBuilder(); - accountSearch.and("typeNEQ", accountSearch.entity().getType(), SearchCriteria.Op.NEQ); - accountSearch.and("typeEQ", accountSearch.entity().getType(), SearchCriteria.Op.EQ); - - sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinBuilder.JoinType.INNER); - - List networksToReturn = new ArrayList(); - - if (isSystem == null || !isSystem) { - if (!permittedAccounts.isEmpty()) { - //get account level networks - networksToReturn.addAll(listAccountSpecificNetworks( - buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, skipProjectNetworks, restartRequired, - specifyIpRanges, vpcId, tags, display), searchFilter, permittedAccounts)); - //get domain level networks - if (domainId != null) { - networksToReturn.addAll(listDomainLevelNetworks( - buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, true, restartRequired, - specifyIpRanges, vpcId, tags, display), searchFilter, domainId, false)); - } - } else { - //add account specific networks - networksToReturn.addAll(listAccountSpecificNetworksByDomainPath( - buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, skipProjectNetworks, restartRequired, - specifyIpRanges, vpcId, tags, display), searchFilter, path, isRecursive)); - //add domain specific networks of domain + parent domains - networksToReturn.addAll(listDomainSpecificNetworksByDomainPath( - buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, skipProjectNetworks, restartRequired, - specifyIpRanges, vpcId, tags, display), searchFilter, path, isRecursive)); - //add networks of subdomains - if (domainId == null) { - networksToReturn.addAll(listDomainLevelNetworks( - buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, true, restartRequired, - specifyIpRanges, vpcId, tags, display), searchFilter, caller.getDomainId(), true)); - } - } - } else { - networksToReturn = _networksDao.search( - buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, null, skipProjectNetworks, restartRequired, - specifyIpRanges, vpcId, tags, display), searchFilter); - } - - if (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !networksToReturn.isEmpty()) { - List supportedNetworks = new ArrayList(); - Service[] suppportedServices = new Service[supportedServicesStr.size()]; - int i = 0; - for (String supportedServiceStr : supportedServicesStr) { - Service service = Service.getService(supportedServiceStr); - if (service == null) { - throw new InvalidParameterValueException("Invalid service specified " + supportedServiceStr); - } else { - suppportedServices[i] = service; - } - i++; - } - - for (NetworkVO network : networksToReturn) { - if (areServicesSupportedInNetwork(network.getId(), suppportedServices)) { - supportedNetworks.add(network); - } - } - - networksToReturn = supportedNetworks; - } - - if (canUseForDeploy != null) { - List networksForDeploy = new ArrayList(); - for (NetworkVO network : networksToReturn) { - if (_networkModel.canUseForDeploy(network) == canUseForDeploy) { - networksForDeploy.add(network); - } - } - - networksToReturn = networksForDeploy; - } - - //Now apply pagination - //Most likely pageSize will never exceed int value, and we need integer to partition the listToReturn - boolean notNull = cmd.getStartIndex() != null && cmd.getPageSizeVal() != null; - if (notNull && cmd.getStartIndex() <= Integer.MAX_VALUE && cmd.getStartIndex() >= Integer.MIN_VALUE && cmd.getPageSizeVal() <= Integer.MAX_VALUE - && cmd.getPageSizeVal() >= Integer.MIN_VALUE) { - int index = cmd.getStartIndex().intValue() == 0 ? 0 : cmd.getStartIndex().intValue() / cmd.getPageSizeVal().intValue(); - List wPagination = new ArrayList(); - List> partitions = partitionNetworks(networksToReturn, cmd.getPageSizeVal().intValue()); - if (index < partitions.size()) { - wPagination = partitions.get(index); - } - return new Pair, Integer>(wPagination, networksToReturn.size()); - } - - return new Pair, Integer>(networksToReturn, networksToReturn.size()); - } - - private static List> partitionNetworks(List originalList, int chunkSize) { - List> listOfChunks = new ArrayList>(); - for (int i = 0; i < originalList.size() / chunkSize; i++) { - listOfChunks.add(originalList.subList(i * chunkSize, i * chunkSize + chunkSize)); - } - if (originalList.size() % chunkSize != 0) { - listOfChunks.add(originalList.subList(originalList.size() - originalList.size() % chunkSize, originalList.size())); - } - return listOfChunks; - } - - private SearchCriteria buildNetworkSearchCriteria(SearchBuilder sb, String keyword, Long id, Boolean isSystem, Long zoneId, String guestIpType, - String trafficType, Long physicalNetworkId, String aclType, boolean skipProjectNetworks, Boolean restartRequired, Boolean specifyIpRanges, Long vpcId, - Map tags, Boolean display) { - + // build network search criteria SearchCriteria sc = sb.create(); - + _accountMgr.buildACLSearchCriteria(sc, isRecursive, permittedDomains, permittedAccounts, permittedResources, listProjectResourcesCriteria); if (isSystem != null) { sc.setJoinParameters("networkOfferingSearch", "systemOnly", isSystem); } @@ -1659,12 +1506,6 @@ private SearchCriteria buildNetworkSearchCriteria(SearchBuilder buildNetworkSearchCriteria(SearchBuilder listDomainLevelNetworks(SearchCriteria sc, Filter searchFilter, long domainId, boolean parentDomainsOnly) { - List networkIds = new ArrayList(); - Set allowedDomains = _domainMgr.getDomainParentIds(domainId); - List maps = _networkDomainDao.listDomainNetworkMapByDomain(allowedDomains.toArray()); + List networksToReturn = _networksDao.search(sc, searchFilter); - for (NetworkDomainVO map : maps) { - if (map.getDomainId() == domainId && parentDomainsOnly) { - continue; - } - boolean subdomainAccess = (map.isSubdomainAccess() != null) ? map.isSubdomainAccess() : getAllowSubdomainAccessGlobal(); - if (map.getDomainId() == domainId || subdomainAccess) { - networkIds.add(map.getNetworkId()); + // filter by supported services + if (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !networksToReturn.isEmpty()) { + List supportedNetworks = new ArrayList(); + Service[] suppportedServices = new Service[supportedServicesStr.size()]; + int i = 0; + for (String supportedServiceStr : supportedServicesStr) { + Service service = Service.getService(supportedServiceStr); + if (service == null) { + throw new InvalidParameterValueException("Invalid service specified " + supportedServiceStr); + } else { + suppportedServices[i] = service; + } + i++; } - } - - if (!networkIds.isEmpty()) { - SearchCriteria domainSC = _networksDao.createSearchCriteria(); - domainSC.addAnd("id", SearchCriteria.Op.IN, networkIds.toArray()); - domainSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Domain.toString()); - sc.addAnd("id", SearchCriteria.Op.SC, domainSC); - return _networksDao.search(sc, searchFilter); - } else { - return new ArrayList(); - } - } + for (NetworkVO network : networksToReturn) { + if (areServicesSupportedInNetwork(network.getId(), suppportedServices)) { + supportedNetworks.add(network); + } + } - private List listAccountSpecificNetworks(SearchCriteria sc, Filter searchFilter, List permittedAccounts) { - SearchCriteria accountSC = _networksDao.createSearchCriteria(); - if (!permittedAccounts.isEmpty()) { - accountSC.addAnd("accountId", SearchCriteria.Op.IN, permittedAccounts.toArray()); + networksToReturn = supportedNetworks; } - accountSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Account.toString()); - - sc.addAnd("id", SearchCriteria.Op.SC, accountSC); - return _networksDao.search(sc, searchFilter); - } - - private List listAccountSpecificNetworksByDomainPath(SearchCriteria sc, Filter searchFilter, String path, boolean isRecursive) { - SearchCriteria accountSC = _networksDao.createSearchCriteria(); - accountSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Account.toString()); - - if (path != null) { - if (isRecursive) { - sc.setJoinParameters("domainSearch", "path", path + "%"); - } else { - sc.setJoinParameters("domainSearch", "path", path); + // filter by usability to deploy + if (canUseForDeploy != null) { + List networksForDeploy = new ArrayList(); + for (NetworkVO network : networksToReturn) { + if (_networkModel.canUseForDeploy(network) == canUseForDeploy) { + networksForDeploy.add(network); + } } - } - - sc.addAnd("id", SearchCriteria.Op.SC, accountSC); - return _networksDao.search(sc, searchFilter); - } - private List listDomainSpecificNetworksByDomainPath(SearchCriteria sc, Filter searchFilter, String path, boolean isRecursive) { + networksToReturn = networksForDeploy; + } - Set allowedDomains = new HashSet(); - if (path != null) { - if (isRecursive) { - allowedDomains = _domainMgr.getDomainChildrenIds(path); - } else { - Domain domain = _domainDao.findDomainByPath(path); - allowedDomains.add(domain.getId()); + //Now apply pagination + //Most likely pageSize will never exceed int value, and we need integer to partition the listToReturn + boolean notNull = cmd.getStartIndex() != null && cmd.getPageSizeVal() != null; + if (notNull && cmd.getStartIndex() <= Integer.MAX_VALUE && cmd.getStartIndex() >= Integer.MIN_VALUE && cmd.getPageSizeVal() <= Integer.MAX_VALUE + && cmd.getPageSizeVal() >= Integer.MIN_VALUE) { + int index = cmd.getStartIndex().intValue() == 0 ? 0 : cmd.getStartIndex().intValue() / cmd.getPageSizeVal().intValue(); + List wPagination = new ArrayList(); + List> partitions = partitionNetworks(networksToReturn, cmd.getPageSizeVal().intValue()); + if (index < partitions.size()) { + wPagination = partitions.get(index); } + return new Pair, Integer>(wPagination, networksToReturn.size()); } - List networkIds = new ArrayList(); - - List maps = _networkDomainDao.listDomainNetworkMapByDomain(allowedDomains.toArray()); + return new Pair, Integer>(networksToReturn, networksToReturn.size()); + } - for (NetworkDomainVO map : maps) { - networkIds.add(map.getNetworkId()); + private static List> partitionNetworks(List originalList, int chunkSize) { + List> listOfChunks = new ArrayList>(); + for (int i = 0; i < originalList.size() / chunkSize; i++) { + listOfChunks.add(originalList.subList(i * chunkSize, i * chunkSize + chunkSize)); } - - if (!networkIds.isEmpty()) { - SearchCriteria domainSC = _networksDao.createSearchCriteria(); - domainSC.addAnd("id", SearchCriteria.Op.IN, networkIds.toArray()); - domainSC.addAnd("aclType", SearchCriteria.Op.EQ, ACLType.Domain.toString()); - - sc.addAnd("id", SearchCriteria.Op.SC, domainSC); - return _networksDao.search(sc, searchFilter); - } else { - return new ArrayList(); + if (originalList.size() % chunkSize != 0) { + listOfChunks.add(originalList.subList(originalList.size() - originalList.size() % chunkSize, originalList.size())); } + return listOfChunks; } @Override @@ -1803,7 +1620,7 @@ public boolean deleteNetwork(long networkId, boolean forced) { Account owner = _accountMgr.getAccount(network.getAccountId()); // Perform permission check - _accountMgr.checkAccess(caller, null, true, network); + _accountMgr.checkAccess(caller, null, network); if (forced && !_accountMgr.isRootAdmin(caller.getId())) { throw new InvalidParameterValueException("Delete network with 'forced' option can only be called by root admins"); @@ -1847,7 +1664,7 @@ public boolean restartNetwork(RestartNetworkCmd cmd, boolean cleanup) throws Con throw new InvalidParameterException("Unable to restart a running SDN network."); } - _accountMgr.checkAccess(callerAccount, null, true, network); + _accountMgr.checkAccess(callerAccount, null, network); boolean success = _networkMgr.restartNetwork(networkId, callerAccount, callerUser, cleanup); @@ -1983,7 +1800,7 @@ public Network updateGuestNetwork(final long networkId, String name, String disp throw new InvalidParameterValueException("Can't allow networks which traffic type is not " + TrafficType.Guest); } - _accountMgr.checkAccess(callerAccount, null, true, network); + _accountMgr.checkAccess(callerAccount, null, network); if (name != null) { network.setName(name); @@ -2265,9 +2082,9 @@ public void doInTransactionWithoutResult(TransactionStatus status) { long isDefault = (nic.isDefaultNic()) ? 1 : 0; String nicIdString = Long.toString(nic.getId()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), nicIdString, - oldNetworkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid()); + oldNetworkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), nicIdString, - networkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid()); + networkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay()); } } }); @@ -3819,12 +3636,12 @@ private PhysicalNetworkServiceProvider addDefaultBaremetalProvidersToPhysicalNet PhysicalNetworkVO pvo = _physicalNetworkDao.findById(physicalNetworkId); DataCenterVO dvo = _dcDao.findById(pvo.getDataCenterId()); if (dvo.getNetworkType() == NetworkType.Basic) { - - Provider provider = Network.Provider.getProvider("BaremetalDhcpProvider"); - if (provider == null) { + + Provider provider = Network.Provider.getProvider("BaremetalDhcpProvider"); + if (provider == null) { // baremetal is not loaded return null; - } + } addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalDhcpProvider", null, null); addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalPxeProvider", null, null); @@ -4028,7 +3845,7 @@ public List listNics(ListNicsCmd cmd) { throw ex; } - _accountMgr.checkAccess(caller, null, true, userVm); + _accountMgr.checkAccess(caller, null, userVm); return _networkMgr.listVmNics(vmId, nicId, networkId); } @@ -4052,7 +3869,7 @@ public IpAddress updateIP(Long id, String customId, Boolean displayIp) { // verify permissions if (ipVO.getAllocatedToAccountId() != null) { - _accountMgr.checkAccess(caller, null, true, ipVO); + _accountMgr.checkAccess(caller, null, ipVO); } else if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { throw new PermissionDeniedException("Only Root admin can update non-allocated ip addresses"); } diff --git a/server/src/com/cloud/network/as/AutoScaleManagerImpl.java b/server/src/com/cloud/network/as/AutoScaleManagerImpl.java index 99189fe43a..09c6694701 100644 --- a/server/src/com/cloud/network/as/AutoScaleManagerImpl.java +++ b/server/src/com/cloud/network/as/AutoScaleManagerImpl.java @@ -240,7 +240,7 @@ private VO getEntityInDatabase(Account caller, Str throw new InvalidParameterValueException("Unable to find " + paramName); } - _accountMgr.checkAccess(caller, null, false, (ControlledEntity)vo); + _accountMgr.checkAccess(caller, null, (ControlledEntity)vo); return vo; } @@ -342,7 +342,7 @@ public AutoScaleVmProfile createAutoScaleVmProfile(CreateAutoScaleVmProfileCmd c Account owner = _accountDao.findById(cmd.getAccountId()); Account caller = CallContext.current().getCallingAccount(); - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); long zoneId = cmd.getZoneId(); long serviceOfferingId = cmd.getServiceOfferingId(); @@ -527,7 +527,7 @@ public AutoScalePolicyVO doInTransaction(TransactionStatus status) { ControlledEntity[] sameOwnerEntities = conditions.toArray(new ControlledEntity[conditions.size() + 1]); sameOwnerEntities[sameOwnerEntities.length - 1] = autoScalePolicyVO; - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, sameOwnerEntities); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, sameOwnerEntities); if (conditionIds.size() != conditions.size()) { // TODO report the condition id which could not be found @@ -621,7 +621,7 @@ public void checkCallerAccess(String accountName, Long domainId) { idList.add(ApiDBUtils.findDomainById(domainId).getUuid()); throw new InvalidParameterValueException("Unable to find account " + accountName + " in domain with specifed domainId"); } - _accountMgr.checkAccess(caller, null, false, owner); + _accountMgr.checkAccess(caller, null, owner); } private class SearchWrapper { @@ -980,7 +980,7 @@ protected AutoScaleVmGroupVO checkValidityAndPersist(final AutoScaleVmGroupVO vm ControlledEntity[] sameOwnerEntities = policies.toArray(new ControlledEntity[policies.size() + 2]); sameOwnerEntities[sameOwnerEntities.length - 2] = loadBalancer; sameOwnerEntities[sameOwnerEntities.length - 1] = profileVO; - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, sameOwnerEntities); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, sameOwnerEntities); return Transaction.execute(new TransactionCallback() { @Override @@ -1414,7 +1414,7 @@ private boolean assignLBruleToNewVm(long vmId, AutoScaleVmGroupVO asGroup) { } } lstVmId.add(new Long(vmId)); - return _loadBalancingRulesService.assignToLoadBalancer(lbId, lstVmId); + return _loadBalancingRulesService.assignToLoadBalancer(lbId, lstVmId, new HashMap>()); } @@ -1431,7 +1431,7 @@ private long removeLBrule(AutoScaleVmGroupVO asGroup) { List lstVmId = new ArrayList(); if (instanceId != -1) lstVmId.add(instanceId); - if (_loadBalancingRulesService.removeFromLoadBalancer(lbId, lstVmId)) + if (_loadBalancingRulesService.removeFromLoadBalancer(lbId, lstVmId, new HashMap>())) return instanceId; else return -1; diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index 3f4ba5b5d3..3b3cacd094 100755 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -188,10 +188,16 @@ public boolean implement(Network network, NetworkOffering offering, DeployDestin Map params = new HashMap(1); params.put(VirtualMachineProfile.Param.ReProgramGuestNetworks, true); - List routers = - _routerMgr.deployVirtualRouterInGuestNetwork(network, dest, _accountMgr.getAccount(network.getAccountId()), params, offering.getRedundantRouter()); - if ((routers == null) || (routers.size() == 0)) { - throw new ResourceUnavailableException("Can't find at least one running router!", DataCenter.class, network.getDataCenterId()); + List routers = _routerMgr.deployVirtualRouterInGuestNetwork(network, dest, + _accountMgr.getAccount(network.getAccountId()), params, + offering.getRedundantRouter()); + int routerCounts = 1; + if (offering.getRedundantRouter()) { + routerCounts = 2; + } + if ((routers == null) || (routers.size() < routerCounts)) { + throw new ResourceUnavailableException("Can't find all necessary running routers!", + DataCenter.class, network.getDataCenterId()); } return true; diff --git a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java index c312d3d1ba..730606816b 100644 --- a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java +++ b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java @@ -27,12 +27,13 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + import org.apache.cloudstack.api.command.user.firewall.ListFirewallRulesCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; import com.cloud.configuration.Config; import com.cloud.domain.dao.DomainDao; @@ -271,7 +272,7 @@ public Pair, Integer> listFirewallRules(ListFirewal if (ipAddressVO == null || !ipAddressVO.readyToUse()) { throw new InvalidParameterValueException("Ip address id=" + ipId + " not ready for firewall rules yet"); } - _accountMgr.checkAccess(caller, null, true, ipAddressVO); + _accountMgr.checkAccess(caller, null, ipAddressVO); } Ternary domainIdRecursiveListProject = new Ternary(cmd.getDomainId(), cmd.isRecursive(), null); @@ -463,7 +464,7 @@ public void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer } // Validate ip address - _accountMgr.checkAccess(caller, null, true, ipAddress); + _accountMgr.checkAccess(caller, null, ipAddress); } //network id either has to be passed explicitly, or implicitly as a part of ipAddress object @@ -475,7 +476,7 @@ public void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer assert network != null : "Can't create rule as network associated with public ip address is null?"; if (trafficType == FirewallRule.TrafficType.Egress) { - _accountMgr.checkAccess(caller, null, true, network); + _accountMgr.checkAccess(caller, null, network); } // Verify that the network guru supports the protocol specified @@ -638,7 +639,7 @@ public boolean applyFirewallRules(List rules, boolean continueOn } if (caller != null) { - _accountMgr.checkAccess(caller, null, true, rules.toArray(new FirewallRuleVO[rules.size()])); + _accountMgr.checkAccess(caller, null, rules.toArray(new FirewallRuleVO[rules.size()])); } try { @@ -692,7 +693,7 @@ protected boolean revokeFirewallRule(long ruleId, boolean apply, Account caller, throw new InvalidParameterValueException("Only root admin can delete the system wide firewall rule"); } - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); revokeRule(rule, caller, userId, false); @@ -742,7 +743,7 @@ protected FirewallRule updateFirewallRule(long ruleId, String customId, Account throw new InvalidParameterValueException("Only root admin can update the system wide firewall rule"); } - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); if (customId != null) { rule.setUuid(customId); @@ -761,7 +762,7 @@ protected FirewallRule updateFirewallRule(long ruleId, String customId, Account @DB public void revokeRule(final FirewallRuleVO rule, Account caller, long userId, final boolean needUsageEvent) { if (caller != null) { - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); } Transaction.execute(new TransactionCallbackNoReturn() { diff --git a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java index 13246a74a5..ddf1f9c3d8 100644 --- a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java +++ b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java @@ -127,6 +127,10 @@ public Network implement(Network config, NetworkOffering offering, DeployDestina throws InsufficientVirtualNetworkCapcityException { assert (config.getState() == State.Implementing) : "Why are we implementing " + config; + if (_networkModel.areServicesSupportedInNetwork(config.getId(), Network.Service.Connectivity)) { + return null; + } + if (!_networkModel.networkIsConfiguredForExternalNetworking(config.getDataCenterId(), config.getId())) { return super.implement(config, offering, dest, context); } diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 9f280ef7a8..a7761c45a4 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -30,6 +30,11 @@ import javax.ejb.Local; import javax.inject.Inject; +import org.apache.log4j.Logger; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.command.user.loadbalancer.CreateLBHealthCheckPolicyCmd; import org.apache.cloudstack.api.command.user.loadbalancer.CreateLBStickinessPolicyCmd; @@ -45,7 +50,6 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.lb.ApplicationLoadBalancerRuleVO; import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao; -import org.apache.log4j.Logger; import com.cloud.agent.api.to.LoadBalancerTO; import com.cloud.configuration.ConfigurationManager; @@ -163,9 +167,8 @@ import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.dao.NicDao; +import com.cloud.vm.dao.NicSecondaryIpDao; import com.cloud.vm.dao.UserVmDao; -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; @Local(value = {LoadBalancingRulesManager.class, LoadBalancingRulesService.class}) public class LoadBalancingRulesManagerImpl extends ManagerBase implements LoadBalancingRulesManager, LoadBalancingRulesService { @@ -258,6 +261,9 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements @Inject LoadBalancerCertMapDao _lbCertMapDao; + @Inject + NicSecondaryIpDao _nicSecondaryIpDao; + // Will return a string. For LB Stickiness this will be a json, for // autoscale this will be "," separated values @Override @@ -523,7 +529,7 @@ public StickinessPolicy createLBStickinessPolicy(CreateLBStickinessPolicyCmd cmd throw new InvalidParameterValueException("Failed: LB rule id: " + cmd.getLbRuleId() + " not present "); } - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + _accountMgr.checkAccess(caller.getCallingAccount(), null, loadBalancer); if (loadBalancer.getState() == FirewallRule.State.Revoke) { throw new InvalidParameterValueException("Failed: LB rule id: " + cmd.getLbRuleId() + " is in deleting state: "); } @@ -578,7 +584,7 @@ public HealthCheckPolicy createLBHealthCheckPolicy(CreateLBHealthCheckPolicyCmd throw new InvalidParameterValueException("Failed: LB rule id: " + cmd.getLbRuleId() + " not present "); } - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + _accountMgr.checkAccess(caller.getCallingAccount(), null, loadBalancer); if (loadBalancer.getState() == FirewallRule.State.Revoke) { throw new InvalidParameterValueException("Failed: LB rule id: " + cmd.getLbRuleId() + " is in deleting state: "); @@ -735,7 +741,7 @@ public boolean deleteLBStickinessPolicy(long stickinessPolicyId, boolean apply) } long loadBalancerId = loadBalancer.getId(); FirewallRule.State backupState = loadBalancer.getState(); - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + _accountMgr.checkAccess(caller.getCallingAccount(), null, loadBalancer); if (apply) { if (loadBalancer.getState() == FirewallRule.State.Active) { @@ -788,7 +794,7 @@ public boolean deleteLBHealthCheckPolicy(long healthCheckPolicyId, boolean apply } final long loadBalancerId = loadBalancer.getId(); FirewallRule.State backupState = loadBalancer.getState(); - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + _accountMgr.checkAccess(caller.getCallingAccount(), null, loadBalancer); if (apply) { if (loadBalancer.getState() == FirewallRule.State.Active) { @@ -882,7 +888,8 @@ public void updateLBHealthChecks(Scheme scheme) throws ResourceUnavailableExcept for (LoadBalancerVMMapVO lbVmMap : lbVmMaps) { UserVm vm = _vmDao.findById(lbVmMap.getInstanceId()); Nic nic = _nicDao.findByInstanceIdAndNetworkIdIncludingRemoved(ulb.getNetworkId(), vm.getId()); - String dstIp = nic.getIp4Address(); + String dstIp = lbVmMap.getInstanceIp() == null ? nic.getIp4Address(): lbVmMap.getInstanceIp(); + for (int i = 0; i < lbto.getDestinations().length; i++) { LoadBalancerTO.DestinationTO des = lbto.getDestinations()[i]; if (dstIp.equalsIgnoreCase(lbto.getDestinations()[i].getDestIp())) { @@ -923,7 +930,7 @@ private boolean isRollBackAllowedForProvider(LoadBalancerVO loadBalancer) { @Override @DB @ActionEvent(eventType = EventTypes.EVENT_ASSIGN_TO_LOAD_BALANCER_RULE, eventDescription = "assigning to load balancer", async = true) - public boolean assignToLoadBalancer(long loadBalancerId, List instanceIds) { + public boolean assignToLoadBalancer(long loadBalancerId, List instanceIds, Map> vmIdIpMap) { CallContext ctx = CallContext.current(); Account caller = ctx.getCallingAccount(); @@ -932,24 +939,53 @@ public boolean assignToLoadBalancer(long loadBalancerId, List instanceIds) throw new InvalidParameterValueException("Failed to assign to load balancer " + loadBalancerId + ", the load balancer was not found."); } + + if (instanceIds == null && vmIdIpMap.isEmpty()) { + throw new InvalidParameterValueException("Both instanceids and vmidipmap can't be null"); + } + + // instanceIds and vmIdipmap is passed + if (instanceIds != null && !vmIdIpMap.isEmpty()) { + for(long instanceId: instanceIds) { + if (!vmIdIpMap.containsKey(instanceId)) { + vmIdIpMap.put(instanceId, null); + } + } + } + + //only instanceids list passed + if (instanceIds != null && vmIdIpMap.isEmpty()){ + vmIdIpMap = new HashMap>(); + for (long instanceId: instanceIds){ + vmIdIpMap.put(instanceId, null); + } + } + List mappedInstances = _lb2VmMapDao.listByLoadBalancerId(loadBalancerId, false); Set mappedInstanceIds = new HashSet(); for (LoadBalancerVMMapVO mappedInstance : mappedInstances) { mappedInstanceIds.add(Long.valueOf(mappedInstance.getInstanceId())); } - final List vmsToAdd = new ArrayList(); + Map> existingVmIdIps = new HashMap>(); + // now get the ips of vm and add it to map + for (LoadBalancerVMMapVO mappedInstance : mappedInstances) { - if (instanceIds == null || instanceIds.isEmpty()) { - s_logger.warn("List of vms to assign to the lb, is empty"); - return false; + List ipsList = null; + if (existingVmIdIps.containsKey(mappedInstance.getInstanceId())) { + ipsList = existingVmIdIps.get(mappedInstance.getInstanceId()); + } else { + ipsList = new ArrayList(); + } + ipsList.add(mappedInstance.getInstanceIp()); + existingVmIdIps.put(mappedInstance.getInstanceId(), ipsList); } - for (Long instanceId : instanceIds) { - if (mappedInstanceIds.contains(instanceId)) { - throw new InvalidParameterValueException("VM " + instanceId + " is already mapped to load balancer."); - } + final List vmsToAdd = new ArrayList(); + // check for conflict + Set passedInstanceIds = vmIdIpMap.keySet(); + for (Long instanceId : passedInstanceIds) { UserVm vm = _vmDao.findById(instanceId); if (vm == null || vm.getState() == State.Destroyed || vm.getState() == State.Expunging) { InvalidParameterValueException ex = new InvalidParameterValueException("Invalid instance id specified"); @@ -985,18 +1021,75 @@ public boolean assignToLoadBalancer(long loadBalancerId, List instanceIds) throw ex; } + String priIp = nicInSameNetwork.getIp4Address(); + + if (existingVmIdIps.containsKey(instanceId)) { + // now check for ip address + List mappedIps = existingVmIdIps.get(instanceId); + List newIps = vmIdIpMap.get(instanceId); + + if (newIps == null) { + newIps = new ArrayList(); + newIps.add(priIp); + } + + for (String newIp: newIps) { + if (mappedIps.contains(newIp)) { + throw new InvalidParameterValueException("VM " + instanceId + " with " + newIp +" is already mapped to load balancer."); + } + } + } + + List vmIpsList = vmIdIpMap.get(instanceId); + String vmLbIp = null; + + if (vmIpsList != null) { + + //check if the ips belongs to nic secondary ip + for (String ip: vmIpsList) { + // skip the primary ip from vm secondary ip comparisions + if (ip.equals(priIp)) { + continue; + } + if(_nicSecondaryIpDao.findByIp4AddressAndNicId(ip,nicInSameNetwork.getId()) == null) { + throw new InvalidParameterValueException("VM ip "+ ip + " specified does not belong to " + + "nic in network " + nicInSameNetwork.getNetworkId()); + } + } + } else { + vmIpsList = new ArrayList(); + vmIpsList.add(priIp); + } + + // when vm id is passed in instance ids and in vmidipmap + // assign for primary ip and ip passed in vmidipmap + if (instanceIds != null ) { + if (instanceIds.contains(instanceId)) { + vmIpsList.add(priIp); + } + } + + vmIdIpMap.put(instanceId, vmIpsList); + if (s_logger.isDebugEnabled()) { s_logger.debug("Adding " + vm + " to the load balancer pool"); } vmsToAdd.add(vm); } + final Set vmIds = vmIdIpMap.keySet(); + final Map> newMap = vmIdIpMap; + Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { - for (UserVm vm : vmsToAdd) { - LoadBalancerVMMapVO map = new LoadBalancerVMMapVO(loadBalancer.getId(), vm.getId(), false); - map = _lb2VmMapDao.persist(map); + + for (Long vmId : vmIds) { + final Set lbVmIps = new HashSet(newMap.get(vmId)); + for (String vmIp: lbVmIps) { + LoadBalancerVMMapVO map = new LoadBalancerVMMapVO(loadBalancer.getId(), vmId, vmIp, false); + map = _lb2VmMapDao.persist(map); + } } } }); @@ -1015,13 +1108,16 @@ public void doInTransactionWithoutResult(TransactionStatus status) { applyLoadBalancerConfig(loadBalancerId); success = true; } catch (ResourceUnavailableException e) { - if (isRollBackAllowedForProvider(loadBalancer)) { + s_logger.warn("Unable to apply the load balancer config because resource is unavaliable.", e); + success = false; + } finally { + if (!success) { final List vmInstanceIds = new ArrayList(); Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { - for (UserVm vm : vmsToAdd) { - vmInstanceIds.add(vm.getId()); + for (Long vmId : vmIds) { + vmInstanceIds.add(vmId); } } }); @@ -1031,16 +1127,14 @@ public void doInTransactionWithoutResult(TransactionStatus status) { } loadBalancer.setState(backupState); _lbDao.persist(loadBalancer); + CloudRuntimeException ex = new CloudRuntimeException("Failed to add specified loadbalancerruleid for vms " + + instanceIds); + ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId"); + // TBD: Also pack in the instanceIds in the exception using the + // right VO object or table name. + throw ex; } - s_logger.warn("Unable to apply the load balancer config because resource is unavaliable.", e); - } - if (!success) { - CloudRuntimeException ex = new CloudRuntimeException("Failed to add specified loadbalancerruleid for vms " + instanceIds); - ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId"); - // TBD: Also pack in the instanceIds in the exception using the - // right VO object or table name. - throw ex; } return success; @@ -1056,8 +1150,8 @@ public boolean assignSSLCertToLoadBalancerRule(Long lbId, String certName, Strin @Override @ActionEvent(eventType = EventTypes.EVENT_REMOVE_FROM_LOAD_BALANCER_RULE, eventDescription = "removing from load balancer", async = true) - public boolean removeFromLoadBalancer(long loadBalancerId, List instanceIds) { - return removeFromLoadBalancerInternal(loadBalancerId, instanceIds, true); + public boolean removeFromLoadBalancer(long loadBalancerId, List instanceIds, Map> vmIdIpsMap) { + return removeFromLoadBalancerInternal(loadBalancerId, instanceIds, true, vmIdIpsMap); } @Override @@ -1092,7 +1186,7 @@ public boolean assignCertToLoadBalancer(long lbRuleId, Long certId) { throw new InvalidParameterException("Invalid certificate id: " + certId); } - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + _accountMgr.checkAccess(caller.getCallingAccount(), null, loadBalancer); // check if LB and Cert belong to the same account if (loadBalancer.getAccountId() != certVO.getAccountId()) { @@ -1155,7 +1249,7 @@ public boolean removeCertFromLoadBalancer(long lbRuleId) { throw new InvalidParameterException("No certificate is bound to lb with id: " + lbRuleId); } - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + _accountMgr.checkAccess(caller.getCallingAccount(), null, loadBalancer); boolean success = false; FirewallRule.State backupState = loadBalancer.getState(); @@ -1191,7 +1285,7 @@ public boolean removeCertFromLoadBalancer(long lbRuleId) { return success; } - private boolean removeFromLoadBalancerInternal(long loadBalancerId, List instanceIds, boolean rollBack) { + private boolean removeFromLoadBalancerInternal(long loadBalancerId, List instanceIds, boolean rollBack, Map> vmIdIpMap) { CallContext caller = CallContext.current(); LoadBalancerVO loadBalancer = _lbDao.findById(Long.valueOf(loadBalancerId)); @@ -1199,19 +1293,67 @@ private boolean removeFromLoadBalancerInternal(long loadBalancerId, List i throw new InvalidParameterException("Invalid load balancer value: " + loadBalancerId); } - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, loadBalancer); + _accountMgr.checkAccess(caller.getCallingAccount(), null, loadBalancer); + + if (instanceIds == null && vmIdIpMap.isEmpty()) { + throw new InvalidParameterValueException("Both instanceids and vmidipmap can't be null"); + } + + // instanceIds and vmIdipmap is passed + if (instanceIds != null && !vmIdIpMap.isEmpty()) { + for(long instanceId: instanceIds) { + if (!vmIdIpMap.containsKey(instanceId)) { + vmIdIpMap.put(instanceId, null); + } + } + } + + //only instanceids list passed + if (instanceIds != null && vmIdIpMap.isEmpty()){ + vmIdIpMap = new HashMap>(); + for (long instanceId: instanceIds){ + vmIdIpMap.put(instanceId, null); + } + } boolean success = false; FirewallRule.State backupState = loadBalancer.getState(); + Set vmIds = vmIdIpMap.keySet(); try { loadBalancer.setState(FirewallRule.State.Add); _lbDao.persist(loadBalancer); - for (long instanceId : instanceIds) { - LoadBalancerVMMapVO map = _lb2VmMapDao.findByLoadBalancerIdAndVmId(loadBalancerId, instanceId); - map.setRevoke(true); - _lb2VmMapDao.persist(map); - s_logger.debug("Set load balancer rule for revoke: rule id " + loadBalancerId + ", vmId " + instanceId); + for (long instanceId : vmIds) { + List lbVmIps = vmIdIpMap.get(instanceId); + + if (lbVmIps == null || lbVmIps.isEmpty()) { + List lbVms = _lb2VmMapDao.listByLoadBalancerIdAndVmId(loadBalancerId, instanceId); + if (lbVms == null) { + throw new InvalidParameterValueException("The instance id: "+ instanceId +" is not configured " + + " for LB rule id " + loadBalancerId); + } + + for (LoadBalancerVMMapVO lbvm: lbVms) { + lbvm.setRevoke(true); + _lb2VmMapDao.persist(lbvm); + } + s_logger.debug("Set load balancer rule for revoke: rule id " + loadBalancerId + ", vmId " + instanceId); + + } else { + for (String vmIp: lbVmIps) { + LoadBalancerVMMapVO map = _lb2VmMapDao.findByLoadBalancerIdAndVmIdVmIp (loadBalancerId, instanceId, vmIp); + if (map == null) { + throw new InvalidParameterValueException("The instance id: "+ instanceId +" is not configured " + + " for LB rule id " + loadBalancerId); + } + map.setRevoke(true); + _lb2VmMapDao.persist(map); + s_logger.debug("Set load balancer rule for revoke: rule id " + loadBalancerId + ", vmId " + + instanceId + ", vmip " + vmIp); + + } + + } } if (_autoScaleVmGroupDao.isAutoScaleLoadBalancer(loadBalancerId)) { @@ -1233,11 +1375,23 @@ private boolean removeFromLoadBalancerInternal(long loadBalancerId, List i } catch (ResourceUnavailableException e) { if (rollBack && isRollBackAllowedForProvider(loadBalancer)) { - for (long instanceId : instanceIds) { - LoadBalancerVMMapVO map = _lb2VmMapDao.findByLoadBalancerIdAndVmId(loadBalancerId, instanceId); - map.setRevoke(false); - _lb2VmMapDao.persist(map); - s_logger.debug("LB Rollback rule id: " + loadBalancerId + ",while removing vmId " + instanceId); + for (long instanceId : vmIds) { + List lbVmIps = vmIdIpMap.get(instanceId); + + if (lbVmIps == null || lbVmIps.isEmpty()) { + LoadBalancerVMMapVO map = _lb2VmMapDao.findByLoadBalancerIdAndVmId(loadBalancerId, instanceId); + map.setRevoke(false); + _lb2VmMapDao.persist(map); + s_logger.debug("LB Rollback rule id: " + loadBalancerId + ",while removing vmId " + instanceId); + }else { + for (String vmIp: lbVmIps) { + LoadBalancerVMMapVO map = _lb2VmMapDao.findByLoadBalancerIdAndVmIdVmIp (loadBalancerId, instanceId, vmIp); + map.setRevoke(true); + _lb2VmMapDao.persist(map); + s_logger.debug("LB Rollback rule id: " + loadBalancerId + ",while removing vmId " + + instanceId + ", vmip " + vmIp); + } + } } loadBalancer.setState(backupState); @@ -1247,7 +1401,7 @@ private boolean removeFromLoadBalancerInternal(long loadBalancerId, List i s_logger.warn("Unable to apply the load balancer config because resource is unavaliable.", e); } if (!success) { - CloudRuntimeException ex = new CloudRuntimeException("Failed to remove specified load balancer rule id for vms " + instanceIds); + CloudRuntimeException ex = new CloudRuntimeException("Failed to remove specified load balancer rule id for vms " + vmIds); ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId"); throw ex; } @@ -1282,7 +1436,7 @@ public boolean removeVmFromLoadBalancers(long instanceId) { // Reapply all lbs that had the vm assigned if (lbsToReconfigure != null) { for (Map.Entry> lb : lbsToReconfigure.entrySet()) { - if (!removeFromLoadBalancerInternal(lb.getKey(), lb.getValue(), false)) { + if (!removeFromLoadBalancerInternal(lb.getKey(), lb.getValue(), false, new HashMap>())) { success = false; } } @@ -1301,7 +1455,7 @@ public boolean deleteLoadBalancerRule(long loadBalancerId, boolean apply) { if (rule == null) { throw new InvalidParameterValueException("Unable to find load balancer rule " + loadBalancerId); } - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); boolean result = deleteLoadBalancerRule(loadBalancerId, apply, caller, ctx.getCallingUserId(), true); if (!result) { @@ -1525,7 +1679,7 @@ public LoadBalancer createPublicLoadBalancer(final String xId, final String name throw ex; } - _accountMgr.checkAccess(caller.getCallingAccount(), null, true, ipAddr); + _accountMgr.checkAccess(caller.getCallingAccount(), null, ipAddr); final Long networkId = ipAddr.getAssociatedWithNetworkId(); if (networkId == null) { @@ -1727,12 +1881,11 @@ public Boolean doInTransaction(TransactionStatus status) { for (LoadBalancerVMMapVO lbVmMap : lbVmMaps) { instanceIds.add(lbVmMap.getInstanceId()); + _lb2VmMapDao.remove(lb.getId(), lbVmMap.getInstanceId(), lbVmMap.getInstanceIp(), null); + s_logger.debug("Load balancer rule id " + lb.getId() + " is removed for vm " + + lbVmMap.getInstanceId() + " instance ip " + lbVmMap.getInstanceIp()); } - if (!instanceIds.isEmpty()) { - _lb2VmMapDao.remove(lb.getId(), instanceIds, null); - s_logger.debug("Load balancer rule id " + lb.getId() + " is removed for vms " + instanceIds); - } if (_lb2VmMapDao.listByLoadBalancerId(lb.getId()).isEmpty()) { lb.setState(FirewallRule.State.Add); @@ -1875,7 +2028,7 @@ public List getExistingDestinations(long lbId) { for (LoadBalancerVMMapVO lbVmMap : lbVmMaps) { UserVm vm = _vmDao.findById(lbVmMap.getInstanceId()); Nic nic = _nicDao.findByInstanceIdAndNetworkIdIncludingRemoved(lb.getNetworkId(), vm.getId()); - dstIp = nic.getIp4Address(); + dstIp = lbVmMap.getInstanceIp() == null ? nic.getIp4Address(): lbVmMap.getInstanceIp(); LbDestination lbDst = new LbDestination(lb.getDefaultPortStart(), lb.getDefaultPortEnd(), dstIp, lbVmMap.isRevoke()); dstList.add(lbDst); } @@ -1900,7 +2053,7 @@ public LoadBalancer updateLoadBalancerRule(UpdateLoadBalancerRuleCmd cmd) { } // check permissions - _accountMgr.checkAccess(caller, null, true, lb); + _accountMgr.checkAccess(caller, null, lb); if (name != null) { lb.setName(name); @@ -1979,7 +2132,7 @@ public Pair, List> listLoadBalancerInstances(List return null; } - _accountMgr.checkAccess(caller, null, true, loadBalancer); + _accountMgr.checkAccess(caller, null, loadBalancer); List loadBalancerInstances = new ArrayList(); List serviceStates = new ArrayList(); @@ -2022,6 +2175,18 @@ public Pair, List> listLoadBalancerInstances(List return new Pair, List>(loadBalancerInstances, serviceStates); } + @Override + public List listLbVmIpAddress (long id, long vmId) { + + List listLbvmMapVo = _lb2VmMapDao.listByLoadBalancerIdAndVmId(id, vmId); + + List vmIps = new ArrayList(); + for (LoadBalancerVMMapVO lbVmVo : listLbvmMapVo) { + vmIps.add(lbVmVo.getInstanceIp()); + } + return vmIps; + } + @Override public List getStickinessMethods(long networkid) { String capability = getLBCapability(networkid, Capability.SupportedStickinessMethods.getName()); @@ -2044,7 +2209,7 @@ public List searchForLBStickinessPolicies(ListLBStickiness return null; } - _accountMgr.checkAccess(caller, null, true, loadBalancer); + _accountMgr.checkAccess(caller, null, loadBalancer); List sDbpolicies = _lb2stickinesspoliciesDao.listByLoadBalancerId(cmd.getLbRuleId()); @@ -2059,7 +2224,7 @@ public List searchForLBHealthCheckPolicies(ListLBHealthCh if (loadBalancer == null) { return null; } - _accountMgr.checkAccess(caller, null, true, loadBalancer); + _accountMgr.checkAccess(caller, null, loadBalancer); List hcDbpolicies = _lb2healthcheckDao.listByLoadBalancerId(cmd.getLbRuleId()); return hcDbpolicies; } @@ -2241,6 +2406,15 @@ public Map getLbInstances(long lbId) { return dstList; } + @Override + public boolean isLbRuleMappedToVmGuestIp(String vmSecondaryIp) { + List lbVmMap = _lb2VmMapDao.listByInstanceIp(vmSecondaryIp); + if (lbVmMap == null || lbVmMap.isEmpty()) { + return false; + } + return true; + } + @Override public void isLbServiceSupportedInNetwork(long networkId, Scheme scheme) { Network network = _networkDao.findById(networkId); diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java index e3597acc31..ae418d239c 100644 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManager.java @@ -51,6 +51,7 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA static final String RouterTemplateHyperVCK = "router.template.hyperv"; static final String RouterTemplateLxcCK = "router.template.lxc"; static final String SetServiceMonitorCK = "network.router.EnableServiceMonitoring"; + static final String RouterAlertsCheckIntervalCK = "router.alerts.check.interval"; static final ConfigKey RouterTemplateXen = new ConfigKey(String.class, RouterTemplateXenCK, "Advanced", "SystemVM Template (XenServer)", "Name of the default router template on Xenserver.", true, ConfigKey.Scope.Zone, null); @@ -66,6 +67,9 @@ public interface VirtualNetworkApplianceManager extends Manager, VirtualNetworkA static final ConfigKey SetServiceMonitor = new ConfigKey(String.class, SetServiceMonitorCK, "Advanced", "true", "service monitoring in router enable/disable option, default true", true, ConfigKey.Scope.Zone, null); + static final ConfigKey RouterAlertsCheckInterval = new ConfigKey(Integer.class, RouterAlertsCheckIntervalCK, "Advanced", "1800", + "Interval (in seconds) to check for alerts in Virtual Router.", false, ConfigKey.Scope.Global, null); + public static final int DEFAULT_ROUTER_VM_RAMSIZE = 128; // 128M public static final int DEFAULT_ROUTER_CPU_MHZ = 500; // 500 MHz public static final boolean USE_POD_VLAN = false; diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index c692491a34..80ca1cfec7 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -17,6 +17,8 @@ package com.cloud.network.router; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -41,10 +43,14 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; + import org.apache.log4j.Logger; + +import org.apache.cloudstack.alert.AlertService.AlertType; import org.apache.cloudstack.api.command.admin.router.RebootRouterCmd; import org.apache.cloudstack.api.command.admin.router.UpgradeRouterCmd; import org.apache.cloudstack.api.command.admin.router.UpgradeRouterTemplateCmd; +import org.apache.cloudstack.config.ApiServiceConfiguration; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.framework.config.ConfigDepot; @@ -55,7 +61,7 @@ import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO; import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.utils.identity.ManagementServerNode; -import org.apache.cloudstack.alert.AlertService.AlertType; + import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; import com.cloud.agent.api.AgentControlAnswer; @@ -69,13 +75,12 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.GetDomRVersionAnswer; import com.cloud.agent.api.GetDomRVersionCmd; +import com.cloud.agent.api.GetRouterAlertsAnswer; import com.cloud.agent.api.ModifySshKeysCommand; import com.cloud.agent.api.NetworkUsageAnswer; import com.cloud.agent.api.NetworkUsageCommand; import com.cloud.agent.api.PvlanSetupCommand; import com.cloud.agent.api.StartupCommand; -import com.cloud.agent.api.routing.GetRouterAlertsCommand; -import com.cloud.agent.api.GetRouterAlertsAnswer; import com.cloud.agent.api.check.CheckSshAnswer; import com.cloud.agent.api.check.CheckSshCommand; import com.cloud.agent.api.routing.AggregationControlCommand; @@ -84,6 +89,7 @@ import com.cloud.agent.api.routing.DeleteIpAliasCommand; import com.cloud.agent.api.routing.DhcpEntryCommand; import com.cloud.agent.api.routing.DnsMasqConfigCommand; +import com.cloud.agent.api.routing.GetRouterAlertsCommand; import com.cloud.agent.api.routing.IpAliasTO; import com.cloud.agent.api.routing.IpAssocCommand; import com.cloud.agent.api.routing.LoadBalancerConfigCommand; @@ -183,6 +189,7 @@ import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.OpRouterMonitorServiceDao; +import com.cloud.network.dao.OpRouterMonitorServiceVO; import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; import com.cloud.network.dao.RemoteAccessVpnDao; import com.cloud.network.dao.Site2SiteCustomerGatewayDao; @@ -192,7 +199,6 @@ import com.cloud.network.dao.UserIpv6AddressDao; import com.cloud.network.dao.VirtualRouterProviderDao; import com.cloud.network.dao.VpnUserDao; -import com.cloud.network.dao.OpRouterMonitorServiceVO; import com.cloud.network.lb.LoadBalancingRule; import com.cloud.network.lb.LoadBalancingRule.LbDestination; import com.cloud.network.lb.LoadBalancingRule.LbHealthCheckPolicy; @@ -281,7 +287,6 @@ import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.UserVmDetailsDao; import com.cloud.vm.dao.VMInstanceDao; -import org.apache.cloudstack.config.ApiServiceConfiguration; /** * VirtualNetworkApplianceManagerImpl manages the different types of virtual network appliances available in the Cloud Stack. @@ -457,7 +462,7 @@ public VirtualRouter destroyRouter(final long routerId, final Account caller, fi return null; } - _accountMgr.checkAccess(caller, null, true, router); + _accountMgr.checkAccess(caller, null, router); _itMgr.expunge(router.getUuid()); _routerDao.remove(router.getId()); @@ -476,7 +481,7 @@ public VirtualRouter upgradeRouter(final UpgradeRouterCmd cmd) { throw new InvalidParameterValueException("Unable to find router with id " + routerId); } - _accountMgr.checkAccess(caller, null, true, router); + _accountMgr.checkAccess(caller, null, router); if (router.getServiceOfferingId() == serviceOfferingId) { s_logger.debug("Router: " + routerId + "already has service offering: " + serviceOfferingId); @@ -591,7 +596,7 @@ public VirtualRouter stopRouter(final long routerId, final boolean forced) throw throw new InvalidParameterValueException("Unable to find router by id " + routerId + "."); } - _accountMgr.checkAccess(account, null, true, router); + _accountMgr.checkAccess(account, null, router); final UserVO user = _userDao.findById(CallContext.current().getCallingUserId()); @@ -650,7 +655,7 @@ public VirtualRouter rebootRouter(final long routerId, final boolean reprogramNe throw new InvalidParameterValueException("Unable to find domain router with id " + routerId + "."); } - _accountMgr.checkAccess(caller, null, true, router); + _accountMgr.checkAccess(caller, null, router); // Can reboot domain router only in Running state if (router == null || router.getState() != State.Running) { @@ -821,6 +826,13 @@ public boolean start() { s_logger.debug("router.check.interval - " + _routerCheckInterval + " so not scheduling the redundant router checking thread"); } + int _routerAlertsCheckInterval = RouterAlertsCheckInterval.value(); + if (_routerAlertsCheckInterval > 0) { + _checkExecutor.scheduleAtFixedRate(new CheckRouterAlertsTask(), _routerAlertsCheckInterval, _routerAlertsCheckInterval, TimeUnit.SECONDS); + } else { + s_logger.debug("router.alerts.check.interval - " + _routerAlertsCheckInterval + " so not scheduling the router alerts checking thread"); + } + return true; } @@ -1355,8 +1367,6 @@ protected void runInContext() { updateSite2SiteVpnConnectionState(routers); - getRouterAlerts(); - final List networks = _networkDao.listRedundantNetworks(); s_logger.debug("Found " + networks.size() + " networks to update RvR status. "); for (final NetworkVO network : networks) { @@ -1371,20 +1381,33 @@ protected void runInContext() { } } - private void getRouterAlerts() { + protected class CheckRouterAlertsTask extends ManagedContextRunnable { + public CheckRouterAlertsTask() { + } + + @Override + protected void runInContext() { + try { + getRouterAlerts(); + } catch (final Exception ex) { + s_logger.error("Fail to complete the CheckRouterAlertsTask! ", ex); + } + } + } + + protected void getRouterAlerts() { try{ - List routersInIsolatedNetwork = _routerDao.listByStateAndNetworkType(State.Running, GuestType.Isolated, mgmtSrvrId); - List routersInSharedNetwork = _routerDao.listByStateAndNetworkType(State.Running, GuestType.Shared, mgmtSrvrId); + List routers = _routerDao.listByStateAndManagementServer(State.Running, mgmtSrvrId); - List routers = new ArrayList(); - routers.addAll(routersInIsolatedNetwork); - routers.addAll(routersInSharedNetwork); s_logger.debug("Found " + routers.size() + " running routers. "); for (final DomainRouterVO router : routers) { - if (router.getVpcId() != null) { + String serviceMonitoringFlag = SetServiceMonitor.valueIn(router.getDataCenterId()); + // Skip the routers in VPC network or skip the routers where Monitor service is not enabled in the corresponding Zone + if ( !Boolean.parseBoolean(serviceMonitoringFlag) || router.getVpcId() != null) { continue; } + String privateIP = router.getPrivateIpAddress(); if (privateIP != null) { @@ -1392,23 +1415,49 @@ private void getRouterAlerts() { GetRouterAlertsCommand command = null; if (opRouterMonitorServiceVO == null) { - command = new GetRouterAlertsCommand(null); + command = new GetRouterAlertsCommand(new String("1970-01-01 00:00:00")); // To avoid sending null value } else { command = new GetRouterAlertsCommand(opRouterMonitorServiceVO.getLastAlertTimestamp()); } command.setAccessDetail(NetworkElementCommand.ROUTER_IP, router.getPrivateIpAddress()); - command.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); - GetRouterAlertsAnswer answer = null; try { - answer = (GetRouterAlertsAnswer) _agentMgr.easySend(router.getHostId(), command); + final Answer origAnswer = _agentMgr.easySend(router.getHostId(), command); + GetRouterAlertsAnswer answer = null; + + if (origAnswer == null) { + s_logger.warn("Unable to get alerts from router " + router.getHostName()); + continue; + } + if (origAnswer instanceof GetRouterAlertsAnswer) { + answer = (GetRouterAlertsAnswer)origAnswer; + } else { + s_logger.warn("Unable to get alerts from router " + router.getHostName()); + continue; + } + if (!answer.getResult()) { + s_logger.warn("Unable to get alerts from router " + router.getHostName() + " " + answer.getDetails()); + continue; + } + String alerts[] = answer.getAlerts(); - if (alerts != null ) { + if (alerts != null) { + String lastAlertTimeStamp = answer.getTimeStamp(); + SimpleDateFormat sdfrmt = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); + sdfrmt.setLenient(false); + try + { + sdfrmt.parse(lastAlertTimeStamp); + } + catch (ParseException e) + { + s_logger.warn("Invalid last alert timestamp received while collecting alerts from router: " + router.getInstanceName()); + continue; + } for (String alert: alerts) { _alertMgr.sendAlert(AlertType.ALERT_TYPE_DOMAIN_ROUTER, router.getDataCenterId(), router.getPodIdToDeployIn(), "Monitoring Service on VR " + router.getInstanceName(), alert); } - String lastAlertTimeStamp = answer.getTimeStamp(); if (opRouterMonitorServiceVO == null) { opRouterMonitorServiceVO = new OpRouterMonitorServiceVO(router.getId(), router.getHostName(), lastAlertTimeStamp); _opRouterMonitorServiceDao.persist(opRouterMonitorServiceVO); @@ -1418,7 +1467,7 @@ private void getRouterAlerts() { } } } catch (Exception e) { - s_logger.warn("Error while collecting alerts from router: " + router.getInstanceName() + " from host: " + router.getHostId(), e); + s_logger.warn("Error while collecting alerts from router: " + router.getInstanceName(), e); continue; } } @@ -1428,7 +1477,6 @@ private void getRouterAlerts() { } } - private final static int DEFAULT_PRIORITY = 100; private final static int DEFAULT_DELTA = 2; @@ -2291,6 +2339,9 @@ protected StringBuilder createGuestBootLoadArgs(final NicProfile guestNic, final buf.append(" guestbrd=").append(brd); buf.append(" guestcidrsize=").append(NetUtils.getCidrSize(guestNic.getNetmask())); buf.append(" router_pr=").append(router.getPriority()); + + int advertInt = NumbersUtil.parseInt(_configDao.getValue(Config.RedundantRouterVrrpInterval.key()), 1); + buf.append(" advert_int=").append(advertInt); } //setup network domain @@ -2299,10 +2350,12 @@ protected StringBuilder createGuestBootLoadArgs(final NicProfile guestNic, final buf.append(" domain=" + domain); } + long cidrSize = 0; + //setup dhcp range if (dc.getNetworkType() == NetworkType.Basic) { if (guestNic.isDefaultNic()) { - final long cidrSize = NetUtils.getCidrSize(guestNic.getNetmask()); + cidrSize = NetUtils.getCidrSize(guestNic.getNetmask()); final String cidr = NetUtils.getCidrSubNet(guestNic.getGateway(), cidrSize); if (cidr != null) { dhcpRange = NetUtils.getIpRangeStartIpFromCidr(cidr, cidrSize); @@ -2311,11 +2364,14 @@ protected StringBuilder createGuestBootLoadArgs(final NicProfile guestNic, final } else if (dc.getNetworkType() == NetworkType.Advanced) { final String cidr = guestNetwork.getCidr(); if (cidr != null) { + cidrSize = NetUtils.getCidrSize(NetUtils.getCidrNetmask(cidr)); dhcpRange = NetUtils.getDhcpRange(cidr); } } if (dhcpRange != null) { + // To limit DNS to the cidr range + buf.append(" cidrsize=" + String.valueOf(cidrSize)); buf.append(" dhcprange=" + dhcpRange); } @@ -3252,7 +3308,7 @@ public VirtualRouter startRouter(final long routerId, final boolean reprogramNet if (router == null) { throw new InvalidParameterValueException("Unable to find router by id " + routerId + "."); } - _accountMgr.checkAccess(caller, null, true, router); + _accountMgr.checkAccess(caller, null, router); final Account owner = _accountMgr.getAccount(router.getAccountId()); @@ -4330,7 +4386,7 @@ public String getConfigComponentName() { @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[] {UseExternalDnsServers, routerVersionCheckEnabled, SetServiceMonitor}; + return new ConfigKey[] {UseExternalDnsServers, routerVersionCheckEnabled, SetServiceMonitor, RouterAlertsCheckInterval}; } @Override diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index 9a76219f00..573c820673 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -25,10 +25,12 @@ import javax.ejb.Local; import javax.inject.Inject; +import org.apache.log4j.Logger; + +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.user.firewall.ListPortForwardingRulesCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; -import org.apache.log4j.Logger; import com.cloud.configuration.ConfigurationManager; import com.cloud.domain.dao.DomainDao; @@ -162,7 +164,7 @@ protected void checkIpAndUserVm(IpAddress ipAddress, UserVm userVm, Account call } } - _accountMgr.checkAccess(caller, null, true, ipAddress, userVm); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, ipAddress, userVm); // validate that IP address and userVM belong to the same account if (ipAddress.getAllocatedToAccountId().longValue() != userVm.getAccountId()) { @@ -187,7 +189,7 @@ public void checkRuleAndUserVm(FirewallRule rule, UserVm userVm, Account caller) return; } - _accountMgr.checkAccess(caller, null, true, rule, userVm); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, rule, userVm); if (userVm.getState() == VirtualMachine.State.Destroyed || userVm.getState() == VirtualMachine.State.Expunging) { throw new InvalidParameterValueException("Invalid user vm: " + userVm.getId()); @@ -680,7 +682,7 @@ public boolean revokePortForwardingRule(long ruleId, boolean apply) { throw new InvalidParameterValueException("Unable to find " + ruleId); } - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); if (!revokePortForwardingRuleInternal(ruleId, caller, ctx.getCallingUserId(), apply)) { throw new CloudRuntimeException("Failed to delete port forwarding rule"); @@ -715,7 +717,7 @@ public boolean revokeStaticNatRule(long ruleId, boolean apply) { throw new InvalidParameterValueException("Unable to find " + ruleId); } - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); if (!revokeStaticNatRuleInternal(ruleId, caller, ctx.getCallingUserId(), apply)) { throw new CloudRuntimeException("Failed to revoke forwarding rule"); @@ -791,7 +793,7 @@ public Pair, Integer> listPortForwardingRules if (ipAddressVO == null || !ipAddressVO.readyToUse()) { throw new InvalidParameterValueException("Ip address id=" + ipId + " not ready for port forwarding rules yet"); } - _accountMgr.checkAccess(caller, null, true, ipAddressVO); + _accountMgr.checkAccess(caller, null, ipAddressVO); } Ternary domainIdRecursiveListProject = new Ternary(cmd.getDomainId(), cmd.isRecursive(), null); @@ -866,7 +868,7 @@ protected boolean applyPortForwardingRules(long ipId, boolean continueOnError, A } if (caller != null) { - _accountMgr.checkAccess(caller, null, true, rules.toArray(new PortForwardingRuleVO[rules.size()])); + _accountMgr.checkAccess(caller, null, rules.toArray(new PortForwardingRuleVO[rules.size()])); } try { @@ -895,7 +897,7 @@ protected boolean applyStaticNatRulesForIp(long sourceIpId, boolean continueOnEr } if (caller != null) { - _accountMgr.checkAccess(caller, null, true, staticNatRules.toArray(new StaticNatRule[staticNatRules.size()])); + _accountMgr.checkAccess(caller, null, staticNatRules.toArray(new StaticNatRule[staticNatRules.size()])); } try { @@ -919,7 +921,7 @@ public boolean applyPortForwardingRulesForNetwork(long networkId, boolean contin } if (caller != null) { - _accountMgr.checkAccess(caller, null, true, rules.toArray(new PortForwardingRuleVO[rules.size()])); + _accountMgr.checkAccess(caller, null, rules.toArray(new PortForwardingRuleVO[rules.size()])); } try { @@ -945,7 +947,7 @@ public boolean applyStaticNatRulesForNetwork(long networkId, boolean continueOnE } if (caller != null) { - _accountMgr.checkAccess(caller, null, true, rules.toArray(new FirewallRule[rules.size()])); + _accountMgr.checkAccess(caller, null, rules.toArray(new FirewallRule[rules.size()])); } for (FirewallRuleVO rule : rules) { @@ -973,7 +975,7 @@ public boolean applyStaticNatsForNetwork(long networkId, boolean continueOnError } if (caller != null) { - _accountMgr.checkAccess(caller, null, true, ips.toArray(new IPAddressVO[ips.size()])); + _accountMgr.checkAccess(caller, null, ips.toArray(new IPAddressVO[ips.size()])); } List staticNats = new ArrayList(); @@ -1009,7 +1011,7 @@ public Pair, Integer> searchStaticNatRules(Long ipI if (ipAddressVO == null || !ipAddressVO.readyToUse()) { throw new InvalidParameterValueException("Ip address id=" + ipId + " not ready for port forwarding rules yet"); } - _accountMgr.checkAccess(caller, null, true, ipAddressVO); + _accountMgr.checkAccess(caller, null, ipAddressVO); } Ternary domainIdRecursiveListProject = new Ternary(domainId, isRecursive, null); @@ -1386,7 +1388,7 @@ protected List createStaticNatForIp(IpAddress sourceIp, Account calle } if (caller != null) { - _accountMgr.checkAccess(caller, null, true, sourceIp); + _accountMgr.checkAccess(caller, null, sourceIp); } // create new static nat rule @@ -1505,7 +1507,7 @@ public PortForwardingRule updatePortForwardingRule(long id, String customId, Boo if (rule == null) { throw new InvalidParameterValueException("Unable to find " + id); } - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); if (customId != null) { rule.setUuid(customId); diff --git a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java index cf71b25119..b4c67b8d74 100755 --- a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java +++ b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java @@ -612,7 +612,7 @@ private List authorizeSecurityGroupRule(final Long security } // Verify permissions - _accountMgr.checkAccess(caller, null, true, securityGroup); + _accountMgr.checkAccess(caller, null, securityGroup); Long domainId = owner.getDomainId(); if (protocol == null) { @@ -716,7 +716,7 @@ private List authorizeSecurityGroupRule(final Long security final Integer startPortOrTypeFinal = startPortOrType; final Integer endPortOrCodeFinal = endPortOrCode; final String protocolFinal = protocol; - return Transaction.execute(new TransactionCallback>() { + List newRules = Transaction.execute(new TransactionCallback>() { @Override public List doInTransaction(TransactionStatus status) { // Prevents other threads/management servers from creating duplicate security rules @@ -761,9 +761,6 @@ public List doInTransaction(TransactionStatus status) { if (s_logger.isDebugEnabled()) { s_logger.debug("Added " + newRules.size() + " rules to security group " + securityGroup.getName()); } - final ArrayList affectedVms = new ArrayList(); - affectedVms.addAll(_securityGroupVMMapDao.listVmIdsBySecurityGroup(securityGroup.getId())); - scheduleRulesetUpdateToHosts(affectedVms, true, null); return newRules; } catch (Exception e) { s_logger.warn("Exception caught when adding security group rules ", e); @@ -776,6 +773,15 @@ public List doInTransaction(TransactionStatus status) { } }); + try { + final ArrayList affectedVms = new ArrayList(); + affectedVms.addAll(_securityGroupVMMapDao.listVmIdsBySecurityGroup(securityGroup.getId())); + scheduleRulesetUpdateToHosts(affectedVms, true, null); + } catch (Exception e) { + s_logger.debug("can't update rules on host, ignore", e); + } + + return newRules; } @Override @@ -813,9 +819,10 @@ private boolean revokeSecurityGroupRule(final Long id, SecurityRuleType type) { // Check permissions SecurityGroup securityGroup = _securityGroupDao.findById(rule.getSecurityGroupId()); - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, securityGroup); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, securityGroup); - return Transaction.execute(new TransactionCallback() { + long securityGroupId = rule.getSecurityGroupId(); + Boolean result = Transaction.execute(new TransactionCallback() { @Override public Boolean doInTransaction(TransactionStatus status) { SecurityGroupVO groupHandle = null; @@ -831,10 +838,6 @@ public Boolean doInTransaction(TransactionStatus status) { _securityGroupRuleDao.remove(id); s_logger.debug("revokeSecurityGroupRule succeeded for security rule id: " + id); - final ArrayList affectedVms = new ArrayList(); - affectedVms.addAll(_securityGroupVMMapDao.listVmIdsBySecurityGroup(groupHandle.getId())); - scheduleRulesetUpdateToHosts(affectedVms, true, null); - return true; } catch (Exception e) { s_logger.warn("Exception caught when deleting security rules ", e); @@ -846,6 +849,16 @@ public Boolean doInTransaction(TransactionStatus status) { } } }); + + try { + final ArrayList affectedVms = new ArrayList(); + affectedVms.addAll(_securityGroupVMMapDao.listVmIdsBySecurityGroup(securityGroupId)); + scheduleRulesetUpdateToHosts(affectedVms, true, null); + } catch (Exception e) { + s_logger.debug("Can't update rules for host, ignore", e); + } + + return result; } @Override @@ -1107,7 +1120,7 @@ public boolean deleteSecurityGroup(DeleteSecurityGroupCmd cmd) throws ResourceIn } // check permissions - _accountMgr.checkAccess(caller, null, true, group); + _accountMgr.checkAccess(caller, null, group); return Transaction.execute(new TransactionCallbackWithException() { @Override @@ -1346,20 +1359,21 @@ public boolean securityGroupRulesForVmSecIp(long nicId, String secondaryIp, bool } // Verify permissions - _accountMgr.checkAccess(caller, null, false, vm); + _accountMgr.checkAccess(caller, null, vm); // Validate parameters List vmSgGrps = getSecurityGroupsForVm(vmId); - if (vmSgGrps == null) { + if (vmSgGrps.isEmpty()) { s_logger.debug("Vm is not in any Security group "); return true; } - for (SecurityGroupVO securityGroup : vmSgGrps) { - Account owner = _accountMgr.getAccount(securityGroup.getAccountId()); - if (owner == null) { - throw new InvalidParameterValueException("Unable to find security group owner by id=" + securityGroup.getAccountId()); - } + //If network does not support SG service, no need add SG rules for secondary ip + Network network = _networkModel.getNetwork(nic.getNetworkId()); + if (!_networkModel.isSecurityGroupSupportedInNetwork(network)) { + s_logger.debug("Network " + network + " is not enabled with security group service, "+ + "so not applying SG rules for secondary ip"); + return true; } String vmMac = vm.getPrivateMacAddress(); diff --git a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java index e024fbe3d3..72996d160c 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java @@ -103,7 +103,7 @@ public NetworkACL createNetworkACL(String name, String description, long vpcId, if (vpc == null) { throw new InvalidParameterValueException("Unable to find VPC"); } - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); return _networkAclMgr.createNetworkACL(name, description, vpcId, forDisplay); } @@ -161,7 +161,7 @@ public Pair, Integer> listNetworkACLs(ListNetworkACLL if (vpc == null) { throw new InvalidParameterValueException("Unable to find VPC"); } - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); //Include vpcId 0 to list default ACLs sc.setParameters("vpcId", vpcId, 0); } else { @@ -225,7 +225,7 @@ public boolean deleteNetworkACL(long id) { if (vpc == null) { throw new InvalidParameterValueException("Unable to find specified VPC associated with the ACL"); } - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); return _networkAclMgr.deleteNetworkACL(acl); } @@ -256,14 +256,14 @@ public boolean replaceNetworkACLonPrivateGw(long aclId, long privateGatewayId) t if (vpc == null) { throw new InvalidParameterValueException("Unable to find Vpc associated with the NetworkACL"); } - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); if (!gateway.getVpcId().equals(acl.getVpcId())) { throw new InvalidParameterValueException("private gateway: " + privateGatewayId + " and ACL: " + aclId + " do not belong to the same VPC"); } } PrivateGateway privateGateway = _vpcSvc.getVpcPrivateGateway(gateway.getId()); - _accountMgr.checkAccess(caller, null, true, privateGateway); + _accountMgr.checkAccess(caller, null, privateGateway); return _networkAclMgr.replaceNetworkACLForPrivateGw(acl, privateGateway); @@ -299,7 +299,7 @@ public boolean replaceNetworkACL(long aclId, long networkId) throws ResourceUnav throw new InvalidParameterValueException("Unable to find Vpc associated with the NetworkACL"); } - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); if (!network.getVpcId().equals(acl.getVpcId())) { throw new InvalidParameterValueException("Network: " + networkId + " and ACL: " + aclId + " do not belong to the same VPC"); } @@ -371,7 +371,7 @@ public NetworkACLItem createNetworkACLItem(CreateNetworkACLCmd aclItemCmd) { if (vpc == null) { throw new InvalidParameterValueException("Unable to find Vpc associated with the NetworkACL"); } - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); //Ensure that number is unique within the ACL if (aclItemCmd.getNumber() != null) { @@ -532,6 +532,11 @@ public Pair, Integer> listNetworkACLItems(ListNet if (networkId != null) { Network network = _networkDao.findById(networkId); aclId = network.getNetworkACLId(); + if( aclId == null){ + // No aclId associated with the network. + //Return empty list + return new Pair(new ArrayList(), 0); + } } if (trafficType != null) { @@ -546,7 +551,7 @@ public Pair, Integer> listNetworkACLItems(ListNet if (vpc == null) { throw new InvalidParameterValueException("Unable to find VPC associated with acl"); } - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); } sc.setParameters("aclId", aclId); } else { @@ -615,7 +620,7 @@ public boolean revokeNetworkACLItem(long ruleId) { Account caller = CallContext.current().getCallingAccount(); - _accountMgr.checkAccess(caller, null, true, vpc); + _accountMgr.checkAccess(caller, null, vpc); if((aclItem.getAclId() == NetworkACL.DEFAULT_ALLOW) || (aclItem.getAclId() == NetworkACL.DEFAULT_DENY)){ throw new InvalidParameterValueException("ACL Items in default ACL cannot be deleted"); @@ -642,7 +647,7 @@ public NetworkACLItem updateNetworkACLItem(Long id, String protocol, List getEntityType() { + return VpcGateway.class; } } diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index 2e63639c33..c517fb1c72 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.network.vpc; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -34,7 +35,10 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.log4j.Logger; + import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.user.vpc.ListPrivateGatewaysCmd; import org.apache.cloudstack.api.command.user.vpc.ListStaticRoutesCmd; import org.apache.cloudstack.context.CallContext; @@ -42,7 +46,6 @@ import org.apache.cloudstack.framework.config.ConfigDepot; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.managed.context.ManagedContextRunnable; -import org.apache.log4j.Logger; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; @@ -65,7 +68,6 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.hypervisor.Hypervisor.HypervisorType; -import com.cloud.network.element.NetworkElement; import com.cloud.network.IpAddress; import com.cloud.network.IpAddressManager; import com.cloud.network.Network; @@ -85,6 +87,7 @@ import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.PhysicalNetworkDao; import com.cloud.network.dao.Site2SiteVpnGatewayDao; +import com.cloud.network.element.NetworkElement; import com.cloud.network.element.StaticNatServiceProvider; import com.cloud.network.element.VpcProvider; import com.cloud.network.vpc.VpcOffering.State; @@ -220,44 +223,49 @@ public boolean configure(String name, Map params) throws Configu Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { - if (_vpcOffDao.findByUniqueName(VpcOffering.defaultVPCOfferingName) == null) { - s_logger.debug("Creating default VPC offering " + VpcOffering.defaultVPCOfferingName); - - Map> svcProviderMap = new HashMap>(); - Set defaultProviders = new HashSet(); - defaultProviders.add(Provider.VPCVirtualRouter); - for (Service svc : getSupportedServices()) { - if (svc == Service.Lb) { - Set lbProviders = new HashSet(); - lbProviders.add(Provider.VPCVirtualRouter); - lbProviders.add(Provider.InternalLbVm); - svcProviderMap.put(svc, lbProviders); - } else { - svcProviderMap.put(svc, defaultProviders); + + if (_vpcOffDao.findByUniqueName(VpcOffering.defaultVPCOfferingName) == null) { + s_logger.debug("Creating default VPC offering " + VpcOffering.defaultVPCOfferingName); + + Map> svcProviderMap = new HashMap>(); + Set defaultProviders = new HashSet(); + defaultProviders.add(Provider.VPCVirtualRouter); + for (Service svc : getSupportedServices()) { + if (svc == Service.Lb) { + Set lbProviders = new HashSet(); + lbProviders.add(Provider.VPCVirtualRouter); + lbProviders.add(Provider.InternalLbVm); + svcProviderMap.put(svc, lbProviders); + } else { + svcProviderMap.put(svc, defaultProviders); + } + } + createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, + svcProviderMap, true, State.Enabled, null, false, false); } - } - createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, svcProviderMap, true, State.Enabled, null, false); - } - //configure default vpc offering with Netscaler as LB Provider + //configure default vpc offering with Netscaler as LB Provider if (_vpcOffDao.findByUniqueName(VpcOffering.defaultVPCNSOfferingName) == null) { - s_logger.debug("Creating default VPC offering with Netscaler as LB Provider" + VpcOffering.defaultVPCNSOfferingName); - Map> svcProviderMap = new HashMap>(); - Set defaultProviders = new HashSet(); - defaultProviders.add(Provider.VPCVirtualRouter); - for (Service svc : getSupportedServices()) { - if (svc == Service.Lb) { - Set lbProviders = new HashSet(); - lbProviders.add(Provider.Netscaler); - lbProviders.add(Provider.InternalLbVm); - svcProviderMap.put(svc, lbProviders); - } else { - svcProviderMap.put(svc, defaultProviders); + s_logger.debug("Creating default VPC offering with Netscaler as LB Provider" + VpcOffering.defaultVPCNSOfferingName); + Map> svcProviderMap = new HashMap>(); + Set defaultProviders = new HashSet(); + defaultProviders.add(Provider.VPCVirtualRouter); + for (Service svc : getSupportedServices()) { + if (svc == Service.Lb) { + Set lbProviders = new HashSet(); + lbProviders.add(Provider.Netscaler); + lbProviders.add(Provider.InternalLbVm); + svcProviderMap.put(svc, lbProviders); + } else { + svcProviderMap.put(svc, defaultProviders); + } + } + createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName, + svcProviderMap, false, State.Enabled, null, false, false); + } } - createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName, svcProviderMap, false, State.Enabled, null, false); - } - } + }); Map configs = _configDao.getConfiguration(params); @@ -380,10 +388,12 @@ public VpcOffering createVpcOffering(String name, String displayText, List> svcProviderMap, final boolean isDefault, final State state, final Long serviceOfferingId, - final boolean supportsDistributedRouter) { + final boolean supportsDistributedRouter, final boolean offersRegionLevelVPC) { + return Transaction.execute(new TransactionCallback() { @Override public VpcOffering doInTransaction(TransactionStatus status) { // create vpc offering object - VpcOfferingVO offering = new VpcOfferingVO(name, displayText, isDefault, serviceOfferingId, supportsDistributedRouter); + VpcOfferingVO offering = new VpcOfferingVO(name, displayText, isDefault, serviceOfferingId, + supportsDistributedRouter, offersRegionLevelVPC); - if (state != null) { - offering.setState(state); - } - s_logger.debug("Adding vpc offering " + offering); - offering = _vpcOffDao.persist(offering); - // populate services and providers - if (svcProviderMap != null) { - for (Network.Service service : svcProviderMap.keySet()) { - Set providers = svcProviderMap.get(service); - if (providers != null && !providers.isEmpty()) { - for (Network.Provider provider : providers) { - VpcOfferingServiceMapVO offService = new VpcOfferingServiceMapVO(offering.getId(), service, provider); - _vpcOffSvcMapDao.persist(offService); - s_logger.trace("Added service for the vpc offering: " + offService + " with provider " + provider.getName()); + if (state != null) { + offering.setState(state); + } + s_logger.debug("Adding vpc offering " + offering); + offering = _vpcOffDao.persist(offering); + // populate services and providers + if (svcProviderMap != null) { + for (Network.Service service : svcProviderMap.keySet()) { + Set providers = svcProviderMap.get(service); + if (providers != null && !providers.isEmpty()) { + for (Network.Provider provider : providers) { + VpcOfferingServiceMapVO offService = new VpcOfferingServiceMapVO(offering.getId(), service, provider); + _vpcOffSvcMapDao.persist(offService); + s_logger.trace("Added service for the vpc offering: " + offService + " with provider " + provider.getName()); + } + } else { + throw new InvalidParameterValueException("Provider is missing for the VPC offering service " + service.getName()); + } } - } else { - throw new InvalidParameterValueException("Provider is missing for the VPC offering service " + service.getName()); } - } - } - return offering; - } + return offering; + } }); } - private boolean isVpcOfferingSupportsDistributedRouter(Map serviceCapabilitystList) { - boolean supportsDistributedRouter = false; + private void validateConnectivtyServiceCapablitlies(Set providers, Map serviceCapabilitystList) { + if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) { Collection serviceCapabilityCollection = serviceCapabilitystList.values(); Iterator iter = serviceCapabilityCollection.iterator(); Map capabilityMap = null; + boolean distributedRouterCapabilitySpecified = false; + boolean regionLevelVpcCapabilitySpecified = false; while (iter.hasNext()) { HashMap svcCapabilityMap = (HashMap)iter.next(); @@ -448,24 +462,56 @@ private boolean isVpcOfferingSupportsDistributedRouter(Map serviceCapabilitystLi } if (!svc.equalsIgnoreCase(Service.Connectivity.getName())) { - throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only for 'Connectivity' service capabilities can be specified"); + throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only 'Connectivity'" + + " service capabilities can be specified"); } - if (!capabilityName.equalsIgnoreCase("DistributedRouter")) { - throw new InvalidParameterValueException("Invalid Capability:" + capabilityName + " specified. Only 'DistributedRouter' capability can be specified."); + if (!capabilityName.equalsIgnoreCase("DistributedRouter") && !capabilityName.equalsIgnoreCase("RegionLevelVpc")) { + throw new InvalidParameterValueException("Invalid Capability:" + capabilityName + " specified." + + " Only 'DistributedRouter'/'RegionLevelVpc' capability can be specified."); + } + + if (capabilityName.equalsIgnoreCase("DistributedRouter")) { + distributedRouterCapabilitySpecified = true; + } + + if (capabilityName.equalsIgnoreCase("RegionLevelVpc")) { + regionLevelVpcCapabilitySpecified = true; } if (!capabilityValue.equalsIgnoreCase("true") && capabilityValue.equalsIgnoreCase("false")) { throw new InvalidParameterValueException("Invalid Capability value:" + capabilityValue + " specified."); } - supportsDistributedRouter = capabilityValue.equalsIgnoreCase("true"); + } + + if (providers != null && !providers.isEmpty()) { + for (Provider provider: providers) { + NetworkElement element = _ntwkModel.getElementImplementingProvider(provider.getName()); + Map> capabilities = element.getCapabilities(); + if (capabilities != null && !capabilities.isEmpty()) { + Map connectivityCapabilities = capabilities.get(Service.Connectivity); + if (regionLevelVpcCapabilitySpecified) { + if (connectivityCapabilities == null || (connectivityCapabilities != null && + !connectivityCapabilities.keySet().contains(Network.Capability.RegionLevelVpc))) { + throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support " + + Network.Capability.RegionLevelVpc.getName() + " capability."); + } + } + if (distributedRouterCapabilitySpecified) { + if (connectivityCapabilities == null || (connectivityCapabilities != null && + !connectivityCapabilities.keySet().contains(Network.Capability.DistributedRouter))) { + throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support " + + Network.Capability.DistributedRouter.getName() + " capability."); + } + } + } + } } } - return supportsDistributedRouter; } - private void validateConnectivtyServiceCapablitlies(Set providers, Map serviceCapabilitystList) { - + private boolean isVpcOfferingForRegionLevelVpc(Map serviceCapabilitystList) { + boolean offersRegionLevelVPC = false; if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) { Collection serviceCapabilityCollection = serviceCapabilitystList.values(); Iterator iter = serviceCapabilityCollection.iterator(); @@ -489,29 +535,55 @@ private void validateConnectivtyServiceCapablitlies(Set providers, Map throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only for 'Connectivity' service capabilities can be specified"); } - if (!capabilityName.equalsIgnoreCase("DistributedRouter")) { - throw new InvalidParameterValueException("Invalid Capability:" + capabilityName + " specified. Only 'DistributedRouter' capability can be specified."); + if (!capabilityName.equalsIgnoreCase("RegionLevelVpc")) { + continue; } if (!capabilityValue.equalsIgnoreCase("true") && capabilityValue.equalsIgnoreCase("false")) { throw new InvalidParameterValueException("Invalid Capability value:" + capabilityValue + " specified."); } + offersRegionLevelVPC = capabilityValue.equalsIgnoreCase("true"); } + } + return offersRegionLevelVPC; + } - if (providers != null && !providers.isEmpty()) { - for (Provider provider: providers) { - NetworkElement element = _ntwkModel.getElementImplementingProvider(provider.getName()); - Map> capabilities = element.getCapabilities(); - if (capabilities != null && !capabilities.isEmpty()) { - Map connectivityCapabilities = capabilities.get(Service.Connectivity); - if (connectivityCapabilities == null || (connectivityCapabilities != null && !connectivityCapabilities.keySet().contains(Network.Capability.DistributedRouter))) { - throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support " - + Network.Capability.DistributedRouter.getName() + " capability."); - } - } + private boolean isVpcOfferingSupportsDistributedRouter(Map serviceCapabilitystList) { + boolean supportsDistributedRouter = false; + if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) { + Collection serviceCapabilityCollection = serviceCapabilitystList.values(); + Iterator iter = serviceCapabilityCollection.iterator(); + Map capabilityMap = null; + + while (iter.hasNext()) { + HashMap svcCapabilityMap = (HashMap)iter.next(); + Network.Capability capability = null; + String svc = svcCapabilityMap.get("service"); + String capabilityName = svcCapabilityMap.get("capabilitytype"); + String capabilityValue = svcCapabilityMap.get("capabilityvalue"); + if (capabilityName != null) { + capability = Network.Capability.getCapability(capabilityName); + } + + if ((capability == null) || (capabilityName == null) || (capabilityValue == null)) { + throw new InvalidParameterValueException("Invalid capability:" + capabilityName + " capability value:" + capabilityValue); + } + + if (!svc.equalsIgnoreCase(Service.Connectivity.getName())) { + throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only for 'Connectivity' service capabilities can be specified"); + } + + if (!capabilityName.equalsIgnoreCase("DistributedRouter")) { + continue; } + + if (!capabilityValue.equalsIgnoreCase("true") && capabilityValue.equalsIgnoreCase("false")) { + throw new InvalidParameterValueException("Invalid Capability value:" + capabilityValue + " specified."); + } + supportsDistributedRouter = capabilityValue.equalsIgnoreCase("true"); } } + return supportsDistributedRouter; } @Override @@ -691,7 +763,7 @@ public Vpc createVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName Account owner = _accountMgr.getAccount(vpcOwnerId); //Verify that caller can perform actions in behalf of vpc owner - _accountMgr.checkAccess(caller, null, false, owner); + _accountMgr.checkAccess(caller, null, owner); //check resource limit _resourceLimitMgr.checkResourceLimit(owner, ResourceType.vpc); @@ -708,6 +780,11 @@ public Vpc createVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName throw ex; } + boolean isRegionLevelVpcOff = vpcOff.offersRegionLevelVPC(); + if (isRegionLevelVpcOff && networkDomain == null) { + throw new InvalidParameterValueException("Network domain must be specified for region level VPC"); + } + //Validate zone DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId); if (zone == null) { @@ -730,13 +807,15 @@ public Vpc createVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName networkDomain = "cs" + Long.toHexString(owner.getId()) + NetworkOrchestrationService.GuestDomainSuffix.valueIn(zoneId); } } + boolean useDistributedRouter = vpcOff.supportsDistributedRouter(); - return createVpc(zoneId, vpcOffId, owner, vpcName, displayText, cidr, networkDomain, displayVpc, useDistributedRouter); + return createVpc(zoneId, vpcOffId, owner, vpcName, displayText, cidr, networkDomain, displayVpc, + useDistributedRouter, isRegionLevelVpcOff); } @DB protected Vpc createVpc(final long zoneId, final long vpcOffId, final Account vpcOwner, final String vpcName, final String displayText, final String cidr, - final String networkDomain, final Boolean displayVpc, final boolean useDistributedRouter) { + final String networkDomain, final Boolean displayVpc, final boolean useDistributedRouter, final boolean regionLevelVpc) { //Validate CIDR if (!NetUtils.isValidCIDR(cidr)) { @@ -759,7 +838,8 @@ protected Vpc createVpc(final long zoneId, final long vpcOffId, final Account vp @Override public VpcVO doInTransaction(TransactionStatus status) { VpcVO vpc = new VpcVO(zoneId, vpcName, displayText, vpcOwner.getId(), vpcOwner.getDomainId(), vpcOffId, - cidr, networkDomain, useDistributedRouter); + cidr, networkDomain, useDistributedRouter, regionLevelVpc); + if (displayVpc != null) { vpc.setDisplay(displayVpc); } @@ -816,7 +896,7 @@ public boolean deleteVpc(long vpcId) throws ConcurrentOperationException, Resour } //verify permissions - _accountMgr.checkAccess(ctx.getCallingAccount(), null, false, vpc); + _accountMgr.checkAccess(ctx.getCallingAccount(), null, vpc); return destroyVpc(vpc, ctx.getCallingAccount(), ctx.getCallingUserId()); } @@ -884,7 +964,7 @@ public Vpc updateVpc(long vpcId, String vpcName, String displayText, String cust throw new InvalidParameterValueException("Unable to find vpc by id " + vpcId); } - _accountMgr.checkAccess(caller, null, false, vpcToUpdate); + _accountMgr.checkAccess(caller, null, vpcToUpdate); VpcVO vpc = _vpcDao.createForUpdate(vpcId); @@ -1076,7 +1156,7 @@ public boolean startVpc(long vpcId, boolean destroyOnFailure) throws ConcurrentO } //permission check - _accountMgr.checkAccess(caller, null, false, vpc); + _accountMgr.checkAccess(caller, null, vpc); DataCenter dc = _entityMgr.findById(DataCenter.class, vpc.getZoneId()); @@ -1136,7 +1216,7 @@ public boolean shutdownVpc(long vpcId) throws ConcurrentOperationException, Reso } //permission check - _accountMgr.checkAccess(caller, null, false, vpc); + _accountMgr.checkAccess(caller, null, vpc); //shutdown provider s_logger.debug("Shutting down vpc " + vpc); @@ -1199,7 +1279,9 @@ public void validateNtwkOffForNtwkInVpc(Long networkId, long newNtwkOffId, Strin continue; } else { NetworkOffering otherOff = _entityMgr.findById(NetworkOffering.class, network.getNetworkOfferingId()); - if (_ntwkModel.areServicesSupportedInNetwork(network.getId(), Service.Lb) && otherOff.getPublicLb()) { + //throw only if networks have different offerings with public lb support + if (_ntwkModel.areServicesSupportedInNetwork(network.getId(), Service.Lb) && otherOff.getPublicLb() && + guestNtwkOff.getId() != otherOff.getId()) { throw new InvalidParameterValueException("Public LB service is already supported " + "by network " + network + " in VPC " + vpc); } } @@ -1400,7 +1482,7 @@ public boolean restartVpc(long vpcId) throws ConcurrentOperationException, Resou throw ex; } - _accountMgr.checkAccess(caller, null, false, vpc); + _accountMgr.checkAccess(caller, null, vpc); s_logger.debug("Restarting VPC " + vpc); boolean restartRequired = false; @@ -1734,7 +1816,7 @@ public Pair, Integer> listPrivateGateway(ListPrivateGateway } SearchCriteria sc = sb.create(); - _accountMgr.buildACLSearchBuilder(sb, isRecursive, permittedDomains, permittedAccounts, permittedResources, listProjectResourcesCriteria); + _accountMgr.buildACLSearchCriteria(sc, isRecursive, permittedDomains, permittedAccounts, permittedResources, listProjectResourcesCriteria); if (id != null) { sc.addAnd("id", Op.EQ, id); @@ -1847,7 +1929,7 @@ public boolean revokeStaticRoute(long routeId) throws ResourceUnavailableExcepti throw new InvalidParameterValueException("Unable to find static route by id"); } - _accountMgr.checkAccess(caller, null, false, route); + _accountMgr.checkAccess(caller, null, route); markStaticRouteForRevoke(route, caller); @@ -1895,7 +1977,7 @@ public StaticRoute createStaticRoute(long gatewayId, final String cidr) throws N if (vpc == null) { throw new InvalidParameterValueException("Can't add static route to VPC that is being deleted"); } - _accountMgr.checkAccess(caller, null, false, vpc); + _accountMgr.checkAccess(caller, null, vpc); if (!NetUtils.isValidCIDR(cidr)) { throw new InvalidParameterValueException("Invalid format for cidr " + cidr); @@ -2047,7 +2129,7 @@ protected void detectRoutesConflict(StaticRoute newRoute) throws NetworkRuleConf protected void markStaticRouteForRevoke(StaticRouteVO route, Account caller) { s_logger.debug("Revoking static route " + route); if (caller != null) { - _accountMgr.checkAccess(caller, null, false, route); + _accountMgr.checkAccess(caller, null, route); } if (route.getState() == StaticRoute.State.Staged) { @@ -2111,7 +2193,6 @@ public IpAddress associateIPToVpc(final long ipId, final long vpcId) throws Reso IpAddress ipToAssoc = _ntwkModel.getIp(ipId); if (ipToAssoc != null) { - _accountMgr.checkAccess(caller, null, true, ipToAssoc); owner = _accountMgr.getAccount(ipToAssoc.getAllocatedToAccountId()); } else { s_logger.debug("Unable to find ip address by id: " + ipId); @@ -2124,7 +2205,7 @@ public IpAddress associateIPToVpc(final long ipId, final long vpcId) throws Reso } // check permissions - _accountMgr.checkAccess(caller, null, true, owner, vpc); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, ipToAssoc, vpc); boolean isSourceNat = false; if (getExistingSourceNatInVpc(owner.getId(), vpcId) == null) { @@ -2204,13 +2285,13 @@ public Network createVpcGuestNetwork(long ntwkOffId, String name, String display ex.addProxyObject(String.valueOf(vpcId), "VPC"); throw ex; } - _accountMgr.checkAccess(caller, null, false, vpc); + _accountMgr.checkAccess(caller, null, vpc); if (networkDomain == null) { networkDomain = vpc.getNetworkDomain(); } - if (vpc.getZoneId() != zoneId) { + if (!vpc.isRegionLevelVpc() && vpc.getZoneId() != zoneId) { throw new InvalidParameterValueException("New network doesn't belong to vpc zone"); } diff --git a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java index 531adad352..0f734dddef 100755 --- a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java @@ -150,7 +150,7 @@ public RemoteAccessVpn createRemoteAccessVpn(final long publicIpId, String ipRan throw new InvalidParameterValueException("Unable to create remote access vpn, invalid public IP address id" + publicIpId); } - _accountMgr.checkAccess(caller, null, true, ipAddr); + _accountMgr.checkAccess(caller, null, ipAddr); if (!ipAddr.readyToUse()) { throw new InvalidParameterValueException("The Ip address is not ready to be used yet: " + ipAddr.getAddress()); @@ -292,7 +292,7 @@ public void destroyRemoteAccessVpnForIp(long ipId, Account caller) throws Resour return; } - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, vpn); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, vpn); vpn.setState(RemoteAccessVpn.State.Removed); _remoteAccessVpnDao.update(vpn.getId(), vpn); @@ -387,7 +387,7 @@ public VpnUser doInTransaction(TransactionStatus status) { if (owner == null) { throw new InvalidParameterValueException("Unable to add vpn user: Another operation active"); } - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); //don't allow duplicated user names for the same account VpnUserVO vpnUser = _vpnUsersDao.findByAccountAndUsername(owner.getId(), username); @@ -416,7 +416,7 @@ public boolean removeVpnUser(long vpnOwnerId, String username, Account caller) { if (user == null) { throw new InvalidParameterValueException("Could not find vpn user " + username); } - _accountMgr.checkAccess(caller, null, true, user); + _accountMgr.checkAccess(caller, null, user); Transaction.execute(new TransactionCallbackNoReturn() { @Override @@ -435,7 +435,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { public List listVpnUsers(long vpnOwnerId, String userName) { Account caller = CallContext.current().getCallingAccount(); Account owner = _accountDao.findById(vpnOwnerId); - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); return _vpnUsersDao.listByAccount(vpnOwnerId); } @@ -453,7 +453,7 @@ public RemoteAccessVpnVO startRemoteAccessVpn(long ipAddressId, boolean openFire openFirewall = false; } - _accountMgr.checkAccess(caller, null, true, vpn); + _accountMgr.checkAccess(caller, null, vpn); boolean started = false; try { @@ -499,7 +499,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { public boolean applyVpnUsers(long vpnOwnerId, String userName) { Account caller = CallContext.current().getCallingAccount(); Account owner = _accountDao.findById(vpnOwnerId); - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); s_logger.debug("Applying vpn users for " + owner); List vpns = _remoteAccessVpnDao.findByAccount(vpnOwnerId); @@ -636,7 +636,7 @@ public Pair, Integer> searchForRemoteAccessVpns( throw new InvalidParameterValueException("Unable to list remote access vpns, IP address " + ipAddressId + " is not associated with an account."); } } - _accountMgr.checkAccess(caller, null, true, publicIp); + _accountMgr.checkAccess(caller, null, publicIp); } Ternary domainIdRecursiveListProject = new Ternary(cmd.getDomainId(), cmd.isRecursive(), null); @@ -747,7 +747,7 @@ public RemoteAccessVpn updateRemoteAccessVpn(long id, String customId, Boolean f throw new InvalidParameterValueException("Can't find remote access vpn by id " + id); } - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, vpn); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, vpn); if (customId != null) { vpn.setUuid(customId); } diff --git a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java index fdb5bbf124..1d6ed22b41 100644 --- a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java @@ -24,6 +24,9 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + import org.apache.cloudstack.api.command.user.vpn.CreateVpnConnectionCmd; import org.apache.cloudstack.api.command.user.vpn.CreateVpnCustomerGatewayCmd; import org.apache.cloudstack.api.command.user.vpn.CreateVpnGatewayCmd; @@ -37,8 +40,6 @@ import org.apache.cloudstack.api.command.user.vpn.UpdateVpnCustomerGatewayCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; import com.cloud.configuration.Config; import com.cloud.event.ActionEvent; @@ -124,7 +125,7 @@ public Site2SiteVpnGateway createVpnGateway(CreateVpnGatewayCmd cmd) { Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); //Verify that caller can perform actions in behalf of vpc owner - _accountMgr.checkAccess(caller, null, false, owner); + _accountMgr.checkAccess(caller, null, owner); Long vpcId = cmd.getVpcId(); VpcVO vpc = _vpcDao.findById(vpcId); @@ -174,7 +175,7 @@ public Site2SiteCustomerGateway createCustomerGateway(CreateVpnCustomerGatewayCm Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); //Verify that caller can perform actions in behalf of vpc owner - _accountMgr.checkAccess(caller, null, false, owner); + _accountMgr.checkAccess(caller, null, owner); String name = cmd.getName(); String gatewayIp = cmd.getGatewayIp(); @@ -242,21 +243,21 @@ public Site2SiteVpnConnection createVpnConnection(CreateVpnConnectionCmd cmd) th Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); //Verify that caller can perform actions in behalf of vpc owner - _accountMgr.checkAccess(caller, null, false, owner); + _accountMgr.checkAccess(caller, null, owner); Long customerGatewayId = cmd.getCustomerGatewayId(); Site2SiteCustomerGateway customerGateway = _customerGatewayDao.findById(customerGatewayId); if (customerGateway == null) { throw new InvalidParameterValueException("Unable to found specified Site to Site VPN customer gateway " + customerGatewayId + " !"); } - _accountMgr.checkAccess(caller, null, false, customerGateway); + _accountMgr.checkAccess(caller, null, customerGateway); Long vpnGatewayId = cmd.getVpnGatewayId(); Site2SiteVpnGateway vpnGateway = _vpnGatewayDao.findById(vpnGatewayId); if (vpnGateway == null) { throw new InvalidParameterValueException("Unable to found specified Site to Site VPN gateway " + vpnGatewayId + " !"); } - _accountMgr.checkAccess(caller, null, false, vpnGateway); + _accountMgr.checkAccess(caller, null, vpnGateway); if (customerGateway.getAccountId() != vpnGateway.getAccountId() || customerGateway.getDomainId() != vpnGateway.getDomainId()) { throw new InvalidParameterValueException("VPN connection can only be esitablished between same account's VPN gateway and customer gateway!"); @@ -366,7 +367,7 @@ public boolean deleteCustomerGateway(DeleteVpnCustomerGatewayCmd cmd) { if (customerGateway == null) { throw new InvalidParameterValueException("Fail to find customer gateway with " + id + " !"); } - _accountMgr.checkAccess(caller, null, false, customerGateway); + _accountMgr.checkAccess(caller, null, customerGateway); return doDeleteCustomerGateway(customerGateway); } @@ -401,7 +402,7 @@ public boolean deleteVpnGateway(DeleteVpnGatewayCmd cmd) { throw new InvalidParameterValueException("Fail to find vpn gateway with " + id + " !"); } - _accountMgr.checkAccess(caller, null, false, vpnGateway); + _accountMgr.checkAccess(caller, null, vpnGateway); doDeleteVpnGateway(vpnGateway); return true; @@ -418,7 +419,7 @@ public Site2SiteCustomerGateway updateCustomerGateway(UpdateVpnCustomerGatewayCm if (gw == null) { throw new InvalidParameterValueException("Find to find customer gateway with id " + id); } - _accountMgr.checkAccess(caller, null, false, gw); + _accountMgr.checkAccess(caller, null, gw); List conns = _vpnConnectionDao.listByCustomerGatewayId(id); if (conns != null) { @@ -508,7 +509,7 @@ public boolean deleteVpnConnection(DeleteVpnConnectionCmd cmd) throws ResourceUn throw new InvalidParameterValueException("Fail to find site to site VPN connection " + id + " to delete!"); } - _accountMgr.checkAccess(caller, null, false, conn); + _accountMgr.checkAccess(caller, null, conn); if (conn.getState() == State.Connected) { stopVpnConnection(id); @@ -557,7 +558,7 @@ public Site2SiteVpnConnection resetVpnConnection(ResetVpnConnectionCmd cmd) thro if (conn == null) { throw new InvalidParameterValueException("Fail to find site to site VPN connection " + id + " to reset!"); } - _accountMgr.checkAccess(caller, null, false, conn); + _accountMgr.checkAccess(caller, null, conn); if (conn.getState() == State.Pending) { throw new InvalidParameterValueException("VPN connection " + id + " cannot be reseted when state is Pending!"); @@ -821,7 +822,7 @@ public Site2SiteVpnConnection updateVpnConnection(long id, String customId, Bool throw new InvalidParameterValueException("Fail to find site to site VPN connection " + id); } - _accountMgr.checkAccess(caller, null, false, conn); + _accountMgr.checkAccess(caller, null, conn); if (customId != null) { conn.setUuid(customId); } @@ -844,7 +845,7 @@ public Site2SiteVpnGateway updateVpnGateway(Long id, String customId, Boolean fo throw new InvalidParameterValueException("Fail to find vpn gateway with " + id); } - _accountMgr.checkAccess(caller, null, false, vpnGateway); + _accountMgr.checkAccess(caller, null, vpnGateway); if (customId != null) { vpnGateway.setUuid(customId); } diff --git a/server/src/com/cloud/projects/ProjectManagerImpl.java b/server/src/com/cloud/projects/ProjectManagerImpl.java index d10c059bd5..6aa5abc0e8 100755 --- a/server/src/com/cloud/projects/ProjectManagerImpl.java +++ b/server/src/com/cloud/projects/ProjectManagerImpl.java @@ -244,7 +244,7 @@ public Project enableProject(long projectId) { throw new InvalidParameterValueException("Unable to find project by id " + projectId); } - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); //at this point enabling project doesn't require anything, so just update the state project.setState(State.Active); @@ -264,7 +264,7 @@ public boolean deleteProject(long projectId) { throw new InvalidParameterValueException("Unable to find project by id " + projectId); } - _accountMgr.checkAccess(ctx.getCallingAccount(), AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(ctx.getCallingAccount(), AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); return deleteProject(ctx.getCallingAccount(), ctx.getCallingUserId(), project); } @@ -463,7 +463,7 @@ public Project updateProject(final long projectId, final String displayText, fin } //verify permissions - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); Transaction.execute(new TransactionCallbackWithExceptionNoReturn() { @Override @@ -550,7 +550,7 @@ public boolean addAccountToProject(long projectId, String accountName, String em } //verify permissions - only project owner can assign - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); //Check if the account already added to the project ProjectAccount projectAccount = _projectAccountDao.findByProjectIdAccountId(projectId, account.getId()); @@ -628,7 +628,7 @@ public boolean deleteAccountFromProject(long projectId, String accountName) { } //verify permissions - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); //Check if the account exists in the project ProjectAccount projectAccount = _projectAccountDao.findByProjectIdAccountId(projectId, account.getId()); @@ -750,7 +750,7 @@ public boolean updateInvitation(final long projectId, String accountName, String } //verify permissions - _accountMgr.checkAccess(caller, null, true, account); + _accountMgr.checkAccess(caller, null, account); accountId = account.getId(); } else { @@ -830,7 +830,7 @@ public Project activateProject(final long projectId) { } //verify permissions - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); //allow project activation only when it's in Suspended state Project.State currentState = project.getState(); @@ -870,7 +870,7 @@ public Project suspendProject(long projectId) throws ConcurrentOperationExceptio throw ex; } - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); if (suspendProject(project)) { s_logger.debug("Successfully suspended project id=" + projectId); @@ -1012,7 +1012,7 @@ public boolean deleteProjectInvitation(long id) { Project project = getProject(invitation.getProjectId()); //check permissions - only project owner can remove the invitations - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, _accountMgr.getAccount(project.getProjectAccountId())); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, _accountMgr.getAccount(project.getProjectAccountId())); if (_projectInvitationDao.remove(id)) { s_logger.debug("Project Invitation id=" + id + " is removed"); diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index f9a59ba4eb..0f2ffc39b5 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -63,6 +63,7 @@ import com.cloud.agent.api.StartupRoutingCommand; import com.cloud.agent.api.UnsupportedAnswer; import com.cloud.agent.api.UpdateHostPasswordCommand; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.agent.api.to.GPUDeviceTO; import com.cloud.agent.transport.Request; import com.cloud.api.ApiDBUtils; @@ -97,7 +98,6 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceInUseException; -import com.cloud.gpu.GPU.vGPUType; import com.cloud.gpu.HostGpuGroupsVO; import com.cloud.gpu.VGPUTypesVO; import com.cloud.gpu.dao.HostGpuGroupsDao; @@ -583,7 +583,7 @@ public List discoverHosts(AddHostCmd cmd) throws IllegalArgument } } - return discoverHostsFull(dcId, podId, clusterId, clusterName, url, username, password, cmd.getHypervisor(), hostTags, cmd.getFullUrlParams(), true); + return discoverHostsFull(dcId, podId, clusterId, clusterName, url, username, password, cmd.getHypervisor(), hostTags, cmd.getFullUrlParams(), false); } @Override @@ -1349,6 +1349,7 @@ public boolean configure(String name, Map params) throws Configu _gpuAvailability = _hostGpuGroupsDao.createSearchBuilder(); _gpuAvailability.and("hostId", _gpuAvailability.entity().getHostId(), Op.EQ); + _gpuAvailability.and("groupName", _gpuAvailability.entity().getGroupName(), Op.EQ); SearchBuilder join1 = _vgpuTypesDao.createSearchBuilder(); join1.and("vgpuType", join1.entity().getVgpuType(), Op.EQ); join1.and("remainingCapacity", join1.entity().getRemainingCapacity(), Op.GT); @@ -2501,21 +2502,26 @@ public List listAllUpAndEnabledHostsInOneZoneByHypervisor(HypervisorType } @Override - public List listAvailableGPUDevice(long hostId, String vgpuType) { - if (vgpuType == null) { - vgpuType = vGPUType.passthrough.getType(); - } + public boolean isHostGpuEnabled(long hostId) { + SearchCriteria sc = _gpuAvailability.create(); + sc.setParameters("hostId", hostId); + return _hostGpuGroupsDao.customSearch(sc, null).size() > 0 ? true : false; + } + + @Override + public List listAvailableGPUDevice(long hostId, String groupName, String vgpuType) { Filter searchFilter = new Filter(VGPUTypesVO.class, "remainingCapacity", false, null, null); SearchCriteria sc = _gpuAvailability.create(); sc.setParameters("hostId", hostId); + sc.setParameters("groupName", groupName); sc.setJoinParameters("groupId", "vgpuType", vgpuType); sc.setJoinParameters("groupId", "remainingCapacity", 0); return _hostGpuGroupsDao.customSearch(sc, searchFilter); } @Override - public boolean isGPUDeviceAvailable(long hostId, String vgpuType) { - if(!listAvailableGPUDevice(hostId, vgpuType).isEmpty()) { + public boolean isGPUDeviceAvailable(long hostId, String groupName, String vgpuType) { + if(!listAvailableGPUDevice(hostId, groupName, vgpuType).isEmpty()) { return true; } else { if (s_logger.isDebugEnabled()) { @@ -2526,13 +2532,13 @@ public boolean isGPUDeviceAvailable(long hostId, String vgpuType) { } @Override - public GPUDeviceTO getGPUDevice(long hostId, String vgpuType) { - HostGpuGroupsVO gpuDevice = listAvailableGPUDevice(hostId, vgpuType).get(0); + public GPUDeviceTO getGPUDevice(long hostId, String groupName, String vgpuType) { + HostGpuGroupsVO gpuDevice = listAvailableGPUDevice(hostId, groupName, vgpuType).get(0); return new GPUDeviceTO(gpuDevice.getGroupName(), vgpuType, null); } @Override - public void updateGPUDetails(long hostId, HashMap> groupDetails) { + public void updateGPUDetails(long hostId, HashMap> groupDetails) { // Update GPU group capacity TransactionLegacy txn = TransactionLegacy.currentTxn(); txn.start(); @@ -2542,7 +2548,7 @@ public void updateGPUDetails(long hostId, HashMap> } @Override - public HashMap> getGPUStatistics(HostVO host) { + public HashMap> getGPUStatistics(HostVO host) { Answer answer = _agentMgr.easySend(host.getId(), new GetGPUStatsCommand(host.getGuid(), host.getName())); if (answer != null && (answer instanceof UnsupportedAnswer)) { return null; diff --git a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java index 74cfc31e74..2b5d976587 100755 --- a/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java +++ b/server/src/com/cloud/resourcelimit/ResourceLimitManagerImpl.java @@ -458,7 +458,7 @@ public List searchForLimits(Long id, Long accountId, Long domai List limits = new ArrayList(); boolean isAccount = true; - if (!_accountMgr.isAdmin(caller.getType())) { + if (!_accountMgr.isAdmin(caller.getId())) { accountId = caller.getId(); domainId = null; } else { @@ -480,7 +480,7 @@ public List searchForLimits(Long id, Long accountId, Long domai return limits; } - _accountMgr.checkAccess(caller, null, true, account); + _accountMgr.checkAccess(caller, null, account); domainId = null; } } @@ -500,7 +500,7 @@ public List searchForLimits(Long id, Long accountId, Long domai if (id != null) { ResourceLimitVO vo = _resourceLimitDao.findById(id); if (vo.getAccountId() != null) { - _accountMgr.checkAccess(caller, null, true, _accountDao.findById(vo.getAccountId())); + _accountMgr.checkAccess(caller, null, _accountDao.findById(vo.getAccountId())); limits.add(vo); } else if (vo.getDomainId() != null) { _accountMgr.checkAccess(caller, _domainDao.findById(vo.getDomainId())); @@ -650,9 +650,9 @@ public ResourceLimitVO updateResourceLimit(Long accountId, Long domainId, Intege } if (account.getType() == Account.ACCOUNT_TYPE_PROJECT) { - _accountMgr.checkAccess(caller, AccessType.ModifyProject, true, account); + _accountMgr.checkAccess(caller, AccessType.ModifyProject, account); } else { - _accountMgr.checkAccess(caller, null, true, account); + _accountMgr.checkAccess(caller, null, account); } ownerType = ResourceOwnerType.Account; diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index b8da4c8831..478101027c 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -1153,9 +1153,9 @@ public void doInTransactionWithoutResult(TransactionStatus status) { // Offering #5 NetworkOfferingVO defaultNetscalerNetworkOffering = - new NetworkOfferingVO(NetworkOffering.DefaultSharedEIPandELBNetworkOffering, - "Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, false, true, null, null, true, - Availability.Optional, null, Network.GuestType.Shared, true, false, false, false, true, true, true, false, false, true, true, false, false); + new NetworkOfferingVO(NetworkOffering.DefaultSharedEIPandELBNetworkOffering, + "Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, false, true, null, null, true, + Availability.Optional, null, Network.GuestType.Shared, true, false, false, false, true, true, true, false, false, true, true, false, false, false); defaultNetscalerNetworkOffering.setState(NetworkOffering.State.Enabled); defaultNetscalerNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNetscalerNetworkOffering); diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index 073cf47a90..5cc9154b81 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -51,8 +51,12 @@ import org.apache.cloudstack.api.command.admin.account.DeleteAccountCmd; import org.apache.cloudstack.api.command.admin.account.DisableAccountCmd; import org.apache.cloudstack.api.command.admin.account.EnableAccountCmd; +import org.apache.cloudstack.api.command.admin.account.ListAccountsCmdByAdmin; import org.apache.cloudstack.api.command.admin.account.LockAccountCmd; import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd; +import org.apache.cloudstack.api.command.admin.address.AssociateIPAddrCmdByAdmin; +import org.apache.cloudstack.api.command.admin.address.ListPublicIpAddressesCmdByAdmin; +import org.apache.cloudstack.api.command.admin.affinitygroup.UpdateVMAffinityGroupCmdByAdmin; import org.apache.cloudstack.api.command.admin.alert.GenerateAlertCmd; import org.apache.cloudstack.api.command.admin.autoscale.CreateCounterCmd; import org.apache.cloudstack.api.command.admin.autoscale.DeleteCounterCmd; @@ -94,8 +98,16 @@ import org.apache.cloudstack.api.command.admin.internallb.ListInternalLoadBalancerElementsCmd; import org.apache.cloudstack.api.command.admin.internallb.StartInternalLBVMCmd; import org.apache.cloudstack.api.command.admin.internallb.StopInternalLBVMCmd; +import org.apache.cloudstack.api.command.admin.iso.AttachIsoCmdByAdmin; +import org.apache.cloudstack.api.command.admin.iso.CopyIsoCmdByAdmin; +import org.apache.cloudstack.api.command.admin.iso.DetachIsoCmdByAdmin; +import org.apache.cloudstack.api.command.admin.iso.ListIsoPermissionsCmdByAdmin; +import org.apache.cloudstack.api.command.admin.iso.ListIsosCmdByAdmin; +import org.apache.cloudstack.api.command.admin.iso.RegisterIsoCmdByAdmin; +import org.apache.cloudstack.api.command.admin.loadbalancer.ListLoadBalancerRuleInstancesCmdByAdmin; import org.apache.cloudstack.api.command.admin.network.AddNetworkDeviceCmd; import org.apache.cloudstack.api.command.admin.network.AddNetworkServiceProviderCmd; +import org.apache.cloudstack.api.command.admin.network.CreateNetworkCmdByAdmin; import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd; import org.apache.cloudstack.api.command.admin.network.CreatePhysicalNetworkCmd; import org.apache.cloudstack.api.command.admin.network.CreateStorageNetworkIpRangeCmd; @@ -109,10 +121,12 @@ import org.apache.cloudstack.api.command.admin.network.ListNetworkDeviceCmd; import org.apache.cloudstack.api.command.admin.network.ListNetworkIsolationMethodsCmd; import org.apache.cloudstack.api.command.admin.network.ListNetworkServiceProvidersCmd; +import org.apache.cloudstack.api.command.admin.network.ListNetworksCmdByAdmin; import org.apache.cloudstack.api.command.admin.network.ListPhysicalNetworksCmd; import org.apache.cloudstack.api.command.admin.network.ListStorageNetworkIpRangeCmd; import org.apache.cloudstack.api.command.admin.network.ListSupportedNetworkServicesCmd; import org.apache.cloudstack.api.command.admin.network.ReleaseDedicatedGuestVlanRangeCmd; +import org.apache.cloudstack.api.command.admin.network.UpdateNetworkCmdByAdmin; import org.apache.cloudstack.api.command.admin.network.UpdateNetworkOfferingCmd; import org.apache.cloudstack.api.command.admin.network.UpdateNetworkServiceProviderCmd; import org.apache.cloudstack.api.command.admin.network.UpdatePhysicalNetworkCmd; @@ -178,7 +192,12 @@ import org.apache.cloudstack.api.command.admin.systemvm.StartSystemVMCmd; import org.apache.cloudstack.api.command.admin.systemvm.StopSystemVmCmd; import org.apache.cloudstack.api.command.admin.systemvm.UpgradeSystemVMCmd; +import org.apache.cloudstack.api.command.admin.template.CopyTemplateCmdByAdmin; +import org.apache.cloudstack.api.command.admin.template.CreateTemplateCmdByAdmin; +import org.apache.cloudstack.api.command.admin.template.ListTemplatePermissionsCmdByAdmin; +import org.apache.cloudstack.api.command.admin.template.ListTemplatesCmdByAdmin; import org.apache.cloudstack.api.command.admin.template.PrepareTemplateCmd; +import org.apache.cloudstack.api.command.admin.template.RegisterTemplateCmdByAdmin; import org.apache.cloudstack.api.command.admin.usage.AddTrafficMonitorCmd; import org.apache.cloudstack.api.command.admin.usage.AddTrafficTypeCmd; import org.apache.cloudstack.api.command.admin.usage.DeleteTrafficMonitorCmd; @@ -204,20 +223,47 @@ import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd; import org.apache.cloudstack.api.command.admin.vlan.ListVlanIpRangesCmd; import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd; +import org.apache.cloudstack.api.command.admin.vm.AddNicToVMCmdByAdmin; import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; +import org.apache.cloudstack.api.command.admin.vm.DeployVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.DestroyVMCmdByAdmin; import org.apache.cloudstack.api.command.admin.vm.ExpungeVMCmd; import org.apache.cloudstack.api.command.admin.vm.GetVMUserDataCmd; import org.apache.cloudstack.api.command.admin.vm.ListVMsCmdByAdmin; import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd; import org.apache.cloudstack.api.command.admin.vm.MigrateVirtualMachineWithVolumeCmd; +import org.apache.cloudstack.api.command.admin.vm.RebootVMCmdByAdmin; import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; +import org.apache.cloudstack.api.command.admin.vm.RemoveNicFromVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.ResetVMPasswordCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.ResetVMSSHKeyCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.RestoreVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.ScaleVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.StartVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.StopVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.UpdateDefaultNicForVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.UpdateVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vm.UpgradeVMCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vmsnapshot.RevertToVMSnapshotCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.AttachVolumeCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.CreateVolumeCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.DetachVolumeCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.ListVolumesCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.MigrateVolumeCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.ResizeVolumeCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.UpdateVolumeCmdByAdmin; +import org.apache.cloudstack.api.command.admin.volume.UploadVolumeCmdByAdmin; import org.apache.cloudstack.api.command.admin.vpc.CreatePrivateGatewayCmd; +import org.apache.cloudstack.api.command.admin.vpc.CreateVPCCmdByAdmin; import org.apache.cloudstack.api.command.admin.vpc.CreateVPCOfferingCmd; import org.apache.cloudstack.api.command.admin.vpc.DeletePrivateGatewayCmd; import org.apache.cloudstack.api.command.admin.vpc.DeleteVPCOfferingCmd; +import org.apache.cloudstack.api.command.admin.vpc.ListVPCsCmdByAdmin; +import org.apache.cloudstack.api.command.admin.vpc.UpdateVPCCmdByAdmin; import org.apache.cloudstack.api.command.admin.vpc.UpdateVPCOfferingCmd; import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd; import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd; +import org.apache.cloudstack.api.command.admin.zone.ListZonesCmdByAdmin; import org.apache.cloudstack.api.command.admin.zone.MarkDefaultZoneForAccountCmd; import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd; import org.apache.cloudstack.api.command.user.account.AddAccountToProjectCmd; @@ -907,7 +953,7 @@ public boolean archiveEvents(ArchiveEventsCmd cmd) { List events = _eventDao.listToArchiveOrDeleteEvents(ids, cmd.getType(), cmd.getStartDate(), cmd.getEndDate(), permittedAccountIds); ControlledEntity[] sameOwnerEvents = events.toArray(new ControlledEntity[events.size()]); - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, false, sameOwnerEvents); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, sameOwnerEvents); if (ids != null && events.size() < ids.size()) { result = false; @@ -934,7 +980,7 @@ public boolean deleteEvents(DeleteEventsCmd cmd) { List events = _eventDao.listToArchiveOrDeleteEvents(ids, cmd.getType(), cmd.getStartDate(), cmd.getEndDate(), permittedAccountIds); ControlledEntity[] sameOwnerEvents = events.toArray(new ControlledEntity[events.size()]); - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, false, sameOwnerEvents); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, sameOwnerEvents); if (ids != null && events.size() < ids.size()) { result = false; @@ -2710,6 +2756,7 @@ public List> getCommands() { cmdList.add(ListIpForwardingRulesCmd.class); cmdList.add(CreateNetworkACLCmd.class); cmdList.add(CreateNetworkCmd.class); + cmdList.add(CreateNetworkCmdByAdmin.class); cmdList.add(DeleteNetworkACLCmd.class); cmdList.add(DeleteNetworkCmd.class); cmdList.add(ListNetworkACLsCmd.class); @@ -2770,7 +2817,6 @@ public List> getCommands() { cmdList.add(ExpungeVMCmd.class); cmdList.add(GetVMPasswordCmd.class); cmdList.add(ListVMsCmd.class); - cmdList.add(ListVMsCmdByAdmin.class); cmdList.add(ScaleVMCmd.class); cmdList.add(RebootVMCmd.class); cmdList.add(RemoveNicFromVMCmd.class); @@ -2898,6 +2944,54 @@ public List> getCommands() { cmdList.add(UpdateRemoteAccessVpnCmd.class); cmdList.add(UpdateVpnConnectionCmd.class); cmdList.add(UpdateVpnGatewayCmd.class); + // separated admin commands + cmdList.add(ListAccountsCmdByAdmin.class); + cmdList.add(ListZonesCmdByAdmin.class); + cmdList.add(ListTemplatesCmdByAdmin.class); + cmdList.add(CreateTemplateCmdByAdmin.class); + cmdList.add(CopyTemplateCmdByAdmin.class); + cmdList.add(RegisterTemplateCmdByAdmin.class); + cmdList.add(ListTemplatePermissionsCmdByAdmin.class); + cmdList.add(RegisterIsoCmdByAdmin.class); + cmdList.add(CopyIsoCmdByAdmin.class); + cmdList.add(ListIsosCmdByAdmin.class); + cmdList.add(AttachIsoCmdByAdmin.class); + cmdList.add(DetachIsoCmdByAdmin.class); + cmdList.add(ListIsoPermissionsCmdByAdmin.class); + cmdList.add(UpdateVMAffinityGroupCmdByAdmin.class); + cmdList.add(AddNicToVMCmdByAdmin.class); + cmdList.add(RemoveNicFromVMCmdByAdmin.class); + cmdList.add(UpdateDefaultNicForVMCmdByAdmin.class); + cmdList.add(ListLoadBalancerRuleInstancesCmdByAdmin.class); + cmdList.add(DeployVMCmdByAdmin.class); + cmdList.add(DestroyVMCmdByAdmin.class); + cmdList.add(RebootVMCmdByAdmin.class); + cmdList.add(ResetVMPasswordCmdByAdmin.class); + cmdList.add(ResetVMSSHKeyCmdByAdmin.class); + cmdList.add(RestoreVMCmdByAdmin.class); + cmdList.add(ScaleVMCmdByAdmin.class); + cmdList.add(StartVMCmdByAdmin.class); + cmdList.add(StopVMCmdByAdmin.class); + cmdList.add(UpdateVMCmdByAdmin.class); + cmdList.add(UpgradeVMCmdByAdmin.class); + cmdList.add(RevertToVMSnapshotCmdByAdmin.class); + cmdList.add(ListVMsCmdByAdmin.class); + cmdList.add(AttachVolumeCmdByAdmin.class); + cmdList.add(CreateVolumeCmdByAdmin.class); + cmdList.add(DetachVolumeCmdByAdmin.class); + cmdList.add(MigrateVolumeCmdByAdmin.class); + cmdList.add(ResizeVolumeCmdByAdmin.class); + cmdList.add(UpdateVolumeCmdByAdmin.class); + cmdList.add(UploadVolumeCmdByAdmin.class); + cmdList.add(ListVolumesCmdByAdmin.class); + cmdList.add(AssociateIPAddrCmdByAdmin.class); + cmdList.add(ListPublicIpAddressesCmdByAdmin.class); + cmdList.add(CreateNetworkCmdByAdmin.class); + cmdList.add(UpdateNetworkCmdByAdmin.class); + cmdList.add(ListNetworksCmdByAdmin.class); + cmdList.add(CreateVPCCmdByAdmin.class); + cmdList.add(ListVPCsCmdByAdmin.class); + cmdList.add(UpdateVPCCmdByAdmin.class); return cmdList; } @@ -3201,7 +3295,7 @@ public ArrayList getCloudIdentifierResponse(long userId) { } // check permissions - _accountMgr.checkAccess(caller, null, true, _accountMgr.getAccount(user.getAccountId())); + _accountMgr.checkAccess(caller, null, _accountMgr.getAccount(user.getAccountId())); String cloudIdentifier = _configDao.getValue("cloud.identifier"); if (cloudIdentifier == null) { @@ -3248,6 +3342,7 @@ public Map listCapabilities(ListCapabilitiesCmd cmd) { } } + long diskOffMinSize = VolumeOrchestrationService.CustomDiskOfferingMinSize.value(); long diskOffMaxSize = VolumeOrchestrationService.CustomDiskOfferingMaxSize.value(); KVMSnapshotEnabled = Boolean.parseBoolean(_configDao.getValue("KVM.snapshot.enabled")); @@ -3271,6 +3366,7 @@ public Map listCapabilities(ListCapabilitiesCmd cmd) { capabilities.put("supportELB", supportELB); capabilities.put("projectInviteRequired", _projectMgr.projectInviteRequired()); capabilities.put("allowusercreateprojects", _projectMgr.allowUserToCreateProject()); + capabilities.put("customDiskOffMinSize", diskOffMinSize); capabilities.put("customDiskOffMaxSize", diskOffMaxSize); capabilities.put("regionSecondaryEnabled", regionSecondaryEnabled); capabilities.put("KVMSnapshotEnabled", KVMSnapshotEnabled); @@ -3306,7 +3402,7 @@ public InstanceGroupVO updateVmGroup(UpdateVMGroupCmd cmd) { throw ex; } - _accountMgr.checkAccess(caller, null, true, group); + _accountMgr.checkAccess(caller, null, group); // Check if name is already in use by this account (exclude this group) boolean isNameInUse = _vmGroupDao.isNameInUse(group.getAccountId(), groupName); @@ -3551,7 +3647,7 @@ public String getVMPassword(GetVMPasswordCmd cmd) { } // make permission check - _accountMgr.checkAccess(caller, null, true, vm); + _accountMgr.checkAccess(caller, null, vm); _userVmDao.loadDetails(vm); String password = vm.getDetail("Encrypted.Password"); @@ -3724,7 +3820,7 @@ private VirtualMachine upgradeStoppedSystemVm(Long systemVmId, Long serviceOffer throw new InvalidParameterValueException("Unable to find SystemVm with id " + systemVmId); } - _accountMgr.checkAccess(caller, null, true, systemVm); + _accountMgr.checkAccess(caller, null, systemVm); // Check that the specified service offering ID is valid ServiceOfferingVO newServiceOffering = _offeringDao.findById(serviceOfferingId); diff --git a/server/src/com/cloud/server/StatsCollector.java b/server/src/com/cloud/server/StatsCollector.java index 50aa93cd5e..29ace93202 100755 --- a/server/src/com/cloud/server/StatsCollector.java +++ b/server/src/com/cloud/server/StatsCollector.java @@ -49,6 +49,7 @@ import com.cloud.agent.api.GetStorageStatsCommand; import com.cloud.agent.api.HostStatsEntry; import com.cloud.agent.api.PerformanceMonitorCommand; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.agent.api.VmDiskStatsEntry; import com.cloud.agent.api.VmStatsEntry; import com.cloud.cluster.ManagementServerHostVO; @@ -342,7 +343,7 @@ protected void runInContext() { gpuEnabledHosts = hosts; } for (HostVO host : gpuEnabledHosts) { - HashMap> groupDetails = _resourceMgr.getGPUStatistics(host); + HashMap> groupDetails = _resourceMgr.getGPUStatistics(host); if (groupDetails != null) { _resourceMgr.updateGPUDetails(host.getId(), groupDetails); } diff --git a/server/src/com/cloud/servlet/ConsoleProxyServlet.java b/server/src/com/cloud/servlet/ConsoleProxyServlet.java index 60f32cf4bb..16d7a3292f 100644 --- a/server/src/com/cloud/servlet/ConsoleProxyServlet.java +++ b/server/src/com/cloud/servlet/ConsoleProxyServlet.java @@ -522,7 +522,7 @@ private boolean checkSessionPermision(HttpServletRequest req, long vmId, Account switch (vm.getType()) { case User: try { - _accountMgr.checkAccess(accountObj, null, true, vm); + _accountMgr.checkAccess(accountObj, null, vm); } catch (PermissionDeniedException ex) { if (_accountMgr.isNormalUser(accountObj.getId())) { if (s_logger.isDebugEnabled()) { diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 3b29b33624..c27a457f0e 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -618,7 +618,7 @@ public PrimaryDataStoreInfo createPool(CreateStoragePoolCmd cmd) throws Resource } else { throw new InvalidParameterValueException("Missing parameter hypervisor. Hypervisor type is required to create zone wide primary storage."); } - if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.VMware && hypervisorType != HypervisorType.Any) { + if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.VMware && hypervisorType != HypervisorType.Hyperv && hypervisorType != HypervisorType.Any) { throw new InvalidParameterValueException("zone wide storage pool is not supported for hypervisor type " + hypervisor); } } diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/com/cloud/storage/VolumeApiServiceImpl.java index 30b5479b63..680cd2ed44 100644 --- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java +++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java @@ -28,6 +28,7 @@ import org.apache.log4j.Logger; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; 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.DetachVolumeCmd; @@ -272,7 +273,7 @@ public VolumeVO uploadVolume(UploadVolumeCmd cmd) throws ResourceAllocationExcep private boolean validateVolume(Account caller, long ownerId, Long zoneId, String volumeName, String url, String format) throws ResourceAllocationException { // permission check - _accountMgr.checkAccess(caller, null, true, _accountMgr.getActiveAccountById(ownerId)); + _accountMgr.checkAccess(caller, null, _accountMgr.getActiveAccountById(ownerId)); // Check that the resource limit for volumes won't be exceeded _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(ownerId), ResourceType.volume); @@ -381,10 +382,11 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept Boolean displayVolume = cmd.getDisplayVolume(); // permission check - _accountMgr.checkAccess(caller, null, true, _accountMgr.getActiveAccountById(ownerId)); + _accountMgr.checkAccess(caller, null, _accountMgr.getActiveAccountById(ownerId)); if (displayVolume == null) { displayVolume = true; + } else { if (!_accountMgr.isRootAdmin(caller.getId())) { throw new PermissionDeniedException("Cannot update parameter displayvolume, only admin permitted "); @@ -508,9 +510,6 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept size = snapshotCheck.getSize(); // ; disk offering is used for tags // purposes - // check snapshot permissions - _accountMgr.checkAccess(caller, null, true, snapshotCheck); - // one step operation - create volume in VM's cluster and attach it // to the VM Long vmId = cmd.getVirtualMachineId(); @@ -525,9 +524,6 @@ public VolumeVO allocVolume(CreateVolumeCmd cmd) throws ResourceAllocationExcept if (vm.getState() != State.Running && vm.getState() != State.Stopped) { throw new InvalidParameterValueException("Please specify a VM that is either running or stopped."); } - - // permission check - _accountMgr.checkAccess(caller, null, false, vm); } } @@ -591,10 +587,10 @@ public VolumeVO doInTransaction(TransactionStatus status) { } volume = _volsDao.persist(volume); - if (cmd.getSnapshotId() == null) { + if (cmd.getSnapshotId() == null && displayVolume) { // for volume created from snapshot, create usage event after volume creation - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - diskOfferingId, null, size, Volume.class.getName(), volume.getUuid()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), + diskOfferingId, null, size, Volume.class.getName(), volume.getUuid(), displayVolume); } CallContext.current().setEventDetails("Volume Id: " + volume.getId()); @@ -677,11 +673,11 @@ protected VolumeVO createVolumeFromSnapshot(VolumeVO volume, long snapshotId, Lo // sync old snapshots to region store if necessary createdVolume = _volumeMgr.createVolumeFromSnapshot(volume, snapshot, vm); - + VolumeVO volumeVo = _volsDao.findById(createdVolume.getId()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, createdVolume.getAccountId(), createdVolume.getDataCenterId(), createdVolume.getId(), - createdVolume.getName(), createdVolume.getDiskOfferingId(), null, createdVolume.getSize(), Volume.class.getName(), createdVolume.getUuid()); + createdVolume.getName(), createdVolume.getDiskOfferingId(), null, createdVolume.getSize(), Volume.class.getName(), createdVolume.getUuid(), volumeVo.isDisplayVolume()); - return _volsDao.findById(createdVolume.getId()); + return volumeVo; } @Override @@ -701,27 +697,17 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep newDiskOffering = _diskOfferingDao.findById(cmd.getNewDiskOfferingId()); - /* - * Volumes with no hypervisor have never been assigned, and can be - * resized by recreating. perhaps in the future we can just update the - * db entry for the volume - */ - if (_volsDao.getHypervisorType(volume.getId()) == HypervisorType.None) { - throw new InvalidParameterValueException("Can't resize a volume that has never been attached, not sure which hypervisor type. Recreate volume to resize."); - } - - /* Only works for KVM/Xen for now */ - if (_volsDao.getHypervisorType(volume.getId()) != HypervisorType.KVM && _volsDao.getHypervisorType(volume.getId()) != HypervisorType.XenServer - && _volsDao.getHypervisorType(volume.getId()) != HypervisorType.VMware) { - throw new InvalidParameterValueException("Cloudstack currently only supports volumes marked as KVM or XenServer hypervisor for resize"); - } - - if (volume.getState() != Volume.State.Ready) { - throw new InvalidParameterValueException("Volume should be in ready state before attempting a resize"); + /* Only works for KVM/Xen/VMware for now, and volumes with 'None' since they're just allocated in db */ + if (_volsDao.getHypervisorType(volume.getId()) != HypervisorType.KVM + && _volsDao.getHypervisorType(volume.getId()) != HypervisorType.XenServer + && _volsDao.getHypervisorType(volume.getId()) != HypervisorType.VMware + && _volsDao.getHypervisorType(volume.getId()) != HypervisorType.None) { + throw new InvalidParameterValueException("Cloudstack currently only supports volumes marked as KVM, VMware, XenServer hypervisor for resize"); } - if (!volume.getVolumeType().equals(Volume.Type.DATADISK)) { - throw new InvalidParameterValueException("Can only resize DATA volumes"); + if (volume.getState() != Volume.State.Ready && volume.getState() != Volume.State.Allocated) { + throw new InvalidParameterValueException("Volume should be in ready or allocated state before attempting a resize. " + + "Volume " + volume.getUuid() + " state is:" + volume.getState()); } /* @@ -729,7 +715,7 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep * required, get the correct size value */ if (newDiskOffering == null) { - if (diskOffering.isCustomized()) { + if (diskOffering.isCustomized() || volume.getVolumeType().equals(Volume.Type.ROOT)) { newSize = cmd.getSize(); if (newSize == null) { @@ -741,6 +727,9 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep throw new InvalidParameterValueException("current offering" + volume.getDiskOfferingId() + " cannot be resized, need to specify a disk offering"); } } else { + if (!volume.getVolumeType().equals(Volume.Type.DATADISK)) { + throw new InvalidParameterValueException("Can only resize Data volumes via new disk offering"); + } if (newDiskOffering.getRemoved() != null || !DiskOfferingVO.Type.Disk.equals(newDiskOffering.getType())) { throw new InvalidParameterValueException("Disk offering ID is missing or invalid"); @@ -782,9 +771,7 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep } /* does the caller have the authority to act on this volume? */ - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume); - - UserVmVO userVm = _userVmDao.findById(volume.getInstanceId()); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, volume); long currentSize = volume.getSize(); @@ -805,6 +792,20 @@ public VolumeVO resizeVolume(ResizeVolumeCmd cmd) throws ResourceAllocationExcep - currentSize)); } + /* If this volume has never been beyond allocated state, short circuit everything and simply update the database */ + if (volume.getState() == Volume.State.Allocated) { + s_logger.debug("Volume is allocated, but never created, simply updating database with new size"); + volume.setSize(newSize); + if (newDiskOffering != null) { + volume.setDiskOfferingId(cmd.getNewDiskOfferingId()); + } + _volsDao.update(volume.getId(), volume); + return volume; + } + + UserVmVO userVm = _userVmDao.findById(volume.getInstanceId()); + + if (userVm != null) { // serialize VM operation AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext(); @@ -933,7 +934,7 @@ public boolean deleteVolume(long volumeId, Account caller) throws ConcurrentOper throw new InvalidParameterValueException("There are snapshot creating on it, Unable to delete the volume"); } - _accountMgr.checkAccess(caller, null, true, volume); + _accountMgr.checkAccess(caller, null, volume); if (volume.getInstanceId() != null) { throw new InvalidParameterValueException("Please specify a volume that is not attached to any VM."); @@ -967,7 +968,7 @@ storage count (in case of upload volume). */ // Log usage event for volumes belonging user VM's only UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - Volume.class.getName(), volume.getUuid()); + Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); } } // Mark volume as removed if volume has not been created on primary or secondary @@ -1126,7 +1127,8 @@ public Volume attachVolumeToVM(Long vmId, Long volumeId, Long deviceId) { } // permission check - _accountMgr.checkAccess(caller, null, true, volume, vm); + // TODO: remove this if we can annotate volume parameter in createVolumeCmd since this routine is used there as well. + _accountMgr.checkAccess(caller, AccessType.OperateEntry, volume, vm); if (!(Volume.State.Allocated.equals(volume.getState()) || Volume.State.Ready.equals(volume.getState()) || Volume.State.Uploaded.equals(volume.getState()))) { throw new InvalidParameterValueException("Volume state must be in Allocated, Ready or in Uploaded state"); @@ -1220,14 +1222,13 @@ public Volume updateVolume(long volumeId, String path, String state, Long storag VolumeVO volume = _volumeDao.findById(volumeId); + if(volume == null) + throw new InvalidParameterValueException("The volume id doesn't exist"); + if (path != null) { volume.setPath(path); } - if (displayVolume != null) { - volume.setDisplayVolume(displayVolume); - } - if(chainInfo != null){ volume.setChainInfo(chainInfo); } @@ -1253,17 +1254,61 @@ public Volume updateVolume(long volumeId, String path, String state, Long storag volume.setUuid(customId); } - if (displayVolume != null && displayVolume != volume.isDisplayVolume()) { // No need to check permissions since only Admin allowed to call this API. - volume.setDisplayVolume(displayVolume); - _resourceLimitMgr.changeResourceCount(entityOwnerId, ResourceType.volume, displayVolume); - _resourceLimitMgr.changeResourceCount(entityOwnerId, ResourceType.primary_storage, displayVolume, new Long(volume.getSize())); - } + updateDisplay(volume, displayVolume); _volumeDao.update(volumeId, volume); return volume; } + + @Override + public void updateDisplay(Volume volume, Boolean displayVolume){ + // 1. Resource limit changes + updateResourceCount(volume, displayVolume); + + // 2. generate usage event if not in destroyed state + saveUsageEvent(volume, displayVolume); + + // 3. Set the flag + if (displayVolume != null && displayVolume != volume.isDisplayVolume()){ + // FIXME - Confused - typecast for now. + ((VolumeVO)volume).setDisplayVolume(displayVolume); + _volumeDao.update(volume.getId(), (VolumeVO)volume); + } + + } + + private void updateResourceCount(Volume volume, Boolean displayVolume){ + // Update only when the flag has changed. + if (displayVolume != null && displayVolume != volume.isDisplayVolume()){ + _resourceLimitMgr.changeResourceCount(volume.getAccountId(), ResourceType.volume, displayVolume); + _resourceLimitMgr.changeResourceCount(volume.getAccountId(), ResourceType.primary_storage, displayVolume, new Long(volume.getSize())); + } + } + + private void saveUsageEvent(Volume volume, Boolean displayVolume){ + + // Update only when the flag has changed && only when volume in a non-destroyed state. + if ((displayVolume != null && displayVolume != volume.isDisplayVolume()) && !isVolumeDestroyed(volume)){ + if (displayVolume){ + // flag turned 1 equivalent to freshly created volume + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), + volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid()); + }else { + // flag turned 0 equivalent to deleting a volume + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), + Volume.class.getName(), volume.getUuid()); + } + } + } + + private boolean isVolumeDestroyed(Volume volume){ + if(volume.getState() == Volume.State.Destroy || volume.getState() == Volume.State.Expunging && volume.getState() == Volume.State.Expunged) + return true; + return false; + } + @Override @ActionEvent(eventType = EventTypes.EVENT_VOLUME_DETACH, eventDescription = "detaching volume", async = true) public Volume detachVolumeFromVM(DetachVolumeCmd cmmd) { @@ -1297,7 +1342,7 @@ public Volume detachVolumeFromVM(DetachVolumeCmd cmmd) { } // Permissions check - _accountMgr.checkAccess(caller, null, true, volume); + _accountMgr.checkAccess(caller, null, volume); // Check that the volume is a data volume if (volume.getVolumeType() != Volume.Type.DATADISK) { @@ -1487,12 +1532,11 @@ public Volume migrateVolume(MigrateVolumeCmd cmd) { liveMigrateVolume = capabilities.isStorageMotionSupported(); } } - } - // If the disk is not attached to any VM then it can be moved. Otherwise, it needs to be attached to a vm - // running on a hypervisor that supports storage motion so that it be be migrated. - if (instanceId != null && !liveMigrateVolume) { - throw new InvalidParameterValueException("Volume needs to be detached from VM"); + // If vm is running, and hypervisor doesn't support live migration, then return error + if (!liveMigrateVolume) { + throw new InvalidParameterValueException("Volume needs to be detached from VM"); + } } if (liveMigrateVolume && !cmd.isLiveMigrate()) { @@ -1743,7 +1787,7 @@ public String extractVolume(ExtractVolumeCmd cmd) { } // perform permission check - _accountMgr.checkAccess(account, null, true, volume); + _accountMgr.checkAccess(account, null, volume); if (_dcDao.findById(zoneId) == null) { throw new InvalidParameterValueException("Please specify a valid zone."); diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index 6bf4817571..d19a0ed846 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -286,7 +286,7 @@ public Snapshot createSnapshot(Long volumeId, Long policyId, Long snapshotId, Ac boolean backedUp = false; // does the caller have the authority to act on this volume - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, volume); SnapshotInfo snapshot = snapshotFactory.getSnapshot(snapshotId, DataStoreRole.Primary); @@ -391,7 +391,7 @@ public boolean deleteSnapshot(long snapshotId) { throw new InvalidParameterValueException("unable to find a snapshot with id " + snapshotId); } - _accountMgr.checkAccess(caller, null, true, snapshotCheck); + _accountMgr.checkAccess(caller, null, snapshotCheck); SnapshotStrategy snapshotStrategy = _storageStrategyFactory.getSnapshotStrategy(snapshotCheck, SnapshotOperation.DELETE); if (snapshotStrategy == null) { s_logger.error("Unable to find snaphot strategy to handle snapshot with id '" + snapshotId + "'"); @@ -450,7 +450,7 @@ public Pair, Integer> listSnapshots(ListSnapshotsCmd cm if (volumeId != null) { VolumeVO volume = _volsDao.findById(volumeId); if (volume != null) { - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, volume); } } @@ -599,7 +599,7 @@ public boolean deleteSnapshotDirsForAccount(long accountId) { SnapshotDataStoreVO snapshotStoreRef = _snapshotStoreDao.findBySnapshot(snapshot.getId(), DataStoreRole.Image); if (snapshotStrategy.deleteSnapshot(snapshot.getId())) { - if (snapshot.getRecurringType() == Type.MANUAL) { + if (Type.MANUAL == snapshot.getRecurringType()) { _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.snapshot); _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.secondary_storage, new Long(snapshotStoreRef.getSize())); } @@ -624,7 +624,7 @@ public SnapshotPolicyVO createPolicy(CreateSnapshotPolicyCmd cmd, Account policy throw new InvalidParameterValueException("Failed to create snapshot policy, unable to find a volume with id " + volumeId); } - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, volume); if (volume.getState() != Volume.State.Ready) { throw new InvalidParameterValueException("VolumeId: " + volumeId + " is not in " + Volume.State.Ready + " state but " + volume.getState() + @@ -723,7 +723,7 @@ public Pair, Integer> listPoliciesforVolume(ListS if (volume == null) { throw new InvalidParameterValueException("Unable to find a volume with id " + volumeId); } - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, volume); Pair, Integer> result = _snapshotPolicyDao.listAndCountByVolumeId(volumeId); return new Pair, Integer>(result.first(), result.second()); } @@ -769,7 +769,7 @@ public List findRecurringSnapshotSchedule(ListRecurringSnaps if (account != null) { long volAcctId = volume.getAccountId(); - if (_accountMgr.isAdmin(account.getType())) { + if (_accountMgr.isAdmin(account.getId())) { Account userAccount = _accountDao.findById(Long.valueOf(volAcctId)); if (!_domainDao.isChildDomain(account.getDomainId(), userAccount.getDomainId())) { throw new PermissionDeniedException("Unable to list snapshot schedule for volume " + volumeId + ", permission denied."); @@ -999,7 +999,7 @@ public boolean deleteSnapshotPolicies(DeleteSnapshotPoliciesCmd cmd) { throw new InvalidParameterValueException("Policy id given: " + policy + " does not belong to a valid volume"); } - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, volume); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, volume); } boolean success = true; @@ -1030,12 +1030,9 @@ public boolean canOperateOnVolume(Volume volume) { @Override public Snapshot allocSnapshot(Long volumeId, Long policyId) throws ResourceAllocationException { - Account caller = CallContext.current().getCallingAccount(); VolumeInfo volume = volFactory.getVolume(volumeId); supportedByHypervisor(volume); - // Verify permissions - _accountMgr.checkAccess(caller, null, true, volume); Type snapshotType = getSnapshotType(policyId); Account owner = _accountMgr.getAccount(volume.getAccountId()); diff --git a/server/src/com/cloud/tags/TaggedResourceManagerImpl.java b/server/src/com/cloud/tags/TaggedResourceManagerImpl.java index 900c822da8..71722a99ad 100644 --- a/server/src/com/cloud/tags/TaggedResourceManagerImpl.java +++ b/server/src/com/cloud/tags/TaggedResourceManagerImpl.java @@ -25,11 +25,12 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.log4j.Logger; + import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.log4j.Logger; import com.cloud.api.query.dao.ResourceTagJoinDao; import com.cloud.dc.DataCenterVO; @@ -222,7 +223,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { Long domainId = accountDomainPair.second(); Long accountId = accountDomainPair.first(); if (accountId != null) { - _accountMgr.checkAccess(caller, null, false, _accountMgr.getAccount(accountId)); + _accountMgr.checkAccess(caller, null, _accountMgr.getAccount(accountId)); } else if (domainId != null && !_accountMgr.isNormalUser(caller.getId())) { //check permissions; _accountMgr.checkAccess(caller, _domainMgr.getDomain(domainId)); @@ -284,7 +285,7 @@ public boolean deleteTags(List resourceIds, ResourceObjectType resourceT for (ResourceTag resourceTag : resourceTags) { //1) validate the permissions Account owner = _accountMgr.getAccount(resourceTag.getAccountId()); - _accountMgr.checkAccess(caller, null, false, owner); + _accountMgr.checkAccess(caller, null, owner); //2) Only remove tag if it matches key value pairs if (tags != null && !tags.isEmpty()) { for (String key : tags.keySet()) { diff --git a/server/src/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/com/cloud/template/HypervisorTemplateAdapter.java index 2b6f1ebf3a..51dedf7697 100755 --- a/server/src/com/cloud/template/HypervisorTemplateAdapter.java +++ b/server/src/com/cloud/template/HypervisorTemplateAdapter.java @@ -29,7 +29,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd; import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd; import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd; @@ -400,6 +399,11 @@ public boolean delete(TemplateProfile profile) { } } if (success) { + if ((imageStores.size() > 1) && (profile.getZoneId() != null)) { + //if template is stored in more than one image stores, and the zone id is not null, then don't delete other templates. + return success; + } + // delete all cache entries for this template List cacheTmpls = imageFactory.listTemplateOnCache(template.getId()); for (TemplateInfo tmplOnCache : cacheTmpls) { @@ -423,7 +427,7 @@ public boolean delete(TemplateProfile profile) { } // remove its related ACL permission - Pair tmplt = new Pair(IAMEntityType.VirtualMachineTemplate, template.getId()); + Pair, Long> tmplt = new Pair, Long>(VirtualMachineTemplate.class, template.getId()); _messageBus.publish(_name, EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, PublishScope.LOCAL, tmplt); } diff --git a/server/src/com/cloud/template/TemplateAdapterBase.java b/server/src/com/cloud/template/TemplateAdapterBase.java index f3c16cad03..cb38075324 100755 --- a/server/src/com/cloud/template/TemplateAdapterBase.java +++ b/server/src/com/cloud/template/TemplateAdapterBase.java @@ -179,7 +179,7 @@ public TemplateProfile prepare(boolean isIso, long userId, String name, String d if (!isAdmin && zoneId == null && !isRegionStore ) { // domain admin and user should also be able to register template on a region store - throw new InvalidParameterValueException("Please specify a valid zone Id."); + throw new InvalidParameterValueException("Please specify a valid zone Id. Only admins can create templates in all zones."); } if (url.toLowerCase().contains("file://")) { @@ -209,10 +209,6 @@ public TemplateProfile prepare(boolean isIso, long userId, String name, String d _resourceLimitMgr.checkResourceLimit(templateOwner, ResourceType.template); - if (!_accountMgr.isRootAdmin(templateOwner.getId()) && zoneId == null) { - throw new IllegalArgumentException("Only admins can create templates in all zones"); - } - // If a zoneId is specified, make sure it is valid if (zoneId != null) { DataCenterVO zone = _dcDao.findById(zoneId); @@ -258,7 +254,7 @@ public TemplateProfile prepare(RegisterTemplateCmd cmd) throws ResourceAllocatio //check if the caller can operate with the template owner Account caller = CallContext.current().getCallingAccount(); Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); boolean isRouting = (cmd.isRoutingType() == null) ? false : cmd.isRoutingType(); @@ -281,7 +277,7 @@ public TemplateProfile prepare(RegisterIsoCmd cmd) throws ResourceAllocationExce //check if the caller can operate with the template owner Account caller = CallContext.current().getCallingAccount(); Account owner = _accountMgr.getAccount(cmd.getEntityOwnerId()); - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); Long zoneId = cmd.getZoneId(); // ignore passed zoneId if we are using region wide image store @@ -324,7 +320,7 @@ protected VMTemplateVO persistTemplate(TemplateProfile profile) { private Long accountAndUserValidation(Account account, long userId, UserVmVO vmInstanceCheck, VMTemplateVO template, String msg) throws PermissionDeniedException { if (account != null) { - if (!_accountMgr.isAdmin(account.getType())) { + if (!_accountMgr.isAdmin(account.getId())) { if ((vmInstanceCheck != null) && (account.getId() != vmInstanceCheck.getAccountId())) { throw new PermissionDeniedException(msg + ". Permission denied."); } diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index 34123cdb98..ead841fb1c 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -33,7 +33,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListTemplateOrIsoPermissionsCmd; @@ -370,7 +369,7 @@ public VirtualMachineTemplate prepareTemplate(long templateId, long zoneId) { throw new InvalidParameterValueException("Unable to find template id=" + templateId); } - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, true, vmTemplate); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, vmTemplate); prepareTemplateInAllStoragePools(vmTemplate, zoneId); return vmTemplate; @@ -416,7 +415,7 @@ private String extract(Account caller, Long templateId, String url, Long zoneId, throw new InvalidParameterValueException("Unable to extract template id=" + templateId + " as it's not extractable"); } - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, template); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, template); List ssStores = _dataStoreMgr.getImageStoresByScope(new ZoneScope(zoneId)); @@ -723,7 +722,7 @@ public VirtualMachineTemplate copyTemplate(CopyTemplateCmd cmd) throws StorageUn return template; } - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, template); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, template); boolean success = copy(userId, template, srcSecStore, dstZone); @@ -912,7 +911,7 @@ public boolean detachIso(long vmId) { throw new InvalidParameterValueException("Please specify a valid VM."); } - _accountMgr.checkAccess(caller, null, true, userVM); + _accountMgr.checkAccess(caller, null, userVM); Long isoId = userVM.getIsoId(); if (isoId == null) { @@ -953,12 +952,11 @@ public boolean attachIso(long isoId, long vmId) { // check permissions // check if caller has access to VM and ISO - // and also check if the VM's owner has access to the ISO. - - _accountMgr.checkAccess(caller, null, false, iso, vm); - + // and also check if the VM's owner has access to the ISO. This is a bit different from sameOwner check for attachVolumeToVM, where both volume and VM need + // OperateEntry access type. Here VM needs OperateEntry access type, ISO needs UseEntry access type. + _accountMgr.checkAccess(caller, null, iso, vm); Account vmOwner = _accountDao.findById(vm.getAccountId()); - _accountMgr.checkAccess(vmOwner, null, false, iso, vm); + _accountMgr.checkAccess(vmOwner, null, iso); State vmState = vm.getState(); if (vmState != State.Running && vmState != State.Stopped) { @@ -1062,7 +1060,7 @@ public boolean deleteTemplate(DeleteTemplateCmd cmd) { throw new InvalidParameterValueException("unable to find template with id " + templateId); } - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, template); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, template); if (template.getFormat() == ImageFormat.ISO) { throw new InvalidParameterValueException("Please specify a valid template."); @@ -1085,7 +1083,7 @@ public boolean deleteIso(DeleteIsoCmd cmd) { throw new InvalidParameterValueException("unable to find iso with id " + templateId); } - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, template); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, template); if (template.getFormat() != ImageFormat.ISO) { throw new InvalidParameterValueException("Please specify a valid iso."); @@ -1135,7 +1133,7 @@ public List listTemplatePermissions(BaseListTemplateOrIsoPermissionsCmd } if (!template.isPublicTemplate()) { - _accountMgr.checkAccess(caller, null, true, template); + _accountMgr.checkAccess(caller, null, template); } List accountNames = new ArrayList(); @@ -1208,8 +1206,7 @@ public boolean updateTemplateOrIsoPermissions(BaseUpdateTemplateOrIsoPermissions } } - //_accountMgr.checkAccess(caller, AccessType.ModifyEntry, true, template); - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, template); //TODO: should we replace all ModifyEntry as OperateEntry? + _accountMgr.checkAccess(caller, AccessType.OperateEntry, template); // If the template is removed throw an error. if (template.getRemoved() != null) { @@ -1221,7 +1218,7 @@ public boolean updateTemplateOrIsoPermissions(BaseUpdateTemplateOrIsoPermissions throw new InvalidParameterValueException("unable to update permissions for " + mediaType + " with id " + id); } - boolean isAdmin = _accountMgr.isAdmin(caller.getType()); + boolean isAdmin = _accountMgr.isAdmin(caller.getId()); // check configuration parameter(allow.public.user.templates) value for // the template owner boolean allowPublicUserTemplates = AllowPublicUserTemplates.valueIn(template.getAccountId()); @@ -1304,7 +1301,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { // add ACL permission in IAM Map permit = new HashMap(); - permit.put(ApiConstants.ENTITY_TYPE, IAMEntityType.VirtualMachineTemplate.toString()); + permit.put(ApiConstants.ENTITY_TYPE, VirtualMachineTemplate.class); permit.put(ApiConstants.ENTITY_ID, id); permit.put(ApiConstants.ACCESS_TYPE, AccessType.UseEntry); permit.put(ApiConstants.IAM_ACTION, "listTemplates"); @@ -1321,7 +1318,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { _launchPermissionDao.removePermissions(id, accountIds); // remove ACL permission in IAM Map permit = new HashMap(); - permit.put(ApiConstants.ENTITY_TYPE, IAMEntityType.VirtualMachineTemplate.toString()); + permit.put(ApiConstants.ENTITY_TYPE, VirtualMachineTemplate.class); permit.put(ApiConstants.ENTITY_ID, id); permit.put(ApiConstants.ACCESS_TYPE, AccessType.UseEntry); permit.put(ApiConstants.IAM_ACTION, "listTemplates"); @@ -1488,9 +1485,9 @@ public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account t Long userId = CallContext.current().getCallingUserId(); Account caller = CallContext.current().getCallingAccount(); - boolean isAdmin = (_accountMgr.isAdmin(caller.getType())); + boolean isAdmin = (_accountMgr.isAdmin(caller.getId())); - _accountMgr.checkAccess(caller, null, true, templateOwner); + _accountMgr.checkAccess(caller, null, templateOwner); String name = cmd.getTemplateName(); if ((name == null) || (name.length() > 32)) { @@ -1542,7 +1539,7 @@ public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account t throw new InvalidParameterValueException("Failed to create private template record, unable to find volume " + volumeId); } // check permissions - _accountMgr.checkAccess(caller, null, true, volume); + _accountMgr.checkAccess(caller, null, volume); // If private template is created from Volume, check that the volume // will not be active when the private template is @@ -1565,7 +1562,7 @@ public VMTemplateVO createPrivateTemplateRecord(CreateTemplateCmd cmd, Account t volume = _volumeDao.findById(snapshot.getVolumeId()); // check permissions - _accountMgr.checkAccess(caller, null, true, snapshot); + _accountMgr.checkAccess(caller, null, snapshot); if (snapshot.getState() != Snapshot.State.BackedUp) { throw new InvalidParameterValueException("Snapshot id=" + snapshotId + " is not in " + Snapshot.State.BackedUp + @@ -1781,7 +1778,7 @@ private VMTemplateVO updateTemplateOrIso(BaseUpdateTemplateOrIsoCmd cmd) { verifyTemplateId(id); // do a permission check - _accountMgr.checkAccess(account, AccessType.OperateEntry, true, template); + _accountMgr.checkAccess(account, AccessType.OperateEntry, template); if (cmd.isRoutingType() != null) { if (!_accountService.isRootAdmin(account.getId())) { throw new PermissionDeniedException("Parameter isrouting can only be specified by a Root Admin, permission denied"); diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index f0d129a3ce..364d0b7ecf 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -46,7 +46,6 @@ import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.dao.AffinityGroupDao; import org.apache.cloudstack.api.InternalIdentity; import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd; @@ -61,7 +60,6 @@ import org.apache.cloudstack.managed.context.ManagedContextRunnable; import org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleDao; -import com.cloud.api.ApiDBUtils; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.Resource.ResourceOwnerType; @@ -91,7 +89,6 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.IpAddress; import com.cloud.network.IpAddressManager; -import com.cloud.network.Network; import com.cloud.network.VpnUserVO; import com.cloud.network.as.AutoScaleManager; import com.cloud.network.dao.AccountGuestVlanMapDao; @@ -126,7 +123,6 @@ import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.snapshot.SnapshotManager; import com.cloud.template.TemplateManager; -import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account.State; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserAccountDao; @@ -361,9 +357,17 @@ public AccountVO getSystemAccount() { } @Override - public boolean isAdmin(short accountType) { - return ((accountType == Account.ACCOUNT_TYPE_ADMIN) || (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) || - (accountType == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || (accountType == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN)); + public boolean isAdmin(Long accountId) { + if (accountId != null) { + AccountVO acct = _accountDao.findById(accountId); + if ((isRootAdmin(accountId)) || (isDomainAdmin(accountId)) || (isResourceDomainAdmin(accountId))) { + return true; + } else if (acct.getType() == Account.ACCOUNT_TYPE_READ_ONLY_ADMIN) { + return true; + } + + } + return false; } @Override @@ -394,7 +398,7 @@ public boolean isDomainAdmin(Long accountId) { try { if (checker.checkAccess(acct, null, null, "DomainCapability")) { if (s_logger.isDebugEnabled()) { - s_logger.debug("Root Access granted to " + acct + " by " + checker.getName()); + s_logger.debug("DomainAdmin Access granted to " + acct + " by " + checker.getName()); } return true; } @@ -415,8 +419,23 @@ public boolean isNormalUser(long accountId) { return false; } - public boolean isResourceDomainAdmin(short accountType) { - return (accountType == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN); + public boolean isResourceDomainAdmin(Long accountId) { + if (accountId != null) { + AccountVO acct = _accountDao.findById(accountId); + for (SecurityChecker checker : _securityCheckers) { + try { + if (checker.checkAccess(acct, null, null, "DomainResourceCapability")) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("ResourceDomainAdmin Access granted to " + acct + " by " + checker.getName()); + } + return true; + } + } catch (PermissionDeniedException ex) { + return false; + } + } + } + return false; } public boolean isInternalAccount(long accountId) { @@ -443,7 +462,7 @@ public void checkAccess(Account caller, Domain domain) throws PermissionDeniedEx } @Override - public void checkAccess(Account account, AccessType accessType, boolean sameOwner, PartOf... entities) throws PermissionDeniedException { + public void checkAccess(Account caller, AccessType accessType, boolean sameOwner, PartOf... entities) throws PermissionDeniedException { // TODO Auto-generated method stub //TO BE IMPLEMENTED @@ -451,95 +470,40 @@ public void checkAccess(Account account, AccessType accessType, boolean sameOwne } @Override - public void checkAccess(Account caller, AccessType accessType, boolean sameOwner, ControlledEntity... entities) { - checkAccess(caller, accessType, sameOwner, null, entities); + public void checkAccess(Account caller, AccessType accessType, ControlledEntity... entities) throws PermissionDeniedException { + checkAccess(caller, accessType, null, entities); } @Override - public void checkAccess(Account caller, AccessType accessType, boolean sameOwner, String apiName, ControlledEntity... entities) { - //check for the same owner - Long ownerId = null; - ControlledEntity prevEntity = null; - if (sameOwner) { - for (ControlledEntity entity : entities) { - if (sameOwner) { - if (ownerId == null) { - ownerId = entity.getAccountId(); - } else if (ownerId.longValue() != entity.getAccountId()) { - throw new PermissionDeniedException("Entity " + entity + " and entity " + prevEntity + " belong to different accounts"); - } - prevEntity = entity; - } - } - } - - if (caller.getId() == Account.ACCOUNT_ID_SYSTEM || isRootAdmin(caller.getId())) { - // no need to make permission checks if the system/root admin makes the call - if (s_logger.isTraceEnabled()) { - s_logger.trace("No need to make permission check for System/RootAdmin account, returning true"); - } - return; - } - - HashMap> domains = new HashMap>(); - - for (ControlledEntity entity : entities) { - long domainId = entity.getDomainId(); - if (entity.getAccountId() != -1 && domainId == -1) { // If account exists domainId should too so calculate - // it. This condition might be hit for templates or entities which miss domainId in their tables - Account account = ApiDBUtils.findAccountById(entity.getAccountId()); - domainId = account != null ? account.getDomainId() : -1; - } - if (entity.getAccountId() != -1 && domainId != -1 && !(entity instanceof VirtualMachineTemplate) && - !(entity instanceof Network && accessType != null && accessType == AccessType.UseEntry) && !(entity instanceof AffinityGroup)) { - List toBeChecked = domains.get(entity.getDomainId()); - // for templates, we don't have to do cross domains check - if (toBeChecked == null) { - toBeChecked = new ArrayList(); - domains.put(domainId, toBeChecked); - } - toBeChecked.add(entity); - } - boolean granted = false; - for (SecurityChecker checker : _securityCheckers) { - if (checker.checkAccess(caller, entity, accessType, apiName)) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Access to " + entity + " granted to " + caller + " by " + checker.getName()); - } - granted = true; - break; + public void checkAccess(Account caller, AccessType accessType, String apiName, ControlledEntity... entities) throws PermissionDeniedException { + boolean granted = false; + // construct entities identification string + StringBuffer entityBuf = new StringBuffer("{"); + for (ControlledEntity ent : entities) { + entityBuf.append(ent.toString()); + } + entityBuf.append("}"); + String entityStr = entityBuf.toString(); + for (SecurityChecker checker : _securityCheckers) { + if (checker.checkAccess(caller, accessType, apiName, entities)) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Access to " + entityStr + " granted to " + caller + " by " + checker.getName()); } - } - - if (!granted) { - assert false : "How can all of the security checkers pass on checking this check: " + entity; - throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to " + entity); + granted = true; + break; } } - for (Map.Entry> domain : domains.entrySet()) { - for (SecurityChecker checker : _securityCheckers) { - Domain d = _domainMgr.getDomain(domain.getKey()); - if (d == null || d.getRemoved() != null) { - throw new PermissionDeniedException("Domain is not found.", caller, domain.getValue()); - } - try { - checker.checkAccess(caller, d); - } catch (PermissionDeniedException e) { - e.addDetails(caller, domain.getValue()); - throw e; - } - } + if (!granted) { + assert false : "How can all of the security checkers pass on checking this check: " + entityStr; + throw new PermissionDeniedException("There's no way to confirm " + caller + " has access to " + entityStr); } - - // check that resources belong to the same account - } @Override public Long checkAccessAndSpecifyAuthority(Account caller, Long zoneId) { // We just care for resource domain admin for now. He should be permitted to see only his zone. - if (isResourceDomainAdmin(caller.getType())) { + if (isResourceDomainAdmin(caller.getAccountId())) { if (zoneId == null) return getZoneIdForAccount(caller); else if (zoneId.compareTo(getZoneIdForAccount(caller)) != 0) @@ -660,8 +624,10 @@ protected boolean cleanupAccount(AccountVO account, long callerUserId, Account c // delete the account from project accounts _projectAccountDao.removeAccountFromProjects(accountId); - //delete the account from group - _messageBus.publish(_name, MESSAGE_REMOVE_ACCOUNT_EVENT, PublishScope.LOCAL, accountId); + if (account.getType() != Account.ACCOUNT_TYPE_PROJECT) { + // delete the account from group + _messageBus.publish(_name, MESSAGE_REMOVE_ACCOUNT_EVENT, PublishScope.LOCAL, accountId); + } // delete all vm groups belonging to accont List groups = _vmGroupDao.listByAccountId(accountId); @@ -1110,7 +1076,7 @@ public UserAccount updateUser(UpdateUserCmd cmd) { throw new PermissionDeniedException("user id : " + id + " is system account, update is not allowed"); } - checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, true, account); + checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, account); if (firstName != null) { if (firstName.isEmpty()) { @@ -1224,7 +1190,7 @@ public UserAccount disableUser(long userId) { throw new InvalidParameterValueException("User id : " + userId + " is a system user, disabling is not allowed"); } - checkAccess(caller, AccessType.OperateEntry, true, account); + checkAccess(caller, AccessType.OperateEntry, account); boolean success = doSetUserStatus(userId, State.disabled); if (success) { @@ -1262,7 +1228,7 @@ public UserAccount enableUser(final long userId) { throw new InvalidParameterValueException("User id : " + userId + " is a system user, enabling is not allowed"); } - checkAccess(caller, AccessType.OperateEntry, true, account); + checkAccess(caller, AccessType.OperateEntry, account); boolean success = Transaction.execute(new TransactionCallback() { @Override @@ -1311,7 +1277,7 @@ public UserAccount lockUser(long userId) { throw new PermissionDeniedException("user id : " + userId + " is a system user, locking is not allowed"); } - checkAccess(caller, AccessType.OperateEntry, true, account); + checkAccess(caller, AccessType.OperateEntry, account); // make sure the account is enabled too // if the user is either locked already or disabled already, don't change state...only lock currently enabled @@ -1375,7 +1341,7 @@ boolean deleteUserAccount(long accountId) { throw new InvalidParameterValueException("The specified account does not exist in the system"); } - checkAccess(caller, null, true, account); + checkAccess(caller, null, account); // don't allow to delete default account (system and admin) if (account.isDefault()) { @@ -1420,7 +1386,7 @@ public AccountVO enableAccount(String accountName, Long domainId, Long accountId // Check if user performing the action is allowed to modify this account Account caller = CallContext.current().getCallingAccount(); - checkAccess(caller, AccessType.OperateEntry, true, account); + checkAccess(caller, AccessType.OperateEntry, account); boolean success = enableAccount(account.getId()); if (success) { @@ -1454,7 +1420,7 @@ public AccountVO lockAccount(String accountName, Long domainId, Long accountId) throw new PermissionDeniedException("Account id : " + accountId + " is a system account, lock is not allowed"); } - checkAccess(caller, AccessType.OperateEntry, true, account); + checkAccess(caller, AccessType.OperateEntry, account); if (lockAccount(account.getId())) { CallContext.current().putContextParameter(Account.class, account.getUuid()); @@ -1484,7 +1450,7 @@ public AccountVO disableAccount(String accountName, Long domainId, Long accountI throw new PermissionDeniedException("Account id : " + accountId + " is a system account, disable is not allowed"); } - checkAccess(caller, AccessType.OperateEntry, true, account); + checkAccess(caller, AccessType.OperateEntry, account); if (disableAccount(account.getId())) { CallContext.current().putContextParameter(Account.class, account.getUuid()); @@ -1603,7 +1569,7 @@ public boolean deleteUser(DeleteUserCmd deleteUserCmd) { throw new InvalidParameterValueException("The user is default and can't be removed"); } - checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, true, account); + checkAccess(CallContext.current().getCallingAccount(), AccessType.OperateEntry, account); CallContext.current().putContextParameter(User.class, user.getUuid()); return _userDao.remove(id); } @@ -1725,7 +1691,7 @@ public Account finalizeOwner(Account caller, String accountName, Long domainId, return getAccount(project.getProjectAccountId()); } - if (isAdmin(caller.getType()) && accountName != null && domainId != null) { + if (isAdmin(caller.getId()) && accountName != null && domainId != null) { Domain domain = _domainMgr.getDomain(domainId); if (domain == null) { throw new InvalidParameterValueException("Unable to find the domain by id=" + domainId); @@ -1738,7 +1704,7 @@ public Account finalizeOwner(Account caller, String accountName, Long domainId, checkAccess(caller, domain); return owner; - } else if (!isAdmin(caller.getType()) && accountName != null && domainId != null) { + } else if (!isAdmin(caller.getId()) && accountName != null && domainId != null) { if (!accountName.equals(caller.getAccountName()) || domainId.longValue() != caller.getDomainId()) { throw new PermissionDeniedException("Can't create/list resources for account " + accountName + " in domain " + domainId + ", permission denied"); } else { @@ -2099,7 +2065,7 @@ private UserAccount getUserAccount(String username, String password, Long domain UserAccount userAccount = _userAccountDao.getUserAccount(username, domainId); if (userAccount != null) { if (userAccount.getState().equalsIgnoreCase(Account.State.enabled.toString())) { - if (!isInternalAccount(userAccount.getType())) { + if (!isInternalAccount(userAccount.getId())) { // Internal accounts are not disabled int attemptsMade = userAccount.getLoginAttempts() + 1; if (updateIncorrectLoginCount) { @@ -2221,39 +2187,44 @@ public UserAccount getUserByApiKey(String apiKey) { public void buildACLSearchParameters(Account caller, Long id, String accountName, Long projectId, List permittedDomains, List permittedAccounts, List permittedResources, Ternary domainIdRecursiveListProject, boolean listAll, boolean forProjectInvitation, String action) { - //TODO: need to handle listAll flag + Long domainId = domainIdRecursiveListProject.first(); - if (domainId != null) { - // look for entity in the given domain - Domain domain = _domainDao.findById(domainId); - if (domain == null) { - throw new InvalidParameterValueException("Unable to find domain by id " + domainId); + Long accountId = null; + if (id == null) { + // if id is specified, it will ignore all other parameters + if (domainId != null) { + // look for entity in the given domain + Domain domain = _domainDao.findById(domainId); + if (domain == null) { + throw new InvalidParameterValueException("Unable to find domain by id " + domainId); + } + // check permissions + checkAccess(caller, domain); } - // check permissions - checkAccess(caller, domain); - } - if (accountName != null) { - if (projectId != null) { - throw new InvalidParameterValueException("Account and projectId can't be specified together"); - } + // specific account is specified, we need to filter contents to only show contents owned by that account. + if (accountName != null) { + if (projectId != null) { + throw new InvalidParameterValueException("Account and projectId can't be specified together"); + } - Account userAccount = null; - Domain domain = null; - if (domainId != null) { - userAccount = _accountDao.findActiveAccount(accountName, domainId); - domain = _domainDao.findById(domainId); - } else { - userAccount = _accountDao.findActiveAccount(accountName, caller.getDomainId()); - domain = _domainDao.findById(caller.getDomainId()); - } + Account userAccount = null; + Domain domain = null; + if (domainId != null) { + userAccount = _accountDao.findActiveAccount(accountName, domainId); + domain = _domainDao.findById(domainId); + } else { + userAccount = _accountDao.findActiveAccount(accountName, caller.getDomainId()); + domain = _domainDao.findById(caller.getDomainId()); + } - if (userAccount != null) { - //check permissions - checkAccess(caller, null, false, userAccount); - permittedAccounts.add(userAccount.getId()); - } else { - throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domain.getUuid()); + if (userAccount != null) { + //check permissions + checkAccess(caller, null, userAccount); + accountId = userAccount.getId(); + } else { + throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domain.getUuid()); + } } } @@ -2278,6 +2249,11 @@ public void buildACLSearchParameters(Account caller, Long id, String accountName } } } else { + AccessType accessType = AccessType.UseEntry; + if (listAll || id != null) { + // listAll = true or id given should show all resources that owner has ListEntry access type. + accessType = AccessType.ListEntry; + } domainIdRecursiveListProject.third(Project.ListProjectResourcesCriteria.SkipProjectResources); // search for policy permissions associated with caller to get all his authorized domains, accounts, and resources @@ -2288,18 +2264,37 @@ public void buildACLSearchParameters(Account caller, Long id, String accountName return; // no futher filtering QuerySelector qs = _querySelectors.get(0); - boolean grantedAll = qs.isGrantedAll(caller, action); + boolean grantedAll = qs.isGrantedAll(caller, action, accessType); + if ( grantedAll ){ - if ( domainId != null ){ + if (accountId != null) { + permittedAccounts.add(accountId); + domainIdRecursiveListProject.second(false); // isRecursive is only valid if only domainId is passed. + } else if (domainId != null) { permittedDomains.add(domainId); + } else { + domainIdRecursiveListProject.second(false); // isRecursive is only valid if only domainId is passed. } } else { - List grantedDomains = qs.getAuthorizedDomains(caller, action); - List grantedAccounts = qs.getAuthorizedAccounts(caller, action); - List grantedResources = qs.getAuthorizedResources(caller, action); - - if (permittedAccounts.isEmpty() && domainId != null) { + List grantedDomains = qs.getAuthorizedDomains(caller, action, accessType); + List grantedAccounts = qs.getAuthorizedAccounts(caller, action, accessType); + List grantedResources = qs.getAuthorizedResources(caller, action, accessType); + + if (accountId != null) { + // specific account filter is specified + if (grantedAccounts.contains(accountId)) { + permittedAccounts.add(accountId); + } else { + //TODO: we should also filter granted resources based on accountId passed. + // potential bug, if accountId is passed, it may show some granted resources that may not be owned by that account. + // to fix this, we need to change the interface to also pass ControlledEntity class to use EntityManager to find + // ControlledEntity instance to check accountId. But this has some issues for those non controlled entities, + // like NetworkACLItem + permittedResources.addAll(grantedResources); + } + domainIdRecursiveListProject.second(false); // isRecursive is only valid if only domainId is passed. + } else if (domainId != null) { // specific domain and no account is specified if (grantedDomains.contains(domainId)) { permittedDomains.add(domainId); @@ -2310,13 +2305,26 @@ public void buildACLSearchParameters(Account caller, Long id, String accountName permittedAccounts.add(acctId); } } + //TODO: we should also filter granted resources based on domainId passed. + // potential bug, if domainId is passed, it may show some granted resources that may not be in that domain. + // to fix this, we need to change the interface to also pass ControlledEntity class to use EntityManager to find + // ControlledEntity instance to check domainId. But this has some issues for those non controlled entities, + // like NetworkACLItem permittedResources.addAll(grantedResources); } - } else if (permittedAccounts.isEmpty()) { + } else { // neither domain nor account is not specified permittedDomains.addAll(grantedDomains); permittedAccounts.addAll(grantedAccounts); permittedResources.addAll(grantedResources); + domainIdRecursiveListProject.second(false); // isRecursive is only valid if only domainId is passed. + } + + if (permittedDomains.isEmpty() && permittedAccounts.isEmpty() & permittedResources.isEmpty()) { + // if at this point, all permitted arrays are empty, that means that caller cannot see anything, we put -1 in permittedAccounts + // to distinguish this case from the case that caller can see everything + permittedAccounts.add(-1L); + } } } diff --git a/server/src/com/cloud/vm/UserVmManager.java b/server/src/com/cloud/vm/UserVmManager.java index afe1002788..61e28d81bd 100755 --- a/server/src/com/cloud/vm/UserVmManager.java +++ b/server/src/com/cloud/vm/UserVmManager.java @@ -109,4 +109,6 @@ UserVm updateVirtualMachine(long id, String displayName, String group, Boolean h public void saveCustomOfferingDetails(long vmId, ServiceOffering serviceOffering); public void removeCustomOfferingDetails(long vmId); + + void generateUsageEvent(VirtualMachine vm, boolean isDisplay, String eventType); } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 393613a140..9a5a034400 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -69,6 +69,8 @@ import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; import org.apache.cloudstack.engine.service.api.OrchestrationService; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; @@ -80,11 +82,13 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.framework.jobs.AsyncJobManager; import org.apache.cloudstack.managed.context.ManagedContextRunnable; +import org.apache.cloudstack.storage.command.DettachCommand; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; import com.cloud.agent.api.GetVmDiskStatsAnswer; import com.cloud.agent.api.GetVmDiskStatsCommand; import com.cloud.agent.api.GetVmStatsAnswer; @@ -93,6 +97,8 @@ import com.cloud.agent.api.StartAnswer; import com.cloud.agent.api.VmDiskStatsEntry; import com.cloud.agent.api.VmStatsEntry; +import com.cloud.agent.api.to.DataTO; +import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.manager.Commands; @@ -191,6 +197,7 @@ import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.service.dao.ServiceOfferingDetailsDao; +import com.cloud.storage.DataStoreRole; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.GuestOSCategoryVO; import com.cloud.storage.GuestOSVO; @@ -204,6 +211,7 @@ import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateZoneVO; import com.cloud.storage.Volume; +import com.cloud.storage.VolumeApiService; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.GuestOSCategoryDao; @@ -445,6 +453,10 @@ public enum UserVmCloneType { UUIDManager _uuidMgr; @Inject DeploymentPlanningManager _planningMgr; + @Inject + VolumeApiService _volumeService; + @Inject + DataStoreManager _dataStoreMgr; protected ScheduledExecutorService _executor = null; protected int _expungeInterval; @@ -520,7 +532,7 @@ public UserVm resetVMPassword(ResetVMPasswordCmd cmd, String password) throws Re throw new InvalidParameterValueException("Vm with id " + vmId + " is not in the right state"); } - _accountMgr.checkAccess(caller, null, true, userVm); + _accountMgr.checkAccess(caller, null, userVm); boolean result = resetVMPasswordInternal(vmId, password); @@ -626,7 +638,7 @@ public UserVm resetVMSSHKey(ResetVMSSHKeyCmd cmd) throws ResourceUnavailableExce + " in specified domain id"); } - _accountMgr.checkAccess(caller, null, true, userVm); + _accountMgr.checkAccess(caller, null, userVm); String password = null; String sshPublicKey = s.getPublicKey(); if (template != null && template.getEnablePassword()) { @@ -766,7 +778,7 @@ public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) throws ResourceAllocationE + "; make sure the virtual machine is stopped"); } - _accountMgr.checkAccess(caller, null, true, vmInstance); + _accountMgr.checkAccess(caller, null, vmInstance); // Check resource limits for CPU and Memory. Map customParameters = cmd.getDetails(); @@ -828,9 +840,10 @@ public UserVm upgradeVirtualMachine(UpgradeVMCmd cmd) throws ResourceAllocationE } // Generate usage event for VM upgrade - generateUsageEvent(newServiceOffering, cmd.getDetails(), _vmDao.findById(vmId), EventTypes.EVENT_VM_UPGRADE); + UserVmVO userVm = _vmDao.findById(vmId); + generateUsageEvent( userVm, userVm.isDisplayVm(), EventTypes.EVENT_VM_UPGRADE); - return _vmDao.findById(vmInstance.getId()); + return userVm; } @Override @@ -879,7 +892,7 @@ private UserVm upgradeStoppedVirtualMachine(Long vmId, Long svcOffId, Map allNics = _nicDao.listByVmId(vmInstance.getId()); for (NicVO nic : allNics) { @@ -977,18 +983,12 @@ public UserVm addNicToVirtualMachine(AddNicToVMCmd cmd) throws InvalidParameterV profile = new NicProfile(ipAddress, null); } - // Perform permission check on VM - _accountMgr.checkAccess(caller, null, true, vmInstance); - // Verify that zone is not Basic DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterId()); if (dc.getNetworkType() == DataCenter.NetworkType.Basic) { throw new CloudRuntimeException("Zone " + vmInstance.getDataCenterId() + ", has a NetworkType of Basic. Can't add a new NIC to a VM on a Basic Network"); } - // Perform account permission check on network - _accountMgr.checkAccess(caller, AccessType.UseEntry, false, network); - //ensure network belongs in zone if (network.getDataCenterId() != vmInstance.getDataCenterId()) { throw new CloudRuntimeException(vmInstance + " is in zone:" + vmInstance.getDataCenterId() + " but " + network + " is in zone:" + network.getDataCenterId()); @@ -1047,7 +1047,7 @@ public UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd) throws Invalid } // Perform permission check on VM - _accountMgr.checkAccess(caller, null, true, vmInstance); + _accountMgr.checkAccess(caller, null, vmInstance); // Verify that zone is not Basic DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterId()); @@ -1061,7 +1061,7 @@ public UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd) throws Invalid } // Perform account permission check on network - _accountMgr.checkAccess(caller, AccessType.UseEntry, false, network); + _accountMgr.checkAccess(caller, AccessType.UseEntry, network); boolean nicremoved = false; @@ -1103,7 +1103,7 @@ public UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd) th } // Perform permission check on VM - _accountMgr.checkAccess(caller, null, true, vmInstance); + _accountMgr.checkAccess(caller, null, vmInstance); // Verify that zone is not Basic DataCenterVO dc = _dcDao.findById(vmInstance.getDataCenterId()); @@ -1184,13 +1184,13 @@ public UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd) th String nicIdString = Long.toString(nic.getId()); long newNetworkOfferingId = network.getNetworkOfferingId(); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(), - oldNicIdString, oldNetworkOfferingId, null, 1L, VirtualMachine.class.getName(), vmInstance.getUuid()); + oldNicIdString, oldNetworkOfferingId, null, 1L, VirtualMachine.class.getName(), vmInstance.getUuid(), vmInstance.isDisplay()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(), nicIdString, - newNetworkOfferingId, null, 1L, VirtualMachine.class.getName(), vmInstance.getUuid()); + newNetworkOfferingId, null, 1L, VirtualMachine.class.getName(), vmInstance.getUuid(), vmInstance.isDisplay()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(), nicIdString, - newNetworkOfferingId, null, 0L, VirtualMachine.class.getName(), vmInstance.getUuid()); + newNetworkOfferingId, null, 0L, VirtualMachine.class.getName(), vmInstance.getUuid(), vmInstance.isDisplay()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vmInstance.getAccountId(), vmInstance.getDataCenterId(), vmInstance.getId(), - oldNicIdString, oldNetworkOfferingId, null, 0L, VirtualMachine.class.getName(), vmInstance.getUuid()); + oldNicIdString, oldNetworkOfferingId, null, 0L, VirtualMachine.class.getName(), vmInstance.getUuid(), vmInstance.isDisplay()); return _vmDao.findById(vmInstance.getId()); } @@ -1212,11 +1212,11 @@ public UserVm upgradeVirtualMachine(ScaleVMCmd cmd) throws ResourceUnavailableEx UserVmVO vmInstance = _vmDao.findById(vmId); if (vmInstance.getState().equals(State.Stopped)) { // Generate usage event for VM upgrade - generateUsageEvent(_offeringDao.findById(newServiceOfferingId), cmd.getDetails(), _vmDao.findById(vmId), EventTypes.EVENT_VM_UPGRADE); + generateUsageEvent(vmInstance, vmInstance.isDisplayVm(), EventTypes.EVENT_VM_UPGRADE); } if (vmInstance.getState().equals(State.Running)) { // Generate usage event for Dynamic scaling of VM - generateUsageEvent(_offeringDao.findById(newServiceOfferingId), cmd.getDetails(), _vmDao.findById(vmId), EventTypes.EVENT_VM_UPGRADE); + generateUsageEvent( vmInstance, vmInstance.isDisplayVm(), EventTypes.EVENT_VM_DYNAMIC_SCALE); } return vmInstance; } else { @@ -1285,7 +1285,7 @@ private boolean upgradeRunningVirtualMachine(Long vmId, Long newServiceOfferingI throw new InvalidParameterValueException("This operation not permitted for this hypervisor of the vm"); } - _accountMgr.checkAccess(caller, null, true, vmInstance); + _accountMgr.checkAccess(caller, null, vmInstance); //Check if its a scale "up" ServiceOfferingVO newServiceOffering = _offeringDao.findById(newServiceOfferingId); @@ -1494,7 +1494,7 @@ public UserVm recoverVirtualMachine(RecoverVMCmd cmd) throws ResourceAllocationE } // check permissions - _accountMgr.checkAccess(caller, null, true, vm); + _accountMgr.checkAccess(caller, null, vm); if (vm.getRemoved() != null) { if (s_logger.isDebugEnabled()) { @@ -1557,8 +1557,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Resour offeringId = offering.getId(); } } - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - offeringId, templateId, volume.getSize(), Volume.class.getName(), volume.getUuid()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), + offeringId, templateId, volume.getSize(), Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); } } @@ -1610,7 +1610,7 @@ public boolean configure(String name, Map params) throws Configu _itMgr.registerGuru(VirtualMachine.Type.User, this); - VirtualMachine.State.getStateMachine().registerListener(new UserVmStateListener(_usageEventDao, _networkDao, _nicDao, _offeringDao)); + VirtualMachine.State.getStateMachine().registerListener(new UserVmStateListener(_usageEventDao, _networkDao, _nicDao, _offeringDao, _vmDao, this)); String value = _configDao.getValue(Config.SetVmInternalNameUsingDisplayName.key()); _instanceNameFlag = (value == null) ? false : Boolean.parseBoolean(value); @@ -1829,6 +1829,7 @@ public UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableEx String userData = cmd.getUserData(); Boolean isDynamicallyScalable = cmd.isDynamicallyScalable(); String hostName = cmd.getHostName(); + Account caller = CallContext.current().getCallingAccount(); // Input validation and permission checks UserVmVO vmInstance = _vmDao.findById(id.longValue()); @@ -1836,19 +1837,85 @@ public UserVm updateVirtualMachine(UpdateVMCmd cmd) throws ResourceUnavailableEx throw new InvalidParameterValueException("unable to find virtual machine with id " + id); } - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, vmInstance); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, vmInstance); //If the flag is specified and is changed if (isDisplayVm != null && isDisplayVm != vmInstance.isDisplayVm()) { + + //update vm + vmInstance.setDisplayVm(isDisplayVm); + + // Resource limit changes ServiceOffering offering = _serviceOfferingDao.findByIdIncludingRemoved(vmInstance.getServiceOfferingId()); _resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.user_vm, isDisplayVm); _resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.cpu, isDisplayVm, new Long(offering.getCpu())); _resourceLimitMgr.changeResourceCount(vmInstance.getAccountId(), ResourceType.memory, isDisplayVm, new Long(offering.getRamSize())); + + // Usage + saveUsageEvent(vmInstance); + + // take care of the root volume as well. + _volumeService.updateDisplay(_volsDao.findByInstanceAndType(id, Volume.Type.ROOT).get(0), isDisplayVm); + } return updateVirtualMachine(id, displayName, group, ha, isDisplayVm, osTypeId, userData, isDynamicallyScalable, cmd.getHttpMethod(), cmd.getCustomId(), hostName); } + private void usage(VirtualMachine vm){ + List nics = _nicDao.listByVmId(vm.getId()); + for (NicVO nic : nics) { + NetworkVO network = _networkDao.findById(nic.getNetworkId()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), + Long.toString(nic.getId()), network.getNetworkOfferingId(), null, 0L, vm.getClass().getName(), vm.getUuid(), vm.isDisplay()); + } + } + + private void saveUsageEvent(UserVmVO vm) { + + // If vm not destroyed + if( vm.getState() != State.Destroyed && vm.getState() != State.Expunging && vm.getState() != State.Error){ + + if(vm.isDisplayVm()){ + //1. Allocated VM Usage Event + generateUsageEvent(vm, true, EventTypes.EVENT_VM_CREATE); + + if(vm.getState() == State.Running || vm.getState() == State.Stopping){ + //2. Running VM Usage Event + generateUsageEvent(vm, true, EventTypes.EVENT_VM_START); + + // 3. Network offering usage + generateNetworkUsageForVm(vm, true, EventTypes.EVENT_NETWORK_OFFERING_ASSIGN); + } + + }else { + //1. Allocated VM Usage Event + generateUsageEvent(vm, true, EventTypes.EVENT_VM_DESTROY); + + if(vm.getState() == State.Running || vm.getState() == State.Stopping){ + //2. Running VM Usage Event + generateUsageEvent(vm, true, EventTypes.EVENT_VM_STOP); + + // 3. Network offering usage + generateNetworkUsageForVm(vm, true, EventTypes.EVENT_NETWORK_OFFERING_REMOVE); + } + } + } + + } + + private void generateNetworkUsageForVm(VirtualMachine vm, boolean isDisplay, String eventType){ + + List nics = _nicDao.listByVmId(vm.getId()); + for (NicVO nic : nics) { + NetworkVO network = _networkDao.findById(nic.getNetworkId()); + long isDefault = (nic.isDefaultNic()) ? 1 : 0; + UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), + Long.toString(nic.getId()), network.getNetworkOfferingId(), null, isDefault, vm.getClass().getName(), vm.getUuid(), isDisplay); + } + + } + @Override public UserVm updateVirtualMachine(long id, String displayName, String group, Boolean ha, Boolean isDisplayVmEnabled, Long osTypeId, String userData, Boolean isDynamicallyScalable, HTTPMethod httpMethod, String customId, String hostName) throws ResourceUnavailableException, InsufficientCapacityException { @@ -1985,7 +2052,7 @@ public UserVm rebootVirtualMachine(RebootVMCmd cmd) throws InsufficientCapacityE throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId); } - _accountMgr.checkAccess(caller, null, true, vmInstance); + _accountMgr.checkAccess(caller, null, vmInstance); // If the VM is Volatile in nature, on reboot discard the VM's root disk and create a new root disk for it: by calling restoreVM long serviceOfferingId = vmInstance.getServiceOfferingId(); @@ -2008,7 +2075,7 @@ public UserVm destroyVm(DestroyVMCmd cmd) throws ResourceUnavailableException, C long vmId = cmd.getId(); boolean expunge = cmd.getExpunge(); - if (!_accountMgr.isAdmin(ctx.getCallingAccount().getType()) && expunge) { + if (!_accountMgr.isAdmin(ctx.getCallingAccount().getId()) && expunge) { throw new PermissionDeniedException("Parameter " + ApiConstants.EXPUNGE + " can be passed by Admin only"); } @@ -2089,7 +2156,7 @@ public boolean deleteVmGroup(DeleteVMGroupCmd cmd) { throw new InvalidParameterValueException("unable to find a vm group with id " + groupId); } - _accountMgr.checkAccess(caller, null, true, group); + _accountMgr.checkAccess(caller, null, group); return deleteVmGroup(groupId); } @@ -2223,7 +2290,7 @@ public UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOff List networkList = new ArrayList(); // Verify that caller can perform actions in behalf of vm owner - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); // Get default guest network in Basic zone Network defaultNetwork = _networkModel.getExclusiveGuestNetwork(zone.getId()); @@ -2278,7 +2345,7 @@ public UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, Service boolean isVmWare = (template.getHypervisorType() == HypervisorType.VMware || (hypervisor != null && hypervisor == HypervisorType.VMware)); // Verify that caller can perform actions in behalf of vm owner - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); // If no network is specified, find system security group enabled network if (networkIdList == null || networkIdList.isEmpty()) { @@ -2336,7 +2403,7 @@ public UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, Service // Perform account permission check if (network.getAclType() == ACLType.Account) { - _accountMgr.checkAccess(caller, AccessType.UseEntry, false, network); + _accountMgr.checkAccess(caller, AccessType.UseEntry, network); } networkList.add(network); } @@ -2382,7 +2449,7 @@ public UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serv List networkList = new ArrayList(); // Verify that caller can perform actions in behalf of vm owner - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); List vpcSupportedHTypes = _vpcMgr.getSupportedVpcHypervisors(); if (networkIdList == null || networkIdList.isEmpty()) { @@ -2447,7 +2514,7 @@ public UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serv } } - _networkModel.checkNetworkPermissions(owner, network); + _networkModel.checkNetworkPermissions(owner, network, AccessType.UseEntry); // don't allow to use system networks NetworkOffering networkOffering = _entityMgr.findById(NetworkOffering.class, network.getNetworkOfferingId()); @@ -2476,7 +2543,7 @@ protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOf List affinityGroupIdList, Map customParameters, String customId) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, StorageUnavailableException, ResourceAllocationException { - _accountMgr.checkAccess(caller, null, true, owner); + _accountMgr.checkAccess(caller, null, owner); if (owner.getState() == Account.State.disabled) { throw new PermissionDeniedException("The owner of vm to deploy is disabled: " + owner); @@ -2552,7 +2619,7 @@ protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOf throw new InvalidParameterValueException("Unable to find security group by id " + securityGroupId); } else { // verify permissions - _accountMgr.checkAccess(caller, null, true, owner, sg); + _accountMgr.checkAccess(owner, AccessType.UseEntry, sg); } } } @@ -2568,27 +2635,7 @@ protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOf + " , Please try again after removing the affinity group"); } else { // verify permissions - if (ag.getAclType() == ACLType.Domain) { - _accountMgr.checkAccess(caller, null, false, owner, ag); - // Root admin has access to both VM and AG by default, - // but - // make sure the owner of these entities is same - if (caller.getId() == Account.ACCOUNT_ID_SYSTEM || _accountMgr.isRootAdmin(caller.getId())) { - if (!_affinityGroupService.isAffinityGroupAvailableInDomain(ag.getId(), owner.getDomainId())) { - throw new PermissionDeniedException("Affinity Group " + ag + " does not belong to the VM's domain"); - } - } - } else { - _accountMgr.checkAccess(caller, null, true, owner, ag); - // Root admin has access to both VM and AG by default, - // but - // make sure the owner of these entities is same - if (caller.getId() == Account.ACCOUNT_ID_SYSTEM || _accountMgr.isRootAdmin(caller.getId())) { - if (ag.getAccountId() != owner.getAccountId()) { - throw new PermissionDeniedException("Affinity Group " + ag + " does not belong to the VM's account"); - } - } - } + _accountMgr.checkAccess(owner, AccessType.UseEntry, ag); } } } @@ -2614,10 +2661,7 @@ protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOf } // Check templates permissions - if (!template.isPublicTemplate()) { - Account templateOwner = _accountMgr.getAccount(template.getAccountId()); - _accountMgr.checkAccess(owner, null, true, templateOwner); - } + _accountMgr.checkAccess(owner, AccessType.UseEntry, template); // check if the user data is correct validateUserData(userData, httpmethod); @@ -2642,17 +2686,12 @@ protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOf boolean securityGroupEnabled = false; boolean vpcNetwork = false; for (NetworkVO network : networkList) { - if (network.getDataCenterId() != zone.getId()) { + if ((network.getDataCenterId() != zone.getId()) && !network.isStrechedL2Network()) { throw new InvalidParameterValueException("Network id=" + network.getId() + " doesn't belong to zone " + zone.getId()); } - //relax the check if the caller is admin account - if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { - if (!(network.getGuestType() == Network.GuestType.Shared && network.getAclType() == ACLType.Domain) - && !(network.getAclType() == ACLType.Account && network.getAccountId() == accountId)) { - throw new InvalidParameterValueException("only shared network or isolated network with the same account_id can be added to vm"); - } - } + // Perform account permission check on network + _accountMgr.checkAccess(caller, AccessType.UseEntry, network); IpAddresses requestedIpPair = null; if (requestedIps != null && !requestedIps.isEmpty()) { @@ -2835,11 +2874,31 @@ public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCap vm.setIsoId(template.getId()); } Long rootDiskSize = null; + // custom root disk size, resizes base template to larger size if (customParameters.containsKey("rootdisksize")) { if (NumbersUtil.parseLong(customParameters.get("rootdisksize"), -1) <= 0) { throw new InvalidParameterValueException("rootdisk size should be a non zero number."); } - rootDiskSize = Long.parseLong(customParameters.get("rootDisksize")); + rootDiskSize = Long.parseLong(customParameters.get("rootdisksize")); + + // only KVM supports rootdisksize override + if (hypervisor != HypervisorType.KVM) { + throw new InvalidParameterValueException("Hypervisor " + hypervisor + " does not support rootdisksize override"); + } + + // rotdisksize must be larger than template + VMTemplateVO templateVO = _templateDao.findById(template.getId()); + if (templateVO == null) { + throw new InvalidParameterValueException("Unable to look up template by id " + template.getId()); + } + + if ((rootDiskSize << 30) < templateVO.getSize()) { + throw new InvalidParameterValueException("unsupported: rootdisksize override is smaller than template size " + templateVO.getSize()); + } else { + s_logger.debug("rootdisksize of " + (rootDiskSize << 30) + " was larger than template size of " + templateVO.getSize()); + } + + s_logger.debug("found root disk size of " + rootDiskSize); customParameters.remove("rootdisksize"); } @@ -2915,10 +2974,10 @@ public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCap if (!offering.isDynamic()) { UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), - hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid()); + hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm()); } else { UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, accountId, zone.getId(), vm.getId(), vm.getHostName(), offering.getId(), template.getId(), - hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), customParameters); + hypervisorType.toString(), VirtualMachine.class.getName(), vm.getUuid(), customParameters, vm.isDisplayVm()); } //Update Resource Count for the given account @@ -2928,13 +2987,22 @@ public UserVmVO doInTransaction(TransactionStatus status) throws InsufficientCap }); } - private void generateUsageEvent(ServiceOfferingVO serviceOffering, Map customParameters, UserVmVO vm, String eventType) { + @Override + public void generateUsageEvent(VirtualMachine vm, boolean isDisplay, String eventType){ + ServiceOfferingVO serviceOffering = _offeringDao.findById(vm.getId(), vm.getServiceOfferingId()); if (!serviceOffering.isDynamic()) { - UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName(), serviceOffering.getId(), vm.getTemplateId(), vm - .getHypervisorType().toString(), VirtualMachine.class.getName(), vm.getUuid()); - } else { - UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName(), serviceOffering.getId(), vm.getTemplateId(), vm - .getHypervisorType().toString(), VirtualMachine.class.getName(), vm.getUuid(), customParameters); + UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), + vm.getHostName(), serviceOffering.getId(), vm.getTemplateId(), vm.getHypervisorType().toString(), + VirtualMachine.class.getName(), vm.getUuid(), isDisplay); + } + else { + Map customParameters = new HashMap(); + customParameters.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString()); + customParameters.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString()); + customParameters.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString()); + UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), + vm.getHostName(), serviceOffering.getId(), vm.getTemplateId(), vm.getHypervisorType().toString(), + VirtualMachine.class.getName(), vm.getUuid(), customParameters, isDisplay); } } @@ -3104,7 +3172,7 @@ public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Command NetworkVO network = _networkDao.findById(nic.getNetworkId()); long isDefault = (nic.isDefaultNic()) ? 1 : 0; UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), Long.toString(nic.getId()), - network.getNetworkOfferingId(), null, isDefault, VirtualMachine.class.getName(), vm.getUuid()); + network.getNetworkOfferingId(), null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay()); if (network.getTrafficType() == TrafficType.Guest) { originalIp = nic.getIp4Address(); guestNic = nic; @@ -3246,7 +3314,7 @@ public Pair> startVirtualMach throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId); } - _accountMgr.checkAccess(callerAccount, null, true, vm); + _accountMgr.checkAccess(callerAccount, null, vm); Account owner = _accountDao.findById(vm.getAccountId()); @@ -3389,7 +3457,7 @@ public UserVm destroyVm(long vmId) throws ResourceUnavailableException, Concurre for (VolumeVO volume : volumes) { if (volume.getVolumeType().equals(Volume.Type.ROOT)) { UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - Volume.class.getName(), volume.getUuid()); + Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); } } @@ -3424,12 +3492,12 @@ public void collectVmDiskStatistics(final UserVmVO userVm) { try { diskStatsAnswer = (GetVmDiskStatsAnswer)_agentMgr.easySend(hostId, new GetVmDiskStatsCommand(vmNames, host.getGuid(), host.getName())); } catch (Exception e) { - s_logger.warn("Error while collecting disk stats for vm: " + userVm.getHostName() + " from host: " + host.getName(), e); + s_logger.warn("Error while collecting disk stats for vm: " + userVm.getInstanceName() + " from host: " + host.getName(), e); return; } if (diskStatsAnswer != null) { if (!diskStatsAnswer.getResult()) { - s_logger.warn("Error while collecting disk stats vm: " + userVm.getHostName() + " from host: " + host.getName() + "; details: " + diskStatsAnswer.getDetails()); + s_logger.warn("Error while collecting disk stats vm: " + userVm.getInstanceName() + " from host: " + host.getName() + "; details: " + diskStatsAnswer.getDetails()); return; } try { @@ -3552,7 +3620,7 @@ public UserVm expungeVm(long vmId) throws ResourceUnavailableException, Concurre throw ex; } - _accountMgr.checkAccess(caller, null, true, vm); + _accountMgr.checkAccess(caller, null, vm); boolean status; @@ -3622,7 +3690,12 @@ public VirtualMachine vmStorageMigration(Long vmId, StoragePool destPool) { throw new InvalidParameterValueException("Data disks attached to the vm, can not migrate. Need to dettach data disks at first"); } - HypervisorType destHypervisorType = _clusterDao.findById(destPool.getClusterId()).getHypervisorType(); + HypervisorType destHypervisorType = destPool.getHypervisor(); + if (destHypervisorType == null) { + destHypervisorType = _clusterDao.findById( + destPool.getClusterId()).getHypervisorType(); + } + if (vm.getHypervisorType() != destHypervisorType) { throw new InvalidParameterValueException("hypervisor is not compatible: dest: " + destHypervisorType.toString() + ", vm: " + vm.getHypervisorType().toString()); } @@ -4128,8 +4201,8 @@ public UserVm moveVMToUser(final AssignVMCmd cmd) throws ResourceAllocationExcep } //check caller has access to both the old and new account - _accountMgr.checkAccess(caller, null, true, oldAccount); - _accountMgr.checkAccess(caller, null, true, newAccount); + _accountMgr.checkAccess(caller, null, oldAccount); + _accountMgr.checkAccess(caller, null, newAccount); // make sure the accounts are not same if (oldAccount.getAccountId() == newAccount.getAccountId()) { @@ -4182,7 +4255,7 @@ public UserVm moveVMToUser(final AssignVMCmd cmd) throws ResourceAllocationExcep VirtualMachineTemplate template = _templateDao.findById(vm.getTemplateId()); if (!template.isPublicTemplate()) { Account templateOwner = _accountMgr.getAccount(template.getAccountId()); - _accountMgr.checkAccess(newAccount, null, true, templateOwner); + _accountMgr.checkAccess(newAccount, null, templateOwner); } // VV 5: check the new account can create vm in the domain @@ -4194,7 +4267,7 @@ public UserVm moveVMToUser(final AssignVMCmd cmd) throws ResourceAllocationExcep public void doInTransactionWithoutResult(TransactionStatus status) { //generate destroy vm event for usage UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_DESTROY, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName(), vm.getServiceOfferingId(), - vm.getTemplateId(), vm.getHypervisorType().toString(), VirtualMachine.class.getName(), vm.getUuid()); + vm.getTemplateId(), vm.getHypervisorType().toString(), VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm()); // update resource counts for old account resourceCountDecrement(oldAccount.getAccountId(), vm.isDisplayVm(), new Long(offering.getCpu()), new Long(offering.getRamSize())); @@ -4206,20 +4279,20 @@ public void doInTransactionWithoutResult(TransactionStatus status) { // OS 2: update volume for (VolumeVO volume : volumes) { - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - Volume.class.getName(), volume.getUuid()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_DELETE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), + Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); _resourceLimitMgr.decrementResourceCount(oldAccount.getAccountId(), ResourceType.volume); - _resourceLimitMgr.decrementResourceCount(oldAccount.getAccountId(), ResourceType.primary_storage, new Long(volume.getSize())); + _resourceLimitMgr.decrementResourceCount(oldAccount.getAccountId(), ResourceType.primary_storage, new Long(volume.getSize())); volume.setAccountId(newAccount.getAccountId()); volume.setDomainId(newAccount.getDomainId()); _volsDao.persist(volume); _resourceLimitMgr.incrementResourceCount(newAccount.getAccountId(), ResourceType.volume); - _resourceLimitMgr.incrementResourceCount(newAccount.getAccountId(), ResourceType.primary_storage, new Long(volume.getSize())); - UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), - volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid()); + _resourceLimitMgr.incrementResourceCount(newAccount.getAccountId(), ResourceType.primary_storage, new Long(volume.getSize())); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VOLUME_CREATE, volume.getAccountId(), volume.getDataCenterId(), volume.getId(), volume.getName(), + volume.getDiskOfferingId(), volume.getTemplateId(), volume.getSize(), Volume.class.getName(), volume.getUuid(), volume.isDisplayVolume()); //snapshots: mark these removed in db List snapshots = _snapshotDao.listByVolumeIdIncludingRemoved(volume.getId()); - for (SnapshotVO snapshot : snapshots) { + for (SnapshotVO snapshot : snapshots) { _snapshotDao.remove(snapshot.getId()); } } @@ -4229,7 +4302,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { //generate usage events to account for this change UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_CREATE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName(), vm.getServiceOfferingId(), - vm.getTemplateId(), vm.getHypervisorType().toString(), VirtualMachine.class.getName(), vm.getUuid()); + vm.getTemplateId(), vm.getHypervisorType().toString(), VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplayVm()); } }); @@ -4332,7 +4405,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { throw ex; } - _networkModel.checkNetworkPermissions(newAccount, network); + _networkModel.checkNetworkPermissions(newAccount, network, AccessType.UseEntry); // don't allow to use system networks NetworkOffering networkOffering = _entityMgr.findById(NetworkOffering.class, network.getNetworkOfferingId()); @@ -4439,7 +4512,7 @@ public UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException, throw ex; } - _accountMgr.checkAccess(caller, null, true, vm); + _accountMgr.checkAccess(caller, null, vm); return restoreVMInternal(caller, vm, newTemplateId); } @@ -4489,7 +4562,7 @@ public UserVm restoreVMInternal(Account caller, UserVmVO vm, Long newTemplateId) //newTemplateId can be either template or ISO id. In the following snippet based on the vm deployment (from template or ISO) it is handled accordingly if (newTemplateId != null) { template = _templateDao.findById(newTemplateId); - _accountMgr.checkAccess(caller, null, true, template); + _accountMgr.checkAccess(caller, null, template); if (isISO) { if (!template.getFormat().equals(ImageFormat.ISO)) { throw new InvalidParameterValueException("Invalid ISO id provided to restore the VM "); @@ -4551,6 +4624,9 @@ public UserVm restoreVMInternal(Account caller, UserVmVO vm, Long newTemplateId) /* Detach and destory the old root volume */ _volsDao.detachVolume(root.getId()); + + handleManagedStorage(vm, root); + volumeMgr.destroyVolume(root); // For VMware hypervisor since the old root volume is replaced by the new root volume, force expunge old root volume if it has been created in storage @@ -4598,6 +4674,59 @@ public UserVm restoreVMInternal(Account caller, UserVmVO vm, Long newTemplateId) } + private void handleManagedStorage(UserVmVO vm, VolumeVO root) { + StoragePoolVO storagePool = _storagePoolDao.findById(root.getPoolId()); + + if (storagePool.isManaged()) { + Long hostId = vm.getHostId() != null ? vm.getHostId() : vm.getLastHostId(); + + if (hostId != null) { + DataTO volTO = volFactory.getVolume(root.getId()).getTO(); + DiskTO disk = new DiskTO(volTO, root.getDeviceId(), root.getPath(), root.getVolumeType()); + + // it's OK in this case to send a detach command to the host for a root volume as this + // will simply lead to the SR that supports the root volume being removed + DettachCommand cmd = new DettachCommand(disk, vm.getInstanceName()); + + cmd.setManaged(true); + + cmd.setStorageHost(storagePool.getHostAddress()); + cmd.setStoragePort(storagePool.getPort()); + + cmd.set_iScsiName(root.get_iScsiName()); + + Commands cmds = new Commands(Command.OnError.Stop); + + cmds.addCommand(cmd); + + try { + _agentMgr.send(hostId, cmds); + } + catch (Exception ex) { + throw new CloudRuntimeException(ex.getMessage()); + } + + if (!cmds.isSuccessful()) { + for (Answer answer : cmds.getAnswers()) { + if (!answer.getResult()) { + s_logger.warn("Failed to reset vm due to: " + answer.getDetails()); + + throw new CloudRuntimeException("Unable to reset " + vm + " due to " + answer.getDetails()); + } + } + } + + if (hostId != null) { + // root.getPoolId() should be null if the VM we are attaching the disk to has never been started before + DataStore dataStore = root.getPoolId() != null ? _dataStoreMgr.getDataStore(root.getPoolId(), DataStoreRole.Primary) : null; + Host host = _hostDao.findById(hostId); + + volumeMgr.disconnectVolumeFromHost(volFactory.getVolume(root.getId()), host, dataStore); + } + } + } + } + @Override public void prepareStop(VirtualMachineProfile profile) { UserVmVO vm = _vmDao.findById(profile.getId()); @@ -4640,7 +4769,7 @@ public String getVmUserData(long vmId) { } //check permissions - _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, true, vm); + _accountMgr.checkAccess(CallContext.current().getCallingAccount(), null, vm); return vm.getUserData(); } diff --git a/server/src/com/cloud/vm/UserVmStateListener.java b/server/src/com/cloud/vm/UserVmStateListener.java index 2f6be6cbbc..202391f4e4 100644 --- a/server/src/com/cloud/vm/UserVmStateListener.java +++ b/server/src/com/cloud/vm/UserVmStateListener.java @@ -25,6 +25,7 @@ import javax.inject.Inject; import com.cloud.server.ManagementService; +import com.cloud.vm.dao.UserVmDao; import org.apache.log4j.Logger; import org.springframework.beans.factory.NoSuchBeanDefinitionException; @@ -33,11 +34,9 @@ import com.cloud.event.EventCategory; import com.cloud.event.EventTypes; import com.cloud.event.UsageEventUtils; -import com.cloud.event.UsageEventVO; import com.cloud.event.dao.UsageEventDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; -import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.fsm.StateListener; @@ -51,15 +50,19 @@ public class UserVmStateListener implements StateListener customParameters = new HashMap(); - customParameters.put(UsageEventVO.DynamicParameters.cpuNumber.name(), serviceOffering.getCpu().toString()); - customParameters.put(UsageEventVO.DynamicParameters.cpuSpeed.name(), serviceOffering.getSpeed().toString()); - customParameters.put(UsageEventVO.DynamicParameters.memory.name(), serviceOffering.getRamSize().toString()); - UsageEventUtils.publishUsageEvent(eventType, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), - vm.getHostName(), serviceOffering.getId(), vm.getTemplateId(), vm.getHypervisorType().toString(), - VirtualMachine.class.getName(), vm.getUuid(), customParameters); + private void generateUsageEvent(Long serviceOfferingId, VirtualMachine vm, String eventType){ + boolean displayVm = true; + if(vm.getType() == VirtualMachine.Type.User){ + UserVmVO uservm = _userVmDao.findById(vm.getId()); + displayVm = uservm.isDisplayVm(); } + + _userVmMgr.generateUsageEvent(vm, displayVm, eventType); } private void pubishOnEventBus(String event, String status, VirtualMachine vo, VirtualMachine.State oldState, VirtualMachine.State newState) { diff --git a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java index 37cdf86fd4..8dc2c1862c 100644 --- a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java +++ b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java @@ -297,7 +297,7 @@ public VMSnapshot allocVMSnapshot(Long vmId, String vsDisplayName, String vsDesc } // check access - _accountMgr.checkAccess(caller, null, true, userVmVo); + //_accountMgr.checkAccess(caller, null, userVmVo); // check max snapshot limit for per VM if (_vmSnapshotDao.findByVm(vmId).size() >= _vmSnapshotMax) { @@ -448,7 +448,7 @@ public boolean deleteVMSnapshot(Long vmSnapshotId) { throw new InvalidParameterValueException("unable to find the vm snapshot with id " + vmSnapshotId); } - _accountMgr.checkAccess(caller, null, true, vmSnapshot); + _accountMgr.checkAccess(caller, null, vmSnapshot); // check VM snapshot states, only allow to delete vm snapshots in created and error state if (VMSnapshot.State.Ready != vmSnapshot.getState() && VMSnapshot.State.Expunging != vmSnapshot.getState() && VMSnapshot.State.Error != vmSnapshot.getState()) { @@ -513,7 +513,7 @@ private boolean orchestrateDeleteVMSnapshot(Long vmSnapshotId) { throw new InvalidParameterValueException("unable to find the vm snapshot with id " + vmSnapshotId); } - _accountMgr.checkAccess(caller, null, true, vmSnapshot); + _accountMgr.checkAccess(caller, null, vmSnapshot); // check VM snapshot states, only allow to delete vm snapshots in created and error state if (VMSnapshot.State.Ready != vmSnapshot.getState() && VMSnapshot.State.Expunging != vmSnapshot.getState() && VMSnapshot.State.Error != vmSnapshot.getState()) { @@ -564,7 +564,7 @@ public UserVm revertToSnapshot(Long vmSnapshotId) throws InsufficientCapacityExc } Account caller = getCaller(); - _accountMgr.checkAccess(caller, null, true, vmSnapshotVo); + _accountMgr.checkAccess(caller, null, vmSnapshotVo); // VM should be in running or stopped states if (userVm.getState() != VirtualMachine.State.Running @@ -646,7 +646,7 @@ private UserVm orchestrateRevertToVMSnapshot(Long vmSnapshotId) throws Insuffici } Account caller = getCaller(); - _accountMgr.checkAccess(caller, null, true, vmSnapshotVo); + _accountMgr.checkAccess(caller, null, vmSnapshotVo); // VM should be in running or stopped states if (userVm.getState() != VirtualMachine.State.Running && userVm.getState() != VirtualMachine.State.Stopped) { diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java index f375fde565..ef636920cd 100644 --- a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java +++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java @@ -28,7 +28,6 @@ import org.apache.log4j.Logger; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; @@ -218,7 +217,7 @@ public AffinityGroupVO doInTransaction(TransactionStatus status) { _affinityGroupDomainMapDao.persist(domainMap); //send event for storing the domain wide resource access Map params = new HashMap(); - params.put(ApiConstants.ENTITY_TYPE, IAMEntityType.AffinityGroup); + params.put(ApiConstants.ENTITY_TYPE, AffinityGroup.class); params.put(ApiConstants.ENTITY_ID, group.getId()); params.put(ApiConstants.DOMAIN_ID, domainId); params.put(ApiConstants.SUBDOMAIN_ACCESS, subDomainAccess); @@ -263,7 +262,7 @@ public boolean deleteAffinityGroup(Long affinityGroupId, String account, Long do affinityGroupId = group.getId(); } // check permissions - _accountMgr.checkAccess(caller, AccessType.OperateEntry, true, group); + _accountMgr.checkAccess(caller, AccessType.OperateEntry, group); final Long affinityGroupIdFinal = affinityGroupId; Transaction.execute(new TransactionCallbackNoReturn() { @@ -300,7 +299,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { _affinityGroupDomainMapDao.remove(groupDomain.getId()); } // remove its related ACL permission - Pair params = new Pair(IAMEntityType.AffinityGroup, affinityGroupIdFinal); + Pair, Long> params = new Pair, Long>(AffinityGroup.class, affinityGroupIdFinal); _messageBus.publish(_name, EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, PublishScope.LOCAL, params); } } @@ -354,7 +353,7 @@ public Pair, Integer> listAffinityGroups(Long affi if (userVM == null) { throw new InvalidParameterValueException("Unable to list affinity groups for virtual machine instance " + vmId + "; instance not found."); } - _accountMgr.checkAccess(caller, null, true, userVM); + _accountMgr.checkAccess(caller, null, userVM); // add join to affinity_groups_vm_map groupSearch.join("vmInstanceSearch", vmInstanceSearch, groupSearch.entity().getId(), vmInstanceSearch.entity().getAffinityGroupId(), JoinBuilder.JoinType.INNER); @@ -478,14 +477,7 @@ public UserVm updateVMAffinityGroups(Long vmId, List affinityGroupIds) { throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupId); } else { // verify permissions - _accountMgr.checkAccess(caller, null, true, owner, ag); - // Root admin has access to both VM and AG by default, but make sure the - // owner of these entities is same - if (caller.getId() == Account.ACCOUNT_ID_SYSTEM || _accountMgr.isRootAdmin(caller.getId())) { - if (ag.getAccountId() != owner.getAccountId()) { - throw new PermissionDeniedException("Affinity Group " + ag + " does not belong to the VM's account"); - } - } + _accountMgr.checkAccess(owner, AccessType.UseEntry, ag); } } _affinityGroupVMMapDao.updateMap(vmId, affinityGroupIds); diff --git a/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java b/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java index 73bf0d2a38..ad1a2c4ec8 100644 --- a/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java +++ b/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java @@ -24,14 +24,15 @@ import javax.ejb.Local; import javax.inject.Inject; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.user.loadbalancer.ListApplicationLoadBalancersCmd; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; import org.apache.cloudstack.lb.ApplicationLoadBalancerRuleVO; import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; @@ -114,7 +115,7 @@ public ApplicationLoadBalancerRule createApplicationLoadBalancer(String name, St } Account caller = CallContext.current().getCallingAccount(); - _accountMgr.checkAccess(caller, AccessType.UseEntry, false, guestNtwk); + _accountMgr.checkAccess(caller, AccessType.UseEntry, guestNtwk); Network sourceIpNtwk = _networkModel.getNetwork(sourceIpNetworkId); if (sourceIpNtwk == null) { @@ -546,7 +547,7 @@ public ApplicationLoadBalancerRule updateApplicationLoadBalancer(Long id, String if (rule == null) { throw new InvalidParameterValueException("Unable to find load balancer " + id); } - _accountMgr.checkAccess(caller, null, true, rule); + _accountMgr.checkAccess(caller, null, rule); if (customId != null) { rule.setUuid(customId); diff --git a/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java b/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java index ba71d631a9..67f2c02e0c 100644 --- a/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java +++ b/server/src/org/apache/cloudstack/network/lb/CertServiceImpl.java @@ -147,7 +147,7 @@ public void deleteSslCert(DeleteSslCertCmd deleteSslCertCmd) { if (certVO == null) { throw new InvalidParameterValueException("Invalid certificate id: " + certId); } - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, true, certVO); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, certVO); List lbCertRule = _lbCertDao.listByCertId(certId); @@ -191,7 +191,7 @@ public List listSslCerts(ListSslCertsCmd listSslCertCmd) { throw new InvalidParameterValueException("Invalid certificate id: " + certId); } - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, true, certVO); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, certVO); certLbMap = _lbCertDao.listByCertId(certId); @@ -206,7 +206,7 @@ public List listSslCerts(ListSslCertsCmd listSslCertCmd) { throw new InvalidParameterValueException("found no loadbalancer wth id: " + lbRuleId); } - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, true, lb); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, lb); // get the cert id LoadBalancerCertMapVO lbCertMapRule; @@ -229,7 +229,7 @@ public List listSslCerts(ListSslCertsCmd listSslCertCmd) { List certVOList = _sslCertDao.listByAccountId(accountId); if (certVOList == null || certVOList.isEmpty()) return certResponseList; - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, true, certVOList.get(0)); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseEntry, certVOList.get(0)); for (SslCertVO cert : certVOList) { certLbMap = _lbCertDao.listByCertId(cert.getId()); diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java index c84fea29d5..516b3ab521 100644 --- a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java @@ -183,7 +183,7 @@ public boolean assignToGlobalLoadBalancerRule(AssignToGlobalLoadBalancerRuleCmd throw new InvalidParameterValueException("Invalid global load balancer rule id: " + gslbRuleId); } - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, true, gslbRule); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, gslbRule); if (gslbRule.getState() == GlobalLoadBalancerRule.State.Revoke) { throw new InvalidParameterValueException("global load balancer rule id: " + gslbRule.getUuid() + " is in revoked state"); @@ -224,7 +224,7 @@ public boolean assignToGlobalLoadBalancerRule(AssignToGlobalLoadBalancerRuleCmd throw new InvalidParameterValueException("Specified load balancer rule ID does not exist."); } - _accountMgr.checkAccess(caller, null, true, loadBalancer); + _accountMgr.checkAccess(caller, null, loadBalancer); if (gslbRule.getAccountId() != loadBalancer.getAccountId()) { throw new InvalidParameterValueException("GSLB rule and load balancer rule does not belong to same account"); @@ -319,7 +319,7 @@ public boolean removeFromGlobalLoadBalancerRule(RemoveFromGlobalLoadBalancerRule throw new InvalidParameterValueException("Invalid global load balancer rule id: " + gslbRuleId); } - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, true, gslbRule); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, gslbRule); if (gslbRule.getState() == GlobalLoadBalancerRule.State.Revoke) { throw new InvalidParameterValueException("global load balancer rule id: " + gslbRuleId + " is already in revoked state"); @@ -346,7 +346,7 @@ public boolean removeFromGlobalLoadBalancerRule(RemoveFromGlobalLoadBalancerRule throw new InvalidParameterValueException("Specified load balancer rule ID does not exist."); } - _accountMgr.checkAccess(caller, null, true, loadBalancer); + _accountMgr.checkAccess(caller, null, loadBalancer); } for (GlobalLoadBalancerLbRuleMapVO gslbLbMapVo : gslbLbMapVos) { @@ -445,7 +445,7 @@ private void revokeGslbRule(final long gslbRuleId, Account caller) { throw new InvalidParameterValueException("Invalid global load balancer rule id: " + gslbRuleId); } - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, true, gslbRule); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, gslbRule); if (gslbRule.getState() == com.cloud.region.ha.GlobalLoadBalancerRule.State.Staged) { if (s_logger.isDebugEnabled()) { @@ -523,7 +523,7 @@ public GlobalLoadBalancerRule updateGlobalLoadBalancerRule(UpdateGlobalLoadBalan CallContext ctx = CallContext.current(); Account caller = ctx.getCallingAccount(); - _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, true, gslbRule); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.OperateEntry, gslbRule); if (algorithm != null && !GlobalLoadBalancerRule.Algorithm.isValidAlgorithm(algorithm)) { throw new InvalidParameterValueException("Invalid Algorithm: " + algorithm); @@ -583,7 +583,7 @@ public List listGlobalLoadBalancerRule(ListGlobalLoadBal if (gslbRule == null) { throw new InvalidParameterValueException("Invalid gslb rule id specified"); } - _accountMgr.checkAccess(caller, org.apache.cloudstack.acl.SecurityChecker.AccessType.UseEntry, false, gslbRule); + _accountMgr.checkAccess(caller, org.apache.cloudstack.acl.SecurityChecker.AccessType.UseEntry, gslbRule); response.add(gslbRule); return response; diff --git a/server/test/com/cloud/api/dispatch/ParamGenericValidationWorkerTest.java b/server/test/com/cloud/api/dispatch/ParamGenericValidationWorkerTest.java index 8f9709ca9d..3073c7ffd8 100644 --- a/server/test/com/cloud/api/dispatch/ParamGenericValidationWorkerTest.java +++ b/server/test/com/cloud/api/dispatch/ParamGenericValidationWorkerTest.java @@ -95,6 +95,10 @@ public void testHandle() throws ResourceAllocationException { params.put(ApiConstants.SIGNATURE, ""); params.put(ApiConstants.CTX_ACCOUNT_ID, ""); params.put(ApiConstants.CTX_START_EVENT_ID, ""); + // Make sure it's case insensitive + params.put(ApiConstants.CTX_START_EVENT_ID, ""); + params.put(ApiConstants.CTX_START_EVENT_ID.toLowerCase(), ""); + params.put(ApiConstants.CTX_USER_ID.toUpperCase(), ""); params.put(ApiConstants.CTX_USER_ID, ""); params.put(ApiConstants.UUID, ""); params.put(ApiConstants.ID, ""); diff --git a/server/test/com/cloud/event/EventControlsUnitTest.java b/server/test/com/cloud/event/EventControlsUnitTest.java index 91dc921d26..0dc57427c5 100644 --- a/server/test/com/cloud/event/EventControlsUnitTest.java +++ b/server/test/com/cloud/event/EventControlsUnitTest.java @@ -60,7 +60,7 @@ protected void setUp() { MockitoAnnotations.initMocks(this); _mgmtServer._eventDao = _eventDao; _mgmtServer._accountMgr = _accountMgr; - doNothing().when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class)); + doNothing().when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(ControlledEntity.class)); when(_eventDao.listToArchiveOrDeleteEvents(anyList(), anyString(), any(Date.class), any(Date.class), anyList())).thenReturn(_events); } diff --git a/server/test/com/cloud/network/CreatePrivateNetworkTest.java b/server/test/com/cloud/network/CreatePrivateNetworkTest.java index dc979d05c9..b124b20dad 100644 --- a/server/test/com/cloud/network/CreatePrivateNetworkTest.java +++ b/server/test/com/cloud/network/CreatePrivateNetworkTest.java @@ -103,7 +103,7 @@ public void setup() throws Exception { NetworkOfferingVO ntwkOff = new NetworkOfferingVO("offer", "fakeOffer", TrafficType.Guest, true, true, null, null, false, null, null, GuestType.Isolated, false, false, false, false, - false, false, false, false, false, false, false, false, false); + false, false, false, false, false, false, false, false, false, false); when(networkService._networkOfferingDao.findById(anyLong())).thenReturn(ntwkOff); List netofferlist = new ArrayList(); netofferlist.add(ntwkOff); diff --git a/server/test/com/cloud/network/MockNetworkModelImpl.java b/server/test/com/cloud/network/MockNetworkModelImpl.java index 6c9e597b9f..33387fae64 100644 --- a/server/test/com/cloud/network/MockNetworkModelImpl.java +++ b/server/test/com/cloud/network/MockNetworkModelImpl.java @@ -25,6 +25,8 @@ import javax.ejb.Local; import javax.naming.ConfigurationException; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; + import com.cloud.dc.Vlan; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InvalidParameterValueException; @@ -878,4 +880,10 @@ public boolean isNetworkReadyForGc(long networkId) { public boolean getNetworkEgressDefaultPolicy(Long networkId) { return false; //To change body of implemented methods use File | Settings | File Templates. } + + @Override + public void checkNetworkPermissions(Account owner, Network network, AccessType accessType) { + // TODO Auto-generated method stub + + } } diff --git a/server/test/com/cloud/network/lb/AssignLoadBalancerTest.java b/server/test/com/cloud/network/lb/AssignLoadBalancerTest.java new file mode 100644 index 0000000000..257a21fd67 --- /dev/null +++ b/server/test/com/cloud/network/lb/AssignLoadBalancerTest.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 com.cloud.network.lb; + +import com.cloud.domain.DomainVO; +import com.cloud.domain.dao.DomainDao; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.NetworkModelImpl; +import com.cloud.network.dao.LoadBalancerDao; +import com.cloud.network.dao.LoadBalancerVMMapDao; +import com.cloud.network.dao.LoadBalancerVMMapVO; +import com.cloud.network.dao.LoadBalancerVO; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.RulesManagerImpl; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountVO; +import com.cloud.user.UserVO; +import com.cloud.user.dao.AccountDao; +import com.cloud.uservm.UserVm; +import com.cloud.vm.Nic; +import com.cloud.vm.NicVO; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.dao.NicSecondaryIpDao; +import com.cloud.vm.dao.UserVmDao; +import org.apache.cloudstack.api.ResponseGenerator; +import org.apache.cloudstack.api.command.user.loadbalancer.AssignToLoadBalancerRuleCmd; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.context.CallContext; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.Spy; + +import javax.inject.Inject; + +import java.util.UUID; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; + +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.when; + +public class AssignLoadBalancerTest { + + @Inject + AccountManager _accountMgr; + + @Inject + AccountManager _acctMgr; + + @Inject + AccountDao _accountDao; + + @Inject + DomainDao _domainDao; + + @Mock + List _lbvmMapList; + + @Mock + List nic; + + @Mock + UserVmDao userDao; + + @Spy + RulesManagerImpl _rulesMgr = new RulesManagerImpl() { + @Override + public void checkRuleAndUserVm (FirewallRule rule, UserVm userVm, Account caller) { + + } + }; + + + @Spy + NicVO nicvo = new NicVO() { + + }; + + @Spy + NetworkModelImpl _networkModel = new NetworkModelImpl() { + @Override + public List getNics(long vmId) { + nic = new ArrayList(); + nicvo.setNetworkId(204L); + nic.add(nicvo); + return nic; + } + }; + + + LoadBalancingRulesManagerImpl _lbMgr = new LoadBalancingRulesManagerImpl(); + + private AssignToLoadBalancerRuleCmd assignToLbRuleCmd; + private ResponseGenerator responseGenerator; + private SuccessResponse successResponseGenerator; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private static long domainId = 5L; + private static long accountId = 5L; + private static String accountName = "admin"; + + @Before + public void setUp() { + assignToLbRuleCmd = new AssignToLoadBalancerRuleCmd() { + }; + + // ComponentContext.initComponentsLifeCycle(); + AccountVO account = new AccountVO(accountName, domainId, "networkDomain", Account.ACCOUNT_TYPE_NORMAL, "uuid"); + DomainVO domain = new DomainVO("rootDomain", 5L, 5L, "networkDomain"); + + UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString()); + + CallContext.register(user, account); + + } + + @Test(expected = InvalidParameterValueException.class) + public void testBothArgsEmpty() throws ResourceAllocationException, ResourceUnavailableException, InsufficientCapacityException { + + Map> emptyMap = new HashMap>(); + + LoadBalancerDao lbdao = Mockito.mock(LoadBalancerDao.class); + _lbMgr._lbDao = lbdao; + + when(lbdao.findById(anyLong())).thenReturn(Mockito.mock(LoadBalancerVO.class)); + + _lbMgr.assignToLoadBalancer(1L, null, emptyMap); + + } + + @Test(expected = InvalidParameterValueException.class) + public void testNicIsNotInNw() throws ResourceAllocationException, ResourceUnavailableException, InsufficientCapacityException { + + Map> vmIdIpMap = new HashMap>(); + List secIp = new ArrayList(); + secIp.add("10.1.1.175"); + vmIdIpMap.put(1L,secIp); + + List vmIds = new ArrayList(); + vmIds.add(2L); + + LoadBalancerDao lbDao = Mockito.mock(LoadBalancerDao.class); + LoadBalancerVMMapDao lb2VmMapDao = Mockito.mock(LoadBalancerVMMapDao.class); + UserVmDao userVmDao = Mockito.mock(UserVmDao.class); + + _lbMgr._lbDao = lbDao; + _lbMgr._lb2VmMapDao = lb2VmMapDao; + _lbMgr._vmDao = userVmDao; + _lbvmMapList = new ArrayList<>(); + _lbMgr._rulesMgr = _rulesMgr; + _lbMgr._networkModel = _networkModel; + + when(lbDao.findById(anyLong())).thenReturn(Mockito.mock(LoadBalancerVO.class)); + when(userVmDao.findById(anyLong())).thenReturn(Mockito.mock(UserVmVO.class)); + when(lb2VmMapDao.listByLoadBalancerId(anyLong(), anyBoolean())).thenReturn(_lbvmMapList); + + _lbMgr.assignToLoadBalancer(1L, null, vmIdIpMap); + } + + + @Test(expected = InvalidParameterValueException.class) + public void tesSecIpNotSetToVm() throws ResourceAllocationException, ResourceUnavailableException, InsufficientCapacityException { + + AssignToLoadBalancerRuleCmd assignLbRuleCmd = Mockito.mock(AssignToLoadBalancerRuleCmd.class); + + Map> vmIdIpMap = new HashMap>(); + List secIp = new ArrayList(); + secIp.add("10.1.1.175"); + vmIdIpMap.put(1L,secIp); + + List vmIds = new ArrayList(); + vmIds.add(2L); + + LoadBalancerVO lbVO = new LoadBalancerVO("1", "L1", "Lbrule", 1, 22, 22, "rb", 204, 0, 0, "tcp"); + + LoadBalancerDao lbDao = Mockito.mock(LoadBalancerDao.class); + LoadBalancerVMMapDao lb2VmMapDao = Mockito.mock(LoadBalancerVMMapDao.class); + UserVmDao userVmDao = Mockito.mock(UserVmDao.class); + NicSecondaryIpDao nicSecIpDao = Mockito.mock(NicSecondaryIpDao.class); + + _lbMgr._lbDao = lbDao; + _lbMgr._lb2VmMapDao = lb2VmMapDao; + _lbMgr._vmDao = userVmDao; + _lbMgr._nicSecondaryIpDao = nicSecIpDao; + _lbvmMapList = new ArrayList<>(); + _lbMgr._rulesMgr = _rulesMgr; + _lbMgr._networkModel = _networkModel; + + when(lbDao.findById(anyLong())).thenReturn(lbVO); + when(userVmDao.findById(anyLong())).thenReturn(Mockito.mock(UserVmVO.class)); + when(lb2VmMapDao.listByLoadBalancerId(anyLong(), anyBoolean())).thenReturn(_lbvmMapList); + when (nicSecIpDao.findByIp4AddressAndNicId(anyString(), anyLong())).thenReturn(null); + + _lbMgr.assignToLoadBalancer(1L, null, vmIdIpMap); + } + + + + @Test(expected = InvalidParameterValueException.class) + public void testVmIdAlreadyExist() throws ResourceAllocationException, ResourceUnavailableException, InsufficientCapacityException { + + AssignToLoadBalancerRuleCmd assignLbRuleCmd = Mockito.mock(AssignToLoadBalancerRuleCmd.class); + + Map> vmIdIpMap = new HashMap>(); + List secIp = new ArrayList(); + secIp.add("10.1.1.175"); + vmIdIpMap.put(1L,secIp); + + List vmIds = new ArrayList(); + vmIds.add(2L); + + LoadBalancerVO lbVO = new LoadBalancerVO("1", "L1", "Lbrule", 1, 22, 22, "rb", 204, 0, 0, "tcp"); + + LoadBalancerDao lbDao = Mockito.mock(LoadBalancerDao.class); + LoadBalancerVMMapDao lb2VmMapDao = Mockito.mock(LoadBalancerVMMapDao.class); + UserVmDao userVmDao = Mockito.mock(UserVmDao.class); + NicSecondaryIpDao nicSecIpDao = Mockito.mock(NicSecondaryIpDao.class); + LoadBalancerVMMapVO lbVmMapVO = new LoadBalancerVMMapVO(1L, 1L, "10.1.1.175", false); + + _lbMgr._lbDao = lbDao; + _lbMgr._lb2VmMapDao = lb2VmMapDao; + _lbMgr._vmDao = userVmDao; + _lbMgr._nicSecondaryIpDao = nicSecIpDao; + _lbvmMapList = new ArrayList<>(); + _lbvmMapList.add(lbVmMapVO); + _lbMgr._rulesMgr = _rulesMgr; + _lbMgr._networkModel = _networkModel; + + when(lbDao.findById(anyLong())).thenReturn(lbVO); + when(userVmDao.findById(anyLong())).thenReturn(Mockito.mock(UserVmVO.class)); + when(lb2VmMapDao.listByLoadBalancerId(anyLong(), anyBoolean())).thenReturn(_lbvmMapList); + when (nicSecIpDao.findByIp4AddressAndNicId(anyString(), anyLong())).thenReturn(null); + + _lbMgr.assignToLoadBalancer(1L, null, vmIdIpMap); + } + + @After + public void tearDown() { + CallContext.unregister(); + } + +} \ No newline at end of file diff --git a/server/test/com/cloud/resource/MockResourceManagerImpl.java b/server/test/com/cloud/resource/MockResourceManagerImpl.java index e6bf9a26b2..2646af079a 100644 --- a/server/test/com/cloud/resource/MockResourceManagerImpl.java +++ b/server/test/com/cloud/resource/MockResourceManagerImpl.java @@ -36,6 +36,7 @@ import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.agent.api.VgpuTypesInfo; import com.cloud.agent.api.to.GPUDeviceTO; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; @@ -558,31 +559,37 @@ public boolean releaseHostReservation(Long hostId) { } @Override - public boolean isGPUDeviceAvailable(long hostId, String vgpuType) { + public boolean isGPUDeviceAvailable(long hostId, String groupName, String vgpuType) { // TODO Auto-generated method stub return false; } @Override - public GPUDeviceTO getGPUDevice(long hostId, String vgpuType) { + public GPUDeviceTO getGPUDevice(long hostId, String groupName, String vgpuType) { // TODO Auto-generated method stub return null; } @Override - public List listAvailableGPUDevice(long hostId, String vgpuType) { + public List listAvailableGPUDevice(long hostId, String groupName, String vgpuType) { // TODO Auto-generated method stub return null; } @Override - public void updateGPUDetails(long hostId, HashMap> deviceDetails) { + public void updateGPUDetails(long hostId, HashMap> deviceDetails) { // TODO Auto-generated method stub } @Override - public HashMap> getGPUStatistics(HostVO host) { + public HashMap> getGPUStatistics(HostVO host) { // TODO Auto-generated method stub return null; } + + @Override + public boolean isHostGpuEnabled(long hostId) { + // TODO Auto-generated method stub + return false; + } } diff --git a/server/test/com/cloud/user/MockAccountManagerImpl.java b/server/test/com/cloud/user/MockAccountManagerImpl.java index f373cba922..e53974a664 100644 --- a/server/test/com/cloud/user/MockAccountManagerImpl.java +++ b/server/test/com/cloud/user/MockAccountManagerImpl.java @@ -120,7 +120,7 @@ public boolean deleteUser(DeleteUserCmd deleteUserCmd) { } @Override - public boolean isAdmin(short accountType) { + public boolean isAdmin(Long accountId) { // TODO Auto-generated method stub return false; } @@ -219,10 +219,6 @@ public String getName() { return null; } - @Override - public void checkAccess(Account account, AccessType accessType, boolean sameOwner, ControlledEntity... entities) throws PermissionDeniedException { - // TODO Auto-generated method stub - } @Override public void checkAccess(Account account, AccessType accessType, boolean sameOwner, PartOf... entities) throws PermissionDeniedException { @@ -344,16 +340,22 @@ public List listAclGroupsByAccount(Long accountId) { return null; } + @Override - public void checkAccess(Account account, AccessType accessType, boolean sameOwner, String apiName, - ControlledEntity... entities) throws PermissionDeniedException { + public Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly) { // TODO Auto-generated method stub + return null; } @Override - public Long finalyzeAccountId(String accountName, Long domainId, Long projectId, boolean enabledOnly) { + public void checkAccess(Account account, AccessType accessType, ControlledEntity... entities) throws PermissionDeniedException { // TODO Auto-generated method stub - return null; + } + + @Override + public void checkAccess(Account account, AccessType accessType, String apiName, ControlledEntity... entities) throws PermissionDeniedException { + // TODO Auto-generated method stub + } diff --git a/server/test/com/cloud/vm/UserVmManagerTest.java b/server/test/com/cloud/vm/UserVmManagerTest.java index 43010a3f64..927d5e33b5 100755 --- a/server/test/com/cloud/vm/UserVmManagerTest.java +++ b/server/test/com/cloud/vm/UserVmManagerTest.java @@ -50,6 +50,8 @@ import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService; import org.apache.cloudstack.framework.config.dao.ConfigurationDao; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import com.cloud.capacity.CapacityManager; import com.cloud.configuration.ConfigurationManager; @@ -141,6 +143,8 @@ public class UserVmManagerTest { EntityManager _entityMgr; @Mock ResourceLimitService _resourceLimitMgr; + @Mock + PrimaryDataStoreDao _storagePoolDao; @Before public void setup() { @@ -162,6 +166,7 @@ public void setup() { _userVmMgr._resourceLimitMgr = _resourceLimitMgr; _userVmMgr._scaleRetry = 2; _userVmMgr._entityMgr = _entityMgr; + _userVmMgr._storagePoolDao = _storagePoolDao; doReturn(3L).when(_account).getId(); doReturn(8L).when(_vmMock).getAccountId(); @@ -214,6 +219,12 @@ public void testRestoreVMF2() throws ResourceUnavailableException, InsufficientC Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString()); + StoragePoolVO storagePool = new StoragePoolVO(); + + storagePool.setManaged(false); + + when(_storagePoolDao.findById(anyLong())).thenReturn(storagePool); + CallContext.register(user, account); try { _userVmMgr.restoreVMInternal(_account, _vmMock, null); @@ -245,6 +256,12 @@ public void testRestoreVMF3() throws ResourceUnavailableException, InsufficientC Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString()); + StoragePoolVO storagePool = new StoragePoolVO(); + + storagePool.setManaged(false); + + when(_storagePoolDao.findById(anyLong())).thenReturn(storagePool); + CallContext.register(user, account); try { _userVmMgr.restoreVMInternal(_account, _vmMock, null); @@ -266,7 +283,7 @@ public void testRestoreVMF4() throws ResourceUnavailableException, InsufficientC doReturn(3L).when(_volumeMock).getTemplateId(); doReturn(ImageFormat.VHD).when(_templateMock).getFormat(); when(_templateDao.findById(anyLong())).thenReturn(_templateMock); - doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock); + doNothing().when(_accountMgr).checkAccess(_account, null, _templateMock); when(_storageMgr.allocateDuplicateVolume(_volumeMock, 14L)).thenReturn(_volumeMock); when(_templateMock.getGuestOSId()).thenReturn(5L); doNothing().when(_vmMock).setGuestOSId(anyLong()); @@ -282,6 +299,12 @@ public void testRestoreVMF4() throws ResourceUnavailableException, InsufficientC Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString()); + StoragePoolVO storagePool = new StoragePoolVO(); + + storagePool.setManaged(false); + + when(_storagePoolDao.findById(anyLong())).thenReturn(storagePool); + CallContext.register(user, account); try { _userVmMgr.restoreVMInternal(_account, _vmMock, 14L); @@ -304,7 +327,7 @@ public void testRestoreVMF5() throws ResourceUnavailableException, InsufficientC doReturn(3L).when(_vmMock).getIsoId(); doReturn(ImageFormat.ISO).when(_templateMock).getFormat(); when(_templateDao.findById(anyLong())).thenReturn(_templateMock); - doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock); + doNothing().when(_accountMgr).checkAccess(_account, null, _templateMock); when(_storageMgr.allocateDuplicateVolume(_volumeMock, null)).thenReturn(_volumeMock); doNothing().when(_vmMock).setIsoId(14L); when(_templateMock.getGuestOSId()).thenReturn(5L); @@ -321,6 +344,12 @@ public void testRestoreVMF5() throws ResourceUnavailableException, InsufficientC Account account = new AccountVO("testaccount", 1L, "networkdomain", (short)0, "uuid"); UserVO user = new UserVO(1, "testuser", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString()); + StoragePoolVO storagePool = new StoragePoolVO(); + + storagePool.setManaged(false); + + when(_storagePoolDao.findById(anyLong())).thenReturn(storagePool); + CallContext.register(user, account); try { _userVmMgr.restoreVMInternal(_account, _vmMock, 14L); @@ -384,7 +413,7 @@ public void testScaleVMF2() throws Exception { doReturn(VirtualMachine.State.Running).when(_vmInstance).getState(); - doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock); + doNothing().when(_accountMgr).checkAccess(_account, null, _templateMock); doNothing().when(_itMgr).checkIfCanUpgrade(_vmMock, _offeringVo); @@ -577,7 +606,7 @@ public void testMoveVmToUser2() throws Exception { when(_accountService.getActiveAccountByName(anyString(), anyLong())).thenReturn(newAccount); - doThrow(new PermissionDeniedException("Access check failed")).when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), + doThrow(new PermissionDeniedException("Access check failed")).when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(ControlledEntity.class)); CallContext.register(user, caller); diff --git a/server/test/com/cloud/vm/snapshot/VMSnapshotManagerTest.java b/server/test/com/cloud/vm/snapshot/VMSnapshotManagerTest.java index 9d5c2b42ea..03afdbd580 100644 --- a/server/test/com/cloud/vm/snapshot/VMSnapshotManagerTest.java +++ b/server/test/com/cloud/vm/snapshot/VMSnapshotManagerTest.java @@ -125,7 +125,7 @@ public void setup() { _vmSnapshotMgr._guestOSDao = _guestOSDao; _vmSnapshotMgr._hypervisorCapabilitiesDao = _hypervisorCapabilitiesDao; - doNothing().when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class)); + doNothing().when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(ControlledEntity.class)); _vmSnapshotMgr._vmSnapshotMax = _vmSnapshotMax; diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index ac303dddfc..387a710d9d 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -606,7 +606,7 @@ public boolean destroyNetwork(long networkId, ReservationContext context, boolea @Override public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner, Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String gatewayv6, - String cidrv6, Boolean displayNetworkEnabled, String isolatedPvlan) throws ConcurrentOperationException, InsufficientCapacityException, + String cidrv6, Boolean displayNetworkEnabled, String isolatedPvlan ) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { // TODO Auto-generated method stub return null; diff --git a/server/test/com/cloud/vpc/MockNetworkModelImpl.java b/server/test/com/cloud/vpc/MockNetworkModelImpl.java index 67ab8e875c..c93584dbe3 100644 --- a/server/test/com/cloud/vpc/MockNetworkModelImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkModelImpl.java @@ -26,6 +26,8 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; + import com.cloud.dc.Vlan; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.exception.InvalidParameterValueException; @@ -893,4 +895,10 @@ public boolean isNetworkReadyForGc(long networkId) { public boolean getNetworkEgressDefaultPolicy(Long networkId) { return false; //To change body of implemented methods use File | Settings | File Templates. } + + @Override + public void checkNetworkPermissions(Account owner, Network network, AccessType accessType) { + // TODO Auto-generated method stub + + } } diff --git a/server/test/com/cloud/vpc/VpcApiUnitTest.java b/server/test/com/cloud/vpc/VpcApiUnitTest.java index 5e283743b7..dee9afe3b5 100644 --- a/server/test/com/cloud/vpc/VpcApiUnitTest.java +++ b/server/test/com/cloud/vpc/VpcApiUnitTest.java @@ -85,7 +85,7 @@ public void getActiveVpc() { public void validateNtwkOffForVpc() { //validate network offering //1) correct network offering - VpcVO vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false); + VpcVO vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false); boolean result = false; try { _vpcService.validateNtwkOffForNtwkInVpc(2L, 1, "0.0.0.0", "111-", vo, "10.1.1.1", new AccountVO(), null); diff --git a/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java b/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java index e1a6ac2ae4..7492598e90 100644 --- a/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java +++ b/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java @@ -98,9 +98,9 @@ public void persistVpcServiceProviders(long vpcId, Map> ser public VpcVO findById(Long id) { VpcVO vo = null; if (id.longValue() == 1) { - vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false); + vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false); } else if (id.longValue() == 2) { - vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false); + vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false); vo.setState(State.Inactive); } diff --git a/server/test/resources/createNetworkOffering.xml b/server/test/resources/createNetworkOffering.xml index 6ae1978f40..887a8af724 100644 --- a/server/test/resources/createNetworkOffering.xml +++ b/server/test/resources/createNetworkOffering.xml @@ -48,4 +48,6 @@ + + diff --git a/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/AddIAMPermissionToIAMPolicyCmd.java b/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/AddIAMPermissionToIAMPolicyCmd.java index d37cc3cb7b..d69f3d0a0b 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/AddIAMPermissionToIAMPolicyCmd.java +++ b/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/AddIAMPermissionToIAMPolicyCmd.java @@ -72,6 +72,9 @@ public class AddIAMPermissionToIAMPolicyCmd extends BaseAsyncCmd { @Parameter(name = ApiConstants.IAM_SCOPE_ID, type = CommandType.STRING, required = false, description = "The UUID of the permission scope id") private String scopeId; + @Parameter(name = ApiConstants.READ_ONLY, type = CommandType.BOOLEAN, required = false, description = "Read Only access is added; Only applicable when action = List/Read api name") + private Boolean readOnly; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -100,6 +103,10 @@ public Long getScopeId() { return _iamApiSrv.getPermissionScopeId(scope, entityType, scopeId); } + public Boolean isReadOnly() { + return (readOnly != null) ? readOnly : false; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -123,7 +130,7 @@ public void execute() throws ResourceUnavailableException, CallContext.current().setEventDetails("IAM policy Id: " + getId()); // Only explicit ALLOW is supported for this release, no explicit deny IAMPolicy result = _iamApiSrv.addIAMPermissionToIAMPolicy(id, entityType, PermissionScope.valueOf(scope), - getScopeId(), action, Permission.Allow, false); + getScopeId(), action, Permission.Allow, false, isReadOnly()); if (result != null) { IAMPolicyResponse response = _iamApiSrv.createIAMPolicyResponse(result); response.setResponseName(getCommandName()); diff --git a/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMGroupCmd.java b/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMGroupCmd.java index d0b9bc6b1c..93940e810c 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMGroupCmd.java +++ b/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMGroupCmd.java @@ -97,7 +97,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { diff --git a/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMPolicyCmd.java b/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMPolicyCmd.java index be863de308..7ebab6735a 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMPolicyCmd.java +++ b/services/iam/plugin/src/org/apache/cloudstack/api/command/iam/CreateIAMPolicyCmd.java @@ -104,7 +104,7 @@ public String getCommandName() { @Override public long getEntityOwnerId() { Account account = CallContext.current().getCallingAccount(); - if ((account == null) || _accountService.isAdmin(account.getType())) { + if ((account == null) || _accountService.isAdmin(account.getId())) { if ((domainId != null) && (accountName != null)) { Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); if (userAccount != null) { diff --git a/services/iam/plugin/src/org/apache/cloudstack/api/response/iam/IAMPermissionResponse.java b/services/iam/plugin/src/org/apache/cloudstack/api/response/iam/IAMPermissionResponse.java index 5def248d7a..046e1f4d34 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/api/response/iam/IAMPermissionResponse.java +++ b/services/iam/plugin/src/org/apache/cloudstack/api/response/iam/IAMPermissionResponse.java @@ -18,7 +18,6 @@ import com.google.gson.annotations.SerializedName; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.PermissionScope; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; @@ -34,7 +33,7 @@ public class IAMPermissionResponse extends BaseResponse { @SerializedName(ApiConstants.ENTITY_TYPE) @Param(description = "the entity type of this permission") - private IAMEntityType entityType; + private String entityType; @SerializedName(ApiConstants.IAM_SCOPE) @Param(description = "scope of this permission") @@ -48,11 +47,11 @@ public class IAMPermissionResponse extends BaseResponse { @Param(description = "allow or deny of this permission") private IAMPolicyPermission.Permission permission; - public IAMEntityType getEntityType() { + public String getEntityType() { return entityType; } - public void setEntityType(IAMEntityType entityType) { + public void setEntityType(String entityType) { this.entityType = entityType; } diff --git a/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiService.java b/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiService.java index bb8f03b77f..6735d4804d 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiService.java +++ b/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiService.java @@ -60,7 +60,7 @@ public interface IAMApiService extends PluggableService { void removeIAMPolicyFromAccounts(Long policyId, List accountIds); IAMPolicy addIAMPermissionToIAMPolicy(long iamPolicyId, String entityType, PermissionScope scope, Long scopeId, - String action, Permission perm, Boolean recursive); + String action, Permission perm, Boolean recursive, Boolean readOnly); IAMPolicy removeIAMPermissionFromIAMPolicy(long iamPolicyId, String entityType, PermissionScope scope, Long scopeId, String action); diff --git a/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiServiceImpl.java b/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiServiceImpl.java index 69f669c7e1..8b454e0da7 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiServiceImpl.java +++ b/services/iam/plugin/src/org/apache/cloudstack/iam/IAMApiServiceImpl.java @@ -27,11 +27,18 @@ import javax.naming.ConfigurationException; import org.apache.log4j.Logger; +import org.bouncycastle.util.IPAddress; + +import com.amazonaws.auth.policy.Condition; +import com.amazonaws.services.ec2.model.SecurityGroup; +import com.amazonaws.services.ec2.model.Snapshot; +import com.amazonaws.services.ec2.model.Volume; +import com.amazonaws.services.ec2.model.Vpc; +import com.amazonaws.services.elasticache.model.Event; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.PermissionScope; import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import org.apache.cloudstack.affinity.AffinityGroupVO; +import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.InternalIdentity; @@ -54,7 +61,7 @@ import org.apache.cloudstack.api.response.iam.IAMPermissionResponse; import org.apache.cloudstack.api.response.iam.IAMPolicyResponse; import org.apache.cloudstack.context.CallContext; -import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO; +import org.apache.cloudstack.framework.jobs.AsyncJob; import org.apache.cloudstack.framework.messagebus.MessageBus; import org.apache.cloudstack.framework.messagebus.MessageSubscriber; import org.apache.cloudstack.iam.api.IAMGroup; @@ -62,9 +69,6 @@ import org.apache.cloudstack.iam.api.IAMPolicyPermission; import org.apache.cloudstack.iam.api.IAMPolicyPermission.Permission; import org.apache.cloudstack.iam.api.IAMService; -import org.apache.cloudstack.iam.server.IAMGroupVO; -import org.apache.cloudstack.iam.server.IAMPolicyVO; -import org.apache.cloudstack.region.gslb.GlobalLoadBalancerRuleVO; import com.cloud.api.ApiServerService; import com.cloud.domain.Domain; @@ -72,50 +76,45 @@ import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; -import com.cloud.event.EventVO; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.network.UserIpv6AddressVO; -import com.cloud.network.VpnUserVO; -import com.cloud.network.as.AutoScalePolicyVO; -import com.cloud.network.as.AutoScaleVmGroupVO; -import com.cloud.network.as.AutoScaleVmProfileVO; -import com.cloud.network.as.ConditionVO; -import com.cloud.network.dao.IPAddressVO; -import com.cloud.network.dao.MonitoringServiceVO; -import com.cloud.network.dao.NetworkVO; -import com.cloud.network.dao.RemoteAccessVpnVO; -import com.cloud.network.dao.Site2SiteCustomerGatewayVO; -import com.cloud.network.dao.Site2SiteVpnConnectionVO; -import com.cloud.network.dao.Site2SiteVpnGatewayVO; -import com.cloud.network.dao.SslCertVO; -import com.cloud.network.rules.FirewallRuleVO; -import com.cloud.network.rules.PortForwardingRuleVO; -import com.cloud.network.security.SecurityGroupVO; -import com.cloud.network.vpc.StaticRouteVO; -import com.cloud.network.vpc.VpcGatewayVO; -import com.cloud.network.vpc.VpcVO; -import com.cloud.projects.ProjectInvitationVO; -import com.cloud.storage.SnapshotVO; -import com.cloud.storage.VMTemplateVO; -import com.cloud.storage.VolumeVO; -import com.cloud.tags.ResourceTagVO; +import com.cloud.network.IpAddress; +import com.cloud.network.MonitoringService; +import com.cloud.network.Network; +import com.cloud.network.RemoteAccessVpn; +import com.cloud.network.Site2SiteCustomerGateway; +import com.cloud.network.Site2SiteVpnConnection; +import com.cloud.network.Site2SiteVpnGateway; +import com.cloud.network.UserIpv6Address; +import com.cloud.network.VpnUser; +import com.cloud.network.as.AutoScalePolicy; +import com.cloud.network.as.AutoScaleVmGroup; +import com.cloud.network.as.AutoScaleVmProfile; +import com.cloud.network.lb.SslCert; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.vpc.StaticRoute; +import com.cloud.network.vpc.VpcGateway; +import com.cloud.projects.ProjectInvitation; +import com.cloud.region.ha.GlobalLoadBalancerRule; +import com.cloud.server.ResourceTag; import com.cloud.template.TemplateManager; +import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; import com.cloud.user.DomainManager; -import com.cloud.user.SSHKeyPairVO; +import com.cloud.user.SSHKeyPair; import com.cloud.user.dao.AccountDao; import com.cloud.utils.Pair; import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.DB; import com.cloud.utils.db.EntityManager; -import com.cloud.vm.InstanceGroupVO; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.dao.NicIpAliasVO; -import com.cloud.vm.dao.NicSecondaryIpVO; -import com.cloud.vm.snapshot.VMSnapshotVO; +import com.cloud.vm.InstanceGroup; +import com.cloud.vm.NicIpAlias; +import com.cloud.vm.NicSecondaryIp; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.snapshot.VMSnapshot; @Local(value = {IAMApiService.class}) public class IAMApiServiceImpl extends ManagerBase implements IAMApiService, Manager { @@ -144,48 +143,46 @@ public class IAMApiServiceImpl extends ManagerBase implements IAMApiService, Man @Inject EntityManager _entityMgr; - private static final Map> s_typeMap = new HashMap>(); + private static final Map> s_typeMap = new HashMap>(); static { - s_typeMap.put(IAMEntityType.VirtualMachine, VMInstanceVO.class); - s_typeMap.put(IAMEntityType.Volume, VolumeVO.class); - s_typeMap.put(IAMEntityType.ResourceTag, ResourceTagVO.class); - s_typeMap.put(IAMEntityType.Account, AccountVO.class); - s_typeMap.put(IAMEntityType.AffinityGroup, AffinityGroupVO.class); - s_typeMap.put(IAMEntityType.AutoScalePolicy, AutoScalePolicyVO.class); - s_typeMap.put(IAMEntityType.AutoScaleVmProfile, AutoScaleVmProfileVO.class); - s_typeMap.put(IAMEntityType.AutoScaleVmGroup, AutoScaleVmGroupVO.class); - s_typeMap.put(IAMEntityType.Condition, ConditionVO.class); - s_typeMap.put(IAMEntityType.Vpc, VpcVO.class); - s_typeMap.put(IAMEntityType.VpcGateway, VpcGatewayVO.class); - s_typeMap.put(IAMEntityType.PrivateGateway, RemoteAccessVpnVO.class); - s_typeMap.put(IAMEntityType.VpnUser, VpnUserVO.class); - s_typeMap.put(IAMEntityType.VMSnapshot, VMSnapshotVO.class); - s_typeMap.put(IAMEntityType.VirtualMachineTemplate, VMTemplateVO.class); - s_typeMap.put(IAMEntityType.UserIpv6Address, UserIpv6AddressVO.class); - s_typeMap.put(IAMEntityType.StaticRoute, StaticRouteVO.class); - s_typeMap.put(IAMEntityType.SSHKeyPair, SSHKeyPairVO.class); - s_typeMap.put(IAMEntityType.Snapshot, SnapshotVO.class); - s_typeMap.put(IAMEntityType.Site2SiteVpnGateway, Site2SiteVpnGatewayVO.class); - s_typeMap.put(IAMEntityType.Site2SiteCustomerGateway, Site2SiteCustomerGatewayVO.class); - s_typeMap.put(IAMEntityType.Site2SiteVpnConnection, Site2SiteVpnConnectionVO.class); - s_typeMap.put(IAMEntityType.SecurityGroup, SecurityGroupVO.class); - s_typeMap.put(IAMEntityType.RemoteAccessVpn, RemoteAccessVpnVO.class); - s_typeMap.put(IAMEntityType.PublicIpAddress, IPAddressVO.class); - s_typeMap.put(IAMEntityType.ProjectInvitation, ProjectInvitationVO.class); - s_typeMap.put(IAMEntityType.NicSecondaryIp, NicSecondaryIpVO.class); - s_typeMap.put(IAMEntityType.NicIpAlias, NicIpAliasVO.class); - s_typeMap.put(IAMEntityType.Network, NetworkVO.class); - s_typeMap.put(IAMEntityType.IpAddress, IPAddressVO.class); - s_typeMap.put(IAMEntityType.InstanceGroup, InstanceGroupVO.class); - s_typeMap.put(IAMEntityType.GlobalLoadBalancerRule, GlobalLoadBalancerRuleVO.class); - s_typeMap.put(IAMEntityType.FirewallRule, FirewallRuleVO.class); - s_typeMap.put(IAMEntityType.PortForwardingRule, PortForwardingRuleVO.class); - s_typeMap.put(IAMEntityType.Event, EventVO.class); - s_typeMap.put(IAMEntityType.AsyncJob, AsyncJobVO.class); - s_typeMap.put(IAMEntityType.IAMGroup, IAMGroupVO.class); - s_typeMap.put(IAMEntityType.IAMPolicy, IAMPolicyVO.class); - s_typeMap.put(IAMEntityType.MonitorService, MonitoringServiceVO.class); - s_typeMap.put(IAMEntityType.SSLCert, SslCertVO.class); + s_typeMap.put(VirtualMachine.class.getSimpleName(), VirtualMachine.class); + s_typeMap.put(Volume.class.getSimpleName(), Volume.class); + s_typeMap.put(ResourceTag.class.getSimpleName(), ResourceTag.class); + s_typeMap.put(Account.class.getSimpleName(), Account.class); + s_typeMap.put(AffinityGroup.class.getSimpleName(), AffinityGroup.class); + s_typeMap.put(AutoScalePolicy.class.getSimpleName(), AutoScalePolicy.class); + s_typeMap.put(AutoScaleVmProfile.class.getSimpleName(), AutoScaleVmProfile.class); + s_typeMap.put(AutoScaleVmGroup.class.getSimpleName(), AutoScaleVmGroup.class); + s_typeMap.put(Condition.class.getSimpleName(), Condition.class); + s_typeMap.put(Vpc.class.getSimpleName(), Vpc.class); + s_typeMap.put(VpcGateway.class.getSimpleName(), VpcGateway.class); + s_typeMap.put(VpnUser.class.getSimpleName(), VpnUser.class); + s_typeMap.put(VMSnapshot.class.getSimpleName(), VMSnapshot.class); + s_typeMap.put(VirtualMachineTemplate.class.getSimpleName(), VirtualMachineTemplate.class); + s_typeMap.put(UserIpv6Address.class.getSimpleName(), UserIpv6Address.class); + s_typeMap.put(StaticRoute.class.getSimpleName(), StaticRoute.class); + s_typeMap.put(SSHKeyPair.class.getSimpleName(), SSHKeyPair.class); + s_typeMap.put(Snapshot.class.getSimpleName(), Snapshot.class); + s_typeMap.put(Site2SiteVpnGateway.class.getSimpleName(), Site2SiteVpnGateway.class); + s_typeMap.put(Site2SiteCustomerGateway.class.getSimpleName(), Site2SiteCustomerGateway.class); + s_typeMap.put(Site2SiteVpnConnection.class.getSimpleName(), Site2SiteVpnConnection.class); + s_typeMap.put(SecurityGroup.class.getSimpleName(), SecurityGroup.class); + s_typeMap.put(RemoteAccessVpn.class.getSimpleName(), RemoteAccessVpn.class); + s_typeMap.put(ProjectInvitation.class.getSimpleName(), ProjectInvitation.class); + s_typeMap.put(NicSecondaryIp.class.getSimpleName(), NicSecondaryIp.class); + s_typeMap.put(NicIpAlias.class.getSimpleName(), NicIpAlias.class); + s_typeMap.put(Network.class.getSimpleName(), Network.class); + s_typeMap.put(IpAddress.class.getSimpleName(), IPAddress.class); + s_typeMap.put(InstanceGroup.class.getSimpleName(), InstanceGroup.class); + s_typeMap.put(GlobalLoadBalancerRule.class.getSimpleName(), GlobalLoadBalancerRule.class); + s_typeMap.put(FirewallRule.class.getSimpleName(), FirewallRule.class); + s_typeMap.put(PortForwardingRule.class.getSimpleName(), PortForwardingRule.class); + s_typeMap.put(Event.class.getSimpleName(), Event.class); + s_typeMap.put(AsyncJob.class.getSimpleName(), AsyncJob.class); + s_typeMap.put(IAMGroup.class.getSimpleName(), IAMGroup.class); + s_typeMap.put(IAMPolicy.class.getSimpleName(), IAMPolicy.class); + s_typeMap.put(MonitoringService.class.getSimpleName(), MonitoringService.class); + s_typeMap.put(SslCert.class.getSimpleName(), SslCert.class); } @Override @@ -261,9 +258,9 @@ public void onPublishMessage(String senderAddress, String subject, Object obj) { Long templateId = (Long)obj; if (templateId != null) { s_logger.debug("MessageBus message: new public template registered: " + templateId + ", grant permission to domain admin and normal user policies"); - _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), IAMEntityType.VirtualMachineTemplate.toString(), + _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), VirtualMachineTemplate.class.getSimpleName(), PermissionScope.RESOURCE.toString(), templateId, "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false); - _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), IAMEntityType.VirtualMachineTemplate.toString(), + _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), VirtualMachineTemplate.class.getSimpleName(), PermissionScope.RESOURCE.toString(), templateId, "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false); } } @@ -283,9 +280,9 @@ public void onPublishMessage(String senderAddress, String subject, Object obj) { _messageBus.subscribe(EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, new MessageSubscriber() { @Override public void onPublishMessage(String senderAddress, String subject, Object obj) { - Pair entity = (Pair)obj; + Pair, Long> entity = (Pair, Long>)obj; if (entity != null) { - String entityType = entity.first().toString(); + String entityType = entity.first().getSimpleName(); Long entityId = entity.second(); s_logger.debug("MessageBus message: delete an entity: (" + entityType + "," + entityId + "), remove its related permission"); _iamSrv.removeIAMPermissionForEntity(entityType, entityId); @@ -299,13 +296,13 @@ public void onPublishMessage(String senderAddress, String subject, Object obj) { public void onPublishMessage(String senderAddress, String subject, Object obj) { Map permit = (Map)obj; if (permit != null) { - String entityType = (String)permit.get(ApiConstants.ENTITY_TYPE); + Class entityType = (Class)permit.get(ApiConstants.ENTITY_TYPE); Long entityId = (Long)permit.get(ApiConstants.ENTITY_ID); AccessType accessType = (AccessType)permit.get(ApiConstants.ACCESS_TYPE); String action = (String)permit.get(ApiConstants.IAM_ACTION); List acctIds = (List)permit.get(ApiConstants.ACCOUNTS); s_logger.debug("MessageBus message: grant accounts permission to an entity: (" + entityType + "," + entityId + ")"); - grantEntityPermissioinToAccounts(entityType, entityId, accessType, action, acctIds); + grantEntityPermissioinToAccounts(entityType.getSimpleName(), entityId, accessType, action, acctIds); } } }); @@ -315,13 +312,13 @@ public void onPublishMessage(String senderAddress, String subject, Object obj) { public void onPublishMessage(String senderAddress, String subject, Object obj) { Map permit = (Map)obj; if (permit != null) { - String entityType = (String)permit.get(ApiConstants.ENTITY_TYPE); + Class entityType = (Class)permit.get(ApiConstants.ENTITY_TYPE); Long entityId = (Long)permit.get(ApiConstants.ENTITY_ID); AccessType accessType = (AccessType)permit.get(ApiConstants.ACCESS_TYPE); String action = (String)permit.get(ApiConstants.IAM_ACTION); List acctIds = (List)permit.get(ApiConstants.ACCOUNTS); s_logger.debug("MessageBus message: revoke from accounts permission to an entity: (" + entityType + "," + entityId + ")"); - revokeEntityPermissioinFromAccounts(entityType, entityId, accessType, action, acctIds); + revokeEntityPermissioinFromAccounts(entityType.getSimpleName(), entityId, accessType, action, acctIds); } } }); @@ -359,16 +356,16 @@ private void populateIAMGroupAdminAccountMap() { private void addDomainWideResourceAccess(Map params) { - IAMEntityType entityType = (IAMEntityType)params.get(ApiConstants.ENTITY_TYPE); + Class entityType = (Class)params.get(ApiConstants.ENTITY_TYPE); Long entityId = (Long) params.get(ApiConstants.ENTITY_ID); Long domainId = (Long) params.get(ApiConstants.DOMAIN_ID); Boolean isRecursive = (Boolean) params.get(ApiConstants.SUBDOMAIN_ACCESS); - if (entityType == IAMEntityType.Network) { - createPolicyAndAddToDomainGroup("DomainWideNetwork-" + entityId, "domain wide network", entityType.toString(), + if (entityType == Network.class) { + createPolicyAndAddToDomainGroup("DomainWideNetwork-" + entityId, "domain wide network", entityType.getSimpleName(), entityId, "listNetworks", AccessType.UseEntry, domainId, isRecursive); - } else if (entityType == IAMEntityType.AffinityGroup) { - createPolicyAndAddToDomainGroup("DomainWideNetwork-" + entityId, "domain wide affinityGroup", entityType.toString(), + } else if (entityType == AffinityGroup.class) { + createPolicyAndAddToDomainGroup("DomainWideNetwork-" + entityId, "domain wide affinityGroup", entityType.getSimpleName(), entityId, "listAffinityGroups", AccessType.UseEntry, domainId, isRecursive); } @@ -509,11 +506,17 @@ public void removeIAMPolicyFromAccounts(final Long policyId, final List ac @Override @ActionEvent(eventType = EventTypes.EVENT_IAM_POLICY_GRANT, eventDescription = "Granting acl permission to IAM Policy") public IAMPolicy addIAMPermissionToIAMPolicy(long iamPolicyId, String entityType, PermissionScope scope, - Long scopeId, String action, Permission perm, Boolean recursive) { + Long scopeId, String action, Permission perm, Boolean recursive, Boolean readOnly) { Class cmdClass = _apiServer.getCmdClass(action); AccessType accessType = null; if (BaseListCmd.class.isAssignableFrom(cmdClass)) { - accessType = AccessType.UseEntry; + if (readOnly) { + accessType = AccessType.ListEntry; + } else { + accessType = AccessType.UseEntry; + } + } else { + accessType = AccessType.OperateEntry; } String accessTypeStr = (accessType != null) ? accessType.toString() : null; return _iamSrv.addIAMPermissionToIAMPolicy(iamPolicyId, entityType, scope.toString(), scopeId, action, @@ -575,7 +578,7 @@ public IAMPolicyResponse createIAMPolicyResponse(IAMPolicy policy) { IAMPermissionResponse perm = new IAMPermissionResponse(); perm.setAction(permission.getAction()); if (permission.getEntityType() != null) { - perm.setEntityType(IAMEntityType.valueOf(permission.getEntityType())); + perm.setEntityType(permission.getEntityType()); } if (permission.getScope() != null) { perm.setScope(PermissionScope.valueOf(permission.getScope())); @@ -717,7 +720,8 @@ public void grantEntityPermissioinToAccounts(String entityType, Long entityId, A String description = "Policy to grant permission to " + entityType + entityId; policy = createIAMPolicy(caller, aclPolicyName, description, null); // add permission to this policy - addIAMPermissionToIAMPolicy(policy.getId(), entityType, PermissionScope.RESOURCE, entityId, action, Permission.Allow, false); + addIAMPermissionToIAMPolicy(policy.getId(), entityType, PermissionScope.RESOURCE, entityId, action, + Permission.Allow, false, false); } // attach this policy to list of accounts if not attached already Long policyId = policy.getId(); @@ -758,12 +762,12 @@ private boolean isPolicyAttachedToAccount(Long policyId, Long accountId) { private void resetTemplatePermission(Long templateId){ // reset template will change template to private, so we need to remove its permission for domain admin and normal user group - _iamSrv.removeIAMPermissionFromIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), IAMEntityType.VirtualMachineTemplate.toString(), + _iamSrv.removeIAMPermissionFromIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), VirtualMachineTemplate.class.getSimpleName(), PermissionScope.RESOURCE.toString(), templateId, "listTemplates"); - _iamSrv.removeIAMPermissionFromIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), IAMEntityType.VirtualMachineTemplate.toString(), + _iamSrv.removeIAMPermissionFromIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), VirtualMachineTemplate.class.getSimpleName(), PermissionScope.RESOURCE.toString(), templateId, "listTemplates"); // check if there is a policy with only UseEntry permission for this template added - IAMPolicy policy = _iamSrv.getResourceGrantPolicy(IAMEntityType.VirtualMachineTemplate.toString(), templateId, AccessType.UseEntry.toString(), "listTemplates"); + IAMPolicy policy = _iamSrv.getResourceGrantPolicy(VirtualMachineTemplate.class.getSimpleName(), templateId, AccessType.UseEntry.toString(), "listTemplates"); if ( policy == null ){ s_logger.info("No policy found for this template grant: " + templateId + ", no detach to be done"); return; @@ -788,7 +792,7 @@ public Long getPermissionScopeId(String scope, String entityType, String scopeId entity = _accountDao.findByUuid(scopeId); break; case RESOURCE: - Class clazz = s_typeMap.get(IAMEntityType.valueOf(entityType)); + Class clazz = s_typeMap.get(entityType); entity = (InternalIdentity)_entityMgr.findByUuid(clazz, scopeId); } diff --git a/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedAPIAccessChecker.java b/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedAPIAccessChecker.java index fb75db310f..fe71912003 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedAPIAccessChecker.java +++ b/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedAPIAccessChecker.java @@ -29,12 +29,10 @@ import org.apache.log4j.Logger; import org.apache.cloudstack.acl.APIChecker; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.PermissionScope; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.APICommand; -import org.apache.cloudstack.api.BaseAsyncCreateCmd; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.iam.api.IAMPolicy; @@ -46,6 +44,7 @@ import com.cloud.exception.PermissionDeniedException; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; import com.cloud.user.AccountService; import com.cloud.user.User; @@ -133,9 +132,9 @@ public boolean start() { // add permissions for public templates List pTmplts = _templateDao.listByPublic(); for (VMTemplateVO tmpl : pTmplts){ - _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), IAMEntityType.VirtualMachineTemplate.toString(), + _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_DOMAIN_ADMIN + 1), VirtualMachineTemplate.class.getSimpleName(), PermissionScope.RESOURCE.toString(), tmpl.getId(), "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false); - _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), IAMEntityType.VirtualMachineTemplate.toString(), + _iamSrv.addIAMPermissionToIAMPolicy(new Long(Account.ACCOUNT_TYPE_NORMAL + 1), VirtualMachineTemplate.class.getSimpleName(), PermissionScope.RESOURCE.toString(), tmpl.getId(), "listTemplates", AccessType.UseEntry.toString(), Permission.Allow, false); } @@ -216,26 +215,8 @@ public void setServices(List services) { } private void addDefaultAclPolicyPermission(String apiName, Class cmdClass, RoleType role) { - AccessType accessType = null; - IAMEntityType[] entityTypes = null; - if (cmdClass != null) { - BaseCmd cmdObj; - try { - cmdObj = (BaseCmd) cmdClass.newInstance(); - if (cmdObj instanceof BaseListCmd) { - accessType = AccessType.UseEntry; - } else if (!(cmdObj instanceof BaseAsyncCreateCmd)) { - accessType = AccessType.OperateEntry; - } - } catch (Exception e) { - throw new CloudRuntimeException(String.format( - "%s is claimed as an API command, but it cannot be instantiated", cmdClass.getName())); - } - - APICommand at = cmdClass.getAnnotation(APICommand.class); - entityTypes = at.entityType(); - } + Class[] entityTypes = null; PermissionScope permissionScope = PermissionScope.ACCOUNT; Long policyId = getDefaultPolicyId(role); @@ -257,14 +238,47 @@ private void addDefaultAclPolicyPermission(String apiName, Class cmdClass, Ro break; } + boolean addAccountScopedUseEntry = false; + + if (cmdClass != null) { + BaseCmd cmdObj; + try { + cmdObj = (BaseCmd) cmdClass.newInstance(); + if (cmdObj instanceof BaseListCmd) { + if (permissionScope == PermissionScope.ACCOUNT) { + accessType = AccessType.UseEntry; + } else { + accessType = AccessType.ListEntry; + addAccountScopedUseEntry = true; + } + } else { + accessType = AccessType.OperateEntry; + } + } catch (Exception e) { + throw new CloudRuntimeException(String.format( + "%s is claimed as an API command, but it cannot be instantiated", cmdClass.getName())); + } + + APICommand at = cmdClass.getAnnotation(APICommand.class); + entityTypes = at.entityType(); + } if (entityTypes == null || entityTypes.length == 0) { _iamSrv.addIAMPermissionToIAMPolicy(policyId, null, permissionScope.toString(), new Long(IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), apiName, (accessType == null) ? null : accessType.toString(), Permission.Allow, false); + if (addAccountScopedUseEntry) { + _iamSrv.addIAMPermissionToIAMPolicy(policyId, null, PermissionScope.ACCOUNT.toString(), new Long( + IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), apiName, AccessType.UseEntry.toString(), Permission.Allow, false); + } } else { - for (IAMEntityType entityType : entityTypes) { - _iamSrv.addIAMPermissionToIAMPolicy(policyId, entityType.toString(), permissionScope.toString(), new Long(IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), + for (Class entityType : entityTypes) { + _iamSrv.addIAMPermissionToIAMPolicy(policyId, entityType.getSimpleName(), permissionScope.toString(), new Long( + IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), apiName, (accessType == null) ? null : accessType.toString(), Permission.Allow, false); + if (addAccountScopedUseEntry) { + _iamSrv.addIAMPermissionToIAMPolicy(policyId, entityType.getSimpleName(), PermissionScope.ACCOUNT.toString(), new Long( + IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER), apiName, AccessType.UseEntry.toString(), Permission.Allow, false); + } } } diff --git a/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityAccessChecker.java b/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityAccessChecker.java index 3fe854a2a0..cc29ab541b 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityAccessChecker.java +++ b/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityAccessChecker.java @@ -81,9 +81,15 @@ public boolean checkAccess(Account caller, ControlledEntity entity, AccessType a throw new InvalidParameterValueException("Entity and action cannot be both NULL in checkAccess!"); } + // if a Project entity, skip + Account entityAccount = _accountService.getAccount(entity.getAccountId()); + if (entityAccount != null && entityAccount.getType() == Account.ACCOUNT_TYPE_PROJECT) { + return false; + } + String entityType = null; if (entity.getEntityType() != null) { - entityType = entity.getEntityType().toString(); + entityType = entity.getEntityType().getSimpleName(); } if (accessType == null) { @@ -101,14 +107,22 @@ public boolean checkAccess(Account caller, ControlledEntity entity, AccessType a permissions = _iamSrv.listPolicyPermissionByActionAndEntity(policy.getId(), action, entityType); if (permissions.isEmpty()) { if (accessType != null) { - permissions.addAll(_iamSrv.listPolicyPermissionByAccessAndEntity(policy.getId(), - accessType.toString(), entityType)); + for (AccessType type : AccessType.values()) { + if (type.ordinal() >= accessType.ordinal()) { + permissions.addAll(_iamSrv.listPolicyPermissionByAccessAndEntity(policy.getId(), + type.toString(), entityType)); + } + } } } } else { if (accessType != null) { - permissions.addAll(_iamSrv.listPolicyPermissionByAccessAndEntity(policy.getId(), - accessType.toString(), entityType)); + for (AccessType type : AccessType.values()) { + if (type.ordinal() >= accessType.ordinal()) { + permissions.addAll(_iamSrv.listPolicyPermissionByAccessAndEntity(policy.getId(), + type.toString(), entityType)); + } + } } } for (IAMPolicyPermission permission : permissions) { @@ -128,6 +142,7 @@ public boolean checkAccess(Account caller, ControlledEntity entity, AccessType a if (!policies.isEmpty()) { // Since we reach this point, none of the // roles granted access + if (s_logger.isDebugEnabled()) { s_logger.debug("Account " + caller + " does not have permission to access resource " + entity + " for access type: " + accessType); @@ -138,6 +153,50 @@ public boolean checkAccess(Account caller, ControlledEntity entity, AccessType a return false; } + @Override + public boolean checkAccess(Account caller, AccessType accessType, String action, ControlledEntity... entities) + throws PermissionDeniedException { + + // operate access on multiple entities? + if (accessType != null && accessType == AccessType.OperateEntry) { + // In this case caller MUST own n-1 entities. + + for (ControlledEntity entity : entities) { + checkAccess(caller, entity, accessType, action); + + boolean otherEntitiesAccess = true; + + for (ControlledEntity otherEntity : entities) { + if (otherEntity != entity) { + if (otherEntity.getAccountId() == caller.getAccountId() + || (checkAccess(caller, otherEntity, accessType, action) && otherEntity.getAccountId() == entity + .getAccountId())) { + continue; + } else { + otherEntitiesAccess = false; + break; + } + } + } + + if (otherEntitiesAccess) { + return true; + } + } + + throw new PermissionDeniedException(caller + + " does not have permission to perform this operation on these resources"); + + } else { + for (ControlledEntity entity : entities) { + if (!checkAccess(caller, entity, accessType, action)) { + return false; + } + } + return true; + } + } + private boolean checkPermissionScope(Account caller, String scope, Long scopeId, ControlledEntity entity) { if(scopeId != null && !scopeId.equals(new Long(IAMPolicyPermission.PERMISSION_SCOPE_ID_CURRENT_CALLER))){ @@ -167,6 +226,8 @@ private boolean checkPermissionScope(Account caller, String scope, Long scopeId, if (_domainDao.isChildDomain(caller.getDomainId(), entity.getDomainId())) { return true; } + } else if (scope.equals(PermissionScope.ALL.name())) { + return true; } } return false; @@ -174,15 +235,8 @@ private boolean checkPermissionScope(Account caller, String scope, Long scopeId, private List getEffectivePolicies(Account caller, ControlledEntity entity) { - // Get the static Policies of the Caller List policies = _iamSrv.listIAMPolicies(caller.getId()); - // add any dynamic policies w.r.t the entity - if (caller.getId() == entity.getAccountId()) { - // The caller owns the entity - policies.add(_iamSrv.getResourceOwnerPolicy()); - } - List groups = _iamSrv.listIAMGroups(caller.getId()); for (IAMGroup group : groups) { // for each group find the grand parent groups. diff --git a/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityQuerySelector.java b/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityQuerySelector.java index 23c57a1688..40c8549c30 100644 --- a/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityQuerySelector.java +++ b/services/iam/plugin/src/org/apache/cloudstack/iam/RoleBasedEntityQuerySelector.java @@ -25,11 +25,14 @@ import org.apache.cloudstack.acl.PermissionScope; import org.apache.cloudstack.acl.QuerySelector; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.iam.api.IAMGroup; import org.apache.cloudstack.iam.api.IAMPolicy; import org.apache.cloudstack.iam.api.IAMPolicyPermission; import org.apache.cloudstack.iam.api.IAMService; +import com.cloud.domain.DomainVO; +import com.cloud.domain.dao.DomainDao; import com.cloud.user.Account; import com.cloud.utils.component.AdapterBase; @@ -39,24 +42,46 @@ public class RoleBasedEntityQuerySelector extends AdapterBase implements QuerySe @Inject IAMService _iamService; + @Inject + DomainDao _domainDao; @Override - public List getAuthorizedDomains(Account caller, String action) { + public List getAuthorizedDomains(Account caller, String action, AccessType accessType) { long accountId = caller.getAccountId(); + if (accessType == null) { + accessType = AccessType.UseEntry; // default always show resources authorized to use + } // Get the static Policies of the Caller List policies = _iamService.listIAMPolicies(accountId); // for each policy, find granted permission with Domain scope List domainIds = new ArrayList(); for (IAMPolicy policy : policies) { - List pp = _iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.DOMAIN.toString()); + List pp = new ArrayList(); + for (AccessType type : AccessType.values()) { + if (type.ordinal() >= accessType.ordinal()) { + pp.addAll(_iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.DOMAIN.toString(), type)); + } + } if (pp != null) { for (IAMPolicyPermission p : pp) { if (p.getScopeId() != null) { + Long domainId = null; if (p.getScopeId().longValue() == -1) { - domainIds.add(caller.getDomainId()); + domainId = caller.getDomainId(); + //domainIds.add(caller.getDomainId()); } else { - domainIds.add(p.getScopeId()); + domainId = p.getScopeId(); + //domainIds.add(p.getScopeId()); } + domainIds.add(domainId); + // add all the domain children from this domain. Like RoleBasedEntityAccessChecker, we made an assumption, if DOMAIN scope is granted, it means that + // the whole domain tree is granted access. + DomainVO domain = _domainDao.findById(domainId); + List childDomains = _domainDao.getDomainChildrenIds(domain.getPath()); + if (childDomains != null && childDomains.size() > 0) { + domainIds.addAll(childDomains); + } + } } } @@ -65,14 +90,22 @@ public List getAuthorizedDomains(Account caller, String action) { } @Override - public List getAuthorizedAccounts(Account caller, String action) { + public List getAuthorizedAccounts(Account caller, String action, AccessType accessType) { long accountId = caller.getAccountId(); + if (accessType == null) { + accessType = AccessType.UseEntry; // default always show resources authorized to use + } // Get the static Policies of the Caller List policies = _iamService.listIAMPolicies(accountId); // for each policy, find granted permission with Account scope List accountIds = new ArrayList(); for (IAMPolicy policy : policies) { - List pp = _iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.ACCOUNT.toString()); + List pp = new ArrayList(); + for (AccessType type : AccessType.values()) { + if (type.ordinal() >= accessType.ordinal()) { + pp.addAll(_iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.ACCOUNT.toString(), type)); + } + } if (pp != null) { for (IAMPolicyPermission p : pp) { if (p.getScopeId() != null) { @@ -89,8 +122,11 @@ public List getAuthorizedAccounts(Account caller, String action) { } @Override - public List getAuthorizedResources(Account caller, String action) { + public List getAuthorizedResources(Account caller, String action, AccessType accessType) { long accountId = caller.getAccountId(); + if (accessType == null) { + accessType = AccessType.UseEntry; // default always show resources authorized to use + } // Get the static Policies of the Caller List policies = _iamService.listIAMPolicies(accountId); @@ -107,7 +143,12 @@ public List getAuthorizedResources(Account caller, String action) { // for each policy, find granted permission with Resource scope List entityIds = new ArrayList(); for (IAMPolicy policy : policies) { - List pp = _iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.RESOURCE.toString()); + List pp = new ArrayList(); + for (AccessType type : AccessType.values()) { + if (type.ordinal() >= accessType.ordinal()) { + pp.addAll(_iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.RESOURCE.toString(), type)); + } + } if (pp != null) { for (IAMPolicyPermission p : pp) { if (p.getScopeId() != null) { @@ -120,15 +161,23 @@ public List getAuthorizedResources(Account caller, String action) { } @Override - public boolean isGrantedAll(Account caller, String action) { + public boolean isGrantedAll(Account caller, String action, AccessType accessType) { long accountId = caller.getAccountId(); + if (accessType == null) { + accessType = AccessType.UseEntry; // default always show resources authorized to use + } // Get the static Policies of the Caller List policies = _iamService.listIAMPolicies(accountId); // for each policy, find granted permission with ALL scope for (IAMPolicy policy : policies) { - List pp = _iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.ALL.toString()); - if (pp != null && pp.size() > 0) { - return true; + List pp = new ArrayList(); + for (AccessType type : AccessType.values()) { + if (type.ordinal() >= accessType.ordinal()) { + pp.addAll(_iamService.listPolicyPermissionsByScope(policy.getId(), action, PermissionScope.ALL.toString(), type)); + } + if (pp != null && pp.size() > 0) { + return true; + } } } return false; diff --git a/services/iam/plugin/test/org/apache/cloudstack/iam/test/IAMApiServiceTest.java b/services/iam/plugin/test/org/apache/cloudstack/iam/test/IAMApiServiceTest.java index b825ab224f..84e1e56255 100644 --- a/services/iam/plugin/test/org/apache/cloudstack/iam/test/IAMApiServiceTest.java +++ b/services/iam/plugin/test/org/apache/cloudstack/iam/test/IAMApiServiceTest.java @@ -50,7 +50,6 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; -import org.apache.cloudstack.acl.IAMEntityType; import org.apache.cloudstack.acl.PermissionScope; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.user.vm.ListVMsCmd; @@ -84,6 +83,7 @@ import com.cloud.utils.Pair; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.db.EntityManager; +import com.cloud.vm.VirtualMachine; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(loader = AnnotationConfigContextLoader.class) @@ -292,15 +292,15 @@ public void addRemovePermissionToPolicyTest() { Class clz = ListVMsCmd.class; when(_apiServer.getCmdClass("listVirtualMachines")).thenReturn(clz); when( - _iamSrv.addIAMPermissionToIAMPolicy(policyId, IAMEntityType.VirtualMachine.toString(), + _iamSrv.addIAMPermissionToIAMPolicy(policyId, VirtualMachine.class.getSimpleName(), PermissionScope.RESOURCE.toString(), resId, "listVirtualMachines", AccessType.UseEntry.toString(), Permission.Allow, false)).thenReturn(policy); - _aclSrv.addIAMPermissionToIAMPolicy(policyId, IAMEntityType.VirtualMachine.toString(), - PermissionScope.RESOURCE, resId, "listVirtualMachines", Permission.Allow, false); + _aclSrv.addIAMPermissionToIAMPolicy(policyId, VirtualMachine.class.getSimpleName(), + PermissionScope.RESOURCE, resId, "listVirtualMachines", Permission.Allow, false, false); Pair, Integer> policyList = new Pair, Integer>(policies, 1); List policyPerms = new ArrayList(); IAMPolicyPermission perm = new IAMPolicyPermissionVO(policyId, "listVirtualMachines", - IAMEntityType.VirtualMachine.toString(), AccessType.UseEntry.toString(), + VirtualMachine.class.getSimpleName(), AccessType.UseEntry.toString(), PermissionScope.RESOURCE.toString(), resId, Permission.Allow, false); policyPerms.add(perm); @@ -316,7 +316,7 @@ public void addRemovePermissionToPolicyTest() { //remove permission from policy policyPerms.remove(perm); - _aclSrv.removeIAMPermissionFromIAMPolicy(policyId, IAMEntityType.VirtualMachine.toString(), + _aclSrv.removeIAMPermissionFromIAMPolicy(policyId, VirtualMachine.class.getSimpleName(), PermissionScope.RESOURCE, resId, "listVirtualMachines"); policyResp = _aclSrv.listIAMPolicies(null, "policy1", callerDomainId, 0L, 20L); assertTrue("No. of response items should be one", policyResp.getCount() == 1); diff --git a/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java index 74a0885150..c396fa922f 100644 --- a/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java +++ b/services/iam/server/src/org/apache/cloudstack/iam/api/IAMService.java @@ -18,6 +18,7 @@ import java.util.List; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.iam.api.IAMPolicyPermission.Permission; import com.cloud.utils.Pair; @@ -72,7 +73,7 @@ IAMPolicy removeIAMPermissionFromIAMPolicy(long iamPolicyId, String entityType, List listPolicyPermissions(long policyId); - List listPolicyPermissionsByScope(long policyId, String action, String scope); + List listPolicyPermissionsByScope(long policyId, String action, String scope, AccessType accessType); List listPolicyPermissionByActionAndEntity(long policyId, String action, String entityType); diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java index 097d84f958..d6a61a1045 100644 --- a/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java +++ b/services/iam/server/src/org/apache/cloudstack/iam/server/IAMServiceImpl.java @@ -25,6 +25,7 @@ import org.apache.log4j.Logger; import org.apache.cloudstack.acl.PermissionScope; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.iam.api.IAMGroup; import org.apache.cloudstack.iam.api.IAMPolicy; import org.apache.cloudstack.iam.api.IAMPolicyPermission; @@ -147,6 +148,9 @@ public List listIAMGroups(long accountId) { List groupIds = _aclGroupAccountMapDao.customSearch(groupSc, null); + if (groupIds == null || groupIds.isEmpty()) { + return new ArrayList(); + } SearchBuilder sb = _aclGroupDao.createSearchBuilder(); sb.and("ids", sb.entity().getId(), Op.IN); SearchCriteria sc = sb.create(); @@ -739,8 +743,8 @@ public List getGrantedEntities(long accountId, String action, String scope // for each policy, find granted permission within the given scope List entityIds = new ArrayList(); for (IAMPolicy policy : policies) { - List pp = _policyPermissionDao.listGrantedByActionAndScope(policy.getId(), action, - scope); + List pp = _policyPermissionDao.listByPolicyActionAndScope(policy.getId(), action, + scope, null); if (pp != null) { for (IAMPolicyPermissionVO p : pp) { if (p.getScopeId() != null) { @@ -762,9 +766,9 @@ public List listPolicyPermissions(long policyId) { @SuppressWarnings("unchecked") @Override - public List listPolicyPermissionsByScope(long policyId, String action, String scope) { + public List listPolicyPermissionsByScope(long policyId, String action, String scope, AccessType accessType) { @SuppressWarnings("rawtypes") - List pp = _policyPermissionDao.listGrantedByActionAndScope(policyId, action, scope); + List pp = _policyPermissionDao.listByPolicyActionAndScope(policyId, action, scope, accessType.toString()); return pp; } diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDao.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDao.java index cdcb02b1de..6e6099c664 100644 --- a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDao.java +++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDao.java @@ -29,7 +29,7 @@ public interface IAMPolicyPermissionDao extends GenericDao listGrantedByActionAndScope(long policyId, String action, String scope); + List listByPolicyActionAndScope(long policyId, String action, String scope, String accessType); List listByPolicyActionAndEntity(long policyId, String action, String entityType); diff --git a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDaoImpl.java b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDaoImpl.java index 3f976cfefc..9cc1af07e8 100644 --- a/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDaoImpl.java +++ b/services/iam/server/src/org/apache/cloudstack/iam/server/dao/IAMPolicyPermissionDaoImpl.java @@ -33,7 +33,6 @@ public class IAMPolicyPermissionDaoImpl extends GenericDaoBase policyIdSearch; private SearchBuilder fullSearch; - private SearchBuilder actionScopeSearch; private SearchBuilder entitySearch; @Override @@ -54,13 +53,6 @@ public boolean configure(String name, Map params) throws Configu fullSearch.and("accessType", fullSearch.entity().getAccessType(), SearchCriteria.Op.EQ); fullSearch.done(); - actionScopeSearch = createSearchBuilder(); - actionScopeSearch.and("policyId", actionScopeSearch.entity().getAclPolicyId(), SearchCriteria.Op.EQ); - actionScopeSearch.and("scope", actionScopeSearch.entity().getScope(), SearchCriteria.Op.EQ); - actionScopeSearch.and("action", actionScopeSearch.entity().getAction(), SearchCriteria.Op.EQ); - actionScopeSearch.and("permission", actionScopeSearch.entity().getPermission(), SearchCriteria.Op.EQ); - actionScopeSearch.done(); - entitySearch = createSearchBuilder(); entitySearch.and("entityType", entitySearch.entity().getEntityType(), SearchCriteria.Op.EQ); entitySearch.and("scopeId", entitySearch.entity().getScopeId(), SearchCriteria.Op.EQ); @@ -90,12 +82,16 @@ public IAMPolicyPermissionVO findByPolicyAndEntity(long policyId, String entityT } @Override - public List listGrantedByActionAndScope(long policyId, String action, String scope) { - SearchCriteria sc = actionScopeSearch.create(); + public List listByPolicyActionAndScope(long policyId, String action, String scope, String accessType) { + SearchCriteria sc = fullSearch.create(); sc.setParameters("policyId", policyId); sc.setParameters("action", action); sc.setParameters("scope", scope); sc.setParameters("permission", Permission.Allow); + if ( accessType != null ){ + // accessType can be optional, used mainly in list apis with ListEntry and UseEntry distinction + sc.setParameters("accessType", accessType); + } return listBy(sc); } @@ -120,7 +116,7 @@ public List listByPolicyAccessAndEntity(long policyId, St @Override public List listByEntity(String entityType, Long entityId) { - SearchCriteria sc = fullSearch.create(); + SearchCriteria sc = entitySearch.create(); sc.setParameters("entityType", entityType); sc.setParameters("scopeId", entityId); return listBy(sc); diff --git a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java index 9782c2ec7c..f35b3f544e 100755 --- a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java +++ b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java @@ -1278,7 +1278,7 @@ protected Answer deleteSnapshot(final DeleteCommand cmd) { if (!snapshotDir.exists()) { details = "snapshot directory " + snapshotDir.getName() + " doesn't exist"; s_logger.debug(details); - return new Answer(cmd, false, details); + return new Answer(cmd, true, details); } // delete snapshot in the directory if exists String lPath = absoluteSnapshotPath + "/*" + snapshotName + "*"; diff --git a/setup/bindir/cloud-setup-baremetal.in b/setup/bindir/cloud-setup-baremetal.in new file mode 100644 index 0000000000..367e38943e --- /dev/null +++ b/setup/bindir/cloud-setup-baremetal.in @@ -0,0 +1,232 @@ +#!/usr/bin/python +# 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 sys, os +from subprocess import PIPE, Popen +import logging +import traceback +from os.path import exists, join +from signal import alarm, signal, SIGALRM, SIGKILL + +class CloudRuntimeException(Exception): + def __init__(self, errMsg): + self.errMsg = errMsg + def __str__(self): + return self.errMsg +def formatExceptionInfo(maxTBlevel=5): + cla, exc, trbk = sys.exc_info() + excTb = traceback.format_tb(trbk, maxTBlevel) + msg = str(exc) + "\n" + for tb in excTb: + msg += tb + return msg + +class bash: + def __init__(self, args, timeout=600): + self.args = args + logging.debug("execute:%s"%args) + self.timeout = timeout + self.process = None + self.success = False + self.run() + + def run(self): + class Alarm(Exception): + pass + def alarm_handler(signum, frame): + raise Alarm + + try: + self.process = Popen(self.args, shell=True, stdout=PIPE, stderr=PIPE) + if self.timeout != -1: + signal(SIGALRM, alarm_handler) + alarm(self.timeout) + + try: + self.stdout, self.stderr = self.process.communicate() + if self.timeout != -1: + alarm(0) + except Alarm: + os.kill(self.process.pid, SIGKILL) + raise CloudRuntimeException("Timeout during command execution") + + self.success = self.process.returncode == 0 + except: + raise CloudRuntimeException(formatExceptionInfo()) + +# if not self.success: +# raise CloudRuntimeException(self.getStderr()) + + def isSuccess(self): + return self.success + + def getStdout(self): + return self.stdout.strip("\n") + + def getLines(self): + return self.stdout.split("\n") + + def getStderr(self): + return self.stderr.strip("\n") + + +def initLoging(logFile=None): + try: + if logFile is None: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(filename=logFile, level=logging.DEBUG) + except: + logging.basicConfig(level=logging.DEBUG) + +def writeProgressBar(msg, result=None): + if msg is not None: + output = "%-80s"%msg + elif result is True: + output = "[ \033[92m%-2s\033[0m ]\n"%"OK" + elif result is False: + output = "[ \033[91m%-6s\033[0m ]\n"%"FAILED" + sys.stdout.write(output) + sys.stdout.flush() + +def printError(msg): + sys.stderr.write(msg) + sys.stderr.write("\n") + sys.stderr.flush() + +def printMsg(msg): + sys.stdout.write(msg+"\n") + sys.stdout.flush() + +def checkRpm(pkgName): + chkPkg = bash("rpm -q %s"%pkgName) + writeProgressBar("Checking %s"%pkgName, None) + if not chkPkg.isSuccess(): + writeProgressBar(None, False) + printError("%s is not found, please make sure it is installed. You may try 'yum install %s'\n"%(pkgName, pkgName)) + return False + else: + writeProgressBar(None, True) + return True + +def checkEnv(): + writeProgressBar("Checking is root") + ret = bash("whoami") + if ret.getStdout() != "root": + writeProgressBar(None, False) + printError("This script must run as root") + return False + else: + writeProgressBar(None, True) + + pkgList = ['tftp-server', 'syslinux', 'xinetd', 'chkconfig', 'dhcp'] + for pkg in pkgList: + if not checkRpm(pkg): + return False + return True + +def exitIfFail(ret): + if not ret: sys.exit(1) + +def bashWithResult(cmd): + writeProgressBar("Executing '%s'"%cmd) + ret = bash(cmd) + if not ret.isSuccess(): + writeProgressBar(None, False) + writeProgressBar(ret.getStderr() + '\n') + return False + else: + writeProgressBar(None, True) + return True + +def configurePxeStuff(): + stuff = ['tftp', 'xinetd', 'dhcpd'] + cmds = ['chkconfig --level 345 %s on' % i for i in stuff] + cmds.append('/etc/init.d/xinetd restart') + + for cmd in cmds: + if not bashWithResult(cmd): return False + + chkIptable = bash('chkconfig --list iptables') + if 'on' in chkIptable.getStdout(): + printMsg("Detected iptables is running, need to open tftp port 69") + if not bashWithResult('iptables -I INPUT 1 -p udp --dport 69 -j ACCEPT'): return False + if not bashWithResult('/etc/init.d/iptables save'): return False + + return True + +def getTftpRootDir(tftpRootDirList): + tftpRoot = bash("cat /etc/xinetd.d/tftp | grep server_args") + if not tftpRoot.isSuccess(): + printError("Cannot get tftp root directory from /etc/xinetd.d/tftp, here may be something wrong with your tftp-server, try reinstall it\n") + return False + tftpRootDir = tftpRoot.getStdout() + index = tftpRootDir.find("/") + if index == -1: + printError("Wrong server_arg in /etc/xinetd.d/tftp (%s)"%tftpRootDir) + return False + tftpRootDir = tftpRootDir[index:] + tftpRootDirList.append(tftpRootDir) + return True + +def preparePING(tftpRootDir): + pingFiles = ['boot.msg', 'initrd.gz', 'kernel', 'pxelinux.0'] + pingDir = "/usr/share/PING" + + for f in pingFiles: + path = join(pingDir, f) + if not exists(path): + printError("Cannot find %s, please make sure PING-3.01 is installed"%path) + return False + if not bashWithResult("cp -f %s %s"%(path, tftpRootDir)): return False + + if not bashWithResult("mkdir -p %s/pxelinux.cfg"%tftpRootDir): return False + + return True + +def prepareSyslinux(tftpRootDir): + pkg = bash('rpm -ql syslinux | grep "/pxelinux.0$"') + if not pkg.isSuccess(): + printError('cannot find pxelinux.0 on system. is syslinux installed?') + return False + + pkg = pkg.getStdout() + cp = "cp -f %s %s" % (pkg, tftpRootDir) + if not bashWithResult(cp): + return False + + return True + + + +if __name__ == "__main__": + initLoging("/tmp/cloud-setup-baremetal.log") + tftpRootDirList = [] + + exitIfFail(checkEnv()) + exitIfFail(configurePxeStuff()) + exitIfFail(getTftpRootDir(tftpRootDirList)) + + tftpRootDir = tftpRootDirList[0].strip() + #exitIfFail(preparePING(tftpRootDir)) + exitIfFail(prepareSyslinux(tftpRootDir)) + printMsg("") + printMsg("Setup BareMetal PXE server successfully") + printMsg("TFTP root directory is: %s\n"%tftpRootDir) + sys.exit(0) + diff --git a/setup/bindir/cloud-sysvmadm.in b/setup/bindir/cloud-sysvmadm.in index e2a626ef92..4c67c31085 100755 --- a/setup/bindir/cloud-sysvmadm.in +++ b/setup/bindir/cloud-sysvmadm.in @@ -7,9 +7,9 @@ # 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 @@ -75,7 +75,7 @@ do esac done - + stop_start_system() { @@ -86,46 +86,46 @@ length_console=(${#console[@]}) echo -e "\nStopping and starting $length_secondary secondary storage vm(s)$inzone..." -echo -e "Stopping and starting $length_secondary secondary storage vm(s)$inzone..." >>$LOGFILE +echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Stopping and starting $length_secondary secondary storage vm(s)$inzone..." >>$LOGFILE for d in "${secondary[@]}"; do - echo "INFO: Stopping secondary storage vm with id $d" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Stopping secondary storage vm with id $d" >>$LOGFILE jobresult=$(send_request stopSystemVm $d) if [ "$jobresult" != "1" ]; then echo -e "ERROR: Failed to stop secondary storage vm with id $d \n" - echo "ERROR: Failed to stop secondary storage vm with id $d" >>$LOGFILE - else - echo "INFO: Starting secondary storage vm with id $d" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to stop secondary storage vm with id $d" >>$LOGFILE + else + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Starting secondary storage vm with id $d" >>$LOGFILE jobresult=$(send_request startSystemVm $d SSVM) if [ "$jobresult" != "1" ]; then - echo "ERROR: Failed to start secondary storage vm with id $d" >>$LOGFILE - echo "ERROR: Failed to start secondary storage vm with id $d" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to start secondary storage vm with id $d" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to start secondary storage vm with id $d" >>$LOGFILE fi fi done if [ "$length_secondary" == "0" ];then echo -e "No running secondary storage vms found \n" -else +else echo -e "Done stopping and starting secondary storage vm(s)$inzone" - echo -e "Done stopping and starting secondary storage vm(s)$inzone." >>$LOGFILE + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Done stopping and starting secondary storage vm(s)$inzone." >>$LOGFILE fi echo -e "\nStopping and starting $length_console console proxy vm(s)$inzone..." -echo -e "Stopping and starting $length_console console proxy vm(s)$inzone..." >>$LOGFILE +echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Stopping and starting $length_console console proxy vm(s)$inzone..." >>$LOGFILE for d in "${console[@]}"; do - echo "INFO: Stopping console proxy with id $d" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Stopping console proxy with id $d" >>$LOGFILE jobresult=$(send_request stopSystemVm $d) if [ "$jobresult" != "1" ]; then echo -e "ERROR: Failed to stop console proxy vm with id $d \n" - echo "ERROR: Failed to stop console proxy vm with id $d" >>$LOGFILE - else - echo "INFO: Starting console proxy vm with id $d" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to stop console proxy vm with id $d" >>$LOGFILE + else + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Starting console proxy vm with id $d" >>$LOGFILE jobresult=$(send_request startSystemVm $d consoleProxy) if [ "$jobresult" != "1" ]; then echo -e "ERROR: Failed to start console proxy vm with id $d \n" - echo "ERROR: Failed to start console proxy vm with id $d" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to start console proxy vm with id $d" >>$LOGFILE fi fi done @@ -134,33 +134,33 @@ if [ "$length_console" == "0" ];then echo -e "No running console proxy vms found \n" else echo "Done stopping and starting console proxy vm(s) $inzone." - echo "Done stopping and starting console proxy vm(s) $inzone." >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] Done stopping and starting console proxy vm(s) $inzone." >>$LOGFILE fi } stop_start_router() { router=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select id from vm_instance where state=\"Running\" and type=\"DomainRouter\"$zone"`) length_router=(${#router[@]}) - + echo -e "\nStopping and starting $length_router running routing vm(s)$inzone... " - echo -e "Stopping and starting $length_router running routing vm(s)$inzone... " >>$LOGFILE - + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Stopping and starting $length_router running routing vm(s)$inzone... " >>$LOGFILE + #Spawn reboot router in parallel - run commands in chunks - number of threads is configurable pids=() for d in "${router[@]}"; do - + reboot_router $d & pids=( "${pids[@]}" $! ) - + length_pids=(${#pids[@]}) unfinishedPids=(${#pids[@]}) - + if [ $maxthreads -gt $length_router ]; then maxthreads=$length_router fi - + if [ $length_pids -ge $maxthreads ]; then while [ $unfinishedPids -gt 0 ]; do sleep 10 @@ -170,33 +170,33 @@ stop_start_router() { count=`expr $count + 1` fi done - + if [ $count -eq $unfinishedPids ]; then unfinishedPids=0 fi - + done - + #remove all elements from pids if [ $unfinishedPids -eq 0 ]; then pids=() length_pids=(${#pids[@]}) fi - + fi - + done - + if [ "$length_router" == "0" ];then - echo -e "No running router vms found \n" >>$LOGFILE - else + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] No running router vms found \n" >>$LOGFILE + else while [ $unfinishedPids -gt 0 ]; do sleep 10 done - + echo -e "Done restarting router(s)$inzone. \n" - echo -e "Done restarting router(s)$inzone. \n" >>$LOGFILE - + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Done restarting router(s)$inzone. \n" >>$LOGFILE + fi } @@ -212,56 +212,60 @@ send_request(){ return fi jobresult=$(query_async_job_result $jobid) + if [ "$jobresult" != "1" ]; then + echo -e "ERROR: Failed to $1 id=$2; jobId is $jobid \n" + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to $1 id=$2; jobId is $jobid" >>$LOGFILE + fi echo $jobresult } reboot_router(){ - echo "INFO: Restarting router with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Restarting router with id $1" >>$LOGFILE jobid=`curl -sS "http://$ms:8096/?command=rebootRouter&id=$1&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F: {'print $3'}` if [ "$jobid" == "" ]; then - echo "ERROR: Failed to restart domainRouter with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart domainRouter with id $1; unable to submit the job" >>$LOGFILE echo 2 return fi - + jobresult=$(query_async_job_result $jobid) - + if [ "$jobresult" != "1" ]; then echo -e "ERROR: Failed to restart domainRouter with id $1 \n" - echo "ERROR: Failed to restart domainRouter with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart domainRouter with id $1; jobId $jobid" >>$LOGFILE exit 0 else - echo "INFO: Successfully restarted domainRouter with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Successfully restarted domainRouter with id $1; jobId $jobid" >>$LOGFILE exit 0 fi - + } restart_networks(){ - networks=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select n.id + networks=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select n.id from networks n, network_offerings no where n.network_offering_id = no.id and no.system_only = 0 and n.removed is null$zone"`) length_networks=(${#networks[@]}) - + echo -e "\nRestarting $length_networks networks$inzone... " - echo -e "Restarting $length_networks networks$inzone... " >>$LOGFILE - + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Restarting $length_networks networks$inzone... " >>$LOGFILE + #Spawn restart network in parallel - run commands in chunks - number of threads is configurable pids=() for d in "${networks[@]}"; do - + restart_network $d & pids=( "${pids[@]}" $! ) - + length_pids=(${#pids[@]}) unfinishedPids=(${#pids[@]}) - + if [ $maxthreads -gt $length_networks ]; then maxthreads=$length_networks fi - + if [ $length_pids -ge $maxthreads ]; then while [ $unfinishedPids -gt 0 ]; do sleep 10 @@ -271,74 +275,74 @@ restart_networks(){ count=`expr $count + 1` fi done - + if [ $count -eq $unfinishedPids ]; then unfinishedPids=0 fi - + done - + #remove all elements from pids if [ $unfinishedPids -eq 0 ]; then pids=() length_pids=(${#pids[@]}) fi - + fi - + done - + if [ "$length_networks" == "0" ];then - echo -e "No networks found \n" >>$LOGFILE - else + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] No networks found \n" >>$LOGFILE + else while [ $unfinishedPids -gt 0 ]; do sleep 10 done - + echo -e "Done restarting networks$inzone. \n" - echo -e "Done restarting networks$inzone. \n" >>$LOGFILE - + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Done restarting networks$inzone. \n" >>$LOGFILE + fi } restart_network(){ jobid=`curl -sS "http://$ms:8096/?command=restartNetwork&id=$1&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F: {'print $3'}` if [ "$jobid" == "" ]; then - echo "ERROR: Failed to restart network with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart network with id $1; unable to submit the job" >>$LOGFILE echo 2 return fi - + jobresult=$(query_async_job_result $jobid) - + if [ "$jobresult" != "1" ]; then - echo "ERROR: Failed to restart network with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart network with id $1; jobId $jobid" >>$LOGFILE else - echo "INFO: Successfully restarted network with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Successfully restarted network with id $1; jobId $jobid" >>$LOGFILE fi - + } restart_vpc(){ echo -e "INFO: Restarting vpc with id $1" - echo "INFO: Restarting vpc with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Restarting vpc with id $1" >>$LOGFILE jobid=`curl -sS "http://$ms:8096/?command=restartVPC&id=$1&response=json" | sed 's/\"//g' | sed 's/ //g' | sed 's/{//g' | sed 's/}//g' | awk -F: {'print $3'}` if [ "$jobid" == "" ]; then - echo "ERROR: Failed to restart vpc with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart vpc with id $1; unable to submit the job" >>$LOGFILE echo 2 return fi - + jobresult=$(query_async_job_result $jobid) - + if [ "$jobresult" != "1" ]; then echo -e "ERROR: Failed to restart vpc with id $1 \n" - echo "ERROR: Failed to restart vpc with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] ERROR: Failed to restart vpc with id $1; jobId $jobid" >>$LOGFILE else echo -e "INFO: Successfully restarted vpc with id $1 \n" - echo "INFO: Successfully restarted vpc with id $1" >>$LOGFILE + echo "[$(date "+%Y.%m.%d-%H.%M.%S")] INFO: Successfully restarted vpc with id $1; jobId $jobid" >>$LOGFILE fi } @@ -346,26 +350,26 @@ restart_vpc(){ restart_vpcs(){ vpcs=(`mysql -h $db --user=$user --password=$password --skip-column-names -U cloud -e "select id from vpc WHERE removed is null$zone"`) length_vpcs=(${#vpcs[@]}) - + echo -e "\nRestarting $length_vpcs vpcs... " - echo -e "Restarting $length_vpcs vpcs... " >>$LOGFILE - + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Restarting $length_vpcs vpcs... " >>$LOGFILE + #Spawn restart vpcs in parallel - run commands in chunks - number of threads is configurable pids=() for d in "${vpcs[@]}"; do - + restart_vpc $d & pids=( "${pids[@]}" $! ) - + length_pids=(${#pids[@]}) unfinishedPids=(${#pids[@]}) - + if [ $maxthreads -gt $length_vpcs ]; then maxthreads=$length_vpcs fi - + if [ $length_pids -ge $maxthreads ]; then while [ $unfinishedPids -gt 0 ]; do sleep 10 @@ -375,34 +379,34 @@ restart_vpcs(){ count=`expr $count + 1` fi done - + if [ $count -eq $unfinishedPids ]; then unfinishedPids=0 fi - + done - + #remove all elements from pids if [ $unfinishedPids -eq 0 ]; then pids=() length_pids=(${#pids[@]}) fi - + fi - + done - + if [ "$length_vpcs" == "0" ];then - echo -e "No vpcs found \n" >>$LOGFILE - else + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] No vpcs found \n" >>$LOGFILE + else while [ $unfinishedPids -gt 0 ]; do sleep 10 done - + echo -e "Done restarting vpcs$inzone. \n" - echo -e "Done restarting vpcs$inzone. \n" >>$LOGFILE - + echo -e "[$(date "+%Y.%m.%d-%H.%M.%S")] Done restarting vpcs$inzone. \n" >>$LOGFILE + fi } diff --git a/setup/db/db/schema-430to440.sql b/setup/db/db/schema-430to440.sql index 5c5511ac5f..fff0ea3200 100644 --- a/setup/db/db/schema-430to440.sql +++ b/setup/db/db/schema-430to440.sql @@ -658,13 +658,27 @@ ALTER TABLE `cloud`.`s2s_vpn_gateway` ADD COLUMN `display` tinyint(1) NOT NULL D INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (225, UUID(), 9, 'FreeBSD 10 (32-bit)'); INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (226, UUID(), 9, 'FreeBSD 10 (64-bit)'); +INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (227, UUID(), 1, 'CentOS 6.5 (32-bit)'); +INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (228, UUID(), 1, 'CentOS 6.5 (64-bit)'); +INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (229, UUID(), 6, 'Windows 8.1 (64-bit)'); +INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (230, UUID(), 6, 'Windows 8.1 (32-bit)'); + +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("XenServer", 'Windows 8.1 (64-bit)', 229); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Windows 8.1 (64-bit)', 229); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("XenServer", 'Windows 8.1 (32-bit)', 230); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Windows 8.1 (32-bit)', 230); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("XenServer", 'CentOS 6.5 (32-bit)', 227); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'CentOS 6.5 (32-bit)', 227); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'CentOS 6.5 (64-bit)', 228); +INSERT IGNORE INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("XenServer", 'CentOS 6.5 (64-bit)', 228); + CREATE TABLE `cloud`.`op_router_monitoring_services` ( `vm_id` bigint unsigned UNIQUE NOT NULL COMMENT 'Primary Key', `router_name` varchar(255) NOT NULL COMMENT 'Name of the Virtual Router', `last_alert_timestamp` varchar(255) NOT NULL COMMENT 'Timestamp of the last alert received from Virtual Router', PRIMARY KEY (`vm_id`), CONSTRAINT `fk_virtual_router__id` FOREIGN KEY `fk_virtual_router__id` (`vm_id`) REFERENCES `vm_instance`(`id`) ON DELETE CASCADE -) ENGINE = InnoDB DEFAULT CHARSET=utf8 +) ENGINE = InnoDB DEFAULT CHARSET=utf8; ALTER TABLE `cloud`.`event` ADD COLUMN `display` tinyint(1) NOT NULL DEFAULT '1' COMMENT 'True if the detail can be displayed to the end user'; @@ -724,7 +738,13 @@ CREATE TABLE `cloud`.`vgpu_types` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `gpu_group_id` bigint(20) unsigned NOT NULL, `vgpu_type` varchar(40) NOT NULL COMMENT 'vgpu type supported by this gpu group', - `remaining_vm_capacity` bigint(20) unsigned DEFAULT NULL COMMENT 'remaining vgpu can be created with this vgpu_type on the given gpu group', + `video_ram` bigint(20) unsigned DEFAULT NULL COMMENT 'video RAM for this vgpu type', + `max_heads` bigint(20) unsigned DEFAULT NULL COMMENT 'maximum displays per user', + `max_resolution_x` bigint(20) unsigned DEFAULT NULL COMMENT 'maximum X resolution per display', + `max_resolution_y` bigint(20) unsigned DEFAULT NULL COMMENT 'maximum Y resolution per display', + `max_vgpu_per_pgpu` bigint(20) unsigned DEFAULT NULL COMMENT 'max number of vgpus per physical gpu (pgpu)', + `remaining_capacity` bigint(20) unsigned DEFAULT NULL COMMENT 'remaining vgpu can be created with this vgpu_type on the given gpu group', + `max_capacity` bigint(20) unsigned DEFAULT NULL COMMENT 'maximum vgpu can be created with this vgpu_type on the given gpu group', PRIMARY KEY (`id`), CONSTRAINT `fk_vgpu_types__gpu_group_id` FOREIGN KEY (`gpu_group_id`) REFERENCES `host_gpu_groups` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB CHARSET=utf8; @@ -742,6 +762,13 @@ UPDATE `cloud`.`guest_os` SET `created` = now(); ALTER TABLE `cloud`.`vm_reservation` ADD COLUMN `deployment_planner` varchar(40) DEFAULT NULL COMMENT 'Preferred deployment planner for the vm'; ALTER TABLE `cloud`.`vpc_offerings` ADD COLUMN supports_distributed_router boolean default false; ALTER TABLE `cloud`.`vpc` ADD COLUMN uses_distributed_router boolean default false; - INSERT INTO `cloud`.`storage_pool_details` (pool_id,name,value,display) SELECT storage_pool.id,data_center_details.name,data_center_details.value,data_center_details.display FROM `cloud`.`storage_pool` JOIN `cloud`.`data_center_details` ON data_center_details.dc_id=storage_pool.data_center_id WHERE data_center_details.name = "storage.overprovisioning.factor"; DELETE FROM `cloud`.`data_center_details` WHERE name="storage.overprovisioning.factor"; +ALTER TABLE `cloud`.`vpc_offerings` ADD COLUMN supports_region_level_vpc boolean default false; +ALTER TABLE `cloud`.`network_offerings` ADD COLUMN supports_streched_l2 boolean default false; +ALTER TABLE `cloud`.`networks` ADD COLUMN streched_l2 boolean default false; +ALTER TABLE `cloud`.`vpc` ADD COLUMN region_level_vpc boolean default false; +ALTER TABLE `cloud`.`load_balancer_vm_map` ADD COLUMN instance_ip VARCHAR(40); +ALTER TABLE `cloud`.`load_balancer_vm_map` DROP KEY `load_balancer_id`, ADD UNIQUE KEY load_balancer_id (`load_balancer_id`, `instance_id`, `instance_ip`); + +INSERT INTO `cloud`.`configuration`(category, instance, component, name, value, description, default_value) VALUES ('Advanced', 'DEFAULT', 'NetworkOrchestrationService', 'router.redundant.vrrp.interval', '1', 'seconds between VRRP broadcast. It would 3 times broadcast fail to trigger fail-over mechanism of redundant router', '1') ON DUPLICATE KEY UPDATE category='Advanced'; diff --git a/setup/db/templates.sql b/setup/db/templates.sql index 329932060e..6a74633efc 100755 --- a/setup/db/templates.sql +++ b/setup/db/templates.sql @@ -16,13 +16,13 @@ -- under the License. INSERT INTO `cloud`.`vm_template` (id, uuid, unique_name, name, public, created, type, hvm, bits, account_id, url, checksum, enable_password, display_text, format, guest_os_id, featured, cross_zones, hypervisor_type) - VALUES (1, UUID(), 'routing-1', 'SystemVM Template (XenServer)', 0, now(), 'SYSTEM', 0, 32, 1, 'http://download.cloud.com/templates/4.2/systemvmtemplate-2013-07-12-master-xen.vhd.bz2', '74b92f031cc5c2089ee89efb81344dcf', 0, 'SystemVM Template (XenServer)', 'VHD', 183, 0, 1, 'XenServer' ); + VALUES (1, UUID(), 'routing-1', 'SystemVM Template (XenServer)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/4.3/systemvm64template-2014-01-14-master-xen.vhd.bz2', '74b92f031cc5c2089ee89efb81344dcf', 0, 'SystemVM Template (XenServer)', 'VHD', 183, 0, 1, 'XenServer' ); INSERT INTO `cloud`.`vm_template` (id, uuid, unique_name, name, public, created, removed, type, hvm, bits, account_id, url, checksum, enable_password, display_text, format, guest_os_id, featured, cross_zones, hypervisor_type, extractable) VALUES (2, UUID(), 'centos53-x86_64', 'CentOS 5.3(64-bit) no GUI (XenServer)', 1, now(), now(), 'BUILTIN', 0, 64, 1, 'http://download.cloud.com/templates/builtin/f59f18fb-ae94-4f97-afd2-f84755767aca.vhd.bz2', 'b63d854a9560c013142567bbae8d98cf', 0, 'CentOS 5.3(64-bit) no GUI (XenServer)', 'VHD', 12, 1, 1, 'XenServer', 1); INSERT INTO `cloud`.`vm_template` (id, uuid, unique_name, name, public, created, type, hvm, bits, account_id, url, checksum, enable_password, display_text, format, guest_os_id, featured, cross_zones, hypervisor_type) - VALUES (3, UUID(), 'routing-3', 'SystemVM Template (KVM)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/4.2/systemvmtemplate-2013-06-12-master-kvm.qcow2.bz2', '6cea42b2633841648040becb588bd8f0', 0, 'SystemVM Template (KVM)', 'QCOW2', 15, 0, 1, 'KVM' ); + VALUES (3, UUID(), 'routing-3', 'SystemVM Template (KVM)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/4.3/systemvm64template-2014-01-14-master-kvm.qcow2.bz2', '85a1bed07bf43cbf022451cb2ecae4ff', 0, 'SystemVM Template (KVM)', 'QCOW2', 15, 0, 1, 'KVM' ); INSERT INTO `cloud`.`vm_template` (id, uuid, unique_name, name, public, created, type, hvm, bits, account_id, url, checksum, display_text, enable_password, format, guest_os_id, featured, cross_zones, hypervisor_type, extractable) VALUES (4, UUID(), 'centos55-x86_64', 'CentOS 5.5(64-bit) no GUI (KVM)', 1, now(), 'BUILTIN', 0, 64, 1, 'http://download.cloud.com/releases/2.2.0/eec2209b-9875-3c8d-92be-c001bd8a0faf.qcow2.bz2', 'ed0e788280ff2912ea40f7f91ca7a249', 'CentOS 5.5(64-bit) no GUI (KVM)', 0, 'QCOW2', 112, 1, 1, 'KVM', 1); @@ -68,7 +68,7 @@ INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (11, INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (12, UUID(), 1, 'CentOS 5.3 (64-bit)'); INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (13, UUID(), 1, 'CentOS 5.4 (32-bit)'); INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (14, UUID(), 1, 'CentOS 5.4 (64-bit)'); -INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (15, UUID(), 2, 'Debian GNU/Linux 5.0 (32-bit)'); +INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (15, UUID(), 2, 'Debian GNU/Linux 5.0 (64-bit)'); INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (16, UUID(), 3, 'Oracle Enterprise Linux 5.0 (32-bit)'); INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (17, UUID(), 3, 'Oracle Enterprise Linux 5.0 (64-bit)'); INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (18, UUID(), 3, 'Oracle Enterprise Linux 5.1 (32-bit)'); diff --git a/systemvm/patches/debian/config/etc/init.d/cloud-early-config b/systemvm/patches/debian/config/etc/init.d/cloud-early-config index 5751f09ac3..ffb23ec7cb 100755 --- a/systemvm/patches/debian/config/etc/init.d/cloud-early-config +++ b/systemvm/patches/debian/config/etc/init.d/cloud-early-config @@ -865,6 +865,12 @@ setup_redundant_router() { sed -i "s/\[RROUTER_LOG\]/$rrouter_log_str/g" $rrouter_bin_path/check_heartbeat.sh sed -i "s/\[RROUTER_LOG\]/$rrouter_log_str/g" $rrouter_bin_path/arping_gateways.sh sed -i "s/\[RROUTER_LOG\]/$rrouter_log_str/g" /opt/cloud/bin/checkrouter.sh + + if [ $ADVERT_INT ] + then + sed -i "s/advert_int 1/advert_int $ADVERT_INT/g" /etc/keepalived/keepalived.conf + fi + chmod a+x $rrouter_bin_path/*.sh sed -i "s/--exec\ \$DAEMON;/--exec\ \$DAEMON\ --\ --vrrp;/g" /etc/init.d/keepalived @@ -1073,8 +1079,16 @@ setup_dhcpsrvr() { enable_svc cloud 0 enable_fwding 0 chkconfig nfs-common off + cp /etc/iptables/iptables-router /etc/iptables/rules.v4 cp /etc/iptables/iptables-router /etc/iptables/rules + + #Only allow DNS service for current network + sed -i "s/-A INPUT -i eth0 -p udp -m udp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p udp -m udp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules.v4 + sed -i "s/-A INPUT -i eth0 -p udp -m udp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p udp -m udp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules + sed -i "s/-A INPUT -i eth0 -p tcp -m tcp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p tcp -m tcp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules.v4 + sed -i "s/-A INPUT -i eth0 -p tcp -m tcp --dport 53 -j ACCEPT/-A INPUT -i eth0 -p tcp -m tcp --dport 53 -s $DHCP_RANGE\/$CIDR_SIZE -j ACCEPT/g" /etc/iptables/rules + if [ "$SSHONGUEST" == "true" ] then setup_sshd $ETH0_IP "eth0" @@ -1100,6 +1114,7 @@ setup_storage_network() { setup_secstorage() { log_it "Setting up secondary storage system vm" + sysctl vm.min_free_kbytes=8192 local hyp=$1 setup_common eth0 eth1 eth2 setup_storage_network @@ -1419,6 +1434,12 @@ for i in $CMDLINE vpccidr) VPCCIDR=$VALUE ;; + cidrsize) + CIDR_SIZE=$VALUE + ;; + advert_int) + ADVERT_INT=$VALUE + ;; esac done diff --git a/systemvm/patches/debian/config/etc/logrotate.d/conntrackd b/systemvm/patches/debian/config/etc/logrotate.d/conntrackd new file mode 100644 index 0000000000..d09d752e11 --- /dev/null +++ b/systemvm/patches/debian/config/etc/logrotate.d/conntrackd @@ -0,0 +1,13 @@ +/var/log/conntrackd-stats.log { + daily + rotate 2 + missingok + compress + delaycompress + + postrotate + if [ -e /var/run/conntrackd.sock ]; then + invoke-rc.d conntrackd restart > /dev/null + fi + endscript +} diff --git a/systemvm/patches/debian/config/opt/cloud/bin/getRouterAlerts.sh b/systemvm/patches/debian/config/opt/cloud/bin/getRouterAlerts.sh index e5e8abeffd..3f5f4a3b05 100644 --- a/systemvm/patches/debian/config/opt/cloud/bin/getRouterAlerts.sh +++ b/systemvm/patches/debian/config/opt/cloud/bin/getRouterAlerts.sh @@ -18,53 +18,38 @@ # getRouterAlerts.sh --- Send the alerts from routerServiceMonitor.log to Management Server -source /root/func.sh - -lock="biglock" -locked=$(getLockFile $lock) -if [ "$locked" != "1" ] -then - exit 1 -fi - #set -x filename=/var/log/routerServiceMonitor.log #Monitor service log file if [ -n "$1" -a -n "$2" ] then - reqdateval=$(date -d $1 +"%Y%m%d"); - reqtimeval=$(date -d $2 +"%H%M%S"); + reqDateVal=$(date -d "$1 $2" "+%s"); else - reqdateval=0 - reqtimeval=0 + reqDateVal=0 fi if [ -f $filename ] then while read line do - if [ -n "$line" ]; then - dateval=`echo $line |awk '{print $1}'` - timeval=`echo $line |awk '{print $2}'` - - todate=$(date -d "$dateval" +"%Y%m%d") > /dev/null - totime=$(date -d "$timeval" +"%H%M%S") > /dev/null - if [ "$todate" -gt "$reqdateval" ] > /dev/null + if [ -n "$line" ] then - if [ -n "$alerts" ]; then alerts="$alerts\n$line"; else alerts="$line"; fi #>> $outputfile - elif [ "$todate" -eq "$reqdateval" ] > /dev/null + dateval=`echo $line |awk '{print $1, $2}'` + IFS=',' read -a array <<< "$dateval" + dateval=${array[0]} + + toDateVal=$(date -d "$dateval" "+%s") + + if [ "$toDateVal" -gt "$reqDateVal" ] then - if [ "$totime" -gt "$reqtimeval" ] > /dev/null - then - if [ -n "$alerts" ]; then alerts="$alerts\n$line"; else alerts="$line"; fi #>> $outputfile - fi + alerts="$line\n$alerts" + else + break fi fi - done < $filename + done < <(tac $filename) fi if [ -n "$alerts" ]; then echo $alerts else echo "No Alerts" -fi - -unlock_exit 0 $lock $locked \ No newline at end of file +fi \ No newline at end of file diff --git a/systemvm/patches/debian/config/opt/cloud/bin/savepassword.sh b/systemvm/patches/debian/config/opt/cloud/bin/savepassword.sh index 1ea27e5b70..21fa09d5b7 100755 --- a/systemvm/patches/debian/config/opt/cloud/bin/savepassword.sh +++ b/systemvm/patches/debian/config/opt/cloud/bin/savepassword.sh @@ -52,7 +52,7 @@ done [ -f $PASSWD_FILE ] || touch $PASSWD_FILE -sed -i /$VM_IP/d $PASSWD_FILE +sed -i /$VM_IP=/d $PASSWD_FILE ps aux | grep serve_password.sh |grep -v grep 2>&1 > /dev/null if [ $? -eq 0 ] diff --git a/test/integration/smoke/test_VirtualRouter_alerts.py b/test/integration/component/test_VirtualRouter_alerts.py similarity index 98% rename from test/integration/smoke/test_VirtualRouter_alerts.py rename to test/integration/component/test_VirtualRouter_alerts.py index 2333d846f1..4b53e3fd2c 100644 --- a/test/integration/smoke/test_VirtualRouter_alerts.py +++ b/test/integration/component/test_VirtualRouter_alerts.py @@ -229,7 +229,7 @@ def test_01_VRServiceFailureAlerting(self): res = str(result) self.debug("apache process status: %s" % res) - time.sleep(300) #wait for 5 minutes meanwhile monitor service on VR starts the apache service + time.sleep(2400) #wait for 40 minutes meanwhile monitor service on VR starts the apache service (router.alerts.check.interval default value is 30minutes) qresultset = self.dbclient.execute( "select id from alert where subject = '%s' ORDER BY id DESC LIMIT 1;" \ diff --git a/test/integration/component/test_accounts.py b/test/integration/component/test_accounts.py index 650a595936..bee17fbc7b 100644 --- a/test/integration/component/test_accounts.py +++ b/test/integration/component/test_accounts.py @@ -148,7 +148,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg", "selfservice"]) def test_01_create_account(self): """Test Create Account and user for that account """ @@ -286,7 +286,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg", "selfservice"]) def test_01_user_remove_VM_running(self): """Test Remove one user from the account """ @@ -440,7 +440,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg", "selfservice"]) def test_01_non_root_admin_Privileges(self): """Test to verify Non Root admin previleges""" @@ -561,7 +561,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg", "selfservice"]) def test_01_service_offering_siblings(self): """Test to verify service offerings at same level in hierarchy""" @@ -679,7 +679,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg", "selfservice"]) def test_01_service_offering_hierarchy(self): """Test to verify service offerings at same level in hierarchy""" @@ -976,7 +976,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg", "selfservice"]) def test_01_add_vm_to_subdomain(self): """ Test Sub domain allowed to launch VM when a Domain level zone is created""" @@ -1533,7 +1533,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["domains", "advanced", "advancedns", "simulator"]) + @attr(tags=["domains", "advanced", "advancedns", "simulator", "selfservice"]) def test_forceDeleteDomain(self): """ Test delete domain with force option""" @@ -1698,7 +1698,7 @@ def test_forceDeleteDomain(self): ) return - @attr(tags=["domains", "advanced", "advancedns", "simulator"]) + @attr(tags=["domains", "advanced", "advancedns", "simulator", "selfservice"]) def test_DeleteDomain(self): """ Test delete domain without force option""" diff --git a/test/integration/component/test_affinity_groups.py b/test/integration/component/test_affinity_groups.py index 7e4fabe547..8808034142 100644 --- a/test/integration/component/test_affinity_groups.py +++ b/test/integration/component/test_affinity_groups.py @@ -169,7 +169,7 @@ def create_aff_grp(self, api_client=None, aff_grp=None, except Exception as e: raise Exception("Error: Creation of Affinity Group failed : %s" %e) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_01_admin_create_aff_grp(self): """ Test create affinity group as admin @@ -184,7 +184,7 @@ def test_01_admin_create_aff_grp(self): self.assert_(list_aff_grps[0].id == aff_grp.id) self.cleanup.append(aff_grp) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_02_doadmin_create_aff_grp(self): """ Test create affinity group as domain admin @@ -204,7 +204,7 @@ def test_02_doadmin_create_aff_grp(self): aff_grp.delete(domainapiclient) #@attr(tags=["simulator", "basic", "advanced"]) - @attr(tags=["vogxn", "simulator", "basic", "advanced"]) + @attr(tags=["vogxn", "simulator", "basic", "advanced", "selfservice"]) def test_03_user_create_aff_grp(self): """ Test create affinity group as user @@ -222,7 +222,7 @@ def test_03_user_create_aff_grp(self): aff_grp.delete(userapiclient) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_04_user_create_aff_grp_existing_name(self): """ Test create affinity group that exists (same name) @@ -243,7 +243,7 @@ def test_04_user_create_aff_grp_existing_name(self): self.debug("Deleted Affinity Group: %s" %aff_grp.name) aff_grp.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_05_create_aff_grp_same_name_diff_acc(self): """ Test create affinity group with existing name but within different account @@ -265,7 +265,7 @@ def test_05_create_aff_grp_same_name_diff_acc(self): self.debug("Deleted Affinity Group: %s" %aff_grp.name) aff_grp.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_06_create_aff_grp_nonexisting_type(self): """ Test create affinity group of non-existing type @@ -391,7 +391,7 @@ def create_vm_in_aff_grps(self, ag_list, account_name=None, domain_id=None): msg="VM is not in Running state") return vm, vm_response.hostid - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_01_list_aff_grps_for_vm(self): """ List affinity group for a vm @@ -413,7 +413,7 @@ def test_01_list_aff_grps_for_vm(self): self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_02_list_multiple_aff_grps_for_vm(self): """ List multiple affinity groups associated with a vm @@ -442,7 +442,7 @@ def test_02_list_multiple_aff_grps_for_vm(self): aff_grp_01.delete(self.api_client) aff_grp_02.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_03_list_aff_grps_by_id(self): """ List affinity groups by id @@ -457,7 +457,7 @@ def test_03_list_aff_grps_by_id(self): self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_04_list_aff_grps_by_name(self): """ List Affinity Groups by name @@ -471,7 +471,7 @@ def test_04_list_aff_grps_by_name(self): self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_05_list_aff_grps_by_non_existing_id(self): """ List Affinity Groups by non-existing id @@ -485,7 +485,7 @@ def test_05_list_aff_grps_by_non_existing_id(self): self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_06_list_aff_grps_by_non_existing_name(self): """ List Affinity Groups by non-existing name @@ -499,7 +499,7 @@ def test_06_list_aff_grps_by_non_existing_name(self): self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_07_list_all_vms_in_aff_grp(self): """ List affinity group should list all for a vms associated with that group @@ -642,7 +642,7 @@ def delete_aff_group(self, apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return apiclient.deleteAffinityGroup(cmd) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_01_delete_aff_grp_by_name(self): """ Delete Affinity Group by name @@ -653,7 +653,7 @@ def test_01_delete_aff_grp_by_name(self): self.delete_aff_group(self.api_client, name=aff_0.name) self.assert_(AffinityGroup.list(self.api_client, name=aff_0.name) is None) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_02_delete_aff_grp_for_acc(self): """ Delete Affinity Group as admin for an account @@ -669,7 +669,7 @@ def test_02_delete_aff_grp_for_acc(self): self.create_vm_in_aff_grps([aff_0.name], account_name=self.account.name, domain_id=self.domain.id) aff_1.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_03_delete_aff_grp_with_vms(self): """ Delete Affinity Group which has vms in it @@ -687,7 +687,7 @@ def test_03_delete_aff_grp_with_vms(self): wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) aff_1.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_05_delete_aff_grp_id(self): """ Delete Affinity Group with id which does not belong to this user @@ -723,7 +723,7 @@ def test_05_delete_aff_grp_id(self): aff_0.delete(self.api_client) aff_1.delete(userapiclient) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_06_delete_aff_grp_name(self): """ Delete Affinity Group by name which does not belong to this user @@ -759,7 +759,7 @@ def test_06_delete_aff_grp_name(self): aff_0.delete(self.api_client) aff_1.delete(userapiclient) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_08_delete_aff_grp_by_id(self): """ Delete Affinity Group by id. @@ -771,7 +771,7 @@ def test_08_delete_aff_grp_by_id(self): aff_grp_1.delete(self.api_client) aff_grp_2.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_09_delete_aff_grp_root_admin(self): """ Root admin should be able to delete affinity group of other users @@ -909,7 +909,7 @@ def create_vm_in_aff_grps(self, ag_list, account_name=None, domain_id=None): return vm, vm_response.hostid - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_01_update_aff_grp_by_ids(self): """ Update the list of affinityGroups by using affinity groupids @@ -957,7 +957,7 @@ def test_01_update_aff_grp_by_ids(self): for aff_grp in self.aff_grp: aff_grp.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_02_update_aff_grp_by_names(self): """ Update the list of affinityGroups by using affinity groupnames @@ -1000,7 +1000,7 @@ def test_02_update_aff_grp_by_names(self): for aff_grp in self.aff_grp: aff_grp.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_03_update_aff_grp_for_vm_with_no_aff_grp(self): """ Update the list of affinityGroups for vm which is not associated @@ -1033,7 +1033,7 @@ def test_03_update_aff_grp_for_vm_with_no_aff_grp(self): aff_grp.delete(self.api_client) @unittest.skip("Skip - Failing - work in progress") - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "NotRun"]) def test_04_update_aff_grp_remove_all(self): """ Update the list of Affinity Groups to empty list @@ -1059,7 +1059,7 @@ def test_04_update_aff_grp_remove_all(self): for aff_grp in aff_grps: aff_grp.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_05_update_aff_grp_on_running_vm(self): """ Update the list of Affinity Groups on running vm @@ -1195,7 +1195,7 @@ def create_vm_in_aff_grps(self, api_client=None, ag_list=None, ag_ids=None, acco return vm, vm_response.hostid - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_01_deploy_vm_without_aff_grp(self): """ Deploy VM without affinity group @@ -1206,7 +1206,7 @@ def test_01_deploy_vm_without_aff_grp(self): #Wait for expunge interval to cleanup VM wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_02_deploy_vm_by_aff_grp_name(self): """ Deploy VM by aff grp name @@ -1218,7 +1218,7 @@ def test_02_deploy_vm_by_aff_grp_name(self): wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_03_deploy_vm_by_aff_grp_id(self): """ Deploy VM by aff grp id @@ -1234,7 +1234,7 @@ def test_03_deploy_vm_by_aff_grp_id(self): wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_04_deploy_vm_anti_affinity_group(self): """ test DeployVM in anti-affinity groups @@ -1255,7 +1255,7 @@ def test_04_deploy_vm_anti_affinity_group(self): wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_05_deploy_vm_by_id(self): """ Deploy vms by affinity group id @@ -1277,7 +1277,7 @@ def test_05_deploy_vm_by_id(self): wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) self.aff_grp[0].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_06_deploy_vm_aff_grp_of_other_user_by_name(self): """ Deploy vm in affinity group of another user by name @@ -1310,7 +1310,7 @@ def test_06_deploy_vm_aff_grp_of_other_user_by_name(self): self.aff_grp[0].delete(self.api_client) self.aff_grp[1].delete(userapiclient) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_07_deploy_vm_aff_grp_of_other_user_by_id(self): """ Deploy vm in affinity group of another user by id @@ -1346,7 +1346,7 @@ def test_07_deploy_vm_aff_grp_of_other_user_by_id(self): self.aff_grp[0].delete(self.api_client) self.aff_grp[1].delete(userapiclient) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_08_deploy_vm_multiple_aff_grps(self): """ Deploy vm in multiple affinity groups @@ -1375,7 +1375,7 @@ def test_08_deploy_vm_multiple_aff_grps(self): self.aff_grp[0].delete(self.api_client) self.aff_grp[1].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_09_deploy_vm_multiple_aff_grps(self): """ Deploy multiple vms in multiple affinity groups @@ -1410,7 +1410,7 @@ def test_09_deploy_vm_multiple_aff_grps(self): self.aff_grp[0].delete(self.api_client) self.aff_grp[1].delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_10_deploy_vm_by_aff_grp_name_and_id(self): """ Deploy VM by aff grp name and id @@ -1540,7 +1540,7 @@ def create_vm_in_aff_grps(self, api_client=None, ag_list=None, ag_ids=None, acco return vm, vm_response.hostid - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_01_deploy_vm_another_user(self): """ Deploy vm as Admin in Affinity Group belonging to regular user (should fail) @@ -1578,7 +1578,7 @@ def test_02_create_aff_grp_user(self): aff_grp.delete(self.apiclient) - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_03_list_aff_grp_all_users(self): """ List Affinity Groups as admin for all the users @@ -1601,7 +1601,7 @@ def test_03_list_aff_grp_all_users(self): "Groups of users") aff_grp.delete(userapiclient) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_04_list_all_admin_aff_grp(self): """ List Affinity Groups belonging to admin user @@ -1628,7 +1628,7 @@ def test_04_list_all_admin_aff_grp(self): aff_grp1.delete(self.api_client) aff_grp2.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_05_list_all_users_aff_grp(self): """ List Affinity Groups belonging to regular user passing account id and domain id @@ -1664,7 +1664,7 @@ def test_05_list_all_users_aff_grp(self): aff_grp1.delete(self.api_client) aff_grp2.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_06_list_all_users_aff_grp_by_id(self): """ List Affinity Groups belonging to regular user passing group id @@ -1696,7 +1696,7 @@ def test_06_list_all_users_aff_grp_by_id(self): aff_grp.delete(self.api_client) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_07_delete_aff_grp_of_other_user(self): """ Delete Affinity Group belonging to regular user diff --git a/test/integration/component/test_allocation_states.py b/test/integration/component/test_allocation_states.py index 5ce0b21124..1c0bce5dbd 100644 --- a/test/integration/component/test_allocation_states.py +++ b/test/integration/component/test_allocation_states.py @@ -120,7 +120,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_01_zones(self): """Check the status of zones""" @@ -146,7 +146,7 @@ def test_01_zones(self): ) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_02_pods(self): """Check the status of pods""" @@ -172,7 +172,7 @@ def test_02_pods(self): ) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_03_clusters(self): """Check the status of clusters""" @@ -198,7 +198,7 @@ def test_03_clusters(self): ) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_04_hosts(self): """Check the status of hosts""" @@ -225,7 +225,7 @@ def test_04_hosts(self): ) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_05_storage_pools(self): """Check the status of Storage pools""" @@ -251,7 +251,7 @@ def test_05_storage_pools(self): ) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_06_secondary_storage(self): """Check the status of secondary storage""" diff --git a/test/integration/component/test_base_image_updation.py b/test/integration/component/test_base_image_updation.py index e31aacfa7e..ac3ac8ea37 100644 --- a/test/integration/component/test_base_image_updation.py +++ b/test/integration/component/test_base_image_updation.py @@ -291,7 +291,7 @@ def verify_template_listing(self, template): return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_01_deploy_instance_with_is_volatile_offering(self): """ Test deploy an instance with service offerings with IsVolatile set. """ @@ -322,7 +322,7 @@ def test_01_deploy_instance_with_is_volatile_offering(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_02_reboot_instance_with_is_volatile_offering(self): """ Test rebooting instances created with isVolatile service offerings """ @@ -400,7 +400,7 @@ def test_02_reboot_instance_with_is_volatile_offering(self): return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_03_restore_vm_with_new_template(self): """ Test restoring a vm with different template than the one it was created with """ @@ -515,7 +515,7 @@ def test_03_restore_vm_with_new_template(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_04_reoccuring_snapshot_rules(self): """ 1) Create a VM using the Service offering IsVolatile enabled diff --git a/test/integration/component/test_blocker_bugs.py b/test/integration/component/test_blocker_bugs.py index 04a26562d0..98bed9235a 100644 --- a/test/integration/component/test_blocker_bugs.py +++ b/test/integration/component/test_blocker_bugs.py @@ -149,7 +149,7 @@ def tearDownClass(cls): return - @attr(tags = ["advanced", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "advancedns", "basic", "sg", "provisioning"]) def test_01_create_template(self): """TS_BUG_002-Test to create and deploy VM using password enabled template """ @@ -308,7 +308,7 @@ def tearDownClass(cls): except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_01_firewall_rules_port_fw(self): """"Checking firewall rules deletion after static NAT disable""" @@ -515,7 +515,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_01_list_routers_admin(self): """TS_BUG_007-Check listRouters() using Admin User """ @@ -630,7 +630,7 @@ def tearDown(self): # No need return - @attr(tags = ["advanced", "advancedns", "eip"]) + @attr(tags=["advanced", "advancedns", "eip", "selfservice"]) def test_01_restart_network_cleanup(self): """TS_BUG_008-Test restart network """ @@ -793,7 +793,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "basic", "sg", "eip"]) + @attr(tags=["advanced", "advancedns", "basic", "sg", "eip", "provisioning"]) def test_01_check_template_size(self): """TS_BUG_009-Test the size of template created from root disk """ @@ -821,7 +821,7 @@ def test_01_check_template_size(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "basic", "sg", "eip"]) + @attr(tags=["advanced", "advancedns", "basic", "sg", "eip", "provisioning"]) def test_02_check_size_snapshotTemplate(self): """TS_BUG_010-Test check size of snapshot and template """ @@ -902,7 +902,7 @@ def test_02_check_size_snapshotTemplate(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "basic", "sg", "eip"]) + @attr(tags=["advanced", "advancedns", "basic", "sg", "eip", "provisioning"]) def test_03_reuse_template_name(self): """TS_BUG_011-Test Reusing deleted template name """ diff --git a/test/integration/component/test_cpu_domain_limits.py b/test/integration/component/test_cpu_domain_limits.py index 1247a799c8..c0bd9e739e 100644 --- a/test/integration/component/test_cpu_domain_limits.py +++ b/test/integration/component/test_cpu_domain_limits.py @@ -217,7 +217,7 @@ def setupAccounts(self): ) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_multiple_core_vm_start_stop_instance(self): """Test Deploy VM with 4 core CPU & verify the usage""" @@ -290,7 +290,7 @@ def test_01_multiple_core_vm_start_stop_instance(self): "Resource count should be same as before, after starting the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_multiple_core_vm_migrate_instance(self): """Test Deploy VM with 4 core CPU & verify the usage""" @@ -351,7 +351,7 @@ def test_02_multiple_core_vm_migrate_instance(self): "Resource count should be same as before, after migrating the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_multiple_core_vm_delete_instance(self): """Test Deploy VM with 4 core CPU & verify the usage""" @@ -408,7 +408,7 @@ def test_03_multiple_core_vm_delete_instance(self): "Resource count for %s should be 0" % get_resource_type(resource_id=8))#CPU return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_04_deploy_multiple_vm_with_multiple_core(self): """Test Deploy multiple VM with 4 core CPU & verify the usage""" @@ -662,7 +662,7 @@ def setupAccounts(self): } return users - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_multiple_child_domains(self): """Test CPU limits with multiple child domains""" diff --git a/test/integration/component/test_cpu_limits.py b/test/integration/component/test_cpu_limits.py index f043773e7b..9868bf2809 100644 --- a/test/integration/component/test_cpu_limits.py +++ b/test/integration/component/test_cpu_limits.py @@ -176,7 +176,7 @@ def createInstance(self, service_off, networks=None, api_client=None): except Exception as e: self.fail("Failed to deploy an instance: %s" % e) - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_multiplecore_start_stop_instance(self): """Test Deploy VM with multiple core CPU & verify the usage""" @@ -231,7 +231,7 @@ def test_01_multiplecore_start_stop_instance(self): "Resource count should be same after stopping the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_multiplecore_migrate_instance(self): """Test Deploy VM with multiple core CPU & verify the usage""" @@ -272,7 +272,7 @@ def test_02_multiplecore_migrate_instance(self): "Resource count should be same after migrating the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_multiplecore_delete_instance(self): """Test Deploy VM with multiple core CPU & verify the usage""" @@ -308,7 +308,7 @@ def test_03_multiplecore_delete_instance(self): self.assertEqual(resource_count, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=8))#CPU return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_04_deploy_multiple_vm_with_multiple_cpus(self): """Test Deploy multiple VM with 4 core CPU & verify the usage""" @@ -462,7 +462,7 @@ def setupAccounts(self): return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_stop_start_instance(self): """Test Deploy VM with 4 core CPU & verify the usage""" @@ -534,7 +534,7 @@ def test_01_stop_start_instance(self): "Resource count should be same after starting the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_migrate_instance(self): """Test Deploy VM with 4 core CPU & verify the usage""" @@ -594,7 +594,7 @@ def test_02_migrate_instance(self): "Resource count should be same after starting the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_delete_instance(self): """Test Deploy VM with 4 core CPU & verify the usage""" diff --git a/test/integration/component/test_cpu_max_limits.py b/test/integration/component/test_cpu_max_limits.py index 317df166a5..c0d30483e5 100644 --- a/test/integration/component/test_cpu_max_limits.py +++ b/test/integration/component/test_cpu_max_limits.py @@ -227,7 +227,7 @@ def setupAccounts(self, account_limit=2, domain_limit=2, project_limit=2): return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_deploy_vm_domain_limit_reached(self): """Test Try to deploy VM with admin account where account has not used the resources but @ domain they are not available""" @@ -260,7 +260,7 @@ def test_01_deploy_vm_domain_limit_reached(self): service_off=self.service_offering, api_client=api_client_admin) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_02_deploy_vm_account_limit_reached(self): """Test Try to deploy VM with admin account where account has used the resources but @ domain they are available""" @@ -301,7 +301,7 @@ def test_02_deploy_vm_account_limit_reached(self): service_off=self.service_offering, api_client=api_client_admin) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_deploy_vm_project_limit_reached(self): """Test TTry to deploy VM with admin account where account has not used the resources but @ project they are not available""" @@ -336,7 +336,7 @@ def test_03_deploy_vm_project_limit_reached(self): service_off=self.service_offering, api_client=api_client_admin) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_04_deployVm__account_limit_reached(self): """Test Try to deploy VM with admin account where account has used the resources but @ project they are available""" diff --git a/test/integration/component/test_cpu_project_limits.py b/test/integration/component/test_cpu_project_limits.py index ed7cd88248..8a355cf44e 100644 --- a/test/integration/component/test_cpu_project_limits.py +++ b/test/integration/component/test_cpu_project_limits.py @@ -216,7 +216,7 @@ def setupProjectAccounts(self): "Check project name from list response") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_project_counts_start_stop_instance(self): # Validate the following @@ -271,7 +271,7 @@ def test_01_project_counts_start_stop_instance(self): "Resource count should be same after starting the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_project_counts_migrate_instance(self): # Validate the following @@ -313,7 +313,7 @@ def test_02_project_counts_migrate_instance(self): "Resource count should be same after migrating the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_project_counts_delete_instance(self): # Validate the following diff --git a/test/integration/component/test_custom_hostname.py b/test/integration/component/test_custom_hostname.py index 1549a20657..baf4f1b46d 100644 --- a/test/integration/component/test_custom_hostname.py +++ b/test/integration/component/test_custom_hostname.py @@ -157,7 +157,7 @@ def tearDown(self): @attr(configuration='vm.instancename.flag') - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_user_provided_hostname(self): """ Verify user provided hostname to an instance """ @@ -261,7 +261,7 @@ def test_01_user_provided_hostname(self): return @attr(configuration='vm.instancename.flag') - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_02_instancename_from_default_configuration(self): """ Verify for globally set instancename """ @@ -372,7 +372,7 @@ def test_02_instancename_from_default_configuration(self): return @attr(configuration='vm.instancename.flag') - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_03_duplicate_name(self): """ Test the duplicate name when old VM is in non-expunged state """ @@ -432,7 +432,7 @@ def test_03_duplicate_name(self): return @attr(configuration='vm.instancename.flag') - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_04_edit_display_name(self): """ Test Edit the Display name Through the UI. """ @@ -525,7 +525,7 @@ def test_04_edit_display_name(self): return @attr(configuration='vm.instancename.flag') - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_05_unsupported_chars_in_display_name(self): """ Test Unsupported chars in the display name (eg: Spaces,Exclamation,yet to get unsupported chars from the dev) @@ -622,7 +622,7 @@ def tearDown(self): return @attr(configuration='vm.instancename.flag') - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_custom_hostname_instancename_false(self): """ Verify custom hostname for the instance when vm.instancename.flag=false diff --git a/test/integration/component/test_deploy_vm_userdata_reg.py b/test/integration/component/test_deploy_vm_userdata_reg.py index b282a86081..912c9172ea 100755 --- a/test/integration/component/test_deploy_vm_userdata_reg.py +++ b/test/integration/component/test_deploy_vm_userdata_reg.py @@ -100,7 +100,7 @@ def setUpClass(cls): - @attr(tags=["simulator", "devcloud", "basic", "advanced"]) + @attr(tags=["simulator", "devcloud", "basic", "advanced", "provisioning"]) def test_deployvm_userdata_post(self): """Test userdata as POST, size > 2k """ diff --git a/test/integration/component/test_dynamic_compute_offering.py b/test/integration/component/test_dynamic_compute_offering.py index 75cf0d658f..cb21caf935 100644 --- a/test/integration/component/test_dynamic_compute_offering.py +++ b/test/integration/component/test_dynamic_compute_offering.py @@ -25,10 +25,14 @@ """ from marvin.cloudstackTestCase import cloudstackTestCase from marvin.integration.lib.utils import (cleanup_resources, - validateList) + validateList, + random_gen) from marvin.integration.lib.base import (ServiceOffering, VirtualMachine, - Account) + Account, + Resources, + AffinityGroup, + Host) from marvin.integration.lib.common import (get_domain, get_zone, get_template, @@ -37,6 +41,7 @@ from nose.plugins.attrib import attr from marvin.codes import PASS, ADMIN_ACCOUNT, USER_ACCOUNT from ddt import ddt, data +import time @ddt class TestDynamicServiceOffering(cloudstackTestCase): @@ -407,3 +412,1051 @@ def test_check_vm_stats(self, value): not matching with provided custom memory %s" % \ (vm.memory, custommemory)) return + +@ddt +class TestScaleVmDynamicServiceOffering(cloudstackTestCase): + """Test scaling VMs with dynamic Service Offerings + """ + + @classmethod + def setUpClass(cls): + cloudstackTestClient = super(TestScaleVmDynamicServiceOffering,cls).getClsTestClient() + cls.api_client = cloudstackTestClient.getApiClient() + + # Fill services from the external config file + cls.services = cloudstackTestClient.getConfigParser().parsedDict + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.mode = str(cls.zone.networktype).lower() + 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 + cls._cleanup = [] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup_co = [] + self.cleanup = [] + return + + def tearDown(self): + try: + # Clean up compute offerings + cleanup_resources(self.apiclient, self.cleanup) + + # Clean up compute offerings + cleanup_resources(self.apiclient, self.cleanup_co) + + self.cleanup_co[:] = [] + self.cleanup[:] = [] + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def stopVM(self, vm): + """Stop VM and verify that it is indeed in stopped state""" + try: + vm.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop VM: %s" % e) + + retriesCount = 10 + while True: + vmlist = VirtualMachine.list(self.apiclient, id=vm.id) + if str(vmlist[0].state).lower() == "stopped": + break + elif retriesCount == 0: + self.fail("Failed to stop VM even after 10 minutes") + else: + retriesCount -= 1 + time.sleep(60) + continue + # End while + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_stopped_vm_static_to_static(self, value): + """Test scale stopped VM from static offering to static offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make two static service offerings + # 3. Deploy VM with one static offering + # 4. Stop the VM + # 5. Scale VM with 2nd static service offering + + # Validations: + # 1. Scaling operation should be successful + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create Account + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + apiclient = self.testClient.createUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + self.cleanup.append(self.account) + + # Create static service offerings (Second offering should have + # one of the custom values greater than 1st one, scaling down is not allowed + self.services["service_offering"]["cpunumber"] = "2" + self.services["service_offering"]["cpuspeed"] = "256" + self.services["service_offering"]["memory"] = "128" + + serviceOffering_static_1 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.services["service_offering"]["cpunumber"] = "4" + + serviceOffering_static_2 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_static_1) + self.cleanup_co.append(serviceOffering_static_2) + + # Deploy VM + try: + virtualMachine = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_static_1.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Stop VM and verify it is in stopped state + self.stopVM(virtualMachine) + + # Scale VM to new static service offering + try: + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_static_2.id) + except Exception as e: + self.fail("Failure while changing service offering: %s" % e) + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_stopped_vm_static_to_dynamic(self, value): + """Test scale stopped VM from static offering to dynamic offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make static and dynamic service offerings + # 3. Deploy VM with static offering + # 4. Stop the VM + # 5. Scale VM with dynamic service offering providing all required + # custom values + # 6. Deploy another VM with static offring and stop the VM + # 7. Scale VM with dynamic service offering providing only custom cpu number + + # Validations: + # 1. Scale operation in step 5 should be successful + # 2. Scale operation in step 7 should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create Account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + apiclient = self.testClient.createUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + self.cleanup.append(self.account) + + # Create static and dynamic service offerings + self.services["service_offering"]["cpunumber"] = "2" + self.services["service_offering"]["cpuspeed"] = "256" + self.services["service_offering"]["memory"] = "128" + + serviceOffering_static = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_static) + self.cleanup_co.append(serviceOffering_dynamic) + + # Deploy VM with static service offering + try: + virtualMachine_1 = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_static.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Stop VM and verify it is in stopped state + self.stopVM(virtualMachine_1) + + # Scale VM to dynamic service offering proving all custom values + try: + virtualMachine_1.scale(apiclient, serviceOfferingId=serviceOffering_dynamic.id, + customcpunumber=4, customcpuspeed=256, custommemory=128) + except Exception as e: + self.fail("Failure while changing service offering: %s" % e) + + # Deploy VM with static service offering + try: + virtualMachine_2 = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_static.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Stop VM and verify it is in stopped state + self.stopVM(virtualMachine_2) + + # Scale VM to dynamic service offering proving only custom cpu number + try: + virtualMachine_2.scale(apiclient, serviceOfferingId=serviceOffering_dynamic.id, + customcpunumber=4) + self.fail("Changing service offering with incomplete data should have failed, it succeded") + except Exception as e: + self.debug("Failure while changing service offering as expected: %s" % e) + + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_stopped_vm_dynamic_to_static(self, value): + """Test scale stopped VM from dynamic offering to static offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make static and dynamic service offerings + # 3. Deploy VM with dynamic service offering + # 4. Stop the VM + # 5. Scale VM with static service offering + + # Validations: + # 1. Scale operation in step 5 should be successful + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + apiclient = self.testClient.createUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + self.cleanup.append(self.account) + + # Create dynamic and static service offering + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.services["service_offering"]["cpunumber"] = "4" + self.services["service_offering"]["cpuspeed"] = "256" + self.services["service_offering"]["memory"] = "128" + + serviceOffering_static = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_static) + self.cleanup_co.append(serviceOffering_dynamic) + + # Deploy VM with dynamic service offering + try: + virtualMachine = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Stop VM and verify that it is in stopped state + self.stopVM(virtualMachine) + + # Scale VM to static service offering + try: + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_static.id) + except Exception as e: + self.fail("Failure while changing service offering: %s" % e) + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_stopped_vm_dynamic_to_dynamic(self, value): + """Test scale stopped VM from dynamic offering to dynamic offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make 2 dynamic service offerings + # 3. Deploy VM with dynamic service offering + # 4. Stop the VM + # 5. Scale VM with same dynamic service offering + # 6. Scale VM with other dynamic service offering + # 7. Scale VM with same/other dynamic offering but providing custom + # value for only cpu number + + # Validations: + # 1. Scale operation in step 5 should be successful + # 2. Scale operation in step 6 should be successful + # 3. Scale operation in step 7 should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create Account + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + apiclient = self.testClient.createUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + self.cleanup.append(self.account) + + # Create dynamic service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic_1 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + serviceOffering_dynamic_2 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_dynamic_1) + self.cleanup_co.append(serviceOffering_dynamic_2) + + # Deploy VM with dynamic service offering + try: + virtualMachine = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic_1.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Stop VM and verify that it is in stopped state + self.stopVM(virtualMachine) + + # Scale VM with same dynamic service offering + try: + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_dynamic_1.id, + customcpunumber=4, customcpuspeed=512, custommemory=256) + except Exception as e: + self.fail("Failure while changing service offering: %s" % e) + + # Scale VM with other dynamic service offering + try: + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_dynamic_2.id, + customcpunumber=4, customcpuspeed=512, custommemory=256) + except Exception as e: + self.fail("Failure while changing service offering: %s" % e) + + # Scale VM with dynamic service offering proving custom value + # only for cpu number + try: + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_dynamic_1.id, + customcpunumber=4) + self.fail("Changing service offering should have failed, it succeded") + except Exception as e: + self.debug("Failure while changing service offering: %s" % e) + + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_running_vm_static_to_static(self, value): + """Test scale running VM from static offering to static offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make two static service offerings + # 3. Deploy VM with one static offering + # 4. Scale VM with 2nd static service offering + + # Validations: + # 1. Scaling operation should be successful + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create Account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + apiclient = self.testClient.createUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + self.cleanup.append(self.account) + + # Create static service offerings + self.services["service_offering"]["cpunumber"] = "2" + self.services["service_offering"]["cpuspeed"] = "256" + self.services["service_offering"]["memory"] = "128" + + serviceOffering_static_1 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.services["service_offering"]["cpunumber"] = "4" + + serviceOffering_static_2 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_static_1) + self.cleanup_co.append(serviceOffering_static_2) + + # Deploy VM with static service offering + try: + virtualMachine = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_static_1.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Scale VM to other static service offering + try: + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_static_2.id) + except Exception as e: + self.fail("Failure while changing service offering: %s" % e) + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_running_vm_static_to_dynamic(self, value): + """Test scale running VM from static offering to dynamic offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make static and dynamic service offerings + # 3. Deploy VM with static offering + # 4. Scale VM with dynamic service offering providing all required + # custom values + # 5. Deploy another VM with static offring + # 6. Scale VM with dynamic service offering providing only custom cpu number + + # Validations: + # 1. Scale operation in step 4 should be successful + # 2. Scale operation in step 6 should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Crate account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + apiclient = self.testClient.createUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + self.cleanup.append(self.account) + + # Create static and dynamic service offerings + self.services["service_offering"]["cpunumber"] = "2" + self.services["service_offering"]["cpuspeed"] = "256" + self.services["service_offering"]["memory"] = "128" + + serviceOffering_static = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_static) + self.cleanup_co.append(serviceOffering_dynamic) + + # Deploy VM with static service offering + try: + virtualMachine_1 = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_static.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Scale VM to dynamic service offering + try: + virtualMachine_1.scale(apiclient, serviceOfferingId=serviceOffering_dynamic.id, + customcpunumber=4, customcpuspeed=256, custommemory=128) + except Exception as e: + self.fail("Failure while changing service offering: %s" % e) + + try: + virtualMachine_2 = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_static.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + try: + virtualMachine_2.scale(apiclient, serviceOfferingId=serviceOffering_dynamic.id, + customcpunumber=4) + self.fail("Changing service offering with incomplete data should have failed, it succeded") + except Exception as e: + self.debug("Failure while changing service offering as expected: %s" % e) + + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_running_vm_dynamic_to_static(self, value): + """Test scale running VM from dynamic offering to static offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make static and dynamic service offerings + # 3. Deploy VM with dynamic service offering + # 4. Scale VM with static service offering + + # Validations: + # 1. Scale operation in step 4 should be successful + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + apiclient = self.testClient.createUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + self.cleanup.append(self.account) + + # Create dynamic and static service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.services["service_offering"]["cpunumber"] = "4" + self.services["service_offering"]["cpuspeed"] = "256" + self.services["service_offering"]["memory"] = "128" + + serviceOffering_static = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_static) + self.cleanup_co.append(serviceOffering_dynamic) + + # deploy VM with dynamic service offering + try: + virtualMachine = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Scale VM to static service offering + try: + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_static.id) + except Exception as e: + self.fail("Failure while changing service offering: %s" % e) + + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_change_so_running_vm_dynamic_to_dynamic(self, value): + """Test scale running VM from dynamic offering to dynamic offering""" + + # Steps: + # 1. Create Account (admin/user) and its api client + # 2. Make 2 dynamic service offerings + # 3. Deploy VM with dynamic service offering + # 4. Scale VM with same dynamic service offering + # 5. Scale VM with other dynamic service offering + # 6. Scale VM with same/other dynamic offering but providing custom + # value for only cpu number + + # Validations: + # 1. Scale operation in step 4 should be successful + # 2. Scale operation in step 5 should be successful + # 3. Scale operation in step 6 should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + apiclient = self.testClient.createUserApiClient( + UserName=self.account.name, + DomainName=self.account.domain) + self.cleanup.append(self.account) + + # Create dynamic service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic_1 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + serviceOffering_dynamic_2 = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_dynamic_1) + self.cleanup_co.append(serviceOffering_dynamic_2) + + # Deploy VM with dynamic service offering + try: + virtualMachine = VirtualMachine.create(apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic_1.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Scale VM with same dynamic offering + try: + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_dynamic_1.id, + customcpunumber=4, customcpuspeed=512, custommemory=256) + except Exception as e: + self.fail("Failure while changing service offering: %s" % e) + + # Scale VM with other dynamic service offering + try: + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_dynamic_2.id, + customcpunumber=4, customcpuspeed=512, custommemory=512) + except Exception as e: + self.fail("Failure while changing service offering: %s" % e) + + # Scale VM with dynamic offering proving custom value only for cpu number + try: + virtualMachine.scale(apiclient, serviceOfferingId=serviceOffering_dynamic_1.id, + customcpunumber=4) + self.fail("Changing service offering should have failed, it succeded") + except Exception as e: + self.debug("Failure while changing service offering: %s" % e) + + return + +@ddt +class TestAccountLimits(cloudstackTestCase): + """Test max limit of account (cpunumber and memory) with dynamic compute offering + """ + + @classmethod + def setUpClass(cls): + cloudstackTestClient = super(TestAccountLimits,cls).getClsTestClient() + cls.api_client = cloudstackTestClient.getApiClient() + + # Fill services from the external config file + cls.services = cloudstackTestClient.getConfigParser().parsedDict + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.mode = str(cls.zone.networktype).lower() + 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 + cls._cleanup = [] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup_co = [] + self.cleanup = [] + return + + def tearDown(self): + try: + # Clean up compute offerings + cleanup_resources(self.apiclient, self.cleanup) + + # Clean up compute offerings + cleanup_resources(self.apiclient, self.cleanup_co) + + self.cleanup_co[:] = [] + self.cleanup[:] = [] + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_max_account_cpus_deploy_VM(self, value): + """Test cpu limits of account while deploying VM with dynamic compute offering""" + + # Steps: + # 1. Create Account (admin/user) + # 2. Update max cpu limit of account to 2 + # 3. Create dynamic service offering + # 4. Deploy VM with dynamic service offering and cpu number 3 + + # Validations: + # 1. VM creation should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + self.cleanup.append(self.account) + + Resources.updateLimit(self.apiclient, + resourcetype=8, + max=2, + account=self.account.name, + domainid=self.account.domainid) + + # Create dynamic service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_dynamic) + + # Deploy VM with dynamic service offering + try: + VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=3, customcpuspeed=256, custommemory=128) + self.fail("vm creation should have failed, it succeeded") + except Exception as e: + self.debug("vm creation failed as expected with error: %s" % e) + + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_max_account_cpus_scale_VM(self, value): + """Test cpu limits of account while scaling VM with dynamic compute offering""" + + # Steps: + # 1. Create Account (admin/user) + # 2. Update max cpu limit of account to 2 + # 3. Create dynamic service offering + # 4. Deploy VM with dynamic service offering and cpu number 2 + # 5. Try to Scale VM with dynamic service offering and cpu number 3 + + # Validations: + # 1. VM creation should succeed + # 2. VM scaling operation should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + self.cleanup.append(self.account) + + Resources.updateLimit(self.apiclient, + resourcetype=8, + max=2, + account=self.account.name, + domainid=self.account.domainid) + + # Create dynamic service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_dynamic) + + # Deploy VM with dynamic service offering + try: + virtualMachine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Scale VM with same dynamic offering + try: + virtualMachine.scale(self.apiclient, serviceOfferingId=serviceOffering_dynamic.id, + customcpunumber=4, customcpuspeed=512, custommemory=256) + self.fail("Scaling virtual machine with cpu number more than \ + allowed limit (of account) succeded, should have failed") + except Exception as e: + self.debug("Failure while changing service offering as expected: %s" % e) + + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_max_account_memory_deploy_VM(self, value): + """Test memory limits of account while deploying VM with dynamic compute offering""" + + # Steps: + # 1. Create Account (admin/user) + # 2. Update max memory limit of account to 256 + # 3. Create dynamic service offering + # 4. Deploy VM with dynamic service offering and memory 512 + + # Validations: + # 1. VM creation should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + self.cleanup.append(self.account) + + Resources.updateLimit(self.apiclient, + resourcetype=9, + max=256, + account=self.account.name, + domainid=self.account.domainid) + + # Create dynamic service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_dynamic) + + # Deploy VM with dynamic service offering + try: + VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=3, customcpuspeed=256, custommemory=512) + self.fail("vm creation should have failed, it succeeded") + except Exception as e: + self.debug("vm creation failed as expected with error: %s" % e) + + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_max_account_memory_scale_VM(self, value): + """Test memory limits of account while scaling VM with dynamic compute offering""" + + # Steps: + # 1. Create Account (admin/user) + # 2. Update max memory limit of account to 256 + # 3. Create dynamic service offering + # 4. Deploy VM with dynamic service offering and memory 256 + # 5. Try to Scale VM with dynamic service offering and memory 512 + + # Validations: + # 1. VM creation should succeed + # 2. VM scaling operation should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + self.cleanup.append(self.account) + + Resources.updateLimit(self.apiclient, + resourcetype=9, + max=256, + account=self.account.name, + domainid=self.account.domainid) + + # Create dynamic service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_dynamic) + + # Deploy VM with dynamic service offering + try: + virtualMachine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=256) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Scale VM with same dynamic offering + try: + virtualMachine.scale(self.apiclient, serviceOfferingId=serviceOffering_dynamic.id, + customcpunumber=4, customcpuspeed=512, custommemory=512) + self.fail("Scaling virtual machine with cpu number more than \ + allowed limit (of account) succeded, should have failed") + except Exception as e: + self.debug("Failure while changing service offering as expected: %s" % e) + + return + +@ddt +class TestAffinityGroup(cloudstackTestCase): + """Test affinity group working with VMs created with dynamic offering + """ + + @classmethod + def setUpClass(cls): + cloudstackTestClient = super(TestAffinityGroup,cls).getClsTestClient() + cls.api_client = cloudstackTestClient.getApiClient() + + # Fill services from the external config file + cls.services = cloudstackTestClient.getConfigParser().parsedDict + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.mode = str(cls.zone.networktype).lower() + 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 + cls._cleanup = [] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup_co = [] + self.cleanup = [] + return + + def tearDown(self): + try: + # Clean up compute offerings + cleanup_resources(self.apiclient, self.cleanup) + + # Clean up compute offerings + cleanup_resources(self.apiclient, self.cleanup_co) + + self.cleanup_co[:] = [] + self.cleanup[:] = [] + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @data(ADMIN_ACCOUNT, USER_ACCOUNT) + @attr(tags=["basic","advanced"]) + def test_deploy_VM_with_affinity_group(self, value): + """Test deploy VMs with affinity group and dynamic compute offering""" + + # Steps: + # 1. Create Account (admin/user) + # 2. Update max cpu limit of account to 2 + # 3. Create dynamic service offering + # 4. Deploy VM with dynamic service offering and cpu number 3 + + # Validations: + # 1. VM creation should fail + + isadmin=True + if value == USER_ACCOUNT: + isadmin=False + + # Create account and api client + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id, admin=isadmin) + self.cleanup.append(self.account) + + # Create dynamic service offerings + self.services["service_offering"]["cpunumber"] = "" + self.services["service_offering"]["cpuspeed"] = "" + self.services["service_offering"]["memory"] = "" + + serviceOffering_dynamic = ServiceOffering.create(self.apiclient, + self.services["service_offering"]) + + self.cleanup_co.append(serviceOffering_dynamic) + + self.services["host_anti_affinity"]["name"] = "aff_grp_" + random_gen(size=6) + affinityGroup = AffinityGroup.create(self.apiclient, self.services["host_anti_affinity"], + self.account.name, self.domain.id) + + # Deploy VM with dynamic service offering + try: + virtualMachine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128, + affinitygroupnames=[affinityGroup.name]) + except Exception as e: + self.fail("vm creation failed with error: %s" % e) + + otherHostsInCluster = Host.list(self.apiclient, virtualmachineid=virtualMachine.id) + if validateList(otherHostsInCluster)[0] == PASS: + try: + VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128, + affinitygroupnames=[affinityGroup.name]) + except Exception as e: + self.fail("vm creation failed with error: %s" % e) + + else: + try: + VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + serviceofferingid=serviceOffering_dynamic.id, + accountid=self.account.name,domainid=self.account.domainid, + customcpunumber=2, customcpuspeed=256, custommemory=128, + affinitygroupnames=[affinityGroup.name]) + self.fail("vm creation should have failed, it succeded") + except Exception as e: + self.debug("vm creation failed as expected with error: %s" % e) + + return diff --git a/test/integration/component/test_egress_fw_rules.py b/test/integration/component/test_egress_fw_rules.py index 8fa8a5ed26..8da37381bb 100644 --- a/test/integration/component/test_egress_fw_rules.py +++ b/test/integration/component/test_egress_fw_rules.py @@ -274,17 +274,19 @@ def exec_script_on_user_vm(self, script, exec_cmd_params, expected_result, negat self.debug("script: %s" % script+exec_cmd_params) self.debug("result: %s" % result) - if str(result).strip() == expected_result: + str_result = str(str(result).strip()) + str_expected_result = str(expected_result).strip() + if str_result == str_expected_result: exec_success = True if negative_test: self.assertEqual(exec_success, True, - "Script result is %s matching with %s" % (result, expected_result)) + "Script result is %s matching with %s" % (str_result, str_expected_result)) else: self.assertEqual(exec_success, True, - "Script result is %s is not matching with %s" % (result, expected_result)) + "Script result is %s is not matching with %s" % (str_result, str_expected_result)) except Exception as e: self.debug('Error=%s' % e) @@ -382,7 +384,7 @@ def tearDown(self): except Exception as e: self.fail("Warning! Cleanup failed: %s" % e) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_01_egress_fr1(self): """Test By-default the communication from guest n/w to public n/w is allowed. """ @@ -397,7 +399,7 @@ def test_01_egress_fr1(self): "['0']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_01_1_egress_fr1(self): """Test By-default the communication from guest n/w to public n/w is NOT allowed. """ @@ -413,7 +415,7 @@ def test_01_1_egress_fr1(self): negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_02_egress_fr2(self): """Test Allow Communication using Egress rule with CIDR + Port Range + Protocol. """ @@ -430,7 +432,7 @@ def test_02_egress_fr2(self): "['100']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_02_1_egress_fr2(self): """Test Allow Communication using Egress rule with CIDR + Port Range + Protocol. """ @@ -447,7 +449,7 @@ def test_02_1_egress_fr2(self): "['0']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_03_egress_fr3(self): """Test Communication blocked with network that is other than specified """ @@ -468,7 +470,7 @@ def test_03_egress_fr3(self): "[]", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_03_1_egress_fr3(self): """Test Communication blocked with network that is other than specified """ @@ -489,7 +491,7 @@ def test_03_1_egress_fr3(self): "['failed:']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_04_egress_fr4(self): """Test Create Egress rule and check the Firewall_Rules DB table """ @@ -526,7 +528,7 @@ def test_04_egress_fr4(self): "DB results not matching, expected: 1, found: %s" % qresultset[0][0]) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_04_1_egress_fr4(self): """Test Create Egress rule and check the Firewall_Rules DB table """ @@ -563,7 +565,7 @@ def test_04_1_egress_fr4(self): "DB results not matching, expected: 0, found: %s" % qresultset[0][0]) @unittest.skip("Skip") - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "NotRun"]) def test_05_egress_fr5(self): """Test Create Egress rule and check the IP tables """ @@ -582,7 +584,7 @@ def test_05_egress_fr5(self): @unittest.skip("Skip") - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "NotRun"]) def test_05_1_egress_fr5(self): """Test Create Egress rule and check the IP tables """ @@ -600,7 +602,7 @@ def test_05_1_egress_fr5(self): #TODO: Query VR for expected route rules. - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_06_egress_fr6(self): """Test Create Egress rule without CIDR """ @@ -616,7 +618,7 @@ def test_06_egress_fr6(self): "['100']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_06_1_egress_fr6(self): """Test Create Egress rule without CIDR """ @@ -632,7 +634,7 @@ def test_06_1_egress_fr6(self): "['0']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_07_egress_fr7(self): """Test Create Egress rule without End Port """ @@ -648,7 +650,7 @@ def test_07_egress_fr7(self): "['failed:']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_07_1_egress_fr7(self): """Test Create Egress rule without End Port """ @@ -665,7 +667,7 @@ def test_07_1_egress_fr7(self): negative_test=False) @unittest.skip("Skip") - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "NotRun"]) def test_08_egress_fr8(self): """Test Port Forwarding and Egress Conflict """ @@ -677,7 +679,7 @@ def test_08_egress_fr8(self): self.createEgressRule() @unittest.skip("Skip") - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "NotRun"]) def test_08_1_egress_fr8(self): """Test Port Forwarding and Egress Conflict """ @@ -689,7 +691,7 @@ def test_08_1_egress_fr8(self): self.createEgressRule() - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_09_egress_fr9(self): """Test Delete Egress rule """ @@ -713,7 +715,7 @@ def test_09_egress_fr9(self): "['0']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_09_1_egress_fr9(self): """Test Delete Egress rule """ @@ -738,7 +740,7 @@ def test_09_1_egress_fr9(self): negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_10_egress_fr10(self): """Test Invalid CIDR and Invalid Port ranges """ @@ -749,7 +751,7 @@ def test_10_egress_fr10(self): self.create_vm() self.assertRaises(Exception, self.createEgressRule, '10.2.2.0/24') - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_10_1_egress_fr10(self): """Test Invalid CIDR and Invalid Port ranges """ @@ -761,7 +763,7 @@ def test_10_1_egress_fr10(self): self.assertRaises(Exception, self.createEgressRule, '10.2.2.0/24') - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_11_egress_fr11(self): """Test Regression on Firewall + PF + LB + SNAT """ @@ -771,7 +773,7 @@ def test_11_egress_fr11(self): # 3. All should work fine. self.create_vm(pfrule=True) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_11_1_egress_fr11(self): """Test Regression on Firewall + PF + LB + SNAT """ @@ -781,7 +783,7 @@ def test_11_1_egress_fr11(self): # 3. All should work fine. self.create_vm(pfrule=True, egress_policy=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_12_egress_fr12(self): """Test Reboot Router """ @@ -798,7 +800,7 @@ def test_12_egress_fr12(self): "['100']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_12_1_egress_fr12(self): """Test Reboot Router """ @@ -815,7 +817,7 @@ def test_12_1_egress_fr12(self): "['0']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_13_egress_fr13(self): """Test Redundant Router : Master failover """ @@ -870,7 +872,7 @@ def test_13_egress_fr13(self): "['100']", negative_test=False) - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_13_1_egress_fr13(self): """Test Redundant Router : Master failover """ diff --git a/test/integration/component/test_explicit_dedication.py b/test/integration/component/test_explicit_dedication.py index 7aefc21a1f..c589c6ae74 100644 --- a/test/integration/component/test_explicit_dedication.py +++ b/test/integration/component/test_explicit_dedication.py @@ -152,7 +152,7 @@ def tearDown(self): # 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"]) + @attr(tags=["advanced", "basic", "multihosts", "explicitdedication", "selfservice"]) def test_01_deploy_vm_with_explicit_dedication(self): """Test explicit dedication is placing vms of an account on dedicated hosts. """ diff --git a/test/integration/component/test_haproxy.py b/test/integration/component/test_haproxy.py index f77e4ec61c..ceea50b7e2 100644 --- a/test/integration/component/test_haproxy.py +++ b/test/integration/component/test_haproxy.py @@ -694,7 +694,7 @@ def test_06_release_ip(self): listall=True) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_07_delete_account(self): """Test Delete account and check the router and its rules""" @@ -735,7 +735,7 @@ def test_07_delete_account(self): listall=True) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_08_create_policy_router_stopped(self): """Test verify create stickiness policy when router is stopped state""" @@ -768,7 +768,7 @@ def test_08_create_policy_router_stopped(self): self.validate_Stickiness_Policy(lb_rule, "LbCookie", self.public_ip.ipaddress.ipaddress) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_09_create_policy_router_destroy(self): """Test check the stickiness policy rules after destroying router""" @@ -799,7 +799,7 @@ def test_09_create_policy_router_destroy(self): return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_10_create_policy_enable_disable_vpn(self): """Test enable/disable the VPN after applying sticky policy rules""" @@ -830,7 +830,7 @@ def test_10_create_policy_enable_disable_vpn(self): self.validate_Stickiness_Policy(lb_rule, "LbCookie", self.public_ip.ipaddress.ipaddress) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_11_invalid_params(self): """Test verfify functionality syncronous and asyncronous validations""" diff --git a/test/integration/component/test_implicit_planner.py b/test/integration/component/test_implicit_planner.py index 2b656d9f2c..5124e70381 100644 --- a/test/integration/component/test_implicit_planner.py +++ b/test/integration/component/test_implicit_planner.py @@ -144,7 +144,7 @@ def tearDown(self): # be running on that host). It uses an implicit planner to deploy instances and the # instances of a new account should go to an host that doesn't have vms of any other # account. - @attr(tags = ["advanced", "basic", "multihosts", "implicitplanner"]) + @attr(tags=["advanced", "basic", "multihosts", "implicitplanner", "selfservice"]) def test_01_deploy_vm_with_implicit_planner(self): """Test implicit planner is placing vms of an account on implicitly dedicated hosts. """ diff --git a/test/integration/component/test_ip_reservation.py b/test/integration/component/test_ip_reservation.py old mode 100755 new mode 100644 index 224212f21d..46b4edb75b --- a/test/integration/component/test_ip_reservation.py +++ b/test/integration/component/test_ip_reservation.py @@ -15,134 +15,568 @@ # specific language governing permissions and limitations # under the License. """ Tests for IP reservation feature + + Test Plan: https://cwiki.apache.org/confluence/display/CLOUDSTACK/IP+Range+Reservation+within+a+Network+Test+Cases + + Issue Link: https://issues.apache.org/jira/browse/CLOUDSTACK-2266 + + Feature Specifications: https://cwiki.apache.org/confluence/display/CLOUDSTACK/FS+-+IP+Range+Reservation+within+a+Network """ -import marvin -from marvin.cloudstackTestCase import * -from marvin.cloudstackAPI import * -from marvin.cloudstackException import cloudstackAPIException -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.integration.lib.utils import (cleanup_resources, + validateList, + verifyRouterState) +from marvin.integration.lib.base import (Network, + Account, + ServiceOffering, + VirtualMachine, + Router, + NetworkOffering, + VpcOffering, + VPC) +from marvin.integration.lib.common import (get_domain, + get_zone, + get_template, + createEnabledNetworkOffering, + get_free_vlan, + wait_for_cleanup, + createNetworkRulesForVM) +from marvin.codes import (PASS, + NAT_RULE, + STATIC_NAT_RULE, + FAIL, + UNKNOWN, + FAULT, + MASTER) import netaddr +import random from nose.plugins.attrib import attr +from ddt import ddt, data -class Services(object): - """Test IP Reservation - """ - def __init__(self): - self.services = { - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - # Random characters are appended for unique - # username - "password": "password", - }, - "service_offering": { - "name": "Tiny Instance ", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 200, # in MHz - "memory": 256, # In MBs - }, - "isolated_network_offering": { - "name": 'Network offering for Isolated Network', - "displaytext": 'Network offering-DA services', - "guestiptype": 'Isolated', - "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', - "traffictype": 'GUEST', - "availability": 'Optional', - "serviceProviderList": { - "Dhcp": 'VirtualRouter', - "Dns": 'VirtualRouter', - "SourceNat": 'VirtualRouter', - "PortForwarding": 'VirtualRouter', - "Vpn": 'VirtualRouter', - "Firewall": 'VirtualRouter', - "Lb": 'VirtualRouter', - "UserData": 'VirtualRouter', - "StaticNat": 'VirtualRouter', - }, - }, - "isolated_persistent_network_offering": { - "name": 'Network offering for Isolated Network', - "displaytext": 'Network offering-DA services', - "guestiptype": 'Isolated', - "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', - "traffictype": 'GUEST', - "availability": 'Optional', - "ispersistent": 'True', - "serviceProviderList": { - "Dhcp": 'VirtualRouter', - "Dns": 'VirtualRouter', - "SourceNat": 'VirtualRouter', - "PortForwarding": 'VirtualRouter', - "Vpn": 'VirtualRouter', - "Firewall": 'VirtualRouter', - "Lb": 'VirtualRouter', - "UserData": 'VirtualRouter', - "StaticNat": 'VirtualRouter', - }, - }, - "isolated_network": { - "name": "Isolated Network", - "displaytext": "Isolated Network", - "netmask": "255.255.255.0", - "gateway": "10.1.1.1" - }, - # update CIDR according to netmask and gateway in isolated_network - "isolated_network_cidr": "10.1.1.0/24", - "virtual_machine": { - "displayname": "Test VM", - }, - "ostype": 'CentOS 5.3 (64-bit)', - # Cent OS 5.3 (64 bit) - "sleep": 90, - "timeout": 10, - "mode": 'advanced' - } +def createIsolatedNetwork(self, network_offering_id, gateway=None): + """Create isolated network with given network offering and gateway if provided + and return""" + try: + isolated_network = Network.create(self.apiclient, self.testData["isolated_network"], + networkofferingid=network_offering_id,accountid=self.account.name, + domainid=self.domain.id,zoneid=self.zone.id, + gateway=gateway, netmask='255.255.255.0' if gateway else None) + except Exception as e: + return [FAIL, e] + return [PASS, isolated_network] + +def matchNetworkGuestVmCIDR(self, networkid, guestvmcidr): + """List networks with given network id and check if the guestvmcidr matches + with the given cidr""" + + networks = Network.list(self.apiclient, id=networkid, listall=True) + self.assertEqual(validateList(networks)[0], PASS, "network list validation failed") + self.assertEqual(str(networks[0].cidr), guestvmcidr, "guestvmcidr of network %s \ + does not match with the given value %s" % (networks[0].cidr, guestvmcidr)) + return +def createVirtualMachine(self, network_id=None, ip_address=None): + """Create and return virtual machine within network and ipaddress""" + virtual_machine = VirtualMachine.create(self.apiclient, + self.testData["virtual_machine"], + networkids=network_id, + serviceofferingid=self.service_offering.id, + accountid=self.account.name, + domainid=self.domain.id, + ipaddress=ip_address) + return virtual_machine + +def CreateEnabledNetworkOffering(apiclient, networkServices): + """Create network offering of given test data and enable it""" + + result = createEnabledNetworkOffering(apiclient, networkServices) + assert result[0] == PASS, "Network offering creation/enabling failed due to %s" % result[2] + return result[1] + +@ddt class TestIpReservation(cloudstackTestCase): """Test IP Range Reservation with a Network """ @classmethod def setUpClass(cls): - cls.api_client = super(TestIpReservation, cls).getClsTestClient().getApiClient() - cls.services = Services().services + cloudstackTestClient = super(TestIpReservation, cls).getClsTestClient() + cls.api_client = cloudstackTestClient.getApiClient() + # Fill test data from the external config file + cls.testData = cloudstackTestClient.getConfigParser().parsedDict # Get Zone, Domain and templates - cls.domain = get_domain(cls.api_client, cls.services) - cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain(cls.api_client, cls.testData) + cls.zone = get_zone(cls.api_client, cls.testData) cls.template = get_template( cls.api_client, cls.zone.id, - cls.services["ostype"] + cls.testData["ostype"] ) - cls.services["domainid"] = cls.domain.id - cls.services["zoneid"] = cls.zone.id - cls.account = Account.create( + cls.testData["domainid"] = cls.domain.id + cls.testData["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["template"] = cls.template.id + cls._cleanup = [] + try: + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.testData["service_offering"] + ) + cls._cleanup.append(cls.service_offering) + cls.isolated_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["isolated_network_offering"]) + cls._cleanup.append(cls.isolated_network_offering) + cls.isolated_persistent_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["nw_off_isolated_persistent"]) + cls._cleanup.append(cls.isolated_persistent_network_offering) + cls.isolated_network_offering_RVR = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["nw_off_isolated_RVR"]) + cls._cleanup.append(cls.isolated_network_offering_RVR) + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Failure in setUpClass: %s" % e) + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + try: + self.account = Account.create(self.apiclient, self.testData["account"], + domainid=self.domain.id) + self.cleanup.append(self.account) + except Exception as e: + self.skipTest("Failed to create account: %s" % e) + return + + def tearDown(self): + try: + # Clean up, terminate the resources created + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags=["advanced"]) + def test_vm_create_after_reservation(self): + """ Test creating VM in network after IP reservation + # steps + # 1. Create vm in isolated network (LB through VR or Netscaler) with ip in guestvmcidr + # 2. Update guestvmcidr + # 3. Create another VM + # validation + # 1. Guest vm cidr should be successfully updated with correct value + # 2. Existing guest vm ip should not be changed after reservation + # 3. Newly created VM should get ip in guestvmcidr""" + + networkOffering = self.isolated_network_offering + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, networkOffering.id, gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network = resultSet[1] + guest_vm_cidr = subnet +".0/29" + + try: + virtual_machine_1 = createVirtualMachine(self, network_id=isolated_network.id, + ip_address = subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, + id=virtual_machine_1.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_1.ipaddress, + "VM IP should not change after reservation") + try: + virtual_machine_2 = createVirtualMachine(self, network_id=isolated_network.id) + if netaddr.IPAddress(virtual_machine_2.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + return + + @attr(tags=["advanced"]) + def test_vm_create_outside_cidr_after_reservation(self): + """ Test create VM outside the range of reserved IPs + # steps + # 1. update guestvmcidr of persistent isolated network (LB through VR or + # Netscaler + # 2. create another VM with ip outside guestvmcidr + """ + # validation + # 1. guest vm cidr should be successfully updated with correct value + # 2 newly created VM should not be created and result in exception + + networkOffering = self.isolated_persistent_network_offering + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, networkOffering.id, gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network = resultSet[1] + guest_vm_cidr = subnet+".0/29" + + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + try: + createVirtualMachine(self, network_id=self.isolated_network.id, + ip_address=subnet+".9") + self.fail("vm should not be created ") + except Exception as e: + self.debug("exception as IP is outside of guestvmcidr %s" % e) + return + + @attr(tags=["advanced"]) + def test_update_cidr_multiple_vms_not_all_inclusive(self): + """ Test reserve IP range such that one of the VM is not included + # steps + # 1. Create two vms in isolated network + # 2. Update guestvmcidr of network such that only one of the ipaddress of vms + # is in the given range + # validation + # 1. Network updation with this new range should fail""" + + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_network_offering.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network = resultSet[1] + guest_vm_cidr = subnet+".0/29" + + try: + createVirtualMachine(self, network_id=isolated_network.id, + ip_address=subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + try: + createVirtualMachine(self, network_id=isolated_network.id, + ip_address=subnet+".9") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + with self.assertRaises(Exception): + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + return + + @attr(tags=["advanced"]) + def test_update_cidr_single_vm_not_inclusive(self): + """ Test reserving IP range in network such that existing VM is outside the range + # steps + # 1. Create vm in isolated network + # 2. Update guestvmcidr of network such that ip address of vm + # is outside the given range + # + # validation + # 1. Network updation with this new range should fail""" + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_network_offering.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network = resultSet[1] + guest_vm_cidr = subnet+".0/29" + + try: + createVirtualMachine(self, network_id=isolated_network.id, + ip_address=subnet+".9") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + with self.assertRaises(Exception): + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + return + + @data(NAT_RULE, STATIC_NAT_RULE) + @attr(tags=["advanced"]) + def test_nat_rules(self, value): + """ Test NAT rules working with IP reservation + # steps + # 1. Create vm in persistent isolated network with ip in guestvmcidr + # 2. Create NAT/static NAT rule for this VM + # 3. Update guestvmcidr + # 4. Create another VM and create network rules for this vm too + # + # validation + # 1. Guest vm cidr should be successfully updated with correct value + # 2. Existing guest vm ip should not be changed after reservation + # 3. Newly created VM should get ip in guestvmcidr + # 4. The network rules should be working""" + + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_network_offering.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network = resultSet[1] + guest_vm_cidr = subnet+".0/29" + + try: + virtual_machine_1 = createVirtualMachine(self, network_id=isolated_network.id, + ip_address=subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + result = createNetworkRulesForVM(self.apiclient, virtual_machine_1,value, + self.account, self.testData) + if result[0] == FAIL: + self.fail("Failed to create network rules for VM: %s" % result[1]) + else: + ipaddress_1 = result[1] + virtual_machine_1.get_ssh_client(ipaddress=ipaddress_1.ipaddress.ipaddress) + + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, id=virtual_machine_1.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_1.ipaddress, + "VM IP should not change after reservation") + try: + virtual_machine_2 = createVirtualMachine(self, network_id=isolated_network.id) + if netaddr.IPAddress(virtual_machine_2.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + + result = createNetworkRulesForVM(self.apiclient, virtual_machine_2, value, + self.account, self.testData) + if result[0] == FAIL: + self.fail("Failed to create network rules for VM: %s" % result[1]) + else: + ipaddress_2 = result[1] + virtual_machine_2.get_ssh_client(ipaddress=ipaddress_2.ipaddress.ipaddress) + return + + @unittest.skip("Skip - WIP") + @attr(tags=["advanced"]) + def test_RVR_network(self): + """ Test IP reservation in network with RVR + # steps + # 1. create vm in isolated network with RVR and ip in guestvmcidr + # 2. update guestvmcidr + # 3. List routers and stop the master router, wait till backup router comes up + # 4. create another VM + # + # validation + # 1. Guest vm cidr should be successfully updated with correct value + # 2. Existing guest vm ip should not be changed after reservation + # 3. Newly created VM should get ip in guestvmcidr + # 4. Verify that the network has two routers associated with it + # 5. Backup router should come up when master router is stopped""" + + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_network_offering_RVR.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network_RVR= resultSet[1] + guest_vm_cidr = subnet+".0/29" + + try: + virtual_machine_1 = createVirtualMachine(self, network_id=isolated_network_RVR.id, + ip_address=subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + isolated_network_RVR.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network_RVR.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, + id=virtual_machine_1.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_1.ipaddress, + "VM IP should not change after reservation") + + self.debug("Listing routers for network: %s" % isolated_network_RVR.name) + routers = Router.list(self.apiclient, networkid=isolated_network_RVR.id, listall=True) + self.assertEqual(validateList(routers)[0], PASS, "Routers list validation failed") + self.assertEqual(len(routers), 2, "Length of the list router should be 2 (Backup & master)") + + if routers[0].redundantstate == MASTER: + master_router = routers[0] + backup_router = routers[1] + else: + master_router = routers[1] + backup_router = routers[0] + + self.debug("Stopping router ID: %s" % master_router.id) + + try: + Router.stop(self.apiclient, id=master_router.id) + except Exception as e: + self.fail("Failed to stop master router due to error %s" % e) + + # wait for VR to update state + wait_for_cleanup(self.apiclient, ["router.check.interval"]) + + result = verifyRouterState(master_router.id, [UNKNOWN,FAULT]) + if result[0] == FAIL: + self.fail(result[1]) + result = verifyRouterState(backup_router.id, [MASTER]) + if result[0] == FAIL: + self.fail(result[1]) + + try: + virtual_machine_2 = createVirtualMachine(self, network_id=isolated_network_RVR.id) + if netaddr.IPAddress(virtual_machine_2.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + return + + @attr(tags=["advanced"]) + def test_ip_reservation_in_multiple_networks_same_account(self): + """ Test IP reservation in multiple networks created in same account + # steps + # 1. Create two isolated networks with user defined cidr in same account + # Test below conditions for both the networks in the account + # 2. Create vm in persistent isolated network with ip in guestvmcidr + # 3. Update guestvmcidr + # 4. Create another VM + # + # validation + # 1. Guest vm cidr should be successfully updated with correct value + # 2. Existing guest vm ip should not be changed after reservation + # 3. Newly created VM should get ip in guestvmcidr""" + + account_1 = Account.create(self.apiclient, self.testData["account"], + domainid=self.domain.id) + self.cleanup.append(account_1) + + random_subnet = str(random.randrange(1,254)) + gateway = "10.1." + random_subnet +".1" + isolated_network_1 = Network.create(self.apiclient, self.testData["isolated_network"], + networkofferingid=self.isolated_network_offering.id,accountid=account_1.name, + domainid=self.domain.id,zoneid=self.zone.id, + gateway=gateway, netmask='255.255.255.0') + guest_vm_cidr = "10.1."+random_subnet+".0/29" + + try: + virtual_machine_1 = VirtualMachine.create(self.apiclient, self.testData["virtual_machine"], + networkids=isolated_network_1.id, serviceofferingid=self.service_offering.id, + accountid=account_1.name, domainid=self.domain.id, + ipaddress="10.1."+random_subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + isolated_network_1.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network_1.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, + id=virtual_machine_1.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_1.ipaddress, + "VM IP should not change after reservation") + + try: + virtual_machine_2 = VirtualMachine.create(self.apiclient, self.testData["virtual_machine"], + networkids=isolated_network_1.id, serviceofferingid=self.service_offering.id, + accountid=account_1.name, domainid=self.domain.id) + if netaddr.IPAddress(virtual_machine_2.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + + random_subnet = str(random.randrange(1,254)) + gateway = "10.1." + random_subnet +".1" + isolated_network_2 = Network.create(self.apiclient, self.testData["isolated_network"], + networkofferingid=self.isolated_network_offering.id,accountid=account_1.name, + domainid=self.domain.id,zoneid=self.zone.id, + gateway=gateway, netmask='255.255.255.0') + guest_vm_cidr = "10.1."+random_subnet+".0/29" + + try: + virtual_machine_3 = VirtualMachine.create(self.apiclient, self.testData["virtual_machine"], + networkids=isolated_network_2.id, serviceofferingid=self.service_offering.id, + accountid=account_1.name, domainid=self.domain.id, + ipaddress="10.1."+random_subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + isolated_network_2.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network_2.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, + id=virtual_machine_3.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_3.ipaddress, + "VM IP should not change after reservation") + + try: + virtual_machine_4 = VirtualMachine.create(self.apiclient, self.testData["virtual_machine"], + networkids=isolated_network_2.id, serviceofferingid=self.service_offering.id, + accountid=account_1.name, domainid=self.domain.id) + if netaddr.IPAddress(virtual_machine_4.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + return + +@ddt +class TestRestartNetwork(cloudstackTestCase): + """Test Restart Network + """ + @classmethod + def setUpClass(cls): + cloudstackTestClient = super(TestRestartNetwork, cls).getClsTestClient() + cls.api_client = cloudstackTestClient.getApiClient() + # Fill test data from the external config file + cls.testData = cloudstackTestClient.getConfigParser().parsedDict + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.testData) + cls.zone = get_zone(cls.api_client, cls.testData) + cls.template = get_template( cls.api_client, - cls.services["account"], - domainid=cls.domain.id + cls.zone.id, + cls.testData["ostype"] ) - cls.services["account"] = cls.account.name - cls.services["virtual_machine"]["zoneid"] = cls.zone.id - cls.services["virtual_machine"]["template"] = cls.template.id - cls.service_offering = ServiceOffering.create( + cls.testData["domainid"] = cls.domain.id + cls.testData["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["template"] = cls.template.id + cls._cleanup = [] + try: + cls.service_offering = ServiceOffering.create( cls.api_client, - cls.services["service_offering"] + cls.testData["service_offering"] ) - cls.isolated_network_offering = cls.create_isolated_network_offering("isolated_network_offering") - cls.isolated_persistent_network_offering = cls.create_isolated_network_offering("isolated_persistent_network_offering") - cls.isolated_network = cls.create_isolated_network(cls.isolated_network_offering.id) - cls.isolated_persistent_network = cls.create_isolated_network(cls.isolated_persistent_network_offering.id) - # network will be deleted as part of account cleanup - cls._cleanup = [ - cls.account, cls.service_offering, cls.isolated_network_offering, cls.isolated_persistent_network_offering, - ] + cls._cleanup.append(cls.service_offering) + cls.isolated_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["isolated_network_offering"]) + cls._cleanup.append(cls.isolated_network_offering) + cls.isolated_persistent_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["nw_off_isolated_persistent"]) + cls._cleanup.append(cls.isolated_persistent_network_offering) + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Failure in setUpClass: %s" % e) return @classmethod @@ -154,44 +588,461 @@ def tearDownClass(cls): raise Exception("Warning: Exception during cleanup : %s" % e) return + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + try: + self.account = Account.create(self.apiclient, self.testData["account"], + domainid=self.domain.id) + self.cleanup.append(self.account) + except Exception as e: + self.skipTest("Failed to create account: %s" % e) + return + + def tearDown(self): + try: + # Clean up, terminate the resources created + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @data(True, False) + @attr(tags=["advanced"]) + def test_restart_network_with_cleanup(self, value): + """ Test IP reservation rules with network restart operation + # steps + # 1. Create vm in isolated network with ip in guestvmcidr + # 2. Update guestvmcidr + # 3. Restart network with cleanup True/False + # 4. Deploy another VM in the network + # + # validation + # 1. Guest vm cidr should be successfully updated with correct value + # 2. Existing guest vm ip should not be changed after reservation + # 3. Network should be restarted successfully with and without cleanup + # 4. Newly created VM should get ip in guestvmcidr""" + + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_network_offering.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network= resultSet[1] + guest_vm_cidr = subnet+".0/29" + + try: + virtual_machine_1 = createVirtualMachine(self, network_id=isolated_network.id, + ip_address=subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, + id=virtual_machine_1.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_1.ipaddress, + "VM IP should not change after reservation") + + #Restart Network + isolated_network.restart(self.apiclient, cleanup=value) + + try: + virtual_machine_2 = createVirtualMachine(self, network_id=isolated_network.id) + if netaddr.IPAddress(virtual_machine_2.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + return + +@ddt +class TestUpdateIPReservation(cloudstackTestCase): + """Test Updating IP reservation multiple times + """ @classmethod - def create_isolated_network_offering(cls, network_offering): - isolated_network_offering = NetworkOffering.create( - cls.api_client, - cls.services[network_offering], - conservemode=False - ) - # Update network offering state from disabled to enabled. - network_offering_update_response = NetworkOffering.update( - isolated_network_offering, - cls.api_client, - id=isolated_network_offering.id, - state="enabled" - ) - return isolated_network_offering + def setUpClass(cls): + cloudstackTestClient = super(TestUpdateIPReservation, cls).getClsTestClient() + cls.api_client = cloudstackTestClient.getApiClient() + # Fill test data from the external config file + cls.testData = cloudstackTestClient.getConfigParser().parsedDict + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.testData) + cls.zone = get_zone(cls.api_client, cls.testData) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.testData["ostype"] + ) + cls.testData["domainid"] = cls.domain.id + cls.testData["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["template"] = cls.template.id + cls._cleanup = [] + try: + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.testData["service_offering"] + ) + cls._cleanup.append(cls.service_offering) + cls.isolated_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["isolated_network_offering"]) + cls._cleanup.append(cls.isolated_network_offering) + cls.isolated_persistent_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["nw_off_isolated_persistent"]) + cls._cleanup.append(cls.isolated_persistent_network_offering) + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Failure in setUpClass: %s" % e) + return @classmethod - def create_isolated_network(cls, network_offering_id): - isolated_network = Network.create( - cls.api_client, - cls.services["isolated_network"], - networkofferingid=network_offering_id, - accountid=cls.account.name, - domainid=cls.domain.id, - zoneid=cls.zone.id - ) - cls.debug("isolated network is created: " + isolated_network.id) - return isolated_network + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + try: + self.account = Account.create(self.apiclient, self.testData["account"], + domainid=self.domain.id) + self.cleanup.append(self.account) + except Exception as e: + self.skipTest("Failed to create account: %s" % e) + return + + def tearDown(self): + try: + # Clean up, terminate the resources created + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @data("existingVmInclusive", "existingVmExclusive") + @attr(tags=["advanced"]) + def test_update_network_guestvmcidr(self, value): + """ Test updating guest vm cidr of the network after + VMs are already deployed in previous guest VM cidr + + # steps + # 1. Create isolated network with user defined cidr + # 2. Deploy VM in the network + # 3. Try to update the guestvmcidr of the network with VM ip in the guestvmcidr and + # deploy another VM + # 4. Try to update the guestvmcidr of the network with VM ip outside the guestvmcidr + # + # validation + # 1. When vm IP is in the guestvmcidr, updation should be successful and + # new VM should get IP from this range + # 2. When VM IP is outside the guestvmcidr, updation should be unsuccessful""" + + random_subnet = str(random.randrange(1,254)) + gateway = "10.1." + random_subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_network_offering.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network= resultSet[1] + guest_vm_cidr = "10.1."+random_subnet+".0/29" + + try: + virtual_machine_1 = createVirtualMachine(self, network_id=isolated_network.id, + ip_address=u"10.1."+random_subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, + id=virtual_machine_1.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_1.ipaddress, + "VM IP should not change after reservation") + try: + virtual_machine_2 = createVirtualMachine(self, network_id=isolated_network.id) + if netaddr.IPAddress(virtual_machine_2.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + + # Update guest vm cidr of network again + if value == "existingVmExclusive": + guest_vm_cidr = "10.1."+random_subnet+".10/29" + + try: + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + self.fail("Network updation should fail") + except Exception as e: + self.debug("Failed to update guest VM cidr of network: %s" % e) + elif value == "existingVmInclusive": + guest_vm_cidr = "10.1."+random_subnet+".0/28" + + try: + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + except Exception as e: + self.fail("Failed to update guest VM cidr of network: %s" % e) + + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + + try: + virtual_machine_3 = createVirtualMachine(self, network_id=isolated_network.id) + if netaddr.IPAddress(virtual_machine_3.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + return + +@ddt +class TestRouterOperations(cloudstackTestCase): + """Test Router operations of network with IP reservation + """ + @classmethod + def setUpClass(cls): + cloudstackTestClient = super(TestRouterOperations, cls).getClsTestClient() + cls.api_client = cloudstackTestClient.getApiClient() + # Fill test data from the external config file + cls.testData = cloudstackTestClient.getConfigParser().parsedDict + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.testData) + cls.zone = get_zone(cls.api_client, cls.testData) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.testData["ostype"] + ) + cls.testData["domainid"] = cls.domain.id + cls.testData["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["template"] = cls.template.id + cls._cleanup = [] + try: + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.testData["service_offering"] + ) + cls._cleanup.append(cls.service_offering) + cls.isolated_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["isolated_network_offering"]) + cls._cleanup.append(cls.isolated_network_offering) + cls.isolated_persistent_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["nw_off_isolated_persistent"]) + cls._cleanup.append(cls.isolated_persistent_network_offering) + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Failure in setUpClass: %s" % e) + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + try: + self.account = Account.create(self.apiclient, self.testData["account"], + domainid=self.domain.id) + self.cleanup.append(self.account) + except Exception as e: + self.skipTest("Failed to create account: %s" % e) + return + + def tearDown(self): + try: + # Clean up, terminate the resources created + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags=["advanced"]) + def test_reservation_after_router_restart(self): + """ Test IP reservation working before and after router is restarted + # steps + # 1. Update guestvmcidr of persistent isolated network + # 2. Reboot router + # + # validation + # 1. Guest vm cidr should be successfully updated with correct value + # 2. Network cidr should remain same after router restart""" + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_persistent_network_offering.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network= resultSet[1] + guest_vm_cidr = subnet+".0/29" + + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + + routers = Router.list(self.apiclient, + networkid=isolated_network.id, + listall=True) + self.assertEqual(validateList(routers)[0], PASS, "routers list validation failed") + if not routers: + self.fail("Router list should not be empty") + + Router.reboot(self.apiclient, routers[0].id) + networks = Network.list(self.apiclient, id=isolated_network.id) + self.assertEqual(validateList(networks)[0], PASS, "networks list validation failed") + self.assertEqual(networks[0].cidr, guest_vm_cidr, "guestvmcidr should match after router reboot") + return + + @attr(tags=["advanced"]) + def test_destroy_recreate_router(self): + """ Test IP reservation working after destroying and recreating router + # steps + # 1. Create isolated network and deploy VM in it and update network with + # guestvmcidr + # 2. List the router associated with network and destroy the router + # 3. Restart the network + # 3. Deploy another VM in the network + # + # validation + # 1. Guest vm cidr should be successfully updated with correct value + # 2. existing guest vm ip should not be changed after reservation + # 3. Router should be destroyed and recreated when network is restarted + # 4. New VM should be deployed in the guestvmcidr""" + + subnet = "10.1."+str(random.randrange(1,254)) + gateway = subnet +".1" + resultSet = createIsolatedNetwork(self, self.isolated_network_offering.id, + gateway=gateway) + if resultSet[0] == FAIL: + self.fail("Failed to create isolated network") + else: + isolated_network= resultSet[1] + guest_vm_cidr = subnet+".0/29" + + try: + virtual_machine_1 = createVirtualMachine(self, network_id=isolated_network.id, + ip_address=subnet+".3") + except Exception as e: + self.fail("VM creation failed: %s" % e) + + isolated_network.update(self.apiclient, guestvmcidr=guest_vm_cidr) + matchNetworkGuestVmCIDR(self, isolated_network.id, guest_vm_cidr) + vms = VirtualMachine.list(self.apiclient, + id=virtual_machine_1.id) + self.assertEqual(validateList(vms)[0], PASS, "vm list validation failed") + self.assertEqual(vms[0].nic[0].ipaddress, + virtual_machine_1.ipaddress, + "VM IP should not change after reservation") + + # List router and destroy it + routers = Router.list(self.apiclient, networkid=isolated_network.id, listall=True) + self.assertEqual(validateList(routers)[0], PASS, "Routers list validation failed") + + # Destroy Router + result = Router.destroy(self.apiclient, id=routers[0].id) + if result[0] == FAIL: + self.fail("Failed to destroy router: %s" % result[2]) + + #Restart Network + isolated_network.restart(self.apiclient) + + try: + virtual_machine_2 = createVirtualMachine(self, network_id=isolated_network.id) + if netaddr.IPAddress(virtual_machine_2.ipaddress) not in netaddr.IPNetwork(guest_vm_cidr): + self.fail("Newly created VM doesn't get IP from reserverd CIDR") + except Exception as e: + self.fail("VM creation failed, cannot validate the condition: %s" % e) + return + +@ddt +class TestFailureScnarios(cloudstackTestCase): + """Test failure scenarios related to IP reservation in network + """ + @classmethod + def setUpClass(cls): + cloudstackTestClient = super(TestFailureScnarios, cls).getClsTestClient() + cls.api_client = cloudstackTestClient.getApiClient() + # Fill test data from the external config file + cls.testData = cloudstackTestClient.getConfigParser().parsedDict + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.testData) + cls.zone = get_zone(cls.api_client, cls.testData) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.testData["ostype"] + ) + cls.testData["domainid"] = cls.domain.id + cls.testData["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["zoneid"] = cls.zone.id + cls.testData["virtual_machine"]["template"] = cls.template.id + cls._cleanup = [] + try: + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.testData["service_offering"] + ) + cls._cleanup.append(cls.service_offering) + cls.isolated_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["isolated_network_offering"]) + cls._cleanup.append(cls.isolated_network_offering) + cls.isolated_persistent_network_offering = CreateEnabledNetworkOffering(cls.api_client, + cls.testData["nw_off_isolated_persistent"]) + cls._cleanup.append(cls.isolated_persistent_network_offering) + + cls.testData["shared_network_offering"]["specifyVlan"] = "True" + cls.testData["shared_network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + cls.shared_network_offering = NetworkOffering.create(cls.api_client, + cls.testData["shared_network_offering"], + conservemode=False) + cls._cleanup.append(cls.shared_network_offering) + + #Update network offering state from disabled to enabled. + NetworkOffering.update(cls.shared_network_offering,cls.api_client,state="enabled") + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Failure in setUpClass: %s" % e) + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return def setUp(self): self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() - self.cleanup = [ ] - update_response = Network.update(self.isolated_persistent_network, self.apiclient, id=self.isolated_persistent_network.id, guestvmcidr=self.services["isolated_network_cidr"]) - if self.services["isolated_network_cidr"] <> update_response.cidr: - raise Exception("problem in updating cidr for test setup") + self.cleanup = [] + try: + self.account = Account.create(self.apiclient, self.testData["account"], + domainid=self.domain.id) + self.cleanup.append(self.account) + except Exception as e: + self.skipTest("Failed to create account: %s" % e) return def tearDown(self): @@ -215,7 +1066,7 @@ def create_virtual_machine(self, network_id=None, ip_address=None): self.cleanup.append(virtual_machine) return virtual_machine - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_network_not_implemented(self): # steps # 1. update guestvmcidr of isolated network (non persistent) @@ -228,7 +1079,7 @@ def test_network_not_implemented(self): except Exception as e: self.debug("Network Update of guest VM CIDR should fail as there is no VM deployed in network") - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_vm_create_after_reservation(self): # steps # 1. create vm in persistent isolated network with ip in guestvmcidr @@ -263,7 +1114,7 @@ def test_vm_create_after_reservation(self): except Exception as e: self.skipTest("VM creation fails, cannot validate the condition") - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_reservation_after_router_restart(self): # steps # 1. update guestvmcidr of persistent isolated network @@ -297,7 +1148,7 @@ def test_reservation_after_router_restart(self): ) self.assertEqual(networks[0].cidr, guest_vm_cidr, "guestvmcidr should match after router reboot") - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_vm_create_outside_cidr_after_reservation(self): # steps # 1. update guestvmcidr of persistent isolated network diff --git a/test/integration/component/test_ldap.py b/test/integration/component/test_ldap.py index d9e7c351cd..965ff36bef 100644 --- a/test/integration/component/test_ldap.py +++ b/test/integration/component/test_ldap.py @@ -128,7 +128,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_01_addLdapConfiguration(self): """ This test configures LDAP and attempts to authenticate as a user. diff --git a/test/integration/component/test_memory_limits.py b/test/integration/component/test_memory_limits.py index 231307f693..020f89b575 100644 --- a/test/integration/component/test_memory_limits.py +++ b/test/integration/component/test_memory_limits.py @@ -176,7 +176,7 @@ def createInstance(self, service_off, networks=None, api_client=None): except Exception as e: self.fail("Failed to deploy an instance: %s" % e) - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_stop_start_instance(self): """Test Deploy VM with specified RAM & verify the usage""" @@ -228,7 +228,7 @@ def test_01_stop_start_instance(self): "Resource count should be same after stopping the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_migrate_instance(self): """Test Deploy VM with specified RAM & verify the usage""" @@ -269,7 +269,7 @@ def test_02_migrate_instance(self): "Resource count should be same after stopping the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_delete_instance(self): """Test Deploy VM with specified GB RAM & verify the usage""" @@ -308,7 +308,7 @@ def test_03_delete_instance(self): self.assertEqual(resource_count_after_delete, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=9))#RAM return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_04_deploy_multiple_vm(self): """Test Deploy multiple VM with specified RAM & verify the usage""" @@ -479,7 +479,7 @@ def setupAccounts(self): return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_stop_start_instance(self): """Test Deploy VM with 5 GB memory & verify the usage""" @@ -551,7 +551,7 @@ def test_01_stop_start_instance(self): "Resource count should be same after starting the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_migrate_instance(self): """Test Deploy VM with specified memory & verify the usage""" @@ -611,7 +611,7 @@ def test_02_migrate_instance(self): "Resource count should be same after starting the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_delete_instance(self): """Test Deploy VM with specified RAM & verify the usage""" diff --git a/test/integration/component/test_mm_domain_limits.py b/test/integration/component/test_mm_domain_limits.py index a2b7395cd1..0a8e98b381 100644 --- a/test/integration/component/test_mm_domain_limits.py +++ b/test/integration/component/test_mm_domain_limits.py @@ -209,7 +209,7 @@ def setupAccounts(self): domainid=self.child_do_admin_2.domainid) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_change_service_offering(self): """Test Deploy VM with specified RAM & verify the usage""" @@ -348,7 +348,7 @@ def test_01_change_service_offering(self): return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_migrate_vm(self): """Test Deploy VM with specified RAM & verify the usage""" @@ -409,7 +409,7 @@ def test_02_migrate_vm(self): "Resource count should be same after migrating the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_delete_vm(self): """Test Deploy VM with specified RAM & verify the usage""" @@ -468,7 +468,7 @@ def test_03_delete_vm(self): self.assertEqual(resource_count_after_delete, 0 , "Resource count for %s should be 0" % get_resource_type(resource_id=9))#RAM return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_04_deploy_multiple_vm(self): """Test Deploy multiple VM with specified RAM & verify the usage""" @@ -682,7 +682,7 @@ def setupAccounts(self): } return users - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_multiple_child_domains(self): """Test memory limits with multiple child domains""" diff --git a/test/integration/component/test_mm_max_limits.py b/test/integration/component/test_mm_max_limits.py index e10c119f07..52ff98e1bd 100644 --- a/test/integration/component/test_mm_max_limits.py +++ b/test/integration/component/test_mm_max_limits.py @@ -239,7 +239,7 @@ def setupAccounts(self, account_limit=2, domain_limit=2, project_limit=2): (responses.domain, responses.domainid, responses.max)) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_deploy_vm_domain_limit_reached(self): """Test Try to deploy VM with admin account where account has not used the resources but @ domain they are not available""" @@ -266,7 +266,7 @@ def test_01_deploy_vm_domain_limit_reached(self): service_off=self.service_offering, api_client=api_client) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_02_deploy_vm_account_limit_reached(self): """Test Try to deploy VM with admin account where account has used the resources but @ domain they are available""" @@ -296,7 +296,7 @@ def test_02_deploy_vm_account_limit_reached(self): service_off=self.service_offering, api_client=api_client) return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_deploy_vm_project_limit_reached(self): """Test TTry to deploy VM with admin account where account has not used the resources but @ project they are not available""" @@ -320,7 +320,7 @@ def test_03_deploy_vm_project_limit_reached(self): service_off=self.service_offering, api_client=api_client) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_04_deployVm__account_limit_reached(self): """Test Try to deploy VM with admin account where account has used the resources but @ project they are available""" diff --git a/test/integration/component/test_mm_project_limits.py b/test/integration/component/test_mm_project_limits.py index 29a3b54972..00c0ab4550 100644 --- a/test/integration/component/test_mm_project_limits.py +++ b/test/integration/component/test_mm_project_limits.py @@ -216,7 +216,7 @@ def setupProjectAccounts(self): "Check project name from list response") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_01_project_vmlifecycle_start_stop_instance(self): # Validate the following @@ -273,7 +273,7 @@ def test_01_project_vmlifecycle_start_stop_instance(self): "Resource count should be same after starting the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "provisioning"]) def test_02_project_vmlifecycle_migrate_instance(self): # Validate the following @@ -314,7 +314,7 @@ def test_02_project_vmlifecycle_migrate_instance(self): "Resource count should be same after migrating the instance") return - @attr(tags=["advanced", "advancedns","simulator"]) + @attr(tags=["advanced", "advancedns","simulator", "selfservice"]) def test_03_project_vmlifecycle_delete_instance(self): # Validate the following diff --git a/test/integration/component/test_netscaler_configs.py b/test/integration/component/test_netscaler_configs.py index 98c47485e3..98613fecc5 100644 --- a/test/integration/component/test_netscaler_configs.py +++ b/test/integration/component/test_netscaler_configs.py @@ -192,7 +192,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advancedns"]) + @attr(tags=["advancedns", "provisioning"]) def test_add_netscaler_device(self): """Test add netscaler device """ @@ -318,7 +318,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advancedns"]) + @attr(tags=["advancedns", "provisioning"]) def test_invalid_cred(self): """Test add netscaler device with invalid credential """ @@ -387,7 +387,7 @@ def test_invalid_cred(self): ) return - @attr(tags = ["advancedns"]) + @attr(tags=["advancedns", "provisioning"]) def test_invalid_public_interface(self): """Test add netscaler device with invalid public interface """ @@ -454,7 +454,7 @@ def test_invalid_public_interface(self): ) return - @attr(tags = ["advancedns"]) + @attr(tags=["advancedns", "provisioning"]) def test_invalid_private_interface(self): """Test add netscaler device with invalid private interface """ diff --git a/test/integration/component/test_netscaler_nw_off.py b/test/integration/component/test_netscaler_nw_off.py index 3372612aba..a94f01d6e7 100644 --- a/test/integration/component/test_netscaler_nw_off.py +++ b/test/integration/component/test_netscaler_nw_off.py @@ -227,7 +227,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advancedns"]) + @attr(tags=["advancedns", "provisioning"]) def test_add_netscaler_device(self): """Test add netscaler device """ @@ -385,7 +385,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advancedns", "multizone"]) + @attr(tags=["advancedns", "multizone", "provisioning"]) def test_add_mul_netscaler_diff_zone(self): """Test add netscaler devices in different zones """ diff --git a/test/integration/component/test_network_offering.py b/test/integration/component/test_network_offering.py index 33c4305933..7040722e8f 100644 --- a/test/integration/component/test_network_offering.py +++ b/test/integration/component/test_network_offering.py @@ -215,7 +215,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_01_network_off_without_conserve_mode(self): """Test Network offering with Conserve mode off and VR - All services """ @@ -460,7 +460,7 @@ def test_01_network_off_without_conserve_mode(self): ) return - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_02_network_off_with_conserve_mode(self): """Test Network offering with Conserve mode ON and VR - All services """ @@ -798,7 +798,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advancedns"]) + @attr(tags=["advancedns", "provisioning"]) def test_01_nwupgrade_netscaler_conserve_on(self): """Test Nw upgrade to netscaler lb service and conserve mode ON """ @@ -998,7 +998,7 @@ def test_01_nwupgrade_netscaler_conserve_on(self): return @attr(speed = "slow") - @attr(tags = ["advancedns"]) + @attr(tags=["advancedns", "provisioning"]) def test_02_nwupgrade_netscaler_conserve_off(self): """Test Nw upgrade to netscaler lb service and conserve mode OFF """ @@ -1218,7 +1218,7 @@ def tearDownClass(cls): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_create_network_with_snat(self): """Test to create a network with SourceNAT service only""" diff --git a/test/integration/component/test_persistent_networks.py b/test/integration/component/test_persistent_networks.py index 8c1d54d192..1eefad8b2e 100644 --- a/test/integration/component/test_persistent_networks.py +++ b/test/integration/component/test_persistent_networks.py @@ -209,7 +209,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_network_state_after_destroying_vms(self): # steps # 1. Create an isolated persistent network @@ -248,7 +248,7 @@ def test_network_state_after_destroying_vms(self): verifyNetworkState(self.api_client, network.id, "implemented") return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_shared_network_offering_with_persistent(self): # steps # 1. create shared network offering with persistent field enabled diff --git a/test/integration/component/test_portable_ip.py b/test/integration/component/test_portable_ip.py index 40d80abbea..e8bf4f5b11 100644 --- a/test/integration/component/test_portable_ip.py +++ b/test/integration/component/test_portable_ip.py @@ -192,7 +192,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_create_portable_ip_range(self): """Test create new portable ip range """ @@ -225,7 +225,7 @@ def test_create_portable_ip_range(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_create_portable_ip_range_non_root_admin(self): """Test create new portable ip range with non admin root account """ @@ -258,7 +258,7 @@ def test_create_portable_ip_range_non_root_admin(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_create_portable_ip_range_invalid_region(self): """Test create portable ip range with invalid region id""" @@ -348,7 +348,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_delete_portable_ip_range(self): """Test delete ip range """ @@ -363,7 +363,7 @@ def test_delete_portable_ip_range(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_delete_portable_ip_range_non_root_admin(self): """Test delete ip range - non admin root """ @@ -389,7 +389,7 @@ def test_delete_portable_ip_range_non_root_admin(self): self.portable_ip_range.delete(self.apiclient) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_delete_portable_ip_range_in_use(self): """Test delete ip range """ @@ -521,7 +521,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_list_portable_ip_range(self): """Test list portable ip ranges """ @@ -553,7 +553,7 @@ def test_list_portable_ip_range(self): "Listed netmask not matching with the netmask of created public ip range") return - @attr(tags=["advanced"]) + @attr(tags=["advanced","swamy", "selfservice"]) def test_list_portable_ip_range_non_root_admin(self): """Test list portable ip ranges with non admin root account """ @@ -684,7 +684,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_associate_ip_address(self): """ Test assocoate public ip address """ @@ -733,7 +733,7 @@ def test_associate_ip_address(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_associate_ip_address_invalid_zone(self): """ Test Associate IP with invalid zone id """ @@ -756,7 +756,7 @@ def test_associate_ip_address_invalid_zone(self): self.debug("Associating ip address failed") return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_associate_ip_address_services_enable_disable(self): """ Test enabling and disabling NAT, Firewall services on portable ip """ @@ -852,7 +852,7 @@ def test_associate_ip_address_services_enable_disable(self): portableip.delete(self.apiclient) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_associate_ip_address_no_free_ip(self): """ Test assocoate public ip address """ @@ -1026,7 +1026,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_disassociate_ip_address_no_services(self): """ Test disassociating portable ip """ @@ -1057,7 +1057,7 @@ def test_disassociate_ip_address_no_services(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_disassociate_ip_address_services_enabled(self): """ Test disassociating portable ip """ @@ -1118,7 +1118,7 @@ def test_disassociate_ip_address_services_enabled(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_disassociate_ip_address_other_account(self): """ Test disassociating portable IP with non-owner account """ @@ -1275,7 +1275,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_delete_account_services_disabled(self): """ test delete account with portable ip with no services enabled """ @@ -1305,7 +1305,7 @@ def test_delete_account_services_disabled(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_delete_account_services_enabled(self): """ test delete account with portable ip with PF and firewall services enabled """ @@ -1519,7 +1519,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced","swamy"]) + @attr(tags=["advanced","swamy", "selfservice"]) def test_list_portable_ip_range_non_root_admin(self): """Test list portable ip ranges with non admin root account """ diff --git a/test/integration/component/test_project_configs.py b/test/integration/component/test_project_configs.py index be6cf1ce27..4d878f73f8 100644 --- a/test/integration/component/test_project_configs.py +++ b/test/integration/component/test_project_configs.py @@ -175,7 +175,7 @@ def tearDown(self): return @attr(configuration = "allow.user.create.projects") - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_admin_project_creation(self): """Test create project as a domain admin and domain user """ @@ -483,7 +483,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_add_user_to_project(self): """Add user to project when 'project.invite.required' is false""" @@ -636,7 +636,7 @@ def tearDown(self): return @attr(configuration = "project.invite.required") - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_add_user_to_project(self): """Add user to project when 'project.invite.required' is true""" diff --git a/test/integration/component/test_project_limits.py b/test/integration/component/test_project_limits.py index 7cb29b7d27..7d938764b8 100644 --- a/test/integration/component/test_project_limits.py +++ b/test/integration/component/test_project_limits.py @@ -185,7 +185,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_project_limits(self): """ Test project limits for domain admin """ @@ -352,7 +352,7 @@ def test_01_project_limits(self): return - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_02_project_limits_normal_user(self): """ Test project limits for normal user """ @@ -576,7 +576,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_03_vm_per_project(self): """Test VM limit per project """ @@ -638,7 +638,7 @@ def test_03_vm_per_project(self): ) return - @attr(tags=["advanced", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "eip", "advancedns", "simulator", "selfservice"]) def test_04_publicip_per_project(self): """Test Public IP limit per project """ @@ -723,7 +723,7 @@ def test_04_publicip_per_project(self): ) return - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_05_snapshots_per_project(self): """Test Snapshot limit per project """ @@ -799,7 +799,7 @@ def test_05_snapshots_per_project(self): ) return - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_06_volumes_per_project(self): """Test Volumes limit per project """ @@ -855,7 +855,7 @@ def test_06_volumes_per_project(self): ) return - @attr(tags=["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_07_templates_per_project(self): """Test Templates limit per project """ diff --git a/test/integration/component/test_project_resources.py b/test/integration/component/test_project_resources.py index d6a732d549..7fb23a42e4 100644 --- a/test/integration/component/test_project_resources.py +++ b/test/integration/component/test_project_resources.py @@ -227,7 +227,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_service_offerings(self): """ Test service offerings in a project """ @@ -269,7 +269,7 @@ def test_01_service_offerings(self): return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_02_project_disk_offerings(self): """ Test project disk offerings """ @@ -403,7 +403,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_03_network_create(self): """ Test create network in project """ @@ -628,7 +628,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_04_public_template_use_in_project(self): """Test Templates creation in projects """ @@ -686,7 +686,7 @@ def test_04_public_template_use_in_project(self): ) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_05_use_private_template_in_project(self): """Test use of private template in a project """ @@ -852,7 +852,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_06_create_snapshots_in_project(self): """Test create snapshots in project """ @@ -1008,7 +1008,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_07_associate_public_ip(self): """Test associate public IP within the project """ diff --git a/test/integration/component/test_project_usage.py b/test/integration/component/test_project_usage.py index ba0a63c97e..10f48a68ef 100644 --- a/test/integration/component/test_project_usage.py +++ b/test/integration/component/test_project_usage.py @@ -192,7 +192,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_vm_usage(self): """Test Create/Destroy VM and verify usage calculation """ @@ -404,7 +404,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "eip", "advancedns", "simulator", "selfservice"]) def test_01_public_ip_usage(self): """Test Assign new IP and verify usage calculation """ @@ -563,7 +563,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_volume_usage(self): """Test Create/delete a volume and verify correct usage is recorded """ @@ -755,7 +755,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_01_template_usage(self): """Test Upload/ delete a template and verify correct usage is generated for the template uploaded @@ -908,7 +908,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_01_ISO_usage(self): """Test Create/Delete a ISO and verify its usage is generated correctly """ @@ -1082,7 +1082,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "eip", "advancedns", "simulator", "selfservice"]) def test_01_lb_usage(self): """Test Create/Delete a LB rule and verify correct usage is recorded """ @@ -1250,7 +1250,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_snapshot_usage(self): """Test Create/Delete a manual snap shot and verify correct usage is recorded @@ -1443,7 +1443,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_01_nat_usage(self): """Test Create/Delete a PF rule and verify correct usage is recorded """ @@ -1627,7 +1627,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_01_vpn_usage(self): """Test Create/Delete a VPN and verify correct usage is recorded """ diff --git a/test/integration/component/test_projects.py b/test/integration/component/test_projects.py index 4b82fc2639..1a00f587dc 100644 --- a/test/integration/component/test_projects.py +++ b/test/integration/component/test_projects.py @@ -168,7 +168,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_create_multiple_projects_by_account(self): """ Verify an account can own multiple projects and can belong to multiple projects """ @@ -389,7 +389,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_02_cross_domain_account_add(self): """ Verify No cross domain projects """ @@ -510,7 +510,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_03_delete_account_with_project(self): """ Test As long as the project exists, its owner can't be removed """ @@ -624,7 +624,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_04_delete_domain_with_project(self): """ Test Verify delete domain with cleanup=true should delete projects belonging to the domain @@ -770,7 +770,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_05_user_project_owner_promotion(self): """ Test Verify a project user can be later promoted to become a owner @@ -912,7 +912,7 @@ def test_05_user_project_owner_promotion(self): ) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_06_max_one_project_owner(self): """ Test Verify there can only be one owner of a project at a time """ @@ -1203,7 +1203,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_07_project_resources_account_delete(self): """ Test Verify after an account is removed from the project, all its resources stay with the project. """ @@ -1317,7 +1317,7 @@ def test_07_project_resources_account_delete(self): ) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_08_cleanup_after_project_delete(self): """ Test accounts are unassigned from project after project deletion """ @@ -1529,7 +1529,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_09_project_suspend(self): """ Test Verify after an account is removed from the project, all his resources stay with the project. @@ -1666,7 +1666,7 @@ def test_09_project_suspend(self): ) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_10_project_activation(self): """ Test project activation after suspension """ diff --git a/test/integration/component/test_recurring_snapshots.py b/test/integration/component/test_recurring_snapshots.py index 06df1708d9..fd1b57da07 100644 --- a/test/integration/component/test_recurring_snapshots.py +++ b/test/integration/component/test_recurring_snapshots.py @@ -216,7 +216,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "selfservice"]) def test_recurring_snapshot_root_disk(self): """Test Recurring Snapshot Root Disk """ @@ -309,7 +309,7 @@ def test_recurring_snapshot_root_disk(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "selfservice"]) def test_recurring_snapshot_data_disk(self): """Test Recurring Snapshot data Disk """ diff --git a/test/integration/component/test_redundant_router_cleanups.py b/test/integration/component/test_redundant_router_cleanups.py index e30c102024..84cbc6ffc8 100644 --- a/test/integration/component/test_redundant_router_cleanups.py +++ b/test/integration/component/test_redundant_router_cleanups.py @@ -201,7 +201,7 @@ def tearDown(self): #raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns", "ssh"]) + @attr(tags=["advanced", "advancedns", "ssh", "selfservice"]) def test_restart_ntwk_no_cleanup(self): """Test restarting RvR network without cleanup """ @@ -342,7 +342,7 @@ def test_restart_ntwk_no_cleanup(self): ) return - @attr(tags=["advanced", "advancedns", "ssh"]) + @attr(tags=["advanced", "advancedns", "ssh", "selfservice"]) def test_restart_ntwk_with_cleanup(self): """Test restart RvR network with cleanup """ @@ -483,7 +483,7 @@ def test_restart_ntwk_with_cleanup(self): ) return - @attr(tags=["advanced", "advancedns", "ssh"]) + @attr(tags=["advanced", "advancedns", "ssh", "selfservice"]) def test_network_gc(self): """Test network garbage collection with RVR """ diff --git a/test/integration/component/test_redundant_router_services.py b/test/integration/component/test_redundant_router_services.py index 64bb6e99ac..5204d6f500 100644 --- a/test/integration/component/test_redundant_router_services.py +++ b/test/integration/component/test_redundant_router_services.py @@ -201,7 +201,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns", "ssh"]) + @attr(tags=["advanced", "advancedns", "ssh", "selfservice"]) def test_enableVPNOverRvR(self): """Test redundant router internals """ diff --git a/test/integration/component/test_redundant_router_upgrades.py b/test/integration/component/test_redundant_router_upgrades.py index e9303c0126..bd38c14e02 100644 --- a/test/integration/component/test_redundant_router_upgrades.py +++ b/test/integration/component/test_redundant_router_upgrades.py @@ -200,7 +200,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns", "ssh"]) + @attr(tags=["advanced", "advancedns", "ssh", "selfservice"]) def test_upgradeVR_to_redundantVR(self): """Test upgrade virtual router to redundant virtual router """ @@ -345,7 +345,7 @@ def test_upgradeVR_to_redundantVR(self): ) return - @attr(tags=["advanced", "advancedns", "ssh"]) + @attr(tags=["advanced", "advancedns", "ssh", "selfservice"]) def test_downgradeRvR_to_VR(self): """Test downgrade redundant virtual router to virtual router """ diff --git a/test/integration/component/test_region_vpc.py b/test/integration/component/test_region_vpc.py new file mode 100644 index 0000000000..2cd9de9073 --- /dev/null +++ b/test/integration/component/test_region_vpc.py @@ -0,0 +1,517 @@ +# 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 unittest + +""" Component tests for region level VPC functionality +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.sshClient import SshClient +import datetime + + +class Services: + """Test inter VLAN services + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 128, + }, + "network_offering": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL, Connectivity', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter', + "Connectivity": 'Ovs' + }, + "serviceCapabilityList": { + "Connectivity": { + "StretchedL2Subnet": "true" + }, + }, + }, + "vpc_offering": { + "name": 'VPC off', + "displaytext": 'VPC off', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat,Connectivity', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "Connectivity": 'Ovs' + }, + "serviceCapabilityList": { + "Connectivity": { + "RegionLevelVpc": "true" + }, + }, + }, + "vpc": { + "name": "TestVPC", + "displaytext": "TestVPC", + "cidr": '10.0.0.1/24' + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + "netmask": '255.255.255.0' + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + "openfirewall": False, + "startport": 2222, + "endport": 2222, + "cidrlist": '0.0.0.0/0', + "protocol": 'TCP' + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "startport": 22, + "endport": 22, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "fw_rule": { + "startport": 1, + "endport": 6000, + "cidr": '0.0.0.0/0', + # Any network (For creating FW rule) + "protocol": "TCP" + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + } + + +class TestRegionVpcOffering(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestRegionVpcOffering, + 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.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 + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [] + self.cleanup.insert(0, self.account) + return + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.assertEqual( + vpc_offs[0].regionlevelvpc,True, + "VPC offering is not set up for region level VPC" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + self.debug("VPC network created successfully - %s" % network.name) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_create_vpc_offering_with_regionlevelvpc_service_capability(self): + """ Test create VPC offering + """ + + # Steps for validation + # 1. Create VPC Offering by specifying all supported Services + # 2. VPC offering should be created successfully. + + self.debug("Creating inter VPC offering") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self.debug("Check if the VPC offering is created successfully?") + self.cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_create_vpc_from_offering_with_regionlevelvpc_service_capability(self): + """ Test create VPC offering + """ + + # Steps for validation + # 1. Create VPC Offering by specifying all supported Services + # 2. VPC offering should be created successfully. + + self.debug("Creating inter VPC offering") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + vpc_off.update(self.apiclient, state='Enabled') + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.name, + domainid=self.account.domainid + ) + self.assertEqual(vpc.distributedvpcrouter, True, "VPC created should have 'distributedvpcrouter' set to True") + + try: + vpc.delete(self.apiclient) + except Exception as e: + self.fail("Failed to delete VPC network - %s" % e) + return + + @attr(tags=["advanced", "intervlan"]) + def test_03_deploy_vms_in_vpc_with_regionlevelvpc(self): + """Test deploy virtual machines in VPC networks""" + + # 1. Create VPC Offering by specifying all supported Services + # (Vpn,dhcpdns,UserData, SourceNat,Static NAT and PF,LB,NetworkAcl) + # 2. Create a VPC using the above VPC offering + # 3. Create a network as part of this VPC. + # 4. Deploy few Vms. + # 5. Create a LB rule for this VM. + # 6. Create a PF rule for this VM. + # 7. Create a Static Nat rule for this VM. + # 8. Create Ingress rules on the network to open the above created + # LB PF and Static Nat rule + # 9. Create Egress Network ACL for this network to access google.com. + # 10. Enable VPN services + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.name) + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.name, + domainid=self.account.domainid + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.name, + domainid=self.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network.id) + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + networkid=network.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + network.id + )) + + self.debug("Creating LB rule for IP address: %s" % + public_ip.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.name, + networkid=network.id, + vpcid=vpc.id, + domainid=self.account.domainid + ) + + self.debug("Associating public IP for network: %s" % vpc.name) + public_ip_2 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + networkid=network.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_2.ipaddress.ipaddress, + network.id + )) + + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=public_ip_2.ipaddress.id, + openfirewall=False, + networkid=network.id, + vpcid=vpc.id + ) + + self.debug("Adding NetwrokACl rules to make PF and LB accessible") + networkacl_1 = NetworkACL.create( + self.apiclient, + networkid=network.id, + services=self.services["natrule"], + traffictype='Ingress' + ) + + networkacl_2 = NetworkACL.create( + self.apiclient, + networkid=network.id, + services=self.services["lbrule"], + traffictype='Ingress' + ) + self.debug("Checking if we can SSH into VM?") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip_2.ipaddress.ipaddress, + ) + self.debug("SSH into VM is successfully") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_2.ipaddress.ipaddress, e)) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip_3 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + networkid=network.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_3.ipaddress.ipaddress, + network.id + )) + self.debug("Enabling static NAT for IP: %s" % + public_ip_3.ipaddress.ipaddress) + try: + StaticNATRule.enable( + self.apiclient, + ipaddressid=public_ip_3.ipaddress.id, + virtualmachineid=virtual_machine.id, + networkid=network.id + ) + self.debug("Static NAT enabled for IP: %s" % + public_ip_3.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip_3.ipaddress.ipaddress, e)) + + public_ips = PublicIPAddress.list( + self.apiclient, + networkid=network.id, + listall=True, + isstaticnat=True, + account=self.account.name, + domainid=self.account.domainid + ) + self.assertEqual( + isinstance(public_ips, list), + True, + "List public Ip for network should list the Ip addr" + ) + self.assertEqual( + public_ips[0].ipaddress, + public_ip_3.ipaddress.ipaddress, + "List public Ip for network should list the Ip addr" + ) + # TODO: Remote Access VPN is not yet supported in VPC + return \ No newline at end of file diff --git a/test/integration/component/test_regions.py b/test/integration/component/test_regions.py index 252ba702b2..b40a48b1ce 100644 --- a/test/integration/component/test_regions.py +++ b/test/integration/component/test_regions.py @@ -67,14 +67,14 @@ def setUp(self): msg="Region creation failed" ) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_createRegionWithExistingRegionId(self): """Test for duplicate checks on region id """ self.services["region"]["regionname"] = random_gen() #alter region name but not id self.assertRaises(Exception, Region.create, self.api_client, self.services["region"]) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_createRegionWithExistingRegionName(self): """Test for duplicate checks on region name """ @@ -83,7 +83,7 @@ def test_createRegionWithExistingRegionName(self): self.services["region"]["regionendpoint"] = "http://region" + str(random_int) + ":8080/client" self.assertRaises(Exception, Region.create, self.api_client, self.services["region"]) - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_updateRegion(self): """ Test for update Region """ diff --git a/test/integration/component/test_regions_accounts.py b/test/integration/component/test_regions_accounts.py index 886e6209f2..51620e50fe 100644 --- a/test/integration/component/test_regions_accounts.py +++ b/test/integration/component/test_regions_accounts.py @@ -61,7 +61,7 @@ def setUpClass(cls): cls.cleanup = [] return - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_createAccountWithUUID(self): """Test for creating account by passing id parameter @@ -101,7 +101,7 @@ def test_createAccountWithUUID(self): self.cleanup.append(account) return - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_createUserWithUUID(self): """Test for creating User by passing id parameter @@ -152,7 +152,7 @@ def test_createUserWithUUID(self): ) return - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_createdomainWithUUID(self): """Test for creating Domain by passing id parameter diff --git a/test/integration/component/test_resource_limits.py b/test/integration/component/test_resource_limits.py index f0d558ec2d..9f991611cd 100644 --- a/test/integration/component/test_resource_limits.py +++ b/test/integration/component/test_resource_limits.py @@ -195,7 +195,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_01_vm_per_account(self): """Test VM limit per account """ @@ -288,7 +288,7 @@ def test_01_vm_per_account(self): ) return - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_02_publicip_per_account(self): """Test Public IP limit per account """ @@ -432,7 +432,7 @@ def test_02_publicip_per_account(self): return @attr(speed="slow") - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_03_snapshots_per_account(self): """Test Snapshot limit per account """ @@ -591,7 +591,7 @@ def test_03_snapshots_per_account(self): ) return - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_04_volumes_per_account(self): """Test Volumes limit per account """ @@ -733,7 +733,7 @@ def test_04_volumes_per_account(self): ) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_05_templates_per_account(self): """Test Templates limit per account """ @@ -966,7 +966,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_01_vm_per_domain(self): """Test VM limit per domain """ @@ -1032,7 +1032,7 @@ def test_01_vm_per_domain(self): ) return - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_01_publicip_per_domain(self): """Test Public IP limit per domain """ @@ -1103,7 +1103,7 @@ def test_01_publicip_per_domain(self): return @attr(speed="slow") - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_03_snapshots_per_domain(self): """Test Snapshot limit per domain """ @@ -1187,7 +1187,7 @@ def test_03_snapshots_per_domain(self): ) return - @attr(tags=["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_04_volumes_per_domain(self): """Test Volumes limit per domain """ @@ -1240,7 +1240,7 @@ def test_04_volumes_per_domain(self): ) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_05_templates_per_domain(self): """Test Templates limit per domain """ diff --git a/test/integration/component/test_routers.py b/test/integration/component/test_routers.py index ced3f525ca..29e2e9fbea 100644 --- a/test/integration/component/test_routers.py +++ b/test/integration/component/test_routers.py @@ -167,7 +167,7 @@ def setUp(self): self.cleanup = [] return - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_01_AdvancedZoneRouterServices(self): """Test advanced zone router services """ @@ -318,7 +318,7 @@ def test_01_AdvancedZoneRouterServices(self): return @attr(configuration = "network.gc") - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_02_NetworkGarbageCollection(self): """Test network garbage collection """ @@ -496,7 +496,7 @@ def test_02_NetworkGarbageCollection(self): self.cleanup.append(self.vm_2) return - @attr(tags = ["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_03_RouterStartOnVmDeploy(self): """Test router start on VM deploy """ @@ -703,7 +703,7 @@ def setUp(self): self.cleanup = [] return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_01_RouterStopCreatePF(self): """Test router stop create port forwarding """ @@ -914,7 +914,7 @@ def setUp(self): self.cleanup = [] return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_01_RouterStopCreateLB(self): """Test router stop create Load balancing """ @@ -1125,7 +1125,7 @@ def setUp(self): self.cleanup = [] return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_01_RouterStopCreateFW(self): """Test router stop create Firewall rule """ diff --git a/test/integration/component/test_shared_networks.py b/test/integration/component/test_shared_networks.py index 99cce19488..9d96fd6f95 100644 --- a/test/integration/component/test_shared_networks.py +++ b/test/integration/component/test_shared_networks.py @@ -260,7 +260,7 @@ def tearDown(self): return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_sharedNetworkOffering_01(self): """ Test shared network Offering 01 """ @@ -396,7 +396,7 @@ def test_sharedNetworkOffering_01(self): ) self.debug("NetworkOffering created and enabled: %s" % self.shared_network_offering.id) - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_sharedNetworkOffering_02(self): """ Test Shared Network Offering 02 """ @@ -485,7 +485,7 @@ def test_sharedNetworkOffering_02(self): self.debug("Network Offering creation failed with vlan as False in advance mode and shared guest type. Exception: %s" % e) - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_sharedNetworkOffering_03(self): """ Test Shared Network Offering 03 """ @@ -575,7 +575,7 @@ def test_sharedNetworkOffering_03(self): self.debug("Network Offering creation failed with vlan as true and ip ranges as False in advance mode and with shared guest type.\ Exception : %s" % e) - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_createSharedNetwork_All(self): """ Test Shared Network ALL """ @@ -846,7 +846,7 @@ def test_createSharedNetwork_All(self): if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: self.fail("Virtual machine ip should be from the ip range assigned to network created.") - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_createSharedNetwork_accountSpecific(self): """ Test Shared Network with scope account """ @@ -1095,7 +1095,7 @@ def test_createSharedNetwork_accountSpecific(self): if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: self.fail("Virtual machine ip should be from the ip range assigned to network created.") - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_createSharedNetwork_domainSpecific(self): """ Test Shared Network with scope domain """ @@ -1439,7 +1439,7 @@ def test_createSharedNetwork_domainSpecific(self): if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: self.fail("Virtual machine ip should be from the ip range assigned to network created.") - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_createSharedNetwork_projectSpecific(self): """ Test Shared Network with scope project """ @@ -1716,7 +1716,7 @@ def test_createSharedNetwork_projectSpecific(self): self.fail("Virtual machine ip should be from the ip range assigned to network created.") @unittest.skip("skipped - This is a redundant case and also this is causing issue for rest fo the cases ") - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "NA"]) def test_createSharedNetwork_usedVlan(self): """ Test Shared Network with used vlan 01 """ @@ -1860,7 +1860,7 @@ def test_createSharedNetwork_usedVlan(self): self.debug("Network creation failed because the valn id being used by another network. Exception: %s" % e) - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_createSharedNetwork_usedVlan2(self): """ Test Shared Network with used vlan 02 """ @@ -2042,7 +2042,7 @@ def test_createSharedNetwork_usedVlan2(self): except Exception as e: self.debug("Network creation failed because the valn id being used by another network. Exception: %s" % e) - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_deployVM_multipleSharedNetwork(self): """ Test Vm deployment with multiple shared networks """ @@ -2292,7 +2292,7 @@ def test_deployVM_multipleSharedNetwork(self): self.assertTrue(self.network1_admin_account_virtual_machine.nic[0].ipaddress is not None, "ip should be assigned to running virtual machine") - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_deployVM_isolatedAndShared(self): """ Test VM deployment in shared and isolated networks """ @@ -2631,7 +2631,7 @@ def test_deployVM_isolatedAndShared(self): except Exception as e: self.fail("SSH Access failed for %s: %s" % (self.isolated_network_admin_account_virtual_machine.ipaddress, e)) - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_networkWithsubdomainaccessTrue(self): """ Test Shared Network with subdomainaccess=True """ @@ -2762,7 +2762,7 @@ def test_networkWithsubdomainaccessTrue(self): except: self.debug("Network creation failed because subdomainaccess parameter was passed when scope was account.") - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_networkWithsubdomainaccessFalse(self): """ Test shared Network with subdomainaccess=False """ diff --git a/test/integration/component/test_snapshot_gc.py b/test/integration/component/test_snapshot_gc.py index 1e1cc5dd80..6858670427 100644 --- a/test/integration/component/test_snapshot_gc.py +++ b/test/integration/component/test_snapshot_gc.py @@ -206,7 +206,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "advancedns", "basic", "sg", "provisioning"]) def test_02_accountSnapshotClean(self): """Test snapshot cleanup after account deletion """ diff --git a/test/integration/component/test_snapshot_limits.py b/test/integration/component/test_snapshot_limits.py index a1bf1ba2f5..e204f4c3c1 100644 --- a/test/integration/component/test_snapshot_limits.py +++ b/test/integration/component/test_snapshot_limits.py @@ -199,7 +199,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_04_snapshot_limit(self): """Test snapshot limit in snapshot policies """ diff --git a/test/integration/component/test_snapshots.py b/test/integration/component/test_snapshots.py index 17579d63d4..034af9c971 100644 --- a/test/integration/component/test_snapshots.py +++ b/test/integration/component/test_snapshots.py @@ -242,7 +242,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "provisioning"]) def test_02_snapshot_data_disk(self): """Test Snapshot Data Disk """ @@ -289,7 +289,7 @@ def test_02_snapshot_data_disk(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "advancedns", "basic", "sg", "provisioning"]) def test_01_volume_from_snapshot(self): """Test Creating snapshot from volume having spaces in name(KVM) """ @@ -534,7 +534,7 @@ def test_01_volume_from_snapshot(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "provisioning"]) def test_04_delete_snapshot(self): """Test Delete Snapshot """ @@ -593,7 +593,7 @@ def test_04_delete_snapshot(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "advancedns", "basic", "sg", "provisioning"]) def test_03_snapshot_detachedDisk(self): """Test snapshot from detached disk """ @@ -719,7 +719,7 @@ def test_03_snapshot_detachedDisk(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "smoke", "xen"]) + @attr(tags=["advanced", "advancedns", "smoke", "xen", "provisioning"]) def test_07_template_from_snapshot(self): """Create Template from snapshot """ @@ -969,7 +969,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_01_createVM_snapshotTemplate(self): """Test create VM, Snapshot and Template """ @@ -1176,7 +1176,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_05_snapshot_events(self): """Test snapshot events """ diff --git a/test/integration/component/test_snapshots_improvement.py b/test/integration/component/test_snapshots_improvement.py index 77c240d34f..52979c43a1 100644 --- a/test/integration/component/test_snapshots_improvement.py +++ b/test/integration/component/test_snapshots_improvement.py @@ -183,7 +183,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "provisioning"]) def test_01_snapshot_on_rootVolume(self): """Test create VM with default cent os template and create snapshot on root disk of the vm diff --git a/test/integration/component/test_stopped_vm.py b/test/integration/component/test_stopped_vm.py index 4ba94bfc29..53ad7e2be6 100644 --- a/test/integration/component/test_stopped_vm.py +++ b/test/integration/component/test_stopped_vm.py @@ -170,7 +170,7 @@ def tearDown(self): except Exception as e: self.debug("Warning! Exception in tearDown: %s" % e) - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "selfservice"]) def test_01_deploy_vm_no_startvm(self): """Test Deploy Virtual Machine with no startVM parameter """ @@ -220,7 +220,7 @@ def test_01_deploy_vm_no_startvm(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_02_deploy_vm_startvm_true(self): """Test Deploy Virtual Machine with startVM=true parameter """ @@ -271,7 +271,7 @@ def test_02_deploy_vm_startvm_true(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_03_deploy_vm_startvm_false(self): """Test Deploy Virtual Machine with startVM=false parameter """ @@ -363,7 +363,7 @@ def test_03_deploy_vm_startvm_false(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_04_deploy_startvm_false_attach_volume(self): """Test Deploy Virtual Machine with startVM=false and attach volume """ @@ -429,7 +429,7 @@ def test_04_deploy_startvm_false_attach_volume(self): self.fail("Attach volume failed!") return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_05_deploy_startvm_false_change_so(self): """Test Deploy Virtual Machine with startVM=false and change service offering """ @@ -502,7 +502,7 @@ def test_05_deploy_startvm_false_change_so(self): return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_06_deploy_startvm_attach_detach(self): """Test Deploy Virtual Machine with startVM=false and attach detach volumes @@ -587,7 +587,7 @@ def test_06_deploy_startvm_attach_detach(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_07_deploy_startvm_attach_iso(self): """Test Deploy Virtual Machine with startVM=false and attach ISO """ @@ -678,7 +678,7 @@ def test_07_deploy_startvm_attach_iso(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_08_deploy_attached_volume(self): """Test Deploy Virtual Machine with startVM=false and attach volume already attached to different machine """ @@ -808,7 +808,7 @@ def test_08_deploy_attached_volume(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_09_stop_vm_migrate_vol(self): """Test Stopped Virtual Machine's ROOT volume migration """ @@ -1025,7 +1025,7 @@ def tearDown(self): except Exception as e: self.debug("Warning! Exception in tearDown: %s" % e) - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_01_deploy_ha_vm_startvm_false(self): """Test Deploy HA enabled Virtual Machine with startvm=false """ @@ -1074,7 +1074,7 @@ def test_01_deploy_ha_vm_startvm_false(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_02_deploy_ha_vm_from_iso(self): """Test Deploy HA enabled Virtual Machine from ISO """ @@ -1139,7 +1139,7 @@ def test_02_deploy_ha_vm_from_iso(self): ) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_03_deploy_ha_vm_iso_startvm_false(self): """Test Deploy HA enabled Virtual Machine from ISO with startvm=false """ @@ -1256,7 +1256,7 @@ def tearDown(self): except Exception as e: self.debug("Warning! Exception in tearDown: %s" % e) - @attr(tags = ["advanced", "eip", "advancedns"]) + @attr(tags=["advanced", "eip", "advancedns", "selfservice"]) def test_01_deploy_vm_no_startvm(self): """Test Deploy Virtual Machine with no startVM parameter """ @@ -1556,7 +1556,7 @@ def tearDown(self): except Exception as e: self.debug("Warning! Exception in tearDown: %s" % e) - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "provisioning"]) def test_deploy_vm_password_enabled(self): """Test Deploy Virtual Machine with startVM=false & enabledpassword in template @@ -1694,7 +1694,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_vm_per_account(self): """Test VM limit per account """ @@ -1810,7 +1810,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + @attr(tags=["advanced", "eip", "advancedns", "basic", "sg", "selfservice"]) def test_upload_attach_volume(self): """Test Upload volume and attach to VM in stopped state """ diff --git a/test/integration/component/test_storage_motion.py b/test/integration/component/test_storage_motion.py index 194ba97709..e1fd40fe03 100644 --- a/test/integration/component/test_storage_motion.py +++ b/test/integration/component/test_storage_motion.py @@ -148,7 +148,7 @@ def tearDown(self): cleanup_resources(self.apiclient, self.cleanup) return - @attr(tags = ["advanced", "basic", "multicluster", "storagemotion", "xenserver"]) + @attr(tags=["advanced", "basic", "multicluster", "storagemotion", "xenserver", "provisioning"]) def test_01_migrate_vm_with_volume(self): """Test migrate virtual machine with its volumes """ @@ -226,7 +226,7 @@ def test_01_migrate_vm_with_volume(self): ) return - @attr(tags = ["advanced", "basic", "multipool", "storagemotion", "xenserver"]) + @attr(tags=["advanced", "basic", "multipool", "storagemotion", "xenserver", "selfservice"]) def test_02_migrate_volume(self): """Test migrate volume of a running vm """ diff --git a/test/integration/component/test_tags.py b/test/integration/component/test_tags.py index 2a6e0764f2..1e8667d163 100644 --- a/test/integration/component/test_tags.py +++ b/test/integration/component/test_tags.py @@ -266,7 +266,7 @@ def tearDown(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_01_lbrule_tag(self): """ Test Create tag on LB rule and remove the LB rule """ @@ -409,7 +409,7 @@ def test_01_lbrule_tag(self): self.fail("failed to delete load balancer rule! - %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_02_natrule_tag(self): """ Test Create tag on nat rule and remove the nat rule """ @@ -546,7 +546,7 @@ def test_02_natrule_tag(self): self.fail("failed to delete port forwarding rule! - %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_03_firewallrule_tag(self): """ Test Create tag on firewall rule and remove the firewall rule """ @@ -689,7 +689,7 @@ def test_03_firewallrule_tag(self): self.fail("failed to delete firewall rule! - %s" % e) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_04_vpn_tag(self): """ Test Create tag on vpn and remove the vpn """ @@ -841,7 +841,7 @@ def test_04_vpn_tag(self): self.fail("failed to disable VPN! - %s" % e) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_05_vm_tag(self): """ Test creation, listing and deletion tags on UserVM """ @@ -918,7 +918,7 @@ def test_05_vm_tag(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_06_template_tag(self): """ Test creation, listing and deletion tag on templates """ @@ -1030,7 +1030,7 @@ def test_06_template_tag(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_07_iso_tag(self): """ Test creation, listing and deletion tags on ISO """ @@ -1127,7 +1127,7 @@ def test_07_iso_tag(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_08_volume_tag(self): """ Test creation, listing and deletion tagson volume """ @@ -1216,7 +1216,7 @@ def test_08_volume_tag(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_09_snapshot_tag(self): """ Test creation, listing and deletion tag son snapshot """ @@ -1325,7 +1325,7 @@ def test_09_snapshot_tag(self): return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_10_network_tag(self): """ Testcreation, listing and deletion tags on guest network """ @@ -1527,7 +1527,7 @@ def test_11_migrate_tagged_vm_del(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_13_tag_case_insensitive(self): """ Test to verify that tags are not case sensitive """ @@ -1608,7 +1608,7 @@ def test_13_tag_case_insensitive(self): return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_14_special_char_mutiple_tags(self): """ Test multiple tags and with special characters on same machine """ @@ -1677,7 +1677,7 @@ def test_14_special_char_mutiple_tags(self): ) return - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_15_project_tag(self): """ Test creation, listing and deletion tags on projects """ @@ -1769,7 +1769,7 @@ def test_15_project_tag(self): ) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_16_query_tags_other_account(self): """ Test Query the tags from other account """ @@ -1861,7 +1861,7 @@ def test_16_query_tags_other_account(self): return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_17_query_tags_admin_account(self): """ Test Query the tags from admin account """ @@ -1948,7 +1948,7 @@ def test_17_query_tags_admin_account(self): return - @attr(tags=["advanced", "basic", "simulator"]) + @attr(tags=["advanced", "basic", "simulator", "selfservice"]) def test_18_invalid_list_parameters(self): """ Test listAPI with invalid tags parameter """ @@ -1987,7 +1987,7 @@ def test_18_invalid_list_parameters(self): return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_19_delete_add_same_tag(self): """ Test deletion and addition of same tag on a resource. """ @@ -2093,7 +2093,7 @@ def test_19_delete_add_same_tag(self): self.fail("Failed to delete the tag - %s" % e) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_20_create_tags_multiple_resources(self): "Test creation of same tag on multiple resources" @@ -2198,7 +2198,7 @@ def test_20_create_tags_multiple_resources(self): return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_21_create_tag_stopped_vm(self): "Test creation of tag on stopped vm." @@ -2275,7 +2275,7 @@ def test_21_create_tag_stopped_vm(self): self.fail("Failed to delete the tag - %s" % e) return - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_22_create_tag_destroyed_vm(self): "Test creation of tag on stopped vm." diff --git a/test/integration/component/test_templates.py b/test/integration/component/test_templates.py index 3e836157ac..1e612c2d14 100644 --- a/test/integration/component/test_templates.py +++ b/test/integration/component/test_templates.py @@ -156,7 +156,7 @@ def tearDownClass(cls): return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "provisioning"]) def test_01_create_template(self): """Test create public & private template """ @@ -382,7 +382,7 @@ def tearDown(self): return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_01_create_template_volume(self): """Test Create template from volume """ @@ -422,7 +422,7 @@ def test_01_create_template_volume(self): ) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_03_delete_template(self): """Test Delete template """ @@ -479,7 +479,7 @@ def test_03_delete_template(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_04_template_from_snapshot(self): """Create Template from snapshot """ diff --git a/test/integration/component/test_update_vm.py b/test/integration/component/test_update_vm.py index 0786310e19..6d847080b5 100644 --- a/test/integration/component/test_update_vm.py +++ b/test/integration/component/test_update_vm.py @@ -83,7 +83,7 @@ def setUp(self): self.account ] - @attr(tags = ['advanced', 'simulator', 'basic', 'sg']) + @attr(tags=['advanced', 'simulator', 'basic', 'sg', "selfservice"]) def test_update_vm_name(self): """Test Update VirtualMachine Name diff --git a/test/integration/component/test_usage.py b/test/integration/component/test_usage.py index 5979a0a495..d18d2eaf3e 100644 --- a/test/integration/component/test_usage.py +++ b/test/integration/component/test_usage.py @@ -178,7 +178,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_vm_usage(self): """Test Create/Destroy VM and verify usage calculation """ @@ -370,7 +370,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "eip", "advancedns", "simulator", "selfservice"]) def test_01_public_ip_usage(self): """Test Assign new IP and verify usage calculation """ @@ -518,7 +518,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_volume_usage(self): """Test Create/delete a volume and verify correct usage is recorded """ @@ -700,7 +700,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_01_template_usage(self): """Test Upload/ delete a template and verify correct usage is generated for the template uploaded @@ -844,7 +844,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "selfservice"]) def test_01_ISO_usage(self): """Test Create/Delete a ISO and verify its usage is generated correctly """ @@ -996,7 +996,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "eip", "advancedns", "simulator", "selfservice"]) def test_01_lb_usage(self): """Test Create/Delete a LB rule and verify correct usage is recorded """ @@ -1153,7 +1153,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator", "selfservice"]) def test_01_snapshot_usage(self): """Test Create/Delete a manual snap shot and verify correct usage is recorded @@ -1325,7 +1325,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator", "selfservice"]) def test_01_nat_usage(self): """Test Create/Delete a PF rule and verify correct usage is recorded """ @@ -1488,7 +1488,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_01_vpn_usage(self): """Test Create/Delete a VPN and verify correct usage is recorded """ diff --git a/test/integration/component/test_vmware_drs.py b/test/integration/component/test_vmware_drs.py index 6a99911184..9a07d912a5 100644 --- a/test/integration/component/test_vmware_drs.py +++ b/test/integration/component/test_vmware_drs.py @@ -178,7 +178,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "vmware", "multihost"]) + @attr(tags=["advanced", "vmware", "multihost", "provisioning"]) def test_vm_creation_in_fully_automated_mode(self): """ Test VM Creation in automation mode = Fully automated This test requires following preconditions: @@ -352,7 +352,7 @@ def create_aff_grp(self, aff_grp=None, except Exception as e: raise Exception("Error: Creation of Affinity Group failed : %s" %e) - @attr(tags = ["advanced", "vmware", "multihost"]) + @attr(tags=["advanced", "vmware", "multihost", "provisioning"]) def test_vmware_anti_affinity(self): """ Test Set up anti-affinity rules @@ -587,7 +587,7 @@ def create_aff_grp(self, aff_grp=None, except Exception as e: raise Exception("Error: Creation of Affinity Group failed : %s" %e) - @attr(tags = ["advanced", "vmware", "multihost"]) + @attr(tags=["advanced", "vmware", "multihost", "provisioning"]) def test_vmware_affinity(self): """ Test Set up affinity rules diff --git a/test/integration/component/test_volumes.py b/test/integration/component/test_volumes.py index ee0f91dd8c..bcf552ab43 100644 --- a/test/integration/component/test_volumes.py +++ b/test/integration/component/test_volumes.py @@ -923,7 +923,7 @@ def tearDown(self): cleanup_resources(self.apiclient, self.cleanup) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_01_attach_volume(self): """Attach a created Volume to a Running VM """ @@ -1006,7 +1006,7 @@ def test_01_attach_volume(self): ) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_02_detach_volume(self): """Detach a Volume attached to a VM """ @@ -1053,7 +1053,7 @@ def test_02_detach_volume(self): ) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_03_delete_detached_volume(self): """Delete a Volume unattached to an VM """ @@ -1080,7 +1080,7 @@ def test_03_delete_detached_volume(self): ) return - @attr(tags=["advanced", "advancedns", "simulator", "basic", "eip", "sg"]) + @attr(tags=["advanced", "advancedns", "simulator", "basic", "eip", "sg", "selfservice"]) def test_create_volume_under_domain(self): """Create a volume under a non-root domain as non-root-domain user diff --git a/test/integration/component/test_vpc.py b/test/integration/component/test_vpc.py index 1af8d8122e..5c55cb6c73 100644 --- a/test/integration/component/test_vpc.py +++ b/test/integration/component/test_vpc.py @@ -286,7 +286,7 @@ def validate_vpc_network(self, network, state=None): return #list_vpc_apis should be the first case otherwise the vpc counts would be wrong - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_01_list_vpc_apis(self): """ Test list VPC APIs """ @@ -465,7 +465,7 @@ def test_01_list_vpc_apis(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_02_restart_vpc_no_networks(self): """ Test restart VPC having no networks """ @@ -496,7 +496,7 @@ def test_02_restart_vpc_no_networks(self): self.validate_vpc_network(vpc, state='Enabled') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_03_restart_vpc_with_networks(self): """ Test restart VPC having networks """ @@ -581,7 +581,7 @@ def test_03_restart_vpc_with_networks(self): self.validate_vpc_network(vpc, state='Enabled') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_04_delete_vpc_no_networks(self): """ Test delete VPC having no networks """ @@ -621,7 +621,7 @@ def test_04_delete_vpc_no_networks(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_05_delete_vpc_with_networks(self): """ Test delete VPC having networks """ @@ -752,7 +752,7 @@ def test_05_delete_vpc_with_networks(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_06_list_vpc_apis_admin(self): """ Test list VPC APIs for different user roles """ @@ -812,7 +812,7 @@ def test_06_list_vpc_apis_admin(self): ) return - @attr(tags=["advanced", "intervlan", "multiple"]) + @attr(tags=["advanced", "intervlan", "multiple", "provisioning"]) def test_07_restart_network_vm_running(self): """ Test Restart VPC when there are multiple networks associated """ @@ -1161,7 +1161,7 @@ def test_07_restart_network_vm_running(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_08_delete_vpc(self): """ Test vpc deletion after account deletion """ @@ -1527,7 +1527,7 @@ def test_08_delete_vpc(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_09_vpc_create(self): """ Test to create vpc and verify VPC state, VR and SourceNatIP """ @@ -1588,7 +1588,7 @@ def test_09_vpc_create(self): "Source Nat IP address was not allocated to VR" ) - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_10_nonoverlaping_cidrs(self): """ Test creation of multiple VPCs with non-overlapping CIDRs """ @@ -1640,7 +1640,7 @@ def test_10_nonoverlaping_cidrs(self): assert("VPC created with overlapping CIDR") return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_11_deploy_vm_wo_network_netdomain(self): """ Test deployment of vm in a VPC without network domain """ @@ -1794,7 +1794,7 @@ def validate_vm_netdomain(self, vm, vpc, network, expected_netdomain): (vm_domain, expected_netdomain) ) - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_12_deploy_vm_with_netdomain(self): """ Test deployment of vm in a VPC with network domain """ @@ -1849,7 +1849,7 @@ def test_12_deploy_vm_with_netdomain(self): networkdomain='test.netdomain' ) - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_13_deploy_vm_with_vpc_netdomain(self): """ Test deployment of vm in a VPC with network domain """ @@ -1914,7 +1914,7 @@ def test_13_deploy_vm_with_vpc_netdomain(self): self.validate_vm_netdomain(virtual_machine, vpc, network, netdomain) - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_14_deploy_vm_1(self): """ Test vm deploy in network by a user where VPC was created without account/domain ID """ @@ -1990,7 +1990,7 @@ def test_14_deploy_vm_1(self): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_15_deploy_vm_2(self): """ Test deployment of vm in a network in a domain admin account where VPC is created without account/domain ID """ @@ -2071,7 +2071,7 @@ def test_15_deploy_vm_2(self): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_16_deploy_vm_for_user_by_admin(self): """ Test deployment of vm in a network by root admin for user. """ @@ -2148,7 +2148,7 @@ def test_16_deploy_vm_for_user_by_admin(self): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_17_deploy_vm_for_user_by_domain_admin(self): """ Test deployment of vm in a network by domain admin for user. """ @@ -2202,7 +2202,7 @@ def test_17_deploy_vm_for_user_by_domain_admin(self): zoneid=self.zone.id, ) - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_18_create_net_for_user_diff_domain_by_doadmin(self): """ Test creation of network by domain admin for user from different domain """ @@ -2279,7 +2279,7 @@ def test_18_create_net_for_user_diff_domain_by_doadmin(self): vpcid=vpc.id ) - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_19_create_vpc_wo_params(self): """ Test creation of VPC without mandatory parameters """ @@ -2339,7 +2339,7 @@ def test_19_create_vpc_wo_params(self): domainid=self.account.domainid ) - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_20_update_vpc_name_display_text(self): """ Test to verify updation of vpc name and display text """ diff --git a/test/integration/component/test_vpc_network.py b/test/integration/component/test_vpc_network.py index c393401403..6f280b8861 100644 --- a/test/integration/component/test_vpc_network.py +++ b/test/integration/component/test_vpc_network.py @@ -695,7 +695,7 @@ def test_05_create_network_ext_LB(self): return @unittest.skip("skipped - RvR didn't support VPC currently ") - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "NA"]) def test_06_create_network_with_rvr(self): """ Test create network with redundant router capability """ @@ -769,7 +769,7 @@ def test_06_create_network_with_rvr(self): self.debug("Network creation failed") return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_07_create_network_unsupported_services(self): """ Test create network services not supported by VPC (Should fail) """ @@ -836,7 +836,7 @@ def test_07_create_network_unsupported_services(self): self.debug("Network creation failed as VPC doesn't have LB service") return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_08_create_network_without_sourceNAT(self): """ Test create network without sourceNAT service in VPC (should fail) """ @@ -1186,7 +1186,7 @@ def test_01_create_network_outside_range(self, value): "Network creation failed as network cidr range is outside of vpc") return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_02_create_network_outside_range(self): """ Test create network outside cidr range of VPC """ @@ -1645,7 +1645,7 @@ def validate_vpc_network(self, network, state=None): self.debug("VPC network validated - %s" % network.name) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_01_network_services_upgrade(self): """ Test update Network that is part of a VPC to a network offering that has more services """ @@ -2007,7 +2007,7 @@ def test_01_network_services_upgrade(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_02_network_vpcvr2vr_upgrade(self): """ Test update Network that is NOT part of a VPC to a nw offering that has services that are provided by VPCVR and vice versa """ @@ -2341,7 +2341,7 @@ def validate_vpc_network(self, network, state=None): self.debug("VPC network validated - %s" % network.name) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_01_wait_network_gc(self): """ Test network gc after shutdown of vms in the network """ @@ -2367,7 +2367,7 @@ def test_01_wait_network_gc(self): self.assertEqual(lbrules, None, "LBrules were not cleared after network GC thread is run") return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_02_start_vm_network_gc(self): """ Test network rules after starting a VpcVr that was shutdown after network.gc """ @@ -2441,7 +2441,7 @@ def test_02_start_vm_network_gc(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_03_restart_vpcvr(self): """ Test Stop all the Vms that are part of the a Network (Wait for network GC).Restart VPCVR. diff --git a/test/integration/component/test_vpc_network_lbrules.py b/test/integration/component/test_vpc_network_lbrules.py index d623fb9bc5..9d75550d57 100644 --- a/test/integration/component/test_vpc_network_lbrules.py +++ b/test/integration/component/test_vpc_network_lbrules.py @@ -507,7 +507,7 @@ def create_egress_Internet_Rule(self, network): return nwacl_internet_1 - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_01_VPC_LBRulesListing(self): """ Test case no 210 and 227: List Load Balancing Rules belonging to a VPC """ @@ -555,7 +555,7 @@ def test_01_VPC_LBRulesListing(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_02_VPC_CreateLBRuleInMultipleNetworks(self): """ Test Create LB rules for 1 network which is part of a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Running State @@ -580,7 +580,7 @@ def test_02_VPC_CreateLBRuleInMultipleNetworks(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_03_VPC_CreateLBRuleInMultipleNetworksVRStoppedState(self): """ Test case no 222 : Create LB rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Stopped State @@ -616,7 +616,7 @@ def test_03_VPC_CreateLBRuleInMultipleNetworksVRStoppedState(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) return - @attr(tags=["advanced","advancedns", "intervlan"]) + @attr(tags=["advanced","advancedns", "intervlan", "provisioning"]) def test_04_VPC_CreateLBRuleInMultipleNetworksVRStoppedState(self): """ Test case no 222 : Create LB rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Stopped State @@ -646,7 +646,7 @@ def test_04_VPC_CreateLBRuleInMultipleNetworksVRStoppedState(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_05_VPC_CreateAndDeleteLBRule(self): """ Test case no 214 : Delete few(not all) LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Running State @@ -677,7 +677,7 @@ def test_05_VPC_CreateAndDeleteLBRule(self): self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_06_VPC_CreateAndDeleteLBRuleVRStopppedState(self): """ Test Delete few(not all) LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Stopped State @@ -714,7 +714,7 @@ def test_06_VPC_CreateAndDeleteLBRuleVRStopppedState(self): self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_07_VPC_CreateAndDeleteAllLBRule(self): """ Test Delete all LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Running State @@ -747,7 +747,7 @@ def test_07_VPC_CreateAndDeleteAllLBRule(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_08_VPC_CreateAndDeleteAllLBRuleVRStoppedState(self): """ Test Delete all LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Stopped State @@ -780,7 +780,7 @@ def test_08_VPC_CreateAndDeleteAllLBRuleVRStoppedState(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_09_VPC_LBRuleCreateFailMultipleVPC(self): """ Test User should not be allowed to create a LB rule for a VM that belongs to a different VPC. """ @@ -818,7 +818,7 @@ def test_09_VPC_LBRuleCreateFailMultipleVPC(self): self.debug('Failed to Create LB rule vm_3 and vm_4') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_10_VPC_FailedToCreateLBRuleNonVPCNetwork(self): """ Test User should not be allowed to create a LB rule for a VM that does not belong to any VPC. """ @@ -855,7 +855,7 @@ def test_10_VPC_FailedToCreateLBRuleNonVPCNetwork(self): self.debug('Failed to Create LB rule vm_3 and vm_4 in network2') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_11_VPC_LBRuleCreateNotAllowed(self): """ Test case no 217 and 236: User should not be allowed to create a LB rule for a VM that does not belong to the same network but belongs to the same VPC. @@ -893,7 +893,7 @@ def test_11_VPC_LBRuleCreateNotAllowed(self): self.debug('Failed to Create LB rule vm_3 and vm_1') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_12_VPC_LBRuleCreateFailForRouterIP(self): """ Test User should not be allowed to create a LB rule on an Ipaddress that Source Nat enabled. """ @@ -921,7 +921,7 @@ def test_12_VPC_LBRuleCreateFailForRouterIP(self): self.debug('Failed to Create LB rule vm_2 and vm_1') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_13_VPC_LBRuleCreateFailForPFSourceNATIP(self): """ Test User should not be allowed to create a LB rule on an Ipaddress that already has a PF rule. """ @@ -951,7 +951,7 @@ def test_13_VPC_LBRuleCreateFailForPFSourceNATIP(self): self.debug('Failed to Create LB rule vm_2 and vm_1') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_14_VPC_LBRuleCreateFailForStaticNatRule(self): """ Test User should not be allowed to create a LB rule on an Ipaddress that already has a Static Nat rule. """ @@ -980,7 +980,7 @@ def test_14_VPC_LBRuleCreateFailForStaticNatRule(self): self.debug('Failed to Create LB rule vm_2 and vm_1') return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_15_VPC_ReleaseIPForLBRuleCreated(self): """ Test release Ip address that has a LB rule assigned to it. """ diff --git a/test/integration/component/test_vpc_network_pfrules.py b/test/integration/component/test_vpc_network_pfrules.py index c65da4136a..e5bb158bdc 100644 --- a/test/integration/component/test_vpc_network_pfrules.py +++ b/test/integration/component/test_vpc_network_pfrules.py @@ -484,7 +484,7 @@ def open_egress_to_world(self, network): return nwacl_internet_1 - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_01_network_services_VPC_StopCreatePF(self): """ Test : Create VPC PF rules on acquired public ip when VpcVirtualRouter is stopped """ @@ -515,7 +515,7 @@ def test_01_network_services_VPC_StopCreatePF(self): self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_02_network_services_VPC_CreatePF(self): """ Test Create VPC PF rules on acquired public ip when VpcVirtualRouter is Running """ @@ -535,7 +535,7 @@ def test_02_network_services_VPC_CreatePF(self): self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_03_network_services_VPC_StopCreateMultiplePF(self): """ Test Create multiple VPC PF rules on acquired public ip in diff't networks when VpcVirtualRouter is stopped """ @@ -571,7 +571,7 @@ def test_03_network_services_VPC_StopCreateMultiplePF(self): self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_04_network_services_VPC_CreateMultiplePF(self): """ Test Create multiple VPC PF rules on acquired public ip in diff't networks when VpcVirtualRouter is running """ @@ -599,7 +599,7 @@ def test_04_network_services_VPC_CreateMultiplePF(self): self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_05_network_services_VPC_StopDeletePF(self): """ Test delete a PF rule in VPC when VpcVirtualRouter is Stopped """ @@ -630,7 +630,7 @@ def test_05_network_services_VPC_StopDeletePF(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_06_network_services_VPC_DeletePF(self): """ Test delete a PF rule in VPC when VpcVirtualRouter is Running """ @@ -657,7 +657,7 @@ def test_06_network_services_VPC_DeletePF(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_07_network_services_VPC_StopDeleteAllPF(self): """ Test delete all PF rules in VPC when VpcVirtualRouter is Stopped """ @@ -691,7 +691,7 @@ def test_07_network_services_VPC_StopDeleteAllPF(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_08_network_services_VPC_DeleteAllPF(self): """ Test delete all PF rules in VPC when VpcVirtualRouter is Running """ @@ -721,7 +721,7 @@ def test_08_network_services_VPC_DeleteAllPF(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_09_network_services_VPC_StopDeleteAllMultiplePF(self): """ Test delete all PF rules in VPC across multiple networks when VpcVirtualRouter is Stopped """ @@ -788,7 +788,7 @@ def test_09_network_services_VPC_StopDeleteAllMultiplePF(self): self.check_wget_from_vm(vm_4, public_ip_4, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_10_network_services_VPC_DeleteAllMultiplePF(self): """ Test delete all PF rules in VPC across multiple networks when VpcVirtualRouter is Running """ diff --git a/test/integration/component/test_vpc_network_staticnatrule.py b/test/integration/component/test_vpc_network_staticnatrule.py index 46e34796f6..ddc3c4c704 100644 --- a/test/integration/component/test_vpc_network_staticnatrule.py +++ b/test/integration/component/test_vpc_network_staticnatrule.py @@ -495,7 +495,7 @@ def create_ingress_rule(self, network, services=None): return nwacl_nat - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_01_VPC_StaticNatRuleCreateStoppedState(self): """ Test case no extra : """ @@ -523,7 +523,7 @@ def test_01_VPC_StaticNatRuleCreateStoppedState(self): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_02_VPC_CreateStaticNatRule(self): """ Test case no 229 : Create Static NAT Rule for a single virtual network of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Running State @@ -546,7 +546,7 @@ def test_02_VPC_CreateStaticNatRule(self): self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_03_VPC_StopCreateMultipleStaticNatRuleStopppedState(self): """ Test case no extra : Create Static Nat Rule rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when Virtual Router is in Stopped State @@ -586,7 +586,7 @@ def test_03_VPC_StopCreateMultipleStaticNatRuleStopppedState(self): self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_04_VPC_CreateMultipleStaticNatRule(self): """ Test case no 230 : Create Static NAT Rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Running State @@ -619,7 +619,7 @@ def test_04_VPC_CreateMultipleStaticNatRule(self): self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_05_network_services_VPC_DeleteAllPF(self): """ Test case no 232: Delete all Static NAT Rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Running State @@ -651,7 +651,7 @@ def test_05_network_services_VPC_DeleteAllPF(self): self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_06_network_services_VPC_DeleteAllMultiplePF(self): """ Test case no 233: Delete all Static NAT rules for two/multiple virtual networks of a VPC. Observe the status of the Public IP Addresses of the rules when the Virtual Router is in Running State. diff --git a/test/integration/component/test_vpc_offerings.py b/test/integration/component/test_vpc_offerings.py index 699cef9d8f..9e3064bf2c 100644 --- a/test/integration/component/test_vpc_offerings.py +++ b/test/integration/component/test_vpc_offerings.py @@ -235,7 +235,7 @@ def validate_vpc_network(self, network): self.debug("VPC network created successfully - %s" % network.name) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_01_create_vpc_offering(self): """ Test create VPC offering """ @@ -255,7 +255,7 @@ def test_01_create_vpc_offering(self): self.validate_vpc_offering(vpc_off) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_02_deploy_vms_in_vpc_nw(self): """Test deploy virtual machines in VPC networks""" @@ -457,7 +457,7 @@ def test_02_deploy_vms_in_vpc_nw(self): # TODO: Remote Access VPN is not yet supported in VPC return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_03_vpc_off_without_lb(self): """Test VPC offering without load balancing service""" @@ -578,7 +578,7 @@ def test_03_vpc_off_without_lb(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_04_vpc_off_without_static_nat(self): """Test VPC offering without static NAT service""" @@ -697,7 +697,7 @@ def test_04_vpc_off_without_static_nat(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_05_vpc_off_without_pf(self): """Test VPC offering without port forwarding service""" @@ -815,7 +815,7 @@ def test_05_vpc_off_without_pf(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_06_vpc_off_invalid_services(self): """Test VPC offering with invalid services""" @@ -847,7 +847,7 @@ def test_06_vpc_off_invalid_services(self): self.fail("Failed to create the VPC offering - %s" % e) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_07_update_vpc_off(self): """Test update VPC offering""" @@ -936,7 +936,7 @@ def test_07_update_vpc_off(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_08_list_vpc_off(self): """Test list VPC offering""" diff --git a/test/integration/component/test_vpc_routers.py b/test/integration/component/test_vpc_routers.py index a83662740d..fb5aed55fc 100644 --- a/test/integration/component/test_vpc_routers.py +++ b/test/integration/component/test_vpc_routers.py @@ -343,7 +343,7 @@ def migrate_router(self, router): " still %s" % (host.id, router.hostid)) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_01_stop_start_router_after_creating_vpc(self): """ Test to stop and start router after creation of VPC """ @@ -421,7 +421,7 @@ def test_01_stop_start_router_after_creating_vpc(self): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_02_reboot_router_after_creating_vpc(self): """ Test to reboot the router after creating a VPC """ @@ -470,7 +470,7 @@ def test_02_reboot_router_after_creating_vpc(self): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_03_migrate_router_after_creating_vpc(self): """ Test migration of router to another host after creating VPC """ @@ -491,7 +491,7 @@ def test_03_migrate_router_after_creating_vpc(self): self.migrate_router(routers[0]) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_04_change_service_offerring_vpc(self): """ Tests to change service offering of the Router after creating a vpc @@ -552,7 +552,7 @@ def test_04_change_service_offerring_vpc(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_05_destroy_router_after_creating_vpc(self): """ Test to destroy the router after creating a VPC """ @@ -980,7 +980,7 @@ def migrate_router(self, router): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioining"]) def test_01_start_stop_router_after_addition_of_one_guest_network(self): """ Test start/stop of router after addition of one guest network """ @@ -1075,7 +1075,7 @@ def test_01_start_stop_router_after_addition_of_one_guest_network(self): return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_02_reboot_router_after_addition_of_one_guest_network(self): """ Test reboot of router after addition of one guest network """ @@ -1142,7 +1142,7 @@ def test_02_reboot_router_after_addition_of_one_guest_network(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "provisioning"]) def test_03_migrate_router_after_addition_of_one_guest_network(self): """ Test migrate of router after addition of one guest network """ @@ -1185,7 +1185,7 @@ def test_03_migrate_router_after_addition_of_one_guest_network(self): self.migrate_router(routers[0]) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_04_chg_srv_off_router_after_addition_of_one_guest_network(self): """ Test to change service offering of router after addition of one guest network """ @@ -1263,7 +1263,7 @@ def test_04_chg_srv_off_router_after_addition_of_one_guest_network(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_05_destroy_router_after_addition_of_one_guest_network(self): """ Test destroy of router after addition of one guest network """ diff --git a/test/integration/component/test_vpc_vms_deployment.py b/test/integration/component/test_vpc_vms_deployment.py index 0a244ab656..0ef51b43b1 100644 --- a/test/integration/component/test_vpc_vms_deployment.py +++ b/test/integration/component/test_vpc_vms_deployment.py @@ -276,7 +276,7 @@ def validate_vpc_network(self, network, state=None): self.debug("VPC network validated - %s" % network.name) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_01_deploy_vms_in_network(self): """ Test deploy VMs in VPC networks """ @@ -490,7 +490,7 @@ def test_01_deploy_vms_in_network(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_02_deploy_vms_delete_network(self): """ Test deploy VMs in VPC networks and delete one of the network """ @@ -742,7 +742,7 @@ def test_02_deploy_vms_delete_network(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_03_deploy_vms_delete_add_network(self): """ Test deploy VMs, delete one of the network and add another one """ @@ -1011,7 +1011,7 @@ def test_03_deploy_vms_delete_add_network(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_04_deploy_vms_delete_add_network_noLb(self): """ Test deploy VMs, delete one network without LB and add another one """ @@ -1305,7 +1305,7 @@ def test_04_deploy_vms_delete_add_network_noLb(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_05_create_network_max_limit(self): """ Test create networks in VPC upto maximum limit for hypervisor """ @@ -1476,7 +1476,7 @@ def test_05_create_network_max_limit(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_06_delete_network_vm_running(self): """ Test delete network having running instances in VPC """ @@ -1718,7 +1718,7 @@ def test_06_delete_network_vm_running(self): ) return - @attr(tags=["advanced", "intervlan"]) + @attr(tags=["advanced", "intervlan", "selfservice"]) def test_07_delete_network_with_rules(self): """ Test delete network that has PF/staticNat/LB rules/Network Acl """ diff --git a/test/integration/component/test_vpn_users.py b/test/integration/component/test_vpn_users.py index 02dd02622a..710055a0ab 100644 --- a/test/integration/component/test_vpn_users.py +++ b/test/integration/component/test_vpn_users.py @@ -258,7 +258,7 @@ def test_01_VPN_user_limit(self): self.debug("Limit exceeded exception raised!") return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_02_use_vpn_port(self): """Test create VPN when L2TP port in use""" @@ -289,7 +289,7 @@ def test_02_use_vpn_port(self): self.debug("Create VPN connection failed! Test successful!") return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_03_enable_vpn_use_port(self): """Test create NAT rule when VPN when L2TP enabled""" @@ -315,7 +315,7 @@ def test_03_enable_vpn_use_port(self): self.debug("Create NAT rule failed! Test successful!") return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_04_add_new_users(self): """Test add new users to existing VPN""" @@ -343,7 +343,7 @@ def test_04_add_new_users(self): self.fail("Failed to create new VPN user: %s" % e) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_05_add_duplicate_user(self): """Test add duplicate user to existing VPN""" @@ -366,7 +366,7 @@ def test_05_add_duplicate_user(self): self.create_VPN_Users(rand_name=False) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_06_add_VPN_user_global_admin(self): """Test as global admin, add a new VPN user to an existing VPN entry that was created by another account.""" @@ -409,7 +409,7 @@ def test_06_add_VPN_user_global_admin(self): e) return - @attr(tags=["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns", "selfservice"]) def test_07_add_VPN_user_domain_admin(self): """Test as domain admin, add a new VPN user to an existing VPN entry that was created by another account.""" diff --git a/test/integration/smoke/test_affinity_groups.py b/test/integration/smoke/test_affinity_groups.py index c96a580f19..b118364768 100644 --- a/test/integration/smoke/test_affinity_groups.py +++ b/test/integration/smoke/test_affinity_groups.py @@ -108,7 +108,7 @@ def setUpClass(cls): ] return - @attr(tags=["simulator", "basic", "advanced", "multihost"]) + @attr(tags=["simulator", "basic", "advanced", "multihost", "selfservice"]) def test_DeployVmAntiAffinityGroup(self): """ test DeployVM in anti-affinity groups diff --git a/test/integration/smoke/test_deploy_vgpu_enabled_vm.py b/test/integration/smoke/test_deploy_vgpu_enabled_vm.py index a09e87e6f2..32c618991d 100644 --- a/test/integration/smoke/test_deploy_vgpu_enabled_vm.py +++ b/test/integration/smoke/test_deploy_vgpu_enabled_vm.py @@ -146,7 +146,7 @@ def setUp(self): self.account ] - @attr(tags = ['advanced', 'simulator', 'basic', 'vgpu']) + @attr(tags = ['advanced', 'simulator', 'basic', 'vgpu', 'provisioning']) def test_deploy_vgpu_enabled_vm(self): """Test Deploy Virtual Machine diff --git a/test/integration/smoke/test_deploy_vm.py b/test/integration/smoke/test_deploy_vm.py index fcde2294df..9f3633c95e 100644 --- a/test/integration/smoke/test_deploy_vm.py +++ b/test/integration/smoke/test_deploy_vm.py @@ -101,7 +101,7 @@ def setUp(self): self.account ] - @attr(tags = ['advanced', 'simulator', 'basic', 'sg']) + @attr(tags = ['advanced', 'simulator', 'basic', 'sg', 'selfservice']) def test_deploy_vm(self): """Test Deploy Virtual Machine @@ -154,7 +154,7 @@ def test_deploy_vm(self): msg="VM is not in Running state" ) - @attr(tags = ['advanced', 'simulator', 'basic', 'sg']) + @attr(tags = ['advanced', 'simulator', 'basic', 'sg', 'selfservice']) def test_deploy_vm_multiple(self): """Test Multiple Deploy Virtual Machine diff --git a/test/integration/smoke/test_deploy_vm_root_resize.py b/test/integration/smoke/test_deploy_vm_root_resize.py new file mode 100644 index 0000000000..aa88beb28c --- /dev/null +++ b/test/integration/smoke/test_deploy_vm_root_resize.py @@ -0,0 +1,263 @@ +# 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. + +#Test from the Marvin - Testing in Python wiki + +#All tests inherit from cloudstackTestCase +from marvin.cloudstackTestCase import cloudstackTestCase + +#Import Integration Libraries + +#base - contains all resources as entities and defines create, delete, list operations on them +from marvin.integration.lib.base import Account, VirtualMachine, ServiceOffering + +#utils - utility classes for common cleanup, external library wrappers etc +from marvin.integration.lib.utils import cleanup_resources + +#common - commonly used methods for all tests are listed here +from marvin.integration.lib.common import get_zone, get_domain, get_template, list_volumes + +from nose.plugins.attrib import attr + +class TestData(object): + """Test data object that is required to create resources + """ + def __init__(self): + self.testdata = { + #data to create an account + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + "password": "password", + }, + #data reqd for virtual machine creation + "virtual_machine" : { + "name" : "testvm", + "displayname" : "Test VM", + }, + #small service offering + "service_offering": { + "small": { + "name": "Small Instance", + "displaytext": "Small Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + }, + }, + "ostype": 'CentOS 5.3 (64-bit)', + } + +class TestDeployVM(cloudstackTestCase): + """Test deploy a VM into a user account + """ + + def setUp(self): + self.testdata = TestData().testdata + self.apiclient = self.testClient.getApiClient() + + # Get Zone, Domain and Default Built-in template + self.domain = get_domain(self.apiclient, self.testdata) + self.zone = get_zone(self.apiclient, self.testdata) + self.testdata["mode"] = self.zone.networktype + self.template = get_template(self.apiclient, self.zone.id, self.testdata["ostype"]) +# for testing with specific template +# self.template = get_template(self.apiclient, self.zone.id, self.testdata["ostype"], templatetype='USER', services = {"template":'31f52a4d-5681-43f7-8651-ad4aaf823618'}) + + + #create a user account + self.account = Account.create( + self.apiclient, + self.testdata["account"], + domainid=self.domain.id + ) + #create a service offering + self.service_offering = ServiceOffering.create( + self.apiclient, + self.testdata["service_offering"]["small"] + ) + #build cleanup list + self.cleanup = [ + self.service_offering, + self.account + ] + + @attr(tags = ['advanced', 'simulator', 'basic', 'sg', 'provisioning']) + def test_00_deploy_vm_root_resize(self): + """Test deploy virtual machine with root resize + + # Validate the following: + # 1. listVirtualMachines returns accurate information + # 2. root disk has new size per listVolumes + # 3. Rejects non-supported hypervisor types + """ + if(self.apiclient.hypervisor == 'kvm'): + newrootsize = (self.template.size >> 30) + 2 + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + + list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s"\ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vms, list), + True, + "List VM response was not a valid list" + ) + self.assertNotEqual( + len(list_vms), + 0, + "List VM response was empty" + ) + + vm = list_vms[0] + self.assertEqual( + vm.id, + self.virtual_machine.id, + "Virtual Machine ids do not match" + ) + self.assertEqual( + vm.name, + self.virtual_machine.name, + "Virtual Machine names do not match" + ) + self.assertEqual( + vm.state, + "Running", + msg="VM is not in Running state" + ) + + # get root vol from created vm, verify it is correct size + list_volume_response = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True + ) + + rootvolume = list_volume_response[0] + success = False + if rootvolume is not None and rootvolume.size == (newrootsize << 30): + success = True + + self.assertEqual( + success, + True, + "Check if the root volume resized appropriately" + ) + else: + self.debug("hypervisor %s unsupported for test 00, verifying it errors properly" % self.apiclient.hypervisor) + + newrootsize = (self.template.size >> 30) + 2 + success = False + try: + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + except Exception as ex: + if "Hypervisor XenServer does not support rootdisksize override" in str(ex): + success = True + else: + self.debug("virtual machine create did not fail appropriately. Error was actually : " + str(ex)); + + self.assertEqual(success, True, "Check if unsupported hypervisor %s fails appropriately" % self.apiclient.hypervisor) + + @attr(tags = ['advanced', 'simulator', 'basic', 'sg', 'provisioning']) + def test_01_deploy_vm_root_resize(self): + """Test proper failure to deploy virtual machine with rootdisksize of 0 + """ + if (self.apiclient.hypervisor == 'kvm'): + newrootsize = 0 + success = False + try: + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + except Exception as ex: + if "rootdisk size should be a non zero number" in str(ex): + success = True + else: + self.debug("virtual machine create did not fail appropriately. Error was actually : " + str(ex)); + + self.assertEqual(success, True, "Check if passing 0 as rootdisksize fails appropriately") + else: + self.debug("test 01 does not support hypervisor type " + self.apiclient.hypervisor); + + @attr(tags = ['advanced', 'simulator', 'basic', 'sg', 'provisioning']) + def test_02_deploy_vm_root_resize(self): + """Test proper failure to deploy virtual machine with rootdisksize less than template size + """ + if (self.apiclient.hypervisor == 'kvm'): + newrootsize = (self.template.size >> 30) - 1 + + self.assertEqual(newrootsize > 0, True, "Provided template is less than 1G in size, cannot run test") + + success = False + try: + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + rootdisksize=newrootsize + ) + except Exception as ex: + if "rootdisksize override is smaller than template size" in str(ex): + success = True + else: + self.debug("virtual machine create did not fail appropriately. Error was actually : " + str(ex)); + + self.assertEqual(success, True, "Check if passing rootdisksize < templatesize fails appropriately") + else: + self.debug("test 01 does not support hypervisor type " + self.apiclient.hypervisor); + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + self.debug("Warning! Exception in tearDown: %s" % e) diff --git a/test/integration/smoke/test_deploy_vm_with_userdata.py b/test/integration/smoke/test_deploy_vm_with_userdata.py index e3788cfbc2..b8be83a17e 100644 --- a/test/integration/smoke/test_deploy_vm_with_userdata.py +++ b/test/integration/smoke/test_deploy_vm_with_userdata.py @@ -92,7 +92,7 @@ def setUpClass(cls): user_data = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(2500)) cls.services["virtual_machine"]["userdata"] = user_data - @attr(tags=["simulator", "devcloud", "basic", "advanced"]) + @attr(tags=["simulator", "devcloud", "basic", "advanced", "provisioning"]) def test_deployvm_userdata_post(self): """Test userdata as POST, size > 2k """ @@ -117,7 +117,7 @@ def test_deployvm_userdata_post(self): self.assert_(vm.id == str(deployVmResponse.id), "Vm deployed is different from the test") self.assert_(vm.state == "Running", "VM is not in Running state") - @attr(tags=["simulator", "devcloud", "basic", "advanced"]) + @attr(tags=["simulator", "devcloud", "basic", "advanced", "provisioning"]) def test_deployvm_userdata(self): """Test userdata as GET, size > 2k """ diff --git a/test/integration/smoke/test_deploy_vms_with_varied_deploymentplanners.py b/test/integration/smoke/test_deploy_vms_with_varied_deploymentplanners.py index b4d35e0305..fc11549c8c 100644 --- a/test/integration/smoke/test_deploy_vms_with_varied_deploymentplanners.py +++ b/test/integration/smoke/test_deploy_vms_with_varied_deploymentplanners.py @@ -82,7 +82,7 @@ def setUpClass(cls): cls.account ] - @attr(tags=["simulator", "advanced", "basic", "sg"]) + @attr(tags=["simulator", "advanced", "basic", "sg", "selfservice"]) def test_deployvm_firstfit(self): """Test to deploy vm with a first fit offering """ @@ -126,7 +126,7 @@ def test_deployvm_firstfit(self): msg="VM is not in Running state" ) - @attr(tags=["simulator", "advanced", "basic", "sg"]) + @attr(tags=["simulator", "advanced", "basic", "sg", "selfservice"]) def test_deployvm_userdispersing(self): """Test deploy VMs using user dispersion planner """ @@ -185,7 +185,7 @@ def test_deployvm_userdispersing(self): self.debug("VMs (%s, %s) meant to be dispersed are deployed in the same cluster %s" % ( vm1.id, vm2.id, vm1clusterid)) - @attr(tags=["simulator", "advanced", "basic", "sg"]) + @attr(tags=["simulator", "advanced", "basic", "sg", "selfservice"]) def test_deployvm_userconcentrated(self): """Test deploy VMs using user concentrated planner """ diff --git a/test/integration/smoke/test_disk_offerings.py b/test/integration/smoke/test_disk_offerings.py index 4588a26c8b..4c8a34c953 100644 --- a/test/integration/smoke/test_disk_offerings.py +++ b/test/integration/smoke/test_disk_offerings.py @@ -58,14 +58,14 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "simulator", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "simulator", "smoke", "selfservice"]) def test_01_create_disk_offering(self): - """Test to create disk offering""" + """Test to create disk offering # Validate the following: # 1. createDiskOfferings should return valid info for new offering # 2. The Cloud Database contains the valid information - + """ disk_offering = DiskOffering.create( self.apiclient, self.services["off"] @@ -144,15 +144,16 @@ def tearDownClass(cls): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "simulator", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "simulator", "smoke", "selfservice"]) def test_02_edit_disk_offering(self): - """Test to update existing disk offering""" + """Test to update existing disk offering # Validate the following: # 1. updateDiskOffering should return # a valid information for newly created offering #Generate new name & displaytext from random data + """ random_displaytext = random_gen() random_name = random_gen() @@ -195,14 +196,14 @@ def test_02_edit_disk_offering(self): ) return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "simulator", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "simulator", "smoke", "selfservice"]) def test_03_delete_disk_offering(self): - """Test to delete disk offering""" + """Test to delete disk offering # Validate the following: # 1. deleteDiskOffering should return # a valid information for newly created offering - + """ self.disk_offering_2.delete(self.apiclient) self.debug("Deleted Disk offering with ID: %s" % diff --git a/test/integration/smoke/test_global_settings.py b/test/integration/smoke/test_global_settings.py index 5cd3654b22..f94cf940b1 100644 --- a/test/integration/smoke/test_global_settings.py +++ b/test/integration/smoke/test_global_settings.py @@ -32,7 +32,7 @@ class TestUpdateConfigWithScope(cloudstackTestCase): def setUp(self): self.apiClient = self.testClient.getApiClient() - @attr(tags=["simulator", "devcloud", "basic", "advanced"]) + @attr(tags=["simulator", "devcloud", "basic", "advanced", "selfservice"]) def test_UpdateConfigParamWithScope(self): """ test update configuration setting at zone level scope diff --git a/test/integration/smoke/test_guest_vlan_range.py b/test/integration/smoke/test_guest_vlan_range.py index 07e141d0fe..27225a5469 100644 --- a/test/integration/smoke/test_guest_vlan_range.py +++ b/test/integration/smoke/test_guest_vlan_range.py @@ -99,13 +99,14 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["simulator", "advanced", "guestvlanrange", "dedicate", "release"]) + @attr(tags=["simulator", "advanced", "guestvlanrange", "dedicate", "release", "selfservice"]) def test_dedicateGuestVlanRange(self): """Test guest vlan range dedication """ """Assume a physical network is available """ + """ # Validate the following: # 1. List the available physical network using ListPhysicalNetwork # 2. Add a Guest Vlan range to the available physical network using UpdatePhysicalNetwork @@ -114,7 +115,7 @@ def test_dedicateGuestVlanRange(self): # 5. Release the dedicated guest vlan range back to the system # 6. Verify guest vlan range has been released, verify with listDedicatedGuestVlanRanges # 7. Remove the added guest vlan range using UpdatePhysicalNetwork - + """ self.debug("Adding guest vlan range") diff --git a/test/integration/smoke/test_hosts.py b/test/integration/smoke/test_hosts.py index 6f7d400eda..0810baca55 100644 --- a/test/integration/smoke/test_hosts.py +++ b/test/integration/smoke/test_hosts.py @@ -118,18 +118,19 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @unittest.skip("skipped - our environments will not add hosts") + @attr(tags=["selfservice"]) def test_01_clusters(self): - """Test Add clusters & hosts - XEN, KVM, VWARE - """ + """Test Add clusters & hosts - simulator + # Validate the following: - # 1. Verify hypervisortype returned by API is Xen/KVM/VWare + # 1. Verify hypervisortype returned by API is Simulator/Xen/KVM/VWare # 2. Verify that the cluster is in 'Enabled' allocation state # 3. Verify that the host is added successfully and in Up state # with listHosts API response - #Create clusters with Hypervisor type XEN/KVM/VWare + #Create clusters with Hypervisor type Simulator/XEN/KVM/VWare + """ for k, v in self.services["clusters"].items(): cluster = Cluster.create( self.apiclient, diff --git a/test/integration/smoke/test_internal_lb.py b/test/integration/smoke/test_internal_lb.py index 7510169921..875df04fc4 100644 --- a/test/integration/smoke/test_internal_lb.py +++ b/test/integration/smoke/test_internal_lb.py @@ -103,12 +103,12 @@ def setUpClass(cls): cls.account.id)) cls.cleanup = [cls.account] - @attr(tags=["smoke", "advanced"]) + @attr(tags=["smoke", "advanced", "provisioning"]) def test_internallb(self): """Test create, delete, assign, remove of internal loadbalancer + #1) Create and enable network offering with Internal Lb vm service """ - - #1) Create and enable network offering with Internal Lb vm service + #TODO: SIMENH:modify this test to verify lb rules by sending request from another tier self.networkOffering = NetworkOffering.create(self.apiclient, self.services["network_offering"], conservemode=False) self.networkOffering.update(self.apiclient, state="Enabled") diff --git a/test/integration/smoke/test_iso.py b/test/integration/smoke/test_iso.py index 75289b8fbe..5312d71ac7 100644 --- a/test/integration/smoke/test_iso.py +++ b/test/integration/smoke/test_iso.py @@ -83,7 +83,8 @@ def __init__(self): class TestCreateIso(cloudstackTestCase): - +#TODO: SIMENH: check the existence of registered of ISO in secondary deploy a VM with registered ISO. can be added \ +# as another test def setUp(self): self.services = Services().services self.apiclient = self.testClient.getApiClient() @@ -125,7 +126,7 @@ def tearDown(self): return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke", "selfservice"]) def test_01_create_iso(self): """Test create public & private ISO """ @@ -279,7 +280,7 @@ def tearDown(self): return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke", "selfservice"]) def test_02_edit_iso(self): """Test Edit ISO """ @@ -344,7 +345,7 @@ def test_02_edit_iso(self): ) return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke", "selfservice"]) def test_03_delete_iso(self): """Test delete ISO """ @@ -372,7 +373,7 @@ def test_03_delete_iso(self): ) return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke", "provisioning"]) def test_04_extract_Iso(self): "Test for extract ISO" @@ -423,7 +424,7 @@ def test_04_extract_Iso(self): ) return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke", "selfservice"]) def test_05_iso_permissions(self): """Update & Test for ISO permissions""" @@ -475,7 +476,7 @@ def test_05_iso_permissions(self): ) return - @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke", "multizone"]) + @attr(tags = ["advanced", "basic", "eip", "sg", "advancedns", "smoke", "multizone", "provisioning"]) def test_06_copy_iso(self): """Test for copy ISO from one zone to another""" diff --git a/test/integration/smoke/test_loadbalance.py b/test/integration/smoke/test_loadbalance.py index 5f80c38303..46eb7d49dc 100644 --- a/test/integration/smoke/test_loadbalance.py +++ b/test/integration/smoke/test_loadbalance.py @@ -211,7 +211,7 @@ def try_ssh(self, ip_addr, hostnames): time.sleep(self.services["lb_switch_wait"]) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_01_create_lb_rule_src_nat(self): """Test to create Load balancing rule with source NAT""" @@ -371,7 +371,7 @@ def test_01_create_lb_rule_src_nat(self): self.try_ssh(src_nat_ip_addr.ipaddress, hostnames) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_02_create_lb_rule_non_nat(self): """Test to create Load balancing rule with non source NAT""" @@ -489,7 +489,7 @@ def test_02_create_lb_rule_non_nat(self): self.try_ssh(self.non_src_nat_ip.ipaddress.ipaddress, hostnames) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_assign_and_removal_lb(self): """Test for assign & removing load balancing rule""" diff --git a/test/integration/smoke/test_multipleips_per_nic.py b/test/integration/smoke/test_multipleips_per_nic.py index 7d180641d6..0c6c02a05b 100644 --- a/test/integration/smoke/test_multipleips_per_nic.py +++ b/test/integration/smoke/test_multipleips_per_nic.py @@ -150,8 +150,9 @@ def setUp(self): msg="VM is not in Running state" ) - @attr(tags = ['advanced', 'simulator', 'basic']) + @attr(tags = ['advanced', 'simulator', 'basic', "provisioning"]) def test_nic_secondaryip_add_remove(self): + #TODO: SIMENH: add verification list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) vm = list_vms[0] nicid = vm.nic[0].id diff --git a/test/integration/smoke/test_network.py b/test/integration/smoke/test_network.py index 732fe15825..2cdcfa277b 100644 --- a/test/integration/smoke/test_network.py +++ b/test/integration/smoke/test_network.py @@ -187,7 +187,7 @@ def tearDownClass(cls): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_public_ip_admin_account(self): """Test for Associate/Disassociate public IP address for admin account""" @@ -237,7 +237,7 @@ def test_public_ip_admin_account(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_public_ip_user_account(self): """Test for Associate/Disassociate public IP address for user account""" @@ -347,7 +347,7 @@ def tearDown(self): cleanup_resources(self.apiclient, self.cleanup) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_01_port_fwd_on_src_nat(self): """Test for port forwarding on source NAT""" @@ -470,7 +470,7 @@ def test_01_port_fwd_on_src_nat(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_02_port_fwd_on_non_src_nat(self): """Test for port forwarding on non source NAT""" @@ -680,7 +680,7 @@ def setUp(self): ] return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_reboot_router(self): """Test for reboot router""" @@ -835,7 +835,7 @@ def setUp(self): def tearDown(self): cleanup_resources(self.apiclient, self.cleanup) - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_releaseIP(self): """Test for release public IP address""" @@ -960,7 +960,7 @@ def setUp(self): self.cleanup = [] return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_delete_account(self): """Test for delete account""" diff --git a/test/integration/smoke/test_network_acl.py b/test/integration/smoke/test_network_acl.py index 3363e460dd..69134e565c 100644 --- a/test/integration/smoke/test_network_acl.py +++ b/test/integration/smoke/test_network_acl.py @@ -100,8 +100,9 @@ def setUpClass(cls): cls.account.id)) cls.cleanup = [cls.account] - @attr(tags=["advanced"]) + @attr(tags=["advanced", "provisioning"]) def test_network_acl(self): + #TODO: SIMENH: add actual verification Logic for rules. """Test network ACL lists and items in VPC""" # 0) Get the default network offering for VPC diff --git a/test/integration/smoke/test_nic.py b/test/integration/smoke/test_nic.py index ac95685f37..4ba905a241 100644 --- a/test/integration/smoke/test_nic.py +++ b/test/integration/smoke/test_nic.py @@ -224,8 +224,9 @@ def signal_handler(signal, frame): except Exception as ex: self.debug("Exception during NIC test SETUP!: " + str(ex)) - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_01_nic(self): + #TODO: SIMENH: add validation """Test to add and update added nic to a virtual machine""" try: diff --git a/test/integration/smoke/test_non_contigiousvlan.py b/test/integration/smoke/test_non_contigiousvlan.py index f1736ae447..2f23add2a4 100644 --- a/test/integration/smoke/test_non_contigiousvlan.py +++ b/test/integration/smoke/test_non_contigiousvlan.py @@ -32,7 +32,7 @@ def __init__(self): } -@attr(tags = ["simulator", "advanced"]) +@attr(tags = ["simulator", "advanced", "selfservice"]) class TestUpdatePhysicalNetwork(cloudstackTestCase): """ Test to extend physical network vlan range diff --git a/test/integration/smoke/test_over_provisioning.py b/test/integration/smoke/test_over_provisioning.py index 28f32b7af9..7d10fc77e8 100644 --- a/test/integration/smoke/test_over_provisioning.py +++ b/test/integration/smoke/test_over_provisioning.py @@ -32,7 +32,7 @@ class TestUpdateOverProvision(cloudstackTestCase): def setUp(self): self.apiClient = self.testClient.getApiClient() - @attr(tags=["simulator", "devcloud", "basic", "advanced"]) + @attr(tags=["simulator", "devcloud", "basic", "advanced", "selfservice"]) def test_UpdateStorageOverProvisioningFactor(self): """ test update configuration setting at storage scope diff --git a/test/integration/smoke/test_portable_publicip.py b/test/integration/smoke/test_portable_publicip.py index 0faed7163c..efbd4836c6 100644 --- a/test/integration/smoke/test_portable_publicip.py +++ b/test/integration/smoke/test_portable_publicip.py @@ -135,7 +135,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["simulator", "basic", "advanced", "portablepublicip"]) + @attr(tags = ["simulator", "basic", "advanced", "portablepublicip", "selfservice"]) def test_createPortablePublicIPRange(self): """ Test to create a portable public ip range """ @@ -219,7 +219,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["simulator", "advanced", "portablepublicip"]) + @attr(tags = ["simulator", "advanced", "portablepublicip", "selfservice"]) def test_createPortablePublicIPAcquire(self): """ Test to acquire a provisioned public ip range """ diff --git a/test/integration/smoke/test_primary_storage.py b/test/integration/smoke/test_primary_storage.py index 5cf31b13d8..7113966c23 100644 --- a/test/integration/smoke/test_primary_storage.py +++ b/test/integration/smoke/test_primary_storage.py @@ -70,7 +70,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_01_primary_storage_nfs(self): """Test primary storage pools - XEN, KVM, VMWare """ @@ -163,7 +163,7 @@ def test_01_primary_storage_nfs(self): return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_01_primary_storage_iscsi(self): """Test primary storage pools - XEN, KVM, VMWare """ diff --git a/test/integration/smoke/test_privategw_acl.py b/test/integration/smoke/test_privategw_acl.py index 9c37e5e7fc..ec5ef8b60c 100644 --- a/test/integration/smoke/test_privategw_acl.py +++ b/test/integration/smoke/test_privategw_acl.py @@ -39,8 +39,9 @@ def setUp(self): self.privateGwId = None - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_privategw_acl(self): + #TODO: SIMENH: add a new test to verification of ACL rules # 1) Create VPC self.createVPC() diff --git a/test/integration/smoke/test_public_ip_range.py b/test/integration/smoke/test_public_ip_range.py index e1d78d99d1..759e107799 100644 --- a/test/integration/smoke/test_public_ip_range.py +++ b/test/integration/smoke/test_public_ip_range.py @@ -96,7 +96,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["simulator", "advanced", "publiciprange", "dedicate", "release"]) + @attr(tags = ["simulator", "advanced", "publiciprange", "dedicate", "release", "selfservice"]) def test_dedicatePublicIpRange(self): """Test public IP range dedication """ diff --git a/test/integration/smoke/test_pvlan.py b/test/integration/smoke/test_pvlan.py index aeb47f953c..09b12ccd0e 100644 --- a/test/integration/smoke/test_pvlan.py +++ b/test/integration/smoke/test_pvlan.py @@ -41,7 +41,7 @@ class TestPVLAN(cloudstackTestCase): def setUp(self): self.apiClient = self.testClient.getApiClient() - @attr(tags = ["advanced"]) + @attr(tags = ["advanced", "selfservice"]) def test_create_pvlan_network(self): self.debug("Test create pvlan network") createNetworkCmd = createNetwork.createNetworkCmd() diff --git a/test/integration/smoke/test_regions.py b/test/integration/smoke/test_regions.py index 5d12e74e8d..71900b4a6b 100644 --- a/test/integration/smoke/test_regions.py +++ b/test/integration/smoke/test_regions.py @@ -44,7 +44,7 @@ def setUpClass(cls): cls.domain = get_domain(cls.api_client, cls.services) cls.cleanup = [] - @attr(tags=["simulator", "basic", "advanced"]) + @attr(tags=["simulator", "basic", "advanced", "selfservice"]) def test_createRegion(self): """ Test for create region """ diff --git a/test/integration/smoke/test_reset_vm_on_reboot.py b/test/integration/smoke/test_reset_vm_on_reboot.py index 4e52f0fa8d..6cb63e3647 100644 --- a/test/integration/smoke/test_reset_vm_on_reboot.py +++ b/test/integration/smoke/test_reset_vm_on_reboot.py @@ -146,8 +146,9 @@ def tearDown(self): return @attr(hypervisor="xenserver") - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "selfservice"]) def test_01_reset_vm_on_reboot(self): + #TODO: SIMENH: add new test to check volume contents """Test reset virtual machine on reboot """ # Validate the following diff --git a/test/integration/smoke/test_resource_detail.py b/test/integration/smoke/test_resource_detail.py index 00a7b5c417..a0cac9b21b 100644 --- a/test/integration/smoke/test_resource_detail.py +++ b/test/integration/smoke/test_resource_detail.py @@ -156,7 +156,7 @@ def tearDown(self): cleanup_resources(self.apiclient, self.cleanup) return - @attr(tags = ["advanced", "xenserver"]) + @attr(tags = ["advanced", "xenserver", "selfservice"]) def test_01_updatevolumedetail(self): """Test volume detail """ diff --git a/test/integration/smoke/test_routers.py b/test/integration/smoke/test_routers.py index 7d324136e8..2bd1d5ecfd 100644 --- a/test/integration/smoke/test_routers.py +++ b/test/integration/smoke/test_routers.py @@ -130,7 +130,7 @@ def setUp(self): self.apiclient = self.testClient.getApiClient() return - @attr(tags = ["advanced", "basic", "sg", "smoke"]) + @attr(tags = ["advanced", "basic", "sg", "smoke", "provisioning"]) def test_01_router_internal_basic(self): """Test router internal basic zone """ @@ -218,7 +218,7 @@ def test_01_router_internal_basic(self): - @attr(tags = ["advanced", "smoke"]) + @attr(tags = ["advanced", "smoke", "provisioning"]) def test_02_router_internal_adv(self): """Test router internal advanced zone """ @@ -326,7 +326,7 @@ def test_02_router_internal_adv(self): self.debug("Haproxy process status: %s" % res) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_03_restart_network_cleanup(self): """Test restart network """ @@ -404,7 +404,7 @@ def test_03_restart_network_cleanup(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_04_restart_network_wo_cleanup(self): """Test restart network without cleanup """ @@ -520,7 +520,7 @@ def test_04_restart_network_wo_cleanup(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_05_router_basic(self): """Test router basic setup """ @@ -586,7 +586,7 @@ def test_05_router_basic(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_06_router_advanced(self): """Test router advanced setup """ @@ -669,7 +669,7 @@ def test_06_router_advanced(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_07_stop_router(self): """Test stop router """ @@ -713,7 +713,7 @@ def test_07_stop_router(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_08_start_router(self): """Test start router """ @@ -758,7 +758,7 @@ def test_08_start_router(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_09_reboot_router(self): """Test reboot router """ diff --git a/test/integration/smoke/test_scale_vm.py b/test/integration/smoke/test_scale_vm.py index 1d1726dc90..8b73efe649 100644 --- a/test/integration/smoke/test_scale_vm.py +++ b/test/integration/smoke/test_scale_vm.py @@ -159,7 +159,7 @@ def tearDown(self): return @attr(hypervisor="xenserver") - @attr(tags=["advanced", "basic"]) + @attr(tags=["advanced", "basic", "provisioning"]) def test_01_scale_vm(self): """Test scale virtual machine """ diff --git a/test/integration/smoke/test_secondary_storage.py b/test/integration/smoke/test_secondary_storage.py index ff9692f9c8..b36b10ef91 100644 --- a/test/integration/smoke/test_secondary_storage.py +++ b/test/integration/smoke/test_secondary_storage.py @@ -81,7 +81,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "eip", "sg", "selfservice"]) def test_01_sys_vm_start(self): """Test system VM start """ @@ -160,7 +160,7 @@ def test_01_sys_vm_start(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "eip", "sg", "selfservice"]) def test_02_sys_template_ready(self): """Test system templates are ready """ diff --git a/test/integration/smoke/test_service_offerings.py b/test/integration/smoke/test_service_offerings.py index 968dc5622f..70865b4544 100644 --- a/test/integration/smoke/test_service_offerings.py +++ b/test/integration/smoke/test_service_offerings.py @@ -133,7 +133,7 @@ def tearDown(self): return - @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg", "selfservice"]) def test_01_create_service_offering(self): """Test to create service offering""" @@ -280,7 +280,7 @@ def tearDownClass(cls): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg", "selfservice"]) def test_02_edit_service_offering(self): """Test to update existing service offering""" @@ -331,7 +331,7 @@ def test_02_edit_service_offering(self): return - @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg", "selfservice"]) def test_03_delete_service_offering(self): """Test to delete service offering""" @@ -357,7 +357,7 @@ def test_03_delete_service_offering(self): return - @attr(tags=["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "provisioning"]) def test_04_change_offering_small(self): """Test to change service to a small capacity """ diff --git a/test/integration/smoke/test_snapshots.py b/test/integration/smoke/test_snapshots.py index 6ee7c6271c..8b334520a3 100644 --- a/test/integration/smoke/test_snapshots.py +++ b/test/integration/smoke/test_snapshots.py @@ -196,7 +196,7 @@ def tearDown(self): return @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "provisioning"]) def test_01_snapshot_root_disk(self): """Test Snapshot Root Disk """ diff --git a/test/integration/smoke/test_ssvm.py b/test/integration/smoke/test_ssvm.py index a2b9eabc13..cf40907209 100644 --- a/test/integration/smoke/test_ssvm.py +++ b/test/integration/smoke/test_ssvm.py @@ -60,7 +60,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_01_list_sec_storage_vm(self): """Test List secondary storage VMs """ @@ -178,7 +178,7 @@ def test_01_list_sec_storage_vm(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_02_list_cpvm_vm(self): """Test List console proxy VMs """ @@ -290,7 +290,7 @@ def test_02_list_cpvm_vm(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_03_ssvm_internals(self): """Test SSVM Internals""" @@ -403,7 +403,7 @@ def test_03_ssvm_internals(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_04_cpvm_internals(self): """Test CPVM Internals""" @@ -486,7 +486,7 @@ def test_04_cpvm_internals(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_05_stop_ssvm(self): """Test stop SSVM """ @@ -562,7 +562,7 @@ def test_05_stop_ssvm(self): self.test_03_ssvm_internals() return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_06_stop_cpvm(self): """Test stop CPVM """ @@ -635,7 +635,7 @@ def test_06_stop_cpvm(self): self.test_04_cpvm_internals() return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_07_reboot_ssvm(self): """Test reboot SSVM """ @@ -721,7 +721,7 @@ def test_07_reboot_ssvm(self): self.test_03_ssvm_internals() return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_08_reboot_cpvm(self): """Test reboot CPVM """ @@ -808,7 +808,7 @@ def test_08_reboot_cpvm(self): self.test_04_cpvm_internals() return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_09_destroy_ssvm(self): """Test destroy SSVM """ @@ -890,7 +890,7 @@ def test_09_destroy_ssvm(self): self.test_03_ssvm_internals() return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_10_destroy_cpvm(self): """Test destroy CPVM """ diff --git a/test/integration/smoke/test_templates.py b/test/integration/smoke/test_templates.py index e371ad436a..32b3696d03 100644 --- a/test/integration/smoke/test_templates.py +++ b/test/integration/smoke/test_templates.py @@ -219,7 +219,7 @@ def tearDownClass(cls): return - @attr(tags = ["advanced", "advancedns", "smoke"]) + @attr(tags = ["advanced", "advancedns", "smoke", "selfservice"]) def test_01_create_template(self): """Test create public & private template """ @@ -438,7 +438,7 @@ def tearDown(self): return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_02_edit_template(self): """Test Edit template """ @@ -521,7 +521,7 @@ def test_02_edit_template(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_03_delete_template(self): """Test delete template """ @@ -550,7 +550,7 @@ def test_03_delete_template(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_04_extract_template(self): "Test for extract template" @@ -601,7 +601,7 @@ def test_04_extract_template(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_05_template_permissions(self): """Update & Test for template permissions""" @@ -654,7 +654,7 @@ def test_05_template_permissions(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "multizone"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "multizone", "provisioning"]) def test_06_copy_template(self): """Test for copy template from one zone to another""" @@ -745,7 +745,7 @@ def test_06_copy_template(self): self.apiclient.deleteTemplate(cmd) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_07_list_public_templates(self): """Test only public templates are visible to normal user""" @@ -777,7 +777,7 @@ def test_07_list_public_templates(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_08_list_system_templates(self): """Test System templates are not visible to normal user""" diff --git a/test/integration/smoke/test_vm_iam.py b/test/integration/smoke/test_vm_iam.py index 29e587bbd3..80c049b0cd 100644 --- a/test/integration/smoke/test_vm_iam.py +++ b/test/integration/smoke/test_vm_iam.py @@ -280,7 +280,7 @@ def tearDown(self): - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_01_list_own_vm(self): # listVM command should return owne's VM @@ -357,7 +357,7 @@ def test_01_list_own_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_02_grant_domain_vm(self): # Validate the following @@ -406,7 +406,7 @@ def test_02_grant_domain_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_03_grant_account_vm(self): # Validate the following @@ -459,7 +459,7 @@ def test_03_grant_account_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_04_revoke_account_vm(self): # Validate the following @@ -502,7 +502,7 @@ def test_04_revoke_account_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_05_revoke_domain_vm(self): # Validate the following @@ -543,7 +543,7 @@ def test_05_revoke_domain_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_06_grant_resource_vm(self): # Validate the following @@ -590,7 +590,7 @@ def test_06_grant_resource_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_07_revoke_resource_vm(self): # Validate the following @@ -632,7 +632,7 @@ def test_07_revoke_resource_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_08_policy_attach_account(self): # Validate the following @@ -680,7 +680,7 @@ def test_08_policy_attach_account(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_09_policy_detach_account(self): # Validate the following diff --git a/test/integration/smoke/test_vm_life_cycle.py b/test/integration/smoke/test_vm_life_cycle.py index c164f59985..7d47f70f26 100644 --- a/test/integration/smoke/test_vm_life_cycle.py +++ b/test/integration/smoke/test_vm_life_cycle.py @@ -258,6 +258,7 @@ def test_deploy_vm(self): @attr(tags = ["simulator", "advanced"]) def test_advZoneVirtualRouter(self): + #TODO: SIMENH: duplicate test, remove it """ Test advanced zone virtual router 1. Is Running @@ -280,6 +281,7 @@ def test_advZoneVirtualRouter(self): @attr(hypervisor = ["simulator"]) @attr(mode = ["basic"]) def test_basicZoneVirtualRouter(self): + #TODO: SIMENH: duplicate test, remove it """ Tests for basic zone virtual router 1. Is Running @@ -393,7 +395,7 @@ def tearDown(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_01_stop_vm(self): """Test Stop Virtual Machine """ @@ -429,7 +431,7 @@ def test_01_stop_vm(self): ) return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_02_start_vm(self): """Test Start Virtual Machine """ @@ -467,7 +469,7 @@ def test_02_start_vm(self): ) return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_03_reboot_vm(self): """Test Reboot Virtual Machine """ @@ -504,7 +506,7 @@ def test_03_reboot_vm(self): return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_06_destroy_vm(self): """Test destroy Virtual Machine """ @@ -540,8 +542,9 @@ def test_06_destroy_vm(self): ) return - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_07_restore_vm(self): + #TODO: SIMENH: add another test the data on the restored VM. """Test recover Virtual Machine """ @@ -580,7 +583,7 @@ def test_07_restore_vm(self): return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "multihost"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "multihost", "selfservice"]) def test_08_migrate_vm(self): """Test migrate VM """ @@ -667,7 +670,7 @@ def test_08_migrate_vm(self): @attr(configuration = "expunge.interval") @attr(configuration = "expunge.delay") - @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg", "selfservice"]) def test_09_expunge_vm(self): """Test destroy(expunge) Virtual Machine """ @@ -716,7 +719,7 @@ def test_09_expunge_vm(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg", "provisioning"]) def test_10_attachAndDetach_iso(self): """Test for attach and detach ISO to virtual machine""" diff --git a/test/integration/smoke/test_vm_snapshots.py b/test/integration/smoke/test_vm_snapshots.py index b49a37c45b..65a5acbce3 100644 --- a/test/integration/smoke/test_vm_snapshots.py +++ b/test/integration/smoke/test_vm_snapshots.py @@ -150,7 +150,7 @@ def tearDown(self): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags=["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "provisioning"]) def test_01_create_vm_snapshots(self): """Test to create VM snapshots """ @@ -194,7 +194,7 @@ def test_01_create_vm_snapshots(self): ) return - @attr(tags=["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "provisioning"]) def test_02_revert_vm_snapshots(self): """Test to revert VM snapshots """ @@ -281,7 +281,7 @@ def test_02_revert_vm_snapshots(self): "Check the random data is equal with the ramdom file!" ) - @attr(tags=["advanced", "advancedns", "smoke"]) + @attr(tags=["advanced", "advancedns", "smoke", "provisioning"]) def test_03_delete_vm_snapshots(self): """Test to delete vm snapshots """ diff --git a/test/integration/smoke/test_volumes.py b/test/integration/smoke/test_volumes.py index 8f41803638..411ecf11a6 100644 --- a/test/integration/smoke/test_volumes.py +++ b/test/integration/smoke/test_volumes.py @@ -150,7 +150,7 @@ def setUp(self): self.dbclient = self.testClient.getDbConnection() self.cleanup = [] - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "provisioning"]) def test_01_create_volume(self): """Test Volume creation for all Disk Offerings (incl. custom) """ @@ -368,7 +368,7 @@ def tearDown(self): cleanup_resources(self.apiClient, self.cleanup) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "provisioning"]) def test_02_attach_volume(self): """Attach a created Volume to a Running VM """ @@ -414,7 +414,7 @@ def test_02_attach_volume(self): (self.virtual_machine.ipaddress, e)) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "selfservice"]) def test_03_download_attached_volume(self): """Download a Volume attached to a VM """ @@ -436,7 +436,7 @@ def test_03_download_attached_volume(self): with self.assertRaises(Exception): self.apiClient.extractVolume(cmd) - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "selfservice"]) def test_04_delete_attached_volume(self): """Delete a Volume attached to a VM """ @@ -457,7 +457,7 @@ def test_04_delete_attached_volume(self): with self.assertRaises(Exception): self.apiClient.deleteVolume(cmd) - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "selfservice"]) def test_05_detach_volume(self): """Detach a Volume attached to a VM """ @@ -499,7 +499,7 @@ def test_05_detach_volume(self): ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "provisioning"]) def test_06_download_detached_volume(self): """Download a Volume unattached to an VM """ @@ -536,7 +536,7 @@ def test_06_download_detached_volume(self): % (extract_vol.url, self.volume.id) ) - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "selfservice"]) def test_07_resize_fail(self): """Test resize (negative) non-existent volume""" # Verify the size is the new size is what we wanted it to be. @@ -571,6 +571,31 @@ def test_07_resize_fail(self): success, True, "ResizeVolume - verify disk offering is handled appropriately") + + # try to resize a root disk with a disk offering, root can only be resized by size= + # get root vol from created vm + list_volume_response = list_volumes( + self.apiClient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True + ) + + rootvolume = list_volume_response[0] + + cmd.id = rootvolume.id + cmd.diskofferingid = self.services['diskofferingid'] + success = False + try: + response = self.apiClient.resizeVolume(cmd) + except Exception as ex: + if "Can only resize Data volumes" in str(ex): + success = True + self.assertEqual( + success, + True, + "ResizeVolume - verify root disks cannot be resized by disk offering id") + # Ok, now let's try and resize a volume that is not custom. cmd.id = self.volume.id cmd.diskofferingid = self.services['diskofferingid'] @@ -625,7 +650,7 @@ def test_07_resize_fail(self): return - @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "provisioning"]) def test_08_resize_volume(self): """Test resize a volume""" # Verify the size is the new size is what we wanted it to be. @@ -647,6 +672,7 @@ def test_08_resize_volume(self): elif hosts[0].hypervisor.lower() == "vmware": self.skipTest("Resize Volume is unsupported on VmWare") + # resize the data disk self.debug("Resize Volume ID: %s" % self.volume.id) cmd = resizeVolume.resizeVolumeCmd() @@ -675,7 +701,48 @@ def test_08_resize_volume(self): self.assertEqual( success, True, - "Check if the volume resized appropriately" + "Check if the data volume resized appropriately" + ) + + # resize the root disk + self.debug("Resize Root for : %s" % self.virtual_machine.id) + + # get root vol from created vm + list_volume_response = list_volumes( + self.apiClient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True + ) + + rootvolume = list_volume_response[0] + + cmd = resizeVolume.resizeVolumeCmd() + cmd.id = rootvolume.id + cmd.size = 10 + + self.apiClient.resizeVolume(cmd) + + count = 0 + success = False + while count < 3: + list_volume_response = list_volumes( + self.apiClient, + id=rootvolume.id + ) + for vol in list_volume_response: + if vol.id == rootvolume.id and vol.size == 10737418240L and vol.state == 'Ready': + success = True + if success: + break + else: + time.sleep(10) + count += 1 + + self.assertEqual( + success, + True, + "Check if the root volume resized appropriately" ) #start the vm if it is on xenserver @@ -685,7 +752,7 @@ def test_08_resize_volume(self): time.sleep(30) return - @attr(tags = ["advanced", "advancedns", "smoke","basic"]) + @attr(tags = ["advanced", "advancedns", "smoke","basic", "selfservice"]) def test_09_delete_detached_volume(self): """Delete a Volume unattached to an VM """ diff --git a/test/integration/smoke/test_vpc_vpn.py b/test/integration/smoke/test_vpc_vpn.py index 5e97c79065..0e94e25a7b 100644 --- a/test/integration/smoke/test_vpc_vpn.py +++ b/test/integration/smoke/test_vpc_vpn.py @@ -125,7 +125,7 @@ def setUpClass(cls): ) cls.cleanup = [cls.account] - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_vpc_remote_access_vpn(self): """Test VPN in VPC""" @@ -227,7 +227,7 @@ def setUpClass(cls): ) cls.cleanup = [cls.account] - @attr(tags=["advanced"]) + @attr(tags=["advanced", "selfservice"]) def test_vpc_site2site_vpn(self): """Test VPN in VPC""" diff --git a/tools/appliance/definitions/systemvm64template/postinstall.sh b/tools/appliance/definitions/systemvm64template/postinstall.sh index cc8ead9d94..f6e6cdd1fe 100644 --- a/tools/appliance/definitions/systemvm64template/postinstall.sh +++ b/tools/appliance/definitions/systemvm64template/postinstall.sh @@ -81,7 +81,7 @@ install_packages() { dpkg -i hv-kvp-daemon_3.1_amd64.deb #libraries required for rdp client (Hyper-V) - apt-get --no-install-recommends -q -y --force-yes install libtcnative-1 libssl-dev libapr1-dev + DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -qq -y --force-yes install libtcnative-1 libssl-dev libapr1-dev # vmware tools apt-get --no-install-recommends -q -y --force-yes install open-vm-tools diff --git a/tools/devcloud-kvm/devcloud-kvm-advanced-fusion.cfg b/tools/devcloud-kvm/devcloud-kvm-advanced-fusion.cfg index 53e1a441b2..2084417cbe 100644 --- a/tools/devcloud-kvm/devcloud-kvm-advanced-fusion.cfg +++ b/tools/devcloud-kvm/devcloud-kvm-advanced-fusion.cfg @@ -120,20 +120,14 @@ "port": 3306, "user": "cloud" }, - "logger": [ - { - "name": "TestClient", - "file": "/var/log/testclient.log" - }, - { - "name": "TestCase", - "file": "/var/log/testcase.log" - } - ], + "logger": { + "LogFolderPath": "/tmp/" + }, "mgtSvr": [ { "mgtSvrIp": "172.17.10.10", - "port": 8096 + "port": 8096, + "hypervisor": "kvm" } ] } diff --git a/tools/devcloud-kvm/devcloud-kvm-advanced.cfg b/tools/devcloud-kvm/devcloud-kvm-advanced.cfg index 53e1a441b2..74c36b718d 100644 --- a/tools/devcloud-kvm/devcloud-kvm-advanced.cfg +++ b/tools/devcloud-kvm/devcloud-kvm-advanced.cfg @@ -133,7 +133,8 @@ "mgtSvr": [ { "mgtSvrIp": "172.17.10.10", - "port": 8096 + "port": 8096, + "hypervisor": "kvm" } ] } diff --git a/tools/devcloud-kvm/devcloud-kvm.cfg b/tools/devcloud-kvm/devcloud-kvm.cfg index 3122e5a979..ab7f9a5276 100644 --- a/tools/devcloud-kvm/devcloud-kvm.cfg +++ b/tools/devcloud-kvm/devcloud-kvm.cfg @@ -104,7 +104,8 @@ "mgtSvr": [ { "mgtSvrIp": "127.0.0.1", - "port": 8096 + "port": 8096, + "hypervisor": "kvm" } ], "dbSvr": diff --git a/tools/marvin/marvin/codes.py b/tools/marvin/marvin/codes.py index e4a0f6a789..92d6cf9d20 100644 --- a/tools/marvin/marvin/codes.py +++ b/tools/marvin/marvin/codes.py @@ -52,3 +52,8 @@ SHARED_NETWORK = "SHARED" VPC_NETWORK = "VPC" ERROR_NO_HOST_FOR_MIGRATION = "Could not find suitable host for migration, please ensure setup has required no. of hosts" +NAT_RULE = "nat rule" +STATIC_NAT_RULE = "static nat rule" +UNKNOWN = "UNKNOWN" +FAULT = "FAULT" +MASTER = "MASTER" diff --git a/tools/marvin/marvin/config/config.cfg b/tools/marvin/marvin/config/config.cfg index 356a291191..a27806808e 100644 --- a/tools/marvin/marvin/config/config.cfg +++ b/tools/marvin/marvin/config/config.cfg @@ -256,6 +256,35 @@ "StaticNat": "VirtualRouter" } }, + "nw_off_isolated_RVR": { + "name": "Network offering-RVR services", + "displaytext": "Network off-RVR services", + "guestiptype": "Isolated", + "supportedservices": "Vpn,Dhcp,Dns,SourceNat,PortForwarding,Firewall,Lb,UserData,StaticNat", + "traffictype": "GUEST", + "availability": "Optional", + "ispersistent": "False", + "serviceProviderList": { + "Vpn": "VirtualRouter", + "Dhcp": "VirtualRouter", + "Dns": "VirtualRouter", + "SourceNat": "VirtualRouter", + "PortForwarding": "VirtualRouter", + "Firewall": "VirtualRouter", + "Lb": "VirtualRouter", + "UserData": "VirtualRouter", + "StaticNat": "VirtualRouter" + }, + "serviceCapabilityList": { + "SourceNat": { + "SupportedSourceNatTypes": "peraccount", + "RedundantRouter": "true" + }, + "lb": { + "SupportedLbIsolation": "dedicated" + } + } + }, "nw_off_persistent_RVR": { "name": "Network offering-RVR services", "displaytext": "Network off-RVR services", @@ -388,5 +417,9 @@ "securitygroupenabled": "true" }, "securitygroupenabled": "true" - } + }, + "host_anti_affinity": { + "name": "", + "type": "host anti-affinity" + } } diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py index b7e2be4755..775b289b14 100755 --- a/tools/marvin/marvin/integration/lib/base.py +++ b/tools/marvin/marvin/integration/lib/base.py @@ -325,7 +325,7 @@ def create(cls, apiclient, services, templateid=None, accountid=None, securitygroupids=None, projectid=None, startvm=None, diskofferingid=None, affinitygroupnames=None, affinitygroupids=None, group=None, hostid=None, keypair=None, ipaddress=None, mode='default', method='GET', - customcpunumber=None, customcpuspeed=None, custommemory=None): + customcpunumber=None, customcpuspeed=None, custommemory=None, rootdisksize=None): """Create the instance""" cmd = deployVirtualMachine.deployVirtualMachineCmd() @@ -413,7 +413,7 @@ def create(cls, apiclient, services, templateid=None, accountid=None, if "userdata" in services: cmd.userdata = base64.urlsafe_b64encode(services["userdata"]) - cmd.details = [{"cpuNumber": "","cpuSpeed":"","memory":""}] + cmd.details = [{}] if customcpunumber: cmd.details[0]["cpuNumber"] = customcpunumber @@ -424,6 +424,9 @@ def create(cls, apiclient, services, templateid=None, accountid=None, if custommemory: cmd.details[0]["memory"] = custommemory + if rootdisksize >= 0: + cmd.details[0]["rootdisksize"] = rootdisksize + if group: cmd.group = group diff --git a/tools/marvin/marvin/integration/lib/common.py b/tools/marvin/marvin/integration/lib/common.py index 3b292bf920..02fa5f1f1c 100644 --- a/tools/marvin/marvin/integration/lib/common.py +++ b/tools/marvin/marvin/integration/lib/common.py @@ -65,13 +65,17 @@ Host, PublicIPAddress, NetworkOffering, - Network) + Network, + FireWallRule, + NATRule, + StaticNATRule) from marvin.integration.lib.utils import (get_process_status, xsplit, validateList) from marvin.sshClient import SshClient -from marvin.codes import PASS, ISOLATED_NETWORK, VPC_NETWORK, BASIC_ZONE, FAIL +from marvin.codes import (PASS, ISOLATED_NETWORK, VPC_NETWORK, + BASIC_ZONE, FAIL, NAT_RULE, STATIC_NAT_RULE) import random #Import System modules @@ -994,8 +998,39 @@ def verifyComputeOfferingCreation(apiclient, computeofferingid): serviceOfferings = None try: serviceOfferings = apiclient.listServiceOfferings(cmd) - except Exception as e: + except Exception: return FAIL if not (isinstance(serviceOfferings, list) and len(serviceOfferings) > 0): return FAIL return PASS + +def createNetworkRulesForVM(apiclient, virtualmachine, ruletype, + account, networkruledata): + """Acquire IP, create Firewall and NAT/StaticNAT rule + (associating it with given vm) for that IP""" + + try: + public_ip = PublicIPAddress.create( + apiclient,accountid=account.name, + zoneid=virtualmachine.zoneid,domainid=account.domainid, + networkid=virtualmachine.nic[0].networkid) + + FireWallRule.create( + apiclient,ipaddressid=public_ip.ipaddress.id, + protocol='TCP', cidrlist=[networkruledata["fwrule"]["cidr"]], + startport=networkruledata["fwrule"]["startport"], + endport=networkruledata["fwrule"]["endport"] + ) + + if ruletype == NAT_RULE: + # Create NAT rule + NATRule.create(apiclient, virtualmachine, + networkruledata["natrule"],ipaddressid=public_ip.ipaddress.id, + networkid=virtualmachine.nic[0].networkid) + elif ruletype == STATIC_NAT_RULE: + # Enable Static NAT for VM + StaticNATRule.enable(apiclient,public_ip.ipaddress.id, + virtualmachine.id, networkid=virtualmachine.nic[0].networkid) + except Exception as e: + [FAIL, e] + return [PASS, public_ip] diff --git a/tools/marvin/marvin/integration/lib/utils.py b/tools/marvin/marvin/integration/lib/utils.py index 709fddebe7..7e11d521be 100644 --- a/tools/marvin/marvin/integration/lib/utils.py +++ b/tools/marvin/marvin/integration/lib/utils.py @@ -28,7 +28,7 @@ import socket import urlparse import datetime -from marvin.cloudstackAPI import cloudstackAPIClient, listHosts +from marvin.cloudstackAPI import cloudstackAPIClient, listHosts, listRouters from marvin.sshClient import SshClient from marvin.codes import (FAIL, PASS, @@ -429,3 +429,25 @@ def verifyElementInList(inp, toverify, responsevar=None, pos=0): else: return [FAIL, MATCH_NOT_FOUND] +def verifyRouterState(apiclient, routerid, allowedstates): + """List the router and verify that its state is in allowed states + @output: List, containing [Result, Reason] + Ist Argument ('Result'): FAIL: If router state is not + in allowed states + PASS: If router state is in + allowed states""" + + try: + cmd = listRouters.listRoutersCmd() + cmd.id = routerid + cmd.listall = True + routers = apiclient.listRouters(cmd) + except Exception as e: + return [FAIL, e] + listvalidationresult = validateList(routers) + if listvalidationresult[0] == FAIL: + return [FAIL, listvalidationresult[2]] + if routers[0].redundantstate not in allowedstates: + return [FAIL, "Redundant state of the router should be in %s but is %s" % + (allowedstates, routers[0].redundantstate)] + return [PASS, None] diff --git a/tools/transifex/.tx/config b/tools/transifex/.tx/config index 5e83db3ef0..a2c1e26289 100644 --- a/tools/transifex/.tx/config +++ b/tools/transifex/.tx/config @@ -15,23 +15,14 @@ source_lang = en [CloudStack_UI.42xmessagesproperties] file_filter = translations/CloudStack_UI.42xmessagesproperties/.properties -source_file = work-dir/messages.properties source_lang = en -trans.ar = work-dir/messages_ar.properties -trans.ca = work-dir/messages_ca.properties -trans.de_DE = work-dir/messages_de_DE.properties -trans.es = work-dir/messages_es.properties -trans.fr_FR = work-dir/messages_fr_FR.properties -trans.it_IT = work-dir/messages_it_IT.properties -trans.ja = work-dir/messages_ja.properties -trans.ko_KR = work-dir/messages_ko_KR.properties -trans.nb_NO = work-dir/messages_nb_NO.properties -trans.pt_BR = work-dir/messages_pt_BR.properties -trans.ru_RU = work-dir/messages_ru_RU.properties -trans.zh_CN = work-dir/messages_zh_CN.properties [CloudStack_UI.43xmessagesproperties] -source_file = work-dir/messages.properties +file_filter = translations/CloudStack_UI.43xmessagesproperties/.properties +source_lang = en + +[CloudStack_UI.44xmessagesproperties] +file_filter = translations/CloudStack_UI.44xmessagesproperties/.properties source_lang = en trans.ar = work-dir/messages_ar.properties trans.ca = work-dir/messages_ca.properties diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 2b88e03366..06351d7078 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -1333,7 +1333,7 @@ div.list-view td.first { cursor: pointer; } -div.list-view td.first:hover { +div.list-view tr:not(.multi-edit-selected) td.first:hover { color: #3A82CD; } @@ -1836,6 +1836,58 @@ div.list-view td.state.off span { width: 245px; } +.detail-group .main-groups table td.value > span.copypasteenabledvalue { + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +.detail-group .main-groups table td.value > .copypasteactive { + display: auto; + white-space: nowrap; + overflow: none; +} + +div.copypasteicon { + background: url("../images/sprites.png") no-repeat -271px -65px; + float: left; + height: 21px; + margin-left: 6px; + margin-top: 0px; + width: 18px; +} + +div.copypasteicon:hover { + background: url("../images/sprites.png") no-repeat -271px -646px; +} + +.detail-group .main-groups table td.value > span.copypasteenabledvalue { + text-overflow: ellipsis; + -o-text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +.detail-group .main-groups table td.value > .copypasteactive { + display: auto; + white-space: nowrap; + overflow: none; +} + +div.copypasteicon { + background: url("../images/sprites.png") no-repeat -271px -65px; + float: left; + height: 21px; + margin-left: 6px; + margin-top: 0px; + width: 18px; +} + +div.copypasteicon:hover { + background: url("../images/sprites.png") no-repeat -271px -646px; +} + .detail-group .main-groups table td.value > span select { width: 100% !important; } @@ -1926,6 +1978,11 @@ div.list-view td.state.off span { margin: 4px 0 0 12px; } +.list-view .subselect span.info { + font-size: 10px; + white-space: nowrap; +} + .list-view .subselect select { width: 85%; margin: 5px 0 4px; @@ -3893,7 +3950,7 @@ Dialogs*/ } .ui-dialog.confirm .ui-dialog-title { - background: url(../images/icons.png) no-repeat 0px -225px; + background: url(../images/icons.png) no-repeat 0px -224px; } .ui-dialog.create-form .ui-dialog-title { @@ -5988,7 +6045,7 @@ label.error { } .multi-wizard.instance-wizard .data-disk-offering .select-container { - height: 280px; + height: 300px; margin: -7px 6px 0 8px; /*+border-radius:6px;*/ -moz-border-radius: 6px; @@ -5998,6 +6055,94 @@ label.error { border-radius: 6px 6px 6px 6px; } +.multi-wizard.instance-wizard .data-disk-offering .disk-select-group { + float: left; + margin-top: 12px; + width: 100%; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-header { + border-bottom: 1px solid #D4D4D4; + /*+border-radius:4px;*/ + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; + background: #C2C2C2 0px 4px; + padding: 6px; + height: 17px; +} + +.multi-wizard.instance-wizard .disk-select-group.selected .disk-select-header { + background: #505050; + /*+border-radius:4px 4px 0 0;*/ + -moz-border-radius: 4px 4px 0 0; + -webkit-border-radius: 4px 4px 0 0; + -khtml-border-radius: 4px 4px 0 0; + border-radius: 4px 4px 0 0; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-header input { + float: left; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-header .title { + float: left; + font-size: 14px; + padding: 2px; +} + +.multi-wizard.instance-wizard .disk-select-group.selected .disk-select-header .title { + color: #FFFFFF; + /*+text-shadow:0px -1px #000000;*/ + -moz-text-shadow: 0px -1px #000000; + -webkit-text-shadow: 0px -1px #000000; + -o-text-shadow: 0px -1px #000000; + text-shadow: 0px -1px #000000; +} + +.multi-wizard.instance-wizard .data-disk-offering .multi-disk-select-container { + max-height: 257px; + overflow: auto; + border: 1px solid #DDDBDB; + padding: 13px; + background: #E4E4E4; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-group .select-container { + max-height: 114px; + float: left; + margin: 0; + border: none; + /*+border-radius:0;*/ + -moz-border-radius: 0; + -webkit-border-radius: 0; + -khtml-border-radius: 0; + border-radius: 0; + display: none; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-group.selected .select-container { + display: block; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-group .select { + padding: 0 0 17px; + height: 0; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-group.custom-size .section.custom-size { + display: block !important; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-group .select input { + margin: 13px 12px 12px; +} + +.multi-wizard.instance-wizard .data-disk-offering .disk-select-group .select-desc { + margin: 13px 0 0; +} + .multi-wizard.instance-wizard .data-disk-offering.required .select-container { height: 344px; position: relative; @@ -6057,6 +6202,13 @@ label.error { border-radius: 4px; } +.multi-wizard.instance-wizard .section.custom-iops-do { + position: relative; + background: #F4F4F4; + padding: 7px; + border-radius: 4px; +} + .multi-wizard.instance-wizard .section.custom-size input[type=radio] { float: left; } @@ -6073,6 +6225,12 @@ label.error { margin: 6px -1px 0 8px; } +.multi-wizard.instance-wizard .section.custom-iops-do input[type=text] { + float: left; + width: 28px; + margin: 6px -1px 0 8px; +} + .multi-wizard.instance-wizard .section.custom-size label.error { position: absolute; top: 29px; @@ -6080,6 +6238,53 @@ label.error { font-size: 10px; } +.instance-wizard .step.data-disk-offering.custom-disk-size .select-container { + height: 272px; +} + +.instance-wizard .step.data-disk-offering.custom-iops-do .select-container { + height: 240px; +} + +.instance-wizard .step.data-disk-offering.custom-disk-size.custom-iops-do .select-container { + height: 176px; +} + +.instance-wizard .step.data-disk-offering.required.custom-disk-size .select-container { + height: 315px; +} + +.instance-wizard .step.data-disk-offering.required.custom-iops-do .select-container { + height: 295px; +} + +.instance-wizard .step.data-disk-offering.required.custom-disk-size.custom-iops-do .select-container { + height: 223px; +} + +.instance-wizard .step.data-disk-offering .custom-iops-do { + display: none; +} + +.instance-wizard .step.data-disk-offering.custom-iops-do .custom-iops-do { + display: block; +} + +.instance-wizard .step.data-disk-offering .custom-iops-do .field { + width: 30%; + float: left; + margin-bottom: 5px; +} + +.instance-wizard .step.data-disk-offering .custom-iops-do .field label { + text-indent: 20px; +} + +.instance-wizard .step.data-disk-offering .custom-iops-do .field input { + width: 88%; + margin-left: 26px; +} + /*** Compute offering*/ .instance-wizard .step.service-offering { } @@ -7739,23 +7944,37 @@ div.panel.ui-dialog div.list-view div.fixed-header { /*List-view: subselect dropdown*/ .list-view .subselect { - width: 116px; + width: 102px; + cursor: default; display: block; float: left; - background: url(../images/bg-gradients.png) 0px -42px; + background: #EFEFEF; padding: 0; margin: 8px 0 1px 7px; clear: both; border: 1px solid #A8A7A7; - /*+border-radius:4px;*/ - -moz-border-radius: 4px; - -webkit-border-radius: 4px; - -khtml-border-radius: 4px; - border-radius: 4px; + /*+border-radius:2px;*/ + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -khtml-border-radius: 2px; + border-radius: 2px; +} + +.list-view .subselect:hover span { + color: initial; } .list-view .subselect span { margin: 4px 0 0 12px; + cursor: default; +} + +.list-view .subselect span.info { + background: none; +} + +.list-view .subselect span:hover { + color: initial; } .list-view .subselect select { @@ -12374,11 +12593,13 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it } .restoreVM .icon, -.restore .icon { +.restore .icon, +.recover .icon { background-position: -168px -31px; } -.reset .icon { +.reset .icon, +.reinstall .icon { background-position: -168px -31px; } @@ -12687,3 +12908,49 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it display: inline-block; } + +/*GPU*/ +div.gpugroups div.list-view div.fixed-header { + position: relative; + left: 12px !important; + top: 0px !important; +} + +div.gpugroups div.list-view div.fixed-header table { + width: auto; +} + +div.gpugroups div.list-view div.data-table table { + margin-top: 0; +} + +div.gpugroups div.list-view { + position: relative; + height: auto !important; + margin-top: 0 !important; + border: none !important; +} + +.gpugroups { + float: left; + height: 100%; + width: 100%; + overflow-x: hidden; + overflow-y: auto; +} +.gpugroups .gpugroup-container { + border: 1px solid #C8C2C2; + border-radius: 3px; + height: auto !important; + margin: 12px; + padding: 0; + position: relative; + float: left; + width: auto; +} + +.gpugroups .gpugroup-container .title { + font-size: 13px; + font-weight: 100; + padding: 12px 12px 5px; +} diff --git a/ui/dictionary.jsp b/ui/dictionary.jsp index 074db7f061..50832efbf8 100644 --- a/ui/dictionary.jsp +++ b/ui/dictionary.jsp @@ -25,6 +25,12 @@ under the License. <% long now = System.currentTimeMillis(); %>