diff --git a/DISCLAIMER b/DISCLAIMER deleted file mode 100644 index fa1e9261a36..00000000000 --- a/DISCLAIMER +++ /dev/null @@ -1,7 +0,0 @@ -Apache CloudStack is an effort undergoing incubation at The Apache Software Foundation (ASF), -sponsored by the Apache Incubator. Incubation is required of all newly accepted -projects until a further review indicates that the infrastructure, communications, and -decision making process have stabilized in a manner consistent with other successful ASF -projects. While incubation status is not necessarily a reflection of the completeness or -stability of the code, it does indicate that the project has yet to be fully endorsed by -the ASF. diff --git a/api/src/com/cloud/agent/api/DeleteSnapshotBackupCommand.java b/api/src/com/cloud/agent/api/DeleteSnapshotBackupCommand.java index 6114148954f..128df84c729 100644 --- a/api/src/com/cloud/agent/api/DeleteSnapshotBackupCommand.java +++ b/api/src/com/cloud/agent/api/DeleteSnapshotBackupCommand.java @@ -19,6 +19,7 @@ package com.cloud.agent.api; import com.cloud.agent.api.LogLevel.Log4jLevel; import com.cloud.agent.api.to.S3TO; import com.cloud.agent.api.to.SwiftTO; +import com.cloud.storage.StoragePool; /** * This command encapsulates a primitive operation which enables coalescing the backed up VHD snapshots on the secondary server @@ -78,7 +79,8 @@ public class DeleteSnapshotBackupCommand extends SnapshotCommand { * @param backupUUID The VHD which has to be deleted * @param childUUID The child VHD file of the backup whose parent is reset to its grandparent. */ - public DeleteSnapshotBackupCommand(SwiftTO swift, + public DeleteSnapshotBackupCommand(StoragePool pool, + SwiftTO swift, S3TO s3, String secondaryStoragePoolURL, Long dcId, @@ -86,7 +88,7 @@ public class DeleteSnapshotBackupCommand extends SnapshotCommand { Long volumeId, String backupUUID, Boolean all) { - super(null, secondaryStoragePoolURL, backupUUID, null, dcId, accountId, volumeId); + super(pool, secondaryStoragePoolURL, backupUUID, null, dcId, accountId, volumeId); setSwift(swift); this.s3 = s3; setAll(all); diff --git a/api/src/com/cloud/async/AsyncJob.java b/api/src/com/cloud/async/AsyncJob.java index 8e4aec0739a..866429b6547 100644 --- a/api/src/com/cloud/async/AsyncJob.java +++ b/api/src/com/cloud/async/AsyncJob.java @@ -49,7 +49,8 @@ public interface AsyncJob extends Identity, InternalIdentity { AutoScalePolicy, AutoScaleVmProfile, AutoScaleVmGroup, - GlobalLoadBalancerRule + GlobalLoadBalancerRule, + AffinityGroup } long getUserId(); diff --git a/api/src/com/cloud/configuration/ConfigurationService.java b/api/src/com/cloud/configuration/ConfigurationService.java index e63fcece525..6937d0b64de 100644 --- a/api/src/com/cloud/configuration/ConfigurationService.java +++ b/api/src/com/cloud/configuration/ConfigurationService.java @@ -35,7 +35,9 @@ import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCmd import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd; import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd; import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd; +import org.apache.cloudstack.api.command.admin.vlan.DedicatePublicIpRangeCmd; import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd; +import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd; 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.UpdateZoneCmd; @@ -234,6 +236,10 @@ public interface ConfigurationService { boolean deleteVlanIpRange(DeleteVlanIpRangeCmd cmd); + Vlan dedicatePublicIpRange(DedicatePublicIpRangeCmd cmd) throws ResourceAllocationException; + + boolean releasePublicIpRange(ReleasePublicIpRangeCmd cmd); + NetworkOffering createNetworkOffering(CreateNetworkOfferingCmd cmd); NetworkOffering updateNetworkOffering(UpdateNetworkOfferingCmd cmd); diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index 5671f995c70..0ee7f402fd7 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -226,6 +226,8 @@ public class EventTypes { // VLANs/IP ranges public static final String EVENT_VLAN_IP_RANGE_CREATE = "VLAN.IP.RANGE.CREATE"; public static final String EVENT_VLAN_IP_RANGE_DELETE = "VLAN.IP.RANGE.DELETE"; + public static final String EVENT_VLAN_IP_RANGE_DEDICATE = "VLAN.IP.RANGE.DEDICATE"; + public static final String EVENT_VLAN_IP_RANGE_RELEASE = "VLAN.IP.RANGE.RELEASE"; public static final String EVENT_STORAGE_IP_RANGE_CREATE = "STORAGE.IP.RANGE.CREATE"; public static final String EVENT_STORAGE_IP_RANGE_DELETE = "STORAGE.IP.RANGE.DELETE"; @@ -348,7 +350,7 @@ public class EventTypes { // tag related events public static final String EVENT_TAGS_CREATE = "CREATE_TAGS"; public static final String EVENT_TAGS_DELETE = "DELETE_TAGS"; - + // vm snapshot events public static final String EVENT_VM_SNAPSHOT_CREATE = "VMSNAPSHOT.CREATE"; public static final String EVENT_VM_SNAPSHOT_DELETE = "VMSNAPSHOT.DELETE"; @@ -382,6 +384,12 @@ public class EventTypes { public static final String EVENT_BAREMETAL_PXE_SERVER_ADD = "PHYSICAL.PXE.ADD"; public static final String EVENT_BAREMETAL_PXE_SERVER_DELETE = "PHYSICAL.PXE.DELETE"; + public static final String EVENT_AFFINITY_GROUP_CREATE = "AG.CREATE"; + public static final String EVENT_AFFINITY_GROUP_DELETE = "AG.DELETE"; + public static final String EVENT_AFFINITY_GROUP_ASSIGN = "AG.ASSIGN"; + public static final String EVENT_AFFINITY_GROUP_REMOVE = "AG.REMOVE"; + public static final String EVENT_VM_AFFINITY_GROUP_UPDATE = "VM.AG.UPDATE"; + static { // TODO: need a way to force author adding event types to declare the entity details as well, with out braking @@ -539,6 +547,8 @@ public class EventTypes { // VLANs/IP ranges entityEventDetails.put(EVENT_VLAN_IP_RANGE_CREATE, Vlan.class.getName()); entityEventDetails.put(EVENT_VLAN_IP_RANGE_DELETE,Vlan.class.getName()); + entityEventDetails.put(EVENT_VLAN_IP_RANGE_DEDICATE, Vlan.class.getName()); + entityEventDetails.put(EVENT_VLAN_IP_RANGE_RELEASE,Vlan.class.getName()); entityEventDetails.put(EVENT_STORAGE_IP_RANGE_CREATE, StorageNetworkIpRange.class.getName()); entityEventDetails.put(EVENT_STORAGE_IP_RANGE_DELETE, StorageNetworkIpRange.class.getName()); diff --git a/api/src/com/cloud/exception/AffinityConflictException.java b/api/src/com/cloud/exception/AffinityConflictException.java new file mode 100644 index 00000000000..8b187783f24 --- /dev/null +++ b/api/src/com/cloud/exception/AffinityConflictException.java @@ -0,0 +1,34 @@ +// 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.exception; + +import com.cloud.utils.SerialVersionUID; +import com.cloud.utils.exception.CloudRuntimeException; + +public class AffinityConflictException extends CloudRuntimeException { + + private static final long serialVersionUID = SerialVersionUID.AffinityConflictException; + + public AffinityConflictException(String message) { + super(message); + } + + public AffinityConflictException(String message, Throwable th) { + super(message, th); + } + +} diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index c0b0117fc7e..4472dbacc53 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -16,24 +16,11 @@ // under the License. package com.cloud.network; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.api.Identity; -import org.apache.cloudstack.api.InternalIdentity; - -import com.cloud.network.Networks.BroadcastDomainType; -import com.cloud.network.Networks.Mode; -import com.cloud.network.Networks.TrafficType; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; import com.cloud.utils.fsm.StateMachine2; import com.cloud.utils.fsm.StateObject; - import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; @@ -137,6 +124,7 @@ public interface Network extends ControlledEntity, StateObject, I public static final Provider None = new Provider("None", false); // NiciraNvp is not an "External" provider, otherwise we get in trouble with NetworkServiceImpl.providersConfiguredForExternalNetworking public static final Provider NiciraNvp = new Provider("NiciraNvp", false); + public static final Provider CiscoVnmc = new Provider("CiscoVnmc", true); private String name; private boolean isExternal; @@ -182,6 +170,7 @@ public interface Network extends ControlledEntity, StateObject, I public static final Capability AllowDnsSuffixModification = new Capability("AllowDnsSuffixModification"); public static final Capability RedundantRouter = new Capability("RedundantRouter"); public static final Capability ElasticIp = new Capability("ElasticIp"); + public static final Capability AssociatePublicIP = new Capability("AssociatePublicIP"); public static final Capability ElasticLb = new Capability("ElasticLb"); public static final Capability AutoScaleCounters = new Capability("AutoScaleCounters"); public static final Capability InlineMode = new Capability("InlineMode"); diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java index ab6d7bfd882..066009b8b75 100755 --- a/api/src/com/cloud/network/NetworkService.java +++ b/api/src/com/cloud/network/NetworkService.java @@ -46,7 +46,7 @@ public interface NetworkService { List getIsolatedNetworksOwnedByAccountInZone(long zoneId, Account owner); - IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) throws ResourceAllocationException, + IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException; boolean releaseIpAddress(long ipAddressId) throws InsufficientAddressCapacityException; diff --git a/api/src/com/cloud/offering/NetworkOffering.java b/api/src/com/cloud/offering/NetworkOffering.java index bd14acd4718..6f0b9937854 100644 --- a/api/src/com/cloud/offering/NetworkOffering.java +++ b/api/src/com/cloud/offering/NetworkOffering.java @@ -107,6 +107,8 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity, boolean getElasticIp(); + boolean getAssociatePublicIP(); + boolean getElasticLb(); boolean getSpecifyIpRanges(); diff --git a/api/src/com/cloud/server/ManagementService.java b/api/src/com/cloud/server/ManagementService.java index 1e6ca8d0b67..6e6dbc36f0c 100755 --- a/api/src/com/cloud/server/ManagementService.java +++ b/api/src/com/cloud/server/ManagementService.java @@ -123,7 +123,7 @@ public interface ManagementService { /** * Searches for servers by the specified search criteria Can search by: "name", "type", "state", "dataCenterId", * "podId" - * + * * @param cmd * @return List of Hosts */ @@ -407,4 +407,6 @@ public interface ManagementService { */ List listTopConsumedResources(ListCapacityCmd cmd); + List listDeploymentPlanners(); + } diff --git a/api/src/com/cloud/vm/DiskProfile.java b/api/src/com/cloud/vm/DiskProfile.java index e34a3340e9e..e3a3386d1e5 100644 --- a/api/src/com/cloud/vm/DiskProfile.java +++ b/api/src/com/cloud/vm/DiskProfile.java @@ -139,7 +139,7 @@ public class DiskProfile { this.hyperType = hyperType; } - public HypervisorType getHypersorType() { + public HypervisorType getHypervisorType() { return this.hyperType; } diff --git a/api/src/com/cloud/vm/UserVmService.java b/api/src/com/cloud/vm/UserVmService.java index 2c33d41cd35..d963b74b080 100755 --- a/api/src/com/cloud/vm/UserVmService.java +++ b/api/src/com/cloud/vm/UserVmService.java @@ -26,9 +26,6 @@ import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; import org.apache.cloudstack.api.command.user.vm.*; import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; -import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; -import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; - import com.cloud.dc.DataCenter; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; @@ -42,7 +39,6 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.Network.IpAddresses; import com.cloud.offering.ServiceOffering; import com.cloud.storage.StoragePool; -import com.cloud.storage.Volume; import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; import com.cloud.uservm.UserVm; @@ -104,14 +100,14 @@ public interface UserVmService { * @return the vm object if successful, null otherwise */ UserVm addNicToVirtualMachine(AddNicToVMCmd cmd); - + /** * Removes a NIC on the given network from the virtual machine * @param cmd the command object that defines the vm and the given network * @return the vm object if successful, null otherwise */ UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd); - + /** * Updates default Nic to the given network for given virtual machine * @param cmd the command object that defines the vm and the given network @@ -123,7 +119,8 @@ public interface UserVmService { /** - * Creates a Basic Zone User VM in the database and returns the VM to the caller. + * Creates a Basic Zone User VM in the database and returns the VM to the + * caller. * * @param zone * - availability zone for the virtual machine @@ -132,61 +129,69 @@ public interface UserVmService { * @param template * - the template for the virtual machine * @param securityGroupIdList - * - comma separated list of security groups id that going to be applied to the virtual machine + * - comma separated list of security groups id that going to be + * applied to the virtual machine * @param hostName * - host name for the virtual machine * @param displayName * - an optional user generated name for the virtual machine * @param diskOfferingId - * - the ID of the disk offering for the virtual machine. If the template is of ISO format, the - * diskOfferingId is - * for the root disk volume. Otherwise this parameter is used to indicate the offering for the data disk - * volume. - * If the templateId parameter passed is from a Template object, the diskOfferingId refers to a DATA Disk - * Volume - * created. If the templateId parameter passed is from an ISO object, the diskOfferingId refers to a ROOT - * Disk - * Volume created + * - the ID of the disk offering for the virtual machine. If the + * template is of ISO format, the diskOfferingId is for the root + * disk volume. Otherwise this parameter is used to indicate the + * offering for the data disk volume. If the templateId parameter + * passed is from a Template object, the diskOfferingId refers to + * a DATA Disk Volume created. If the templateId parameter passed + * is from an ISO object, the diskOfferingId refers to a ROOT + * Disk Volume created * @param diskSize - * - the arbitrary size for the DATADISK volume. Mutually exclusive with diskOfferingId + * - the arbitrary size for the DATADISK volume. Mutually + * exclusive with diskOfferingId * @param group * - an optional group for the virtual machine * @param hypervisor * - the hypervisor on which to deploy the virtual machine * @param userData - * - an optional binary data that can be sent to the virtual machine upon a successful deployment. This - * binary - * data must be base64 encoded before adding it to the request. Currently only HTTP GET is supported. - * Using HTTP - * GET (via querystring), you can send up to 2KB of data after base64 encoding + * - an optional binary data that can be sent to the virtual + * machine upon a successful deployment. This binary data must be + * base64 encoded before adding it to the request. Currently only + * HTTP GET is supported. Using HTTP GET (via querystring), you + * can send up to 2KB of data after base64 encoding * @param sshKeyPair - * - name of the ssh key pair used to login to the virtual machine + * - name of the ssh key pair used to login to the virtual + * machine * @param requestedIps * TODO * @param defaultIp * TODO + * @param affinityGroupIdList * @param accountName - * - an optional account for the virtual machine. Must be used with domainId + * - an optional account for the virtual machine. Must be used + * with domainId * @param domainId - * - an optional domainId for the virtual machine. If the account parameter is used, domainId must also - * be used + * - an optional domainId for the virtual machine. If the account + * parameter is used, domainId must also be used * @return UserVm object if successful. * * @throws InsufficientCapacityException * if there is insufficient capacity to deploy the VM. * @throws ConcurrentOperationException - * if there are multiple users working on the same VM or in the same environment. + * if there are multiple users working on the same VM or in the + * same environment. * @throws ResourceUnavailableException - * if the resources required to deploy the VM is not currently available. + * if the resources required to deploy the VM is not currently + * available. * @throws InsufficientResourcesException */ UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List securityGroupIdList, Account owner, String hostName, - String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map requestedIps, IpAddresses defaultIp, String keyboard) + String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, + String userData, String sshKeyPair, Map requestedIps, IpAddresses defaultIp, + String keyboard, List affinityGroupIdList) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException; /** - * Creates a User VM in Advanced Zone (Security Group feature is enabled) in the database and returns the VM to the - * caller. + * Creates a User VM in Advanced Zone (Security Group feature is enabled) in + * the database and returns the VM to the caller. * * @param zone * - availability zone for the virtual machine @@ -197,63 +202,69 @@ public interface UserVmService { * @param networkIdList * - list of network ids used by virtual machine * @param securityGroupIdList - * - comma separated list of security groups id that going to be applied to the virtual machine + * - comma separated list of security groups id that going to be + * applied to the virtual machine * @param hostName * - host name for the virtual machine * @param displayName * - an optional user generated name for the virtual machine * @param diskOfferingId - * - the ID of the disk offering for the virtual machine. If the template is of ISO format, the - * diskOfferingId is - * for the root disk volume. Otherwise this parameter is used to indicate the offering for the data disk - * volume. - * If the templateId parameter passed is from a Template object, the diskOfferingId refers to a DATA Disk - * Volume - * created. If the templateId parameter passed is from an ISO object, the diskOfferingId refers to a ROOT - * Disk - * Volume created + * - the ID of the disk offering for the virtual machine. If the + * template is of ISO format, the diskOfferingId is for the root + * disk volume. Otherwise this parameter is used to indicate the + * offering for the data disk volume. If the templateId parameter + * passed is from a Template object, the diskOfferingId refers to + * a DATA Disk Volume created. If the templateId parameter passed + * is from an ISO object, the diskOfferingId refers to a ROOT + * Disk Volume created * @param diskSize - * - the arbitrary size for the DATADISK volume. Mutually exclusive with diskOfferingId + * - the arbitrary size for the DATADISK volume. Mutually + * exclusive with diskOfferingId * @param group * - an optional group for the virtual machine * @param hypervisor * - the hypervisor on which to deploy the virtual machine * @param userData - * - an optional binary data that can be sent to the virtual machine upon a successful deployment. This - * binary - * data must be base64 encoded before adding it to the request. Currently only HTTP GET is supported. - * Using HTTP - * GET (via querystring), you can send up to 2KB of data after base64 encoding + * - an optional binary data that can be sent to the virtual + * machine upon a successful deployment. This binary data must be + * base64 encoded before adding it to the request. Currently only + * HTTP GET is supported. Using HTTP GET (via querystring), you + * can send up to 2KB of data after base64 encoding * @param sshKeyPair - * - name of the ssh key pair used to login to the virtual machine + * - name of the ssh key pair used to login to the virtual + * machine * @param requestedIps * TODO * @param defaultIps * TODO + * @param affinityGroupIdList * @param accountName - * - an optional account for the virtual machine. Must be used with domainId + * - an optional account for the virtual machine. Must be used + * with domainId * @param domainId - * - an optional domainId for the virtual machine. If the account parameter is used, domainId must also - * be used + * - an optional domainId for the virtual machine. If the account + * parameter is used, domainId must also be used * @return UserVm object if successful. * * @throws InsufficientCapacityException * if there is insufficient capacity to deploy the VM. * @throws ConcurrentOperationException - * if there are multiple users working on the same VM or in the same environment. + * if there are multiple users working on the same VM or in the + * same environment. * @throws ResourceUnavailableException - * if the resources required to deploy the VM is not currently available. + * if the resources required to deploy the VM is not currently + * available. * @throws InsufficientResourcesException */ UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List networkIdList, List securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map requestedIps, - IpAddresses defaultIps, String keyboard) + IpAddresses defaultIps, String keyboard, List affinityGroupIdList) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException; /** - * Creates a User VM in Advanced Zone (Security Group feature is disabled) in the database and returns the VM to the - * caller. - * + * Creates a User VM in Advanced Zone (Security Group feature is disabled) + * in the database and returns the VM to the caller. + * * @param zone * - availability zone for the virtual machine * @param serviceOffering @@ -267,49 +278,57 @@ public interface UserVmService { * @param displayName * - an optional user generated name for the virtual machine * @param diskOfferingId - * - the ID of the disk offering for the virtual machine. If the template is of ISO format, the - * diskOfferingId is - * for the root disk volume. Otherwise this parameter is used to indicate the offering for the data disk - * volume. - * If the templateId parameter passed is from a Template object, the diskOfferingId refers to a DATA Disk - * Volume - * created. If the templateId parameter passed is from an ISO object, the diskOfferingId refers to a ROOT - * Disk - * Volume created + * - the ID of the disk offering for the virtual machine. If the + * template is of ISO format, the diskOfferingId is for the root + * disk volume. Otherwise this parameter is used to indicate the + * offering for the data disk volume. If the templateId parameter + * passed is from a Template object, the diskOfferingId refers to + * a DATA Disk Volume created. If the templateId parameter passed + * is from an ISO object, the diskOfferingId refers to a ROOT + * Disk Volume created * @param diskSize - * - the arbitrary size for the DATADISK volume. Mutually exclusive with diskOfferingId + * - the arbitrary size for the DATADISK volume. Mutually + * exclusive with diskOfferingId * @param group * - an optional group for the virtual machine * @param hypervisor * - the hypervisor on which to deploy the virtual machine * @param userData - * - an optional binary data that can be sent to the virtual machine upon a successful deployment. This - * binary - * data must be base64 encoded before adding it to the request. Currently only HTTP GET is supported. - * Using HTTP - * GET (via querystring), you can send up to 2KB of data after base64 encoding + * - an optional binary data that can be sent to the virtual + * machine upon a successful deployment. This binary data must be + * base64 encoded before adding it to the request. Currently only + * HTTP GET is supported. Using HTTP GET (via querystring), you + * can send up to 2KB of data after base64 encoding * @param sshKeyPair - * - name of the ssh key pair used to login to the virtual machine + * - name of the ssh key pair used to login to the virtual + * machine * @param requestedIps * TODO - * @param defaultIps TODO + * @param defaultIps + * TODO + * @param affinityGroupIdList * @param accountName - * - an optional account for the virtual machine. Must be used with domainId + * - an optional account for the virtual machine. Must be used + * with domainId * @param domainId - * - an optional domainId for the virtual machine. If the account parameter is used, domainId must also - * be used + * - an optional domainId for the virtual machine. If the account + * parameter is used, domainId must also be used * @return UserVm object if successful. - * + * * @throws InsufficientCapacityException * if there is insufficient capacity to deploy the VM. * @throws ConcurrentOperationException - * if there are multiple users working on the same VM or in the same environment. + * if there are multiple users working on the same VM or in the + * same environment. * @throws ResourceUnavailableException - * if the resources required to deploy the VM is not currently available. + * if the resources required to deploy the VM is not currently + * available. * @throws InsufficientResourcesException */ UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List networkIdList, Account owner, String hostName, - String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map requestedIps, IpAddresses defaultIps, String keyboard) + String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, + String userData, String sshKeyPair, Map requestedIps, IpAddresses defaultIps, + String keyboard, List affinityGroupIdList) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException; /** diff --git a/api/src/org/apache/cloudstack/affinity/AffinityGroup.java b/api/src/org/apache/cloudstack/affinity/AffinityGroup.java new file mode 100644 index 00000000000..ac2eb613370 --- /dev/null +++ b/api/src/org/apache/cloudstack/affinity/AffinityGroup.java @@ -0,0 +1,31 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity; + +import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +public interface AffinityGroup extends ControlledEntity, InternalIdentity, Identity { + + String getName(); + + String getDescription(); + + String getType(); + +} diff --git a/api/src/org/apache/cloudstack/affinity/AffinityGroupProcessor.java b/api/src/org/apache/cloudstack/affinity/AffinityGroupProcessor.java new file mode 100644 index 00000000000..60b8e4c554f --- /dev/null +++ b/api/src/org/apache/cloudstack/affinity/AffinityGroupProcessor.java @@ -0,0 +1,49 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity; + +import com.cloud.deploy.DeploymentPlan; +import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.exception.AffinityConflictException; +import com.cloud.utils.component.Adapter; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +public interface AffinityGroupProcessor extends Adapter { + + /** + * process() is called to apply any user preferences to the deployment plan + * and avoid set for the given VM placement. + * + * @param vm + * virtual machine. + * @param plan + * deployment plan that tells you where it's being deployed to. + * @param avoid + * avoid these data centers, pods, clusters, or hosts. + */ + void process(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) + throws AffinityConflictException; + + /** + * getType() should return the affinity/anti-affinity group being + * implemented + * + * @return String Affinity/Anti-affinity type + */ + String getType(); +} \ No newline at end of file diff --git a/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java b/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java new file mode 100644 index 00000000000..afd33da84b7 --- /dev/null +++ b/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java @@ -0,0 +1,155 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; +import org.apache.cloudstack.api.response.ControlledEntityResponse; +import org.apache.cloudstack.api.response.ControlledViewEntityResponse; +import org.apache.cloudstack.api.response.UserVmResponse; + +import com.cloud.network.security.SecurityGroup; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +@SuppressWarnings("unused") +@EntityReference(value = AffinityGroup.class) +public class AffinityGroupResponse extends BaseResponse implements ControlledViewEntityResponse { + + @SerializedName(ApiConstants.ID) @Param(description="the ID of the affinity group") + private String id; + + @SerializedName(ApiConstants.NAME) @Param(description="the name of the affinity group") + private String name; + + @SerializedName(ApiConstants.DESCRIPTION) @Param(description="the description of the affinity group") + private String description; + + @SerializedName(ApiConstants.ACCOUNT) @Param(description="the account owning the affinity group") + private String accountName; + + @SerializedName(ApiConstants.DOMAIN_ID) @Param(description="the domain ID of the affinity group") + private String domainId; + + @SerializedName(ApiConstants.DOMAIN) @Param(description="the domain name of the affinity group") + private String domainName; + + @SerializedName(ApiConstants.TYPE) + @Param(description = "the type of the affinity group") + private String type; + + @SerializedName("virtualmachineIds") + @Param(description = "virtual machine Ids associated with this affinity group ") + private List vmIdList; + + public AffinityGroupResponse() { + this.vmIdList = new ArrayList(); + } + + @Override + public String getObjectId() { + return this.getId(); + } + + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + + public void setName(String name) { + this.name = name; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + public void setType(String type) { + this.type = type; + } + + @Override + public void setDomainId(String domainId) { + this.domainId = domainId; + } + + public void setDomainName(String domainName) { + this.domainName = domainName; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AffinityGroupResponse other = (AffinityGroupResponse) obj; + if (id == null) { + if (other.id != null) + return false; + } else if (!id.equals(other.id)) + return false; + return true; + } + + @Override + public void setProjectId(String projectId) { + // TODO Auto-generated method stub + + } + + @Override + public void setProjectName(String projectName) { + // TODO Auto-generated method stub + + } + + public void setVMIdList(List vmIdList) { + this.vmIdList = vmIdList; + } + + public void addVMId(String vmId) { + this.vmIdList.add(vmId); + } + +} diff --git a/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java b/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java new file mode 100644 index 00000000000..26c32c89c1f --- /dev/null +++ b/api/src/org/apache/cloudstack/affinity/AffinityGroupService.java @@ -0,0 +1,79 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity; + +import java.util.List; + +import com.cloud.exception.ResourceInUseException; +import com.cloud.uservm.UserVm; +import com.cloud.utils.Pair; + +public interface AffinityGroupService { + + /** + * Creates an affinity/anti-affinity group for the given account/domain. + * + * @param account + * @param domainId + * @param name + * @param type + * @param description + * @return AffinityGroup + */ + + AffinityGroup createAffinityGroup(String account, Long domainId, String affinityGroupName, + String affinityGroupType, String description); + + /** + * Creates an affinity/anti-affinity group. + * + * @param affinityGroupId + * @param account + * @param domainId + * @param affinityGroupName + * @throws ResourceInUseException + */ + boolean deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName) + throws ResourceInUseException; + + /** Lists Affinity Groups in your account + * @param account + * @param domainId + * @param affinityGroupId + * @param affinityGroupName + * @param affinityGroupType + * @param vmId + * @param startIndex + * @param pageSize + * @return + */ + Pair, Integer> listAffinityGroups(Long affinityGroupId, String affinityGroupName, + String affinityGroupType, Long vmId, Long startIndex, Long pageSize); + + + /** + * List group types available in deployment + * + * @return + */ + List listAffinityGroupTypes(); + + AffinityGroup getAffinityGroup(Long groupId); + + UserVm updateVMAffinityGroups(Long vmId, List affinityGroupIds); + +} diff --git a/api/src/org/apache/cloudstack/affinity/AffinityGroupTypeResponse.java b/api/src/org/apache/cloudstack/affinity/AffinityGroupTypeResponse.java new file mode 100644 index 00000000000..2d1cd25edda --- /dev/null +++ b/api/src/org/apache/cloudstack/affinity/AffinityGroupTypeResponse.java @@ -0,0 +1,48 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity; + +import java.util.HashSet; +import java.util.Set; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; +import org.apache.cloudstack.api.response.ControlledEntityResponse; +import org.apache.cloudstack.api.response.ControlledViewEntityResponse; + +import com.cloud.network.security.SecurityGroup; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +@SuppressWarnings("unused") +@EntityReference(value = AffinityGroup.class) +public class AffinityGroupTypeResponse extends BaseResponse { + + @SerializedName(ApiConstants.TYPE) + @Param(description = "the type of the affinity group") + private String type; + + + public AffinityGroupTypeResponse() { + } + + public void setType(String type) { + this.type = type; + } + +} diff --git a/api/src/org/apache/cloudstack/affinity/AffinityProcessorBase.java b/api/src/org/apache/cloudstack/affinity/AffinityProcessorBase.java new file mode 100644 index 00000000000..70ecd08350f --- /dev/null +++ b/api/src/org/apache/cloudstack/affinity/AffinityProcessorBase.java @@ -0,0 +1,44 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity; + +import com.cloud.deploy.DeploymentPlan; +import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.exception.AffinityConflictException; +import com.cloud.utils.component.AdapterBase; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +public class AffinityProcessorBase extends AdapterBase implements AffinityGroupProcessor { + + protected String _type; + + @Override + public void process(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid) + throws AffinityConflictException { + + } + + @Override + public String getType() { + return _type; + } + + public void setType(String type) { + _type = type; + } +} diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index c518830c92c..37cb59f3758 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -473,13 +473,17 @@ public class ApiConstants { public static final String HEALTHCHECK_HEALTHY_THRESHOLD = "healthythreshold"; public static final String HEALTHCHECK_UNHEALTHY_THRESHOLD = "unhealthythreshold"; public static final String HEALTHCHECK_PINGPATH = "pingpath"; + public static final String AFFINITY_GROUP_IDS = "affinitygroupids"; + public static final String AFFINITY_GROUP_NAMES = "affinitygroupnames"; + public static final String DEPLOYMENT_PLANNER = "deploymentplanner"; + public static final String ASA_INSIDE_PORT_PROFILE = "insideportprofile"; public enum HostDetails { all, capacity, events, stats, min; } public enum VMDetails { - all, group, nics, stats, secgrp, tmpl, servoff, iso, volume, min; + all, group, nics, stats, secgrp, tmpl, servoff, iso, volume, min, affgrp; } public enum LDAPParams { diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java index 8fef422b915..42c0680ce0f 100644 --- a/api/src/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseCmd.java @@ -27,6 +27,7 @@ import java.util.regex.Pattern; import javax.inject.Inject; +import org.apache.cloudstack.affinity.AffinityGroupService; import org.apache.cloudstack.query.QueryService; import org.apache.cloudstack.usage.UsageService; import org.apache.log4j.Logger; @@ -132,6 +133,7 @@ public abstract class BaseCmd { @Inject public VMSnapshotService _vmSnapshotService; @Inject public DataStoreProviderApiService dataStoreProviderApiService; @Inject public VpcProvisioningService _vpcProvSvc; + @Inject public AffinityGroupService _affinityGroupService; public abstract void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException; @@ -154,7 +156,7 @@ public abstract class BaseCmd { /** * For commands the API framework needs to know the owner of the object being acted upon. This method is * used to determine that information. - * + * * @return the id of the account that owns the object being acted upon */ public abstract long getEntityOwnerId(); @@ -467,7 +469,7 @@ public abstract class BaseCmd { if (!enabledOnly || account.getState() == Account.State.enabled) { return account.getId(); } else { - throw new PermissionDeniedException("Can't add resources to the account id=" + account.getId() + " in state=" + account.getState() + " as it's no longer active"); + throw new PermissionDeniedException("Can't add resources to the account id=" + account.getId() + " in state=" + account.getState() + " as it's no longer active"); } } else { // idList is not used anywhere, so removed it now @@ -484,7 +486,7 @@ public abstract class BaseCmd { return project.getProjectAccountId(); } else { PermissionDeniedException ex = new PermissionDeniedException("Can't add resources to the project with specified projectId in state=" + project.getState() + " as it's no longer active"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(project, projectId, "projectId"); throw ex; } } else { diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java index d1e13023117..c0dd57e15bd 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -20,6 +20,8 @@ import java.text.DecimalFormat; import java.util.EnumSet; import java.util.List; +import org.apache.cloudstack.affinity.AffinityGroup; +import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.ApiConstants.HostDetails; import org.apache.cloudstack.api.ApiConstants.VMDetails; import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; @@ -150,18 +152,9 @@ import com.cloud.user.UserAccount; import com.cloud.uservm.UserVm; import com.cloud.vm.InstanceGroup; import com.cloud.vm.Nic; -import com.cloud.vm.NicSecondaryIp; import com.cloud.vm.snapshot.VMSnapshot; import com.cloud.vm.VirtualMachine; -import org.apache.cloudstack.api.ApiConstants.HostDetails; -import org.apache.cloudstack.api.ApiConstants.VMDetails; -import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; import org.apache.cloudstack.api.response.*; -import org.apache.cloudstack.region.Region; - -import java.text.DecimalFormat; -import java.util.EnumSet; -import java.util.List; public interface ResponseGenerator { UserResponse createUserResponse(UserAccount user); @@ -384,12 +377,17 @@ public interface ResponseGenerator { GuestOSResponse createGuestOSResponse(GuestOS os); SnapshotScheduleResponse createSnapshotScheduleResponse(SnapshotSchedule sched); - + UsageRecordResponse createUsageResponse(Usage usageRecord); TrafficMonitorResponse createTrafficMonitorResponse(Host trafficMonitor); VMSnapshotResponse createVMSnapshotResponse(VMSnapshot vmSnapshot); + NicSecondaryIpResponse createSecondaryIPToNicResponse(String ip, Long nicId, Long networkId); public NicResponse createNicResponse(Nic result); + + AffinityGroupResponse createAffinityGroupResponse(AffinityGroup group); + + Long getAffinityGroupId(String name, long entityOwnerId); } diff --git a/api/src/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java b/api/src/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java index 95728dd184d..c5130587ec5 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/cluster/UpdateClusterCmd.java @@ -111,14 +111,14 @@ public class UpdateClusterCmd extends BaseCmd { if(cpuovercommitratio != null){ return Float.parseFloat(cpuovercommitratio); } - return 1.0f; + return null; } public Float getMemoryOvercommitRaito (){ if (memoryovercommitratio != null){ return Float.parseFloat(memoryovercommitratio); } - return 1.0f; + return null; } @Override @@ -127,9 +127,16 @@ public class UpdateClusterCmd extends BaseCmd { if (cluster == null) { throw new InvalidParameterValueException("Unable to find the cluster by id=" + getId()); } + if (getMemoryOvercommitRaito() !=null){ + if ((getMemoryOvercommitRaito().compareTo(1f) < 0)) { + throw new InvalidParameterValueException("Memory overcommit ratio should be greater than or equal to one"); + } + } - if ((getMemoryOvercommitRaito().compareTo(1f) < 0) | (getCpuOvercommitRatio().compareTo(1f) < 0)) { - throw new InvalidParameterValueException("Cpu and ram overcommit ratios should be greater than one"); + if (getCpuOvercommitRatio() !=null){ + if (getCpuOvercommitRatio().compareTo(1f) < 0) { + throw new InvalidParameterValueException("Cpu overcommit ratio should be greater than or equal to one"); + } } Cluster result = _resourceService.updateCluster(cluster, getClusterType(), getHypervisor(), getAllocationState(), getManagedstate(), getMemoryOvercommitRaito(), getCpuOvercommitRatio()); diff --git a/api/src/org/apache/cloudstack/api/command/admin/config/ListDeploymentPlannersCmd.java b/api/src/org/apache/cloudstack/api/command/admin/config/ListDeploymentPlannersCmd.java new file mode 100644 index 00000000000..69004de2a6b --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/config/ListDeploymentPlannersCmd.java @@ -0,0 +1,71 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.admin.config; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.response.DeploymentPlannersResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.log4j.Logger; + +@APICommand(name = "listDeploymentPlanners", description = "Lists all DeploymentPlanners available.", responseObject = DeploymentPlannersResponse.class) +public class ListDeploymentPlannersCmd extends BaseListCmd { + public static final Logger s_logger = Logger.getLogger(ListDeploymentPlannersCmd.class.getName()); + + private static final String s_name = "listdeploymentplannersresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public void execute(){ + List planners = _mgr.listDeploymentPlanners(); + ListResponse response = new ListResponse(); + List plannerResponses = new ArrayList(); + + for (String planner : planners) { + DeploymentPlannersResponse plannerResponse = new DeploymentPlannersResponse(); + plannerResponse.setName(planner); + plannerResponse.setObjectName("deploymentPlanner"); + plannerResponses.add(plannerResponse); + } + + response.setResponses(plannerResponses); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + + } +} 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 e915c48e9b6..74392cd4299 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 @@ -84,6 +84,9 @@ public class CreateServiceOfferingCmd extends BaseCmd { @Parameter(name=ApiConstants.NETWORKRATE, type=CommandType.INTEGER, description="data transfer rate in megabits per second allowed. Supported only for non-System offering and system offerings having \"domainrouter\" systemvmtype") private Integer networkRate; + @Parameter(name = ApiConstants.DEPLOYMENT_PLANNER, type = CommandType.STRING, description = "The deployment planner heuristics used to deploy a VM of this offering, default \"FirstFitPlanner\".") + private String deploymentPlanner; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -148,6 +151,10 @@ public class CreateServiceOfferingCmd extends BaseCmd { return networkRate; } + public String getDeploymentPlanner() { + return deploymentPlanner; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/org/apache/cloudstack/api/command/admin/vlan/DedicatePublicIpRangeCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vlan/DedicatePublicIpRangeCmd.java new file mode 100755 index 00000000000..e7b1105af94 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/vlan/DedicatePublicIpRangeCmd.java @@ -0,0 +1,108 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.admin.vlan; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.ProjectResponse; +import org.apache.cloudstack.api.response.VlanIpRangeResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.log4j.Logger; + +import com.cloud.dc.Vlan; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.user.Account; + +@APICommand(name = "dedicatePublicIpRange", description="Dedicates a Public IP range to an account", responseObject=VlanIpRangeResponse.class) +public class DedicatePublicIpRangeCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(DedicatePublicIpRangeCmd.class.getName()); + + private static final String s_name = "dedicatepubliciprangeresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = VlanIpRangeResponse.class, + required=true, description="the id of the VLAN IP range") + private Long id; + + @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, required=true, + description="account who will own the VLAN") + private String accountName; + + @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, entityType = ProjectResponse.class, + description="project who will own the VLAN") + private Long projectId; + + @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType = DomainResponse.class, + required=true, description="domain ID of the account owning a VLAN") + private Long domainId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + public String getAccountName() { + return accountName; + } + + public Long getDomainId() { + return domainId; + } + + public Long getProjectId() { + return projectId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() throws ResourceUnavailableException, ResourceAllocationException { + Vlan result = _configService.dedicatePublicIpRange(this); + if (result != null) { + VlanIpRangeResponse response = _responseGenerator.createVlanIpRangeResponse(result); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to dedicate vlan ip range"); + } + } + +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/vlan/ReleasePublicIpRangeCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vlan/ReleasePublicIpRangeCmd.java new file mode 100644 index 00000000000..91cc7d33da9 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/vlan/ReleasePublicIpRangeCmd.java @@ -0,0 +1,77 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.admin.vlan; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.cloudstack.api.response.VlanIpRangeResponse; +import org.apache.log4j.Logger; + +import com.cloud.user.Account; + +@APICommand(name = "releasePublicIpRange", description="Releases a Public IP range back to the system pool", responseObject=SuccessResponse.class) +public class ReleasePublicIpRangeCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(ReleasePublicIpRangeCmd.class.getName()); + + private static final String s_name = "releasepubliciprangeresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = VlanIpRangeResponse.class, + required=true, description="the id of the Public IP range") + private Long id; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute(){ + boolean result = _configService.releasePublicIpRange(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to release public ip range"); + } + } +} 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 406f782da51..28fbae4437a 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 @@ -16,38 +16,21 @@ // under the License. package org.apache.cloudstack.api.command.user.address; -import java.util.List; - -import org.apache.cloudstack.api.APICommand; -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseAsyncCmd; -import org.apache.cloudstack.api.BaseAsyncCreateCmd; -import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.response.DomainResponse; -import org.apache.cloudstack.api.response.IPAddressResponse; -import org.apache.cloudstack.api.response.NetworkResponse; -import org.apache.cloudstack.api.response.ProjectResponse; -import org.apache.cloudstack.api.response.VpcResponse; -import org.apache.cloudstack.api.response.ZoneResponse; -import org.apache.log4j.Logger; - import com.cloud.async.AsyncJob; import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenter.NetworkType; import com.cloud.event.EventTypes; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientAddressCapacityException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.*; import com.cloud.network.IpAddress; import com.cloud.network.Network; import com.cloud.network.vpc.Vpc; import com.cloud.user.Account; import com.cloud.user.UserContext; +import org.apache.cloudstack.api.*; +import org.apache.cloudstack.api.response.*; +import org.apache.log4j.Logger; + +import java.util.List; @APICommand(name = "associateIpAddress", description="Acquires and associates a public IP to an account.", responseObject=IPAddressResponse.class) public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { @@ -213,7 +196,7 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { @Override public void create() throws ResourceAllocationException{ try { - IpAddress ip = _networkService.allocateIP(_accountService.getAccount(getEntityOwnerId()), false, getZoneId()); + IpAddress ip = _networkService.allocateIP(_accountService.getAccount(getEntityOwnerId()), getZoneId(), getNetworkId()); if (ip != null) { this.setEntityId(ip.getId()); 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 new file mode 100644 index 00000000000..96de4aa13c0 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/CreateAffinityGroupCmd.java @@ -0,0 +1,167 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.affinitygroup; + +import org.apache.cloudstack.affinity.AffinityGroup; +import org.apache.cloudstack.affinity.AffinityGroupResponse; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCreateCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.log4j.Logger; + +import com.cloud.async.AsyncJob; +import com.cloud.event.EventTypes; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.user.Account; +import com.cloud.user.UserContext; + +@APICommand(name = "createAffinityGroup", responseObject = AffinityGroupResponse.class, description = "Creates an affinity/anti-affinity group") +public class CreateAffinityGroupCmd extends BaseAsyncCreateCmd { + public static final Logger s_logger = Logger.getLogger(CreateAffinityGroupCmd.class.getName()); + + private static final String s_name = "createaffinitygroupresponse"; + + // /////////////////////////////////////////////////// + // ////////////// API parameters ///////////////////// + // /////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "an account for the affinity group. Must be used with domainId.") + private String accountName; + + @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, description = "domainId of the account owning the affinity group", entityType = DomainResponse.class) + private Long domainId; + + @Parameter(name = ApiConstants.DESCRIPTION, type = CommandType.STRING, description = "optional description of the affinity group") + private String description; + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "name of the affinity group") + private String affinityGroupName; + + @Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, required = true, description = "Type of the affinity group from the available affinity/anti-affinity group types") + private String affinityGroupType; + + + // /////////////////////////////////////////////////// + // ///////////////// Accessors /////////////////////// + // /////////////////////////////////////////////////// + + public String getAccountName() { + return accountName; + } + + public String getDescription() { + return description; + } + + public Long getDomainId() { + return domainId; + } + + public String getAffinityGroupName() { + return affinityGroupName; + } + + public String getAffinityGroupType() { + return affinityGroupType; + } + + // /////////////////////////////////////////////////// + // ///////////// API Implementation/////////////////// + // /////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + Account account = UserContext.current().getCaller(); + if ((account == null) || isAdmin(account.getType())) { + if ((domainId != null) && (accountName != null)) { + Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); + if (userAccount != null) { + return userAccount.getId(); + } + } + } + + if (account != null) { + return account.getId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this + // command to SYSTEM so ERROR events + // are tracked + } + + @Override + public void execute() { + AffinityGroup group = _affinityGroupService.getAffinityGroup(getEntityId()); + if (group != null) { + AffinityGroupResponse response = _responseGenerator.createAffinityGroupResponse(group); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create affinity group:" + + affinityGroupName); + } + } + + @Override + public void create() throws ResourceAllocationException { + AffinityGroup result = _affinityGroupService.createAffinityGroup(accountName, domainId, affinityGroupName, + affinityGroupType, description); + if (result != null) { + setEntityId(result.getId()); + setEntityUuid(result.getUuid()); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create affinity group entity" + affinityGroupName); + } + + } + + @Override + public String getEventType() { + return EventTypes.EVENT_AFFINITY_GROUP_CREATE; + } + + @Override + public String getEventDescription() { + return "creating Affinity Group"; + } + + @Override + public String getCreateEventType() { + return EventTypes.EVENT_AFFINITY_GROUP_CREATE; + } + + @Override + public String getCreateEventDescription() { + return "creating Affinity Group"; + } + + @Override + public AsyncJob.Type getInstanceType() { + return AsyncJob.Type.AffinityGroup; + } + +} 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 new file mode 100644 index 00000000000..ea4a010ab93 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/DeleteAffinityGroupCmd.java @@ -0,0 +1,154 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.affinitygroup; + +import org.apache.cloudstack.affinity.AffinityGroupResponse; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.log4j.Logger; + +import com.cloud.async.AsyncJob; +import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceInUseException; +import com.cloud.user.Account; +import com.cloud.user.UserContext; + +@APICommand(name = "deleteAffinityGroup", description = "Deletes affinity group", responseObject = SuccessResponse.class) +public class DeleteAffinityGroupCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(DeleteAffinityGroupCmd.class.getName()); + private static final String s_name = "deleteaffinitygroupresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "the account of the affinity group. Must be specified with domain ID") + private String accountName; + + @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, description = "the domain ID of account owning the affinity group", entityType = DomainResponse.class) + private Long domainId; + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "The ID of the affinity group. Mutually exclusive with name parameter", entityType = AffinityGroupResponse.class) + private Long id; + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "The name of the affinity group. Mutually exclusive with id parameter") + private String name; + + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public String getAccountName() { + return accountName; + } + + public Long getDomainId() { + return domainId; + } + + + public Long getId() { + if (id != null && name != null) { + throw new InvalidParameterValueException("name and id parameters are mutually exclusive"); + } + + if (name != null) { + id = _responseGenerator.getAffinityGroupId(name, getEntityOwnerId()); + if (id == null) { + throw new InvalidParameterValueException("Unable to find affinity group by name " + name + + " for the account id=" + getEntityOwnerId()); + } + } + + if (id == null) { + throw new InvalidParameterValueException( + "Either id or name parameter is requred by deleteAffinityGroup command"); + } + + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + Account account = UserContext.current().getCaller(); + if ((account == null) || isAdmin(account.getType())) { + if ((domainId != null) && (accountName != null)) { + Account userAccount = _responseGenerator.findAccountByNameDomain(accountName, domainId); + if (userAccount != null) { + return userAccount.getId(); + } + } + } + + if (account != null) { + return account.getId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this + // command to SYSTEM so ERROR events + // are tracked + + } + + @Override + public void execute(){ + try{ + boolean result = _affinityGroupService.deleteAffinityGroup(id, accountName, domainId, name); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete affinity group"); + } + } catch (ResourceInUseException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.RESOURCE_IN_USE_ERROR, ex.getMessage()); + } + } + + @Override + public String getEventType() { + return EventTypes.EVENT_AFFINITY_GROUP_DELETE; + } + + @Override + public String getEventDescription() { + return "Deleting Affinity Group"; + } + + @Override + public AsyncJob.Type getInstanceType() { + return AsyncJob.Type.AffinityGroup; + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupTypesCmd.java b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupTypesCmd.java new file mode 100644 index 00000000000..ce6e89a078c --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupTypesCmd.java @@ -0,0 +1,67 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.affinitygroup; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.cloudstack.affinity.AffinityGroupTypeResponse; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.log4j.Logger; + +import com.cloud.user.Account; + +@APICommand(name = "listAffinityGroupTypes", description = "Lists affinity group types available", responseObject = AffinityGroupTypeResponse.class) +public class ListAffinityGroupTypesCmd extends BaseListCmd { + public static final Logger s_logger = Logger.getLogger(ListAffinityGroupTypesCmd.class.getName()); + + private static final String s_name = "listaffinitygrouptypesresponse"; + + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public void execute() { + List result = _affinityGroupService.listAffinityGroupTypes(); + ListResponse response = new ListResponse(); + ArrayList responses = new ArrayList(); + if (result != null) { + for (String type : result) { + AffinityGroupTypeResponse affinityTypeResponse = new AffinityGroupTypeResponse(); + affinityTypeResponse.setType(type); + affinityTypeResponse.setObjectName("affinityGroupType"); + responses.add(affinityTypeResponse); + } + } + response.setResponses(responses); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } +} 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 new file mode 100644 index 00000000000..9310fb91016 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/ListAffinityGroupsCmd.java @@ -0,0 +1,90 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.affinitygroup; + +import org.apache.cloudstack.affinity.AffinityGroupResponse; +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.log4j.Logger; + +import com.cloud.async.AsyncJob; + +@APICommand(name = "listAffinityGroups", description = "Lists affinity groups", responseObject = AffinityGroupResponse.class) +public class ListAffinityGroupsCmd extends BaseListCmd { + public static final Logger s_logger = Logger.getLogger(ListAffinityGroupsCmd.class.getName()); + + private static final String s_name = "listaffinitygroupsresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "lists affinity groups by name") + private String affinityGroupName; + + @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, description = "lists affinity groups by virtual machine id", entityType = UserVmResponse.class) + private Long virtualMachineId; + + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, description = "list the affinity group by the id provided", entityType = AffinityGroupResponse.class) + private Long id; + + @Parameter(name = ApiConstants.TYPE, type = CommandType.STRING, description = "lists affinity groups by type") + private String affinityGroupType; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + public String getAffinityGroupName() { + return affinityGroupName; + } + + public Long getVirtualMachineId() { + return virtualMachineId; + } + + public Long getId(){ + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public void execute(){ + + ListResponse response = _queryService.listAffinityGroups(id, affinityGroupName, + affinityGroupType, virtualMachineId, this.getStartIndex(), this.getPageSizeVal()); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + + } + + @Override + public AsyncJob.Type getInstanceType() { + return AsyncJob.Type.AffinityGroup; + } +} 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 new file mode 100644 index 00000000000..44d017b7d8b --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/user/affinitygroup/UpdateVMAffinityGroupCmd.java @@ -0,0 +1,164 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.command.user.affinitygroup; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; + +import org.apache.cloudstack.affinity.AffinityGroupResponse; +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.BaseAsyncCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.ApiConstants.VMDetails; +import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.log4j.Logger; + +import com.cloud.async.AsyncJob; +import com.cloud.event.EventTypes; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.user.Account; +import com.cloud.user.UserContext; +import com.cloud.uservm.UserVm; + + +@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) +public class UpdateVMAffinityGroupCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(UpdateVMAffinityGroupCmd.class.getName()); + private static final String s_name = "updatevirtualmachineresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + + @ACL + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=UserVmResponse.class, + required=true, description="The ID of the virtual machine") + private Long id; + + @ACL + @Parameter(name = ApiConstants.AFFINITY_GROUP_IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AffinityGroupResponse.class, description = "comma separated list of affinity groups id that are going to be applied to the virtual machine. " + + "Should be passed only when vm is created from a zone with Basic Network support." + + " Mutually exclusive with securitygroupnames parameter") + private List affinityGroupIdList; + + @ACL + @Parameter(name = ApiConstants.AFFINITY_GROUP_NAMES, type = CommandType.LIST, collectionType = CommandType.STRING, entityType = AffinityGroupResponse.class, description = "comma separated list of affinity groups names that are going to be applied to the virtual machine." + + " Should be passed only when vm is created from a zone with Basic Network support. " + + "Mutually exclusive with securitygroupids parameter") + private List affinityGroupNameList; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + + public Long getId() { + return id; + } + + + public List getAffinityGroupIdList() { + if (affinityGroupNameList != null && affinityGroupIdList != null) { + throw new InvalidParameterValueException( + "affinitygroupids parameter is mutually exclusive with affinitygroupnames parameter"); + } + + // transform group names to ids here + if (affinityGroupNameList != null) { + List affinityGroupIds = new ArrayList(); + for (String groupName : affinityGroupNameList) { + Long groupId = _responseGenerator.getAffinityGroupId(groupName, getEntityOwnerId()); + if (groupId == null) { + throw new InvalidParameterValueException("Unable to find group by name " + groupName + + " for account " + getEntityOwnerId()); + } else { + affinityGroupIds.add(groupId); + } + } + return affinityGroupIds; + } else { + return affinityGroupIdList; + } + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + + @Override + public String getCommandName() { + return s_name; + } + + public static String getResultObjectName() { + return "virtualmachine"; + } + + @Override + public long getEntityOwnerId() { + UserVm userVm = _entityMgr.findById(UserVm.class, getId()); + if (userVm != null) { + return userVm.getAccountId(); + } + + return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked + } + + @Override + public void execute() throws ResourceUnavailableException, + InsufficientCapacityException, ServerApiException { + UserContext.current().setEventDetails("Vm Id: "+getId()); + UserVm result = _affinityGroupService.updateVMAffinityGroups(getId(), getAffinityGroupIdList()); + ArrayList dc = new ArrayList(); + dc.add(VMDetails.valueOf("affgrp")); + EnumSet details = EnumSet.copyOf(dc); + + if (result != null){ + UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", details, result).get(0); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update vm's affinity groups"); + } + } + + @Override + public String getEventType() { + return EventTypes.EVENT_VM_AFFINITY_GROUP_UPDATE; + } + + @Override + public String getEventDescription() { + return "updating VM Affinity Group"; + } + + @Override + public AsyncJob.Type getInstanceType() { + return AsyncJob.Type.AffinityGroup; + } + +} diff --git a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java index cd559d8c470..b08b6aeff17 100644 --- a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/CreateGlobalLoadBalancerRuleCmd.java @@ -93,6 +93,9 @@ public class CreateGlobalLoadBalancerRuleCmd extends BaseAsyncCreateCmd { } public String getStickyMethod() { + if (stickyMethod == null) { + return "sourceip"; + } return stickyMethod; } 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 21a45f8cc7f..77ba9fed59e 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 @@ -25,6 +25,7 @@ import java.util.List; import java.util.Map; import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.ACL; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -172,6 +173,16 @@ public class DeployVMCmd extends BaseAsyncCreateCmd { @Parameter(name=ApiConstants.START_VM, type=CommandType.BOOLEAN, description="true if network offering supports specifying ip ranges; defaulted to true if not specified") private Boolean startVm; + @ACL + @Parameter(name = ApiConstants.AFFINITY_GROUP_IDS, type = CommandType.LIST, collectionType = CommandType.UUID, entityType = AffinityGroupResponse.class, description = "comma separated list of affinity groups id that are going to be applied to the virtual machine." + + " Mutually exclusive with affinitygroupnames parameter") + private List affinityGroupIdList; + + @ACL + @Parameter(name = ApiConstants.AFFINITY_GROUP_NAMES, type = CommandType.LIST, collectionType = CommandType.STRING, entityType = AffinityGroupResponse.class, description = "comma separated list of affinity groups names that are going to be applied to the virtual machine." + + "Mutually exclusive with affinitygroupids parameter") + private List affinityGroupNameList; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -321,6 +332,30 @@ public class DeployVMCmd extends BaseAsyncCreateCmd { return ip6Address.toLowerCase(); } + public List getAffinityGroupIdList() { + if (affinityGroupNameList != null && affinityGroupIdList != null) { + throw new InvalidParameterValueException( + "affinitygroupids parameter is mutually exclusive with affinitygroupnames parameter"); + } + + // transform group names to ids here + if (affinityGroupNameList != null) { + List affinityGroupIds = new ArrayList(); + for (String groupName : affinityGroupNameList) { + Long groupId = _responseGenerator.getAffinityGroupId(groupName, getEntityOwnerId()); + if (groupId == null) { + throw new InvalidParameterValueException("Unable to find group by name " + groupName + + " for account " + getEntityOwnerId()); + } else { + affinityGroupIds.add(groupId); + } + } + return affinityGroupIds; + } else { + return affinityGroupIdList; + } + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -447,18 +482,18 @@ public class DeployVMCmd extends BaseAsyncCreateCmd { throw new InvalidParameterValueException("Can't specify network Ids in Basic zone"); } else { vm = _userVmService.createBasicSecurityGroupVirtualMachine(zone, serviceOffering, template, getSecurityGroupIdList(), owner, name, - displayName, diskOfferingId, size, group, getHypervisor(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, keyboard); + displayName, diskOfferingId, size, group, getHypervisor(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, keyboard, getAffinityGroupIdList()); } } else { if (zone.isSecurityGroupEnabled()) { vm = _userVmService.createAdvancedSecurityGroupVirtualMachine(zone, serviceOffering, template, getNetworkIds(), getSecurityGroupIdList(), - owner, name, displayName, diskOfferingId, size, group, getHypervisor(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, keyboard); + owner, name, displayName, diskOfferingId, size, group, getHypervisor(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, keyboard, getAffinityGroupIdList()); } else { if (getSecurityGroupIdList() != null && !getSecurityGroupIdList().isEmpty()) { throw new InvalidParameterValueException("Can't create vm with security groups; security group feature is not enabled per zone"); } vm = _userVmService.createAdvancedVirtualMachine(zone, serviceOffering, template, getNetworkIds(), owner, name, displayName, - diskOfferingId, size, group, getHypervisor(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, keyboard); + diskOfferingId, size, group, getHypervisor(), userData, sshKeyPairName, getIpToNetworkMap(), addrs, keyboard, getAffinityGroupIdList()); } } diff --git a/api/src/org/apache/cloudstack/api/response/DeploymentPlannersResponse.java b/api/src/org/apache/cloudstack/api/response/DeploymentPlannersResponse.java new file mode 100644 index 00000000000..a37800fd650 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/DeploymentPlannersResponse.java @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.api.response; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; + +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +public class DeploymentPlannersResponse extends BaseResponse { + @SerializedName(ApiConstants.NAME) + @Param(description = "Deployment Planner name") + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/api/src/org/apache/cloudstack/api/response/GlobalLoadBalancerResponse.java b/api/src/org/apache/cloudstack/api/response/GlobalLoadBalancerResponse.java index 0fd064f41b5..38e080bd28a 100644 --- a/api/src/org/apache/cloudstack/api/response/GlobalLoadBalancerResponse.java +++ b/api/src/org/apache/cloudstack/api/response/GlobalLoadBalancerResponse.java @@ -50,6 +50,10 @@ public class GlobalLoadBalancerResponse extends BaseResponse implements Controll @Param(description = "session persistence method used for the global load balancer") private String stickyMethod; + @SerializedName(ApiConstants.GSLB_SERVICE_TYPE) + @Param(description = "GSLB service type") + private String serviceType; + @SerializedName(ApiConstants.REGION_ID) @Param(description = "Region Id in which global load balancer is created") private Integer regionId; @@ -96,6 +100,10 @@ public class GlobalLoadBalancerResponse extends BaseResponse implements Controll this.stickyMethod = stickyMethod; } + public void setServiceType(String serviceType) { + this.serviceType = serviceType; + } + public void setServiceDomainName(String domainName) { this.gslbDomainName = domainName; } diff --git a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java index 71d1b823c6a..212601ce20c 100644 --- a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java +++ b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java @@ -21,6 +21,7 @@ import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; +import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; @@ -169,10 +170,15 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp @SerializedName(ApiConstants.SSH_KEYPAIR) @Param(description="ssh key-pair") private String keyPairName; + @SerializedName("affinitygroup") + @Param(description = "list of affinity groups associated with the virtual machine", responseObject = AffinityGroupResponse.class) + private Set affinityGroupList; + public UserVmResponse(){ securityGroupList = new LinkedHashSet(); nics = new LinkedHashSet(); tags = new LinkedHashSet(); + affinityGroupList = new LinkedHashSet(); } public void setHypervisor(String hypervisor) { @@ -381,4 +387,12 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp this.keyPairName = keyPairName; } + public void setAffinityGroupList(Set affinityGroups) { + this.affinityGroupList = affinityGroups; + } + + public void addAffinityGroup(AffinityGroupResponse affinityGroup) { + this.affinityGroupList.add(affinityGroup); + } + } diff --git a/api/src/org/apache/cloudstack/network/ExternalNetworkDeviceManager.java b/api/src/org/apache/cloudstack/network/ExternalNetworkDeviceManager.java index aeed81d2011..29ce2e3971d 100644 --- a/api/src/org/apache/cloudstack/network/ExternalNetworkDeviceManager.java +++ b/api/src/org/apache/cloudstack/network/ExternalNetworkDeviceManager.java @@ -43,6 +43,7 @@ public interface ExternalNetworkDeviceManager extends Manager { public static final NetworkDevice F5BigIpLoadBalancer = new NetworkDevice("F5BigIpLoadBalancer", Network.Provider.F5BigIp.getName()); public static final NetworkDevice JuniperSRXFirewall = new NetworkDevice("JuniperSRXFirewall", Network.Provider.JuniperSRX.getName()); public static final NetworkDevice NiciraNvp = new NetworkDevice("NiciraNvp", Network.Provider.NiciraNvp.getName()); + public static final NetworkDevice CiscoVnmc = new NetworkDevice("CiscoVnmc", Network.Provider.CiscoVnmc.getName()); public NetworkDevice(String deviceName, String ntwkServiceprovider) { _name = deviceName; diff --git a/api/src/org/apache/cloudstack/query/QueryService.java b/api/src/org/apache/cloudstack/query/QueryService.java index c3f86aabb7f..443c5df65b5 100644 --- a/api/src/org/apache/cloudstack/query/QueryService.java +++ b/api/src/org/apache/cloudstack/query/QueryService.java @@ -16,6 +16,7 @@ // under the License. package org.apache.cloudstack.query; +import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.command.admin.host.ListHostsCmd; import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd; import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd; @@ -97,4 +98,7 @@ public interface QueryService { public ListResponse searchForServiceOfferings(ListServiceOfferingsCmd cmd); public ListResponse listDataCenters(ListZonesByCmd cmd); + + public ListResponse listAffinityGroups(Long affinityGroupId, String affinityGroupName, + String affinityGroupType, Long vmId, Long startIndex, Long pageSize); } diff --git a/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java b/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java index 29a002cebaf..630e16fb5f3 100644 --- a/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java +++ b/awsapi/src/com/cloud/bridge/service/EC2RestServlet.java @@ -209,7 +209,7 @@ public class EC2RestServlet extends HttpServlet { if (installedPath == null) installedPath = System.getProperty("catalina.home"); String webappPath = config.getServletContext().getRealPath("/"); //pathToKeystore = new String( installedPath + File.separator + "webapps" + File.separator + webappName + File.separator + "WEB-INF" + File.separator + "classes" + File.separator + keystore ); - pathToKeystore = new String( webappPath + File.separator + "\\WEB-INF" + File.separator + "classes" + File.separator + keystore ); + pathToKeystore = new String( webappPath + File.separator + "WEB-INF" + File.separator + "classes" + File.separator + keystore ); } } diff --git a/build/replace.properties b/build/replace.properties index c9a93c2831c..265f3358724 100644 --- a/build/replace.properties +++ b/build/replace.properties @@ -27,3 +27,4 @@ MSMNTDIR=/mnt COMPONENTS-SPEC=components.xml AWSAPILOG=awsapi.log REMOTEHOST=localhost +COMMONLIBDIR=C:\Users\htrippaers\eclipse_workspace\cloudstack\client\target\cloud-client-ui-4.2.0-SNAPSHOT\WEB-INF\classes diff --git a/client/pom.xml b/client/pom.xml index b3d7acb08a8..743cd363005 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -234,6 +234,11 @@ cloud-plugin-snmp-alerts ${project.version} + + org.apache.cloudstack + cloud-plugin-host-anti-affinity + ${project.version} + install @@ -284,7 +289,7 @@ --> copy-systemvm - package + process-resources run @@ -450,6 +455,11 @@ file="${basedir}/target/generated-webapp/WEB-INF/web.xml" match="classpath:componentContext.xml" replace="classpath:nonossComponentContext.xml" byline="true" /> + + + + + @@ -634,6 +644,11 @@ cloud-vmware-base ${project.version} + + org.apache.cloudstack + cloud-plugin-network-cisco-vnmc + ${project.version} + diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in index 67b1286eaed..866e3ed3291 100644 --- a/client/tomcatconf/applicationContext.xml.in +++ b/client/tomcatconf/applicationContext.xml.in @@ -454,11 +454,11 @@ - + - + @@ -609,8 +609,10 @@ + + - + @@ -733,7 +735,7 @@ - + @@ -836,5 +838,18 @@ --> + + + + + + + + + + + + + diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 163c2cee861..10fcfe3f687 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -124,6 +124,8 @@ listDiskOfferings=15 createVlanIpRange=1 deleteVlanIpRange=1 listVlanIpRanges=1 +dedicatePublicIpRange=1 +releasePublicIpRange=1 #### address commands associateIpAddress=15 @@ -568,3 +570,21 @@ revertToSnapshot=15 #### Baremetal commands addBaremetalHost=1 + +#### Affinity group commands +createAffinityGroup=15 +deleteAffinityGroup=15 +listAffinityGroups=15 +updateVMAffinityGroup=15 +listAffinityGroupTypes=15 + +#### Cisco Vnmc commands +addCiscoVnmcResource=1 +deleteCiscoVnmcResource=1 +listCiscoVnmcResources=1 + +#### Cisco Asa1000v commands +addCiscoAsa1000vResource=1 +deleteCiscoAsa1000vResource=1 +listCiscoAsa1000vResources=1 + diff --git a/client/tomcatconf/componentContext.xml.in b/client/tomcatconf/componentContext.xml.in index bea2f787c17..7a469816f82 100644 --- a/client/tomcatconf/componentContext.xml.in +++ b/client/tomcatconf/componentContext.xml.in @@ -31,6 +31,7 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> + @@ -197,6 +197,7 @@ + @@ -249,5 +250,20 @@ - + + + + + + + + + + + + + + diff --git a/client/tomcatconf/nonossComponentContext.xml.in b/client/tomcatconf/nonossComponentContext.xml.in index fc8a9cd5409..2359ba80699 100644 --- a/client/tomcatconf/nonossComponentContext.xml.in +++ b/client/tomcatconf/nonossComponentContext.xml.in @@ -136,6 +136,16 @@ + + + + + + + + @@ -283,6 +293,7 @@ + @@ -324,6 +335,7 @@ + @@ -339,5 +351,21 @@ + + + + + + + + + + + + + + diff --git a/client/tomcatconf/simulatorComponentContext.xml.in b/client/tomcatconf/simulatorComponentContext.xml.in index fc5cf540bd0..9d8c6c0ce93 100644 --- a/client/tomcatconf/simulatorComponentContext.xml.in +++ b/client/tomcatconf/simulatorComponentContext.xml.in @@ -1,4 +1,3 @@ - - - + + @@ -122,9 +121,9 @@ - - - + + + + + + + + + + + + + + + diff --git a/core/src/com/cloud/vm/VmDetailConstants.java b/core/src/com/cloud/vm/VmDetailConstants.java index 90068d1b72b..5ff3ce02fe4 100644 --- a/core/src/com/cloud/vm/VmDetailConstants.java +++ b/core/src/com/cloud/vm/VmDetailConstants.java @@ -20,4 +20,5 @@ public interface VmDetailConstants { public static final String KEYBOARD = "keyboard"; public static final String NIC_ADAPTER = "nicAdapter"; public static final String ROOK_DISK_CONTROLLER = "rootDiskController"; + public static final String NESTED_VIRTUALIZATION_FLAG = "nestedVirtualizationFlag"; } diff --git a/debian/cloudstack-awsapi.install b/debian/cloudstack-awsapi.install index 02ba66829ef..675b84def74 100644 --- a/debian/cloudstack-awsapi.install +++ b/debian/cloudstack-awsapi.install @@ -15,4 +15,12 @@ # specific language governing permissions and limitations # under the License. -/var/log/cloudstack/awsapi \ No newline at end of file +/etc/cloudstack/management/cloud-bridge.properties +/etc/cloudstack/management/commons-logging.properties +/etc/cloudstack/management/crypto.properties +/etc/cloudstack/management/xes.keystore +/etc/cloudstack/management/ec2-service.properties +/var/log/cloudstack/awsapi +/usr/bin/cloudstack-setup-bridge +/usr/bin/cloudstack-aws-api-register +/usr/share/cloudstack-bridge \ No newline at end of file diff --git a/debian/rules b/debian/rules index 4e55c71048c..f5f68aba03d 100755 --- a/debian/rules +++ b/debian/rules @@ -34,7 +34,7 @@ build: build-indep build-indep: build-indep-stamp build-indep-stamp: configure - mvn package -DskipTests -Dsystemvm \ + mvn -Pawsapi package -DskipTests -Dsystemvm \ -Dcs.replace.properties=replace.properties.tmp touch $@ @@ -147,7 +147,25 @@ install: install -D packaging/debian/init/cloud-usage $(DESTDIR)/$(SYSCONFDIR)/init.d/$(PACKAGE)-usage # cloudstack-awsapi + mkdir $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/awsapi mkdir $(DESTDIR)/var/log/$(PACKAGE)/awsapi + mkdir $(DESTDIR)/usr/share/$(PACKAGE)-bridge + mkdir -p $(DESTDIR)/usr/share/$(PACKAGE)-bridge/webapps/awsapi + mkdir $(DESTDIR)/usr/share/$(PACKAGE)-bridge/setup + cp -r awsapi/target/cloud-awsapi-$(VERSION)-SNAPSHOT/* $(DESTDIR)/usr/share/$(PACKAGE)-bridge/webapps/awsapi + install -D awsapi-setup/setup/cloud-setup-bridge $(DESTDIR)/usr/bin/cloudstack-setup-bridge + install -D awsapi-setup/setup/cloudstack-aws-api-register $(DESTDIR)/usr/bin/cloudstack-aws-api-register + cp -r awsapi-setup/db/mysql/* $(DESTDIR)/usr/share/$(PACKAGE)-bridge/setup + for i in applicationContext.xml cloud-bridge.properties commons-logging.properties crypto.properties xes.keystore ec2-service.properties; do \ + mv $(DESTDIR)/usr/share/$(PACKAGE)-bridge/webapps/awsapi/WEB-INF/classes/$$i $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/management/; \ + done + rm $(DESTDIR)/usr/share/$(PACKAGE)-bridge/webapps/awsapi/WEB-INF/classes/log4j-vmops.xml + rm $(DESTDIR)/usr/share/$(PACKAGE)-bridge/webapps/awsapi/WEB-INF/classes/log4j.properties + rm $(DESTDIR)/usr/share/$(PACKAGE)-bridge/webapps/awsapi/WEB-INF/classes/db.properties + rm $(DESTDIR)/usr/share/$(PACKAGE)-bridge/webapps/awsapi/WEB-INF/classes/LICENSE.txt + rm $(DESTDIR)/usr/share/$(PACKAGE)-bridge/webapps/awsapi/WEB-INF/classes/NOTICE.txt + rm $(DESTDIR)/usr/share/$(PACKAGE)-bridge/webapps/awsapi/WEB-INF/classes/services.xml + rm -rf $(DESTDIR)/usr/share/$(PACKAGE)-bridge/webapps/awsapi/WEB-INF/classes/META-INF dh_installdirs dh_install diff --git a/docs/en-US/Admin_Guide.xml b/docs/en-US/Admin_Guide.xml index 07f5e889fc8..d3b9706f84e 100644 --- a/docs/en-US/Admin_Guide.xml +++ b/docs/en-US/Admin_Guide.xml @@ -26,7 +26,7 @@ &PRODUCT; Administrator's Guide Apache CloudStack - 4.0.0-incubating + 4.2.0 1 diff --git a/docs/en-US/Book_Info.xml b/docs/en-US/Book_Info.xml index 0ab84c40d9b..327668dfc9d 100644 --- a/docs/en-US/Book_Info.xml +++ b/docs/en-US/Book_Info.xml @@ -27,7 +27,7 @@ &PRODUCT; Guide Revised August 9, 2012 10:48 pm Pacific Apache CloudStack - 4.0.0 + 4.2.0 1 diff --git a/docs/en-US/CloudStack_Nicira_NVP_Guide.xml b/docs/en-US/CloudStack_Nicira_NVP_Guide.xml index a4c367c26f7..7f156d5dc09 100644 --- a/docs/en-US/CloudStack_Nicira_NVP_Guide.xml +++ b/docs/en-US/CloudStack_Nicira_NVP_Guide.xml @@ -28,7 +28,7 @@ &PRODUCT; Plugin Guide for the Nicira NVP Plugin Apache CloudStack - 4.0.0-incubating + 4.2.0 1 diff --git a/docs/en-US/Developers_Guide.xml b/docs/en-US/Developers_Guide.xml index c86208b3271..87dc8a6675a 100644 --- a/docs/en-US/Developers_Guide.xml +++ b/docs/en-US/Developers_Guide.xml @@ -26,7 +26,7 @@ &PRODUCT; Developer's Guide Apache CloudStack - 4.1.0-incubating + 4.2.0 diff --git a/docs/en-US/Installation_Guide.xml b/docs/en-US/Installation_Guide.xml index 6ce5527e86c..e6a80318611 100644 --- a/docs/en-US/Installation_Guide.xml +++ b/docs/en-US/Installation_Guide.xml @@ -25,7 +25,7 @@ &PRODUCT; Installation Guide Apache CloudStack - 4.0.0 + 4.2.0 1 diff --git a/docs/en-US/Release_Notes.xml b/docs/en-US/Release_Notes.xml index b8c5c01fb0b..f449518401b 100644 --- a/docs/en-US/Release_Notes.xml +++ b/docs/en-US/Release_Notes.xml @@ -27,6 +27,4089 @@ under the License. This document contains information specific to this release of &PRODUCT;, including upgrade instructions from prior releases, new features added to &PRODUCT;, API changes, and issues fixed in the release. For installation instructions, please see the Installation Guide. For usage and administration instructions, please see the &PRODUCT; Administrator's Guide. Developers and users who wish to work with the API will find instruction in the &PRODUCT; API Developer's Guide If you find any errors or problems in this guide, please see . We hope you enjoy working with &PRODUCT;! + + Version 4.1.0 +
+ What’s New in 4.1 + Apache CloudStack 4.1.0 includes many new features. This section covers the most prominent new features and changes. +
+ Localization + The 4.1.0 release adds partial User Interface (UI) support for Catalan, Chinese, French, German, Italian, Japanese, Korean, Norwegian, Portuguese, Russian, and Spanish. Not all languages are complete. + The 4.1.0 release also adds documentation translations for Chinese, Chinese (Taiwan), Italian, Japanese, Korean, and Portuguese. +
+
+ Added Region Support + CLOUDSTACK-241: This feature adds a "region" construct that spans several management servers. The objective of this feature is to add AWS EC2 like Regions implementation into CloudStack. Regions are dispersed and located in separate geographic areas. Availability Zones (or Zones in CloudStack) are distinct locations within a Region that are engineered to be isolated from failures in other Zones and provide inexpensive, low latency network connectivity to other Zones in the same Region. + Regions are expected to add the following benefits + + Higher availability of the services: users can deploy services across AZs and even if one of the AZ goes down the services are still available to the end-user through VMs deployed in other zones. + Higher availability of the Management Server (MS): Since each MS Cluster only manages a single Region, if that MS Cluster goes down, only that particular Region is impacted. Admin should be able to access all the other Regions. + Scalability: The scalability limit of CloudStack dramatically improves, as the scalability limit of MS Cluster is limited to a single Region. + Object Store: With Regions construct, CloudStack would also allow users to define Object Store (Secondary Storage) across AZs. This helps users easily deploy VMs in different AZs using the same template, offerings. + Geographical Grouping: Regions allow admins to group AZs (that have low latency and are geographically located nearby) into a broader region construct. + + Currently the Region feature is exposed in the API, but does not have a UI component. +
+
+ Support for EC2 Query API + CLOUDSTACK-197: This introduces a query API for the AWS APIs that are currently only supported by SOAP. The AWS Java SDK and AWS PHP SDK should now be supported by the AWSAPI in CloudStack. + Supported Query APIs in 4.1.0: + + AllocateAddress + AssociateAddress + AttachVolume + AuthorizeSecurityGroupIngress + CreateImage + CreateKeyPair + CreateSecurityGroup + CreateSnapshot + CreateTags + CreateVolume + DeleteKeyPair + DeleteSecurityGroup + DeleteSnapshot + DeleteTags + DeleteVolume + DeregisterImage + DescribeAddresses + DescribeAvailabilityZones + DescribeImageAttribute + DescribeImages + DescribeInstanceAttribute + DescribeInstances + DescribeKeyPairs + DescribeSecurityGroups + DescribeSnapshots + DescribeTags + DescribeVolumes + DetachVolume + DisassociateAddress + GetPasswordData + ImportkeyPair + ModifyImageAttribute + RebootInstances + RegisterImage + ReleaseAddress + ResetImageAttribute + RevokeSecurityGroupIngress + RunInstances + StartInstances + StopInstances + TerminateInstances + + See the Feature Specification for more information on the Query API support. +
+
+ Auto-Completing Shell for CloudStack (CloudMonkey) + CLOUDSTACK-132: Adds a auto-completing shell and command-line tool for &PRODUCT; written in Python, called CloudMonkey. + CloudMonkey includes the following features: + + Usable as a command line tool and interactive shell. + All commands are lowercase unlike API. + Api Discovery using sync feature, with build time api precaching for failsafe sync. + Raw api execution support. + Auto-completion via double tab. + Reverse search using Ctrl+R + Emacs compatible key bindings. + Output that's "pipeable" to other *nix programs. + Unix shell execution. + Support to handle asynchronous jobs using user defined blocking or non-blocking way. + Tabular or JSON output with filtering of table columns. + Colored output. + API parameter value completion (based on predication, fuzzy results may fail sometimes). + + CloudMonkey has a few requirements above and beyond CloudStack, and does not need to be run on the same machine as a management server. If you wish to run CloudMonkey you'll need Python 2.5 or later, readline, Pygments, and prettytable. CloudMonkey can be installed with pip: + $ pip install cloudmonkey + See the Developer's Guide and the CloudStack wiki for the latest information on CloudMonkey installation and use. +
+
+ API Discovery Service + CLOUDSTACK-926: CloudStack has more than 300 APIs and more are added in each major release. CloudStack admins can enable or disable APIs, or add plugins which provide more APIs. The API Discovery Service is a plugin which will help users discover the APIs available to them on a CloudStack Management Server. + The discovery service implements a method called listApis which will return information about APIs for a user. It currently accepts an apiName to list api information of that particular API. The method ensures that user can only list APIs they are entitled to. + All CloudStack APIs are implemented by annotated command class and PluggableService is a contract implemented by all the components such as the Management Server and all the plugins which provide an API. During load time, API discovery service asks all the pluggable services to return list of API cmd classes from whose fields and annotations it gathers information about each API, the information consists of name, description, parameter name, parameter description, etc. + For more information on the implementation of the API Discovery Service for 4.1.0, see the CloudStack wiki. +
+
+ Events Framework + CLOUDSTACK-820: The Events Framework provides a mechanism to publish and subscribe to events in &PRODUCT;. +
+
+ Additional VMX Settings + ### +
+
+ L3 Router Functionality in Nicira Nvp Plugin + ### +
+
+ Persistent Networks without Running VM + ### +
+
+ Add/Remove Network on VM + ### +
+
+ Resize Volumes Feature + ### +
+
+ Autoscale + ### +
+
+ API Request Throttling + CLOUDSTACK-618: Limits the number of API requests per second that can be placed against a management server to avoid DoS attacks via API requests. + The throttling is controlled by the api.throttling.enabled, api.throttling.interval, and api.throttling.max configuration settings. Note that api.throttling.enabled is set to false by default. +
+
+ S3 Backed Secondary Storage + CLOUDSTACK-509: This enhancement backs NFS secondary storage with an S3-compatible object store. Periodically, a reaper thread synchronizes the templates, ISOs, and snapshots stored on a NFS secondary storage mount with a configured S3 object store. In addition to permitting the use of commodity or IaaS storage solutions for static assets, it provides a means of automatically synchronizing template and ISO assets across multiple zones. + See the &PRODUCT; wiki for more information on this feature, currently the documentation is incomplete. +
+
+ User and Domain Admin Can Create API Key and Secret + CLOUDSTACK-437: This feature adds the ability for domain admins and users to create their own API Key and Secret. Domain admins can create keys for themselves, subdomain admins, and for regular users, but not for other domain admins. +
+
+ Support Inline Mode for F5 and SRX + CLOUDSTACK-306: For &PRODUCT; deployments using the Juniper SRX (firewall) and F5 Big IP (load balancer), &PRODUCT; 4.1.0 supports putting the firewall in front of the load balancer, making the firewall device the gateway and putting the load balancer behind the public network. +
+
+ Egress Firewall Rules for Guest Networks + CLOUDSTACK-299: This feature allows users to create egress (exit) traffic rules from private networks to public networks (e.g. from your internal network to the public Internet). By default all traffic is blocked from internal networks to the public networks, this allows you to open ports as necessary. + Egress traffic rules are suppored only on virtual routers at this time, physical devices are not supported. +
+
+ Reset SSH Key to Access VM + CLOUDSTACK-297: &PRODUCT; 4.1.0 introduces a new API resetSSHKeyForVirtualMachine, that can allow them to set or reset the SSH keypair assigned to a virtual machine. +
+
+
+ Issues Fixed in 4.1.0 + Apache CloudStack uses Jira + to track its issues. All new features and bugs for 4.1.0 have been tracked in Jira, and have + a standard naming convention of "CLOUDSTACK-NNNN" where "NNNN" is the issue number. + This section includes a summary of known issues against 4.0.0 that were fixed in 4.1.0. Approximately 470 bugs were resolved or closed in the 4.1.0 cycle. + + + + + + + + Defect + + + Description + + + + + + + CLOUDSTACK-46 + + + Remnants of mycloud remain. + + + + + CLOUDSTACK-70 + + + Improve Network Restart Behaviour for Basic Zone: Restarting Network Fail + + + + + CLOUDSTACK-94 + + + "API command, listIsos documentation clarity + + + + + CLOUDSTACK-95 + + + IP address allocation not working when a user tries to allocate IP addresses in a Project + + + + + CLOUDSTACK-97 + + + Vmware network labels are ignored when creating a Zone using basic networkin + + + + + CLOUDSTACK-108 + + + VM should not be allowed to be deployed on two Isolated Networks of an Account that were created from DefaultNetworkOfferingwithSourceNATService + + + + + CLOUDSTACK-118 + + + "Status of host resorce stuck in ""ErrorInMaintenance"" + + + + + CLOUDSTACK-119 + + + Move Agent-Simulator in to the hypervisor plugin mode + + + + + CLOUDSTACK-130 + + + Clarify docs on tags parameter in API referenc + + + + + CLOUDSTACK-152 + + + Routes on the User VM are programmed incorrectly on a VM present on both Isolated and Shared Guest Network + + + + + CLOUDSTACK-178 + + + Expose name parameter of VM in list Vm view + + + + + CLOUDSTACK-198 + + + vpn:failto add VPN Users deletes all the existing Vpn use + + + + + CLOUDSTACK-222 + + + Admin UI prompts to restart Management server with cancel edit operatio + + + + + CLOUDSTACK-225 + + + API Docs: Request params repeated with different description + + + + + CLOUDSTACK-226 + + + UpdatePhysicalNetworkcommand failed due to java.sql.BatchUpdateException ; Tried to extend the existing Guest VLAN Range of one physical network into the Guest VLAN range of the other physical networ + + + + + CLOUDSTACK-227 + + + ReconnectHostCmd: NullPointerException: Unable to get host Information for XenServer 6.0.2 host - on intentionally changing the traffic labels on the physical networ + + + + + CLOUDSTACK-228 + + + UI provides an option to reconnect a disconnected host - ServerApiException is thrown on an attemp + + + + + CLOUDSTACK-232 + + + Zone infrastructure chart -- disable resource total displa + + + + + CLOUDSTACK-235 + + + Network rate can be set in 2 places. Clarify docs on how this works + + + + + CLOUDSTACK-249 + + + Add host id to failed VM deploy alert + + + + + CLOUDSTACK-250 + + + Incorrect description of maintenance mode in admin guid + + + + + CLOUDSTACK-256 + + + "vpn:As an admin user, not able to delete VPN user which is present in a regular user's network. + + + + + CLOUDSTACK-271 + + + updatePhysicalNetwork dies with an NPE when the vlan range is empt + + + + + CLOUDSTACK-274 + + + Two error codes mapped to same value in AP + + + + + CLOUDSTACK-275 + + + hostid not always a UUI + + + + + CLOUDSTACK-277 + + + Message during CloudStack management server Installation: cannot access /usr/share/cloud/bridge/lib: No such file or director + + + + + CLOUDSTACK-279 + + + deleteProject fails when executed by the regular user (works fine for root/domain admin + + + + + CLOUDSTACK-284 + + + listVirtualMachines does not return deleted machines when zone is specifie + + + + + CLOUDSTACK-290 + + + 3.0.0 template also needed for 2.2.14 to 3.0.5 direct upgrade + + + + + CLOUDSTACK-293 + + + "We do awful, hacky things in our spec file for client + + + + + CLOUDSTACK-304 + + + Add synchronization for createSnapshot command per host basi + + + + + CLOUDSTACK-309 + + + iptables rules being deleted from wrong VM after a migratio + + + + + CLOUDSTACK-318 + + + Adding XenServer Host Fails - 6.0.2 fails with 4.0. + + + + + CLOUDSTACK-320 + + + "sessionKey query parameter should be case-insensitive, now only sessionkey is accepted + + + + + CLOUDSTACK-322 + + + During upgrade displays error - a foreign key constraint fails (`cloud/#sql-f34_6e`.. + + + + + CLOUDSTACK-332 + + + """count"" property in list* API response should be equal to how many entries in database, not how many objects in API response + + + + + CLOUDSTACK-333 + + + When Datacenter name in VCenter has spaces Primary Storage (VMFS) discovery will fai + + + + + CLOUDSTACK-335 + + + KVM VPC load balancer not workin + + + + + CLOUDSTACK-336 + + + listZones doesn't honour pagin + + + + + CLOUDSTACK-343 + + + "Document what tools and packages are required to build, package and install CloudStack 4.0 + + + + + CLOUDSTACK-346 + + + Cannot add Vmware cluster with class loader conflict exceptio + + + + + CLOUDSTACK-347 + + + listNetworks API: return vlan information only when the caller is ROOT admi + + + + + CLOUDSTACK-348 + + + deleteNetwork does not clean up network resource count correctl + + + + + CLOUDSTACK-354 + + + Display of storage statistics is wrong + + + + + CLOUDSTACK-355 + + + "Fix ""count"" in a bunch of API commands + + + + + CLOUDSTACK-357 + + + "ISOs can be deleted while still attached to a running VM, and they subsequently cannot be detached from a running VM + + + + + CLOUDSTACK-359 + + + PropagateResourceEventCommand failes in cluster configuratio + + + + + CLOUDSTACK-361 + + + Wrong creation of guest networks on a KVM host in Multiple Physical Networks with guest traffi + + + + + CLOUDSTACK-364 + + + Docs point to download.cloud.com for AWS API scrip + + + + + CLOUDSTACK-368 + + + OVM - cannot create guest V + + + + + CLOUDSTACK-369 + + + ASF 4.0 - unable to support XenServer 6.1 hos + + + + + CLOUDSTACK-373 + + + "static NAT and Firewall is not working on external firewall device SRX, it needs to be implemented + + + + + CLOUDSTACK-377 + + + provide deployment config access to marvin's testcas + + + + + CLOUDSTACK-378 + + + mavenize marvin on maste + + + + + CLOUDSTACK-390 + + + Install Guide: Section 4.5.7 (Prepare the System VM Template): Links go to cloud.co + + + + + CLOUDSTACK-397 + + + Install Guide: Section 11.1 (Guest Traffic): Diagram is the wrong diagra + + + + + CLOUDSTACK-398 + + + Install Guide: Section 11.17.3 (Using VPN with Mac OSX): Not complete + + + + + CLOUDSTACK-404 + + + Update docs on the usage of cloud-setup-database + + + + + CLOUDSTACK-412 + + + Data truncation: Out of range value for column 'ram' at row + + + + + CLOUDSTACK-415 + + + restartNetwork call causes VM to be unreachable when Nicira based SDN is used + + + + + CLOUDSTACK-416 + + + XCP 1.6beta2 (61002c) - can't add a hos + + + + + CLOUDSTACK-417 + + + Handle password server securely to run on port 8080 on V + + + + + CLOUDSTACK-424 + + + Updated userdata not propagating to the VR + + + + + CLOUDSTACK-427 + + + Change hardcoded step number references to dynamic link + + + + + CLOUDSTACK-428 + + + Storage capacity shown in UI is incorrec + + + + + CLOUDSTACK-435 + + + Vmware network labels are ignored when creating a Zone using basic networkin + + + + + CLOUDSTACK-441 + + + Running mgmt server using jetty fails to start api serve + + + + + CLOUDSTACK-446 + + + "Host going to alert state, if you are adding already added host + + + + + CLOUDSTACK-448 + + + SSVM bootstrap failure on XenServer hosts with E3 CP + + + + + CLOUDSTACK-456 + + + License tag in SPEC isn't what RPM is expectin + + + + + CLOUDSTACK-459 + + + [Optional Public IP assignment for EIP with Basic Zone] Associate IP Checkbox in Create Network Offering Dialog is Displayed When Elastic LB is Selecte + + + + + CLOUDSTACK-462 + + + A few corrections to make to the 4.0.0 installation guid + + + + + CLOUDSTACK-464 + + + "Regression in AWSAPI docs, entire sections removed + + + + + CLOUDSTACK-465 + + + French language file quotes are dropping javascript syntax error + + + + + CLOUDSTACK-467 + + + Developer's Guide points to cloud.com for API referenc + + + + + CLOUDSTACK-479 + + + UpdateVirtualMachine api fails to propagate userdata to dom + + + + + CLOUDSTACK-481 + + + Installation Guide Doc Erro + + + + + CLOUDSTACK-493 + + + 2.2.x-3.0 DB upgrade support for Advance SG enabled network + + + + + CLOUDSTACK-499 + + + cloudmonkey CLI can't accept complex parameter + + + + + CLOUDSTACK-500 + + + Passwd-server iptables rules are dropped on domr on fresh start or on reboot. + + + + + CLOUDSTACK-501 + + + Apidocs and marvin does not know how to handle Autoscaling docs. + + + + + CLOUDSTACK-504 + + + Duplicate guest password scripts in codebase. + + + + + CLOUDSTACK-507 + + + fix api docs for listSSHKeyPair + + + + + CLOUDSTACK-508 + + + CLVM copies template to primary storage unnecessarily. + + + + + CLOUDSTACK-510 + + + Add button not visible when adding public IPs to physical network. + + + + + CLOUDSTACK-514 + + + Marvin and Cloudmonkey don't work when an API target uses https or an alternate path. + + + + + CLOUDSTACK-518 + + + API refactoring -- change @Parameter annotation and remove the @IdentityMapper annotation. + + + + + CLOUDSTACK-520 + + + Dependency jar names mismatch with install-non-oss.s + + + + + CLOUDSTACK-521 + + + Build will hung up when doing test for TestAgentShel + + + + + CLOUDSTACK-522 + + + Log requests in cloudmonkey's log file. + + + + + CLOUDSTACK-527 + + + List API performance optimization by using DB views and removing UUID conversion + + + + + CLOUDSTACK-534 + + + Failed to add hos + + + + + CLOUDSTACK-536 + + + remove citrix cloudpatform from 4.0 build - CloudStack is ASF project. + + + + + CLOUDSTACK-539 + + + Cropped Text in UI under Quick View. + + + + + CLOUDSTACK-552 + + + ]Quick view details for a volume displays scroll bar in place of name of the volume when the name of the volume has more no of characters. + + + + + CLOUDSTACK-553 + + + "SRX - When adding SRX device make "Public Network" - default to "untrusted" and "Private Network" - default to "trusted" as un-editable fields. + + + + + CLOUDSTACK-556 + + + Erratic window behavior in Quick View tooltip. + + + + + CLOUDSTACK-559 + + + source code import problem + + + + + CLOUDSTACK-560 + + + Usage server doesn't work in 4.0.0 due to missing db changes + + + + + CLOUDSTACK-572 + + + SG Enabled Advanced Zone - Not able to deploy a VM in an account specific shared network + + + + + CLOUDSTACK-573 + + + "NPE at ""com.cloud.network.NetworkManagerImpl.networkOfferingIsConfiguredForExternalNetworking(NetworkManagerImpl.java:4345)"" when create network from the network offering having NULL provider for the service + + + + + CLOUDSTACK-578 + + + The already deleted same hostname is not deleted from /etc/hosts of vRouter + + + + + CLOUDSTACK-584 + + + "typos in ""Apache_CloudStack-4.0.0-incubating-CloudStack_Nicira_NVP_Guide-en-US"" + + + + + CLOUDSTACK-590 + + + Incorrect Network Gateways Assigned to System VM + + + + + CLOUDSTACK-592 + + + "API bloat, unknown apis cmd classes + + + + + CLOUDSTACK-593 + + + "2 guest network, auto create vlan error + + + + + CLOUDSTACK-596 + + + DeployVM command takes a lot of time to return job id. + + + + + CLOUDSTACK-599 + + + DhcpEntryCommand fails on Router VM on CS4.0 and vSphere5 with Advanced Network Zone. + + + + + CLOUDSTACK-600 + + + When rebooting KVM local storage VM host, libvirt definitions deleted + + + + + CLOUDSTACK-605 + + + Host physical CPU is incorrectly calculated for Vmware host + + + + + CLOUDSTACK-606 + + + Starting VM fails with 'ConcurrentOperationException' in a clustered MS scenari + + + + + CLOUDSTACK-614 + + + "ListTemplates API is not returning ""Enable SSH Key"" attribute for any given template + + + + + CLOUDSTACK-617 + + + Unable to edit a Sub domai + + + + + CLOUDSTACK-639 + + + API Refactoring: Adapters for AC + + + + + CLOUDSTACK-648 + + + The normal users could change their own login password. + + + + + CLOUDSTACK-660 + + + Network Traffic Labels are not functional in Marvin + + + + + CLOUDSTACK-683 + + + Image Is Missing in the Accessing VM Section + + + + + CLOUDSTACK-689 + + + RVR: Stop pending flag is not cleared when user start the disconnected router from another hos + + + + + CLOUDSTACK-691 + + + A warning dialog box shows after reloading the welcome page. + + + + + CLOUDSTACK-693 + + + Adding a VPC virtual router to a NiciraNVP enabled network fails. + + + + + CLOUDSTACK-694 + + + "Create a new VPC network offering with "connectivity" option needed for SDN networking) is not allowed / VPC support for SDN networks + + + + + CLOUDSTACK-717 + + + cloudmonkey fails to parse/print response. + + + + + CLOUDSTACK-720 + + + Fail to load a png image when accessing the web console. + + + + + CLOUDSTACK-721 + + + Bytes sent/received in user statistics is empty (CloudStack 4.0) + + + + + CLOUDSTACK-725 + + + UI: Error when the Egress rules tab is selected for a network. + + + + + CLOUDSTACK-734 + + + api_refactoring: CreateAccountCmd fails to send response due to NPE in service layer + + + + + CLOUDSTACK-735 + + + Integration smoke tests: Fix expunge vm test on api_refactoring + + + + + CLOUDSTACK-736 + + + Integration smoke tests: Fix check for vm name for the deployvm smoke test. + + + + + CLOUDSTACK-793 + + + "Create cloudmonkey-helper, a plugin that helps autodiscover and sync api info via an api over some endpoint + + + + + CLOUDSTACK-798 + + + Move usage related cmd classes from cloud-server to cloud-api + + + + + CLOUDSTACK-799 + + + [Load Test] Check router statistics falls behind in gathering stats by more than 2 times the set value + + + + + CLOUDSTACK-819 + + + Create Account/User API logging password in access log + + + + + CLOUDSTACK-863 + + + Non-printable characters (ASCII control character) such as %00 or %0025 are getting stored in raw/non encoded form in the database + + + + + CLOUDSTACK-870 + + + Client UI: Wrong character encoding for some language + + + + + CLOUDSTACK-928 + + + [Simulator] Latency for Agent Commands - change unit of wait from seconds to millisecond + + + + + CLOUDSTACK-938 + + + s2s VPN trouble + + + + + CLOUDSTACK-959 + + + Missing sub-sections in document section System Service Offering + + + + + CLOUDSTACK-968 + + + marvin: vlan should be an attribute of the physical_network and not the zon + + + + + CLOUDSTACK-977 + + + Document how to use openvswitch with KVM hypervisor + + + + + CLOUDSTACK-978 + + + TypeError: instance.displayname is undefined while adding VM's to the LB rule + + + + + CLOUDSTACK-985 + + + Different MAC address for RvR caused issue in short term network outrag + + + + + CLOUDSTACK-987 + + + Sections missing in Working With Snapshot + + + + + CLOUDSTACK-993 + + + "admin"" user is not getting created when management server is started. + + + + + CLOUDSTACK-995 + + + Not able to add the KVM host + + + + + CLOUDSTACK-1002 + + + Not able to start VM + + + + + CLOUDSTACK-1006 + + + need to disable service libvirt-guests in CentOS packaging RPMs, or in installation docs + + + + + CLOUDSTACK-1008 + + + "Egress"" tab should not be presented in the UI for Shared Networks + + + + + CLOUDSTACK-1010 + + + Host count and Secondary storage count always shows 1 in UI + + + + + CLOUDSTACK-1011 + + + KVM host getting disconnected in cluster environment + + + + + CLOUDSTACK-1013 + + + running cloudstack overwrites default public/private ssh key + + + + + CLOUDSTACK-1014 + + + Merge ManagementServer and ManagementServerEx + + + + + CLOUDSTACK-1016 + + + Not able to deploy VM + + + + + CLOUDSTACK-1021 + + + the vlan is not creat to right nic. when i creat multi guest network + + + + + CLOUDSTACK-1024 + + + Regression: Unable to add Xenserver host with latest build. + + + + + CLOUDSTACK-1027 + + + "Update SSL certificate" button should properly reflect its functionality + + + + + CLOUDSTACK-1029 + + + Enter the token to specified project is malfunctioned + + + + + CLOUDSTACK-1037 + + + "Make cloudmonkey awesome-er: Online help docs and api discovery, better colored output, parameter value autocompletion + + + + + CLOUDSTACK-1050 + + + No Documentation on Adding a Load Balancer Rule + + + + + CLOUDSTACK-1051 + + + API dispatcher unable to find objectVO corresponding to DeleteTemplatecm + + + + + CLOUDSTACK-1055 + + + "The overlay still exists when the ""Recurring Snapshots"" dialog is canceled by pressing esc key. + + + + + CLOUDSTACK-1056 + + + S3 secondary storage fails to upload systemvm template due to KVMHA director + + + + + CLOUDSTACK-1057 + + + regression of changeServiceForVirtualMachine API - fails to find service offering by serviceOfferingId parameter + + + + + CLOUDSTACK-1063 + + + "SG Enabled Advanced Zone - "Add Guest Networks" - When user tries to add a guest Network with scope as "Account" he should NOT be presented with ""Offering for shared security group enabled"" + + + + + CLOUDSTACK-1064 + + + A type error occurs when trying to add account/register template... + + + + + CLOUDSTACK-1068 + + + Names in VR list is useles + + + + + CLOUDSTACK-1070 + + + javelin: NPE on executing registerIso AP + + + + + CLOUDSTACK-1071 + + + Netscaler element is not getting loaded as part of LoadBalancing Service Providers + + + + + CLOUDSTACK-1078 + + + Not able to start System Vms on Rhel 6.3 KVM hos + + + + + CLOUDSTACK-1079 + + + Deploying AWSAPI with mvn -pl :cloud-awsapi jetty:run fail + + + + + CLOUDSTACK-1082 + + + UI doesn't throw any error message when trying to delete ip range from a network that is in use. + + + + + CLOUDSTACK-1083 + + + listUsageRecords api: removed project results in NP + + + + + CLOUDSTACK-1087 + + + Update the Developer Guide for ASFCS 4.1 Releas + + + + + CLOUDSTACK-1088 + + + EnableStaticNat error will clear the data in databas + + + + + CLOUDSTACK-1094 + + + Ipv6 - hostname/hostname --fqdn does not return the name of the VM. But i am able to reach the Vm using their names + + + + + CLOUDSTACK-1095 + + + Ipv6 - dhclient command needs to be run manually on the Vms to get the Ipv6 address + + + + + CLOUDSTACK-1100 + + + Expunge thread is not kicked off based on global configuration if the global setting is less than 60 second + + + + + CLOUDSTACK-1103 + + + "IpV6 - listNetwork() command does not retrun gateway,netmask,cidr + + + + + CLOUDSTACK-1104 + + + Ipv6 - listVlanIpRanges() returns error 530 + + + + + CLOUDSTACK-1105 + + + "IpV6 - listVirtualMachines() does not return netmask, gateway,ipaddress. + + + + + CLOUDSTACK-1107 + + + Ipv6 - Unable to extend Ip range for a Ipv6 network using craeteVlanIpRange() command - Error code 530 returned + + + + + CLOUDSTACK-1108 + + + Ipv6 - Not able to restart Networks + + + + + CLOUDSTACK-1109 + + + "Ipv6 - Unable to expunge User Vms that are ""Destroyed"". + + + + + CLOUDSTACK-1111 + + + Ipv6 - listRouters() does not return guestipaddress + + + + + CLOUDSTACK-1112 + + + "Errors in ""Prepare the System VM Template"" + + + + + CLOUDSTACK-1113 + + + "Ipv6 - Not able to deploy a new VM in this network because of ""Unable to allocate Unique Ipv6 address"" + + + + + CLOUDSTACK-1114 + + + unable to execute listegressfirewallrules API due invalid value i + + + + + CLOUDSTACK-1115 + + + In multiple shared network unable to login with default nic - KV + + + + + CLOUDSTACK-1123 + + + ListStoragePools API broken by refacto + + + + + CLOUDSTACK-1138 + + + "Providing invalid values for gateway, netmask etc in the zoneWizard blocks the VLAN container to load, throwing an error + + + + + CLOUDSTACK-1139 + + + "After the Vm is "Expunged" we see the entry still being present in the router in /etc/dhcphosts.txt + + + + + CLOUDSTACK-1141 + + + "Ipv6 - After network restart (and reboot router), we do not see the existing vms dnsentries not being programmed in the router. + + + + + CLOUDSTACK-1152 + + + Missing tag in host-add.xm + + + + + CLOUDSTACK-1153 + + + "Ipv6 - Vm deployment fails with "n must be positive" error. + + + + + CLOUDSTACK-1154 + + + Account/Users related API failed due to RegionService inject exception. + + + + + CLOUDSTACK-1157 + + + No API Documentation on Listing Custom User Templates Using CS4 API + + + + + CLOUDSTACK-1160 + + + References to version=3.0.3|4|5|6 in API classes needs to be removed. + + + + + CLOUDSTACK-1161 + + + Differences between 4.1 and master in ongoing-config-of-external-firewalls-lb.xml + + + + + CLOUDSTACK-1163 + + + Failed with NPE while creating firewall rule + + + + + CLOUDSTACK-1168 + + + Create firewall rule broke + + + + + CLOUDSTACK-1173 + + + ConsoleProxyResource instantiation exception. + + + + + CLOUDSTACK-1174 + + + Snapshots related SQL error. + + + + + CLOUDSTACK-1176 + + + Issue with snapshots(create/list + + + + + CLOUDSTACK-1181 + + + mvn deploy db failing with NP + + + + + CLOUDSTACK-1190 + + + Make APIChecker interface throw a single sensible exception. + + + + + CLOUDSTACK-1200 + + + "Unknown column 'vm_instance.disk_offering_id' in table vm_instance, db exception shown in MS log + + + + + CLOUDSTACK-1201 + + + "Failed to create ssh key for user "cloud" /var/lib/cloud/management/.ssh/id_rsa and failed to start management server + + + + + CLOUDSTACK-1202 + + + Fail to install KVM cloud-agent. + + + + + CLOUDSTACK-1203 + + + Fail to create advance zone with SG enabled when UI allows SG enabled option. + + + + + CLOUDSTACK-1204 + + + Fail to create advance zone due to fail to add host + + + + + CLOUDSTACK-1205 + + + Ipv6 - Ubuntu 12.10 guest Vms loses default route (after it expiration time ~ 30 mts) when ipv6.autoconfig parameters are disabled except for net.ipv6.conf.lo.autoconf which is enabled. + + + + + CLOUDSTACK-1206 + + + Failure in Copy of System template + + + + + CLOUDSTACK-1210 + + + Make all pluggable services return list of api cmd classes + + + + + CLOUDSTACK-1216 + + + UUID is null for admin and failed to register user key with 4.0 + + + + + CLOUDSTACK-1218 + + + "IPv6: Shared Network - After network restart with clean option, router is assigned a different address. Name resolution for the existing guest Vms in the network fails. + + + + + CLOUDSTACK-1219 + + + Ipv6 - Provide better error messages when deploying a Vm with Ip an address that is outside the network's ip range / if the ip address already is assigned to another Vm + + + + + CLOUDSTACK-1220 + + + Ipv6 - Better error message when deploy Vm fails to get a free Ip address + + + + + CLOUDSTACK-1222 + + + API rate limit configs: removed double quote in upgrade script + + + + + CLOUDSTACK-1223 + + + Exception while starting jetty server: org.springframework.beans.factory.BeanCreationException Error creating bean with name 'apiServer' + + + + + CLOUDSTACK-1224 + + + Volume snapshot creation failing + + + + + CLOUDSTACK-1226 + + + Error while running Cloudstack-setup-database + + + + + CLOUDSTACK-1228 + + + Unable to Create System Vm's in the VMware Hypervisor setup + + + + + CLOUDSTACK-1229 + + + Incorrect SQL syntax to insert api limit related configuration items in upgrade path script. + + + + + CLOUDSTACK-1231 + + + cloud-install-sys-tmplt failed due to missing path + + + + + CLOUDSTACK-1232 + + + "Ipv6 - Guest Vms are not able to get Ipaddress when executing dhclient command when using ""/96"" network. + + + + + CLOUDSTACK-1233 + + + Veewee configuration files are inappropriately identified as ASLv2 licensed file + + + + + CLOUDSTACK-1234 + + + Unable to start KVM agent with 4.1 build. + + + + + CLOUDSTACK-1237 + + + "Register Template fails with ""Cannot find template adapter for XenServer"" + + + + + CLOUDSTACK-1239 + + + Unable to registerISO :unhandled exception executing api command: registerIs + + + + + CLOUDSTACK-1240 + + + Unable to registerTemplate : Cannot find template adapter for XenServer. + + + + + CLOUDSTACK-1241 + + + Network apply rules logic is broken. + + + + + CLOUDSTACK-1242 + + + [F5-SRX-InlineMode] Failed to create LB rule with F5-SRX inlinemode deployemen + + + + + CLOUDSTACK-1243 + + + Failed to cleanup account :java.lang.NullPointerException + + + + + CLOUDSTACK-1244 + + + fail to push sysmvm.iso onto xen host + + + + + CLOUDSTACK-1246 + + + "[ ALU beta CS 4.1 build2] ""Guest network"" missing in Add Zone wizard ( step 3, Setup Network \ Physical Network) + + + + + CLOUDSTACK-1251 + + + Baremetal zone doesn't need primary/secondary storage in UI wizard. + + + + + CLOUDSTACK-1252 + + + Failed to download default template in VMware. + + + + + CLOUDSTACK-1260 + + + Failed to register template: Unable to find template adapter + + + + + CLOUDSTACK-1261 + + + Cannot find template adapter for XenServer. + + + + + CLOUDSTACK-1262 + + + "Failed to Prepare Secondary Storage in VMware, + + + + + CLOUDSTACK-1265 + + + logrotate dnsmasq configuration is wrong + + + + + CLOUDSTACK-1267 + + + KVM's cloudstack-agent service doesn't log (log4j) + + + + + CLOUDSTACK-1269 + + + Failed to start CPVM java.lang.NullPointerException Unable to start SSVM + + + + + CLOUDSTACK-1272 + + + Autoscale: createAutoScaleVmProfile fails due to unable to retrieve Service Offering ip + + + + + CLOUDSTACK-1274 + + + UpdateNetworkCmd throws NP + + + + + CLOUDSTACK-1276 + + + Remove autoscanning for 4.1 + + + + + CLOUDSTACK-1277 + + + ApiResponseHelper.createUserVmResponse failed to populate password field set from UserVm object + + + + + CLOUDSTACK-1278 + + + Improper permissions on injectkeys.s + + + + + CLOUDSTACK-1288 + + + [F5-SRX-InlineMode] classCastException during network restart with cleanup option true + + + + + CLOUDSTACK-1289 + + + [F5-SRX-InlineMode] Usage stats are not generated for Juniper SRX Firewall in inlinemod + + + + + CLOUDSTACK-1290 + + + listNetoworks API takes too long to respond + + + + + CLOUDSTACK-1292 + + + "[F5-SRX-InlineMode] Update network from SRX,F5 as service provideds to VR as service provider does not delete firewall rules from SRX + + + + + CLOUDSTACK-1295 + + + NPE in usage parsers due to missing @Component inject + + + + + CLOUDSTACK-1299 + + + Errors in 4.5.5 section of installation guide + + + + + CLOUDSTACK-1300 + + + section in wrong order in installation guide + + + + + CLOUDSTACK-1303 + + + Ipv6 - java.lang.NullPointerException when executing listnetworks() and deployVirtualMachine() after extending the Ipv4 range of a dual stack network + + + + + CLOUDSTACK-1307 + + + Noticed NPE when we put host in maintenance mode in clustered management setup + + + + + CLOUDSTACK-1310 + + + ASF-build-master-nonoss-rhel63 - create advance zone FAIL - CreatePhysicalNetworkCmd FAIL - MySQLIntegrityConstraintViolationException: Duplicate entry '200-Public' for key 'physical_network_id + + + + + CLOUDSTACK-1312 + + + "Fix rolling upgrades from 4.0 to 4.1 in 4.1 release, fix db schemas to be same as 4.0 + + + + + CLOUDSTACK-1313 + + + Working with Volumes Section Is Missing + + + + + CLOUDSTACK-1315 + + + [F5-SRX-InlineMode] Network implement failed with Run time Exception during network upgrade from VR to SRX-F + + + + + CLOUDSTACK-1319 + + + createCustomerVpnGateway response gives TypeError: json.createvpncustomergatewayresponse is undefined + + + + + CLOUDSTACK-1320 + + + Routers naming convention is changed to hostname. + + + + + CLOUDSTACK-1321 + + + [Site-to-Site VPN] No events are generated in case of status change in site to site vpn connection + + + + + CLOUDSTACK-1326 + + + KVM - Failed to start cloud agent from SSVM + + + + + CLOUDSTACK-1328 + + + console view unable to connect - CPVM SSVM guest VM + + + + + CLOUDSTACK-1329 + + + "API listRouters response returns hostname instead of Virtual Routers, UI displays host entry for each VR + + + + + CLOUDSTACK-1330 + + + ec2-run-instances - When -n option is used to deploy multiple Vms API returns error even though few of the Vms have been deployed successfully + + + + + CLOUDSTACK-1331 + + + Upgrade fails for a 2.2.14 Zone having multiple guest networks using network_tags and Public Vlan + + + + + CLOUDSTACK-1332 + + + IPV6 - Router and guest Vms should be able to use an IPV6 address for external DNS entry + + + + + CLOUDSTACK-1334 + + + vmware.root.disk.controller doesn't work + + + + + CLOUDSTACK-1337 + + + Zone to zone template/ISO copy fails and template/ISO download also fail + + + + + CLOUDSTACK-1338 + + + Deploy VM failed using IS + + + + + CLOUDSTACK-1339 + + + ASF 4.1: Management server becomes unresponsive + + + + + CLOUDSTACK-1341 + + + URL for the KEYs file is wrong in the installation guide + + + + + CLOUDSTACK-1342 + + + Document installation and usage of cloudmonkey for 4.1 docs + + + + + CLOUDSTACK-1343 + + + Porting Baremetal related UI changes to ACS + + + + + CLOUDSTACK-1344 + + + Typo in use.external.dns setting description + + + + + CLOUDSTACK-1345 + + + BigSwitch plugin introduces 'VNS' isolation in UI without backend implementation + + + + + CLOUDSTACK-1346 + + + "Check to see if external devices are used in the network, is hardcoded for specific devices + + + + + CLOUDSTACK-1347 + + + "Not able to delete network. Error - ""Unable to insert queue item into database, DB is full?"" + + + + + CLOUDSTACK-1348 + + + API/UI: zoneObj is undefined. + + + + + CLOUDSTACK-1349 + + + "VPC network Adding Network ACls, PF rules - Unable to insert queue item into database, DB is full? PF rules and NW Acls in Add state in DB + + + + + CLOUDSTACK-1350 + + + Management server Stop and start causes previously downloaded ISOs and templates to redownload & reinstall. + + + + + CLOUDSTACK-1353 + + + KVM 6.3 snapshot Scheduling snapshot failed due to java.lang.NullPointerExceptio + + + + + CLOUDSTACK-1357 + + + "Autoscale: Provisioned VMs from Netscaler not being added to lb vserver, provserver fails with provserver_err_asynctaskpoll + + + + + CLOUDSTACK-1360 + + + The clusterid field of the createStoragePool API command should be documented as required. + + + + + CLOUDSTACK-1367 + + + NPE noticed in logs while AgentMonitor is monitoring the host ping interval + + + + + CLOUDSTACK-1368 + + + Shared network - Not able to delete network because of java.lang.NullPointerException + + + + + CLOUDSTACK-1369 + + + "Ipv6 - In dual Stack network, guest VM does not have the Ipv6 address of the router programmed in /etc/resolv.conf for DNS resolution. + + + + + CLOUDSTACK-1370 + + + DeployVM Fail - VPC or non-VPC network + + + + + CLOUDSTACK-1375 + + + deploydb failing with acs master + + + + + CLOUDSTACK-1376 + + + Unable to migrate VM due to internal error process exited while connecting to monitor + + + + + CLOUDSTACK-1377 + + + HA fail - when host is shutdown, VMs and SSVMs are not failover to second host in cluster. + + + + + CLOUDSTACK-1382 + + + vm deploy fails with Error "cannot find DeployPlannerSelector for vm" + + + + + CLOUDSTACK-1383 + + + Deploying basic zone on 4.1 fails in NP + + + + + CLOUDSTACK-1386 + + + BASIC zone SSVM fail to start due to exception + + + + + CLOUDSTACK-1388 + + + UI - ListUsers doesnt display any User except the Default Root Admin User + + + + + CLOUDSTACK-1391 + + + EventBus is not getting injected after javelin merge + + + + + CLOUDSTACK-1394 + + + [F5-SRX-InlineMode] Failure in static nat configuration on SRX does not result in LB configuration error in CS during LB rule configuratio + + + + + CLOUDSTACK-1397 + + + Static Nat configuration is failing with NP + + + + + CLOUDSTACK-1399 + + + Unhandled exception executing api command: stopVirtualMachine + + + + + CLOUDSTACK-1402 + + + listRouters API response doesn't return linklocal IP and public IP detail + + + + + CLOUDSTACK-1403 + + + Storage and console-proxy related error + + + + + CLOUDSTACK-1411 + + + Issues with VMWare Hypervisor host_ids not updated when ESX(i) crashes in instance table + + + + + CLOUDSTACK-1414 + + + Redundant router: BACKUP switch cancelled due to lock timeout after a glitch in network. + + + + + CLOUDSTACK-1417 + + + When invalid values are passed to createNetwork(), error message does not indicate the parameter name that has invalid values. + + + + + CLOUDSTACK-1418 + + + As regular user, we are not allowed to deploy VM on a shared network. + + + + + CLOUDSTACK-1419 + + + Apache-ify and apply trademark logos in the UI + + + + + CLOUDSTACK-1420 + + + Ensure trademarks are properly attributed in publican brand + + + + + CLOUDSTACK-1423 + + + Unable to launch UI [HTTP Status 404]. + + + + + CLOUDSTACK-1425 + + + unhandled exception executing api command: migrateVirtualMachine & recoverVirtualMachine + + + + + CLOUDSTACK-1427 + + + Failed to delete Guestnetwork which has LB with Netscaler + + + + + CLOUDSTACK-1428 + + + [UI] Instance which are created without display name are not visible when added to LB + + + + + CLOUDSTACK-1429 + + + single account is unable to use same vnet across multiple physical network + + + + + CLOUDSTACK-1436 + + + 4.1 management server fails to start from RPM build artifact + + + + + CLOUDSTACK-1443 + + + As domain admin we are allowed to create shared network + + + + + CLOUDSTACK-1446 + + + [UI]VPC Router type should be of type vpc and not syste + + + + + CLOUDSTACK-1447 + + + [UI]Persistent Status is not displayed for VPC Tier + + + + + CLOUDSTACK-1449 + + + listAccounts and listProjectAccounts API lists all the users not account-specific users for each account returne + + + + + CLOUDSTACK-1451 + + + Getting EntityExistsException while creating more than one project in CS 4. + + + + + CLOUDSTACK-1452 + + + Public IP's are assigned to private interface with VPC Restart [PF/LB rules are not functional + + + + + CLOUDSTACK-1461 + + + "Ipv6 - From a Vm that that is part of 2 networks, non default network router's details should not get programmed in the DNS entries of the guest VM. + + + + + CLOUDSTACK-1463 + + + IPV6 - Ubuntu 12.10 - Multiple Nic - IPV6 address is assigned automatically for 1 nic only. Need to do a manual dhclient request to get the ipv6 for other nic + + + + + CLOUDSTACK-1464 + + + "IPV6 - Multi nic - Ubuntu 1210 -When Vm is stopped and started/ rebooted, i get multiple global IPV6 addresses being allocated for one of the nics. + + + + + CLOUDSTACK-1465 + + + List Zones returns null under create instance when logged is as use + + + + + CLOUDSTACK-1467 + + + Failed to create Volume for the System Vm's + + + + + CLOUDSTACK-1469 + + + kvm agent: agent service fails to start u + + + + + CLOUDSTACK-1470 + + + unhandled exception executing api command: deployVirtualMachin + + + + + CLOUDSTACK-1472 + + + AssignVirtualMachine API with wrong Virtual Instance ID failed with NP + + + + + CLOUDSTACK-1473 + + + deleteDomain is failing with NP + + + + + CLOUDSTACK-1481 + + + "IPV6 - When Vm is part of 1 dual network and 1 ipv6 network, name resolution using fqdn fails for the ipv6 network. + + + + + CLOUDSTACK-1482 + + + IPV6 - We are not allowed to create a shared IPV6 network with a VLAN which already is associated with a IPV4 network + + + + + CLOUDSTACK-1484 + + + "API Throttling : api.throttling.enabled, Global setting missing + + + + + CLOUDSTACK-1485 + + + Add Baremetal Provider back to 4.1 branc + + + + + CLOUDSTACK-1487 + + + cloudstack-setup-agent fails to set private.network.device on KVM host ad + + + + + CLOUDSTACK-1488 + + + "Ipv6 - When Vm is deployed as part of multiple networks, one of the IPV6 address assigned to guest VM is lost. + + + + + CLOUDSTACK-1490 + + + 4.1 deb management fails to start due to tomcat dep problem + + + + + CLOUDSTACK-1496 + + + List API Performance: listAccounts failing with OOME for high values of pagesize (>1000 + + + + + CLOUDSTACK-1499 + + + ListAPI Performance for few APIs not as good as it was before API optimizatio + + + + + CLOUDSTACK-1503 + + + listHypervisor API not getting fired when logged in as Use + + + + + CLOUDSTACK-1505 + + + Unknown column 'domain.region_id' in 'field list + + + + + CLOUDSTACK-1509 + + + Failed to implement network elements and resources while provisioning for persistent network(createVlanIpRange to an account + + + + + CLOUDSTACK-1511 + + + [UI] Instances NIC details does not have Network Nam + + + + + CLOUDSTACK-1512 + + + [UI] Wrong message[message.configure.all.traffic.types] when trying to create zone with mulitple physical networks without providing the traffic labe + + + + + CLOUDSTACK-1515 + + + None of the cloudstack packges are marked for upgrade when tried to upgrade from.4.0/4.0.1 to 4. + + + + + CLOUDSTACK-1516 + + + Create documentation in languages that have translations availabl + + + + + CLOUDSTACK-1517 + + + Check UI in languages availabl + + + + + CLOUDSTACK-1521 + + + Redundant router: Services are not stopped when switch to BACKUP stat + + + + + CLOUDSTACK-1526 + + + Template registration fails in the VMware Setup + + + + + CLOUDSTACK-1531 + + + vmware create volume from snapshot will missing dat + + + + + CLOUDSTACK-1537 + + + Restart network with clean up set to true causes Autoscaled LB rule to get mangled and unusabl + + + + + CLOUDSTACK-1541 + + + NPE while deleting snapshot :Unexpected exception while executing org.apache.cloudstack.api.command.user.snapshot.DeleteSnapshotCm + + + + + CLOUDSTACK-1542 + + + unhandled exception while creating projec + + + + + CLOUDSTACK-1544 + + + The description and the response format for the deleteUser command are incorrec + + + + + CLOUDSTACK-1550 + + + createaccountresponse returns more than the user you requested for creation + + + + + CLOUDSTACK-1553 + + + AWS Regions-Not able to list accounts from the 2nd region after user/account/domain details have been manually synced up from first region + + + + + CLOUDSTACK-1555 + + + "AWS Regions - userapikey and usersecretkey parameters are not returned in the response of addRegion, updateRegion listRegion api calls.. + + + + + CLOUDSTACK-1557 + + + EC2 REST API : cloudbridge database is missing on the CloudStack Installatio + + + + + CLOUDSTACK-1562 + + + Replace the short-cut solution of supportting @DB with the formal on + + + + + CLOUDSTACK-1565 + + + "Used Master Branch System VM Template: Default Route on the System VMs (SSVM,CPVM and VR) is missing + + + + + CLOUDSTACK-1566 + + + Baremetal API addBaremetalPxePingServer fail to add PXE PING server to deployment causing create instance with PING style image to fai + + + + + CLOUDSTACK-1569 + + + "AWS Regions - Not able to Edit domain/account/user from a region that is not the owner region.""The content of elements must consist of well-formed character data or markup."" - error message presented to the user. + + + + + CLOUDSTACK-1571 + + + "AWS Regions - When deleting domain/account/user from a region that is not the owner, the request is not being forwarded to the owner region. + + + + + CLOUDSTACK-1574 + + + updateResourceCount API is failed saying to specify valida resource type even after parsing the valid resource typ + + + + + CLOUDSTACK-1583 + + + AWS Regions - RabbitMQ Server did not recieve any event notification during account creation + + + + + CLOUDSTACK-1587 + + + "Basic zone - CPVM fail to go to running state, Exception while trying to start secondary storage vm + + + + + CLOUDSTACK-1588 + + + "AWS Regions - When registerUserKeys() is called for a user from a region that is not the owner, it is handled by this region. + + + + + CLOUDSTACK-1600 + + + Typo in dpkg-buildpackage comman + + + + + CLOUDSTACK-1604 + + + "deploy VM failed when global setting ""vm.allocation.algorithm"" is set to ""userdispersing"" + + + + + CLOUDSTACK-1615 + + + "VMware Cluster discovery fails with if ESXi version is 5.0 Update 1, build 721882 + + + + + CLOUDSTACK-1620 + + + Cannot provision CentOS 6 VMs on XenServer 6. + + + + + CLOUDSTACK-1621 + + + listProjectInvitations fails with NPE for valid request + + + + + CLOUDSTACK-1624 + + + API is not returning response in details:UI is also not returning any outpu + + + + + CLOUDSTACK-1625 + + + NPE with updateResourceCount when && is passed thru AP + + + + + CLOUDSTACK-1630 + + + 4.0.x cloud-aws-api not properly obsoleted + + + + + CLOUDSTACK-1631 + + + 4.1 RPM packaging broke + + + + + CLOUDSTACK-1636 + + + AWS Regions - Remove the concept of having an owner region for domain/account/user objects + + + + + CLOUDSTACK-1642 + + + Add support CentOS 6. + + + + + CLOUDSTACK-1648 + + + Unable to add KVM hos + + + + + CLOUDSTACK-1649 + + + vmware vm os type erro + + + + + CLOUDSTACK-1651 + + + agent scripts still pointing to /var/log/cloud + + + + + CLOUDSTACK-1656 + + + NicResponses in a UserVmResponse are not preseving the natural order + + + + + CLOUDSTACK-1663 + + + AWS Regions - Events - There are no events being generated when a new domain is added/edited + + + + + CLOUDSTACK-1664 + + + Action Events are not logged due to spring change + + + + + CLOUDSTACK-1665 + + + AWS Regions - Events - There are no events being generated when a new user is added/edited/enabled/deleted/password changes/api & secret keys are generated + + + + + CLOUDSTACK-1666 + + + KVM VPC NetworkUsage doesnot wor + + + + + CLOUDSTACK-1668 + + + IP conflict in VPC tie + + + + + CLOUDSTACK-1671 + + + AWS Regions - Events - Domain Delete event does not include the UUID of the domain that was deleted + + + + + CLOUDSTACK-1674 + + + AWS Regions - Events - Account Deletion event does not include the UUID of the account deleted + + + + + CLOUDSTACK-1681 + + + Upgrade instructions mention incorrect name and description of systemvm-vmware template in registering template section + + + + + CLOUDSTACK-1684 + + + "api.throttling.enabled configuration setting should be set to ""false"" in Config.java + + + + + CLOUDSTACK-1688 + + + AWS Regions - Domain admin user is not able to use getUser() command to fetch user details + + + + + CLOUDSTACK-1690 + + + NPE from API server when starting mgmt serve + + + + + CLOUDSTACK-1694 + + + Issues to start/access Management Server after upgrade from 4.0 to 4. + + + + + CLOUDSTACK-1697 + + + Six DB tables are not available with upgraded setup(4.0 to 4.1) when compare to 4.1 newly installatio + + + + + CLOUDSTACK-1706 + + + "Failed to deploy VM with error ""cannot find DeployPlannerSelector"" + + + + + CLOUDSTACK-1709 + + + "AWS Regions - As part of adding a new region, project related entries should not be synced from accounts table. + + + + + CLOUDSTACK-1710 + + + "AWS Regions - As part of adding a new region,default_zone_id column for the account entries should not be synced. + + + + + CLOUDSTACK-1711 + + + AWS Regions - Include all the details of the API call made in the Events payload when changes in Admin/Account/User objects are made. + + + + + CLOUDSTACK-1713 + + + EC2 REST API: AWS API Installation Problem + + + + + CLOUDSTACK-1714 + + + Doc section has wrong title: Setting Zone VLAN and Running VM Maximum + + + + + CLOUDSTACK-1715 + + + "Missing ""host"" config setting in docs on management server load balancing + + + + + CLOUDSTACK-1716 + + + "AWS Regions - listRegions(),removeRegions(),updateRegions() should accept UUID value instead of id. + + + + + CLOUDSTACK-1718 + + + AWS Regions - removeRegion() response returns updateregionresponse + + + + + CLOUDSTACK-1719 + + + EC2 REST API: AWS APIs are not getting translated on the CloudStack Management Serve + + + + + CLOUDSTACK-1720 + + + Have an upgrade path from 4.0.x to 4.1 and 4.0.x to 4.2. + + + + + CLOUDSTACK-1729 + + + Ensure adapter execution order in runtim + + + + + CLOUDSTACK-1733 + + + [ACS41][UI] Add guest network is missing ip range fields and missing network offering + + + + + CLOUDSTACK-1736 + + + Ubuntu 12.04 cloud-setup-management Failed to configure CloudStack Management Serve + + + + + CLOUDSTACK-1738 + + + StatsCollector is not runnin + + + + + CLOUDSTACK-1740 + + + Failed to view consol + + + + + CLOUDSTACK-1746 + + + Cloudstack Usage Server won't star + + + + + CLOUDSTACK-1747 + + + "mvn deploydb only creates 4.0 DB, not 4.1 + + + + + CLOUDSTACK-1750 + + + injectkeys script fails on OSX because cp does not have a -b option (backup of destination file + + + + + CLOUDSTACK-1761 + + + Available local storage disk capacity incorrectly reported in KVM to manager + + + + + CLOUDSTACK-1764 + + + ListTemplateCommand failed with java.lang.NumberFormatException and failed to create default template. + + + + + CLOUDSTACK-1772 + + + the change in vnc listening port will cause live migration doesn't work. + + + + + CLOUDSTACK-1773 + + + Disable baremetal functionality + + + + + CLOUDSTACK-1776 + + + NPE on listSecondaryStorageHostsInAllZones in Upgraded setup from 4.0 to 4.1.0 + + + + + CLOUDSTACK-1785 + + + Redundant Router test cases failing during automation run. + + + + + CLOUDSTACK-1789 + + + Unable to download templates to Primary Storage if a host is in maintenance. + + + + + CLOUDSTACK-1791 + + + Volumes with storage tags can't be attached. + + + + + CLOUDSTACK-1792 + + + "AWS Regions - RuntimeException while executing listAccounts(), when the encryption keys are set to different values between regions. + + + + + CLOUDSTACK-1793 + + + L10n docs don't build in chinese, portuguese and japanese + + + + + CLOUDSTACK-1795 + + + Customize AOP to fully support legacy CloudStack @DB and @ActionEvent semantics. + + + + + CLOUDSTACK-1796 + + + Japanese docs don't build. + + + + + CLOUDSTACK-1802 + + + Upgrade 4.0 -> 4.1 - Not able to start management server becasue of missing /etc/cloudstack/management/tomcat6.conf file + + + + + CLOUDSTACK-1804 + + + Upgrade 4.0 -> 4.1 - DB upgrade fails + + + + + CLOUDSTACK-1805 + + + com.mysql.jdbc.exceptions.jdbc4.CommunicationsException seen after long time of inactivity resulting in not being able to log in to the management server + + + + + CLOUDSTACK-1810 + + + listTemplate API with templatefilter=featured|community is not returning any lists + + + + + CLOUDSTACK-1811 + + + "Upgrade 4.0->4.1 - When upgrade scripts fail, component loading continues and management server starts. + + + + + CLOUDSTACK-1812 + + + create physical network fails while creating basic zon + + + + + CLOUDSTACK-1825 + + + EC2 REST API: AWS APIs fail to execute due to BeanCreationException: Error creating bean with name 'SAclDaoImpl + + + + + CLOUDSTACK-1826 + + + "Storage migration not working, seemingly due to uuid vs id + + + + + CLOUDSTACK-1827 + + + Redundant router - When VR Master was stopped failover to VR Backup did not occur. + + + + + CLOUDSTACK-1834 + + + "Events are not generated for registerUserKeys(), Enabling account and Editing account. + + + + + CLOUDSTACK-1836 + + + License header failures for ja-JP .po translation file + + + + + CLOUDSTACK-1839 + + + Upgrade 4.0 -> 4.1 - Upgraded DB has lot more keys and indexes for many tables compare to the fresh installed 4.1 DB + + + + + CLOUDSTACK-1841 + + + ASF 4.0 to 4.1 Upgrade: Missing Few Global Configuration parameters on the Upgraded Setup. + + + + + CLOUDSTACK-1842 + + + ASF 4.0 to 4.1 Upgrade: Missing Ubuntu 12.04 Guest OS Types on the Upgraded Setup. + + + + + CLOUDSTACK-1844 + + + Upgrade 4.0 -> 4.1 - KVM host agent.properties is not restored as part of upgrading the binaries from 4.0 to 4.1. + + + + + CLOUDSTACK-1845 + + + KVM - storage migration often fail. + + + + + CLOUDSTACK-1846 + + + "KVM - storage pools can silently fail to be unregistered, leading to failure to register later. + + + + + CLOUDSTACK-1848 + + + Cloudstack Packages are not got updated with scenario 4.0 to 4.1 upgrade where MS is on Ubuntu 12.04. + + + + + CLOUDSTACK-1856 + + + Upgrade 4.0 -> 4.1 - Fresh install of 4.1 has 3 parameters missing in db.properties compared to an upgraded 4.0 set up + + + + + CLOUDSTACK-1873 + + + "Installation : JasyptPBEStringDecryptionCLI missing, failed to decrypt db password + + + + + CLOUDSTACK-1874 + + + AWS Regions - Account table in cloud_usage DB has region_id + + + + + CLOUDSTACK-1876 + + + External Devices - network offering for external devices is not returned in API listNetworkOfferings when creating instances. + + + + + CLOUDSTACK-1877 + + + Failed to connect to DB while starting Ubuntu management server after upgrading the packages from 4.0 to 4.1.0 + + + + + CLOUDSTACK-1882 + + + “HTTP Status 404 。 The requested resource () is not available. + + + + + CLOUDSTACK-1890 + + + listProjects is not listing state in the respons + + + + + CLOUDSTACK-1900 + + + "Upgrade 4.0 -> 4.1, We do not have a copy of db.properties that comes from a 4.1 installation saved anywhere. + + + + + CLOUDSTACK-1929 + + + ASF 4.1 cloudstack agent fail to install in KVM host CENTOS 6.3 OS: qemu-kvm-0.12.1.2-3.295.el6.10.x86_64 requires libusbredirparser.so. + + + + + CLOUDSTACK-1934 + + + NPE with listSupportedNetworkServices after upgrade from 4.0 to 4.1 (Ubuntu MS + + + + + CLOUDSTACK-1935 + + + Cloud utilities are not renamed to Cloudstack after upgrade from 4.0 to 4.1 [Ubutnu MS + + + + + CLOUDSTACK-1936 + + + On CentOS, after a upgrade from 4.0.1 to 4.1 on a cloud node (cloud-agent), the new cloustack-agent isn't add as a service (chkconfig) + + + + + CLOUDSTACK-1951 + + + centos packaging: cloud-install-sys-tmplt can't find jasypt jar. + + + + + CLOUDSTACK-1971 + + + VM deployed to incorrect primary storage. + + + + + CLOUDSTACK-1972 + + + VM deployed to incorrect primary storage. + + + + + CLOUDSTACK-1978 + + + openvswitch - unable to start console session for SSVM CPVM user VM + + + + + CLOUDSTACK-1980 + + + "[4.1]cloudstack-setup-bridge, cloudstack-setup-encryption & cloudstack-sysvmadm utilities are not available in Ubuntu 12.04 Management Server. + + + + + CLOUDSTACK-1987 + + + Deleted service offerings owned by a domain show up to domain user. + + + + + CLOUDSTACK-1988 + + + AWS API using SOAP client - User Registeration fails + + + + + CLOUDSTACK-1989 + + + "Query service offering by ID returns no result, but querying all returns service offering + + + + + CLOUDSTACK-2003 + + + Deleting domain while deleted account is cleaning up leaves VMs expunging forever due to 'Failed to update resource count + + + + + CLOUDSTACK-2007 + + + Release Notes failing to build on jenkins.cs. + + + + CS-16135 + Creating volumes after upgrading from snapshot taken in 2.2.14 no longer deletes the snapshot physically from the secondary storage. + + + + +
+
+ Known Issues in 4.1.0 + + + + + + + + Issue ID + + + Description + + + + + + CLOUDSTACK-1747 + mvn deploydb only creates 4.0 DB, not 4.1 + Due to tooling changes between 4.1 and 4.2, CloudStack's database is created using the 4.0 schema and updated to the 4.1 schema when the management server starts for the first time. It's OK to see the same schema if the management server has not started yet. + + + + CLOUDSTACK-1824 + Service CloudStack-Management is being displayed as cloud-management service + Many scripts and text entries have references to cloud-management rather than cloudstack-management due to the changeover between 4.0 and 4.1 to rename services. This is a minor issue and should be corrected by 4.2. + + + + + CLOUDSTACK-1824 + Service CloudStack-Management is being displayed as cloud-management service + + + + + CLOUDSTACK-1510 + + + NPE when primary storage is added with wrong path + + + + + CLOUDSTACK-1428 + + + [UI] Instance which are created without display name are not visible when added to LB + + + + + CLOUDSTACK-1306 + + + Better Error message when trying to deploy Vm by passing static Ipv4 addresses that are assigned to another VM/IP4 address is outside the iprange. + + + + + CLOUDSTACK-1236 + + + Warning while adding Xen 6.1 host [Unable to create local link network] + + + + + CLOUDSTACK-969 + + + api: zone response lists vlan in it as "vlan range of zone" but the vlan belongs to physical network + + + + + CLOUDSTACK-963 + + + [cloud.utils.AnnotationHelper] class java.lang.Stringdoes not have a Table annotation + + + + + CLOUDSTACK-458 + + + xen:snapshots:Storage gc fail to clean the failed snapshot images from secondarystorage + + + + + CLOUDSTACK-315 + + + Infrastructure view does not show capacity values + + + + + CLOUDSTACK-300 + + + Creation of compute offering allow combination of local storage + HA + + + + + CLOUDSTACK-282 + + + Virtual Routers do not properly resolve DNS SRV Records + + + + + CLOUDSTACK-276 + + + SSVM ID is exposed in the Error Message thrown by AddTrafficType API + + + + + CLOUDSTACK-270 + + + Ui should not ask for a vlan range if the physical network isolation type is not VLAN + + + + + CLOUDSTACK-245 + + + VPC ACLs are not stored and programmed consistently + + + + + CLOUDSTACK-231 + + + Tag creation using special charecters + + + + + CLOUDSTACK-124 + + + NetworkGarbageCollector not cleaning up networks + + + + + CLOUDSTACK-62 + + + console proxy does not support any keymaps besides us, jp + + + + + +
+
Upgrade Instructions This section contains upgrade instructions from prior versions of CloudStack to Apache CloudStack 4.1.0. We include instructions on upgrading to Apache CloudStack from pre-Apache versions of Citrix CloudStack (last version prior to Apache is 3.0.2) and from the releases made while CloudStack was in the Apache Incubator. @@ -46,6 +4129,92 @@ under the License. Create RPM or Debian packages (as appropriate) and a repository from the 4.1.0 source, or check the Apache CloudStack downloads page at http://cloudstack.apache.org/downloads.html for package repositories supplied by community members. You will need them for step or step . Instructions for creating packages from the &PRODUCT; source are in the Installation Guide. + + For VMware Only + This step is only required if you are using VMware. You can safely skip this step if you are using KVM and/or Xen only. + + In each zone that includes VMware hosts, you need to add a new system VM template. + + + While running the existing 3.0.2 system, log in to the UI as root administrator. + + + In the left navigation bar, click Templates. + + + In Select view, click Templates. + + + Click Register template. + The Register template dialog box is displayed. + + + In the Register template dialog box, specify the following values (do not change these): + + + + + + + Field + Value + + + + + Name + systemvm-vmware-4.1 + + + Description + systemvm-vmware-4.1 + + + URL + http://download.cloud.com/templates/burbank/burbank-systemvm-08012012.ova + + + Zone + Choose the zone where this hypervisor is used + + + Hypervisor + VMware + + + Format + OVA + + + OS Type + Debian GNU/Linux 5.0 (32-bit) + + + Extractable + no + + + Password Enabled + no + + + Public + no + + + Featured + no + + + + + + + Watch the screen to be sure that the template downloads successfully and enters + the READY state. Do not proceed until this is successful. + + + Stop your management server or servers. Run this on all management server hosts: # service cloud-management stop @@ -102,17 +4271,17 @@ under the License. Restart the agent: -service cloud-agent stop -killall jsvc -service cloudstack-agent start + service cloud-agent stop + killall jsvc + service cloudstack-agent start During the upgrade, log4j-cloud.xml was simply copied over, so the logs will continue to be added to /var/log/cloud/agent/agent.log. There's nothing wrong with this, but if you prefer to be consistent, you can change this by copying over the sample configuration file: -cd /etc/cloudstack/agent -mv log4j-cloud.xml.dpkg-dist log4j-cloud.xml -service cloudstack-agent restart + cd /etc/cloudstack/agent + mv log4j-cloud.xml.dpkg-dist log4j-cloud.xml + service cloudstack-agent restart @@ -132,12 +4301,12 @@ service cloudstack-agent restart # tail -f sysvm.log The output to sysvm.log will look something like this: -Stopping and starting 1 secondary storage vm(s)... -Done stopping and starting secondary storage vm(s) -Stopping and starting 1 console proxy vm(s)... -Done stopping and starting console proxy vm(s). -Stopping and starting 4 running routing vm(s)... -Done restarting router(s). + Stopping and starting 1 secondary storage vm(s)... + Done stopping and starting secondary storage vm(s) + Stopping and starting 1 console proxy vm(s)... + Done stopping and starting console proxy vm(s). + Stopping and starting 4 running routing vm(s)... + Done restarting router(s). @@ -196,11 +4365,11 @@ Done restarting router(s). Name - systemvm-vmware-4.0 + systemvm-vmware-4.1 Description - systemvm-vmware-4.0 + systemvm-vmware-4.1 URL @@ -886,12 +5055,12 @@ Done restarting router(s). # tail -f sysvm.log The content should be like the following: -Stopping and starting 1 secondary storage vm(s)... -Done stopping and starting secondary storage vm(s) -Stopping and starting 1 console proxy vm(s)... -Done stopping and starting console proxy vm(s). -Stopping and starting 4 running routing vm(s)... -Done restarting router(s). + Stopping and starting 1 secondary storage vm(s)... + Done stopping and starting secondary storage vm(s) + Stopping and starting 1 console proxy vm(s)... + Done stopping and starting console proxy vm(s). + Stopping and starting 4 running routing vm(s)... + Done restarting router(s). @@ -1083,210 +5252,6 @@ Done restarting router(s). - - Version 4.1.0 -
- What’s New in 4.1 - Apache CloudStack 4.1.0 includes many new features. This section covers the most prominent new features and changes. -
-
- Issues Fixed in 4.1.0 - Apache CloudStack uses Jira - to track its issues. All new features and bugs for 4.1.0 have been tracked in Jira, and have - a standard naming convention of "CLOUDSTACK-NNNN" where "NNNN" is the issue number. - This section includes a summary of known issues against 4.0.0 that were fixed in 4.1.0. - - - - - - - - Defect - - - Description - - - - - - CS-16135 - Creating volumes after upgrading from snapshot taken in 2.2.14 no longer - deletes the snapshot physically from the secondary storage. - - - - -
-
- Known Issues in 4.1.0 - - - - - - - - Issue ID - - - Description - - - - - - CLOUDSTACK-1747 - mvn deploydb only creates 4.0 DB, not 4.1 - Due to tooling changes between 4.1 and 4.2, CloudStack's database is created using the 4.0 schema and updated to the 4.1 schema when the management server starts for the first time. It's OK to see the same schema if the management server has not started yet. - - - - CLOUDSTACK-1824 - Service CloudStack-Management is being displayed as cloud-management service - Many scripts and text entries have references to cloud-management rather than cloudstack-management due to the changeover between 4.0 and 4.1 to rename services. This is a minor issue and should be corrected by 4.2. - - - - - CLOUDSTACK-1824 - Service CloudStack-Management is being displayed as cloud-management service - - - - - CLOUDSTACK-1510 - - - NPE when primary storage is added with wrong path - - - - - CLOUDSTACK-1428 - - - [UI] Instance which are created without display name are not visible when added to LB - - - - - CLOUDSTACK-1306 - - - Better Error message when trying to deploy Vm by passing static Ipv4 addresses that are assigned to another VM/IP4 address is outside the iprange. - - - - - CLOUDSTACK-1236 - - - Warning while adding Xen 6.1 host [Unable to create local link network] - - - - - CLOUDSTACK-969 - - - api: zone response lists vlan in it as "vlan range of zone" but the vlan belongs to physical network - - - - - CLOUDSTACK-963 - - - [cloud.utils.AnnotationHelper] class java.lang.Stringdoes not have a Table annotation - - - - - CLOUDSTACK-458 - - - xen:snapshots:Storage gc fail to clean the failed snapshot images from secondarystorage - - - - - CLOUDSTACK-315 - - - Infrastructure view does not show capacity values - - - - - CLOUDSTACK-300 - - - Creation of compute offering allow combination of local storage + HA - - - - - CLOUDSTACK-282 - - - Virtual Routers do not properly resolve DNS SRV Records - - - - - CLOUDSTACK-276 - - - SSVM ID is exposed in the Error Message thrown by AddTrafficType API - - - - - CLOUDSTACK-270 - - - Ui should not ask for a vlan range if the physical network isolation type is not VLAN - - - - - CLOUDSTACK-245 - - - VPC ACLs are not stored and programmed consistently - - - - - CLOUDSTACK-231 - - - Tag creation using special charecters - - - - - CLOUDSTACK-124 - - - NetworkGarbageCollector not cleaning up networks - - - - - CLOUDSTACK-62 - - - console proxy does not support any keymaps besides us, jp - - - - - -
-
diff --git a/docs/en-US/hypervisor-kvm-install-flow.xml b/docs/en-US/hypervisor-kvm-install-flow.xml index 6cc73e4fdfa..7dfd47d2e52 100644 --- a/docs/en-US/hypervisor-kvm-install-flow.xml +++ b/docs/en-US/hypervisor-kvm-install-flow.xml @@ -34,4 +34,5 @@ + diff --git a/docs/en-US/images/VMSnapshotButton.png b/docs/en-US/images/VMSnapshotButton.png new file mode 100644 index 00000000000..52177402198 Binary files /dev/null and b/docs/en-US/images/VMSnapshotButton.png differ diff --git a/docs/en-US/images/revert-vm.png b/docs/en-US/images/revert-vm.png new file mode 100644 index 00000000000..04655dc37ad Binary files /dev/null and b/docs/en-US/images/revert-vm.png differ diff --git a/docs/en-US/ipv6-support.xml b/docs/en-US/ipv6-support.xml index 7367ec9ad80..c7f7744393e 100644 --- a/docs/en-US/ipv6-support.xml +++ b/docs/en-US/ipv6-support.xml @@ -75,8 +75,8 @@ Use the System VM template exclusively designed to support IPv6. Download the System - VM template from http://nfs1.lab.vmops.com/templates/routing/debian/ipv6/. + VM template from http://cloudstack.apt-get.eu/systemvm/. The concept of Default Network applies to IPv6 networks. However, unlike IPv4 diff --git a/docs/en-US/virtual-machines.xml b/docs/en-US/virtual-machines.xml index 7c74932b649..20018da8dfb 100644 --- a/docs/en-US/virtual-machines.xml +++ b/docs/en-US/virtual-machines.xml @@ -26,6 +26,7 @@ + diff --git a/docs/en-US/vm-snapshots.xml b/docs/en-US/vm-snapshots.xml new file mode 100644 index 00000000000..8d4bcf9bca1 --- /dev/null +++ b/docs/en-US/vm-snapshots.xml @@ -0,0 +1,146 @@ + + +%BOOK_ENTITIES; +]> + + +
+ Virtual Machine Snapshots for VMware + (VMware hosts only) + In addition to the existing &PRODUCT; ability to snapshot VM volumes, + you can now take a VM snapshot to preserve all of the VM's state and data. + This is useful for quick restore of a VM. + For example, you can snapshot a VM, then make changes such as software upgrades. + If anything goes wrong, simply restore the VM to its previous state using the previously saved VM snapshot. + + The snapshot is created using the VMware native snapshot facility. The VM snapshot + includes not only the data volumes, but optionally also whether the VM is running or + turned off (CPU state) and the memory contents. The snapshot is stored in &PRODUCT;'s + primary storage. + VM snapshots can have a parent/child relationship. + Each successive snapshot of the same VM is the child of the snapshot that came before it. + Each time you take an additional snapshot of the same VM, it saves only the differences + between the current state of the VM and the state stored in the most recent previous snapshot. + The previous snapshot becomes a parent, and the new snapshot is its child. + It is possible to create a long chain of these parent/child snapshots, + which amount to a "redo" record leading from the current state of the VM back to the + original. + If you need more information about VM snapshots, check out the VMware documentation + and the VMware Knowledge Base, especially + Understanding virtual machine snapshots. +
+ Limitations on VM Snapshots + + If a VM has some stored snapshots, you can't attach new volume to the VM + or delete any existing volumes. + If you change the volumes on the VM, it would become impossible to restore the VM snapshot + which was created with the previous volume structure. + VM snapshots which include both data volumes and memory can't be kept if you change the VM's + service offering. Any existing VM snapshots of this type will be discarded. + + You can't make a VM snapshot at the same time as you are taking a volume + snapshot. + + + The "quiesce" option is not supported. This option is provided by the underlying + VMware snapshot facility so that you can choose whether to quiesce the file system + on a running virtual machine before taking the snapshot. In &PRODUCT;, the quiesce option is always + set to false; the file system is not quiesced before taking a snapshot of a running VM. + + + You should use only &PRODUCT; to create VM snapshots on VMware hosts managed by &PRODUCT;. + Any snapshots that you make directly on vSphere will not be tracked in &PRODUCT;. + +
+
+ Configuring VM Snapshots + The cloud administrator can use global configuration variables to control the behavior of VM snapshots. + To set these variables, go through the Global Settings are of the UI. + + + + + Configuration Setting Name + Description + + + + + vmsnapshots.max + The maximum number of VM snapshots that can be saved for any given virtual machine in the cloud. + The total possible number of VM snapshots in the cloud is (number of VMs) * vmsnapshots.max. + If the number of snapshots for any VM ever hits the maximum, the older ones are removed + by the snapshot expunge job. + + + + vmsnapshot.create.wait + Number of seconds to wait for a snapshot job to succeed before declaring failure and issuing an error. + + + + +
+
+ Using VM Snapshots + To create a VM snapshot using the &PRODUCT; UI: + + Log in to the &PRODUCT; UI as a user or administrator. + Click Instances. + Click the name of the VM you want to snapshot. + Click the Take VM Snapshot button. + + + + + + If a snapshot is already in progress, then clicking this button will have no effect. + + Provide a name and description. These will be displayed in the VM Snapshots list. + (For running VMs only) If you want to include the VM's memory in the snapshot, click the + Memory checkbox. This saves the CPU and memory state of the virtual machine. If you + don't check this box, then only the current state of the VM disk is saved. Checking + this box makes the snapshot take longer. + Click OK. + + To delete a snapshot or restore a VM to the state saved in a particular snapshot: + + Navigate to the VM as described in the earlier steps. + Click View VM Snapshots. + In the list of snapshots, click the name of the snapshot you want to work with. + Depending on what you want to do: + To delete the snapshot, click the Delete button. + + + + + + To revert to the snapshot, click the Revert button. + + + + + + + + VM snapshots are deleted automatically when a VM is destroyed. + You don't have to manually delete the snapshots in this case. +
+
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CommandResult.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CommandResult.java index 6b6139b937d..cc45914dc41 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CommandResult.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/CommandResult.java @@ -34,7 +34,7 @@ public class CommandResult { return !this.success; } - public void setSucess(boolean success) { + public void setSuccess(boolean success) { this.success = success; } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java index 726ce0821c5..f619ef4e976 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java @@ -26,7 +26,7 @@ public interface ObjectInDataStoreStateMachine extends StateObject _planners; - + @Inject protected VolumeDao _volsDao; - + @Inject protected PrimaryDataStoreDao _storagePoolDao; @Inject DataStoreManager dataStoreMgr; - + + @Inject + DeploymentPlanningManager _dpMgr; + @Override public VMEntityVO loadVirtualMachine(String vmId) { // TODO Auto-generated method stub @@ -114,11 +119,11 @@ public class VMEntityManagerImpl implements VMEntityManager { @Override public void saveVirtualMachine(VMEntityVO entity) { _vmEntityDao.persist(entity); - + } @Override - public String reserveVirtualMachine(VMEntityVO vmEntityVO, String plannerToUse, DeploymentPlan planToDeploy, ExcludeList exclude) + public String reserveVirtualMachine(VMEntityVO vmEntityVO, String plannerToUse, DeploymentPlan planToDeploy, ExcludeList exclude) throws InsufficientCapacityException, ResourceUnavailableException { //call planner and get the deployDestination. @@ -130,12 +135,12 @@ public class VMEntityManagerImpl implements VMEntityManager { if(planToDeploy != null && planToDeploy.getDataCenterId() != 0){ plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), planToDeploy.getPoolId(), planToDeploy.getPhysicalNetworkId()); } - + List vols = _volsDao.findReadyRootVolumesByInstance(vm.getId()); if(!vols.isEmpty()){ VolumeVO vol = vols.get(0); StoragePool pool = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(vol.getPoolId()); - + if (!pool.isInMaintenance()) { long rootVolDcId = pool.getDataCenterId(); Long rootVolPodId = pool.getPodId(); @@ -156,21 +161,21 @@ public class VMEntityManagerImpl implements VMEntityManager { } } - + + } + + DeployDestination dest; + try { + dest = _dpMgr.planDeployment(vmProfile, plan, exclude); + } catch (AffinityConflictException e) { + throw new CloudRuntimeException("Unable to create deployment, affinity rules associted to the VM conflict"); } - - DeploymentPlanner planner = ComponentContext.getComponent(plannerToUse); - DeployDestination dest = null; - - if (planner.canHandle(vmProfile, plan, exclude)) { - dest = planner.plan(vmProfile, plan, exclude); - } if (dest != null) { //save destination with VMEntityVO VMReservationVO vmReservation = new VMReservationVO(vm.getId(), dest.getDataCenter().getId(), dest.getPod().getId(), dest.getCluster().getId(), dest.getHost().getId()); Map volumeReservationMap = new HashMap(); - + if (vm.getHypervisorType() != HypervisorType.BareMetal) { for(Volume vo : dest.getStorageForDisks().keySet()){ volumeReservationMap.put(vo.getId(), dest.getStorageForDisks().get(vo).getId()); @@ -180,21 +185,21 @@ public class VMEntityManagerImpl implements VMEntityManager { vmEntityVO.setVmReservation(vmReservation); _vmEntityDao.persist(vmEntityVO); - + return vmReservation.getUuid(); }else{ throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId()); } - + } @Override public void deployVirtualMachine(String reservationId, String caller, Map params) throws InsufficientCapacityException, ResourceUnavailableException{ //grab the VM Id and destination using the reservationId. - + VMReservationVO vmReservation = _reservationDao.findByReservationId(reservationId); long vmId = vmReservation.getVmId(); - + VMInstanceVO vm = _vmDao.findById(vmId); //Pass it down Long poolId = null; @@ -205,12 +210,17 @@ public class VMEntityManagerImpl implements VMEntityManager { poolId = storage.get(volIdList.get(0)); } } - - DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), vmReservation.getPodId(), vmReservation.getClusterId(), + + DataCenterDeployment reservedPlan = new DataCenterDeployment(vm.getDataCenterId(), vmReservation.getPodId(), vmReservation.getClusterId(), vmReservation.getHostId(), null , null); - - VMInstanceVO vmDeployed = _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), plan); - + try{ + VMInstanceVO vmDeployed = _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), reservedPlan); + }catch(Exception ex){ + //Retry the deployment without using the reservation plan + DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), null, null,null, null , null); + _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), plan); + } + } @Override @@ -227,7 +237,7 @@ public class VMEntityManagerImpl implements VMEntityManager { VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid()); return _itMgr.destroy(vm, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId())); - + } } diff --git a/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java index c07931befc8..963e4d7d967 100755 --- a/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/platform/orchestration/CloudOrchestrator.java @@ -51,7 +51,6 @@ import com.cloud.user.dao.AccountDao; import com.cloud.utils.Pair; import com.cloud.utils.component.ComponentContext; import com.cloud.vm.NicProfile; -import com.cloud.vm.UserVmVO; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.dao.UserVmDao; @@ -66,25 +65,25 @@ public class CloudOrchestrator implements OrchestrationService { @Inject private VirtualMachineManager _itMgr; - + @Inject protected VMTemplateDao _templateDao = null; - + @Inject protected VMInstanceDao _vmDao; - + @Inject protected UserVmDao _userVmDao = null; - + @Inject protected ServiceOfferingDao _serviceOfferingDao; - + @Inject protected DiskOfferingDao _diskOfferingDao = null; - + @Inject protected NetworkDao _networkDao; - + @Inject protected AccountDao _accountDao = null; @@ -147,17 +146,17 @@ public class CloudOrchestrator implements OrchestrationService { @Override public VirtualMachineEntity createVirtualMachine( - String id, - String owner, - String templateId, - String hostName, + String id, + String owner, + String templateId, + String hostName, String displayName, String hypervisor, - int cpu, - int speed, + int cpu, + int speed, long memory, Long diskSize, - List computeTags, + List computeTags, List rootDiskTags, Map networkNicMap, DeploymentPlan plan) throws InsufficientCapacityException { @@ -173,22 +172,22 @@ public class CloudOrchestrator implements OrchestrationService { VirtualMachineEntityImpl vmEntity = ComponentContext.inject(VirtualMachineEntityImpl.class); vmEntity.init(id, owner, hostName, displayName, cpu, speed, memory, computeTags, rootDiskTags, new ArrayList(networkNicMap.keySet())); - - + + HypervisorType hypervisorType = HypervisorType.valueOf(hypervisor); //load vm instance and offerings and call virtualMachineManagerImpl VMInstanceVO vm = _vmDao.findByUuid(id); - + // If the template represents an ISO, a disk offering must be passed in, and will be used to create the root disk // Else, a disk offering is optional, and if present will be used to create the data disk Pair rootDiskOffering = new Pair(null, null); List> dataDiskOfferings = new ArrayList>(); - + ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getServiceOfferingId()); rootDiskOffering.first(offering); - + if(vm.getDiskOfferingId() != null){ DiskOfferingVO diskOffering = _diskOfferingDao.findById(vm.getDiskOfferingId()); if (diskOffering == null) { @@ -205,32 +204,32 @@ public class CloudOrchestrator implements OrchestrationService { } dataDiskOfferings.add(new Pair(diskOffering, size)); } - - - + + + if (_itMgr.allocate(_userVmDao.findById(vm.getId(), true), _templateDao.findById(new Long(templateId)), offering, rootDiskOffering, dataDiskOfferings, networkIpMap, null, plan, hypervisorType, _accountDao.findById(new Long(owner))) == null) { return null; } - + return vmEntity; } @Override public VirtualMachineEntity createVirtualMachineFromScratch(String id, String owner, String isoId, String hostName, String displayName, String hypervisor, String os, int cpu, int speed, long memory,Long diskSize, List computeTags, List rootDiskTags, Map networkNicMap, DeploymentPlan plan) throws InsufficientCapacityException { - + // VirtualMachineEntityImpl vmEntity = new VirtualMachineEntityImpl(id, owner, hostName, displayName, cpu, speed, memory, computeTags, rootDiskTags, networks, vmEntityManager); VirtualMachineEntityImpl vmEntity = ComponentContext.inject(VirtualMachineEntityImpl.class); vmEntity.init(id, owner, hostName, displayName, cpu, speed, memory, computeTags, rootDiskTags, new ArrayList(networkNicMap.keySet())); //load vm instance and offerings and call virtualMachineManagerImpl VMInstanceVO vm = _vmDao.findByUuid(id); - - + + Pair rootDiskOffering = new Pair(null, null); ServiceOfferingVO offering = _serviceOfferingDao.findById(vm.getServiceOfferingId()); rootDiskOffering.first(offering); - + List> dataDiskOfferings = new ArrayList>(); Long diskOfferingId = vm.getDiskOfferingId(); if (diskOfferingId == null) { @@ -251,7 +250,7 @@ public class CloudOrchestrator implements OrchestrationService { } rootDiskOffering.first(diskOffering); rootDiskOffering.second(size); - + List> networkIpMap = new ArrayList>(); for (String uuid : networkNicMap.keySet()) { NetworkVO network = _networkDao.findByUuid(uuid); @@ -259,13 +258,13 @@ public class CloudOrchestrator implements OrchestrationService { networkIpMap.add(new Pair(network, networkNicMap.get(uuid))); } } - + HypervisorType hypervisorType = HypervisorType.valueOf(hypervisor); - + if (_itMgr.allocate(_userVmDao.findById(vm.getId(), true), _templateDao.findById(new Long(isoId)), offering, rootDiskOffering, dataDiskOfferings, networkIpMap, null, plan, hypervisorType, _accountDao.findById(new Long(owner))) == null) { return null; } - + return vmEntity; } diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java index 97ea6c48c79..4c16f2fe4b1 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java @@ -33,6 +33,8 @@ import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncRpcConext; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.image.ImageDataStoreDriver; import org.apache.log4j.Logger; @@ -45,8 +47,8 @@ import com.cloud.agent.api.to.SwiftTO; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.storage.RegisterVolumePayload; -import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.SnapshotVO; +import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateZoneVO; @@ -80,6 +82,7 @@ public class AncientImageDataStoreDriverImpl implements ImageDataStoreDriver { @Inject SnapshotDao snapshotDao; @Inject AgentManager agentMgr; @Inject SnapshotManager snapshotMgr; + @Inject PrimaryDataStoreDao primaryDataStoreDao; @Inject private SwiftManager _swiftMgr; @Inject @@ -196,9 +199,10 @@ public class AncientImageDataStoreDriverImpl implements ImageDataStoreDriver { } SwiftTO swift = _swiftMgr.getSwiftTO(snapshot.getSwiftId()); S3TO s3 = _s3Mgr.getS3TO(); - + VolumeVO volume = volumeDao.findById(volumeId); + StoragePoolVO pool = primaryDataStoreDao.findById(volume.getPoolId()); DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand( - swift, s3, secondaryStoragePoolUrl, dcId, accountId, volumeId, + pool, swift, s3, secondaryStoragePoolUrl, dcId, accountId, volumeId, backupOfSnapshot, false); Answer answer = agentMgr.sendToSSVM(dcId, cmd); diff --git a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java b/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java index c49a521a3ca..a70fd8ab227 100644 --- a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java +++ b/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java @@ -70,12 +70,12 @@ public class DefaultImageMotionStrategy implements ImageMotionStrategy { CommandResult result = new CommandResult(); if (!answer.getResult()) { - result.setSucess(answer.getResult()); + result.setSuccess(answer.getResult()); result.setResult(answer.getDetails()); } else { TemplateOnPrimaryDataStoreInfo templateStore = context.getTemplate(); templateStore.setPath(answer.getPath()); - result.setSucess(true); + result.setSuccess(true); } parentCall.complete(result); diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java index 2d6b94fdfaf..fc4aea85822 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java @@ -23,7 +23,7 @@ import java.util.UUID; import javax.inject.Inject; import org.apache.cloudstack.storage.to.ImageDataStoreTO; -import org.apache.cloudstack.storage.to.ImageOnPrimayDataStoreTO; +import org.apache.cloudstack.storage.to.ImageOnPrimaryDataStoreTO; import org.apache.cloudstack.storage.to.PrimaryDataStoreTO; import org.apache.cloudstack.storage.to.TemplateTO; import org.mockito.Mockito; @@ -126,7 +126,7 @@ public class DirectAgentTest extends CloudStackTestNGBase { @Test public void testDownloadTemplate() { - ImageOnPrimayDataStoreTO image = Mockito.mock(ImageOnPrimayDataStoreTO.class); + ImageOnPrimaryDataStoreTO image = Mockito.mock(ImageOnPrimaryDataStoreTO.class); PrimaryDataStoreTO primaryStore = Mockito.mock(PrimaryDataStoreTO.class); Mockito.when(primaryStore.getUuid()).thenReturn(this.getLocalStorageUuid()); Mockito.when(image.getPrimaryDataStore()).thenReturn(primaryStore); diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervsiorHostEndPointRpcServer.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervisorHostEndPointRpcServer.java similarity index 95% rename from engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervsiorHostEndPointRpcServer.java rename to engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervisorHostEndPointRpcServer.java index d6985768d91..8fc161bae1e 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervsiorHostEndPointRpcServer.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervisorHostEndPointRpcServer.java @@ -29,9 +29,9 @@ import org.apache.cloudstack.storage.HypervisorHostEndPoint; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; -public class MockHypervsiorHostEndPointRpcServer implements HostEndpointRpcServer { +public class MockHypervisorHostEndPointRpcServer implements HostEndpointRpcServer { private ScheduledExecutorService executor; - public MockHypervsiorHostEndPointRpcServer() { + public MockHypervisorHostEndPointRpcServer() { executor = Executors.newScheduledThreadPool(10); } diff --git a/engine/storage/integration-test/test/resource/component.xml b/engine/storage/integration-test/test/resource/component.xml index 0368ad41425..5ba87e8ebe9 100644 --- a/engine/storage/integration-test/test/resource/component.xml +++ b/engine/storage/integration-test/test/resource/component.xml @@ -75,7 +75,7 @@
- + 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 d10dc778092..37238b72121 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 @@ -106,7 +106,7 @@ public class SnapshotObject implements SnapshotInfo { @Override public Long getSize() { - return this.getSize(); + return this.snapshot.getSize(); } @Override diff --git a/engine/storage/src/org/apache/cloudstack/storage/HypervsiorHostEndPointRpcServer.java b/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPointRpcServer.java similarity index 92% rename from engine/storage/src/org/apache/cloudstack/storage/HypervsiorHostEndPointRpcServer.java rename to engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPointRpcServer.java index f441f39ddfa..bc217769d91 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/HypervsiorHostEndPointRpcServer.java +++ b/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPointRpcServer.java @@ -36,16 +36,16 @@ import com.cloud.agent.api.Command; import com.cloud.utils.exception.CloudRuntimeException; @Component -public class HypervsiorHostEndPointRpcServer implements HostEndpointRpcServer { - private static final Logger s_logger = Logger.getLogger(HypervsiorHostEndPointRpcServer.class); +public class HypervisorHostEndPointRpcServer implements HostEndpointRpcServer { + private static final Logger s_logger = Logger.getLogger(HypervisorHostEndPointRpcServer.class); @Inject private RpcProvider rpcProvider; - public HypervsiorHostEndPointRpcServer() { + public HypervisorHostEndPointRpcServer() { } - public HypervsiorHostEndPointRpcServer(RpcProvider rpcProvider) { + public HypervisorHostEndPointRpcServer(RpcProvider rpcProvider) { rpcProvider = rpcProvider; rpcProvider.registerRpcServiceEndpoint(RpcServiceDispatcher.getDispatcher(this)); } @@ -91,7 +91,7 @@ public class HypervsiorHostEndPointRpcServer implements HostEndpointRpcServer { @Override public Answer sendCommand(HypervisorHostEndPoint host, Command command) { SendCommandContext context = new SendCommandContext(null); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); caller.setCallback(caller.getTarget().sendCommandCallback(null, null)) .setContext(context); @@ -109,7 +109,7 @@ public class HypervsiorHostEndPointRpcServer implements HostEndpointRpcServer { return context.getAnswer(); } - protected Object sendCommandCallback(AsyncCallbackDispatcher callback, SendCommandContext context) { + protected Object sendCommandCallback(AsyncCallbackDispatcher callback, SendCommandContext context) { context.setAnswer((Answer)callback.getResult()); synchronized(context) { context.notify(); diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java index 6334ca7f2dc..3a66b859b39 100755 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java @@ -176,7 +176,7 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement Long clusterId = pool.getClusterId(); ClusterVO cluster = _clusterDao.findById(clusterId); - if (!(cluster.getHypervisorType() == dskCh.getHypersorType())) { + if (!(cluster.getHypervisorType() == dskCh.getHypervisorType())) { if (s_logger.isDebugEnabled()) { s_logger.debug("StoragePool's Cluster does not have required hypervisorType, skipping this pool"); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java index 7c6c946765f..1d3cd819d70 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/ZoneWideStoragePoolAllocator.java @@ -57,7 +57,7 @@ public class ZoneWideStoragePoolAllocator extends AbstractStoragePoolAllocator { DeploymentPlan plan, ExcludeList avoid, int returnUpTo) { s_logger.debug("ZoneWideStoragePoolAllocator to find storage pool"); List suitablePools = new ArrayList(); - HypervisorType hypervisor = dskCh.getHypersorType(); + HypervisorType hypervisor = dskCh.getHypervisorType(); if (hypervisor != null) { if (hypervisor != HypervisorType.KVM) { s_logger.debug("Only kvm supports zone wide storage"); diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeFromBaseImageCommand.java b/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeFromBaseImageCommand.java index f4be0676b9b..1734bc409cc 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeFromBaseImageCommand.java +++ b/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeFromBaseImageCommand.java @@ -18,14 +18,14 @@ */ package org.apache.cloudstack.storage.command; -import org.apache.cloudstack.storage.to.ImageOnPrimayDataStoreTO; +import org.apache.cloudstack.storage.to.ImageOnPrimaryDataStoreTO; import org.apache.cloudstack.storage.to.VolumeTO; import com.cloud.agent.api.Command; public class CreateVolumeFromBaseImageCommand extends Command implements StorageSubSystemCommand { private final VolumeTO volume; - private final ImageOnPrimayDataStoreTO image; + private final ImageOnPrimaryDataStoreTO image; public CreateVolumeFromBaseImageCommand(VolumeTO volume, String image) { this.volume = volume; @@ -36,7 +36,7 @@ public class CreateVolumeFromBaseImageCommand extends Command implements Storage return this.volume; } - public ImageOnPrimayDataStoreTO getImage() { + public ImageOnPrimaryDataStoreTO getImage() { return this.image; } diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/DataObjectManagerImpl.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/DataObjectManagerImpl.java index 218f9013a17..9d1afbeacad 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/DataObjectManagerImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/DataObjectManagerImpl.java @@ -109,7 +109,7 @@ public class DataObjectManagerImpl implements DataObjectManager { if (obj == null) { CreateCmdResult result = new CreateCmdResult( null, null); - result.setSucess(false); + result.setSuccess(false); result.setResult(e.toString()); callback.complete(result); return; @@ -124,7 +124,7 @@ public class DataObjectManagerImpl implements DataObjectManager { data, store); } catch (Exception e) { CreateCmdResult result = new CreateCmdResult(null, null); - result.setSucess(false); + result.setSuccess(false); result.setResult(e.toString()); callback.complete(result); return; @@ -153,7 +153,7 @@ public class DataObjectManagerImpl implements DataObjectManager { s_logger.debug("state transation failed", e1); } CreateCmdResult result = new CreateCmdResult(null, null); - result.setSucess(false); + result.setSuccess(false); result.setResult(e.toString()); callback.complete(result); return; diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/provider/DataStoreProviderManagerImpl.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/provider/DataStoreProviderManagerImpl.java index 91b6c6329bb..40a65dcf07f 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/provider/DataStoreProviderManagerImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/provider/DataStoreProviderManagerImpl.java @@ -64,7 +64,7 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto return null; } - public List getPrimayrDataStoreProviders() { + public List getPrimaryDataStoreProviders() { List providers = new ArrayList(); for (DataStoreProvider provider : providerMap.values()) { if (provider instanceof PrimaryDataStoreProvider) { @@ -138,7 +138,7 @@ public class DataStoreProviderManagerImpl extends ManagerBase implements DataSto throw new InvalidParameterValueException("Invalid parameter, need to specify type: either primary or image"); } if (type.equalsIgnoreCase(DataStoreProvider.DataStoreProviderType.PRIMARY.toString())) { - return this.getPrimayrDataStoreProviders(); + return this.getPrimaryDataStoreProviders(); } else if (type.equalsIgnoreCase(DataStoreProvider.DataStoreProviderType.IMAGE.toString())) { return this.getImageDataStoreProviders(); } else { diff --git a/engine/storage/src/org/apache/cloudstack/storage/to/ImageOnPrimayDataStoreTO.java b/engine/storage/src/org/apache/cloudstack/storage/to/ImageOnPrimaryDataStoreTO.java similarity index 92% rename from engine/storage/src/org/apache/cloudstack/storage/to/ImageOnPrimayDataStoreTO.java rename to engine/storage/src/org/apache/cloudstack/storage/to/ImageOnPrimaryDataStoreTO.java index 18743d70bf2..a9a3cc43c0e 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/to/ImageOnPrimayDataStoreTO.java +++ b/engine/storage/src/org/apache/cloudstack/storage/to/ImageOnPrimaryDataStoreTO.java @@ -20,11 +20,11 @@ package org.apache.cloudstack.storage.to; import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreInfo; -public class ImageOnPrimayDataStoreTO { +public class ImageOnPrimaryDataStoreTO { private final String pathOnPrimaryDataStore; private PrimaryDataStoreTO dataStore; private final TemplateTO template; - public ImageOnPrimayDataStoreTO(TemplateOnPrimaryDataStoreInfo template) { + public ImageOnPrimaryDataStoreTO(TemplateOnPrimaryDataStoreInfo template) { this.pathOnPrimaryDataStore = template.getPath(); //this.dataStore = template.getPrimaryDataStore().getDataStoreTO(); this.template = new TemplateTO(template.getTemplate()); diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java index 6d0c2c6862b..e5ee742f5ba 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java @@ -144,12 +144,12 @@ public class DefaultPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver CreateVolumeAnswer answer = (CreateVolumeAnswer)callback.getResult(); CommandResult result = new CommandResult(); if (answer == null || answer.getDetails() != null) { - result.setSucess(false); + result.setSuccess(false); if (answer != null) { result.setResult(answer.getDetails()); } } else { - result.setSucess(true); + result.setSuccess(true); VolumeObject volume = context.getVolume(); volume.setPath(answer.getVolumeUuid()); } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/DefaultPrimaryDatastoreProviderImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/DefaultPrimaryDatastoreProviderImpl.java index 46fa738e294..8c674dc0444 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/DefaultPrimaryDatastoreProviderImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/provider/DefaultPrimaryDatastoreProviderImpl.java @@ -42,7 +42,7 @@ public class DefaultPrimaryDatastoreProviderImpl implements PrimaryDataStoreProv @Inject PrimaryDataStoreProviderManager storeMgr; - protected DataStoreLifeCycle lifecyle; + protected DataStoreLifeCycle lifecycle; protected String uuid; protected long id; @Override @@ -52,12 +52,12 @@ public class DefaultPrimaryDatastoreProviderImpl implements PrimaryDataStoreProv @Override public DataStoreLifeCycle getDataStoreLifeCycle() { - return this.lifecyle; + return this.lifecycle; } @Override public boolean configure(Map params) { - lifecyle = ComponentContext.inject(DefaultPrimaryDataStoreLifeCycleImpl.class); + lifecycle = ComponentContext.inject(DefaultPrimaryDataStoreLifeCycleImpl.class); driver = ComponentContext.inject(DefaultPrimaryDataStoreDriverImpl.class); listener = ComponentContext.inject(DefaultHostListener.class); return true; diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplateInstallStrategyImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplateInstallStrategyImpl.java index 5f1735c180a..e09961913de 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplateInstallStrategyImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/TemplateInstallStrategyImpl.java @@ -107,7 +107,7 @@ public class TemplateInstallStrategyImpl implements TemplateInstallStrategy { if (obj == null) { CreateBaseImageResult result = new CreateBaseImageResult( null); - result.setSucess(false); + result.setSuccess(false); result.setResult(e.toString()); callback.complete(result); return null; @@ -122,7 +122,7 @@ public class TemplateInstallStrategyImpl implements TemplateInstallStrategy { template, store); } catch (Exception e) { CreateBaseImageResult result = new CreateBaseImageResult(null); - result.setSucess(false); + result.setSuccess(false); result.setResult(e.toString()); callback.complete(result); return null; @@ -145,7 +145,7 @@ public class TemplateInstallStrategyImpl implements TemplateInstallStrategy { s_logger.debug("state transation failed", e1); } CreateBaseImageResult result = new CreateBaseImageResult(null); - result.setSucess(false); + result.setSuccess(false); result.setResult(e.toString()); callback.complete(result); return null; diff --git a/packaging/centos63/cloud-usage.rc b/packaging/centos63/cloud-usage.rc index 76f0e06fdfe..a9b60478875 100755 --- a/packaging/centos63/cloud-usage.rc +++ b/packaging/centos63/cloud-usage.rc @@ -58,7 +58,7 @@ export JAVA_HOME SCP="" DCP="" -UCP=`ls /usr/share/cloudstack-usage/cloud-usage-*.jar`":"`ls /usr/share/cloudstack-usage/lib/* | tr '\n' ':'` +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" # We need to append the JSVC daemon JAR to the classpath diff --git a/packaging/centos63/cloud.spec b/packaging/centos63/cloud.spec index 9ce46c97c42..a7cc20e8ab8 100644 --- a/packaging/centos63/cloud.spec +++ b/packaging/centos63/cloud.spec @@ -278,6 +278,8 @@ cp plugins/hypervisors/kvm/target/dependencies/* ${RPM_BUILD_ROOT}%{_datadir}/% mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/usage mkdir -p ${RPM_BUILD_ROOT}%{_datadir}/%{name}-usage/lib install -D usage/target/cloud-usage-%{_maventag}.jar ${RPM_BUILD_ROOT}%{_datadir}/%{name}-usage/cloud-usage-%{_maventag}.jar +install -D usage/target/transformed/db.properties ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/usage/db.properties +install -D usage/target/transformed/log4j-cloud_usage.xml ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/usage/log4j-cloud.xml cp usage/target/dependencies/* ${RPM_BUILD_ROOT}%{_datadir}/%{name}-usage/lib/ install -D packaging/centos63/cloud-usage.rc ${RPM_BUILD_ROOT}/%{_sysconfdir}/init.d/%{name}-usage mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/log/%{name}/usage/ @@ -438,6 +440,13 @@ if [ -f "%{_sysconfdir}/cloud.rpmsave/agent/agent.properties" ]; then mv %{_sysconfdir}/cloud.rpmsave/agent/agent.properties %{_sysconfdir}/cloud.rpmsave/agent/agent.properties.rpmsave fi +%post usage +if [ -f "%{_sysconfdir}/%{name}/management/db.properties" ]; then + echo Replacing db.properties with management server db.properties + rm -f %{_sysconfdir}/%{name}/usage/db.properties + ln -s %{_sysconfdir}/%{name}/management/db.properties %{_sysconfdir}/%{name}/usage/db.properties +fi + #%post awsapi #if [ -d "%{_datadir}/%{name}-management" ] ; then # ln -s %{_datadir}/%{name}-bridge/webapps %{_datadir}/%{name}-management/webapps7080 @@ -532,8 +541,9 @@ fi %attr(0755,root,root) %{_sysconfdir}/init.d/%{name}-usage %attr(0644,root,root) %{_datadir}/%{name}-usage/*.jar %attr(0644,root,root) %{_datadir}/%{name}-usage/lib/*.jar -%dir /var/log/%{name}/usage -%dir %{_sysconfdir}/%{name}/usage +%dir %attr(0770,root,cloud) %{_localstatedir}/log/%{name}/usage +%attr(0644,root,root) %{_sysconfdir}/%{name}/usage/db.properties +%attr(0644,root,root) %{_sysconfdir}/%{name}/usage/log4j-cloud.xml %{_defaultdocdir}/%{name}-usage-%{version}/LICENSE %{_defaultdocdir}/%{name}-usage-%{version}/NOTICE diff --git a/packaging/centos63/replace.properties b/packaging/centos63/replace.properties index 211cc95449f..83458549570 100644 --- a/packaging/centos63/replace.properties +++ b/packaging/centos63/replace.properties @@ -56,5 +56,5 @@ SYSCONFDIR=/etc/sysconfig SYSTEMCLASSPATH= SYSTEMJARS= USAGECLASSPATH= -USAGELOG=/var/log/cloudstack/usage +USAGELOG=/var/log/cloudstack/usage/usage.log USAGESYSCONFDIR=/etc/sysconfig diff --git a/plugins/affinity-group-processors/host-anti-affinity/pom.xml b/plugins/affinity-group-processors/host-anti-affinity/pom.xml new file mode 100644 index 00000000000..669febd7db8 --- /dev/null +++ b/plugins/affinity-group-processors/host-anti-affinity/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + cloud-plugin-host-anti-affinity + Apache CloudStack Plugin - Host Anti-Affinity Processor + + org.apache.cloudstack + cloudstack-plugins + 4.2.0-SNAPSHOT + ../../pom.xml + + + install + src + + diff --git a/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java b/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java new file mode 100644 index 00000000000..4c2c7f1c131 --- /dev/null +++ b/plugins/affinity-group-processors/host-anti-affinity/src/org/apache/cloudstack/affinity/HostAntiAffinityProcessor.java @@ -0,0 +1,93 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity; + +import java.util.List; + +import javax.ejb.Local; +import javax.inject.Inject; + +import org.apache.cloudstack.affinity.dao.AffinityGroupDao; +import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; +import org.apache.log4j.Logger; + +import com.cloud.deploy.DeploymentPlan; +import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.exception.AffinityConflictException; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; +import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.dao.VMInstanceDao; + +@Local(value = AffinityGroupProcessor.class) +public class HostAntiAffinityProcessor extends AffinityProcessorBase implements AffinityGroupProcessor { + + private static final Logger s_logger = Logger.getLogger(HostAntiAffinityProcessor.class); + @Inject + protected UserVmDao _vmDao; + @Inject + protected VMInstanceDao _vmInstanceDao; + @Inject + protected AffinityGroupDao _affinityGroupDao; + @Inject + protected AffinityGroupVMMapDao _affinityGroupVMMapDao; + + @Override + public void process(VirtualMachineProfile vmProfile, DeploymentPlan plan, + ExcludeList avoid) + throws AffinityConflictException { + VirtualMachine vm = vmProfile.getVirtualMachine(); + List vmGroupMappings = _affinityGroupVMMapDao.findByVmIdType(vm.getId(), getType()); + + for (AffinityGroupVMMapVO vmGroupMapping : vmGroupMappings) { + if (vmGroupMapping != null) { + AffinityGroupVO group = _affinityGroupDao.findById(vmGroupMapping.getAffinityGroupId()); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Processing affinity group " + group.getName() + " for VM Id: " + vm.getId()); + } + + List groupVMIds = _affinityGroupVMMapDao.listVmIdsByAffinityGroup(group.getId()); + groupVMIds.remove(vm.getId()); + + for (Long groupVMId : groupVMIds) { + VMInstanceVO groupVM = _vmInstanceDao.findById(groupVMId); + if (groupVM != null && !groupVM.isRemoved()) { + if (groupVM.getHostId() != null) { + avoid.addHost(groupVM.getHostId()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Added host " + groupVM.getHostId() + " to avoid set, since VM " + + groupVM.getId() + " is present on the host"); + } + } else if (VirtualMachine.State.Stopped.equals(groupVM.getState()) + && groupVM.getLastHostId() != null) { + avoid.addHost(groupVM.getLastHostId()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Added host " + groupVM.getLastHostId() + " to avoid set, since VM " + + groupVM.getId() + " is present on the host, in Stopped state"); + } + + } + } + } + } + } + + } + +} diff --git a/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java b/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java index d2f25654c7a..09563da2264 100644 --- a/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java +++ b/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java @@ -217,7 +217,7 @@ public class AlertsSyslogAppender extends AppenderSkeleton { message.append("unknown" + MESSAGE_DELIMITER_STRING); } - if (alertType > 0) { + if (alertType >= 0) { message.append("alertType").append(_keyValueDelimiter).append(" ").append(alertsMap.get(alertType)) .append(MESSAGE_DELIMITER_STRING); if (dataCenterId != 0) { @@ -333,4 +333,4 @@ public class AlertsSyslogAppender extends AppenderSkeleton { public void setKeyValueDelimiter(String keyValueDelimiter) { this._keyValueDelimiter = keyValueDelimiter; } -} \ No newline at end of file +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java index 20146970daa..122ba3b9dba 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java @@ -27,6 +27,7 @@ import java.util.Map; import javax.ejb.Local; import javax.inject.Inject; +import org.apache.cloudstack.api.ApiConstants.VMDetails; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -40,6 +41,8 @@ import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.cluster.ClusterManager; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; @@ -49,7 +52,9 @@ import com.cloud.hypervisor.HypervisorGuru; import com.cloud.hypervisor.HypervisorGuruBase; import com.cloud.hypervisor.vmware.manager.VmwareManager; import com.cloud.hypervisor.vmware.mo.VirtualEthernetCardType; +import com.cloud.network.Network.Provider; import com.cloud.network.NetworkModel; +import com.cloud.network.Network.Service; import com.cloud.network.Networks.TrafficType; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.NetworkVO; @@ -84,6 +89,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { @Inject VmwareManager _vmwareMgr; @Inject SecondaryStorageVmManager _secStorageMgr; @Inject NetworkModel _networkMgr; + @Inject ConfigurationDao _configDao; protected VMwareGuru() { super(); @@ -139,13 +145,23 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { details.put(VmDetailConstants.ROOK_DISK_CONTROLLER, _vmwareMgr.getRootDiskController()); } } - + + List nicProfiles = vm.getNics(); + + for(NicProfile nicProfile : nicProfiles) { + if(nicProfile.getTrafficType() == TrafficType.Guest) { + if(_networkMgr.isProviderSupportServiceInNetwork(nicProfile.getNetworkId(), Service.Firewall, Provider.CiscoVnmc)) { + details.put("ConfigureVServiceInNexus", Boolean.TRUE.toString()); + } + break; + } + } + to.setDetails(details); if(vm.getVirtualMachine() instanceof DomainRouterVO) { - List nicProfiles = vm.getNics(); - NicProfile publicNicProfile = null; + NicProfile publicNicProfile = null; for(NicProfile nicProfile : nicProfiles) { if(nicProfile.getTrafficType() == TrafficType.Public) { publicNicProfile = nicProfile; @@ -212,8 +228,21 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { sbMacSequence.deleteCharAt(sbMacSequence.length() - 1); String bootArgs = to.getBootArgs(); to.setBootArgs(bootArgs + " nic_macs=" + sbMacSequence.toString()); + + } + + // Don't do this if the virtual machine is one of the special types + // Should only be done on user machines + if(!(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO + || vm.getVirtualMachine() instanceof SecondaryStorageVmVO)) { + String nestedVirt = _configDao.getValue(Config.VmwareEnableNestedVirtualization.key()); + if (nestedVirt != null) { + s_logger.debug("Nested virtualization requested, adding flag to vm configuration"); + details.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, nestedVirt); + to.setDetails(details); + + } } - // Determine the VM's OS description GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId()); to.setOs(guestOS.getDisplayName()); diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java index b2e37685d17..eb09af0d67e 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareManagerImpl.java @@ -317,8 +317,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw } s_logger.info("Preparing network on host " + hostMo.getContext().toString() + " for " + privateTrafficLabel); - HypervisorHostHelper.prepareNetwork(vSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false); - + HypervisorHostHelper.prepareNetwork(vSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false); } @Override diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 634827b6468..3dc23ccb060 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -232,6 +232,7 @@ import com.vmware.vim25.ClusterDasConfigInfo; import com.vmware.vim25.ComputeResourceSummary; import com.vmware.vim25.DatastoreSummary; import com.vmware.vim25.DynamicProperty; +import com.vmware.vim25.HostCapability; import com.vmware.vim25.HostFirewallInfo; import com.vmware.vim25.HostFirewallRuleset; import com.vmware.vim25.HostNetworkTrafficShapingPolicy; @@ -1328,7 +1329,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa NicTO nicTo = cmd.getNic(); VirtualDevice nic; - Pair networkInfo = prepareNetworkFromNicInfo(vmMo.getRunningHost(), nicTo); + Pair networkInfo = prepareNetworkFromNicInfo(vmMo.getRunningHost(), nicTo, false); if (VmwareHelper.isDvPortGroup(networkInfo.first())) { String dvSwitchUuid; ManagedObjectReference dcMor = hyperHost.getHyperHostDatacenter(); @@ -1570,7 +1571,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa vmMo.getRunningHost(), vlanId, null, null, this._ops_timeout, true); } else { networkInfo = HypervisorHostHelper.prepareNetwork(this._publicTrafficInfo.getVirtualSwitchName(), "cloud.public", - vmMo.getRunningHost(), vlanId, null, null, this._ops_timeout, vSwitchType, _portsPerDvPortGroup); + vmMo.getRunningHost(), vlanId, null, null, this._ops_timeout, vSwitchType, _portsPerDvPortGroup, null, false); } int nicIndex = allocPublicNicIndex(vmMo); @@ -2147,6 +2148,23 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa VmwareHelper.setBasicVmConfig(vmConfigSpec, vmSpec.getCpus(), vmSpec.getMaxSpeed(), vmSpec.getMinSpeed(),(int) (vmSpec.getMaxRam()/(1024*1024)), ramMb, translateGuestOsIdentifier(vmSpec.getArch(), vmSpec.getOs()).value(), vmSpec.getLimitCpuUse()); + + if ("true".equals(vmSpec.getDetails().get(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG))) { + s_logger.debug("Nested Virtualization enabled in configuration, checking hypervisor capability"); + ManagedObjectReference hostMor = vmMo.getRunningHost().getMor(); + ManagedObjectReference computeMor = context.getVimClient().getMoRefProp(hostMor, "parent"); + ManagedObjectReference environmentBrowser = + context.getVimClient().getMoRefProp(computeMor, "environmentBrowser"); + HostCapability hostCapability = context.getService().queryTargetCapabilities(environmentBrowser, hostMor); + if (hostCapability.isNestedHVSupported()) { + s_logger.debug("Hypervisor supports nested virtualization, enabling for VM " + vmSpec.getName()); + vmConfigSpec.setNestedHVEnabled(true); + } + else { + s_logger.warn("Hypervisor doesn't support nested virtualization, unable to set config for VM " +vmSpec.getName()); + vmConfigSpec.setNestedHVEnabled(false); + } + } VirtualDeviceConfigSpec[] deviceConfigSpecArray = new VirtualDeviceConfigSpec[totalChangeDevices]; int i = 0; @@ -2286,7 +2304,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa for (NicTO nicTo : sortNicsByDeviceId(nics)) { s_logger.info("Prepare NIC device based on NicTO: " + _gson.toJson(nicTo)); - Pair networkInfo = prepareNetworkFromNicInfo(vmMo.getRunningHost(), nicTo); + boolean configureVServiceInNexus = (nicTo.getType() == TrafficType.Guest) && (vmSpec.getDetails().containsKey("ConfigureVServiceInNexus")); + Pair networkInfo = prepareNetworkFromNicInfo(vmMo.getRunningHost(), nicTo, configureVServiceInNexus); if (VmwareHelper.isDvPortGroup(networkInfo.first())) { String dvSwitchUuid; ManagedObjectReference dcMor = hyperHost.getHyperHostDatacenter(); @@ -2486,7 +2505,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return defaultVlan; } - private Pair prepareNetworkFromNicInfo(HostMO hostMo, NicTO nicTo) throws Exception { + private Pair prepareNetworkFromNicInfo(HostMO hostMo, NicTO nicTo, boolean configureVServiceInNexus) throws Exception { Pair switchName; TrafficType trafficType; VirtualSwitchType switchType; @@ -2516,7 +2535,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } else { networkInfo = HypervisorHostHelper.prepareNetwork(switchName.first(), namePrefix, hostMo, getVlanInfo(nicTo, switchName.second()), - nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _ops_timeout, switchType, _portsPerDvPortGroup); + nicTo.getNetworkRateMbps(), nicTo.getNetworkRateMulticastMbps(), _ops_timeout, switchType, _portsPerDvPortGroup, nicTo.getGateway(), configureVServiceInNexus); } return networkInfo; @@ -3006,7 +3025,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa NicTO[] nics = vm.getNics(); for (NicTO nic : nics) { // prepare network on the host - prepareNetworkFromNicInfo(new HostMO(getServiceContext(), _morHyperHost), nic); + prepareNetworkFromNicInfo(new HostMO(getServiceContext(), _morHyperHost), nic, false); } String secStoreUrl = mgr.getSecondaryStorageStoreUrl(Long.parseLong(_dcId)); diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java index 9c291491114..7e0ccbed39c 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java @@ -39,7 +39,7 @@ import org.apache.cloudstack.storage.command.CreatePrimaryDataStoreCmd; import org.apache.cloudstack.storage.command.CreateVolumeFromBaseImageCommand; import org.apache.cloudstack.storage.command.StorageSubSystemCommand; import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol; -import org.apache.cloudstack.storage.to.ImageOnPrimayDataStoreTO; +import org.apache.cloudstack.storage.to.ImageOnPrimaryDataStoreTO; import org.apache.cloudstack.storage.to.VolumeTO; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; @@ -207,7 +207,7 @@ public class XenServerStorageResource { protected Answer execute(CreateVolumeFromBaseImageCommand cmd) { VolumeTO volume = cmd.getVolume(); - ImageOnPrimayDataStoreTO baseImage = cmd.getImage(); + ImageOnPrimaryDataStoreTO baseImage = cmd.getImage(); Connection conn = hypervisorResource.getConnection(); try { diff --git a/plugins/network-elements/cisco-vnmc/pom.xml b/plugins/network-elements/cisco-vnmc/pom.xml new file mode 100644 index 00000000000..1ac6bd8d8c9 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + cloud-plugin-network-cisco-vnmc + Apache CloudStack Plugin - Cisco VNMC + + org.apache.cloudstack + cloudstack-plugins + 4.2.0-SNAPSHOT + ../../pom.xml + + + + org.apache.cloudstack + cloud-plugin-hypervisor-vmware + ${project.version} + + + org.apache.cloudstack + cloud-vmware-base + ${project.version} + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/assoc-asa1000v.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/assoc-asa1000v.xml new file mode 100644 index 00000000000..b0249db741b --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/assoc-asa1000v.xml @@ -0,0 +1,34 @@ + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/associate-acl-policy-set.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/associate-acl-policy-set.xml new file mode 100755 index 00000000000..e3113ae22c7 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/associate-acl-policy-set.xml @@ -0,0 +1,37 @@ + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/associate-dhcp-policy.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/associate-dhcp-policy.xml new file mode 100644 index 00000000000..e866f51e366 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/associate-dhcp-policy.xml @@ -0,0 +1,34 @@ + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/associate-dhcp-server.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/associate-dhcp-server.xml new file mode 100644 index 00000000000..930e4ec77a2 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/associate-dhcp-server.xml @@ -0,0 +1,32 @@ + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/associate-nat-policy-set.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/associate-nat-policy-set.xml new file mode 100644 index 00000000000..6d67c31c5d6 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/associate-nat-policy-set.xml @@ -0,0 +1,35 @@ + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/associate-route-policy.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/associate-route-policy.xml new file mode 100644 index 00000000000..8884a1b9686 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/associate-route-policy.xml @@ -0,0 +1,33 @@ + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-acl-policy-ref.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-acl-policy-ref.xml new file mode 100755 index 00000000000..c534c327194 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-acl-policy-ref.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-acl-policy-set.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-acl-policy-set.xml new file mode 100755 index 00000000000..b475d2ca564 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-acl-policy-set.xml @@ -0,0 +1,36 @@ + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-acl-policy.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-acl-policy.xml new file mode 100755 index 00000000000..e71cd429858 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-acl-policy.xml @@ -0,0 +1,35 @@ + + + + + + + + \ No newline at end of file diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-acl-rule-for-dnat.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-acl-rule-for-dnat.xml new file mode 100755 index 00000000000..5b6aaa3f59b --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-acl-rule-for-dnat.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-acl-rule-for-pf.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-acl-rule-for-pf.xml new file mode 100755 index 00000000000..1a1d9cbf3e2 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-acl-rule-for-pf.xml @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-dhcp-policy.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-dhcp-policy.xml new file mode 100644 index 00000000000..5bb4abcd8e1 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-dhcp-policy.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-dnat-rule.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-dnat-rule.xml new file mode 100755 index 00000000000..bd8dbff6d32 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-dnat-rule.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-profile.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-profile.xml new file mode 100644 index 00000000000..c4bdd026186 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-profile.xml @@ -0,0 +1,32 @@ + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-route-policy.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-route-policy.xml new file mode 100644 index 00000000000..69f4a5f7bfd --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-route-policy.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-route.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-route.xml new file mode 100644 index 00000000000..126c188f979 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-device-route.xml @@ -0,0 +1,35 @@ + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-firewall.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-firewall.xml new file mode 100644 index 00000000000..e5447e39e63 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-firewall.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-security-profile.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-security-profile.xml new file mode 100644 index 00000000000..e2f5eaf0686 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-edge-security-profile.xml @@ -0,0 +1,41 @@ + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-egress-acl-rule.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-egress-acl-rule.xml new file mode 100755 index 00000000000..930272ed8ee --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-egress-acl-rule.xml @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-generic-egress-acl-rule.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-generic-egress-acl-rule.xml new file mode 100755 index 00000000000..92c25043dad --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-generic-egress-acl-rule.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-generic-ingress-acl-rule.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-generic-ingress-acl-rule.xml new file mode 100755 index 00000000000..7c1164138bc --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-generic-ingress-acl-rule.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-ingress-acl-rule.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-ingress-acl-rule.xml new file mode 100755 index 00000000000..1af30b44416 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-ingress-acl-rule.xml @@ -0,0 +1,201 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-ip-pool.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-ip-pool.xml new file mode 100755 index 00000000000..4cf0451c33d --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-ip-pool.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-nat-policy-ref.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-nat-policy-ref.xml new file mode 100755 index 00000000000..450d40c9d6d --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-nat-policy-ref.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-nat-policy-set.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-nat-policy-set.xml new file mode 100644 index 00000000000..090caf15cb4 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-nat-policy-set.xml @@ -0,0 +1,37 @@ + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-nat-policy.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-nat-policy.xml new file mode 100755 index 00000000000..0b556f42a84 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-nat-policy.xml @@ -0,0 +1,33 @@ + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-pf-rule.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-pf-rule.xml new file mode 100755 index 00000000000..a8a631f5d7f --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-pf-rule.xml @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-port-pool.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-port-pool.xml new file mode 100755 index 00000000000..e1b7be024f7 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-port-pool.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-source-nat-pool.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-source-nat-pool.xml new file mode 100644 index 00000000000..2ad1e8798a5 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-source-nat-pool.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-source-nat-rule.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-source-nat-rule.xml new file mode 100644 index 00000000000..a3ee9875e19 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-source-nat-rule.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-tenant.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-tenant.xml new file mode 100644 index 00000000000..085b7a2e533 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-tenant.xml @@ -0,0 +1,29 @@ + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-vdc.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-vdc.xml new file mode 100644 index 00000000000..4cb805ecf7e --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/create-vdc.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-acl-policy-set.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-acl-policy-set.xml new file mode 100755 index 00000000000..2c5578659c7 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-acl-policy-set.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-acl-policy.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-acl-policy.xml new file mode 100755 index 00000000000..b1a27650419 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-acl-policy.xml @@ -0,0 +1,33 @@ + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-edge-firewall.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-edge-firewall.xml new file mode 100755 index 00000000000..992d6a1ab62 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-edge-firewall.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-edge-security-profile.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-edge-security-profile.xml new file mode 100755 index 00000000000..f394fe91d9e --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-edge-security-profile.xml @@ -0,0 +1,38 @@ + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-nat-policy-set.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-nat-policy-set.xml new file mode 100755 index 00000000000..3f4c08d747f --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-nat-policy-set.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-nat-policy.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-nat-policy.xml new file mode 100755 index 00000000000..6c3ed7b9f48 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-nat-policy.xml @@ -0,0 +1,33 @@ + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-rule.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-rule.xml new file mode 100755 index 00000000000..e56e9190496 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-rule.xml @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-tenant.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-tenant.xml new file mode 100755 index 00000000000..05bef9a2906 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-tenant.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-vdc.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-vdc.xml new file mode 100755 index 00000000000..fbc2312c208 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/delete-vdc.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/disassoc-asa1000v.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/disassoc-asa1000v.xml new file mode 100755 index 00000000000..448b65f0d53 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/disassoc-asa1000v.xml @@ -0,0 +1,30 @@ + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-acl-policies.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-acl-policies.xml new file mode 100755 index 00000000000..aec800e9f4a --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-acl-policies.xml @@ -0,0 +1,31 @@ + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-children.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-children.xml new file mode 100755 index 00000000000..f272999a76c --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-children.xml @@ -0,0 +1,27 @@ + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-nat-policies.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-nat-policies.xml new file mode 100755 index 00000000000..720ced06d8a --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-nat-policies.xml @@ -0,0 +1,31 @@ + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-policyrefs-in-policyset.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-policyrefs-in-policyset.xml new file mode 100755 index 00000000000..c53af90369d --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-policyrefs-in-policyset.xml @@ -0,0 +1,31 @@ + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-tenants.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-tenants.xml new file mode 100644 index 00000000000..63ae848b3e1 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-tenants.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-unassigned-asa1000v.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-unassigned-asa1000v.xml new file mode 100644 index 00000000000..539f330da8a --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/list-unassigned-asa1000v.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + diff --git a/plugins/network-elements/cisco-vnmc/scripts/network/cisco/login.xml b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/login.xml new file mode 100644 index 00000000000..8e1c435ea15 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/scripts/network/cisco/login.xml @@ -0,0 +1,20 @@ + + + diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/agent/api/AssociateAsaWithLogicalEdgeFirewallCommand.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/agent/api/AssociateAsaWithLogicalEdgeFirewallCommand.java new file mode 100755 index 00000000000..a438cbc0e59 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/agent/api/AssociateAsaWithLogicalEdgeFirewallCommand.java @@ -0,0 +1,53 @@ +// 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; + +/** + * Associates an ASA 1000v appliance with logical edge firewall in VNMC + */ +public class AssociateAsaWithLogicalEdgeFirewallCommand extends Command { + private long _vlanId; + private String _asaMgmtIp; + + public AssociateAsaWithLogicalEdgeFirewallCommand(long vlanId, String asaMgmtIp) { + super(); + this._vlanId = vlanId; + this._asaMgmtIp = asaMgmtIp; + } + + @Override + public boolean executeInSequence() { + return false; + } + + public long getVlanId() { + return _vlanId; + } + + public void setVlanId(long vlanId) { + this._vlanId = vlanId; + } + + public String getAsaMgmtIp() { + return _asaMgmtIp; + } + + public void setAsaMgmtIp(String asaMgmtIp) { + this._asaMgmtIp = asaMgmtIp; + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/agent/api/CleanupLogicalEdgeFirewallCommand.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/agent/api/CleanupLogicalEdgeFirewallCommand.java new file mode 100755 index 00000000000..c9f7f8c4c83 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/agent/api/CleanupLogicalEdgeFirewallCommand.java @@ -0,0 +1,43 @@ +// 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; + +/** + * Command for cleaning up logical edge firewall in VNMC + */ +public class CleanupLogicalEdgeFirewallCommand extends Command { + private long _vlanId; + + public CleanupLogicalEdgeFirewallCommand(long vlanId) { + super(); + this._vlanId = vlanId; + } + + @Override + public boolean executeInSequence() { + return false; + } + + public long getVlanId() { + return _vlanId; + } + + public void setVlanId(long vlanId) { + this._vlanId = vlanId; + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/agent/api/ConfigureNexusVsmForAsaCommand.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/agent/api/ConfigureNexusVsmForAsaCommand.java new file mode 100755 index 00000000000..b20ad1f2df6 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/agent/api/ConfigureNexusVsmForAsaCommand.java @@ -0,0 +1,95 @@ +// 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; + +/** + * Command for configuring n1kv VSM for asa1kv device. It does the following in VSM: + * a. creating vservice node for asa1kv + * b. updating vlan of inside port profile associated with asa1kv + */ +public class ConfigureNexusVsmForAsaCommand extends Command { + private long _vlanId; + private String _ipAddress; + private String _vsmUsername; + private String _vsmPassword; + private String _vsmIp; + private String _asaInPortProfile; + + public ConfigureNexusVsmForAsaCommand(long vlanId, String ipAddress, + String vsmUsername, String vsmPassword, String vsmIp, String asaInPortProfile) { + super(); + this._vlanId = vlanId; + this._ipAddress = ipAddress; + this._vsmUsername = vsmUsername; + this._vsmPassword = vsmPassword; + this._vsmIp = vsmIp; + this._asaInPortProfile = asaInPortProfile; + } + + @Override + public boolean executeInSequence() { + return false; + } + + public long getVlanId() { + return _vlanId; + } + + public void setVlanId(long _vlanId) { + this._vlanId = _vlanId; + } + + public String getIpAddress() { + return _ipAddress; + } + + public void setIpAddress(String _ipAddress) { + this._ipAddress = _ipAddress; + } + + public String getVsmUsername() { + return _vsmUsername; + } + + public void setVsmUsername(String _vsmUsername) { + this._vsmUsername = _vsmUsername; + } + + public String getVsmPassword() { + return _vsmPassword; + } + + public void setVsmPassword(String _vsmPassword) { + this._vsmPassword = _vsmPassword; + } + + public String getVsmIp() { + return _vsmIp; + } + + public void setVsmIp(String _vsmIp) { + this._vsmIp = _vsmIp; + } + + public String getAsaInPortProfile() { + return _asaInPortProfile; + } + + public void setAsaInPortProfile(String _asaInPortProfile) { + this._asaInPortProfile = _asaInPortProfile; + } +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/agent/api/CreateLogicalEdgeFirewallCommand.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/agent/api/CreateLogicalEdgeFirewallCommand.java new file mode 100755 index 00000000000..def8225acf1 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/agent/api/CreateLogicalEdgeFirewallCommand.java @@ -0,0 +1,94 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.api; + +import java.util.ArrayList; +import java.util.List; + +/** + * Command for creating a logical edge firewall in VNMC + */ +public class CreateLogicalEdgeFirewallCommand extends Command { + private long _vlanId; + private String _publicIp; + private String _internalIp; + private String _publicSubnet; + private String _internalSubnet; + private List _publicGateways; + + public CreateLogicalEdgeFirewallCommand(long vlanId, + String publicIp, String internalIp, + String publicSubnet, String internalSubnet) { + super(); + this._vlanId = vlanId; + this._publicIp = publicIp; + this._internalIp = internalIp; + this._publicSubnet = publicSubnet; + this.setInternalSubnet(internalSubnet); + _publicGateways = new ArrayList(); + } + + @Override + public boolean executeInSequence() { + return false; + } + + public long getVlanId() { + return _vlanId; + } + + public void setVlanId(long vlanId) { + this._vlanId = vlanId; + } + + public String getPublicIp() { + return _publicIp; + } + + public void setPublicIp(String publicIp) { + this._publicIp = publicIp; + } + + public String getInternalIp() { + return _internalIp; + } + + public void setInternalIp(String internalIp) { + this._internalIp = internalIp; + } + + public String getPublicSubnet() { + return _publicSubnet; + } + + public void setPublicSubnet(String publicSubnet) { + this._publicSubnet = publicSubnet; + } + + public String getInternalSubnet() { + return _internalSubnet; + } + + public void setInternalSubnet(String _internalSubnet) { + this._internalSubnet = _internalSubnet; + } + + public List getPublicGateways() { + return _publicGateways; + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/AddCiscoAsa1000vResourceCmd.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/AddCiscoAsa1000vResourceCmd.java new file mode 100755 index 00000000000..c880199f5c4 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/AddCiscoAsa1000vResourceCmd.java @@ -0,0 +1,116 @@ +// 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.api.commands; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ClusterResponse; +import org.apache.cloudstack.api.response.PhysicalNetworkResponse; +import org.apache.log4j.Logger; + +import com.cloud.api.response.CiscoAsa1000vResourceResponse; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.cisco.CiscoAsa1000vDevice; +import com.cloud.network.element.CiscoAsa1000vService; +import com.cloud.user.UserContext; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name="addCiscoAsa1000vResource", responseObject=CiscoAsa1000vResourceResponse.class, description="Adds a Cisco Asa 1000v appliance") +public class AddCiscoAsa1000vResourceCmd extends BaseCmd { + private static final Logger s_logger = Logger.getLogger(AddCiscoAsa1000vResourceCmd.class.getName()); + private static final String s_name = "addCiscoAsa1000vResource"; + @Inject CiscoAsa1000vService _ciscoAsa1000vService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.UUID, entityType = PhysicalNetworkResponse.class, required=true, description="the Physical Network ID") + private Long physicalNetworkId; + + @Parameter(name=ApiConstants.HOST_NAME, type=CommandType.STRING, required = true, description="Hostname or ip address of the Cisco ASA 1000v appliance.") + private String host; + + @Parameter(name=ApiConstants.ASA_INSIDE_PORT_PROFILE, type=CommandType.STRING, required = true, description="Nexus port profile associated with inside interface of ASA 1000v") + private String inPortProfile; + + @Parameter(name=ApiConstants.CLUSTER_ID, type=CommandType.UUID, entityType = ClusterResponse.class, required=true, description="the Cluster ID") + private Long clusterId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getPhysicalNetworkId() { + return physicalNetworkId; + } + + public String getManagementIp() { + return host; + } + + public String getInPortProfile() { + return inPortProfile; + } + + public Long getClusterId() { + return clusterId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { + try { + CiscoAsa1000vDevice ciscoAsa1000v = _ciscoAsa1000vService.addCiscoAsa1000vResource(this); + if (ciscoAsa1000v != null) { + CiscoAsa1000vResourceResponse response = _ciscoAsa1000vService.createCiscoAsa1000vResourceResponse(ciscoAsa1000v); + response.setObjectName("CiscoAsa1000vResource"); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add Cisco ASA 1000v appliance due to internal error."); + } + } catch (InvalidParameterValueException invalidParamExcp) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage()); + } catch (CloudRuntimeException runtimeExcp) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage()); + } + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return UserContext.current().getCaller().getId(); + } +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/AddCiscoVnmcResourceCmd.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/AddCiscoVnmcResourceCmd.java new file mode 100644 index 00000000000..bfd6db95434 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/AddCiscoVnmcResourceCmd.java @@ -0,0 +1,115 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.api.commands; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.PhysicalNetworkResponse; +import org.apache.log4j.Logger; + +import com.cloud.api.response.CiscoVnmcResourceResponse; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.cisco.CiscoVnmcController; +import com.cloud.network.element.CiscoVnmcElementService; +import com.cloud.user.UserContext; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name="addCiscoVnmcResource", responseObject=CiscoVnmcResourceResponse.class, description="Adds a Cisco Vnmc Controller") +public class AddCiscoVnmcResourceCmd extends BaseCmd { + private static final Logger s_logger = Logger.getLogger(AddCiscoVnmcResourceCmd.class.getName()); + private static final String s_name = "addCiscoVnmcResource"; + @Inject CiscoVnmcElementService _ciscoVnmcElementService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.UUID, entityType = PhysicalNetworkResponse.class, required=true, description="the Physical Network ID") + private Long physicalNetworkId; + + @Parameter(name=ApiConstants.HOST_NAME, type=CommandType.STRING, required = true, description="Hostname or ip address of the Cisco VNMC Controller.") + private String host; + + @Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="Credentials to access the Cisco VNMC Controller API") + private String username; + + @Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required = true, description="Credentials to access the Cisco VNMC Controller API") + private String password; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getPhysicalNetworkId() { + return physicalNetworkId; + } + + public String getHost() { + return host; + } + + public String getUsername() { + return username; + } + + public String getPassword() { + return password; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { + try { + CiscoVnmcController CiscoVnmcResourceVO = _ciscoVnmcElementService.addCiscoVnmcResource(this); + if (CiscoVnmcResourceVO != null) { + CiscoVnmcResourceResponse response = _ciscoVnmcElementService.createCiscoVnmcResourceResponse(CiscoVnmcResourceVO); + response.setObjectName("CiscoVnmcResource"); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add Cisco VNMC controller due to internal error."); + } + } catch (InvalidParameterValueException invalidParamExcp) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage()); + } catch (CloudRuntimeException runtimeExcp) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage()); + } + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return UserContext.current().getCaller().getId(); + } +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/DeleteCiscoAsa1000vResourceCmd.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/DeleteCiscoAsa1000vResourceCmd.java new file mode 100755 index 00000000000..d4f86fa527a --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/DeleteCiscoAsa1000vResourceCmd.java @@ -0,0 +1,93 @@ +// 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.api.commands; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.log4j.Logger; + +import com.cloud.api.response.CiscoAsa1000vResourceResponse; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.element.CiscoAsa1000vService; +import com.cloud.user.UserContext; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name="deleteCiscoAsa1000vResource", responseObject=SuccessResponse.class, description="Deletes a Cisco ASA 1000v appliance") +public class DeleteCiscoAsa1000vResourceCmd extends BaseCmd { + private static final Logger s_logger = Logger.getLogger(DeleteCiscoAsa1000vResourceCmd.class.getName()); + private static final String s_name = "deleteCiscoAsa1000vResource"; + @Inject CiscoAsa1000vService _ciscoAsa1000vService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.RESOURCE_ID, type=CommandType.UUID, required=true, entityType=CiscoAsa1000vResourceResponse.class, description="Cisco ASA 1000v resource ID") + private Long ciscoAsa1000vResourceId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getCiscoAsa1000vResourceId() { + return ciscoAsa1000vResourceId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { + try { + boolean result = _ciscoAsa1000vService.deleteCiscoAsa1000vResource(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete Cisco ASA 1000v appliance."); + } + } catch (InvalidParameterValueException invalidParamExcp) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage()); + } catch (CloudRuntimeException runtimeExcp) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage()); + } + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return UserContext.current().getCaller().getId(); + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/DeleteCiscoVnmcResourceCmd.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/DeleteCiscoVnmcResourceCmd.java new file mode 100644 index 00000000000..d2a37202f0a --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/DeleteCiscoVnmcResourceCmd.java @@ -0,0 +1,93 @@ +// 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.api.commands; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.SuccessResponse; +import org.apache.log4j.Logger; + +import com.cloud.api.response.CiscoVnmcResourceResponse; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.element.CiscoVnmcElementService; +import com.cloud.user.UserContext; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name="deleteCiscoVnmcResource", responseObject=SuccessResponse.class, description="Deletes a Cisco Vnmc controller") +public class DeleteCiscoVnmcResourceCmd extends BaseCmd { + private static final Logger s_logger = Logger.getLogger(DeleteCiscoVnmcResourceCmd.class.getName()); + private static final String s_name = "deleteCiscoVnmcResource"; + @Inject CiscoVnmcElementService _ciscoVnmcElementService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.RESOURCE_ID, type=CommandType.UUID, required=true, entityType=CiscoVnmcResourceResponse.class, description="Cisco Vnmc resource ID") + private Long ciscoVnmcResourceId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getCiscoVnmcResourceId() { + return ciscoVnmcResourceId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { + try { + boolean result = _ciscoVnmcElementService.deleteCiscoVnmcResource(this); + if (result) { + SuccessResponse response = new SuccessResponse(getCommandName()); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to delete Cisco Vnmc resource."); + } + } catch (InvalidParameterValueException invalidParamExcp) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage()); + } catch (CloudRuntimeException runtimeExcp) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage()); + } + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return UserContext.current().getCaller().getId(); + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/ListCiscoAsa1000vResourcesCmd.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/ListCiscoAsa1000vResourcesCmd.java new file mode 100755 index 00000000000..509d39fb5f9 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/ListCiscoAsa1000vResourcesCmd.java @@ -0,0 +1,110 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.api.commands; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.PhysicalNetworkResponse; +import org.apache.log4j.Logger; + +import com.cloud.api.response.CiscoAsa1000vResourceResponse; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.cisco.CiscoAsa1000vDevice; +import com.cloud.network.cisco.CiscoAsa1000vDeviceVO; +import com.cloud.network.element.CiscoAsa1000vService; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name="listCiscoAsa1000vResources", responseObject=CiscoAsa1000vResourceResponse.class, description="Lists Cisco ASA 1000v appliances") +public class ListCiscoAsa1000vResourcesCmd extends BaseListCmd { + private static final Logger s_logger = Logger.getLogger(ListCiscoAsa1000vResourcesCmd.class.getName()); + private static final String s_name = "listCiscoAsa1000vResources"; + @Inject CiscoAsa1000vService _ciscoAsa1000vService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.UUID, entityType = PhysicalNetworkResponse.class, description="the Physical Network ID") + private Long physicalNetworkId; + + @Parameter(name=ApiConstants.RESOURCE_ID, type=CommandType.UUID, entityType=CiscoAsa1000vResourceResponse.class, description="Cisco ASA 1000v resource ID") + private Long ciscoAsa1000vResourceId; + + @Parameter(name=ApiConstants.HOST_NAME, type=CommandType.STRING, description="Hostname or ip address of the Cisco ASA 1000v appliance.") + private String host; + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getCiscoAsa1000vResourceId() { + return ciscoAsa1000vResourceId; + } + + public Long getPhysicalNetworkId() { + return physicalNetworkId; + } + + public String getManagementIp() { + return host; + } + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { + try { + List ciscoAsa1000vDevices = _ciscoAsa1000vService.listCiscoAsa1000vResources(this); + ListResponse response = new ListResponse(); + List ciscoAsa1000vResourcesResponse = new ArrayList(); + + if (ciscoAsa1000vDevices != null && !ciscoAsa1000vDevices.isEmpty()) { + for (CiscoAsa1000vDevice ciscoAsa1000vDeviceVO : ciscoAsa1000vDevices) { + CiscoAsa1000vResourceResponse ciscoAsa1000vResourceResponse = _ciscoAsa1000vService.createCiscoAsa1000vResourceResponse(ciscoAsa1000vDeviceVO); + ciscoAsa1000vResourcesResponse.add(ciscoAsa1000vResourceResponse); + } + } + + response.setResponses(ciscoAsa1000vResourcesResponse); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } catch (InvalidParameterValueException invalidParamExcp) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage()); + } catch (CloudRuntimeException runtimeExcp) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage()); + } + } + + @Override + public String getCommandName() { + return s_name; + } +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/ListCiscoVnmcResourcesCmd.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/ListCiscoVnmcResourcesCmd.java new file mode 100644 index 00000000000..ab553ee94ac --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/commands/ListCiscoVnmcResourcesCmd.java @@ -0,0 +1,106 @@ +// 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.api.commands; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.PhysicalNetworkResponse; +import org.apache.log4j.Logger; + +import com.cloud.api.response.CiscoVnmcResourceResponse; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.cisco.CiscoVnmcController; +import com.cloud.network.cisco.CiscoVnmcControllerVO; +import com.cloud.network.element.CiscoVnmcElementService; +import com.cloud.utils.exception.CloudRuntimeException; + +@APICommand(name="listCiscoVnmcResources", responseObject=CiscoVnmcResourceResponse.class, description="Lists Cisco VNMC controllers") +public class ListCiscoVnmcResourcesCmd extends BaseListCmd { + private static final Logger s_logger = Logger.getLogger(ListCiscoVnmcResourcesCmd.class.getName()); + private static final String s_name = "listCiscoVnmcResources"; + @Inject CiscoVnmcElementService _ciscoVnmcElementService; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.UUID, entityType = PhysicalNetworkResponse.class, description="the Physical Network ID") + private Long physicalNetworkId; + + @Parameter(name=ApiConstants.RESOURCE_ID, type=CommandType.UUID, entityType=CiscoVnmcResourceResponse.class, description="Cisco VNMC resource ID") + private Long ciscoVnmcResourceId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getCiscoVnmcResourceId() { + return ciscoVnmcResourceId; + } + + public Long getPhysicalNetworkId() { + return physicalNetworkId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException { + try { + List CiscoVnmcResources = _ciscoVnmcElementService.listCiscoVnmcResources(this); + ListResponse response = new ListResponse(); + List CiscoVnmcResourcesResponse = new ArrayList(); + + if (CiscoVnmcResources != null && !CiscoVnmcResources.isEmpty()) { + for (CiscoVnmcController CiscoVnmcResourceVO : CiscoVnmcResources) { + CiscoVnmcResourceResponse CiscoVnmcResourceResponse = _ciscoVnmcElementService.createCiscoVnmcResourceResponse(CiscoVnmcResourceVO); + CiscoVnmcResourcesResponse.add(CiscoVnmcResourceResponse); + } + } + + response.setResponses(CiscoVnmcResourcesResponse); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } catch (InvalidParameterValueException invalidParamExcp) { + throw new ServerApiException(ApiErrorCode.PARAM_ERROR, invalidParamExcp.getMessage()); + } catch (CloudRuntimeException runtimeExcp) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, runtimeExcp.getMessage()); + } + } + + @Override + public String getCommandName() { + return s_name; + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/api/response/CiscoAsa1000vResourceResponse.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/response/CiscoAsa1000vResourceResponse.java new file mode 100755 index 00000000000..9cd87da66a1 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/response/CiscoAsa1000vResourceResponse.java @@ -0,0 +1,88 @@ +// 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.api.response; + + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.NetworkResponse; +import org.apache.cloudstack.api.response.PhysicalNetworkResponse; + +import com.cloud.network.cisco.CiscoAsa1000vDevice; +import com.google.gson.annotations.SerializedName; + +@EntityReference(value = CiscoAsa1000vDevice.class) +public class CiscoAsa1000vResourceResponse extends BaseResponse { + public static final String RESOURCE_NAME = "resourcename"; + + @SerializedName(ApiConstants.RESOURCE_ID) @Parameter(description="resource id of the Cisco ASA 1000v appliance") + private String id; + + @SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) + @Parameter(description="the physical network to which this ASA 1000v belongs to", entityType = PhysicalNetworkResponse.class) + private Long physicalNetworkId ; + + public Long getPhysicalNetworkId() { + return physicalNetworkId; + } + + @SerializedName(ApiConstants.HOST_NAME) + @Parameter(description="management ip address of ASA 1000v") + private String managementIp; + + public String getManagementIp() { + return managementIp; + } + + @SerializedName(ApiConstants.ASA_INSIDE_PORT_PROFILE) + @Parameter(description="management ip address of ASA 1000v") + private String inPortProfile; + + public String getInPortProfile() { + return inPortProfile; + } + + @SerializedName(ApiConstants.NETWORK_ID) + @Parameter(description="the guest network to which ASA 1000v is associated", entityType = NetworkResponse.class) + private Long guestNetworkId; + + public Long getGuestNetworkId() { + return guestNetworkId; + } + + public void setId(String ciscoAsa1000vResourceId) { + this.id = ciscoAsa1000vResourceId; + } + + public void setPhysicalNetworkId(Long physicalNetworkId) { + this.physicalNetworkId = physicalNetworkId; + } + + public void setManagementIp(String managementIp) { + this.managementIp = managementIp; + } + + public void setInPortProfile(String inPortProfile) { + this.inPortProfile = inPortProfile; + } + + public void setGuestNetworkId(Long guestNetworkId) { + this.guestNetworkId = guestNetworkId; + } +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/api/response/CiscoVnmcResourceResponse.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/response/CiscoVnmcResourceResponse.java new file mode 100644 index 00000000000..f5c9b727f8f --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/api/response/CiscoVnmcResourceResponse.java @@ -0,0 +1,75 @@ +// 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.api.response; + + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.PhysicalNetworkResponse; + +import com.cloud.network.cisco.CiscoVnmcController; +import com.google.gson.annotations.SerializedName; +@EntityReference(value = CiscoVnmcController.class) +public class CiscoVnmcResourceResponse extends BaseResponse { + public static final String RESOURCE_NAME = "resourcename"; + + @SerializedName(ApiConstants.RESOURCE_ID) + @Parameter(description="resource id of the Cisco VNMC controller") + private String id; + + @SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) + @Parameter(description="the physical network to which this VNMC belongs to", entityType = PhysicalNetworkResponse.class) + private Long physicalNetworkId; + + public Long getPhysicalNetworkId() { + return physicalNetworkId; + } + + public String getProviderName() { + return providerName; + } + + public String getResourceName() { + return resourceName; + } + + @SerializedName(ApiConstants.PROVIDER) @Parameter(description="name of the provider") + private String providerName; + + @SerializedName(RESOURCE_NAME) + @Parameter(description="Cisco VNMC resource name") + private String resourceName; + + public void setId(String ciscoVnmcResourceId) { + this.id = ciscoVnmcResourceId; + } + + public void setPhysicalNetworkId(Long physicalNetworkId) { + this.physicalNetworkId = physicalNetworkId; + } + + public void setProviderName(String providerName) { + this.providerName = providerName; + } + + public void setResourceName(String resourceName) { + this.resourceName = resourceName; + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoAsa1000vDevice.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoAsa1000vDevice.java new file mode 100755 index 00000000000..3c5f6827718 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoAsa1000vDevice.java @@ -0,0 +1,39 @@ +// 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.cisco; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +import com.cloud.org.Grouping; + +public interface CiscoAsa1000vDevice extends Grouping, InternalIdentity, Identity { + + long getId(); + + String getUuid(); + + void setUuid(String uuid); + + long getPhysicalNetworkId(); + + String getManagementIp(); + + String getInPortProfile(); + + long getClusterId(); +} \ No newline at end of file diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoAsa1000vDeviceVO.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoAsa1000vDeviceVO.java new file mode 100755 index 00000000000..ba85fb105c8 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoAsa1000vDeviceVO.java @@ -0,0 +1,101 @@ +// 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.cisco; + +import java.util.UUID; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name="external_cisco_asa1000v_devices") +public class CiscoAsa1000vDeviceVO implements CiscoAsa1000vDevice { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="uuid") + private String uuid; + + @Column(name="physical_network_id") + private long physicalNetworkId; + + @Column(name="management_ip") + private String managementIp; + + @Column(name="in_Port_profile") + private String inPortProfile; + + @Column(name="cluster_id") + private long clusterId; + + public CiscoAsa1000vDeviceVO() { + this.uuid = UUID.randomUUID().toString(); + } + + public CiscoAsa1000vDeviceVO(long physicalNetworkId, + String managementIp, String inPortProfile, long clusterId) { + super(); + this.physicalNetworkId = physicalNetworkId; + this.managementIp = managementIp; + this.inPortProfile = inPortProfile; + this.uuid = UUID.randomUUID().toString(); + this.clusterId = clusterId; + } + + @Override + public long getId() { + return id; + } + + @Override + public String getUuid() { + return uuid; + } + + @Override + public void setUuid(String uuid) { + this.uuid = uuid; + } + + @Override + public long getPhysicalNetworkId() { + return physicalNetworkId; + } + + @Override + public String getManagementIp() { + return managementIp; + } + + @Override + public String getInPortProfile() { + return inPortProfile; + } + + @Override + public long getClusterId() { + return clusterId; + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnection.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnection.java new file mode 100644 index 00000000000..f137148ab48 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnection.java @@ -0,0 +1,196 @@ +// 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.cisco; + +import java.util.Map; + +import com.cloud.utils.exception.ExecutionException; + +public interface CiscoVnmcConnection { + + public boolean createTenant(String tenantName) throws ExecutionException; + + public boolean deleteTenant(String tenantName) throws ExecutionException; + + public boolean createTenantVDC(String tenantName) throws ExecutionException; + + public boolean deleteTenantVDC(String tenantName) throws ExecutionException; + + public boolean createTenantVDCEdgeDeviceProfile(String tenantName) + throws ExecutionException; + + public boolean createTenantVDCEdgeStaticRoutePolicy(String tenantName) + throws ExecutionException; + + public boolean createTenantVDCEdgeStaticRoute(String tenantName, + String nextHopIp, String destination, String netmask) throws ExecutionException; + + public boolean associateTenantVDCEdgeStaticRoutePolicy(String tenantName) + throws ExecutionException; + + public boolean associateTenantVDCEdgeDhcpPolicy(String tenantName, + String intfName) throws ExecutionException; + + public boolean createTenantVDCEdgeDhcpPolicy(String tenantName, + String startIp, String endIp, String subnet, String nameServerIp, + String domain) throws ExecutionException; + + public boolean associateTenantVDCEdgeDhcpServerPolicy(String tenantName, + String intfName) throws ExecutionException; + + public boolean createTenantVDCEdgeSecurityProfile(String tenantName) + throws ExecutionException; + + public boolean deleteTenantVDCEdgeSecurityProfile(String tenantName) + throws ExecutionException; + + public boolean createTenantVDCSourceNatIpPool(String tenantName, String identifier, + String publicIp) throws ExecutionException; + + public boolean createTenantVDCSourceNatRule(String tenantName, String identifier, + String startSourceIp, String endSourceIp) throws ExecutionException; + + public boolean createTenantVDCSourceNatPolicy(String tenantName, String identifier) + throws ExecutionException; + + public boolean createTenantVDCSourceNatPolicyRef(String tenantName, String identifier) + throws ExecutionException; + + public boolean createTenantVDCDNatIpPool(String tenantName, String identifier, + String ipAddress) throws ExecutionException; + + public boolean createTenantVDCDNatRule(String tenantName, + String identifier, String policyIdentifier, + String publicIp) + throws ExecutionException; + + public boolean deleteTenantVDCDNatRule(String tenantName, + String identifier, String policyIdentifier) + throws ExecutionException; + + public boolean createTenantVDCAclRuleForDNat(String tenantName, + String identifier, String policyIdentifier, + String ipAddress) + throws ExecutionException; + + public boolean createTenantVDCDNatPolicy(String tenantName, String identifier) + throws ExecutionException; + + public boolean deleteTenantVDCDNatPolicy(String tenantName, String identifier) + throws ExecutionException; + + public boolean createTenantVDCDNatPolicyRef(String tenantName, String identifier) + throws ExecutionException; + + public boolean createTenantVDCPFPortPool(String tenantName, String identifier, + String startPort, String endPort) + throws ExecutionException; + + public boolean createTenantVDCPFIpPool(String tenantName, String identifier, + String ipAddress) throws ExecutionException; + + public boolean createTenantVDCPFRule(String tenantName, + String identifier, String policyIdentifier, + String protocol, String publicIp, + String startPort, String endPort) + throws ExecutionException; + + public boolean deleteTenantVDCPFRule(String tenantName, + String identifier, String policyIdentifier) + throws ExecutionException; + + public boolean createTenantVDCAclRuleForPF(String tenantName, + String identifier, String policyIdentifier, + String protocol, String ipAddress, + String startPort, String endPort) + throws ExecutionException; + + public boolean createTenantVDCPFPolicy(String tenantName, String identifier) + throws ExecutionException; + + public boolean deleteTenantVDCPFPolicy(String tenantName, String identifier) + throws ExecutionException; + + public boolean createTenantVDCPFPolicyRef(String tenantName, String identifier) + throws ExecutionException; + + public boolean createTenantVDCNatPolicySet(String tenantName) + throws ExecutionException; + + public boolean deleteTenantVDCNatPolicySet(String tenantName) + throws ExecutionException; + + public boolean associateNatPolicySet(String tenantName) + throws ExecutionException; + + public boolean createTenantVDCIngressAclRule(String tenantName, + String identifier, String policyIdentifier, + String protocol, String sourceStartIp, String sourceEndIp, + String destStartPort, String destEndPort, String destIp) + throws ExecutionException; + + public boolean createTenantVDCIngressAclRule(String tenantName, + String identifier, String policyIdentifier, + String protocol, String sourceStartIp, String sourceEndIp, String destIp) + throws ExecutionException; + + public boolean createTenantVDCEgressAclRule(String tenantName, + String identifier, String policyIdentifier, + String protocol, String sourceStartPort, String sourceEndPort, String sourceIp, + String destStartIp, String destEndIp) + throws ExecutionException; + + public boolean createTenantVDCEgressAclRule(String tenantName, + String identifier, String policyIdentifier, + String protocol, String sourceIp, String destStartIp, String destEndIp) + throws ExecutionException; + + public boolean deleteTenantVDCAclRule(String tenantName, + String identifier, String policyIdentifier) throws ExecutionException; + + public boolean createTenantVDCAclPolicy(String tenantName, + String identifier) throws ExecutionException; + + public boolean createTenantVDCAclPolicyRef(String tenantName, String identifier, + boolean ingress) throws ExecutionException; + + public boolean deleteTenantVDCAclPolicy(String tenantName, String identifier) + throws ExecutionException; + + public boolean createTenantVDCAclPolicySet(String tenantName, boolean ingress) + throws ExecutionException; + + public boolean deleteTenantVDCAclPolicySet(String tenantName, boolean ingress) + throws ExecutionException; + + public boolean associateAclPolicySet(String tenantName) + throws ExecutionException; + + public boolean createEdgeFirewall(String tenantName, String publicIp, + String insideIp, String publicSubnet, String insideSubnet) + throws ExecutionException; + + public boolean deleteEdgeFirewall(String tenantName) throws ExecutionException; + + public Map listUnAssocAsa1000v() throws ExecutionException; + + public boolean assignAsa1000v(String tenantName, String firewallDn) + throws ExecutionException; + + public boolean unassignAsa1000v(String tenantName, String firewallDn) + throws ExecutionException; +} \ No newline at end of file diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnectionImpl.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnectionImpl.java new file mode 100644 index 00000000000..527fb04698e --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcConnectionImpl.java @@ -0,0 +1,1415 @@ +// 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.cisco; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.log4j.Logger; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; + +import com.cloud.utils.exception.ExecutionException; +import com.cloud.utils.script.Script; + +public class CiscoVnmcConnectionImpl implements CiscoVnmcConnection { + + private String _ip; + private String _username; + private String _password; + private String _cookie; + + private final Logger s_logger = Logger.getLogger(CiscoVnmcConnectionImpl.class); + + private enum VnmcXml { + LOGIN("login.xml", "mgmt-controller"), + + CREATE_TENANT("create-tenant.xml", "service-reg"), + DELETE_TENANT("delete-tenant.xml", "service-reg"), + CREATE_VDC("create-vdc.xml", "service-reg"), + DELETE_VDC("delete-vdc.xml", "service-reg"), + + CREATE_EDGE_DEVICE_PROFILE("create-edge-device-profile.xml", "policy-mgr"), + CREATE_EDGE_ROUTE_POLICY("create-edge-device-route-policy.xml", "policy-mgr"), + CREATE_EDGE_ROUTE("create-edge-device-route.xml", "policy-mgr"), + RESOLVE_EDGE_ROUTE_POLICY("associate-route-policy.xml", "policy-mgr"), + + CREATE_DHCP_POLICY("create-dhcp-policy.xml", "policy-mgr"), + RESOLVE_EDGE_DHCP_POLICY("associate-dhcp-policy.xml", "policy-mgr"), + RESOLVE_EDGE_DHCP_SERVER_POLICY("associate-dhcp-server.xml", "policy-mgr"), + + CREATE_EDGE_SECURITY_PROFILE("create-edge-security-profile.xml", "policy-mgr"), + DELETE_EDGE_SECURITY_PROFILE("delete-edge-security-profile.xml", "policy-mgr"), + + CREATE_NAT_POLICY_SET("create-nat-policy-set.xml", "policy-mgr"), + DELETE_NAT_POLICY_SET("delete-nat-policy-set.xml", "policy-mgr"), + RESOLVE_NAT_POLICY_SET("associate-nat-policy-set.xml", "policy-mgr"), + CREATE_NAT_POLICY("create-nat-policy.xml", "policy-mgr"), + DELETE_NAT_POLICY("delete-nat-policy.xml", "policy-mgr"), + LIST_NAT_POLICIES("list-nat-policies.xml", "policy-mgr"), + CREATE_NAT_POLICY_REF("create-nat-policy-ref.xml", "policy-mgr"), + CREATE_PORT_POOL("create-port-pool.xml", "policy-mgr"), + CREATE_IP_POOL("create-ip-pool.xml", "policy-mgr"), + + CREATE_PF_RULE("create-pf-rule.xml", "policy-mgr"), + CREATE_ACL_RULE_FOR_PF("create-acl-rule-for-pf.xml", "policy-mgr"), + CREATE_DNAT_RULE("create-dnat-rule.xml", "policy-mgr"), + CREATE_ACL_RULE_FOR_DNAT("create-acl-rule-for-dnat.xml", "policy-mgr"), + CREATE_SOURCE_NAT_RULE("create-source-nat-rule.xml", "policy-mgr"), + + CREATE_ACL_POLICY_SET("create-acl-policy-set.xml", "policy-mgr"), + DELETE_ACL_POLICY_SET("delete-acl-policy-set.xml", "policy-mgr"), + RESOLVE_ACL_POLICY_SET("associate-acl-policy-set.xml", "policy-mgr"), + CREATE_ACL_POLICY("create-acl-policy.xml", "policy-mgr"), + DELETE_ACL_POLICY("delete-acl-policy.xml", "policy-mgr"), + LIST_ACL_POLICIES("list-acl-policies.xml", "policy-mgr"), + CREATE_ACL_POLICY_REF("create-acl-policy-ref.xml", "policy-mgr"), + CREATE_INGRESS_ACL_RULE("create-ingress-acl-rule.xml", "policy-mgr"), + CREATE_EGRESS_ACL_RULE("create-egress-acl-rule.xml", "policy-mgr"), + CREATE_GENERIC_INGRESS_ACL_RULE("create-generic-ingress-acl-rule.xml", "policy-mgr"), + CREATE_GENERIC_EGRESS_ACL_RULE("create-generic-egress-acl-rule.xml", "policy-mgr"), + + DELETE_RULE("delete-rule.xml", "policy-mgr"), + + LIST_CHILDREN("list-children.xml", "policy-mgr"), + + CREATE_EDGE_FIREWALL("create-edge-firewall.xml", "resource-mgr"), + DELETE_EDGE_FIREWALL("delete-edge-firewall.xml", "resource-mgr"), + + LIST_UNASSOC_ASA1000V("list-unassigned-asa1000v.xml", "resource-mgr"), + ASSIGN_ASA1000V("assoc-asa1000v.xml", "resource-mgr"), + UNASSIGN_ASA1000V("disassoc-asa1000v.xml", "resource-mgr"); + + private String scriptsDir = "scripts/network/cisco"; + private String xml; + private String service; + private final Logger s_logger = Logger.getLogger(CiscoVnmcConnectionImpl.class); + + + private VnmcXml(String filename, String service) { + this.xml = getXml(filename); + this.service = service; + } + + public String getXml() { + return xml; + } + + private String getXml(String filename) { + try { + String xmlFilePath = Script.findScript(scriptsDir, filename); + + if (xmlFilePath == null) { + throw new Exception("Failed to find Cisco VNMC XML file: " + filename); + } + + FileReader fr = new FileReader(xmlFilePath); + BufferedReader br = new BufferedReader(fr); + + String xml = ""; + String line; + while ((line = br.readLine()) != null) { + //xml += line.replaceAll("\n"," "); + xml += line; + } + + return xml; + } catch (Exception e) { + s_logger.debug(e); + return null; + } + } + + public String getService() { + return service; + } + } + + public CiscoVnmcConnectionImpl(String hostIp, String userName, String password) { + this._ip = hostIp; + this._username = userName; + this._password = password; + + } + + public boolean login() throws ExecutionException { + String xml = VnmcXml.LOGIN.getXml(); + String service = VnmcXml.LOGIN.getService(); + xml = replaceXmlValue(xml, "username", _username); + xml = replaceXmlValue(xml, "password", _password); + String response = sendRequest(service, xml); + Map checked = checkResponse(response, "outCookie", "errorCode", "response"); + + if (checked.get("errorCode") != null) + return false; + _cookie = checked.get("outCookie"); + if (_cookie == null) { + return false; + } + return true; + } + + private String getDnForTenant(String tenantName) { + return "org-root/org-" + tenantName; + } + + private String getDnForTenantVDC(String tenantName) { + return getDnForTenant(tenantName) + "/org-VDC-" + tenantName; + } + + private String getDnForTenantVDCEdgeDeviceProfile(String tenantName) { + return getDnForTenantVDC(tenantName) + "/edsp-" + getNameForEdgeDeviceServiceProfile(tenantName); + } + + private String getDnForTenantVDCEdgeSecurityProfile(String tenantName) { + return getDnForTenantVDC(tenantName) + "/vnep-" + getNameForEdgeDeviceSecurityProfile(tenantName); + } + + private String getDnForEdgeDeviceRoutingPolicy(String tenantName) { + return getDnForTenantVDC(tenantName) + "/routing-policy-" + getNameForEdgeDeviceRoutePolicy(tenantName); + //FIXME: any other construct is unreliable. why? + } + + private String getDnForDhcpPolicy(String tenantName, String intfName) { + return getDnForTenantVDCEdgeDeviceProfile(tenantName) + "/dhcp-" + intfName; + } + + private String getNameForDhcpPolicy(String tenantName) { + return tenantName + "-Dhcp-Policy"; + } + + private String getNameForDhcpServer(String tenantName) { + return tenantName + "-Dhcp-Server"; + } + + private String getDnForDhcpServerPolicy(String tenantName) { + return getDnForTenantVDC(tenantName) + "/dhcp-server-" + getNameForDhcpPolicy(tenantName); + } + + private String getNameForIpRange() { + return "iprange"; + } + + private String getDnForDhcpIpRange(String tenantName) { + return getDnForDhcpServerPolicy(tenantName) + "/ip-range-" + getNameForIpRange(); + } + + private String getNameForDNSService(String tenantName) { + return tenantName + "-DNS"; + } + + private String getDnForDnsService(String tenantName) { + return getDnForDhcpServerPolicy(tenantName) + "/dns-svc-" + getNameForDNSService(tenantName); + } + + private String getDnForDnsServer(String tenantName, String dnsip) { + return getDnForDnsService(tenantName) + "/dns-" + dnsip; + } + + private String getNameForTenantVDC(String tenantName) { + return "VDC-" + tenantName; + } + + private String getNameForEdgeDeviceServiceProfile(String tenantName) { + return "EDSP-" + tenantName; + } + + private String getNameForEdgeDeviceSecurityProfile(String tenantName) { + return "ESP-" + tenantName; + } + + private String getNameForEdgeDeviceRoutePolicy(String tenantName) { + return "EDSP-" + tenantName + "-Routes"; + } + + @Override + public boolean createTenant(String tenantName) throws ExecutionException { + String xml = VnmcXml.CREATE_TENANT.getXml(); + String service = VnmcXml.CREATE_TENANT.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "descr", "Tenant for account " + tenantName); + xml = replaceXmlValue(xml, "name", tenantName); + xml = replaceXmlValue(xml, "dn", getDnForTenant(tenantName)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean deleteTenant(String tenantName) throws ExecutionException { + String xml = VnmcXml.DELETE_TENANT.getXml(); + String service = VnmcXml.DELETE_TENANT.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "name", tenantName); + xml = replaceXmlValue(xml, "dn", getDnForTenant(tenantName)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean createTenantVDC(String tenantName) throws ExecutionException { + String xml = VnmcXml.CREATE_VDC.getXml(); + String service = VnmcXml.CREATE_VDC.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "descr", "VDC for Tenant" + tenantName); + xml = replaceXmlValue(xml, "name", getNameForTenantVDC(tenantName)); + xml = replaceXmlValue(xml, "dn", getDnForTenantVDC(tenantName)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean deleteTenantVDC(String tenantName) throws ExecutionException { + String xml = VnmcXml.DELETE_VDC.getXml(); + String service = VnmcXml.DELETE_VDC.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "name", getNameForTenantVDC(tenantName)); + xml = replaceXmlValue(xml, "dn", getDnForTenantVDC(tenantName)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean createTenantVDCEdgeDeviceProfile(String tenantName) throws ExecutionException { + String xml = VnmcXml.CREATE_EDGE_DEVICE_PROFILE.getXml(); + String service = VnmcXml.CREATE_EDGE_DEVICE_PROFILE.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "descr", "Edge Device Profile for Tenant VDC" + tenantName); + xml = replaceXmlValue(xml, "name", getNameForEdgeDeviceServiceProfile(tenantName)); + xml = replaceXmlValue(xml, "dn", getDnForTenantVDCEdgeDeviceProfile(tenantName)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean createTenantVDCEdgeStaticRoutePolicy(String tenantName) throws ExecutionException { + String xml = VnmcXml.CREATE_EDGE_ROUTE_POLICY.getXml(); + String service = VnmcXml.CREATE_EDGE_ROUTE_POLICY.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "name", getNameForEdgeDeviceRoutePolicy(tenantName)); + xml = replaceXmlValue(xml, "routepolicydn", getDnForEdgeDeviceRoutingPolicy(tenantName)); + xml = replaceXmlValue(xml, "descr", "Routing Policy for Edge Device for Tenant " + tenantName); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean createTenantVDCEdgeStaticRoute(String tenantName, + String nextHopIp, String destination, String netmask) throws ExecutionException { + String xml = VnmcXml.CREATE_EDGE_ROUTE.getXml(); + String service = VnmcXml.CREATE_EDGE_ROUTE.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "routepolicydn", getDnForEdgeDeviceRoutingPolicy(tenantName)); + xml = replaceXmlValue(xml, "nexthop", nextHopIp); + xml = replaceXmlValue(xml, "nexthopintf", getNameForEdgeOutsideIntf(tenantName)); + xml = replaceXmlValue(xml, "destination", destination); + xml = replaceXmlValue(xml, "netmask", netmask); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean associateTenantVDCEdgeStaticRoutePolicy(String tenantName) throws ExecutionException { + String xml = VnmcXml.RESOLVE_EDGE_ROUTE_POLICY.getXml(); + String service = VnmcXml.RESOLVE_EDGE_ROUTE_POLICY.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "name", getNameForEdgeDeviceServiceProfile(tenantName)); + xml = replaceXmlValue(xml, "dn", getDnForTenantVDCEdgeDeviceProfile(tenantName)); + xml = replaceXmlValue(xml, "routepolicyname", getNameForEdgeDeviceRoutePolicy(tenantName)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean associateTenantVDCEdgeDhcpPolicy(String tenantName, String intfName) throws ExecutionException { + String xml = VnmcXml.RESOLVE_EDGE_DHCP_POLICY.getXml(); + String service = VnmcXml.RESOLVE_EDGE_DHCP_POLICY.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "dhcpdn", getDnForDhcpPolicy(tenantName, intfName)); + xml = replaceXmlValue(xml, "insideintf", intfName); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean createTenantVDCEdgeDhcpPolicy(String tenantName, + String startIp, String endIp, String subnet, String nameServerIp, String domain) throws ExecutionException { + String xml = VnmcXml.CREATE_DHCP_POLICY.getXml(); + String service = VnmcXml.CREATE_DHCP_POLICY.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "dhcpserverdn", getDnForDhcpServerPolicy(tenantName)); + xml = replaceXmlValue(xml, "dhcpserverdescr", "DHCP server for " + tenantName); + xml = replaceXmlValue(xml, "dhcpservername", getNameForDhcpPolicy(tenantName)); + xml = replaceXmlValue(xml, "iprangedn", getDnForDhcpIpRange(tenantName)); + xml = replaceXmlValue(xml, "startip", startIp); + xml = replaceXmlValue(xml, "endip", endIp); + xml = replaceXmlValue(xml, "subnet", subnet); + xml = replaceXmlValue(xml, "domain", domain); + xml = replaceXmlValue(xml, "dnsservicedn", getDnForDnsService(tenantName)); + xml = replaceXmlValue(xml, "dnsservicename", getNameForDNSService(tenantName)); + xml = replaceXmlValue(xml, "nameserverip", nameServerIp); + xml = replaceXmlValue(xml, "nameserverdn", getDnForDnsServer(tenantName, nameServerIp)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean associateTenantVDCEdgeDhcpServerPolicy(String tenantName, String intfName) throws ExecutionException { + String xml = VnmcXml.RESOLVE_EDGE_DHCP_SERVER_POLICY.getXml(); + String service = VnmcXml.RESOLVE_EDGE_DHCP_SERVER_POLICY.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "dhcpdn", getDnForDhcpPolicy(tenantName, intfName)); + xml = replaceXmlValue(xml, "insideintf", intfName); + xml = replaceXmlValue(xml, "dhcpserverpolicyname", getNameForDhcpServer(tenantName)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean createTenantVDCEdgeSecurityProfile(String tenantName) throws ExecutionException { + String xml = VnmcXml.CREATE_EDGE_SECURITY_PROFILE.getXml(); + String service = VnmcXml.CREATE_EDGE_SECURITY_PROFILE.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "descr", "Edge Security Profile for Tenant VDC" + tenantName); + xml = replaceXmlValue(xml, "name", getNameForEdgeDeviceSecurityProfile(tenantName)); + xml = replaceXmlValue(xml, "espdn", getDnForTenantVDCEdgeSecurityProfile(tenantName)); + xml = replaceXmlValue(xml, "egressref", "default-egress"); + xml = replaceXmlValue(xml, "ingressref", "default-ingress"); //FIXME: allows everything + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean deleteTenantVDCEdgeSecurityProfile(String tenantName) throws ExecutionException { + String xml = VnmcXml.DELETE_EDGE_SECURITY_PROFILE.getXml(); + String service = VnmcXml.DELETE_EDGE_SECURITY_PROFILE.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "name", getNameForEdgeDeviceSecurityProfile(tenantName)); + xml = replaceXmlValue(xml, "espdn", getDnForTenantVDCEdgeSecurityProfile(tenantName)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + private String getNameForSourceNatIpPool(String tenantName) { + return "SNATIp-" + tenantName; + } + + private String getDnForSourceNatPool(String tenantName) { + return getDnForTenantVDC(tenantName) + "/objgrp-" + getNameForSourceNatIpPool(tenantName); + } + + @Override + public boolean createTenantVDCSourceNatIpPool(String tenantName, String identifier, + String publicIp) throws ExecutionException { + return createTenantVDCIpPool( + getDnForSourceNatPool(tenantName), + getNameForSourceNatIpPool(tenantName), + "Source NAT ip pool for Tenant VDC " + tenantName, + publicIp); + } + + private String getNameForSourceNatPolicy(String tenantName) { + return "SNAT-Policy-" + tenantName; + } + + private String getDnForSourceNatPolicy(String tenantName) { + return getDnForTenantVDC(tenantName) + "/natpol-" + getNameForSourceNatPolicy(tenantName); + } + + private String getNameForSourceNatRule(String tenantName) { + return "SNAT-Rule-" + tenantName; + } + + private String getDnForSourceNatRule(String tenantName) { + return getDnForSourceNatPolicy(tenantName) + "/rule-" + getNameForSourceNatRule(tenantName); + } + + private String getNameForNatPolicySet(String tenantName) { + return "NAT-PolicySet-" + tenantName; + } + + private String getDnForNatPolicySet(String tenantName) { + return getDnForTenantVDC(tenantName) + "/natpset-" + getNameForNatPolicySet(tenantName) ; + } + + private String getDnForSourceNatPolicyRef(String tenantName) { + return getDnForNatPolicySet(tenantName) + "/polref-" + getNameForSourceNatPolicy(tenantName) ; + } + + @Override + public boolean createTenantVDCSourceNatRule(String tenantName, String identifier, + String startSourceIp, String endSourceIp) throws ExecutionException { + + String xml = VnmcXml.CREATE_SOURCE_NAT_RULE.getXml(); + String service = VnmcXml.CREATE_SOURCE_NAT_RULE.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "natruledn", getDnForSourceNatRule(tenantName)); + xml = replaceXmlValue(xml, "natrulename", getNameForSourceNatRule(tenantName)); + xml = replaceXmlValue(xml, "descr", "Source NAT rule for Tenant VDC " + tenantName); + xml = replaceXmlValue(xml, "srcstartip", startSourceIp); + xml = replaceXmlValue(xml, "srcendip", endSourceIp); + xml = replaceXmlValue(xml, "ippoolname", getNameForSourceNatIpPool(tenantName)); + + List rules = listChildren(getDnForSourceNatPolicy(tenantName)); + int order = 100; + if (rules != null) { + order += rules.size(); + } + xml = replaceXmlValue(xml, "order", Integer.toString(order)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean createTenantVDCSourceNatPolicyRef(String tenantName, String identifier) throws ExecutionException { + return createTenantVDCNatPolicyRef( + getDnForSourceNatPolicyRef(tenantName), + getNameForSourceNatPolicy(tenantName), + tenantName); + } + + @Override + public boolean createTenantVDCSourceNatPolicy(String tenantName, String identifier) throws ExecutionException { + return createTenantVDCNatPolicy( + getDnForSourceNatPolicy(tenantName), + getNameForSourceNatPolicy(tenantName)); + } + + @Override + public boolean createTenantVDCNatPolicySet(String tenantName) throws ExecutionException { + String xml = VnmcXml.CREATE_NAT_POLICY_SET.getXml(); + String service = VnmcXml.CREATE_NAT_POLICY_SET.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "descr", "NAT policy set for Tenant VDC " + tenantName); + xml = replaceXmlValue(xml, "natpolicysetname", getNameForNatPolicySet(tenantName)); + xml = replaceXmlValue(xml, "natpolicysetdn", getDnForNatPolicySet(tenantName)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean deleteTenantVDCNatPolicySet(String tenantName) throws ExecutionException { + String xml = VnmcXml.DELETE_NAT_POLICY_SET.getXml(); + String service = VnmcXml.DELETE_NAT_POLICY_SET.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "natpolicysetname", getNameForNatPolicySet(tenantName)); + xml = replaceXmlValue(xml, "natpolicysetdn", getDnForNatPolicySet(tenantName)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean associateNatPolicySet(String tenantName) throws ExecutionException { + String xml = VnmcXml.RESOLVE_NAT_POLICY_SET.getXml(); + String service = VnmcXml.RESOLVE_NAT_POLICY_SET.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "descr", "Edge Security Profile for Tenant VDC" + tenantName); + xml = replaceXmlValue(xml, "name", getNameForEdgeDeviceSecurityProfile(tenantName)); + xml = replaceXmlValue(xml, "espdn", getDnForTenantVDCEdgeSecurityProfile(tenantName)); + xml = replaceXmlValue(xml, "natpolicysetname", getNameForNatPolicySet(tenantName)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + private String getNameForAclPolicySet(String tenantName, boolean ingress) { + return (ingress ? "Ingress-" : "Egress-") + "ACL-PolicySet-" + tenantName; + } + + private String getDnForAclPolicySet(String tenantName, boolean ingress) { + return getDnForTenantVDC(tenantName) + "/pset-" + getNameForAclPolicySet(tenantName, ingress) ; + } + + private String getNameForAclPolicy(String tenantName, String identifier) { + return "ACL-" + tenantName + "-" + identifier; + } + + private String getDnForAclPolicy(String tenantName, String identifier) { + return getDnForTenantVDC(tenantName) + "/pol-" + getNameForAclPolicy(tenantName, identifier); + } + + private String getDnForAclPolicyRef(String tenantName, String identifier, boolean ingress) { + return getDnForAclPolicySet(tenantName, ingress) + "/polref-" + getNameForAclPolicy(tenantName, identifier); + } + + private String getNameForAclRule(String tenantName, String identifier) { + return "Rule-" + tenantName + "-" + identifier; + } + + private String getDnForAclRule(String tenantName, String identifier, String policyIdentifier) { + return getDnForAclPolicy(tenantName, policyIdentifier) + "/rule-" + getNameForAclRule(tenantName, identifier); + } + + @Override + public boolean createTenantVDCAclPolicy(String tenantName, String identifier) throws ExecutionException { + String xml = VnmcXml.CREATE_ACL_POLICY.getXml(); + String service = VnmcXml.CREATE_ACL_POLICY.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "aclpolicyname", getNameForAclPolicy(tenantName, identifier)); + xml = replaceXmlValue(xml, "aclpolicydn", getDnForAclPolicy(tenantName, identifier)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean deleteTenantVDCAclPolicy(String tenantName, String identifier) throws ExecutionException { + String xml = VnmcXml.DELETE_ACL_POLICY.getXml(); + String service = VnmcXml.DELETE_ACL_POLICY.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "aclpolicyname", getNameForAclPolicy(tenantName, identifier)); + xml = replaceXmlValue(xml, "aclpolicydn", getDnForAclPolicy(tenantName, identifier)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean createTenantVDCAclPolicyRef(String tenantName, String identifier, boolean ingress) throws ExecutionException { + String xml = VnmcXml.CREATE_ACL_POLICY_REF.getXml(); + String service = VnmcXml.CREATE_ACL_POLICY_REF.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "aclpolicyname", getNameForAclPolicy(tenantName, identifier)); + xml = replaceXmlValue(xml, "aclpolicydn", getDnForAclPolicy(tenantName, identifier)); + xml = replaceXmlValue(xml, "aclpolicyrefdn", getDnForAclPolicyRef(tenantName, identifier, ingress)); + + List policies = listAclPolicies(tenantName); + int order = 100; + if (policies != null) { + order += policies.size(); + } + xml = replaceXmlValue(xml, "order", Integer.toString(order)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean createTenantVDCAclPolicySet(String tenantName, boolean ingress) throws ExecutionException { + String xml = VnmcXml.CREATE_ACL_POLICY_SET.getXml(); + String service = VnmcXml.CREATE_ACL_POLICY_SET.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "descr", "ACL policy set for Tenant VDC " + tenantName); + xml = replaceXmlValue(xml, "aclpolicysetname", getNameForAclPolicySet(tenantName, ingress)); + xml = replaceXmlValue(xml, "aclpolicysetdn", getDnForAclPolicySet(tenantName, ingress)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean deleteTenantVDCAclPolicySet(String tenantName, boolean ingress) throws ExecutionException { + String xml = VnmcXml.DELETE_ACL_POLICY_SET.getXml(); + String service = VnmcXml.DELETE_ACL_POLICY_SET.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "aclpolicysetname", getNameForAclPolicySet(tenantName, ingress)); + xml = replaceXmlValue(xml, "aclpolicysetdn", getDnForAclPolicySet(tenantName, ingress)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean associateAclPolicySet(String tenantName) throws ExecutionException { + String xml = VnmcXml.RESOLVE_ACL_POLICY_SET.getXml(); + String service = VnmcXml.RESOLVE_ACL_POLICY_SET.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "descr", "Edge Security Profile for Tenant VDC" + tenantName); + xml = replaceXmlValue(xml, "name", getNameForEdgeDeviceSecurityProfile(tenantName)); + xml = replaceXmlValue(xml, "espdn", getDnForTenantVDCEdgeSecurityProfile(tenantName)); + //xml = replaceXmlValue(xml, "egresspolicysetname", getNameForAclPolicySet(tenantName, false)); + xml = replaceXmlValue(xml, "egresspolicysetname", "default-egress"); + xml = replaceXmlValue(xml, "ingresspolicysetname", getNameForAclPolicySet(tenantName, true)); + xml = replaceXmlValue(xml, "natpolicysetname", getNameForNatPolicySet(tenantName)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean createTenantVDCIngressAclRule(String tenantName, + String identifier, String policyIdentifier, + String protocol, String sourceStartIp, String sourceEndIp, + String destStartPort, String destEndPort, String destIp) throws ExecutionException { + String xml = VnmcXml.CREATE_INGRESS_ACL_RULE.getXml(); + String service = VnmcXml.CREATE_INGRESS_ACL_RULE.getService(); + + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "aclruledn", getDnForAclRule(tenantName, identifier, policyIdentifier)); + xml = replaceXmlValue(xml, "aclrulename", getNameForAclRule(tenantName, identifier)); + xml = replaceXmlValue(xml, "descr", "Ingress ACL rule for Tenant VDC " + tenantName); + xml = replaceXmlValue(xml, "actiontype", "permit"); + xml = replaceXmlValue(xml, "protocolvalue", protocol); + xml = replaceXmlValue(xml, "sourcestartip", sourceStartIp); + xml = replaceXmlValue(xml, "sourceendip", sourceEndIp); + xml = replaceXmlValue(xml, "deststartport", destStartPort); + xml = replaceXmlValue(xml, "destendport", destEndPort); + xml = replaceXmlValue(xml, "destip", destIp); + + List rules = listChildren(getDnForAclPolicy(tenantName, policyIdentifier)); + int order = 100; + if (rules != null) { + order += rules.size(); + } + xml = replaceXmlValue(xml, "order", Integer.toString(order)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean createTenantVDCIngressAclRule(String tenantName, + String identifier, String policyIdentifier, + String protocol, String sourceStartIp, String sourceEndIp, + String destIp) throws ExecutionException { + String xml = VnmcXml.CREATE_GENERIC_INGRESS_ACL_RULE.getXml(); + String service = VnmcXml.CREATE_GENERIC_INGRESS_ACL_RULE.getService(); + + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "aclruledn", getDnForAclRule(tenantName, identifier, policyIdentifier)); + xml = replaceXmlValue(xml, "aclrulename", getNameForAclRule(tenantName, identifier)); + xml = replaceXmlValue(xml, "descr", "Ingress ACL rule for Tenant VDC " + tenantName); + xml = replaceXmlValue(xml, "actiontype", "permit"); + xml = replaceXmlValue(xml, "protocolvalue", protocol); + xml = replaceXmlValue(xml, "sourcestartip", sourceStartIp); + xml = replaceXmlValue(xml, "sourceendip", sourceEndIp); + + List rules = listChildren(getDnForAclPolicy(tenantName, policyIdentifier)); + int order = 100; + if (rules != null) { + order += rules.size(); + } + xml = replaceXmlValue(xml, "order", Integer.toString(order)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean createTenantVDCEgressAclRule(String tenantName, + String identifier, String policyIdentifier, + String protocol, String sourceStartPort, String sourceEndPort, String sourceIp, + String destStartIp, String destEndIp) throws ExecutionException { + String xml = VnmcXml.CREATE_EGRESS_ACL_RULE.getXml(); + String service = VnmcXml.CREATE_EGRESS_ACL_RULE.getService(); + + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "aclruledn", getDnForAclRule(tenantName, identifier, policyIdentifier)); + xml = replaceXmlValue(xml, "aclrulename", getNameForAclRule(tenantName, identifier)); + xml = replaceXmlValue(xml, "descr", "Egress ACL rule for Tenant VDC " + tenantName); + xml = replaceXmlValue(xml, "actiontype", "permit"); + xml = replaceXmlValue(xml, "protocolvalue", protocol); + xml = replaceXmlValue(xml, "deststartip", destStartIp); + xml = replaceXmlValue(xml, "destendip", destEndIp); + xml = replaceXmlValue(xml, "sourcestartport", sourceStartPort); + xml = replaceXmlValue(xml, "sourceendport", sourceEndPort); + xml = replaceXmlValue(xml, "sourceip", sourceIp); + + List rules = listChildren(getDnForAclPolicy(tenantName, policyIdentifier)); + int order = 100; + if (rules != null) { + order += rules.size(); + } + xml = replaceXmlValue(xml, "order", Integer.toString(order)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean createTenantVDCEgressAclRule(String tenantName, + String identifier, String policyIdentifier, + String protocol, String sourceIp, + String destStartIp, String destEndIp) throws ExecutionException { + String xml = VnmcXml.CREATE_GENERIC_EGRESS_ACL_RULE.getXml(); + String service = VnmcXml.CREATE_GENERIC_EGRESS_ACL_RULE.getService(); + + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "aclruledn", getDnForAclRule(tenantName, identifier, policyIdentifier)); + xml = replaceXmlValue(xml, "aclrulename", getNameForAclRule(tenantName, identifier)); + xml = replaceXmlValue(xml, "descr", "Egress ACL rule for Tenant VDC " + tenantName); + xml = replaceXmlValue(xml, "actiontype", "permit"); + xml = replaceXmlValue(xml, "protocolvalue", protocol); + xml = replaceXmlValue(xml, "deststartip", destStartIp); + xml = replaceXmlValue(xml, "destendip", destEndIp); + + List rules = listChildren(getDnForAclPolicy(tenantName, policyIdentifier)); + int order = 100; + if (rules != null) { + order += rules.size(); + } + xml = replaceXmlValue(xml, "order", Integer.toString(order)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean deleteTenantVDCAclRule(String tenantName, String identifier, String policyIdentifier) throws ExecutionException { + return deleteTenantVDCRule( + getDnForAclRule(tenantName, identifier, policyIdentifier), + getNameForAclRule(tenantName, identifier)); + } + + private String getNameForPFPortPool(String tenantName, String identifier) { + return "PFPort-" + tenantName + "-" + identifier; + } + + private String getDnForPFPortPool(String tenantName, String identifier) { + return getDnForTenantVDC(tenantName) + "/objgrp-" + getNameForPFPortPool(tenantName, identifier); + } + + private String getNameForPFIpPool(String tenantName, String identifier) { + return "PFIp-" + tenantName + "-" + identifier; + } + + private String getDnForPFIpPool(String tenantName, String identifier) { + return getDnForTenantVDC(tenantName) + "/objgrp-" + getNameForPFIpPool(tenantName, identifier); + } + + private boolean createTenantVDCPortPool(String poolDn, String name, + String description, String startPort, String endPort) throws ExecutionException { + String xml = VnmcXml.CREATE_PORT_POOL.getXml(); + String service = VnmcXml.CREATE_PORT_POOL.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "portpooldn", poolDn); + xml = replaceXmlValue(xml, "portpoolname", name); + xml = replaceXmlValue(xml, "descr", description); + xml = replaceXmlValue(xml, "startport", startPort); + xml = replaceXmlValue(xml, "endport", endPort); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + private boolean createTenantVDCIpPool(String poolDn, String name, + String description, String ipAddress) throws ExecutionException { + String xml = VnmcXml.CREATE_IP_POOL.getXml(); + String service = VnmcXml.CREATE_IP_POOL.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "ippooldn", poolDn); + xml = replaceXmlValue(xml, "ippoolname", name); + xml = replaceXmlValue(xml, "descr", description); + xml = replaceXmlValue(xml, "ipvalue", ipAddress); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + private boolean createTenantVDCNatPolicyRef(String policyRefDn, String name, String tenantName) throws ExecutionException { + String xml = VnmcXml.CREATE_NAT_POLICY_REF.getXml(); + String service = VnmcXml.CREATE_NAT_POLICY_REF.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "natpolicyrefdn", policyRefDn); + xml = replaceXmlValue(xml, "natpolicyname", name); + + List policies = listNatPolicies(tenantName); + int order = 100; + if (policies != null) { + order += policies.size(); + } + xml = replaceXmlValue(xml, "order", Integer.toString(order)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + private boolean createTenantVDCNatPolicy(String policyDn, String name) throws ExecutionException { + String xml = VnmcXml.CREATE_NAT_POLICY.getXml(); + String service = VnmcXml.CREATE_NAT_POLICY.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "natpolicydn", policyDn); + xml = replaceXmlValue(xml, "natpolicyname", name); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + private boolean deleteTenantVDCNatPolicy(String policyDn, String name) throws ExecutionException { + String xml = VnmcXml.DELETE_NAT_POLICY.getXml(); + String service = VnmcXml.DELETE_NAT_POLICY.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "natpolicydn", policyDn); + xml = replaceXmlValue(xml, "natpolicyname", name); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + private boolean deleteTenantVDCRule(String ruledn, String ruleName) throws ExecutionException { + String xml = VnmcXml.DELETE_RULE.getXml(); + String service = VnmcXml.DELETE_RULE.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "ruledn", ruledn); + xml = replaceXmlValue(xml, "rulename", ruleName); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + private List listNatPolicies(String tenantName) throws ExecutionException { + + String xml = VnmcXml.LIST_NAT_POLICIES.getXml(); + String service = VnmcXml.LIST_NAT_POLICIES.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "vdcdn", getDnForTenantVDC(tenantName)); + + String response = sendRequest(service, xml); + + List result = new ArrayList(); + Document xmlDoc = getDocument(response); + xmlDoc.normalize(); + NodeList policyList = xmlDoc.getElementsByTagName("pair"); + for (int i=0; i < policyList.getLength(); i++) { + Node policyNode = policyList.item(i); + result.add(policyNode.getAttributes().getNamedItem("key").getNodeValue()); + } + + return result; + } + + private List listAclPolicies(String tenantName) throws ExecutionException { + + String xml = VnmcXml.LIST_ACL_POLICIES.getXml(); + String service = VnmcXml.LIST_ACL_POLICIES.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "vdcdn", getDnForTenantVDC(tenantName)); + + String response = sendRequest(service, xml); + + List result = new ArrayList(); + Document xmlDoc = getDocument(response); + xmlDoc.normalize(); + NodeList policyList = xmlDoc.getElementsByTagName("pair"); + for (int i=0; i < policyList.getLength(); i++) { + Node policyNode = policyList.item(i); + result.add(policyNode.getAttributes().getNamedItem("key").getNodeValue()); + } + + return result; + } + + private List listChildren(String dn) throws ExecutionException { + + String xml = VnmcXml.LIST_CHILDREN.getXml(); + String service = VnmcXml.LIST_CHILDREN.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "dn", dn); + + String response = sendRequest(service, xml); + + List result = new ArrayList(); + Document xmlDoc = getDocument(response); + xmlDoc.normalize(); + NodeList policyList = xmlDoc.getElementsByTagName("policyRule"); + for (int i=0; i < policyList.getLength(); i++) { + Node policyNode = policyList.item(i); + result.add(policyNode.getAttributes().getNamedItem("name").getNodeValue()); + } + + return result; + } + + @Override + public boolean createTenantVDCPFPortPool(String tenantName, String identifier, + String startPort, String endPort) throws ExecutionException { + return createTenantVDCPortPool( + getDnForPFPortPool(tenantName, identifier), + getNameForPFPortPool(tenantName, identifier), + "PF port pool for " + getNameForPFPortPool(tenantName, identifier), + startPort, endPort); + } + + @Override + public boolean createTenantVDCPFIpPool(String tenantName, String identifier, + String ipAddress) throws ExecutionException { + return createTenantVDCIpPool( + getDnForPFIpPool(tenantName, identifier), + getNameForPFIpPool(tenantName, identifier), + "PF ip pool for " + getNameForPFIpPool(tenantName, identifier), + ipAddress); + } + + private String getNameForPFPolicy(String tenantName, String identifier) { + return "PF-" + tenantName + "-" + identifier; + } + + private String getDnForPFPolicy(String tenantName, String identifier) { + return getDnForTenantVDC(tenantName) + "/natpol-" + getNameForPFPolicy(tenantName, identifier); + } + + private String getDnForPFPolicyRef(String tenantName, String identifier) { + return getDnForNatPolicySet(tenantName) + "/polref-" + getNameForPFPolicy(tenantName, identifier); + } + + private String getNameForPFRule(String tenantName, String identifier) { + return "Rule-" + tenantName + "-" + identifier; + } + + private String getDnForPFRule(String tenantName, String identifier, String policyIdentifier) { + return getDnForPFPolicy(tenantName, policyIdentifier) + "/rule-" + getNameForPFRule(tenantName, identifier); + } + + @Override + public boolean createTenantVDCPFRule(String tenantName, + String identifier, String policyIdentifier, + String protocol, String publicIp, + String startPort, String endPort) throws ExecutionException { + String xml = VnmcXml.CREATE_PF_RULE.getXml(); + String service = VnmcXml.CREATE_PF_RULE.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "natruledn", getDnForPFRule(tenantName, identifier, policyIdentifier)); + xml = replaceXmlValue(xml, "natrulename", getNameForPFRule(tenantName, identifier)); + xml = replaceXmlValue(xml, "descr", "PF rule for Tenant VDC " + tenantName); + xml = replaceXmlValue(xml, "ippoolname", getNameForPFIpPool(tenantName, policyIdentifier + "-" + identifier)); + xml = replaceXmlValue(xml, "portpoolname", getNameForPFPortPool(tenantName, policyIdentifier + "-" + identifier)); + xml = replaceXmlValue(xml, "ip", publicIp); + xml = replaceXmlValue(xml, "startport", startPort); + xml = replaceXmlValue(xml, "endport", endPort); + xml = replaceXmlValue(xml, "protocolvalue", protocol); + + List rules = listChildren(getDnForPFPolicy(tenantName, policyIdentifier)); + int order = 100; + if (rules != null) { + order += rules.size(); + } + xml = replaceXmlValue(xml, "order", Integer.toString(order)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean deleteTenantVDCPFRule(String tenantName, String identifier, + String policyIdentifier) throws ExecutionException { + return deleteTenantVDCRule( + getDnForPFRule(tenantName, identifier, policyIdentifier), + getNameForPFRule(tenantName, identifier)); + } + + @Override + public boolean createTenantVDCAclRuleForPF(String tenantName, + String identifier, String policyIdentifier, String protocol, + String ipAddress, String startPort, String endPort) + throws ExecutionException { + String xml = VnmcXml.CREATE_ACL_RULE_FOR_PF.getXml(); + String service = VnmcXml.CREATE_ACL_RULE_FOR_PF.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "aclruledn", getDnForAclRule(tenantName, identifier, policyIdentifier)); + xml = replaceXmlValue(xml, "aclrulename", getNameForAclRule(tenantName, identifier)); + xml = replaceXmlValue(xml, "descr", "ACL rule for Tenant VDC " + tenantName); + xml = replaceXmlValue(xml, "actiontype", "permit"); + xml = replaceXmlValue(xml, "protocolvalue", protocol); + xml = replaceXmlValue(xml, "ip", ipAddress); + xml = replaceXmlValue(xml, "startport", startPort); + xml = replaceXmlValue(xml, "endport", endPort); + + List rules = listChildren(getDnForAclPolicy(tenantName, policyIdentifier)); + int order = 100; + if (rules != null) { + order += rules.size(); + } + xml = replaceXmlValue(xml, "order", Integer.toString(order)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean createTenantVDCPFPolicyRef(String tenantName, String identifier) throws ExecutionException { + return createTenantVDCNatPolicyRef( + getDnForPFPolicyRef(tenantName, identifier), + getNameForPFPolicy(tenantName, identifier), + tenantName); + } + + @Override + public boolean createTenantVDCPFPolicy(String tenantName, String identifier) throws ExecutionException { + return createTenantVDCNatPolicy( + getDnForPFPolicy(tenantName, identifier), + getNameForPFPolicy(tenantName, identifier)); + } + + @Override + public boolean deleteTenantVDCPFPolicy(String tenantName, String identifier) throws ExecutionException { + return deleteTenantVDCNatPolicy( + getDnForPFPolicy(tenantName, identifier), + getNameForPFPolicy(tenantName, identifier)); + } + + private String getNameForDNatIpPool(String tenantName, String identifier) { + return "DNATIp-" + tenantName + "-" + identifier; + } + + private String getDnForDNatIpPool(String tenantName, String identifier) { + return getDnForTenantVDC(tenantName) + "/objgrp-" + getNameForDNatIpPool(tenantName, identifier); + } + + @Override + public boolean createTenantVDCDNatIpPool(String tenantName, + String identifier, String ipAddress) throws ExecutionException { + return createTenantVDCIpPool( + getDnForDNatIpPool(tenantName, identifier), + getNameForDNatIpPool(tenantName, identifier), + "DNAT ip pool for " + getNameForDNatIpPool(tenantName, identifier), + ipAddress); + } + + private String getNameForDNatRule(String tenantName, String identifier) { + return "Rule-" + tenantName + "-" + identifier; + } + + private String getDnForDNatRule(String tenantName, String identifier, String policyIdentifier) { + return getDnForDNatPolicy(tenantName, policyIdentifier) + "/rule-" + getNameForDNatRule(tenantName, identifier); + } + + private String getNameForDNatPolicy(String tenantName, String identifier) { + return "DNAT-" + tenantName + "-" + identifier; + } + + private String getDnForDNatPolicy(String tenantName, String identifier) { + return getDnForTenantVDC(tenantName) + "/natpol-" + getNameForDNatPolicy(tenantName, identifier); + } + + private String getDnForDNatPolicyRef(String tenantName, String identifier) { + return getDnForNatPolicySet(tenantName) + "/polref-" + getNameForDNatPolicy(tenantName, identifier); + } + + @Override + public boolean createTenantVDCDNatRule(String tenantName, + String identifier, String policyIdentifier, String publicIp) + throws ExecutionException { + String xml = VnmcXml.CREATE_DNAT_RULE.getXml(); + String service = VnmcXml.CREATE_DNAT_RULE.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "natruledn", getDnForDNatRule(tenantName, identifier, policyIdentifier)); + xml = replaceXmlValue(xml, "natrulename", getNameForDNatRule(tenantName, identifier)); + xml = replaceXmlValue(xml, "descr", "DNAT rule for Tenant VDC " + tenantName); + xml = replaceXmlValue(xml, "ippoolname", getNameForDNatIpPool(tenantName, policyIdentifier + "-" + identifier)); + xml = replaceXmlValue(xml, "ip", publicIp); + + List rules = listChildren(getDnForDNatPolicy(tenantName, policyIdentifier)); + int order = 100; + if (rules != null) { + order += rules.size(); + } + xml = replaceXmlValue(xml, "order", Integer.toString(order)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean deleteTenantVDCDNatRule(String tenantName, + String identifier, String policyIdentifier) + throws ExecutionException { + return deleteTenantVDCRule( + getDnForDNatRule(tenantName, identifier, policyIdentifier), + getNameForDNatRule(tenantName, identifier)); + } + + @Override + public boolean createTenantVDCAclRuleForDNat(String tenantName, + String identifier, String policyIdentifier, String ipAddress) + throws ExecutionException { + String xml = VnmcXml.CREATE_ACL_RULE_FOR_DNAT.getXml(); + String service = VnmcXml.CREATE_ACL_RULE_FOR_DNAT.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "aclruledn", getDnForAclRule(tenantName, identifier, policyIdentifier)); + xml = replaceXmlValue(xml, "aclrulename", getNameForAclRule(tenantName, identifier)); + xml = replaceXmlValue(xml, "descr", "ACL rule for Tenant VDC " + tenantName); + xml = replaceXmlValue(xml, "actiontype", "permit"); + xml = replaceXmlValue(xml, "ip", ipAddress); + + List rules = listChildren(getDnForAclPolicy(tenantName, policyIdentifier)); + int order = 100; + if (rules != null) { + order += rules.size(); + } + xml = replaceXmlValue(xml, "order", Integer.toString(order)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean createTenantVDCDNatPolicyRef(String tenantName, + String identifier) throws ExecutionException { + return createTenantVDCNatPolicyRef( + getDnForDNatPolicyRef(tenantName, identifier), + getNameForDNatPolicy(tenantName, identifier), + tenantName); + } + + @Override + public boolean createTenantVDCDNatPolicy(String tenantName, + String identifier) throws ExecutionException { + return createTenantVDCNatPolicy( + getDnForDNatPolicy(tenantName, identifier), + getNameForDNatPolicy(tenantName, identifier)); + } + + @Override + public boolean deleteTenantVDCDNatPolicy(String tenantName, + String identifier) throws ExecutionException { + return deleteTenantVDCNatPolicy( + getDnForDNatPolicy(tenantName, identifier), + getNameForDNatPolicy(tenantName, identifier)); + } + + private String getNameForEdgeFirewall(String tenantName) { + return "ASA-1000v-" + tenantName; + } + + private String getDnForEdgeFirewall(String tenantName) { + return getDnForTenantVDC(tenantName) + "/efw-" + getNameForEdgeFirewall(tenantName); + } + + private String getNameForEdgeInsideIntf(String tenantName) { + return "Edge_Inside"; //TODO: make this configurable + } + + private String getNameForEdgeOutsideIntf(String tenantName) { + return "Edge_Outside"; //TODO: make this configurable + } + + private String getDnForOutsideIntf(String tenantName) { + return getDnForEdgeFirewall(tenantName) + "/interface-" + getNameForEdgeOutsideIntf(tenantName); + } + + private String getDnForInsideIntf(String tenantName) { + return getDnForEdgeFirewall(tenantName) + "/interface-" + getNameForEdgeInsideIntf(tenantName); + } + + @Override + public boolean createEdgeFirewall(String tenantName, String publicIp, String insideIp, + String publicSubnet, String insideSubnet) throws ExecutionException { + String xml = VnmcXml.CREATE_EDGE_FIREWALL.getXml(); + String service = VnmcXml.CREATE_EDGE_FIREWALL.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "edgefwdescr", "Edge Firewall for Tenant VDC " + tenantName); + xml = replaceXmlValue(xml, "edgefwname", getNameForEdgeFirewall(tenantName)); + xml = replaceXmlValue(xml, "edgefwdn", getDnForEdgeFirewall(tenantName)); + xml = replaceXmlValue(xml, "insideintfname", getNameForEdgeInsideIntf(tenantName)); + xml = replaceXmlValue(xml, "outsideintfname", getNameForEdgeOutsideIntf(tenantName)); + + xml = replaceXmlValue(xml, "insideintfdn", getDnForInsideIntf(tenantName)); + xml = replaceXmlValue(xml, "outsideintfdn", getDnForOutsideIntf(tenantName)); + + xml = replaceXmlValue(xml, "deviceserviceprofiledn", getDnForEdgeFirewall(tenantName) + "/device-service-profile"); + xml = replaceXmlValue(xml, "outsideintfsp", getDnForOutsideIntf(tenantName) + "/interface-service-profile"); + + xml = replaceXmlValue(xml, "secprofileref", getNameForEdgeDeviceSecurityProfile(tenantName)); + xml = replaceXmlValue(xml, "deviceserviceprofile", getNameForEdgeDeviceServiceProfile(tenantName)); + + xml = replaceXmlValue(xml, "insideip", insideIp); + xml = replaceXmlValue(xml, "publicip", publicIp); + xml = replaceXmlValue(xml, "insidesubnet", insideSubnet); + xml = replaceXmlValue(xml, "outsidesubnet", publicSubnet); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean deleteEdgeFirewall(String tenantName) throws ExecutionException { + String xml = VnmcXml.DELETE_EDGE_FIREWALL.getXml(); + String service = VnmcXml.DELETE_EDGE_FIREWALL.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "edgefwname", getNameForEdgeFirewall(tenantName)); + xml = replaceXmlValue(xml, "edgefwdn", getDnForEdgeFirewall(tenantName)); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public Map listUnAssocAsa1000v() throws ExecutionException { + String xml = VnmcXml.LIST_UNASSOC_ASA1000V.getXml(); + String service = VnmcXml.LIST_UNASSOC_ASA1000V.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + + String response = sendRequest(service, xml); + + Map result = new HashMap(); + Document xmlDoc = getDocument(response); + xmlDoc.normalize(); + NodeList fwList = xmlDoc.getElementsByTagName("fwInstance"); + for (int j=0; j < fwList.getLength(); j++) { + Node fwNode = fwList.item(j); + result.put(fwNode.getAttributes().getNamedItem("mgmtIp").getNodeValue(), + fwNode.getAttributes().getNamedItem("dn").getNodeValue()); + } + + return result; + } + + @Override + public boolean assignAsa1000v(String tenantName, String firewallDn) throws ExecutionException { + String xml = VnmcXml.ASSIGN_ASA1000V.getXml(); + String service = VnmcXml.ASSIGN_ASA1000V.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "binddn", getDnForEdgeFirewall(tenantName) + "/binding"); + xml = replaceXmlValue(xml, "fwdn", firewallDn); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + @Override + public boolean unassignAsa1000v(String tenantName, String firewallDn) throws ExecutionException { + String xml = VnmcXml.UNASSIGN_ASA1000V.getXml(); + String service = VnmcXml.UNASSIGN_ASA1000V.getService(); + xml = replaceXmlValue(xml, "cookie", _cookie); + xml = replaceXmlValue(xml, "binddn", getDnForEdgeFirewall(tenantName) + "/binding"); + xml = replaceXmlValue(xml, "fwdn", firewallDn); + + String response = sendRequest(service, xml); + return verifySuccess(response); + } + + private String sendRequest(String service, String xmlRequest) throws ExecutionException { + org.apache.commons.httpclient.protocol.Protocol myhttps = + new org.apache.commons.httpclient.protocol.Protocol("https", new EasySSLProtocolSocketFactory(), 443); + HttpClient client = new HttpClient(); + client.getHostConfiguration().setHost(_ip, 443, myhttps); + byte[] response = null; + PostMethod method = new PostMethod("/xmlIM/" + service); + + method.setRequestBody(xmlRequest); + + try{ + int statusCode = client.executeMethod(method); + + if (statusCode != HttpStatus.SC_OK) { + throw new Exception("Error code : " + statusCode); + } + response = method.getResponseBody(); + }catch(Exception e){ + System.out.println(e.getMessage()); + throw new ExecutionException(e.getMessage()); + } + System.out.println(new String(response)); + return new String(response); + } + + private Map checkResponse(String xmlResponse, String... keys) throws ExecutionException { + Document xmlDoc = getDocument(xmlResponse); + Map result = new HashMap(); + Node topElement = xmlDoc.getChildNodes().item(0); + if (topElement != null) { + for (String key: keys){ + Node valueNode = topElement.getAttributes().getNamedItem(key); + result.put(key, valueNode==null?null:valueNode.getNodeValue()); + } + } + return result; + } + + private boolean verifySuccess(String xmlResponse) throws ExecutionException { + Map checked = checkResponse(xmlResponse, "errorCode", "errorDescr"); + + if (checked.get("errorCode") != null) { + String errorCode = checked.get("errorCode"); + if (errorCode.equals("103")) { + //tenant already exists + return true; + } + String errorDescr = checked.get("errorDescr"); + throw new ExecutionException(errorDescr); + } + return true; + } + + /* + * XML utils + */ + + private Document getDocument(String xml) throws ExecutionException { + StringReader xmlReader = new StringReader(" \n" + xml.trim()); + InputSource xmlSource = new InputSource(xmlReader); + Document doc = null; + + try { + doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(xmlSource); + + } catch (Exception e) { + s_logger.error(e); + throw new ExecutionException(e.getMessage()); + } + + if (doc == null) { + throw new ExecutionException("Failed to parse xml " + xml); + } else { + return doc; + } + } + + private String replaceXmlTag(String xml, String oldTag, String newTag) { + return xml.replaceAll(oldTag, newTag); + } + + private String replaceXmlValue(String xml, String marker, String value) { + marker = "\\s*%" + marker + "%\\s*"; + + if (value == null) { + value = ""; + } + + return xml.replaceAll(marker, value); + } + + private String extractXml(String xml, String marker) { + String startMarker = "<" + marker + ">"; + String endMarker = ""; + if (xml.contains(startMarker) && xml.contains(endMarker)) { + return xml.substring(xml.indexOf(startMarker) + startMarker.length(), xml.indexOf(endMarker)); + } else { + return null; + } + + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcController.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcController.java new file mode 100644 index 00000000000..e756165bdaa --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcController.java @@ -0,0 +1,40 @@ +// 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.cisco; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +import com.cloud.org.Grouping; + +public interface CiscoVnmcController extends Grouping, InternalIdentity, Identity { + + long getId(); + + String getUuid(); + + void setUuid(String uuid); + + long getPhysicalNetworkId(); + + long getHostId(); + + String getProviderName(); + + String getDeviceName(); + +} \ No newline at end of file diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcControllerVO.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcControllerVO.java new file mode 100644 index 00000000000..4207f1dac4c --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/CiscoVnmcControllerVO.java @@ -0,0 +1,102 @@ +// 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.cisco; + +import java.util.UUID; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name="external_cisco_vnmc_devices") +public class CiscoVnmcControllerVO implements CiscoVnmcController { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="uuid") + private String uuid; + + @Column(name="host_id") + private long hostId; + + @Column(name="physical_network_id") + private long physicalNetworkId; + + @Column(name="provider_name") + private String providerName; + + @Column(name="device_name") + private String deviceName; + + + public CiscoVnmcControllerVO() { + this.uuid = UUID.randomUUID().toString(); + } + + public CiscoVnmcControllerVO(long hostId, long physicalNetworkId, + String providerName, String deviceName) { + super(); + this.hostId = hostId; + this.physicalNetworkId = physicalNetworkId; + this.providerName = providerName; + this.deviceName = deviceName; + this.uuid = UUID.randomUUID().toString(); + } + + @Override + public long getId() { + return id; + } + + @Override + public String getUuid() { + return uuid; + } + + @Override + public void setUuid(String uuid) { + this.uuid = uuid; + } + + @Override + public long getPhysicalNetworkId() { + return physicalNetworkId; + } + + @Override + public long getHostId() { + return hostId; + } + + @Override + public String getProviderName() { + return providerName; + } + + @Override + public String getDeviceName() { + return deviceName; + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/NetworkAsa1000vMap.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/NetworkAsa1000vMap.java new file mode 100755 index 00000000000..2e004dccd41 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/NetworkAsa1000vMap.java @@ -0,0 +1,31 @@ +// 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.cisco; + +import org.apache.cloudstack.api.InternalIdentity; + +import com.cloud.org.Grouping; + +public interface NetworkAsa1000vMap extends Grouping, InternalIdentity { + + long getId(); + + long getNetworkId(); + + long getAsa1000vId(); + +} \ No newline at end of file diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/NetworkAsa1000vMapVO.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/NetworkAsa1000vMapVO.java new file mode 100755 index 00000000000..9638b6f8ae2 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/cisco/NetworkAsa1000vMapVO.java @@ -0,0 +1,73 @@ +// 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.cisco; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name="network_asa1000v_map") +public class NetworkAsa1000vMapVO implements NetworkAsa1000vMap { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="id") + private long id; + + @Column(name="network_id") + private long networkId; + + @Column(name="asa1000v_id") + private long asa1000vId; + + public NetworkAsa1000vMapVO() { + } + + public NetworkAsa1000vMapVO(long networkId, long asa1000vId) { + super(); + this.networkId = networkId; + this.asa1000vId = asa1000vId; + } + + @Override + public long getId() { + return id; + } + + @Override + public long getAsa1000vId() { + return asa1000vId; + } + + public void setAsa1000vId(long asa1000vId) { + this.asa1000vId = asa1000vId; + } + + @Override + public long getNetworkId() { + return networkId; + } + + public void setNetworkId(long networkId) { + this.networkId = networkId; + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/CiscoAsa1000vDao.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/CiscoAsa1000vDao.java new file mode 100755 index 00000000000..1a380b13691 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/CiscoAsa1000vDao.java @@ -0,0 +1,33 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network.dao; + +import java.util.List; + +import com.cloud.network.cisco.CiscoAsa1000vDeviceVO; +import com.cloud.utils.db.GenericDao; + +public interface CiscoAsa1000vDao extends GenericDao{ + /** + * list all the Cisco Asa 1000v devices added in to this physical network + * @param physicalNetworkId physical Network Id + * @return list of CiscoAsa1000vDeviceVO for this physical network. + */ + List listByPhysicalNetwork(long physicalNetworkId); + + CiscoAsa1000vDeviceVO findByManagementIp(String managementIp); +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/CiscoAsa1000vDaoImpl.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/CiscoAsa1000vDaoImpl.java new file mode 100755 index 00000000000..a5820dea48b --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/CiscoAsa1000vDaoImpl.java @@ -0,0 +1,63 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network.dao; + +import java.util.List; + +import javax.ejb.Local; + +import org.springframework.stereotype.Component; + +import com.cloud.network.cisco.CiscoAsa1000vDeviceVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; + +@Component +@Local(value=CiscoAsa1000vDao.class) +public class CiscoAsa1000vDaoImpl extends GenericDaoBase + implements CiscoAsa1000vDao { + + protected final SearchBuilder physicalNetworkIdSearch; + protected final SearchBuilder managementIpSearch; + + public CiscoAsa1000vDaoImpl() { + physicalNetworkIdSearch = createSearchBuilder(); + physicalNetworkIdSearch.and("physicalNetworkId", physicalNetworkIdSearch.entity().getPhysicalNetworkId(), Op.EQ); + physicalNetworkIdSearch.done(); + + managementIpSearch = createSearchBuilder(); + managementIpSearch.and("managementIp", managementIpSearch.entity().getManagementIp(), Op.EQ); + managementIpSearch.done(); + } + + @Override + public List listByPhysicalNetwork(long physicalNetworkId) { + SearchCriteria sc = physicalNetworkIdSearch.create(); + sc.setParameters("physicalNetworkId", physicalNetworkId); + return search(sc, null); + } + + @Override + public CiscoAsa1000vDeviceVO findByManagementIp(String managementIp) { + SearchCriteria sc = managementIpSearch.create(); + sc.setParameters("managementIp", managementIp); + return findOneBy(sc); + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/CiscoVnmcDao.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/CiscoVnmcDao.java new file mode 100644 index 00000000000..f0b394834a0 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/CiscoVnmcDao.java @@ -0,0 +1,32 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network.dao; + +import java.util.List; + +import com.cloud.network.cisco.CiscoVnmcControllerVO; +import com.cloud.utils.db.GenericDao; + +public interface CiscoVnmcDao extends GenericDao{ + /** + * list all the Cisco VNMC devices added in to this physical network + * @param physicalNetworkId physical Network Id + * @return list of CiscoVnmcDeviceVO for this physical network. + */ + List listByPhysicalNetwork(long physicalNetworkId); + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/CiscoVnmcDaoImpl.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/CiscoVnmcDaoImpl.java new file mode 100644 index 00000000000..89518104851 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/CiscoVnmcDaoImpl.java @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network.dao; + +import java.util.List; + +import javax.ejb.Local; + +import org.springframework.stereotype.Component; + +import com.cloud.network.cisco.CiscoVnmcControllerVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; + +@Component +@Local(value=CiscoVnmcDao.class) +public class CiscoVnmcDaoImpl extends GenericDaoBase + implements CiscoVnmcDao { + + protected final SearchBuilder physicalNetworkIdSearch; + + public CiscoVnmcDaoImpl() { + physicalNetworkIdSearch = createSearchBuilder(); + physicalNetworkIdSearch.and("physicalNetworkId", physicalNetworkIdSearch.entity().getPhysicalNetworkId(), Op.EQ); + physicalNetworkIdSearch.done(); + } + + @Override + public List listByPhysicalNetwork(long physicalNetworkId) { + SearchCriteria sc = physicalNetworkIdSearch.create(); + sc.setParameters("physicalNetworkId", physicalNetworkId); + return search(sc, null); + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/NetworkAsa1000vMapDao.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/NetworkAsa1000vMapDao.java new file mode 100755 index 00000000000..053f4afef54 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/NetworkAsa1000vMapDao.java @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network.dao; + +import com.cloud.network.cisco.NetworkAsa1000vMapVO; +import com.cloud.utils.db.GenericDao; + +public interface NetworkAsa1000vMapDao extends GenericDao{ + + NetworkAsa1000vMapVO findByNetworkId(long networkId); + + NetworkAsa1000vMapVO findByAsa1000vId(long asa1000vId); + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/NetworkAsa1000vMapDaoImpl.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/NetworkAsa1000vMapDaoImpl.java new file mode 100755 index 00000000000..692b3d6fda6 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/dao/NetworkAsa1000vMapDaoImpl.java @@ -0,0 +1,61 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network.dao; + +import javax.ejb.Local; + +import org.springframework.stereotype.Component; + +import com.cloud.network.cisco.NetworkAsa1000vMapVO; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Op; + +@Component +@Local(value=NetworkAsa1000vMapDao.class) +public class NetworkAsa1000vMapDaoImpl extends GenericDaoBase + implements NetworkAsa1000vMapDao { + + protected final SearchBuilder networkSearch; + protected final SearchBuilder asa1000vSearch; + + public NetworkAsa1000vMapDaoImpl() { + networkSearch = createSearchBuilder(); + networkSearch.and("networkId", networkSearch.entity().getNetworkId(), Op.EQ); + networkSearch.done(); + + asa1000vSearch = createSearchBuilder(); + asa1000vSearch.and("asa1000vId", asa1000vSearch.entity().getAsa1000vId(), Op.EQ); + asa1000vSearch.done(); + } + + @Override + public NetworkAsa1000vMapVO findByNetworkId(long networkId) { + SearchCriteria sc = networkSearch.create(); + sc.setParameters("networkId", networkId); + return findOneBy(sc); + } + + @Override + public NetworkAsa1000vMapVO findByAsa1000vId(long asa1000vId) { + SearchCriteria sc = asa1000vSearch.create(); + sc.setParameters("asa1000vId", asa1000vId); + return findOneBy(sc); + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoAsa1000vService.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoAsa1000vService.java new file mode 100755 index 00000000000..dff9288b0ff --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoAsa1000vService.java @@ -0,0 +1,43 @@ +// 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.element; + +import java.util.List; + +import com.cloud.api.commands.AddCiscoAsa1000vResourceCmd; +import com.cloud.api.commands.DeleteCiscoAsa1000vResourceCmd; +import com.cloud.api.commands.ListCiscoAsa1000vResourcesCmd; +import com.cloud.api.response.CiscoAsa1000vResourceResponse; +import com.cloud.network.Network; +import com.cloud.network.cisco.CiscoAsa1000vDevice; +import com.cloud.network.cisco.CiscoAsa1000vDeviceVO; +import com.cloud.utils.component.PluggableService; + +public interface CiscoAsa1000vService extends PluggableService { + + public CiscoAsa1000vDevice addCiscoAsa1000vResource(AddCiscoAsa1000vResourceCmd cmd); + + public CiscoAsa1000vResourceResponse createCiscoAsa1000vResourceResponse( + CiscoAsa1000vDevice ciscoAsa1000vDeviceVO); + + boolean deleteCiscoAsa1000vResource(DeleteCiscoAsa1000vResourceCmd cmd); + + List listCiscoAsa1000vResources(ListCiscoAsa1000vResourcesCmd cmd); + + CiscoAsa1000vDevice assignAsa1000vToNetwork(Network network); + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java new file mode 100644 index 00000000000..443bb40f57f --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java @@ -0,0 +1,928 @@ +// 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.element; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice; +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.AssociateAsaWithLogicalEdgeFirewallCommand; +import com.cloud.agent.api.CleanupLogicalEdgeFirewallCommand; +import com.cloud.agent.api.ConfigureNexusVsmForAsaCommand; +import com.cloud.agent.api.CreateLogicalEdgeFirewallCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupExternalFirewallCommand; +import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.api.routing.SetFirewallRulesCommand; +import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; +import com.cloud.agent.api.routing.SetSourceNatCommand; +import com.cloud.agent.api.routing.SetStaticNatRulesCommand; +import com.cloud.agent.api.to.FirewallRuleTO; +import com.cloud.agent.api.to.IpAddressTO; +import com.cloud.agent.api.to.PortForwardingRuleTO; +import com.cloud.agent.api.to.StaticNatRuleTO; +import com.cloud.api.commands.AddCiscoAsa1000vResourceCmd; +import com.cloud.api.commands.AddCiscoVnmcResourceCmd; +import com.cloud.api.commands.DeleteCiscoAsa1000vResourceCmd; +import com.cloud.api.commands.DeleteCiscoVnmcResourceCmd; +import com.cloud.api.commands.ListCiscoAsa1000vResourcesCmd; +import com.cloud.api.commands.ListCiscoVnmcResourcesCmd; +import com.cloud.api.response.CiscoAsa1000vResourceResponse; +import com.cloud.api.response.CiscoVnmcResourceResponse; +import com.cloud.configuration.ConfigurationManager; +import com.cloud.dc.ClusterVO; +import com.cloud.dc.ClusterVSMMapVO; +import com.cloud.dc.DataCenter; +import com.cloud.dc.Vlan; +import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.VlanVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.ClusterVSMMapDao; +import com.cloud.dc.dao.VlanDao; +import com.cloud.deploy.DeployDestination; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.host.DetailVO; +import com.cloud.host.Host; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.host.dao.HostDetailsDao; +import com.cloud.network.CiscoNexusVSMDeviceVO; +import com.cloud.network.IpAddress; +import com.cloud.network.Network; +import com.cloud.network.NetworkManager; +import com.cloud.network.NetworkModel; +import com.cloud.network.PhysicalNetworkServiceProvider; +import com.cloud.network.dao.PhysicalNetworkVO; +import com.cloud.network.Network.Capability; +import com.cloud.network.Network.Provider; +import com.cloud.network.Network.Service; +import com.cloud.network.Networks.BroadcastDomainType; +import com.cloud.network.PublicIpAddress; +import com.cloud.network.addr.PublicIp; +import com.cloud.network.cisco.CiscoAsa1000vDevice; +import com.cloud.network.cisco.CiscoAsa1000vDeviceVO; +import com.cloud.network.cisco.CiscoVnmcController; +import com.cloud.network.cisco.CiscoVnmcControllerVO; +import com.cloud.network.cisco.NetworkAsa1000vMapVO; +import com.cloud.network.dao.CiscoAsa1000vDao; +import com.cloud.network.dao.CiscoNexusVSMDeviceDao; +import com.cloud.network.dao.CiscoVnmcDao; +import com.cloud.network.dao.NetworkAsa1000vMapDao; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.PhysicalNetworkDao; +import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; +import com.cloud.network.dao.PhysicalNetworkServiceProviderVO; +import com.cloud.network.resource.CiscoVnmcResource; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.rules.StaticNat; +import com.cloud.offering.NetworkOffering; +import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceState; +import com.cloud.resource.ResourceStateAdapter; +import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; +import com.cloud.user.Account; +import com.cloud.utils.component.AdapterBase; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.net.NetUtils; +import com.cloud.vm.NicProfile; +import com.cloud.vm.ReservationContext; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachine.Type; +import com.cloud.vm.VirtualMachineProfile; + +@Local(value = NetworkElement.class) +public class CiscoVnmcElement extends AdapterBase implements SourceNatServiceProvider, FirewallServiceProvider, + PortForwardingServiceProvider, IpDeployer, StaticNatServiceProvider, ResourceStateAdapter, NetworkElement, + CiscoVnmcElementService, CiscoAsa1000vService { + private static final Logger s_logger = Logger.getLogger(CiscoVnmcElement.class); + private static final Map> capabilities = setCapabilities(); + + @Inject + AgentManager _agentMgr; + @Inject + ResourceManager _resourceMgr; + @Inject + ConfigurationManager _configMgr; + @Inject + NetworkManager _networkMgr; + @Inject + NetworkModel _networkModel; + + @Inject + PhysicalNetworkDao _physicalNetworkDao; + @Inject + PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao; + @Inject + HostDetailsDao _hostDetailsDao; + @Inject + HostDao _hostDao; + @Inject + NetworkDao _networkDao; + @Inject + ClusterDao _clusterDao; + @Inject + VlanDao _vlanDao; + @Inject + ClusterVSMMapDao _clusterVsmMapDao; + @Inject + CiscoNexusVSMDeviceDao _vsmDeviceDao; + @Inject + CiscoVnmcDao _ciscoVnmcDao; + @Inject + CiscoAsa1000vDao _ciscoAsa1000vDao; + @Inject + NetworkAsa1000vMapDao _networkAsa1000vMapDao; + + protected boolean canHandle(Network network) { + if (network.getBroadcastDomainType() != BroadcastDomainType.Vlan) { + return false; //TODO: should handle VxLAN as well + } + + return true; + } + + @Override + public boolean configure(String name, Map params) + throws ConfigurationException { + super.configure(name, params); + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); + return true; + } + + private static Map> setCapabilities() { + Map> capabilities = new HashMap>(); + capabilities.put(Service.Gateway, null); + + Map firewallCapabilities = new HashMap(); + firewallCapabilities.put(Capability.TrafficStatistics, "per public ip"); + firewallCapabilities.put(Capability.SupportedTrafficDirection, "ingress,egress"); + firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp"); + firewallCapabilities.put(Capability.SupportedEgressProtocols, "tcp,udp,icmp"); + firewallCapabilities.put(Capability.MultipleIps, "true"); + capabilities.put(Service.Firewall, firewallCapabilities); + + capabilities.put(Service.StaticNat, null); + capabilities.put(Service.PortForwarding, null); + + Map sourceNatCapabilities = new HashMap(); + sourceNatCapabilities.put(Capability.SupportedSourceNatTypes, "peraccount"); + sourceNatCapabilities.put(Capability.RedundantRouter, "false"); //TODO: + capabilities.put(Service.SourceNat, sourceNatCapabilities); + return capabilities; + } + + @Override + public Map> getCapabilities() { + return capabilities; + } + + @Override + public Provider getProvider() { + return Provider.CiscoVnmc; + } + + private boolean createLogicalEdgeFirewall(long vlanId, + String gateway, String gatewayNetmask, + String publicIp, String publicNetmask, + List publicGateways, long hostId) { + CreateLogicalEdgeFirewallCommand cmd = new CreateLogicalEdgeFirewallCommand(vlanId, publicIp, gateway, publicNetmask, gatewayNetmask); + for (String publicGateway : publicGateways) { + cmd.getPublicGateways().add(publicGateway); + } + Answer answer = _agentMgr.easySend(hostId, cmd); + return answer.getResult(); + } + + private boolean configureNexusVsmForAsa(long vlanId, String gateway, + String vsmUsername, String vsmPassword, String vsmIp, + String asaInPortProfile, long hostId) { + ConfigureNexusVsmForAsaCommand cmd = new ConfigureNexusVsmForAsaCommand(vlanId, gateway, vsmUsername, vsmPassword, vsmIp, asaInPortProfile); + Answer answer = _agentMgr.easySend(hostId, cmd); + return answer.getResult(); + } + + private boolean configureSourceNat(long vlanId, String guestCidr, + PublicIp sourceNatIp, long hostId) { + boolean add = (sourceNatIp.getState() == IpAddress.State.Releasing ? false : true); + IpAddressTO ip = new IpAddressTO(sourceNatIp.getAccountId(), sourceNatIp.getAddress().addr(), add, false, + sourceNatIp.isSourceNat(), sourceNatIp.getVlanTag(), sourceNatIp.getGateway(), sourceNatIp.getNetmask(), sourceNatIp.getMacAddress(), + null, sourceNatIp.isOneToOneNat()); + boolean addSourceNat = false; + if (sourceNatIp.isSourceNat()) { + addSourceNat = add; + } + + SetSourceNatCommand cmd = new SetSourceNatCommand(ip, addSourceNat); + cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, Long.toString(vlanId)); + cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, guestCidr); + Answer answer = _agentMgr.easySend(hostId, cmd); + return answer.getResult(); + } + + private boolean associateAsaWithLogicalEdgeFirewall(long vlanId, + String asaMgmtIp, long hostId) { + AssociateAsaWithLogicalEdgeFirewallCommand cmd = + new AssociateAsaWithLogicalEdgeFirewallCommand(vlanId, asaMgmtIp); + Answer answer = _agentMgr.easySend(hostId, cmd); + return answer.getResult(); + } + + @Override + public boolean implement(Network network, NetworkOffering offering, + DeployDestination dest, ReservationContext context) + throws ConcurrentOperationException, ResourceUnavailableException, + InsufficientCapacityException { + DataCenter zone = _configMgr.getZone(network.getDataCenterId()); + + if (zone.getNetworkType() == NetworkType.Basic) { + s_logger.debug("Not handling network implement in zone of type " + NetworkType.Basic); + return false; + } + + if (!canHandle(network)) { + return false; + } + + List devices = _ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId()); + if (devices.isEmpty()) { + s_logger.error("No Cisco Vnmc device on network " + network.getName()); + return false; + } + + List asaList = _ciscoAsa1000vDao.listByPhysicalNetwork(network.getPhysicalNetworkId()); + if (asaList.isEmpty()) { + s_logger.debug("No Cisco ASA 1000v device on network " + network.getName()); + return false; + } + + NetworkAsa1000vMapVO asaForNetwork = _networkAsa1000vMapDao.findByNetworkId(network.getId()); + if (asaForNetwork != null) { + s_logger.debug("Cisco ASA 1000v device already associated with network " + network.getName()); + return true; + } + + if (!_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.SourceNat, Provider.CiscoVnmc)) { + s_logger.error("SourceNat service is not provided by Cisco Vnmc device on network " + network.getName()); + return false; + } + + Transaction txn = Transaction.currentTxn(); + boolean status = false; + try { + txn.start(); + + // ensure that there is an ASA 1000v assigned to this network + CiscoAsa1000vDevice assignedAsa = assignAsa1000vToNetwork(network); + if (assignedAsa == null) { + s_logger.error("Unable to assign ASA 1000v device to network " + network.getName()); + return false; + } + + ClusterVO asaCluster = _clusterDao.findById(assignedAsa.getClusterId()); + ClusterVSMMapVO clusterVsmMap = _clusterVsmMapDao.findByClusterId(assignedAsa.getClusterId()); + if (clusterVsmMap == null) { + s_logger.error("Vmware cluster " + asaCluster.getName() + " has no Cisco Nexus VSM device associated with it"); + return false; + } + + CiscoNexusVSMDeviceVO vsmDevice = _vsmDeviceDao.findById(clusterVsmMap.getVsmId()); + if (vsmDevice == null) { + s_logger.error("Unable to load details of Cisco Nexus VSM device associated with cluster " + asaCluster.getName()); + return false; + } + + CiscoVnmcControllerVO ciscoVnmcDevice = devices.get(0); + HostVO ciscoVnmcHost = _hostDao.findById(ciscoVnmcDevice.getHostId()); + _hostDao.loadDetails(ciscoVnmcHost); + Account owner = context.getAccount(); + PublicIp sourceNatIp = _networkMgr.assignSourceNatIpAddressToGuestNetwork(owner, network); + String vlan = network.getBroadcastUri().getHost(); + long vlanId = Long.parseLong(vlan); + + List vlanVOList = _vlanDao.listVlansByPhysicalNetworkId(network.getPhysicalNetworkId()); + List publicGateways = new ArrayList(); + for (VlanVO vlanVO : vlanVOList) { + publicGateways.add(vlanVO.getVlanGateway()); + } + + // create logical edge firewall in VNMC + String gatewayNetmask = NetUtils.getCidrNetmask(network.getCidr()); + if (!createLogicalEdgeFirewall(vlanId, network.getGateway(), gatewayNetmask, + sourceNatIp.getAddress().addr(), sourceNatIp.getNetmask(), publicGateways, ciscoVnmcHost.getId())) { + s_logger.error("Failed to create logical edge firewall in Cisco VNMC device for network " + network.getName()); + return false; + } + + // create stuff in VSM for ASA device + if (!configureNexusVsmForAsa(vlanId, network.getGateway(), + vsmDevice.getUserName(), vsmDevice.getPassword(), vsmDevice.getipaddr(), + assignedAsa.getInPortProfile(), ciscoVnmcHost.getId())) { + s_logger.error("Failed to configure Cisco Nexus VSM " + vsmDevice.getipaddr() + + " for ASA device for network " + network.getName()); + return false; + } + + // configure source NAT + //if (!configureSourceNat(vlanId, network.getCidr(), sourceNatIp, ciscoVnmcHost.getId())) { + // s_logger.error("Failed to configure source NAT in Cisco VNMC device for network " + network.getName()); + // return false; + //} + + // associate Asa 1000v instance with logical edge firewall + if (!associateAsaWithLogicalEdgeFirewall(vlanId, assignedAsa.getManagementIp(), ciscoVnmcHost.getId())) { + s_logger.error("Failed to associate Cisco ASA 1000v (" + assignedAsa.getManagementIp() + + ") with logical edge firewall in VNMC for network " + network.getName()); + return false; + } + + status = true; + txn.commit(); + } finally { + if (!status) { + txn.rollback(); + //FIXME: also undo changes in VNMC, VSM if anything failed + } + } + + return true; + } + + @Override + public boolean prepare(Network network, NicProfile nic, + VirtualMachineProfile vm, + DeployDestination dest, ReservationContext context) + throws ConcurrentOperationException, ResourceUnavailableException, + InsufficientCapacityException { + if (vm.getType() != Type.User) { + return false; + } + + // ensure that there is an ASA 1000v assigned to this network + NetworkAsa1000vMapVO asaForNetwork = _networkAsa1000vMapDao.findByNetworkId(network.getId()); + if (asaForNetwork == null) { + return false; + } + + return true; + } + + @Override + public boolean release(Network network, NicProfile nic, + VirtualMachineProfile vm, + ReservationContext context) throws ConcurrentOperationException, + ResourceUnavailableException { + return true; + } + + private boolean cleanupLogicalEdgeFirewall(long vlanId, long hostId) { + CleanupLogicalEdgeFirewallCommand cmd = new CleanupLogicalEdgeFirewallCommand(vlanId); + Answer answer = _agentMgr.easySend(hostId, cmd); + return answer.getResult(); + } + + @Override + public boolean shutdown(Network network, ReservationContext context, + boolean cleanup) throws ConcurrentOperationException, + ResourceUnavailableException { + + unassignAsa1000vFromNetwork(network); + + String vlan = network.getBroadcastUri().getHost(); + long vlanId = Long.parseLong(vlan); + List devices = _ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId()); + if (!devices.isEmpty()) { + CiscoVnmcControllerVO ciscoVnmcDevice = devices.get(0); + HostVO ciscoVnmcHost = _hostDao.findById(ciscoVnmcDevice.getHostId()); + cleanupLogicalEdgeFirewall(vlanId, ciscoVnmcHost.getId()); + } + + return true; + } + + @Override + public boolean isReady(PhysicalNetworkServiceProvider provider) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean shutdownProviderInstances( + PhysicalNetworkServiceProvider provider, ReservationContext context) + throws ConcurrentOperationException, ResourceUnavailableException { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean canEnableIndividualServices() { + return true; + } + + @Override + public boolean verifyServicesCombination(Set services) { + if (!services.contains(Service.Firewall)) { + s_logger.warn("CiscoVnmc must be used as Firewall Service Provider in the network"); + return false; + } + return true; + } + + @Override + public boolean destroy(Network network, ReservationContext context) + throws ConcurrentOperationException, ResourceUnavailableException { + return true; + } + + @Override + public List> getCommands() { + List> cmdList = new ArrayList>(); + cmdList.add(AddCiscoVnmcResourceCmd.class); + cmdList.add(DeleteCiscoVnmcResourceCmd.class); + cmdList.add(ListCiscoVnmcResourcesCmd.class); + cmdList.add(AddCiscoAsa1000vResourceCmd.class); + cmdList.add(DeleteCiscoAsa1000vResourceCmd.class); + cmdList.add(ListCiscoAsa1000vResourcesCmd.class); + return cmdList; + } + + @Override + public CiscoVnmcController addCiscoVnmcResource(AddCiscoVnmcResourceCmd cmd) { + String deviceName = Provider.CiscoVnmc.getName(); + NetworkDevice networkDevice = NetworkDevice.getNetworkDevice(deviceName); + Long physicalNetworkId = cmd.getPhysicalNetworkId(); + CiscoVnmcController ciscoVnmcResource = null; + + PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId); + if (physicalNetwork == null) { + throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId); + } + long zoneId = physicalNetwork.getDataCenterId(); + + PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(physicalNetwork.getId(), networkDevice.getNetworkServiceProvder()); + if (ntwkSvcProvider == null) { + throw new CloudRuntimeException("Network Service Provider: " + networkDevice.getNetworkServiceProvder() + + " is not enabled in the physical network: " + physicalNetworkId + "to add this device"); + } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) { + throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() + + " is in shutdown state in the physical network: " + physicalNetworkId + "to add this device"); + } + + if (_ciscoVnmcDao.listByPhysicalNetwork(physicalNetworkId).size() != 0) { + throw new CloudRuntimeException("A Cisco Vnmc device is already configured on this physical network"); + } + + Map params = new HashMap(); + params.put("guid", UUID.randomUUID().toString()); + params.put("zoneId", String.valueOf(physicalNetwork.getDataCenterId())); + params.put("physicalNetworkId", String.valueOf(physicalNetwork.getId())); + params.put("name", "Cisco VNMC Controller - " + cmd.getHost()); + params.put("ip", cmd.getHost()); + params.put("username", cmd.getUsername()); + params.put("password", cmd.getPassword()); + params.put("transportzoneisotype", physicalNetwork.getIsolationMethods().get(0).toLowerCase()); // FIXME What to do with multiple isolation types + + Map hostdetails = new HashMap(); + hostdetails.putAll(params); + + ServerResource resource = new CiscoVnmcResource(); + Transaction txn = Transaction.currentTxn(); + try { + resource.configure(cmd.getHost(), hostdetails); + + Host host = _resourceMgr.addHost(zoneId, resource, Host.Type.ExternalFirewall, params); + if (host != null) { + txn.start(); + + ciscoVnmcResource = new CiscoVnmcControllerVO(host.getId(), physicalNetworkId, ntwkSvcProvider.getProviderName(), deviceName); + _ciscoVnmcDao.persist((CiscoVnmcControllerVO)ciscoVnmcResource); + + DetailVO detail = new DetailVO(host.getId(), "deviceid", String.valueOf(ciscoVnmcResource.getId())); + _hostDetailsDao.persist(detail); + + txn.commit(); + return ciscoVnmcResource; + } else { + throw new CloudRuntimeException("Failed to add Cisco Vnmc device due to internal error."); + } + } catch (ConfigurationException e) { + txn.rollback(); + throw new CloudRuntimeException(e.getMessage()); + } + } + + @Override + public CiscoVnmcResourceResponse createCiscoVnmcResourceResponse( + CiscoVnmcController ciscoVnmcResourceVO) { + HostVO ciscoVnmcHost = _hostDao.findById(ciscoVnmcResourceVO.getHostId()); + + CiscoVnmcResourceResponse response = new CiscoVnmcResourceResponse(); + response.setId(ciscoVnmcResourceVO.getUuid()); + response.setPhysicalNetworkId(ciscoVnmcResourceVO.getPhysicalNetworkId()); + response.setProviderName(ciscoVnmcResourceVO.getProviderName()); + response.setResourceName(ciscoVnmcHost.getName()); + + return response; + } + + @Override + public boolean deleteCiscoVnmcResource(DeleteCiscoVnmcResourceCmd cmd) { + Long vnmcResourceId = cmd.getCiscoVnmcResourceId(); + CiscoVnmcControllerVO vnmcResource = _ciscoVnmcDao.findById(vnmcResourceId); + if (vnmcResource == null) { + throw new InvalidParameterValueException( + "Could not find a Cisco VNMC appliance with id " + vnmcResourceId); + } + + // Check if there any ASA 1000v appliances + Long physicalNetworkId = vnmcResource.getPhysicalNetworkId(); + PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId); + if (physicalNetwork != null) { + List responseList = _ciscoAsa1000vDao.listByPhysicalNetwork(physicalNetworkId); + if (responseList.size() > 0) { + throw new CloudRuntimeException( + "Cisco VNMC appliance with id " + vnmcResourceId + + " cannot be deleted as there Cisco ASA 1000v appliances using it"); + } + } + + HostVO vnmcHost = _hostDao.findById(vnmcResource.getHostId()); + Long hostId = vnmcHost.getId(); + vnmcHost.setResourceState(ResourceState.Maintenance); + _hostDao.update(hostId, vnmcHost); + _resourceMgr.deleteHost(hostId, false, false); + _ciscoVnmcDao.remove(vnmcResourceId); + + return true; + } + + @Override + public List listCiscoVnmcResources( + ListCiscoVnmcResourcesCmd cmd) { + Long physicalNetworkId = cmd.getPhysicalNetworkId(); + Long ciscoVnmcResourceId = cmd.getCiscoVnmcResourceId(); + List responseList = new ArrayList(); + + if (physicalNetworkId == null && ciscoVnmcResourceId == null) { + throw new InvalidParameterValueException("Either physical network Id or vnmc device Id must be specified"); + } + + if (ciscoVnmcResourceId != null) { + CiscoVnmcControllerVO ciscoVnmcResource = _ciscoVnmcDao.findById(ciscoVnmcResourceId); + if (ciscoVnmcResource == null) { + throw new InvalidParameterValueException("Could not find Cisco Vnmc device with id: " + ciscoVnmcResource); + } + responseList.add(ciscoVnmcResource); + } + else { + PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId); + if (physicalNetwork == null) { + throw new InvalidParameterValueException("Could not find a physical network with id: " + physicalNetworkId); + } + responseList = _ciscoVnmcDao.listByPhysicalNetwork(physicalNetworkId); + } + + return responseList; + } + + @Override + public IpDeployer getIpDeployer(Network network) { + return this; + } + + @Override + public boolean applyFWRules(Network network, + List rules) + throws ResourceUnavailableException { + + if (!_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Firewall, Provider.CiscoVnmc)) { + s_logger.error("Firewall service is not provided by Cisco Vnmc device on network " + network.getName()); + return false; + } + + // Find VNMC host for physical network + List devices = _ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId()); + if (devices.isEmpty()) { + s_logger.error("No Cisco Vnmc device on network " + network.getName()); + return true; + } + + // Find if ASA 1000v is associated with network + NetworkAsa1000vMapVO asaForNetwork = _networkAsa1000vMapDao.findByNetworkId(network.getId()); + if (asaForNetwork == null) { + s_logger.debug("Cisco ASA 1000v device is not associated with network " + network.getName()); + return true; + } + + if (network.getState() == Network.State.Allocated) { + s_logger.debug("External firewall was asked to apply firewall rules for network with ID " + network.getId() + "; this network is not implemented. Skipping backend commands."); + return true; + } + + CiscoVnmcControllerVO ciscoVnmcDevice = devices.get(0); + HostVO ciscoVnmcHost = _hostDao.findById(ciscoVnmcDevice.getHostId()); + + List rulesTO = new ArrayList(); + for (FirewallRule rule : rules) { + IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId()); + FirewallRuleTO ruleTO = new FirewallRuleTO(rule, null, sourceIp.getAddress().addr(), rule.getPurpose(), rule.getTrafficType()); + rulesTO.add(ruleTO); + } + + if (!rulesTO.isEmpty()) { + SetFirewallRulesCommand cmd = new SetFirewallRulesCommand(rulesTO); + cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, network.getBroadcastUri().getHost()); + cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, network.getCidr()); + Answer answer = _agentMgr.easySend(ciscoVnmcHost.getId(), cmd); + if (answer == null || !answer.getResult()) { + String details = (answer != null) ? answer.getDetails() : "details unavailable"; + String msg = "Unable to apply firewall rules to Cisco ASA 1000v appliance due to: " + details + "."; + s_logger.error(msg); + throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId()); + } + } + + return true; + } + + @Override + public boolean applyPFRules(Network network, List rules) + throws ResourceUnavailableException { + + if (!_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.PortForwarding, Provider.CiscoVnmc)) { + s_logger.error("Port forwarding service is not provided by Cisco Vnmc device on network " + network.getName()); + return false; + } + + // Find VNMC host for physical network + List devices = _ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId()); + if (devices.isEmpty()) { + s_logger.error("No Cisco Vnmc device on network " + network.getName()); + return true; + } + + // Find if ASA 1000v is associated with network + NetworkAsa1000vMapVO asaForNetwork = _networkAsa1000vMapDao.findByNetworkId(network.getId()); + if (asaForNetwork == null) { + s_logger.debug("Cisco ASA 1000v device is not associated with network " + network.getName()); + return true; + } + + if (network.getState() == Network.State.Allocated) { + s_logger.debug("External firewall was asked to apply port forwarding rules for network with ID " + network.getId() + "; this network is not implemented. Skipping backend commands."); + return true; + } + + CiscoVnmcControllerVO ciscoVnmcDevice = devices.get(0); + HostVO ciscoVnmcHost = _hostDao.findById(ciscoVnmcDevice.getHostId()); + + List rulesTO = new ArrayList(); + for (PortForwardingRule rule : rules) { + IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId()); + Vlan vlan = _vlanDao.findById(sourceIp.getVlanId()); + PortForwardingRuleTO ruleTO = new PortForwardingRuleTO(rule, vlan.getVlanTag(), sourceIp.getAddress().addr()); + rulesTO.add(ruleTO); + } + + if (!rulesTO.isEmpty()) { + SetPortForwardingRulesCommand cmd = new SetPortForwardingRulesCommand(rulesTO); + cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, network.getBroadcastUri().getHost()); + cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, network.getCidr()); + Answer answer = _agentMgr.easySend(ciscoVnmcHost.getId(), cmd); + if (answer == null || !answer.getResult()) { + String details = (answer != null) ? answer.getDetails() : "details unavailable"; + String msg = "Unable to apply port forwarding rules to Cisco ASA 1000v appliance due to: " + details + "."; + s_logger.error(msg); + throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId()); + } + } + + return true; + } + + @Override + public boolean applyStaticNats(Network network, + List rules) + throws ResourceUnavailableException { + if (!_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.StaticNat, Provider.CiscoVnmc)) { + s_logger.error("Static NAT service is not provided by Cisco Vnmc device on network " + network.getName()); + return false; + } + + // Find VNMC host for physical network + List devices = _ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId()); + if (devices.isEmpty()) { + s_logger.error("No Cisco Vnmc device on network " + network.getName()); + return true; + } + + // Find if ASA 1000v is associated with network + NetworkAsa1000vMapVO asaForNetwork = _networkAsa1000vMapDao.findByNetworkId(network.getId()); + if (asaForNetwork == null) { + s_logger.debug("Cisco ASA 1000v device is not associated with network " + network.getName()); + return true; + } + + if (network.getState() == Network.State.Allocated) { + s_logger.debug("External firewall was asked to apply static NAT rules for network with ID " + network.getId() + "; this network is not implemented. Skipping backend commands."); + return true; + } + + CiscoVnmcControllerVO ciscoVnmcDevice = devices.get(0); + HostVO ciscoVnmcHost = _hostDao.findById(ciscoVnmcDevice.getHostId()); + + List rulesTO = new ArrayList(); + for (StaticNat rule : rules) { + IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId()); + StaticNatRuleTO ruleTO = new StaticNatRuleTO(0, sourceIp.getAddress().addr(), null, + null, rule.getDestIpAddress(), null, null, null, rule.isForRevoke(), false); + rulesTO.add(ruleTO); + } + + if (!rulesTO.isEmpty()) { + SetStaticNatRulesCommand cmd = new SetStaticNatRulesCommand(rulesTO, null); + cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, network.getBroadcastUri().getHost()); + cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, network.getCidr()); + Answer answer = _agentMgr.easySend(ciscoVnmcHost.getId(), cmd); + if (answer == null || !answer.getResult()) { + String details = (answer != null) ? answer.getDetails() : "details unavailable"; + String msg = "Unable to apply static NAT rules to Cisco ASA 1000v appliance due to: " + details + "."; + s_logger.error(msg); + throw new ResourceUnavailableException(msg, DataCenter.class, network.getDataCenterId()); + } + } + + return true; + } + + @Override + public boolean applyIps(Network network, + List ipAddress, Set services) + throws ResourceUnavailableException { + // TODO Auto-generated method stub + return false; + } + + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, + StartupCommand[] cmd) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, + StartupCommand[] startup, ServerResource resource, + Map details, List hostTags) { + if (!(startup[0] instanceof StartupExternalFirewallCommand)) { + return null; + } + host.setType(Host.Type.ExternalFirewall); + return host; + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, + boolean isForceDeleteStorage) throws UnableDeleteHostException { + if (host.getType() != com.cloud.host.Host.Type.ExternalFirewall) { + return null; + } + return new DeleteHostAnswer(true); + } + + @Override + public CiscoAsa1000vDevice addCiscoAsa1000vResource( + AddCiscoAsa1000vResourceCmd cmd) { + Long physicalNetworkId = cmd.getPhysicalNetworkId(); + CiscoAsa1000vDevice ciscoAsa1000vResource = null; + + PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId); + if (physicalNetwork == null) { + throw new InvalidParameterValueException("Could not find phyical network with ID: " + physicalNetworkId); + } + + ciscoAsa1000vResource = new CiscoAsa1000vDeviceVO(physicalNetworkId, cmd.getManagementIp(), cmd.getInPortProfile(), cmd.getClusterId()); + _ciscoAsa1000vDao.persist((CiscoAsa1000vDeviceVO)ciscoAsa1000vResource); + + return ciscoAsa1000vResource; + } + + @Override + public CiscoAsa1000vResourceResponse createCiscoAsa1000vResourceResponse( + CiscoAsa1000vDevice ciscoAsa1000vDeviceVO) { + CiscoAsa1000vResourceResponse response = new CiscoAsa1000vResourceResponse(); + response.setId(ciscoAsa1000vDeviceVO.getUuid()); + response.setManagementIp(ciscoAsa1000vDeviceVO.getManagementIp()); + response.setInPortProfile(ciscoAsa1000vDeviceVO.getInPortProfile()); + + NetworkAsa1000vMapVO networkAsaMap = _networkAsa1000vMapDao.findByAsa1000vId(ciscoAsa1000vDeviceVO.getId()); + if (networkAsaMap != null) { + response.setGuestNetworkId(networkAsaMap.getNetworkId()); + } + + return response; + } + + @Override + public boolean deleteCiscoAsa1000vResource( + DeleteCiscoAsa1000vResourceCmd cmd) { + Long asaResourceId = cmd.getCiscoAsa1000vResourceId(); + CiscoAsa1000vDeviceVO asaResource = _ciscoAsa1000vDao.findById(asaResourceId); + if (asaResource == null) { + throw new InvalidParameterValueException( + "Could not find a Cisco ASA 1000v appliance with id " + asaResourceId); + } + + NetworkAsa1000vMapVO networkAsaMap = _networkAsa1000vMapDao.findByAsa1000vId(asaResource.getId()); + if (networkAsaMap != null) { + throw new CloudRuntimeException( + "Cisco ASA 1000v appliance with id " + asaResourceId + + " cannot be deleted as it is associated with guest network"); + } + + _ciscoAsa1000vDao.remove(asaResourceId); + + return true; + } + + @Override + public List listCiscoAsa1000vResources( + ListCiscoAsa1000vResourcesCmd cmd) { + Long physicalNetworkId = cmd.getPhysicalNetworkId(); + Long ciscoAsa1000vResourceId = cmd.getCiscoAsa1000vResourceId(); + List responseList = new ArrayList(); + + if (physicalNetworkId == null && ciscoAsa1000vResourceId == null) { + throw new InvalidParameterValueException("Either physical network Id or Asa 1000v device Id must be specified"); + } + + if (ciscoAsa1000vResourceId != null) { + CiscoAsa1000vDeviceVO ciscoAsa1000vResource = _ciscoAsa1000vDao.findById(ciscoAsa1000vResourceId); + if (ciscoAsa1000vResource == null) { + throw new InvalidParameterValueException("Could not find Cisco Asa 1000v device with id: " + ciscoAsa1000vResourceId); + } + responseList.add(ciscoAsa1000vResource); + } else { + PhysicalNetworkVO physicalNetwork = _physicalNetworkDao.findById(physicalNetworkId); + if (physicalNetwork == null) { + throw new InvalidParameterValueException("Could not find a physical network with id: " + physicalNetworkId); + } + responseList = _ciscoAsa1000vDao.listByPhysicalNetwork(physicalNetworkId); + } + + return responseList; + } + + @Override + public CiscoAsa1000vDevice assignAsa1000vToNetwork(Network network) { + List asaList = _ciscoAsa1000vDao.listByPhysicalNetwork(network.getPhysicalNetworkId()); + for (CiscoAsa1000vDeviceVO asa : asaList) { + NetworkAsa1000vMapVO assignedToNetwork = _networkAsa1000vMapDao.findByAsa1000vId(asa.getId()); + if (assignedToNetwork == null) { + NetworkAsa1000vMapVO networkAsaMap = new NetworkAsa1000vMapVO(network.getId(), asa.getId()); + _networkAsa1000vMapDao.persist(networkAsaMap); + return asa; + } + } + return null; + } + + private void unassignAsa1000vFromNetwork(Network network) { + NetworkAsa1000vMapVO networkAsaMap = _networkAsa1000vMapDao.findByNetworkId(network.getId()); + if (networkAsaMap != null) { + _networkAsa1000vMapDao.remove(networkAsaMap.getId()); + } + } +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElementService.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElementService.java new file mode 100644 index 00000000000..e8eb473154a --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElementService.java @@ -0,0 +1,42 @@ +// 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.element; + +import java.util.List; + +import com.cloud.api.commands.AddCiscoVnmcResourceCmd; +import com.cloud.api.commands.DeleteCiscoVnmcResourceCmd; +import com.cloud.api.commands.ListCiscoVnmcResourcesCmd; +import com.cloud.api.response.CiscoVnmcResourceResponse; +import com.cloud.network.cisco.CiscoVnmcController; +import com.cloud.network.cisco.CiscoVnmcControllerVO; +import com.cloud.utils.component.PluggableService; + +public interface CiscoVnmcElementService extends PluggableService { + + //public static final Provider CiscoVnmc = new Provider("CiscoVnmc", true); + + public CiscoVnmcController addCiscoVnmcResource(AddCiscoVnmcResourceCmd cmd); + + public CiscoVnmcResourceResponse createCiscoVnmcResourceResponse( + CiscoVnmcController CiscoVnmcResourceVO); + + boolean deleteCiscoVnmcResource(DeleteCiscoVnmcResourceCmd cmd); + + List listCiscoVnmcResources(ListCiscoVnmcResourcesCmd cmd); + +} diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java new file mode 100644 index 00000000000..91559782304 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/resource/CiscoVnmcResource.java @@ -0,0 +1,780 @@ +// 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.resource; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.IAgentControl; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.AssociateAsaWithLogicalEdgeFirewallCommand; +import com.cloud.agent.api.CleanupLogicalEdgeFirewallCommand; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.ConfigureNexusVsmForAsaCommand; +import com.cloud.agent.api.CreateLogicalEdgeFirewallCommand; +import com.cloud.agent.api.ExternalNetworkResourceUsageAnswer; +import com.cloud.agent.api.ExternalNetworkResourceUsageCommand; +import com.cloud.agent.api.MaintainAnswer; +import com.cloud.agent.api.MaintainCommand; +import com.cloud.agent.api.PingCommand; +import com.cloud.agent.api.ReadyAnswer; +import com.cloud.agent.api.ReadyCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupExternalFirewallCommand; +import com.cloud.agent.api.routing.IpAssocAnswer; +import com.cloud.agent.api.routing.IpAssocCommand; +import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.api.routing.SetFirewallRulesCommand; +import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; +import com.cloud.agent.api.routing.SetSourceNatCommand; +import com.cloud.agent.api.routing.SetStaticNatRulesCommand; +import com.cloud.agent.api.to.FirewallRuleTO; +import com.cloud.agent.api.to.PortForwardingRuleTO; +import com.cloud.agent.api.to.StaticNatRuleTO; +import com.cloud.host.Host; +import com.cloud.network.cisco.CiscoVnmcConnectionImpl; +import com.cloud.network.rules.FirewallRule.TrafficType; +import com.cloud.resource.ServerResource; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.Pair; +import com.cloud.utils.cisco.n1kv.vsm.NetconfHelper; +import com.cloud.utils.cisco.n1kv.vsm.VsmCommand.OperationType; +import com.cloud.utils.cisco.n1kv.vsm.VsmCommand.SwitchPortMode; +import com.cloud.utils.exception.ExecutionException; +import com.cloud.utils.net.NetUtils; + +public class CiscoVnmcResource implements ServerResource { + + private String _name; + private String _zoneId; + private String _physicalNetworkId; + private String _ip; + private String _username; + private String _password; + private String _guid; + private Integer _numRetries; + + private CiscoVnmcConnectionImpl _connection; + + public void setConnection(CiscoVnmcConnectionImpl connection) { + this._connection = connection; + } + + private final Logger s_logger = Logger.getLogger(CiscoVnmcResource.class); + + public Answer executeRequest(Command cmd) { + if (cmd instanceof ReadyCommand) { + return execute((ReadyCommand) cmd); + } else if (cmd instanceof MaintainCommand) { + return execute((MaintainCommand) cmd); + } else if (cmd instanceof IpAssocCommand) { + return execute((IpAssocCommand) cmd); + } else if (cmd instanceof SetSourceNatCommand) { + return execute((SetSourceNatCommand) cmd); + } else if (cmd instanceof SetFirewallRulesCommand) { + return execute((SetFirewallRulesCommand) cmd); + } else if (cmd instanceof SetStaticNatRulesCommand) { + return execute((SetStaticNatRulesCommand) cmd); + } else if (cmd instanceof SetPortForwardingRulesCommand) { + return execute((SetPortForwardingRulesCommand) cmd); + } else if (cmd instanceof ExternalNetworkResourceUsageCommand) { + return execute((ExternalNetworkResourceUsageCommand) cmd); + } else if (cmd instanceof CreateLogicalEdgeFirewallCommand) { + return execute((CreateLogicalEdgeFirewallCommand)cmd); + } else if (cmd instanceof CleanupLogicalEdgeFirewallCommand) { + return execute((CleanupLogicalEdgeFirewallCommand)cmd); + } else if (cmd instanceof ConfigureNexusVsmForAsaCommand) { + return execute((ConfigureNexusVsmForAsaCommand)cmd); + } else if (cmd instanceof AssociateAsaWithLogicalEdgeFirewallCommand) { + return execute((AssociateAsaWithLogicalEdgeFirewallCommand)cmd); + } else { + return Answer.createUnsupportedCommandAnswer(cmd); + } + } + + public boolean configure(String name, Map params) throws ConfigurationException { + try { + _name = (String) params.get("name"); + if (_name == null) { + throw new ConfigurationException("Unable to find name"); + } + + _zoneId = (String) params.get("zoneId"); + if (_zoneId == null) { + throw new ConfigurationException("Unable to find zone"); + } + + _physicalNetworkId = (String) params.get("physicalNetworkId"); + if (_physicalNetworkId == null) { + throw new ConfigurationException("Unable to find physical network id in the configuration parameters"); + } + + _ip = (String) params.get("ip"); + if (_ip == null) { + throw new ConfigurationException("Unable to find IP"); + } + + _username = (String) params.get("username"); + if (_username == null) { + throw new ConfigurationException("Unable to find username"); + } + + _password = (String) params.get("password"); + if (_password == null) { + throw new ConfigurationException("Unable to find password"); + } + + _guid = (String)params.get("guid"); + if (_guid == null) { + throw new ConfigurationException("Unable to find the guid"); + } + + _numRetries = NumbersUtil.parseInt((String) params.get("numretries"), 1); + + NumbersUtil.parseInt((String) params.get("timeout"), 300); + + // Open a socket and login + _connection = new CiscoVnmcConnectionImpl(_ip, _username, _password); + //if (!refreshVnmcConnection()) { + // throw new ConfigurationException("Unable to open a connection to the VNMC."); + //} + + return true; + } catch (Exception e) { + throw new ConfigurationException(e.getMessage()); + } + + } + + public StartupCommand[] initialize() { + StartupExternalFirewallCommand cmd = new StartupExternalFirewallCommand(); + cmd.setName(_name); + cmd.setDataCenter(_zoneId); + cmd.setPod(""); + cmd.setPrivateIpAddress(_ip); + cmd.setStorageIpAddress(""); + cmd.setVersion(""); + cmd.setGuid(_guid); + return new StartupCommand[] { cmd }; + } + + public Host.Type getType() { + return Host.Type.ExternalFirewall; + } + + @Override + public String getName() { + return _name; + } + + @Override + public boolean start() { + return true; + } + + @Override + public boolean stop() { + return true; + } + + @Override + public PingCommand getCurrentStatus(final long id) { + if (!refreshVnmcConnection()) { + return null; + } + return new PingCommand(Host.Type.ExternalFirewall, id); + } + + @Override + public void disconnected() { + } + + public IAgentControl getAgentControl() { + return null; + } + + public void setAgentControl(IAgentControl agentControl) { + return; + } + + private Answer execute(ReadyCommand cmd) { + return new ReadyAnswer(cmd); + } + + private Answer execute(MaintainCommand cmd) { + return new MaintainAnswer(cmd); + } + + private ExternalNetworkResourceUsageAnswer execute(ExternalNetworkResourceUsageCommand cmd) { + return new ExternalNetworkResourceUsageAnswer(cmd); + } + + /* + * Login + */ + private boolean refreshVnmcConnection() { + boolean ret = false; + try { + ret = _connection.login(); + } catch (ExecutionException ex) { + s_logger.error("Login to Vnmc failed", ex); + } + return ret; + } + + private synchronized Answer execute(IpAssocCommand cmd) { + refreshVnmcConnection(); + return execute(cmd, _numRetries); + } + + private Answer execute(IpAssocCommand cmd, int numRetries) { + String[] results = new String[cmd.getIpAddresses().length]; + return new IpAssocAnswer(cmd, results); + } + + private String[] getIpRangeFromCidr(String cidr) { + String[] result = new String[2]; + String[] cidrData = cidr.split("\\/"); + assert (cidrData.length == 2) : "Something is wrong with source cidr " + cidr; + long size = Long.valueOf(cidrData[1]); + result[0] = cidrData[0]; + result[1] = cidrData[0]; + if (size < 32) { + result[0] = NetUtils.getIpRangeStartIpFromCidr(cidrData[0], size); + result[1] = NetUtils.getIpRangeEndIpFromCidr(cidrData[0], size); + } + return result; + } + + /* + * Source NAT + */ + private synchronized Answer execute(SetSourceNatCommand cmd) { + refreshVnmcConnection(); + return execute(cmd, _numRetries); + } + + private Answer execute(SetSourceNatCommand cmd, int numRetries) { + String vlanId = cmd.getContextParam(NetworkElementCommand.GUEST_VLAN_TAG); + String tenant = "vlan-" + vlanId; + String policyIdentifier = cmd.getIpAddress().getPublicIp().replace('.', '-'); + try { + if (!_connection.createTenantVDCNatPolicySet(tenant)) { + throw new Exception("Failed to create NAT policy set in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.createTenantVDCSourceNatPolicy(tenant, policyIdentifier)) { + throw new Exception("Failed to create source NAT policy in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.createTenantVDCSourceNatPolicyRef(tenant, policyIdentifier)) { + throw new Exception("Failed to associate source NAT policy with NAT policy set in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.createTenantVDCSourceNatIpPool(tenant, policyIdentifier, cmd.getIpAddress().getPublicIp())) { + throw new Exception("Failed to create source NAT ip pool in VNMC for guest network with vlan " + vlanId); + } + + String[] ipRange = getIpRangeFromCidr(cmd.getContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR)); + if (!_connection.createTenantVDCSourceNatRule(tenant, policyIdentifier, ipRange[0], ipRange[1])) { + throw new Exception("Failed to create source NAT rule in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.associateNatPolicySet(tenant)) { + throw new Exception("Failed to associate source NAT policy set with edge security profile in VNMC for guest network with vlan " + vlanId); + } + } catch (Throwable e) { + String msg = "SetSourceNatCommand failed due to " + e.getMessage(); + s_logger.error(msg, e); + return new Answer(cmd, false, msg); + } + + return new Answer(cmd, true, "Success"); + } + + /* + * Firewall rule + */ + private synchronized Answer execute(SetFirewallRulesCommand cmd) { + refreshVnmcConnection(); + return execute(cmd, _numRetries); + } + + private Answer execute(SetFirewallRulesCommand cmd, int numRetries) { + String vlanId = cmd.getContextParam(NetworkElementCommand.GUEST_VLAN_TAG); + String tenant = "vlan-" + vlanId; + + FirewallRuleTO[] rules = cmd.getRules(); + Map> publicIpRulesMap = new HashMap>(); + for (FirewallRuleTO rule : rules) { + String publicIp = rule.getSrcIp(); + if (!publicIpRulesMap.containsKey(publicIp)) { + List publicIpRulesList = new ArrayList(); + publicIpRulesMap.put(publicIp, publicIpRulesList); + } + publicIpRulesMap.get(publicIp).add(rule); + } + + try { + if (!_connection.createTenantVDCAclPolicySet(tenant, true)) { + throw new Exception("Failed to create ACL ingress policy set in VNMC for guest network with vlan " + vlanId); + } + if (!_connection.createTenantVDCAclPolicySet(tenant, false)) { + throw new Exception("Failed to create ACL egress policy set in VNMC for guest network with vlan " + vlanId); + } + + for (String publicIp : publicIpRulesMap.keySet()) { + String policyIdentifier = publicIp.replace('.', '-'); + + if (!_connection.createTenantVDCAclPolicy(tenant, policyIdentifier)) { + throw new Exception("Failed to create ACL policy in VNMC for guest network with vlan " + vlanId); + } + if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, true)) { + throw new Exception("Failed to associate ACL policy with ACL ingress policy set in VNMC for guest network with vlan " + vlanId); + } + if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, false)) { + throw new Exception("Failed to associate ACL policy with ACL egress policy set in VNMC for guest network with vlan " + vlanId); + } + + for (FirewallRuleTO rule : publicIpRulesMap.get(publicIp)) { + if (rule.revoked()) { + if (!_connection.deleteTenantVDCAclRule(tenant, Long.toString(rule.getId()), policyIdentifier)) { + throw new Exception("Failed to delete ACL rule in VNMC for guest network with vlan " + vlanId); + } + } else { + String[] externalIpRange = getIpRangeFromCidr(rule.getSourceCidrList().get(0)); + if (rule.getTrafficType() == TrafficType.Ingress) { + if (!rule.getProtocol().equalsIgnoreCase("icmp")) { + if (!_connection.createTenantVDCIngressAclRule(tenant, + Long.toString(rule.getId()), policyIdentifier, + rule.getProtocol().toUpperCase(), externalIpRange[0], externalIpRange[1], + Integer.toString(rule.getSrcPortRange()[0]), Integer.toString(rule.getSrcPortRange()[1]), publicIp)) { + throw new Exception("Failed to create ACL ingress rule in VNMC for guest network with vlan " + vlanId); + } + } else { + if (!_connection.createTenantVDCIngressAclRule(tenant, + Long.toString(rule.getId()), policyIdentifier, + rule.getProtocol().toUpperCase(), externalIpRange[0], externalIpRange[1], publicIp)) { + throw new Exception("Failed to create ACL ingress rule in VNMC for guest network with vlan " + vlanId); + } + } + } else { + if (!rule.getProtocol().equalsIgnoreCase("icmp")) { + if (!_connection.createTenantVDCEgressAclRule(tenant, + Long.toString(rule.getId()), policyIdentifier, + rule.getProtocol().toUpperCase(), + Integer.toString(rule.getSrcPortRange()[0]), Integer.toString(rule.getSrcPortRange()[1]), publicIp, + externalIpRange[0], externalIpRange[1])) { + throw new Exception("Failed to create ACL egress rule in VNMC for guest network with vlan " + vlanId); + } + } else { + if (!_connection.createTenantVDCEgressAclRule(tenant, + Long.toString(rule.getId()), policyIdentifier, + rule.getProtocol().toUpperCase(), publicIp, externalIpRange[0], externalIpRange[1])) { + throw new Exception("Failed to create ACL egress rule in VNMC for guest network with vlan " + vlanId); + } + } + } + } + } + } + + if (!_connection.associateAclPolicySet(tenant)) { + throw new Exception("Failed to associate ACL policy set with edge security profile in VNMC for guest network with vlan " + vlanId); + } + } catch (Throwable e) { + String msg = "SetFirewallRulesCommand failed due to " + e.getMessage(); + s_logger.error(msg, e); + return new Answer(cmd, false, msg); + } + + return new Answer(cmd, true, "Success"); + } + + /* + * Static NAT + */ + private synchronized Answer execute(SetStaticNatRulesCommand cmd) { + refreshVnmcConnection(); + return execute(cmd, _numRetries); + } + + private Answer execute(SetStaticNatRulesCommand cmd, int numRetries) { + String vlanId = cmd.getContextParam(NetworkElementCommand.GUEST_VLAN_TAG); + String tenant = "vlan-" + vlanId; + + StaticNatRuleTO[] rules = cmd.getRules(); + Map> publicIpRulesMap = new HashMap>(); + for (StaticNatRuleTO rule : rules) { + String publicIp = rule.getSrcIp(); + if (!publicIpRulesMap.containsKey(publicIp)) { + List publicIpRulesList = new ArrayList(); + publicIpRulesMap.put(publicIp, publicIpRulesList); + } + publicIpRulesMap.get(publicIp).add(rule); + } + + try { + if (!_connection.createTenantVDCNatPolicySet(tenant)) { + throw new Exception("Failed to create NAT policy set in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.createTenantVDCAclPolicySet(tenant, true)) { + throw new Exception("Failed to create ACL ingress policy set in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.createTenantVDCAclPolicySet(tenant, false)) { + throw new Exception("Failed to create ACL egress policy set in VNMC for guest network with vlan " + vlanId); + } + + for (String publicIp : publicIpRulesMap.keySet()) { + String policyIdentifier = publicIp.replace('.', '-'); + + if (!_connection.createTenantVDCDNatPolicy(tenant, policyIdentifier)) { + throw new Exception("Failed to create DNAT policy in VNMC for guest network with vlan " + vlanId); + } + if (!_connection.createTenantVDCDNatPolicyRef(tenant, policyIdentifier)) { + throw new Exception("Failed to associate DNAT policy with NAT policy set in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.createTenantVDCAclPolicy(tenant, policyIdentifier)) { + throw new Exception("Failed to create ACL policy in VNMC for guest network with vlan " + vlanId); + } + if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, true)) { + throw new Exception("Failed to associate ACL policy with ACL ingress policy set in VNMC for guest network with vlan " + vlanId); + } + if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, false)) { + throw new Exception("Failed to associate ACL policy with ACL egress policy set in VNMC for guest network with vlan " + vlanId); + } + + for (StaticNatRuleTO rule : publicIpRulesMap.get(publicIp)) { + if (rule.revoked()) { + if (!_connection.deleteTenantVDCDNatRule(tenant, Long.toString(rule.getId()), policyIdentifier)) { + throw new Exception("Failed to delete DNAT rule in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.deleteTenantVDCAclRule(tenant, Long.toString(rule.getId()), policyIdentifier)) { + throw new Exception("Failed to delete ACL ingress rule for DNAT in VNMC for guest network with vlan " + vlanId); + } + } else { + if (!_connection.createTenantVDCDNatIpPool(tenant, policyIdentifier + "-" + rule.getId(), rule.getDstIp())) { + throw new Exception("Failed to create DNAT ip pool in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.createTenantVDCDNatRule(tenant, + Long.toString(rule.getId()), policyIdentifier, rule.getSrcIp())) { + throw new Exception("Failed to create DNAT rule in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.createTenantVDCAclRuleForDNat(tenant, + Long.toString(rule.getId()), policyIdentifier, rule.getDstIp())) { + throw new Exception("Failed to create ACL rule for DNAT in VNMC for guest network with vlan " + vlanId); + } + } + } + } + + if (!_connection.associateAclPolicySet(tenant)) { + throw new Exception("Failed to associate source NAT policy set with edge security profile in VNMC for guest network with vlan " + vlanId); + } + } catch (Throwable e) { + String msg = "SetSourceNatCommand failed due to " + e.getMessage(); + s_logger.error(msg, e); + return new Answer(cmd, false, msg); + } + + return new Answer(cmd, true, "Success"); + } + + /* + * Destination NAT + */ + private synchronized Answer execute(SetPortForwardingRulesCommand cmd) { + refreshVnmcConnection(); + return execute(cmd, _numRetries); + } + + private Answer execute(SetPortForwardingRulesCommand cmd, int numRetries) { + String vlanId = cmd.getContextParam(NetworkElementCommand.GUEST_VLAN_TAG); + String tenant = "vlan-" + vlanId; + + PortForwardingRuleTO[] rules = cmd.getRules(); + Map> publicIpRulesMap = new HashMap>(); + for (PortForwardingRuleTO rule : rules) { + String publicIp = rule.getSrcIp(); + if (!publicIpRulesMap.containsKey(publicIp)) { + List publicIpRulesList = new ArrayList(); + publicIpRulesMap.put(publicIp, publicIpRulesList); + } + publicIpRulesMap.get(publicIp).add(rule); + } + + try { + if (!_connection.createTenantVDCNatPolicySet(tenant)) { + throw new Exception("Failed to create NAT policy set in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.createTenantVDCAclPolicySet(tenant, true)) { + throw new Exception("Failed to create ACL ingress policy set in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.createTenantVDCAclPolicySet(tenant, false)) { + throw new Exception("Failed to create ACL egress policy set in VNMC for guest network with vlan " + vlanId); + } + + for (String publicIp : publicIpRulesMap.keySet()) { + String policyIdentifier = publicIp.replace('.', '-'); + + if (!_connection.createTenantVDCPFPolicy(tenant, policyIdentifier)) { + throw new Exception("Failed to create PF policy in VNMC for guest network with vlan " + vlanId); + } + if (!_connection.createTenantVDCPFPolicyRef(tenant, policyIdentifier)) { + throw new Exception("Failed to associate PF policy with NAT policy set in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.createTenantVDCAclPolicy(tenant, policyIdentifier)) { + throw new Exception("Failed to create ACL policy in VNMC for guest network with vlan " + vlanId); + } + if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, true)) { + throw new Exception("Failed to associate ACL policy with ACL ingress policy set in VNMC for guest network with vlan " + vlanId); + } + if (!_connection.createTenantVDCAclPolicyRef(tenant, policyIdentifier, false)) { + throw new Exception("Failed to associate ACL policy with ACL egress policy set in VNMC for guest network with vlan " + vlanId); + } + + for (PortForwardingRuleTO rule : publicIpRulesMap.get(publicIp)) { + if (rule.revoked()) { + if (!_connection.deleteTenantVDCPFRule(tenant, Long.toString(rule.getId()), policyIdentifier)) { + throw new Exception("Failed to delete PF rule in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.deleteTenantVDCAclRule(tenant, Long.toString(rule.getId()), policyIdentifier)) { + throw new Exception("Failed to delete ACL ingress rule for PF in VNMC for guest network with vlan " + vlanId); + } + } else { + if (!_connection.createTenantVDCPFIpPool(tenant, policyIdentifier + "-" + rule.getId(), rule.getDstIp())) { + throw new Exception("Failed to create PF ip pool in VNMC for guest network with vlan " + vlanId); + } + if (!_connection.createTenantVDCPFPortPool(tenant, policyIdentifier + "-" + rule.getId(), + Integer.toString(rule.getDstPortRange()[0]), Integer.toString(rule.getDstPortRange()[1]))) { + throw new Exception("Failed to create PF port pool in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.createTenantVDCPFRule(tenant, + Long.toString(rule.getId()), policyIdentifier, + rule.getProtocol().toUpperCase(), rule.getSrcIp(), + Integer.toString(rule.getSrcPortRange()[0]), Integer.toString(rule.getSrcPortRange()[1]))) { + throw new Exception("Failed to create PF rule in VNMC for guest network with vlan " + vlanId); + } + + if (!_connection.createTenantVDCAclRuleForPF(tenant, + Long.toString(rule.getId()), policyIdentifier, + rule.getProtocol().toUpperCase(), rule.getDstIp(), + Integer.toString(rule.getDstPortRange()[0]), Integer.toString(rule.getDstPortRange()[1]))) { + throw new Exception("Failed to create ACL rule for PF in VNMC for guest network with vlan " + vlanId); + } + } + } + } + + if (!_connection.associateAclPolicySet(tenant)) { + throw new Exception("Failed to associate source NAT policy set with edge security profile in VNMC for guest network with vlan " + vlanId); + } + } catch (Throwable e) { + String msg = "SetSourceNatCommand failed due to " + e.getMessage(); + s_logger.error(msg, e); + return new Answer(cmd, false, msg); + } + + return new Answer(cmd, true, "Success"); + } + + /* + * Logical edge firewall + */ + private synchronized Answer execute(CreateLogicalEdgeFirewallCommand cmd) { + refreshVnmcConnection(); + return execute(cmd, _numRetries); + } + + private void createEdgeDeviceProfile(String tenant, List gateways, Long vlanId) throws Exception { + // create edge device profile + if (!_connection.createTenantVDCEdgeDeviceProfile(tenant)) + throw new Exception("Failed to create tenant edge device profile in VNMC for guest network with vlan " + vlanId); + + // create edge static route policy + if (!_connection.createTenantVDCEdgeStaticRoutePolicy(tenant)) + throw new Exception("Failed to create tenant edge static route policy in VNMC for guest network with vlan " + vlanId); + + // create edge static route for all gateways + for (String gateway : gateways) { + if (!_connection.createTenantVDCEdgeStaticRoute(tenant, gateway, "0.0.0.0", "0.0.0.0")) + throw new Exception("Failed to create tenant edge static route in VNMC for guest network with vlan " + vlanId); + } + + // associate edge + if (!_connection.associateTenantVDCEdgeStaticRoutePolicy(tenant)) + throw new Exception("Failed to associate edge static route policy with edge device profile in VNMC for guest network with vlan " + vlanId); + } + + private Answer execute(CreateLogicalEdgeFirewallCommand cmd, int numRetries) { + String tenant = "vlan-" + cmd.getVlanId(); + try { + // create tenant + if (!_connection.createTenant(tenant)) + throw new Exception("Failed to create tenant in VNMC for guest network with vlan " + cmd.getVlanId()); + + // create tenant VDC + if (!_connection.createTenantVDC(tenant)) + throw new Exception("Failed to create tenant VDC in VNMC for guest network with vlan " + cmd.getVlanId()); + + // create edge security profile + if (!_connection.createTenantVDCEdgeSecurityProfile(tenant)) + throw new Exception("Failed to create tenant edge security profile in VNMC for guest network with vlan " + cmd.getVlanId()); + + // create edge device profile and associated route + createEdgeDeviceProfile(tenant, cmd.getPublicGateways(), cmd.getVlanId()); + + // create logical edge firewall + if (!_connection.createEdgeFirewall(tenant, cmd.getPublicIp(), cmd.getInternalIp(), cmd.getPublicSubnet(), cmd.getInternalSubnet())) + throw new Exception("Failed to create edge firewall in VNMC for guest network with vlan " + cmd.getVlanId()); + } catch (Throwable e) { + String msg = "CreateLogicalEdgeFirewallCommand failed due to " + e.getMessage(); + s_logger.error(msg, e); + return new Answer(cmd, false, msg); + } + + return new Answer(cmd, true, "Success"); + } + + /* + * Create vservice node and update inside port profile for ASA appliance in VSM + */ + private synchronized Answer execute(ConfigureNexusVsmForAsaCommand cmd) { + return execute(cmd, _numRetries); + } + + private Answer execute(ConfigureNexusVsmForAsaCommand cmd, int numRetries) { + String vlanId = Long.toString(cmd.getVlanId()); + NetconfHelper helper = null; + List> params = new ArrayList>(); + params.add(new Pair(OperationType.addvlanid, vlanId)); + try { + helper = new NetconfHelper(cmd.getVsmIp(), cmd.getVsmUsername(), cmd.getVsmPassword()); + s_logger.debug("Connected to Cisco VSM " + cmd.getVsmIp()); + helper.addVServiceNode(vlanId, cmd.getIpAddress()); + s_logger.debug("Created vservice node for ASA appliance in Cisco VSM for vlan " + vlanId); + helper.updatePortProfile(cmd.getAsaInPortProfile(), SwitchPortMode.access, params); + s_logger.debug("Updated inside port profile for ASA appliance in Cisco VSM with new vlan " + vlanId); + } catch (Throwable e) { + String msg = "ConfigureVSMForASACommand failed due to " + e.getMessage(); + s_logger.error(msg, e); + return new Answer(cmd, false, msg); + } finally { + helper.disconnect(); + } + + return new Answer(cmd, true, "Success"); + } + + /* + * Associates ASA 1000v with logical edge firewall in VNMC + */ + private synchronized Answer execute(AssociateAsaWithLogicalEdgeFirewallCommand cmd) { + return execute(cmd, _numRetries); + } + + private Answer execute(AssociateAsaWithLogicalEdgeFirewallCommand cmd, int numRetries) { + String tenant = "vlan-" + cmd.getVlanId(); + try { + Map availableAsaAppliances = _connection.listUnAssocAsa1000v(); + if (availableAsaAppliances.isEmpty()) { + throw new Exception("No ASA 1000v available to associate with logical edge firewall for guest vlan " + cmd.getVlanId()); + } + + String asaInstanceDn = availableAsaAppliances.get(cmd.getAsaMgmtIp()); + if (asaInstanceDn == null) { + throw new Exception("Requested ASA 1000v (" + cmd.getAsaMgmtIp() + ") is not available"); + } + + if (!_connection.assignAsa1000v(tenant, asaInstanceDn)) { + throw new Exception("Failed to associate ASA 1000v (" + cmd.getAsaMgmtIp() + ") with logical edge firewall for guest vlan " + cmd.getVlanId()); + } + } catch (Throwable e) { + String msg = "AssociateAsaWithLogicalEdgeFirewallCommand failed due to " + e.getMessage(); + s_logger.error(msg, e); + return new Answer(cmd, false, msg); + } + + return new Answer(cmd, true, "Success"); + } + + /* + * Cleanup + */ + private synchronized Answer execute(CleanupLogicalEdgeFirewallCommand cmd) { + refreshVnmcConnection(); + return execute(cmd, _numRetries); + } + + private Answer execute(CleanupLogicalEdgeFirewallCommand cmd, int numRetries) { + String tenant = "vlan-" + cmd.getVlanId(); + try { + _connection.deleteTenant(tenant); + } catch (Throwable e) { + String msg = "CleanupLogicalEdgeFirewallCommand failed due to " + e.getMessage(); + s_logger.error(msg, e); + return new Answer(cmd, false, msg); + } + + return new Answer(cmd, true, "Success"); + } + + @Override + public void setName(String name) { + // TODO Auto-generated method stub + } + + @Override + public void setConfigParams(Map params) { + // TODO Auto-generated method stub + } + + @Override + public Map getConfigParams() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getRunLevel() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void setRunLevel(int level) { + // TODO Auto-generated method stub + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java b/plugins/network-elements/cisco-vnmc/src/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java new file mode 100644 index 00000000000..52f0ea66f50 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java @@ -0,0 +1,232 @@ +/* + * $HeadURL$ + * $Revision$ + * $Date$ + * + * ==================================================================== + * + * 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.commons.httpclient.contrib.ssl; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.UnknownHostException; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; + +import org.apache.commons.httpclient.ConnectTimeoutException; +import org.apache.commons.httpclient.HttpClientError; +import org.apache.commons.httpclient.params.HttpConnectionParams; +import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + *

+ * EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s + * that accept self-signed certificates. + *

+ *

+ * This socket factory SHOULD NOT be used for productive systems + * due to security reasons, unless it is a concious decision and + * you are perfectly aware of security implications of accepting + * self-signed certificates + *

+ * + *

+ * Example of using custom protocol socket factory for a specific host: + *

+ *     Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
+ *
+ *     URI uri = new URI("https://localhost/", true);
+ *     // use relative url only
+ *     GetMethod httpget = new GetMethod(uri.getPathQuery());
+ *     HostConfiguration hc = new HostConfiguration();
+ *     hc.setHost(uri.getHost(), uri.getPort(), easyhttps);
+ *     HttpClient client = new HttpClient();
+ *     client.executeMethod(hc, httpget);
+ *     
+ *

+ *

+ * Example of using custom protocol socket factory per default instead of the standard one: + *

+ *     Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
+ *     Protocol.registerProtocol("https", easyhttps);
+ *
+ *     HttpClient client = new HttpClient();
+ *     GetMethod httpget = new GetMethod("https://localhost/");
+ *     client.executeMethod(httpget);
+ *     
+ *

+ * + * @author Oleg Kalnichevski + * + *

+ * DISCLAIMER: HttpClient developers DO NOT actively support this component. + * The component is provided as a reference material, which may be inappropriate + * for use without additional customization. + *

+ */ + +public class EasySSLProtocolSocketFactory implements SecureProtocolSocketFactory { + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(EasySSLProtocolSocketFactory.class); + + private SSLContext sslcontext = null; + + /** + * Constructor for EasySSLProtocolSocketFactory. + */ + public EasySSLProtocolSocketFactory() { + super(); + } + + private static SSLContext createEasySSLContext() { + try { + SSLContext context = SSLContext.getInstance("SSL"); + context.init( + null, + new TrustManager[] {new EasyX509TrustManager(null)}, + null); + return context; + } catch (Exception e) { + LOG.error(e.getMessage(), e); + throw new HttpClientError(e.toString()); + } + } + + private SSLContext getSSLContext() { + if (this.sslcontext == null) { + this.sslcontext = createEasySSLContext(); + } + return this.sslcontext; + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int) + */ + public Socket createSocket( + String host, + int port, + InetAddress clientHost, + int clientPort) + throws IOException, UnknownHostException { + + return getSSLContext().getSocketFactory().createSocket( + host, + port, + clientHost, + clientPort + ); + } + + /** + * Attempts to get a new socket connection to the given host within the given time limit. + *

+ * To circumvent the limitations of older JREs that do not support connect timeout a + * controller thread is executed. The controller thread attempts to create a new socket + * within the given limit of time. If socket constructor does not return until the + * timeout expires, the controller terminates and throws an {@link ConnectTimeoutException} + *

+ * + * @param host the host name/IP + * @param port the port on the host + * @param clientHost the local host name/IP to bind the socket to + * @param clientPort the port on the local machine + * @param params {@link HttpConnectionParams Http connection parameters} + * + * @return Socket a new socket + * + * @throws IOException if an I/O error occurs while creating the socket + * @throws UnknownHostException if the IP address of the host cannot be + * determined + */ + public Socket createSocket( + final String host, + final int port, + final InetAddress localAddress, + final int localPort, + final HttpConnectionParams params + ) throws IOException, UnknownHostException, ConnectTimeoutException { + if (params == null) { + throw new IllegalArgumentException("Parameters may not be null"); + } + int timeout = params.getConnectionTimeout(); + SocketFactory socketfactory = getSSLContext().getSocketFactory(); + if (timeout == 0) { + return socketfactory.createSocket(host, port, localAddress, localPort); + } else { + Socket socket = socketfactory.createSocket(); + SocketAddress localaddr = new InetSocketAddress(localAddress, localPort); + SocketAddress remoteaddr = new InetSocketAddress(host, port); + socket.bind(localaddr); + socket.connect(remoteaddr, timeout); + return socket; + } + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int) + */ + public Socket createSocket(String host, int port) + throws IOException, UnknownHostException { + return getSSLContext().getSocketFactory().createSocket( + host, + port + ); + } + + /** + * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean) + */ + public Socket createSocket( + Socket socket, + String host, + int port, + boolean autoClose) + throws IOException, UnknownHostException { + return getSSLContext().getSocketFactory().createSocket( + socket, + host, + port, + autoClose + ); + } + + public boolean equals(Object obj) { + return ((obj != null) && obj.getClass().equals(EasySSLProtocolSocketFactory.class)); + } + + public int hashCode() { + return EasySSLProtocolSocketFactory.class.hashCode(); + } + +} diff --git a/plugins/network-elements/cisco-vnmc/src/org/apache/commons/httpclient/contrib/ssl/EasyX509TrustManager.java b/plugins/network-elements/cisco-vnmc/src/org/apache/commons/httpclient/contrib/ssl/EasyX509TrustManager.java new file mode 100644 index 00000000000..ae9f9380b31 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/src/org/apache/commons/httpclient/contrib/ssl/EasyX509TrustManager.java @@ -0,0 +1,114 @@ +/* + * ==================================================================== + * + * 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.commons.httpclient.contrib.ssl; + +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + *

+ * EasyX509TrustManager unlike default {@link X509TrustManager} accepts + * self-signed certificates. + *

+ *

+ * This trust manager SHOULD NOT be used for productive systems + * due to security reasons, unless it is a concious decision and + * you are perfectly aware of security implications of accepting + * self-signed certificates + *

+ * + * @author Adrian Sutton + * @author Oleg Kalnichevski + * + *

+ * DISCLAIMER: HttpClient developers DO NOT actively support this component. + * The component is provided as a reference material, which may be inappropriate + * for use without additional customization. + *

+ */ + +public class EasyX509TrustManager implements X509TrustManager +{ + private X509TrustManager standardTrustManager = null; + + /** Log object for this class. */ + private static final Log LOG = LogFactory.getLog(EasyX509TrustManager.class); + + /** + * Constructor for EasyX509TrustManager. + */ + public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException { + super(); + TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + factory.init(keystore); + TrustManager[] trustmanagers = factory.getTrustManagers(); + if (trustmanagers.length == 0) { + throw new NoSuchAlgorithmException("no trust manager found"); + } + this.standardTrustManager = (X509TrustManager)trustmanagers[0]; + } + + /** + * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],String authType) + */ + public void checkClientTrusted(X509Certificate[] certificates,String authType) throws CertificateException { + standardTrustManager.checkClientTrusted(certificates,authType); + } + + /** + * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],String authType) + */ + public void checkServerTrusted(X509Certificate[] certificates,String authType) throws CertificateException { + if ((certificates != null) && LOG.isDebugEnabled()) { + LOG.debug("Server certificate chain:"); + for (int i = 0; i < certificates.length; i++) { + LOG.debug("X509Certificate[" + i + "]=" + certificates[i]); + } + } + if ((certificates != null) && (certificates.length == 1)) { + certificates[0].checkValidity(); + } else { + standardTrustManager.checkServerTrusted(certificates,authType); + } + } + + /** + * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers() + */ + public X509Certificate[] getAcceptedIssuers() { + return this.standardTrustManager.getAcceptedIssuers(); + } +} diff --git a/plugins/network-elements/cisco-vnmc/test/com/cloud/network/cisco/CiscoVnmcConnectionTest.java b/plugins/network-elements/cisco-vnmc/test/com/cloud/network/cisco/CiscoVnmcConnectionTest.java new file mode 100644 index 00000000000..bf52356779e --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/test/com/cloud/network/cisco/CiscoVnmcConnectionTest.java @@ -0,0 +1,248 @@ +// 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.cisco; + +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +import com.cloud.network.cisco.CiscoVnmcConnectionImpl; +import com.cloud.utils.exception.ExecutionException; + + +@Ignore("Requires actual VNMC to connect to") +public class CiscoVnmcConnectionTest { + static CiscoVnmcConnectionImpl connection; + static String tenantName = "TenantE"; + static Map fwDns = null; + + @BeforeClass + public static void setUpClass() throws Exception { + connection = new CiscoVnmcConnectionImpl("10.223.56.5", "admin", "C1sco123"); + try { + boolean response = connection.login(); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + + @Test + public void testLogin() { + //fail("Not yet implemented"); + try { + boolean response = connection.login(); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + + @Test + public void testCreateTenant() { + //fail("Not yet implemented"); + try { + boolean response = connection.createTenant(tenantName); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCreateTenantVDC() { + //fail("Not yet implemented"); + try { + boolean response = connection.createTenantVDC(tenantName); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCreateTenantVDCEdgeDeviceProfile() { + //fail("Not yet implemented"); + try { + boolean response = connection.createTenantVDCEdgeDeviceProfile(tenantName); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCreateTenantVDCEdgeDeviceRoutePolicy() { + try { + boolean response = connection.createTenantVDCEdgeStaticRoutePolicy(tenantName); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCreateTenantVDCEdgeDeviceRoute() { + try { + boolean response = connection.createTenantVDCEdgeStaticRoute(tenantName, + "10.223.136.1", "0.0.0.0", "0.0.0.0"); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testAssociateRoutePolicyWithEdgeProfile() { + try { + boolean response = connection.associateTenantVDCEdgeStaticRoutePolicy(tenantName); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testAssociateTenantVDCEdgeDhcpPolicy() { + try { + boolean response = connection.associateTenantVDCEdgeDhcpPolicy(tenantName, "Edge_Inside"); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCreateTenantVDCEdgeDhcpPolicy() { + try { + boolean response = connection.createTenantVDCEdgeDhcpPolicy(tenantName, + "10.1.1.2", "10.1.1.254", "255.255.255.0","4.4.4.4", tenantName+ ".net"); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCreateTenantVDCEdgeSecurityProfile() { + try { + boolean response = connection.createTenantVDCEdgeSecurityProfile(tenantName); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCreateTenantVDCSourceNatIpPool() { + try { + boolean response = connection.createTenantVDCSourceNatIpPool(tenantName, "1", "10.223.136.10"); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCreateTenantVDCSourceNatPolicy() { + try { + boolean response = connection.createTenantVDCSourceNatPolicy(tenantName, "1"); + assertTrue(response); + response = connection.createTenantVDCSourceNatPolicyRef(tenantName, "1"); + assertTrue(response); + response = connection.createTenantVDCSourceNatRule(tenantName, "1", "10.1.1.2", "10.1.1.254"); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCreateTenantVDCNatPolicySet() { + try { + boolean response = connection.createTenantVDCNatPolicySet(tenantName); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testAssociateNatPolicySet() { + try { + boolean response = connection.associateNatPolicySet(tenantName); + assertTrue(response); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void testCreateEdgeFirewall() { + try { + boolean response = connection.createEdgeFirewall(tenantName, + "44.44.44.44", "192.168.1.1", "255.255.255.0", "255.255.255.192"); + assertTrue(response); + } catch (ExecutionException e) { + e.printStackTrace(); + } + } + + @Test + public void testListUnassocAsa1000v() { + try { + Map response = connection.listUnAssocAsa1000v(); + assertTrue(response.size() >=0); + fwDns = response; + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + @Test + public void assocAsa1000v() { + try { + boolean result = connection.assignAsa1000v(tenantName, fwDns.get(0)); + assertTrue(result); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/plugins/network-elements/cisco-vnmc/test/com/cloud/network/element/CiscoVnmcElementTest.java b/plugins/network-elements/cisco-vnmc/test/com/cloud/network/element/CiscoVnmcElementTest.java new file mode 100755 index 00000000000..a16733b5135 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/test/com/cloud/network/element/CiscoVnmcElementTest.java @@ -0,0 +1,401 @@ +// 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.element; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.naming.ConfigurationException; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.internal.matchers.Any; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.AssociateAsaWithLogicalEdgeFirewallCommand; +import com.cloud.agent.api.CleanupLogicalEdgeFirewallCommand; +import com.cloud.agent.api.ConfigureNexusVsmForAsaCommand; +import com.cloud.agent.api.CreateLogicalEdgeFirewallCommand; +import com.cloud.agent.api.routing.SetFirewallRulesCommand; +import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; +import com.cloud.agent.api.routing.SetSourceNatCommand; +import com.cloud.agent.api.routing.SetStaticNatRulesCommand; +import com.cloud.configuration.ConfigurationManager; +import com.cloud.dc.ClusterVSMMapVO; +import com.cloud.dc.DataCenter; +import com.cloud.dc.VlanVO; +import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.dao.ClusterVSMMapDao; +import com.cloud.dc.dao.VlanDao; +import com.cloud.deploy.DeployDestination; +import com.cloud.domain.Domain; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InsufficientCapacityException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.network.Network; +import com.cloud.network.Network.GuestType; +import com.cloud.network.Network.Provider; +import com.cloud.network.Network.Service; +import com.cloud.network.CiscoNexusVSMDeviceVO; +import com.cloud.network.IpAddress; +import com.cloud.network.NetworkManager; +import com.cloud.network.NetworkModel; +import com.cloud.network.Networks.BroadcastDomainType; +import com.cloud.network.Networks.TrafficType; +import com.cloud.network.addr.PublicIp; +import com.cloud.network.cisco.CiscoAsa1000vDeviceVO; +import com.cloud.network.cisco.CiscoVnmcControllerVO; +import com.cloud.network.cisco.NetworkAsa1000vMapVO; +import com.cloud.network.dao.CiscoAsa1000vDao; +import com.cloud.network.dao.CiscoNexusVSMDeviceDao; +import com.cloud.network.dao.CiscoVnmcDao; +import com.cloud.network.dao.NetworkAsa1000vMapDao; +import com.cloud.network.dao.NetworkServiceMapDao; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.rules.StaticNat; +import com.cloud.network.rules.StaticNatRule; +import com.cloud.offering.NetworkOffering; +import com.cloud.resource.ResourceManager; +import com.cloud.user.Account; +import com.cloud.utils.net.Ip; +import com.cloud.vm.ReservationContext; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class CiscoVnmcElementTest { + + CiscoVnmcElement _element = new CiscoVnmcElement(); + AgentManager _agentMgr = mock(AgentManager.class); + NetworkManager _networkMgr = mock(NetworkManager.class); + NetworkModel _networkModel = mock(NetworkModel.class); + HostDao _hostDao = mock(HostDao.class); + NetworkServiceMapDao _ntwkSrvcDao = mock(NetworkServiceMapDao.class); + ConfigurationManager _configMgr = mock(ConfigurationManager.class); + CiscoVnmcDao _ciscoVnmcDao = mock(CiscoVnmcDao.class); + CiscoAsa1000vDao _ciscoAsa1000vDao = mock(CiscoAsa1000vDao.class); + NetworkAsa1000vMapDao _networkAsa1000vMapDao = mock(NetworkAsa1000vMapDao.class); + ClusterVSMMapDao _clusterVsmMapDao = mock(ClusterVSMMapDao.class); + CiscoNexusVSMDeviceDao _vsmDeviceDao = mock(CiscoNexusVSMDeviceDao.class); + VlanDao _vlanDao = mock(VlanDao.class); + + @Before + public void setUp() throws ConfigurationException { + _element._resourceMgr = mock(ResourceManager.class); + _element._agentMgr = _agentMgr; + _element._networkMgr = _networkMgr; + _element._networkModel = _networkModel; + _element._hostDao = _hostDao; + _element._configMgr = _configMgr; + _element._ciscoVnmcDao = _ciscoVnmcDao; + _element._ciscoAsa1000vDao = _ciscoAsa1000vDao; + _element._networkAsa1000vMapDao = _networkAsa1000vMapDao; + _element._clusterVsmMapDao = _clusterVsmMapDao; + _element._vsmDeviceDao = _vsmDeviceDao; + _element._vlanDao = _vlanDao; + + // Standard responses + when(_networkModel.isProviderForNetwork(Provider.CiscoVnmc, 1L)).thenReturn(true); + + _element.configure("CiscoVnmcTestElement", Collections. emptyMap()); + } + + @Test + public void canHandleTest() { + Network network = mock(Network.class); + when(network.getId()).thenReturn(1L); + when(network.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Vlan); + assertTrue(_element.canHandle(network)); + + when(network.getBroadcastDomainType()).thenReturn(BroadcastDomainType.UnDecided); + assertFalse(_element.canHandle(network)); + } + + @Test + public void implementTest() throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + URI uri = URI.create("vlan://123"); + + Network network = mock(Network.class); + when(network.getId()).thenReturn(1L); + when(network.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Vlan); + when(network.getDataCenterId()).thenReturn(1L); + when(network.getGateway()).thenReturn("1.1.1.1"); + when(network.getBroadcastUri()).thenReturn(uri); + when(network.getCidr()).thenReturn("1.1.1.0/24"); + + NetworkOffering offering = mock(NetworkOffering.class); + when(offering.getId()).thenReturn(1L); + when(offering.getTrafficType()).thenReturn(TrafficType.Guest); + when(offering.getGuestType()).thenReturn(GuestType.Isolated); + + DeployDestination dest = mock(DeployDestination.class); + + Domain dom = mock(Domain.class); + when(dom.getName()).thenReturn("d1"); + Account acc = mock(Account.class); + when(acc.getAccountName()).thenReturn("a1"); + ReservationContext context = mock(ReservationContext.class); + when(context.getDomain()).thenReturn(dom); + when(context.getAccount()).thenReturn(acc); + + DataCenter dc = mock(DataCenter.class); + when(dc.getNetworkType()).thenReturn(NetworkType.Advanced); + when(_configMgr.getZone(network.getDataCenterId())).thenReturn(dc); + + List devices = new ArrayList(); + devices.add(mock(CiscoVnmcControllerVO.class)); + when(_ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId())).thenReturn(devices); + + CiscoAsa1000vDeviceVO asaVO = mock(CiscoAsa1000vDeviceVO.class); + when(asaVO.getInPortProfile()).thenReturn("foo"); + when(asaVO.getManagementIp()).thenReturn("1.2.3.4"); + + List asaList = new ArrayList(); + asaList.add(asaVO); + when(_ciscoAsa1000vDao.listByPhysicalNetwork(network.getPhysicalNetworkId())).thenReturn(asaList); + + when(_networkAsa1000vMapDao.findByNetworkId(network.getId())).thenReturn(mock(NetworkAsa1000vMapVO.class)); + when(_networkAsa1000vMapDao.findByAsa1000vId(anyLong())).thenReturn(null); + when(_networkAsa1000vMapDao.persist(any(NetworkAsa1000vMapVO.class))).thenReturn(mock(NetworkAsa1000vMapVO.class)); + + when(_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.SourceNat, Provider.CiscoVnmc)).thenReturn(true); + + ClusterVSMMapVO clusterVsmMap = mock(ClusterVSMMapVO.class); + when(_clusterVsmMapDao.findByClusterId(anyLong())).thenReturn(clusterVsmMap); + + CiscoNexusVSMDeviceVO vsmDevice = mock(CiscoNexusVSMDeviceVO.class); + when(vsmDevice.getUserName()).thenReturn("foo"); + when(vsmDevice.getPassword()).thenReturn("bar"); + when(vsmDevice.getipaddr()).thenReturn("1.2.3.4"); + when(_vsmDeviceDao.findById(anyLong())).thenReturn(vsmDevice); + + HostVO hostVO = mock(HostVO.class); + when(hostVO.getId()).thenReturn(1L); + when(_hostDao.findById(anyLong())).thenReturn(hostVO); + + Ip ip = mock(Ip.class); + when(ip.addr()).thenReturn("1.2.3.4"); + + PublicIp publicIp = mock(PublicIp.class); + when(publicIp.getAddress()).thenReturn(ip); + when(publicIp.getState()).thenReturn(IpAddress.State.Releasing); + when(publicIp.getAccountId()).thenReturn(1L); + when(publicIp.isSourceNat()).thenReturn(true); + when(publicIp.getVlanTag()).thenReturn("123"); + when(publicIp.getGateway()).thenReturn("1.1.1.1"); + when(publicIp.getNetmask()).thenReturn("1.1.1.1"); + when(publicIp.getMacAddress()).thenReturn(null); + when(publicIp.isOneToOneNat()).thenReturn(true); + when(_networkMgr.assignSourceNatIpAddressToGuestNetwork(acc, network)).thenReturn(publicIp); + + VlanVO vlanVO = mock(VlanVO.class); + when(vlanVO.getVlanGateway()).thenReturn("1.1.1.1"); + List vlanVOList = new ArrayList(); + when(_vlanDao.listVlansByPhysicalNetworkId(network.getPhysicalNetworkId())).thenReturn(vlanVOList); + + Answer answer = mock(Answer.class); + when(answer.getResult()).thenReturn(true); + + when(_agentMgr.easySend(anyLong(), any(CreateLogicalEdgeFirewallCommand.class))).thenReturn(answer); + when(_agentMgr.easySend(anyLong(), any(ConfigureNexusVsmForAsaCommand.class))).thenReturn(answer); + when(_agentMgr.easySend(anyLong(), any(SetSourceNatCommand.class))).thenReturn(answer); + when(_agentMgr.easySend(anyLong(), any(AssociateAsaWithLogicalEdgeFirewallCommand.class))).thenReturn(answer); + + assertTrue(_element.implement(network, offering, dest, context)); + } + + @Test + public void shutdownTest() throws ConcurrentOperationException, ResourceUnavailableException { + URI uri = URI.create("vlan://123"); + + Network network = mock(Network.class); + when(network.getId()).thenReturn(1L); + when(network.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Vlan); + when(network.getDataCenterId()).thenReturn(1L); + when(network.getBroadcastUri()).thenReturn(uri); + + ReservationContext context = mock(ReservationContext.class); + + when(_networkAsa1000vMapDao.findByNetworkId(network.getId())).thenReturn(mock(NetworkAsa1000vMapVO.class)); + + List devices = new ArrayList(); + devices.add(mock(CiscoVnmcControllerVO.class)); + when(_ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId())).thenReturn(devices); + + HostVO hostVO = mock(HostVO.class); + when(hostVO.getId()).thenReturn(1L); + when(_hostDao.findById(anyLong())).thenReturn(hostVO); + + Answer answer = mock(Answer.class); + when(answer.getResult()).thenReturn(true); + + when(_agentMgr.easySend(anyLong(), any(CleanupLogicalEdgeFirewallCommand.class))).thenReturn(answer); + + assertTrue(_element.shutdown(network, context, true)); + } + + @Test + public void applyFWRulesTest() throws ResourceUnavailableException { + URI uri = URI.create("vlan://123"); + + Network network = mock(Network.class); + when(network.getId()).thenReturn(1L); + when(network.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Vlan); + when(network.getDataCenterId()).thenReturn(1L); + when(network.getBroadcastUri()).thenReturn(uri); + when(network.getCidr()).thenReturn("1.1.1.0/24"); + when(network.getState()).thenReturn(Network.State.Implemented); + + Ip ip = mock(Ip.class); + when(ip.addr()).thenReturn("1.2.3.4"); + + IpAddress ipAddress = mock(IpAddress.class); + when(ipAddress.getAddress()).thenReturn(ip); + + when(_networkModel.getIp(anyLong())).thenReturn(ipAddress); + when(_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Firewall, Provider.CiscoVnmc)).thenReturn(true); + + List devices = new ArrayList(); + devices.add(mock(CiscoVnmcControllerVO.class)); + when(_ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId())).thenReturn(devices); + + when(_networkAsa1000vMapDao.findByNetworkId(network.getId())).thenReturn(mock(NetworkAsa1000vMapVO.class)); + + HostVO hostVO = mock(HostVO.class); + when(hostVO.getId()).thenReturn(1L); + when(_hostDao.findById(anyLong())).thenReturn(hostVO); + + FirewallRule rule = mock(FirewallRule.class); + when(rule.getSourceIpAddressId()).thenReturn(1L); + List rules = new ArrayList(); + rules.add(rule); + + Answer answer = mock(Answer.class); + when(answer.getResult()).thenReturn(true); + + when(_agentMgr.easySend(anyLong(), any(SetFirewallRulesCommand.class))).thenReturn(answer); + + assertTrue(_element.applyFWRules(network, rules)); + } + + @Test + public void applyPRulesTest() throws ResourceUnavailableException { + URI uri = URI.create("vlan://123"); + + Network network = mock(Network.class); + when(network.getId()).thenReturn(1L); + when(network.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Vlan); + when(network.getDataCenterId()).thenReturn(1L); + when(network.getBroadcastUri()).thenReturn(uri); + when(network.getCidr()).thenReturn("1.1.1.0/24"); + when(network.getState()).thenReturn(Network.State.Implemented); + + Ip ip = mock(Ip.class); + when(ip.addr()).thenReturn("1.2.3.4"); + + IpAddress ipAddress = mock(IpAddress.class); + when(ipAddress.getAddress()).thenReturn(ip); + when(ipAddress.getVlanId()).thenReturn(1L); + + when(_networkModel.getIp(anyLong())).thenReturn(ipAddress); + when(_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.PortForwarding, Provider.CiscoVnmc)).thenReturn(true); + + List devices = new ArrayList(); + devices.add(mock(CiscoVnmcControllerVO.class)); + when(_ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId())).thenReturn(devices); + + when(_networkAsa1000vMapDao.findByNetworkId(network.getId())).thenReturn(mock(NetworkAsa1000vMapVO.class)); + + HostVO hostVO = mock(HostVO.class); + when(hostVO.getId()).thenReturn(1L); + when(_hostDao.findById(anyLong())).thenReturn(hostVO); + + VlanVO vlanVO = mock(VlanVO.class); + when(vlanVO.getVlanTag()).thenReturn(null); + when(_vlanDao.findById(anyLong())).thenReturn(vlanVO); + + PortForwardingRule rule = mock(PortForwardingRule.class); + when(rule.getSourceIpAddressId()).thenReturn(1L); + when(rule.getDestinationIpAddress()).thenReturn(ip); + List rules = new ArrayList(); + rules.add(rule); + + Answer answer = mock(Answer.class); + when(answer.getResult()).thenReturn(true); + + when(_agentMgr.easySend(anyLong(), any(SetPortForwardingRulesCommand.class))).thenReturn(answer); + + assertTrue(_element.applyPFRules(network, rules)); + } + + @Test + public void applyStaticNatsTest() throws ResourceUnavailableException { + URI uri = URI.create("vlan://123"); + + Network network = mock(Network.class); + when(network.getId()).thenReturn(1L); + when(network.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Vlan); + when(network.getDataCenterId()).thenReturn(1L); + when(network.getBroadcastUri()).thenReturn(uri); + when(network.getCidr()).thenReturn("1.1.1.0/24"); + when(network.getState()).thenReturn(Network.State.Implemented); + + Ip ip = mock(Ip.class); + when(ip.addr()).thenReturn("1.2.3.4"); + + IpAddress ipAddress = mock(IpAddress.class); + when(ipAddress.getAddress()).thenReturn(ip); + when(ipAddress.getVlanId()).thenReturn(1L); + + when(_networkModel.getIp(anyLong())).thenReturn(ipAddress); + when(_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.StaticNat, Provider.CiscoVnmc)).thenReturn(true); + + List devices = new ArrayList(); + devices.add(mock(CiscoVnmcControllerVO.class)); + when(_ciscoVnmcDao.listByPhysicalNetwork(network.getPhysicalNetworkId())).thenReturn(devices); + + when(_networkAsa1000vMapDao.findByNetworkId(network.getId())).thenReturn(mock(NetworkAsa1000vMapVO.class)); + + HostVO hostVO = mock(HostVO.class); + when(hostVO.getId()).thenReturn(1L); + when(_hostDao.findById(anyLong())).thenReturn(hostVO); + + VlanVO vlanVO = mock(VlanVO.class); + when(vlanVO.getVlanTag()).thenReturn(null); + when(_vlanDao.findById(anyLong())).thenReturn(vlanVO); + + StaticNat rule = mock(StaticNat.class); + when(rule.getSourceIpAddressId()).thenReturn(1L); + when(rule.getDestIpAddress()).thenReturn("1.2.3.4"); + when(rule.isForRevoke()).thenReturn(false); + List rules = new ArrayList(); + rules.add(rule); + + Answer answer = mock(Answer.class); + when(answer.getResult()).thenReturn(true); + + when(_agentMgr.easySend(anyLong(), any(SetStaticNatRulesCommand.class))).thenReturn(answer); + + assertTrue(_element.applyStaticNats(network, rules)); + } +} diff --git a/plugins/network-elements/cisco-vnmc/test/com/cloud/network/resource/CiscoVnmcResourceTest.java b/plugins/network-elements/cisco-vnmc/test/com/cloud/network/resource/CiscoVnmcResourceTest.java new file mode 100755 index 00000000000..e814fdcd4d5 --- /dev/null +++ b/plugins/network-elements/cisco-vnmc/test/com/cloud/network/resource/CiscoVnmcResourceTest.java @@ -0,0 +1,285 @@ +// 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.resource; + +import static org.junit.Assert.*; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.naming.ConfigurationException; + +import org.junit.Before; +import org.junit.Test; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.CreateLogicalEdgeFirewallCommand; +import com.cloud.agent.api.PingCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.api.routing.SetFirewallRulesCommand; +import com.cloud.agent.api.routing.SetPortForwardingRulesCommand; +import com.cloud.agent.api.routing.SetSourceNatCommand; +import com.cloud.agent.api.routing.SetStaticNatRulesCommand; +import com.cloud.agent.api.to.FirewallRuleTO; +import com.cloud.agent.api.to.IpAddressTO; +import com.cloud.agent.api.to.PortForwardingRuleTO; +import com.cloud.agent.api.to.StaticNatRuleTO; +import com.cloud.dc.Vlan; +import com.cloud.host.Host; +import com.cloud.network.IpAddress; +import com.cloud.network.cisco.CiscoVnmcConnectionImpl; +import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.rules.StaticNat; +import com.cloud.network.rules.FirewallRule.Purpose; +import com.cloud.network.rules.FirewallRule.TrafficType; +import com.cloud.network.rules.FirewallRuleVO; +import com.cloud.utils.exception.ExecutionException; + +public class CiscoVnmcResourceTest { + CiscoVnmcConnectionImpl _connection = mock(CiscoVnmcConnectionImpl.class); + CiscoVnmcResource _resource; + Map _parameters; + + @Before + public void setUp() throws ConfigurationException { + _resource = new CiscoVnmcResource(); + + _parameters = new HashMap(); + _parameters.put("name", "CiscoVnmc"); + _parameters.put("zoneId", "1"); + _parameters.put("physicalNetworkId", "100"); + _parameters.put("ip", "1.2.3.4"); + _parameters.put("username", "admin"); + _parameters.put("password", "pass"); + _parameters.put("guid", "e8e13097-0a08-4e82-b0af-1101589ec3b8"); + _parameters.put("numretries", "3"); + _parameters.put("timeout", "300"); + } + + @Test(expected=ConfigurationException.class) + public void resourceConfigureFailure() throws ConfigurationException { + _resource.configure("CiscoVnmcResource", Collections.emptyMap()); + } + + @Test + public void resourceConfigure() throws ConfigurationException { + _resource.configure("CiscoVnmcResource", _parameters); + assertTrue("CiscoVnmc".equals(_resource.getName())); + assertTrue(_resource.getType() == Host.Type.ExternalFirewall); + } + + @Test + public void testInitialization() throws ConfigurationException { + _resource.configure("CiscoVnmcResource", _parameters); + StartupCommand[] sc = _resource.initialize(); + assertTrue(sc.length ==1); + assertTrue("e8e13097-0a08-4e82-b0af-1101589ec3b8".equals(sc[0].getGuid())); + assertTrue("CiscoVnmc".equals(sc[0].getName())); + assertTrue("1".equals(sc[0].getDataCenter())); + } + + @Test + public void testPingCommandStatusOk() throws ConfigurationException, ExecutionException { + _resource.configure("CiscoVnmcResource", _parameters); + _resource.setConnection(_connection); + when(_connection.login()).thenReturn(true); + PingCommand ping = _resource.getCurrentStatus(1); + assertTrue(ping != null); + assertTrue(ping.getHostId() == 1); + assertTrue(ping.getHostType() == Host.Type.ExternalFirewall); + } + + @Test + public void testPingCommandStatusFail() throws ConfigurationException, ExecutionException { + _resource.configure("CiscoVnmcResource", _parameters); + _resource.setConnection(_connection); + when(_connection.login()).thenReturn(false); + PingCommand ping = _resource.getCurrentStatus(1); + assertTrue(ping == null); + } + + @Test + public void testSourceNat() throws ConfigurationException, Exception { + long vlanId = 123; + IpAddressTO ip = new IpAddressTO(1, "1.2.3.4", true, false, + false, null, "1.2.3.1", "255.255.255.0", null, null, false); + SetSourceNatCommand cmd = new SetSourceNatCommand(ip, true); + cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, Long.toString(vlanId)); + cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, "1.2.3.4/32"); + + _resource.configure("CiscoVnmcResource", _parameters); + _resource.setConnection(_connection); + when(_connection.login()).thenReturn(true); + when(_connection.createTenantVDCNatPolicySet(anyString())).thenReturn(true); + when(_connection.createTenantVDCSourceNatPolicy(anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCSourceNatPolicyRef(anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCSourceNatIpPool(anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCSourceNatRule(anyString(), anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.associateNatPolicySet(anyString())).thenReturn(true); + + Answer answer = _resource.executeRequest(cmd); + System.out.println(answer.getDetails()); + assertTrue(answer.getResult()); + } + + @Test + public void testFirewall() throws ConfigurationException, Exception { + long vlanId = 123; + List rules = new ArrayList(); + List cidrList = new ArrayList(); + cidrList.add("2.3.2.3/32"); + FirewallRuleTO active = new FirewallRuleTO(1, + null, "1.2.3.4", "tcp", 22, 22, false, false, + FirewallRule.Purpose.Firewall, cidrList, null, null); + rules.add(active); + FirewallRuleTO revoked = new FirewallRuleTO(1, + null, "1.2.3.4", "tcp", 22, 22, true, false, + FirewallRule.Purpose.Firewall, null, null, null); + rules.add(revoked); + + SetFirewallRulesCommand cmd = new SetFirewallRulesCommand(rules); + cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, Long.toString(vlanId)); + cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, "1.2.3.4/32"); + + _resource.configure("CiscoVnmcResource", _parameters); + _resource.setConnection(_connection); + when(_connection.createTenantVDCAclPolicySet(anyString(), anyBoolean())).thenReturn(true); + when(_connection.createTenantVDCAclPolicy(anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCAclPolicyRef(anyString(), anyString(), anyBoolean())).thenReturn(true); + when(_connection.deleteTenantVDCAclRule(anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCIngressAclRule( + anyString(), anyString(), anyString(), + anyString(), anyString(), anyString(), + anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCEgressAclRule( + anyString(), anyString(), anyString(), + anyString(), anyString(), anyString(), + anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.associateAclPolicySet(anyString())).thenReturn(true); + + Answer answer = _resource.executeRequest(cmd); + System.out.println(answer.getDetails()); + assertTrue(answer.getResult()); + } + + @Test + public void testStaticNat() throws ConfigurationException, Exception { + long vlanId = 123; + List rules = new ArrayList(); + StaticNatRuleTO active = new StaticNatRuleTO(0, "1.2.3.4", null, + null, "5.6.7.8", null, null, null, false, false); + rules.add(active); + StaticNatRuleTO revoked = new StaticNatRuleTO(0, "1.2.3.4", null, + null, "5.6.7.8", null, null, null, true, false); + rules.add(revoked); + + SetStaticNatRulesCommand cmd = new SetStaticNatRulesCommand(rules, null); + cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, Long.toString(vlanId)); + cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, "1.2.3.4/32"); + + _resource.configure("CiscoVnmcResource", _parameters); + _resource.setConnection(_connection); + when(_connection.createTenantVDCNatPolicySet(anyString())).thenReturn(true); + when(_connection.createTenantVDCAclPolicySet(anyString(), anyBoolean())).thenReturn(true); + when(_connection.createTenantVDCDNatPolicy(anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCDNatPolicyRef(anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCAclPolicy(anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCAclPolicyRef(anyString(), anyString(), anyBoolean())).thenReturn(true); + when(_connection.deleteTenantVDCDNatRule(anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.deleteTenantVDCAclRule(anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCDNatIpPool(anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCDNatRule(anyString(), + anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCAclRuleForDNat(anyString(), + anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.associateAclPolicySet(anyString())).thenReturn(true); + + Answer answer = _resource.executeRequest(cmd); + System.out.println(answer.getDetails()); + assertTrue(answer.getResult()); + } + + @Test + public void testPortForwarding() throws ConfigurationException, Exception { + long vlanId = 123; + List rules = new ArrayList(); + PortForwardingRuleTO active = new PortForwardingRuleTO(1, "1.2.3.4", 22, 22, + "5.6.7.8", 22, 22, "tcp", false, false); + rules.add(active); + PortForwardingRuleTO revoked = new PortForwardingRuleTO(1, "1.2.3.4", 22, 22, + "5.6.7.8", 22, 22, "tcp", false, false); + rules.add(revoked); + + SetPortForwardingRulesCommand cmd = new SetPortForwardingRulesCommand(rules); + cmd.setContextParam(NetworkElementCommand.GUEST_VLAN_TAG, Long.toString(vlanId)); + cmd.setContextParam(NetworkElementCommand.GUEST_NETWORK_CIDR, "1.2.3.4/32"); + + _resource.configure("CiscoVnmcResource", _parameters); + _resource.setConnection(_connection); + when(_connection.createTenantVDCNatPolicySet(anyString())).thenReturn(true); + when(_connection.createTenantVDCAclPolicySet(anyString(), anyBoolean())).thenReturn(true); + when(_connection.createTenantVDCPFPolicy(anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCPFPolicyRef(anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCAclPolicy(anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCAclPolicyRef(anyString(), anyString(), anyBoolean())).thenReturn(true); + when(_connection.deleteTenantVDCPFRule(anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.deleteTenantVDCAclRule(anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCPFIpPool(anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCPFPortPool(anyString(), anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCPFRule(anyString(), + anyString(), anyString(), anyString(), + anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.createTenantVDCAclRuleForPF(anyString(), + anyString(), anyString(), anyString(), + anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.associateAclPolicySet(anyString())).thenReturn(true); + + Answer answer = _resource.executeRequest(cmd); + System.out.println(answer.getDetails()); + assertTrue(answer.getResult()); + } + + @Test + public void testCreateEdgeFirewall() throws ConfigurationException, Exception { + long vlanId = 123; + CreateLogicalEdgeFirewallCommand cmd = new CreateLogicalEdgeFirewallCommand(vlanId, "1.2.3.4", "5.6.7.8", "255.255.255.0", "255.255.255.0"); + cmd.getPublicGateways().add("1.1.1.1"); + cmd.getPublicGateways().add("2.2.2.2"); + + _resource.configure("CiscoVnmcResource", _parameters); + _resource.setConnection(_connection); + when(_connection.createTenant(anyString())).thenReturn(true); + when(_connection.createTenantVDC(anyString())).thenReturn(true); + when(_connection.createTenantVDCEdgeSecurityProfile(anyString())).thenReturn(true); + when(_connection.createTenantVDCEdgeDeviceProfile(anyString())).thenReturn(true); + when(_connection.createTenantVDCEdgeStaticRoutePolicy(anyString())).thenReturn(true); + when(_connection.createTenantVDCEdgeStaticRoute(anyString(), anyString(), anyString(), anyString())).thenReturn(true); + when(_connection.associateTenantVDCEdgeStaticRoutePolicy(anyString())).thenReturn(true); + when(_connection.createEdgeFirewall(anyString(), anyString(), anyString(), anyString(), anyString())).thenReturn(true); + + Answer answer = _resource.executeRequest(cmd); + System.out.println(answer.getDetails()); + assertTrue(answer.getResult()); + } +} diff --git a/plugins/network-elements/dns-notifier/resources/components-example.xml b/plugins/network-elements/dns-notifier/resources/components-example.xml index 6493e748fae..2e9c5bedc63 100755 --- a/plugins/network-elements/dns-notifier/resources/components-example.xml +++ b/plugins/network-elements/dns-notifier/resources/components-example.xml @@ -86,7 +86,7 @@ under the License. - + diff --git a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java index 77f6b60bfe8..e384e3cfd0d 100644 --- a/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java +++ b/plugins/network-elements/f5/src/com/cloud/network/element/F5ExternalLoadBalancerElement.java @@ -16,19 +16,6 @@ // under the License. package com.cloud.network.element; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.ejb.Local; -import javax.inject.Inject; - -import org.apache.cloudstack.api.response.ExternalLoadBalancerResponse; -import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice; -import org.apache.log4j.Logger; - import com.cloud.agent.api.to.LoadBalancerTO; import com.cloud.api.ApiDBUtils; import com.cloud.api.commands.*; @@ -101,7 +88,7 @@ public class F5ExternalLoadBalancerElement extends ExternalLoadBalancerDeviceMan ConfigurationDao _configDao; private boolean canHandle(Network config) { - if (config.getGuestType() != Network.GuestType.Isolated || config.getTrafficType() != TrafficType.Guest) { + if ((config.getGuestType() != Network.GuestType.Isolated && config.getGuestType() != Network.GuestType.Shared) || config.getTrafficType() != TrafficType.Guest) { s_logger.trace("Not handling network with Type " + config.getGuestType() + " and traffic type " + config.getTrafficType()); return false; } diff --git a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java index 64b0f5aa37d..a429306a680 100644 --- a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java +++ b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java @@ -16,28 +16,8 @@ // under the License. package com.cloud.network.element; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.ejb.Local; -import javax.inject.Inject; - -import org.apache.cloudstack.api.response.ExternalFirewallResponse; -import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice; -import org.apache.log4j.Logger; - import com.cloud.api.ApiDBUtils; -import com.cloud.api.commands.AddExternalFirewallCmd; -import com.cloud.api.commands.AddSrxFirewallCmd; -import com.cloud.api.commands.ConfigureSrxFirewallCmd; -import com.cloud.api.commands.DeleteExternalFirewallCmd; -import com.cloud.api.commands.DeleteSrxFirewallCmd; -import com.cloud.api.commands.ListExternalFirewallsCmd; -import com.cloud.api.commands.ListSrxFirewallNetworksCmd; -import com.cloud.api.commands.ListSrxFirewallsCmd; +import com.cloud.api.commands.*; import com.cloud.api.response.SrxFirewallResponse; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; @@ -47,35 +27,16 @@ import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.deploy.DeployDestination; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InsufficientNetworkCapacityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.*; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.host.dao.HostDetailsDao; -import com.cloud.network.ExternalFirewallDeviceManagerImpl; -import com.cloud.network.Network; +import com.cloud.network.*; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; -import com.cloud.network.NetworkModel; -import com.cloud.network.PhysicalNetwork; -import com.cloud.network.PhysicalNetworkServiceProvider; -import com.cloud.network.PublicIpAddress; -import com.cloud.network.RemoteAccessVpn; -import com.cloud.network.VpnUser; -import com.cloud.network.dao.ExternalFirewallDeviceDao; -import com.cloud.network.dao.ExternalFirewallDeviceVO; -import com.cloud.network.dao.NetworkDao; -import com.cloud.network.dao.NetworkExternalFirewallDao; -import com.cloud.network.dao.NetworkExternalFirewallVO; -import com.cloud.network.dao.NetworkServiceMapDao; -import com.cloud.network.dao.NetworkVO; -import com.cloud.network.dao.PhysicalNetworkDao; -import com.cloud.network.dao.PhysicalNetworkVO; +import com.cloud.network.dao.*; import com.cloud.network.dao.ExternalFirewallDeviceVO.FirewallDeviceState; import com.cloud.network.resource.JuniperSrxResource; import com.cloud.network.rules.FirewallRule; @@ -89,6 +50,13 @@ import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineProfile; +import org.apache.cloudstack.api.response.ExternalFirewallResponse; +import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice; +import org.apache.log4j.Logger; + +import javax.ejb.Local; +import javax.inject.Inject; +import java.util.*; @Local(value = {NetworkElement.class, FirewallServiceProvider.class, PortForwardingServiceProvider.class, IpDeployer.class, @@ -129,7 +97,9 @@ PortForwardingServiceProvider, RemoteAccessVPNServiceProvider, IpDeployer, Junip private boolean canHandle(Network network, Service service) { DataCenter zone = _configMgr.getZone(network.getDataCenterId()); - if ((zone.getNetworkType() == NetworkType.Advanced && network.getGuestType() != Network.GuestType.Isolated) || (zone.getNetworkType() == NetworkType.Basic && network.getGuestType() != Network.GuestType.Shared)) { + if ((zone.getNetworkType() == NetworkType.Advanced && !(network.getGuestType() == Network.GuestType.Isolated || + network.getGuestType() == Network.GuestType.Shared )) || + (zone.getNetworkType() == NetworkType.Basic && network.getGuestType() != Network.GuestType.Shared)) { s_logger.trace("Element " + getProvider().getName() + "is not handling network type = " + network.getGuestType()); return false; } diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java index 17bb7cc1b6a..2bbdb0450be 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/element/NetscalerElement.java @@ -124,7 +124,8 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl private boolean canHandle(Network config, Service service) { DataCenter zone = _dcDao.findById(config.getDataCenterId()); - boolean handleInAdvanceZone = (zone.getNetworkType() == NetworkType.Advanced && config.getGuestType() == Network.GuestType.Isolated && config.getTrafficType() == TrafficType.Guest); + boolean handleInAdvanceZone = (zone.getNetworkType() == NetworkType.Advanced && + (config.getGuestType() == Network.GuestType.Isolated || config.getGuestType() == Network.GuestType.Shared) && config.getTrafficType() == TrafficType.Guest); boolean handleInBasicZone = (zone.getNetworkType() == NetworkType.Basic && config.getGuestType() == Network.GuestType.Shared && config.getTrafficType() == TrafficType.Guest); if (!(handleInAdvanceZone || handleInBasicZone)) { diff --git a/plugins/pom.xml b/plugins/pom.xml index 607c50cff22..471253f0728 100755 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -36,6 +36,7 @@ api/rate-limit api/discovery acl/static-role-based + affinity-group-processors/host-anti-affinity deployment-planners/user-concentrated-pod deployment-planners/user-dispersing host-allocators/random @@ -137,6 +138,7 @@ hypervisors/vmware + network-elements/cisco-vnmc diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/provider/CloudStackPrimaryDataStoreProviderImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/provider/CloudStackPrimaryDataStoreProviderImpl.java index 4d46d99fab3..826f07ae07e 100644 --- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/provider/CloudStackPrimaryDataStoreProviderImpl.java +++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/provider/CloudStackPrimaryDataStoreProviderImpl.java @@ -37,7 +37,7 @@ public class CloudStackPrimaryDataStoreProviderImpl implements private final String providerName = "ancient primary data store provider"; protected PrimaryDataStoreDriver driver; protected HypervisorHostListener listener; - protected DataStoreLifeCycle lifecyle; + protected DataStoreLifeCycle lifecycle; CloudStackPrimaryDataStoreProviderImpl() { @@ -50,12 +50,12 @@ public class CloudStackPrimaryDataStoreProviderImpl implements @Override public DataStoreLifeCycle getDataStoreLifeCycle() { - return this.lifecyle; + return this.lifecycle; } @Override public boolean configure(Map params) { - lifecyle = ComponentContext.inject(CloudStackPrimaryDataStoreLifeCycleImpl.class); + lifecycle = ComponentContext.inject(CloudStackPrimaryDataStoreLifeCycleImpl.class); driver = ComponentContext.inject(CloudStackPrimaryDataStoreDriverImpl.class); listener = ComponentContext.inject(DefaultHostListener.class); return true; diff --git a/server/pom.xml b/server/pom.xml index a3971954475..ca56851ec15 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -158,8 +158,6 @@ com/cloud/network/vpn/RemoteAccessVpnTest.java com/cloud/network/security/SecurityGroupManagerImpl2Test.java com/cloud/network/security/SecurityGroupManagerImpl2Test.java - - org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 7b441901d5e..303f3281d89 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -25,6 +25,9 @@ import java.util.Set; import javax.annotation.PostConstruct; import javax.inject.Inject; +import org.apache.cloudstack.affinity.AffinityGroup; +import org.apache.cloudstack.affinity.AffinityGroupResponse; +import org.apache.cloudstack.affinity.dao.AffinityGroupDao; import org.apache.cloudstack.api.ApiConstants.HostDetails; import org.apache.cloudstack.api.ApiConstants.VMDetails; import org.apache.cloudstack.api.response.AccountResponse; @@ -50,6 +53,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.springframework.stereotype.Component; import com.cloud.api.query.dao.AccountJoinDao; +import com.cloud.api.query.dao.AffinityGroupJoinDao; import com.cloud.api.query.dao.AsyncJobJoinDao; import com.cloud.api.query.dao.DataCenterJoinDao; import com.cloud.api.query.dao.DiskOfferingJoinDao; @@ -67,6 +71,7 @@ import com.cloud.api.query.dao.UserAccountJoinDao; import com.cloud.api.query.dao.UserVmJoinDao; import com.cloud.api.query.dao.VolumeJoinDao; import com.cloud.api.query.vo.AccountJoinVO; +import com.cloud.api.query.vo.AffinityGroupJoinVO; import com.cloud.api.query.vo.AsyncJobJoinVO; import com.cloud.api.query.vo.DataCenterJoinVO; import com.cloud.api.query.vo.DiskOfferingJoinVO; @@ -284,7 +289,7 @@ public class ApiDBUtils { static NetworkModel _networkModel; static NetworkManager _networkMgr; static TemplateManager _templateMgr; - + static StatsCollector _statsCollector; static AccountDao _accountDao; @@ -379,6 +384,8 @@ public class ApiDBUtils { static ClusterDetailsDao _clusterDetailsDao; static NicSecondaryIpDao _nicSecondaryIpDao; static VpcProvisioningService _vpcProvSvc; + static AffinityGroupDao _affinityGroupDao; + static AffinityGroupJoinDao _affinityGroupJoinDao; @Inject private ManagementServer ms; @Inject public AsyncJobManager asyncMgr; @@ -483,6 +490,9 @@ public class ApiDBUtils { @Inject private VMSnapshotDao vmSnapshotDao; @Inject private NicSecondaryIpDao nicSecondaryIpDao; @Inject private VpcProvisioningService vpcProvSvc; + @Inject private AffinityGroupDao affinityGroupDao; + @Inject private AffinityGroupJoinDao affinityGroupJoinDao; + @PostConstruct void init() { _ms = ms; @@ -585,6 +595,8 @@ public class ApiDBUtils { _vmSnapshotDao = vmSnapshotDao; _nicSecondaryIpDao = nicSecondaryIpDao; _vpcProvSvc = vpcProvSvc; + _affinityGroupDao = affinityGroupDao; + _affinityGroupJoinDao = affinityGroupJoinDao; // Note: stats collector should already have been initialized by this time, otherwise a null instance is returned _statsCollector = StatsCollector.getInstance(); } @@ -1579,7 +1591,7 @@ public class ApiDBUtils { public static DataCenterJoinVO newDataCenterView(DataCenter dc){ return _dcJoinDao.newDataCenterView(dc); } - + public static Map findHostDetailsById(long hostId){ return _hostDetailsDao.findDetails(hostId); } @@ -1587,4 +1599,16 @@ public class ApiDBUtils { public static List findNicSecondaryIps(long nicId) { return _nicSecondaryIpDao.listByNicId(nicId); } + + public static AffinityGroup getAffinityGroup(String groupName, long accountId) { + return _affinityGroupDao.findByAccountAndName(accountId, groupName); + } + + public static AffinityGroupResponse newAffinityGroupResponse(AffinityGroupJoinVO group) { + return _affinityGroupJoinDao.newAffinityGroupResponse(group); + } + + public static AffinityGroupResponse fillAffinityGroupDetails(AffinityGroupResponse resp, AffinityGroupJoinVO group) { + return _affinityGroupJoinDao.setAffinityGroupResponse(resp, group); + } } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 93b755a665a..cfe0e00d8ba 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -272,6 +272,36 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Type; import com.cloud.vm.dao.NicSecondaryIpVO; import com.cloud.vm.snapshot.VMSnapshot; +import org.apache.cloudstack.acl.ControlledEntity; +import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.affinity.AffinityGroup; +import org.apache.cloudstack.affinity.AffinityGroupResponse; +import org.apache.cloudstack.api.ApiConstants.HostDetails; +import org.apache.cloudstack.api.ApiConstants.VMDetails; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.ResponseGenerator; +import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; +import org.apache.cloudstack.api.response.*; +import org.apache.cloudstack.region.Region; +import org.apache.cloudstack.usage.Usage; +import org.apache.cloudstack.usage.UsageService; +import org.apache.cloudstack.usage.UsageTypes; +import com.cloud.vm.VmStats; +import com.cloud.vm.dao.UserVmData; +import com.cloud.vm.dao.UserVmData.NicData; +import com.cloud.vm.dao.UserVmData.SecurityGroupData; +import com.cloud.vm.snapshot.VMSnapshot; +import org.apache.cloudstack.api.ResponseGenerator; +import org.apache.cloudstack.api.response.VMSnapshotResponse; +import org.apache.log4j.Logger; + +import java.text.DecimalFormat; +import java.util.*; + +import javax.inject.Inject; + +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; @Component public class ApiResponseHelper implements ResponseGenerator { @@ -439,7 +469,7 @@ public class ApiResponseHelper implements ResponseGenerator { vmSnapshotResponse.setCreated(vmSnapshot.getCreated()); vmSnapshotResponse.setDescription(vmSnapshot.getDescription()); vmSnapshotResponse.setDisplayName(vmSnapshot.getDisplayName()); - UserVm vm = ApiDBUtils.findUserVmById(vmSnapshot.getVmId()); + UserVm vm = ApiDBUtils.findUserVmById(vmSnapshot.getVmId()); if(vm!=null) vmSnapshotResponse.setVirtualMachineid(vm.getUuid()); if(vmSnapshot.getParent() != null) @@ -449,7 +479,7 @@ public class ApiResponseHelper implements ResponseGenerator { vmSnapshotResponse.setObjectName("vmsnapshot"); return vmSnapshotResponse; } - + @Override public SnapshotPolicyResponse createSnapshotPolicyResponse(SnapshotPolicy policy) { SnapshotPolicyResponse policyResponse = new SnapshotPolicyResponse(); @@ -546,7 +576,7 @@ public class ApiResponseHelper implements ResponseGenerator { vlanResponse.setIp6Gateway(vlan.getIp6Gateway()); vlanResponse.setIp6Cidr(vlan.getIp6Cidr()); - + String ip6Range = vlan.getIp6Range(); if (ip6Range != null) { String[] range = ip6Range.split("-"); @@ -738,11 +768,13 @@ public class ApiResponseHelper implements ResponseGenerator { GlobalLoadBalancerResponse response = new GlobalLoadBalancerResponse(); response.setAlgorithm(globalLoadBalancerRule.getAlgorithm()); response.setStickyMethod(globalLoadBalancerRule.getPersistence()); + response.setServiceType(globalLoadBalancerRule.getServiceType()); response.setServiceDomainName(globalLoadBalancerRule.getGslbDomain()); response.setName(globalLoadBalancerRule.getName()); response.setDescription(globalLoadBalancerRule.getDescription()); response.setRegionIdId(globalLoadBalancerRule.getRegion()); response.setId(globalLoadBalancerRule.getUuid()); + response.setObjectName("globalloadbalancer"); return response; } @@ -2250,7 +2282,7 @@ public class ApiResponseHelper implements ResponseGenerator { if (((network.getCidr()) != null) && (network.getNetworkCidr() == null)) { response.setNetmask(NetUtils.cidr2Netmask(network.getCidr())); } - + response.setIp6Gateway(network.getIp6Gateway()); response.setIp6Cidr(network.getIp6Cidr()); @@ -2445,7 +2477,7 @@ public class ApiResponseHelper implements ResponseGenerator { List cidrs = ApiDBUtils.findFirewallSourceCidrs(fwRule.getId()); response.setCidrList(StringUtils.join(cidrs, ",")); - + if (fwRule.getTrafficType() == FirewallRule.TrafficType.Ingress) { IpAddress ip = ApiDBUtils.findIpAddressById(fwRule.getSourceIpAddressId()); response.setPublicIpAddressId(ip.getId()); @@ -2685,8 +2717,8 @@ public class ApiResponseHelper implements ResponseGenerator { List serviceProviders = ApiDBUtils.getProvidersForService(service); List serviceProvidersResponses = new ArrayList(); for (Network.Provider serviceProvider : serviceProviders) { - // return only Virtual Router/JuniperSRX as a provider for the firewall - if (service == Service.Firewall && !(serviceProvider == Provider.VirtualRouter || serviceProvider == Provider.JuniperSRX)) { + // return only Virtual Router/JuniperSRX/CiscoVnmc as a provider for the firewall + if (service == Service.Firewall && !(serviceProvider == Provider.VirtualRouter || serviceProvider == Provider.JuniperSRX || serviceProvider == Provider.CiscoVnmc)) { continue; } @@ -3476,7 +3508,7 @@ public class ApiResponseHelper implements ResponseGenerator { return usageRecResponse; } - + public String getDateStringInternal(Date inputDate) { if (inputDate == null) return null; @@ -3560,7 +3592,7 @@ public class ApiResponseHelper implements ResponseGenerator { return sb.toString(); } - + @Override public TrafficMonitorResponse createTrafficMonitorResponse(Host trafficMonitor) { Map tmDetails = ApiDBUtils.findHostDetailsById(trafficMonitor.getId()); @@ -3620,4 +3652,29 @@ public class ApiResponseHelper implements ResponseGenerator { response.setIsDefault(result.isDefaultNic()); return response; } + + @Override + public AffinityGroupResponse createAffinityGroupResponse(AffinityGroup group) { + + AffinityGroupResponse response = new AffinityGroupResponse(); + + Account account = ApiDBUtils.findAccountById(group.getAccountId()); + response.setAccountName(account.getAccountName()); + response.setName(group.getName()); + response.setType(group.getType()); + response.setDescription(group.getDescription()); + // response.setDomainId(account.) + + return response; + } + + @Override + public Long getAffinityGroupId(String groupName, long accountId) { + AffinityGroup ag = ApiDBUtils.getAffinityGroup(groupName, accountId); + if (ag == null) { + return null; + } else { + return ag.getId(); + } + } } diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index 951d09ed185..5ffc2db995c 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -27,6 +27,11 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.affinity.AffinityGroup; +import org.apache.cloudstack.affinity.AffinityGroupResponse; +import org.apache.cloudstack.affinity.AffinityGroupVMMapVO; +import org.apache.cloudstack.affinity.AffinityGroupVO; +import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; import org.apache.cloudstack.api.command.admin.host.ListHostsCmd; import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd; import org.apache.cloudstack.api.command.admin.storage.ListStoragePoolsCmd; @@ -69,6 +74,7 @@ import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.api.query.dao.AccountJoinDao; +import com.cloud.api.query.dao.AffinityGroupJoinDao; import com.cloud.api.query.dao.AsyncJobJoinDao; import com.cloud.api.query.dao.DataCenterJoinDao; import com.cloud.api.query.dao.DiskOfferingJoinDao; @@ -86,6 +92,7 @@ import com.cloud.api.query.dao.UserAccountJoinDao; import com.cloud.api.query.dao.UserVmJoinDao; import com.cloud.api.query.dao.VolumeJoinDao; import com.cloud.api.query.vo.AccountJoinVO; +import com.cloud.api.query.vo.AffinityGroupJoinVO; import com.cloud.api.query.vo.AsyncJobJoinVO; import com.cloud.api.query.vo.DataCenterJoinVO; import com.cloud.api.query.vo.DiskOfferingJoinVO; @@ -138,6 +145,7 @@ import com.cloud.utils.Ternary; import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.Filter; +import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Func; @@ -246,6 +254,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { @Inject private HighAvailabilityManager _haMgr; + @Inject + AffinityGroupVMMapDao _affinityGroupVMMapDao; + + @Inject + private AffinityGroupJoinDao _affinityGroupJoinDao; + /* (non-Javadoc) * @see com.cloud.api.query.QueryService#searchForUsers(org.apache.cloudstack.api.command.admin.user.ListUsersCmd) */ @@ -1927,7 +1941,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Boolean isAscending = Boolean.parseBoolean(_configDao.getValue("sortkey.algorithm")); isAscending = (isAscending == null ? true : isAscending); Filter searchFilter = new Filter(DiskOfferingJoinVO.class, "sortKey", isAscending, cmd.getStartIndex(), cmd.getPageSizeVal()); - SearchBuilder sb = _diskOfferingJoinDao.createSearchBuilder(); + SearchCriteria sc = _diskOfferingJoinDao.createSearchCriteria(); Account account = UserContext.current().getCaller(); @@ -1942,9 +1956,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { if (account.getType() == Account.ACCOUNT_TYPE_ADMIN || isPermissible(account.getDomainId(), domainId) ) { // check if the user's domain == do's domain || user's domain is // a child of so's domain for non-root users - sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ); - SearchCriteria sc = sb.create(); - sc.setParameters("domainId", domainId); + sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); return _diskOfferingJoinDao.searchAndCount(sc, searchFilter); } else { throw new PermissionDeniedException("The account:" + account.getAccountName() @@ -1952,11 +1964,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } } - sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); - sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); - - boolean includePublicOfferings = false; List domainIds = null; // For non-root users, only return all offerings for the user's domain, and everything above till root if ((account.getType() == Account.ACCOUNT_TYPE_NORMAL || account.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) @@ -1973,16 +1981,17 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { domainRecord = _domainDao.findById(domainRecord.getParent()); domainIds.add(domainRecord.getId()); } - sb.and("domainIdIn", sb.entity().getDomainId(), SearchCriteria.Op.IN); + + SearchCriteria spc = _diskOfferingJoinDao.createSearchCriteria(); - // include also public offering if no keyword, name and id specified - if ( keyword == null && name == null && id == null ){ - includePublicOfferings = true; - } + spc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray()); + spc.addOr("domainId", SearchCriteria.Op.NULL); // include public offering as where + sc.addAnd("domainId", SearchCriteria.Op.SC, spc); + sc.addAnd("systemUse", SearchCriteria.Op.EQ, false); // non-root users should not see system offering at all + } - SearchCriteria sc = sb.create(); - if (keyword != null) { + if (keyword != null) { SearchCriteria ssc = _diskOfferingJoinDao.createSearchCriteria(); ssc.addOr("displayText", SearchCriteria.Op.LIKE, "%" + keyword + "%"); ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); @@ -1990,26 +1999,14 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sc.addAnd("name", SearchCriteria.Op.SC, ssc); } - if (name != null) { - sc.setParameters("name", "%" + name + "%"); - } - if (id != null) { - sc.setParameters("id", id); + sc.addAnd("id", SearchCriteria.Op.EQ, id); } - if (domainIds != null ){ - sc.setParameters("domainIdIn", domainIds.toArray()); + if (name != null) { + sc.addAnd("name", SearchCriteria.Op.EQ, name); } - - if (includePublicOfferings){ - SearchCriteria spc = _diskOfferingJoinDao.createSearchCriteria(); - spc.addAnd("domainId", SearchCriteria.Op.NULL); - spc.addAnd("systemUse", SearchCriteria.Op.EQ, false); - - sc.addOr("systemUse", SearchCriteria.Op.SC, spc); - } - + // FIXME: disk offerings should search back up the hierarchy for // available disk offerings... /* @@ -2086,10 +2083,10 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } } - boolean includePublicOfferings = false; + // boolean includePublicOfferings = false; if ((caller.getType() == Account.ACCOUNT_TYPE_NORMAL || caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { - // For non-root users + // For non-root users. if (isSystem) { throw new InvalidParameterValueException("Only root admins can access system's offering"); } @@ -2105,12 +2102,12 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { domainRecord = _domainDao.findById(domainRecord.getParent()); domainIds.add(domainRecord.getId()); } - sc.addAnd("domainId", SearchCriteria.Op.IN, domainIds.toArray()); + SearchCriteria spc = _srvOfferingJoinDao.createSearchCriteria(); + + spc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray()); + spc.addOr("domainId", SearchCriteria.Op.NULL); // include public offering as where + sc.addAnd("domainId", SearchCriteria.Op.SC, spc); - // include also public offering if no keyword, name and id specified - if ( keyword == null && name == null && id == null ){ - includePublicOfferings = true; - } } else { // for root users @@ -2153,24 +2150,18 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } if (isSystem != null) { + // note that for non-root users, isSystem is always false when control comes to here sc.addAnd("systemUse", SearchCriteria.Op.EQ, isSystem); } if (name != null) { - sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%"); + sc.addAnd("name", SearchCriteria.Op.EQ, name); } if (vmTypeStr != null) { sc.addAnd("vm_type", SearchCriteria.Op.EQ, vmTypeStr); } - if (includePublicOfferings){ - SearchCriteria spc = _srvOfferingJoinDao.createSearchCriteria(); - spc.addAnd("domainId", SearchCriteria.Op.NULL); - spc.addAnd("systemUse", SearchCriteria.Op.EQ, false); - sc.addOr("systemUse", SearchCriteria.Op.SC, spc); - } - return _srvOfferingJoinDao.searchAndCount(sc, searchFilter); } @@ -2328,5 +2319,99 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { return false; } + @Override + public ListResponse listAffinityGroups(Long affinityGroupId, String affinityGroupName, + String affinityGroupType, Long vmId, Long startIndex, Long pageSize) { + Pair, Integer> result = listAffinityGroupsInternal(affinityGroupId, + affinityGroupName, affinityGroupType, vmId, startIndex, pageSize); + ListResponse response = new ListResponse(); + List agResponses = ViewResponseHelper.createAffinityGroupResponses(result.first()); + response.setResponses(agResponses, result.second()); + return response; + } + + + public Pair, Integer> listAffinityGroupsInternal(Long affinityGroupId, + String affinityGroupName, String affinityGroupType, Long vmId, Long startIndex, Long pageSize) { + + Account caller = UserContext.current().getCaller(); + + Long accountId = caller.getAccountId(); + Long domainId = caller.getDomainId(); + + if (vmId != null) { + UserVmVO userVM = _userVmDao.findById(vmId); + 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); + return listAffinityGroupsByVM(vmId.longValue(), startIndex, pageSize); + } + + Filter searchFilter = new Filter(AffinityGroupJoinVO.class, "id", true, startIndex, pageSize); + SearchBuilder groupSearch = _affinityGroupJoinDao.createSearchBuilder(); + groupSearch.select(null, Func.DISTINCT, groupSearch.entity().getId()); // select + // distinct + + SearchCriteria sc = groupSearch.create(); + + if (accountId != null) { + sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId); + } + + if (domainId != null) { + sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); + } + + if (affinityGroupId != null) { + sc.addAnd("id", SearchCriteria.Op.EQ, affinityGroupId); + } + + if (affinityGroupName != null) { + sc.addAnd("name", SearchCriteria.Op.EQ, affinityGroupName); + } + + if (affinityGroupType != null) { + sc.addAnd("type", SearchCriteria.Op.EQ, affinityGroupType); + } + + + Pair, Integer> uniqueGroupsPair = _affinityGroupJoinDao.searchAndCount(sc, + searchFilter); + // search group details by ids + Integer count = uniqueGroupsPair.second(); + if (count.intValue() == 0) { + // empty result + return uniqueGroupsPair; + } + List uniqueGroups = uniqueGroupsPair.first(); + Long[] vrIds = new Long[uniqueGroups.size()]; + int i = 0; + for (AffinityGroupJoinVO v : uniqueGroups) { + vrIds[i++] = v.getId(); + } + List vrs = _affinityGroupJoinDao.searchByIds(vrIds); + return new Pair, Integer>(vrs, count); + + } + + private Pair, Integer> listAffinityGroupsByVM(long vmId, long pageInd, long pageSize) { + Filter sf = new Filter(SecurityGroupVMMapVO.class, null, true, pageInd, pageSize); + Pair, Integer> agVmMappingPair = _affinityGroupVMMapDao.listByInstanceId(vmId, sf); + Integer count = agVmMappingPair.second(); + if (count.intValue() == 0) { + // handle empty result cases + return new Pair, Integer>(new ArrayList(), count); + } + List agVmMappings = agVmMappingPair.first(); + Long[] agIds = new Long[agVmMappings.size()]; + int i = 0; + for (AffinityGroupVMMapVO agVm : agVmMappings) { + agIds[i++] = agVm.getAffinityGroupId(); + } + List ags = _affinityGroupJoinDao.searchByIds(agIds); + return new Pair, Integer>(ags, count); + } } diff --git a/server/src/com/cloud/api/query/ViewResponseHelper.java b/server/src/com/cloud/api/query/ViewResponseHelper.java index 9e612b07d1b..dc2727e8e0d 100644 --- a/server/src/com/cloud/api/query/ViewResponseHelper.java +++ b/server/src/com/cloud/api/query/ViewResponseHelper.java @@ -21,6 +21,7 @@ import java.util.EnumSet; import java.util.Hashtable; import java.util.List; +import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.ApiConstants.HostDetails; import org.apache.cloudstack.api.ApiConstants.VMDetails; import org.apache.cloudstack.api.response.AccountResponse; @@ -45,6 +46,7 @@ import org.apache.log4j.Logger; import com.cloud.api.ApiDBUtils; import com.cloud.api.query.vo.AccountJoinVO; +import com.cloud.api.query.vo.AffinityGroupJoinVO; import com.cloud.api.query.vo.AsyncJobJoinVO; import com.cloud.api.query.vo.DataCenterJoinVO; import com.cloud.api.query.vo.DiskOfferingJoinVO; @@ -123,7 +125,7 @@ public class ViewResponseHelper { // first time encountering this vm userVmData = ApiDBUtils.newUserVmResponse(objectName, userVm, details, caller); } else{ - // update nics, securitygroups, tags for 1 to many mapping fields + // update nics, securitygroups, tags, affinitygroups for 1 to many mapping fields userVmData = ApiDBUtils.fillVmDetails(userVmData, userVm); } vmDataList.put(userVm.getId(), userVmData); @@ -303,4 +305,20 @@ public class ViewResponseHelper { } return respList; } + + public static List createAffinityGroupResponses(List groups) { + Hashtable vrDataList = new Hashtable(); + for (AffinityGroupJoinVO vr : groups) { + AffinityGroupResponse vrData = vrDataList.get(vr.getId()); + if (vrData == null) { + // first time encountering this AffinityGroup + vrData = ApiDBUtils.newAffinityGroupResponse(vr); + } else { + // update vms + vrData = ApiDBUtils.fillAffinityGroupDetails(vrData, vr); + } + vrDataList.put(vr.getId(), vrData); + } + return new ArrayList(vrDataList.values()); + } } diff --git a/server/src/com/cloud/api/query/dao/AffinityGroupJoinDao.java b/server/src/com/cloud/api/query/dao/AffinityGroupJoinDao.java new file mode 100644 index 00000000000..c029b3fc4f8 --- /dev/null +++ b/server/src/com/cloud/api/query/dao/AffinityGroupJoinDao.java @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.api.query.dao; + +import java.util.List; + +import org.apache.cloudstack.affinity.AffinityGroup; +import org.apache.cloudstack.affinity.AffinityGroupResponse; +import com.cloud.api.query.vo.AffinityGroupJoinVO; +import com.cloud.user.Account; +import com.cloud.utils.db.GenericDao; + +public interface AffinityGroupJoinDao extends GenericDao { + + AffinityGroupResponse newAffinityGroupResponse(AffinityGroupJoinVO vsg); + + AffinityGroupResponse setAffinityGroupResponse(AffinityGroupResponse vsgData, AffinityGroupJoinVO vsg); + + List newAffinityGroupView(AffinityGroup ag); + + List searchByIds(Long... ids); +} + diff --git a/server/src/com/cloud/api/query/dao/AffinityGroupJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/AffinityGroupJoinDaoImpl.java new file mode 100644 index 00000000000..a17679313d6 --- /dev/null +++ b/server/src/com/cloud/api/query/dao/AffinityGroupJoinDaoImpl.java @@ -0,0 +1,142 @@ +// 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.api.query.dao; + +import java.util.ArrayList; +import java.util.List; + +import javax.ejb.Local; +import javax.inject.Inject; + + +import org.apache.cloudstack.affinity.AffinityGroup; +import org.apache.cloudstack.affinity.AffinityGroupResponse; +import org.apache.log4j.Logger; +import com.cloud.api.ApiResponseHelper; +import com.cloud.api.query.vo.AffinityGroupJoinVO; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +@Local(value = { AffinityGroupJoinDao.class }) +public class AffinityGroupJoinDaoImpl extends GenericDaoBase implements AffinityGroupJoinDao { + public static final Logger s_logger = Logger.getLogger(AffinityGroupJoinDaoImpl.class); + + @Inject + private ConfigurationDao _configDao; + + private final SearchBuilder agSearch; + + private final SearchBuilder agIdSearch; + + protected AffinityGroupJoinDaoImpl() { + + agSearch = createSearchBuilder(); + agSearch.and("idIN", agSearch.entity().getId(), SearchCriteria.Op.IN); + agSearch.done(); + + agIdSearch = createSearchBuilder(); + agIdSearch.and("id", agIdSearch.entity().getId(), SearchCriteria.Op.EQ); + agIdSearch.done(); + + this._count = "select count(distinct id) from affinity_group_view WHERE "; + } + + @Override + public AffinityGroupResponse newAffinityGroupResponse(AffinityGroupJoinVO vag) { + AffinityGroupResponse agResponse = new AffinityGroupResponse(); + agResponse.setId(vag.getUuid()); + agResponse.setName(vag.getName()); + agResponse.setDescription(vag.getDescription()); + + ApiResponseHelper.populateOwner(agResponse, vag); + + // update vm information + long instanceId = vag.getVmId(); + if (instanceId > 0) { + List vmIdList = new ArrayList(); + vmIdList.add(vag.getVmUuid()); + agResponse.setVMIdList(vmIdList); + } + + agResponse.setObjectName("affinitygroup"); + return agResponse; + } + + @Override + public AffinityGroupResponse setAffinityGroupResponse(AffinityGroupResponse vagData, AffinityGroupJoinVO vag) { + // update vm information + long instanceId = vag.getVmId(); + if (instanceId > 0) { + vagData.addVMId(vag.getVmUuid()); + } + return vagData; + } + + @Override + public List newAffinityGroupView(AffinityGroup ag) { + + SearchCriteria sc = agIdSearch.create(); + sc.setParameters("id", ag.getId()); + return searchIncludingRemoved(sc, null, null, false); + } + + @Override + public List searchByIds(Long... agIds) { + // set detail batch query size + int DETAILS_BATCH_SIZE = 2000; + String batchCfg = _configDao.getValue("detail.batch.query.size"); + if ( batchCfg != null ){ + DETAILS_BATCH_SIZE = Integer.parseInt(batchCfg); + } + // query details by batches + List uvList = new ArrayList(); + // query details by batches + int curr_index = 0; + if (agIds.length > DETAILS_BATCH_SIZE) { + while ((curr_index + DETAILS_BATCH_SIZE) <= agIds.length) { + Long[] ids = new Long[DETAILS_BATCH_SIZE]; + for (int k = 0, j = curr_index; j < curr_index + DETAILS_BATCH_SIZE; j++, k++) { + ids[k] = agIds[j]; + } + SearchCriteria sc = agSearch.create(); + sc.setParameters("idIN", ids); + List vms = searchIncludingRemoved(sc, null, null, false); + if (vms != null) { + uvList.addAll(vms); + } + curr_index += DETAILS_BATCH_SIZE; + } + } + if (curr_index < agIds.length) { + int batch_size = (agIds.length - curr_index); + // set the ids value + Long[] ids = new Long[batch_size]; + for (int k = 0, j = curr_index; j < curr_index + batch_size; j++, k++) { + ids[k] = agIds[j]; + } + SearchCriteria sc = agSearch.create(); + sc.setParameters("idIN", ids); + List vms = searchIncludingRemoved(sc, null, null, false); + if (vms != null) { + uvList.addAll(vms); + } + } + return uvList; + } +} diff --git a/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java index 8b6abf8a3e4..4ed62262966 100644 --- a/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/UserVmJoinDaoImpl.java @@ -26,6 +26,7 @@ import java.util.Set; import javax.ejb.Local; import javax.inject.Inject; +import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.ApiConstants.VMDetails; import org.apache.cloudstack.api.response.NicResponse; import org.apache.cloudstack.api.response.SecurityGroupResponse; @@ -216,6 +217,20 @@ public class UserVmJoinDaoImpl extends GenericDaoBase implem userVmResponse.addTag(ApiDBUtils.newResourceTagResponse(vtag, false)); } } + + if (details.contains(VMDetails.all) || details.contains(VMDetails.affgrp)) { + Long affinityGroupId = userVm.getAffinityGroupId(); + if (affinityGroupId != null && affinityGroupId.longValue() != 0) { + AffinityGroupResponse resp = new AffinityGroupResponse(); + resp.setId(userVm.getAffinityGroupUuid()); + resp.setName(userVm.getAffinityGroupName()); + resp.setDescription(userVm.getAffinityGroupDescription()); + resp.setObjectName("affinitygroup"); + resp.setAccountName(userVm.getAccountName()); + userVmResponse.addAffinityGroup(resp); + } + } + userVmResponse.setObjectName(objectName); return userVmResponse; @@ -276,6 +291,18 @@ public class UserVmJoinDaoImpl extends GenericDaoBase implem userVmData.addTag(ApiDBUtils.newResourceTagResponse(vtag, false)); } } + + Long affinityGroupId = uvo.getAffinityGroupId(); + if (affinityGroupId != null && affinityGroupId.longValue() != 0) { + AffinityGroupResponse resp = new AffinityGroupResponse(); + resp.setId(uvo.getAffinityGroupUuid()); + resp.setName(uvo.getAffinityGroupName()); + resp.setDescription(uvo.getAffinityGroupDescription()); + resp.setObjectName("affinitygroup"); + resp.setAccountName(uvo.getAccountName()); + userVmData.addAffinityGroup(resp); + } + return userVmData; } diff --git a/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java b/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java new file mode 100644 index 00000000000..e68996c53df --- /dev/null +++ b/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java @@ -0,0 +1,248 @@ +// 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.api.query.vo; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.Id; +import javax.persistence.Table; + +import com.cloud.vm.VirtualMachine; + +@Entity +@Table(name = "affinity_group_view") +public class AffinityGroupJoinVO extends BaseViewVO implements ControlledViewEntity { + + @Id + @Column(name="id", updatable=false, nullable = false) + private long id; + + @Column(name="name") + private String name; + + @Column(name = "description") + private String description; + + @Column(name = "uuid") + private String uuid; + + @Column(name="account_id") + private long accountId; + + @Column(name="account_uuid") + private String accountUuid; + + @Column(name="account_name") + private String accountName = null; + + @Column(name="account_type") + private short accountType; + + @Column(name="domain_id") + private long domainId; + + @Column(name="domain_uuid") + private String domainUuid; + + @Column(name="domain_name") + private String domainName = null; + + @Column(name="domain_path") + private String domainPath = null; + + @Column(name = "vm_id") + private long vmId; + + @Column(name = "vm_uuid") + private String vmUuid; + + @Column(name = "vm_name") + private String vmName; + + @Column(name = "vm_display_name") + private String vmDisplayName; + + @Column(name = "vm_state") + @Enumerated(value = EnumType.STRING) + protected VirtualMachine.State vmState = null; + + + public AffinityGroupJoinVO() { + } + + @Override + public long getId() { + return id; + } + + @Override + public void setId(long id) { + this.id = id; + } + + @Override + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public long getAccountId() { + return accountId; + } + + public void setAccountId(long accountId) { + this.accountId = accountId; + } + + @Override + public String getAccountUuid() { + return accountUuid; + } + + public void setAccountUuid(String accountUuid) { + this.accountUuid = accountUuid; + } + + @Override + public String getAccountName() { + return accountName; + } + + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + @Override + public short getAccountType() { + return accountType; + } + + public void setAccountType(short accountType) { + this.accountType = accountType; + } + + @Override + public long getDomainId() { + return domainId; + } + + public void setDomainId(long domainId) { + this.domainId = domainId; + } + + @Override + public String getDomainUuid() { + return domainUuid; + } + + public void setDomainUuid(String domainUuid) { + this.domainUuid = domainUuid; + } + + @Override + public String getDomainName() { + return domainName; + } + + public void setDomainName(String domainName) { + this.domainName = domainName; + } + + @Override + public String getDomainPath() { + return domainPath; + } + + public void setDomainPath(String domainPath) { + this.domainPath = domainPath; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public long getVmId() { + return vmId; + } + + public void setVmId(long vmId) { + this.vmId = vmId; + } + + public String getVmUuid() { + return vmUuid; + } + + public void setVmUuid(String vmUuid) { + this.vmUuid = vmUuid; + } + + public String getVmName() { + return vmName; + } + + public void setVmName(String vmName) { + this.vmName = vmName; + } + + public String getVmDisplayName() { + return vmDisplayName; + } + + public void setVmDisplayName(String vmDisplayName) { + this.vmDisplayName = vmDisplayName; + } + + public VirtualMachine.State getVmState() { + return vmState; + } + + public void setVmState(VirtualMachine.State vmState) { + this.vmState = vmState; + } + + @Override + public String getProjectUuid() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getProjectName() { + // TODO Auto-generated method stub + return null; + } +} diff --git a/server/src/com/cloud/api/query/vo/UserVmJoinVO.java b/server/src/com/cloud/api/query/vo/UserVmJoinVO.java index 33c49cdeae9..8d1314eafae 100644 --- a/server/src/com/cloud/api/query/vo/UserVmJoinVO.java +++ b/server/src/com/cloud/api/query/vo/UserVmJoinVO.java @@ -368,6 +368,18 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity { @Column(name="tag_customer") private String tagCustomer; + @Column(name = "affinity_group_id") + private long affinityGroupId; + + @Column(name = "affinity_group_uuid") + private String affinityGroupUuid; + + @Column(name = "affinity_group_name") + private String affinityGroupName; + + @Column(name = "affinity_group_description") + private String affinityGroupDescription; + transient String password; @Transient @@ -1671,4 +1683,29 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity { public void setIp6Cidr(String ip6Cidr) { this.ip6Cidr = ip6Cidr; } + + + public long getAffinityGroupId() { + return affinityGroupId; + } + + + + public String getAffinityGroupUuid() { + return affinityGroupUuid; + } + + + + public String getAffinityGroupName() { + return affinityGroupName; + } + + + + public String getAffinityGroupDescription() { + return affinityGroupDescription; + } + + } diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 2137c003912..e69ea19e979 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -276,6 +276,7 @@ public enum Config { VmwareRootDiskControllerType("Advanced", ManagementServer.class, String.class, "vmware.root.disk.controller", "ide", "Specify the default disk controller for root volumes, valid values are scsi, ide", null), VmwareSystemVmNicDeviceType("Advanced", ManagementServer.class, String.class, "vmware.systemvm.nic.device.type", "E1000", "Specify the default network device type for system VMs, valid values are E1000, PCNet32, Vmxnet2, Vmxnet3", null), VmwareRecycleHungWorker("Advanced", ManagementServer.class, Boolean.class, "vmware.recycle.hung.wokervm", "false", "Specify whether or not to recycle hung worker VMs", null), + VmwareEnableNestedVirtualization("Advanced", ManagementServer.class, Boolean.class, "vmware.nested.virtualization", "false", "When set to true this will enable nested virtualization when this is supported by the hypervisor", null), // Midonet MidoNetAPIServerAddress("Network", ManagementServer.class, String.class, "midonet.apiserver.address", "http://localhost:8081", "Specify the address at which the Midonet API server can be contacted (if using Midonet)", null), @@ -304,6 +305,8 @@ public enum Config { SSOAuthTolerance("Advanced", ManagementServer.class, Long.class, "security.singlesignon.tolerance.millis", "300000", "The allowable clock difference in milliseconds between when an SSO login request is made and when it is received.", null), //NetworkType("Hidden", ManagementServer.class, String.class, "network.type", "vlan", "The type of network that this deployment will use.", "vlan,direct"), HashKey("Hidden", ManagementServer.class, String.class, "security.hash.key", null, "for generic key-ed hash", null), + EncryptionKey("Hidden", ManagementServer.class, String.class, "security.encryption.key", null, "base64 encoded key data", null), + EncryptionIV("Hidden", ManagementServer.class, String.class, "security.encryption.iv", null, "base64 encoded IV data", null), RouterRamSize("Hidden", NetworkManager.class, Integer.class, "router.ram.size", "128", "Default RAM for router VM (in MB).", null), VmOpWaitInterval("Advanced", ManagementServer.class, Integer.class, "vm.op.wait.interval", "120", "Time (in seconds) to wait before checking if a previous operation has succeeded", null), diff --git a/server/src/com/cloud/configuration/ConfigurationManager.java b/server/src/com/cloud/configuration/ConfigurationManager.java old mode 100644 new mode 100755 index 20e98845ac0..d7faf19fd28 --- a/server/src/com/cloud/configuration/ConfigurationManager.java +++ b/server/src/com/cloud/configuration/ConfigurationManager.java @@ -30,6 +30,7 @@ import com.cloud.dc.Vlan; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceAllocationException; import com.cloud.network.Network; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; @@ -78,10 +79,11 @@ public interface ConfigurationManager extends ConfigurationService, Manager { * TODO * @param id * @param useVirtualNetwork + * @param deploymentPlanner * @return ID */ ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, VirtualMachine.Type vm_typeType, String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired, - boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate); + boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner); /** * Creates a new disk offering @@ -149,6 +151,8 @@ public interface ConfigurationManager extends ConfigurationService, Manager { */ boolean deleteVlanAndPublicIpRange(long userId, long vlanDbId, Account caller); + boolean releasePublicIpRange(long userId, long vlanDbId, Account caller); + /** * Converts a comma separated list of tags to a List * @@ -210,7 +214,7 @@ public interface ConfigurationManager extends ConfigurationService, Manager { ClusterVO getCluster(long id); - boolean deleteAccountSpecificVirtualRanges(long accountId); + boolean releaseAccountSpecificVirtualRanges(long accountId); /** * Edits a pod in the database. Will not allow you to edit pods that are being used anywhere in the system. diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 1526fb0e125..c9ae854ee81 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -56,7 +56,9 @@ import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCmd import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd; import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd; import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd; +import org.apache.cloudstack.api.command.admin.vlan.DedicatePublicIpRangeCmd; import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd; +import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd; 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.UpdateZoneCmd; @@ -1821,16 +1823,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } return createServiceOffering(userId, cmd.getIsSystem(), vmType, cmd.getServiceOfferingName(), cpuNumber.intValue(), memory.intValue(), cpuSpeed.intValue(), cmd.getDisplayText(), - localStorageRequired, offerHA, limitCpuUse, volatileVm, cmd.getTags(), cmd.getDomainId(), cmd.getHostTag(), cmd.getNetworkRate()); + localStorageRequired, offerHA, limitCpuUse, volatileVm, cmd.getTags(), cmd.getDomainId(), cmd.getHostTag(), cmd.getNetworkRate(), cmd.getDeploymentPlanner()); } @Override @ActionEvent(eventType = EventTypes.EVENT_SERVICE_OFFERING_CREATE, eventDescription = "creating service offering") public ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, VirtualMachine.Type vm_type, String name, int cpu, int ramSize, int speed, String displayText, - boolean localStorageRequired, boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate) { + boolean localStorageRequired, boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner) { tags = cleanupTags(tags); ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, speed, networkRate, null, offerHA, limitResourceUse, volatileVm, displayText, localStorageRequired, false, tags, isSystem, vm_type, - domainId, hostTag); + domainId, hostTag, deploymentPlanner); if ((offering = _serviceOfferingDao.persist(offering)) != null) { UserContext.current().setEventDetails("Service offering id=" + offering.getId()); @@ -2306,9 +2308,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("Gateway, netmask and zoneId have to be passed in for virtual and direct untagged networks"); } - // if it's an account specific range, associate ip address list to the account - boolean associateIpRangeToAccount = false; - if (forVirtualNetwork) { if (vlanOwner != null) { @@ -2316,8 +2315,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati //check resource limits _resourceLimitMgr.checkResourceLimit(vlanOwner, ResourceType.public_ip, accountIpRange); - - associateIpRangeToAccount = true; } } @@ -2332,21 +2329,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati endIP, vlanGateway, vlanNetmask, vlanId, vlanOwner, startIPv6, endIPv6, ip6Gateway, ip6Cidr); txn.commit(); - if (associateIpRangeToAccount) { - _networkMgr.associateIpAddressListToAccount(userId, vlanOwner.getId(), zoneId, vlan.getId(), null); - } - - // Associate ips to the network - if (associateIpRangeToAccount) { - if (network.getState() == Network.State.Implemented) { - s_logger.debug("Applying ip associations for vlan id=" + vlanId + " in network " + network); - if (!_networkMgr.applyIpAssociations(network, false)) { - s_logger.warn("Failed to apply ip associations for vlan id=1 as a part of add vlan range for account id=" + vlanOwner.getId()); - } - } else { - s_logger.trace("Network id=" + network.getId() + " is not Implemented, no need to apply ipAssociations"); - } - } return vlan; } @@ -2698,6 +2680,149 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } + @Override + @DB + @ActionEvent(eventType = EventTypes.EVENT_VLAN_IP_RANGE_DEDICATE, eventDescription = "dedicating vlan ip range", async = false) + public Vlan dedicatePublicIpRange(DedicatePublicIpRangeCmd cmd) throws ResourceAllocationException { + Long vlanDbId = cmd.getId(); + String accountName = cmd.getAccountName(); + Long domainId = cmd.getDomainId(); + Long projectId = cmd.getProjectId(); + + // Check if account is valid + Account vlanOwner = null; + if (projectId != null) { + if (accountName != null) { + throw new InvalidParameterValueException("accountName and projectId are mutually exclusive"); + } + Project project = _projectMgr.getProject(projectId); + if (project == null) { + throw new InvalidParameterValueException("Unable to find project by id " + projectId); + } + vlanOwner = _accountMgr.getAccount(project.getProjectAccountId()); + } + + if ((accountName != null) && (domainId != null)) { + vlanOwner = _accountDao.findActiveAccount(accountName, domainId); + if (vlanOwner == null) { + throw new InvalidParameterValueException("Please specify a valid account"); + } + } + + // Check if range is valid + VlanVO vlan = _vlanDao.findById(vlanDbId); + if (vlan == null) { + throw new InvalidParameterValueException("Please specify a valid Public IP range id"); + } + + // Check if range has already been dedicated + List maps = _accountVlanMapDao.listAccountVlanMapsByVlan(vlanDbId); + if (maps != null && !maps.isEmpty()) { + throw new InvalidParameterValueException("Specified Public IP range has already been dedicated"); + } + + // Verify that zone exists and is advanced + Long zoneId = vlan.getDataCenterId(); + DataCenterVO zone = _zoneDao.findById(zoneId); + if (zone == null) { + throw new InvalidParameterValueException("Unable to find zone by id " + zoneId); + } + if (zone.getNetworkType() == NetworkType.Basic) { + throw new InvalidParameterValueException("Public IP range can be dedicated to an account only in the zone of type " + NetworkType.Advanced); + } + + // Check Public IP resource limits + int accountPublicIpRange = _publicIpAddressDao.countIPs(zoneId, vlanDbId, false); + _resourceLimitMgr.checkResourceLimit(vlanOwner, ResourceType.public_ip, accountPublicIpRange); + + // Check if any of the Public IP addresses is allocated to another account + List ips = _publicIpAddressDao.listByVlanId(vlanDbId); + for (IPAddressVO ip : ips) { + Long allocatedToAccountId = ip.getAllocatedToAccountId(); + if (allocatedToAccountId != null) { + Account accountAllocatedTo = _accountMgr.getActiveAccountById(allocatedToAccountId); + if (!accountAllocatedTo.getAccountName().equalsIgnoreCase(accountName)) + throw new InvalidParameterValueException("Public IP address in range is already allocated to another account"); + } + } + + Transaction txn = Transaction.currentTxn(); + txn.start(); + + // Create an AccountVlanMapVO entry + AccountVlanMapVO accountVlanMapVO = new AccountVlanMapVO(vlanOwner.getId(), vlan.getId()); + _accountVlanMapDao.persist(accountVlanMapVO); + + txn.commit(); + + return vlan; + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_VLAN_IP_RANGE_RELEASE, eventDescription = "releasing a public ip range", async = false) + public boolean releasePublicIpRange(ReleasePublicIpRangeCmd cmd) { + Long vlanDbId = cmd.getId(); + + VlanVO vlan = _vlanDao.findById(vlanDbId); + if (vlan == null) { + throw new InvalidParameterValueException("Please specify a valid IP range id."); + } + + return releasePublicIpRange(vlanDbId, UserContext.current().getCallerUserId(), UserContext.current().getCaller()); + } + + @Override + @DB + public boolean releasePublicIpRange(long vlanDbId, long userId, Account caller) { + VlanVO vlan = _vlanDao.findById(vlanDbId); + + List acctVln = _accountVlanMapDao.listAccountVlanMapsByVlan(vlanDbId); + // Verify range is dedicated + if (acctVln == null || acctVln.isEmpty()) { + throw new InvalidParameterValueException("Can't release Public IP range " + vlanDbId + " as it not dedicated to any account"); + } + + // Check if range has any allocated public IPs + long allocIpCount = _publicIpAddressDao.countIPs(vlan.getDataCenterId(), vlanDbId, true); + boolean success = true; + if (allocIpCount > 0) { + try { + vlan = _vlanDao.acquireInLockTable(vlanDbId, 30); + if (vlan == null) { + throw new CloudRuntimeException("Unable to acquire vlan configuration: " + vlanDbId); + } + if (s_logger.isDebugEnabled()) { + s_logger.debug("lock vlan " + vlanDbId + " is acquired"); + } + List ips = _publicIpAddressDao.listByVlanId(vlanDbId); + for (IPAddressVO ip : ips) { + // Disassociate allocated IP's that are not in use + if ( !ip.isOneToOneNat() && !(ip.isSourceNat() && _networkModel.getNetwork(ip.getAssociatedWithNetworkId()) != null) && + !(_firewallDao.countRulesByIpId(ip.getId()) > 0) ) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Releasing Public IP addresses" + ip +" of vlan " + vlanDbId + " as part of Public IP" + + " range release to the system pool"); + } + success = success && _networkMgr.disassociatePublicIpAddress(ip.getId(), userId, caller); + } + } + if (!success) { + s_logger.warn("Some Public IP addresses that were not in use failed to be released as a part of" + + " vlan " + vlanDbId + "release to the system pool"); + } + } finally { + _vlanDao.releaseFromLockTable(vlanDbId); + } + } + + // A Public IP range can only be dedicated to one account at a time + if (_accountVlanMapDao.remove(acctVln.get(0).getId())) { + return true; + } else { + return false; + } + } + @Override public List csvTagsToList(String tags) { List tagsList = new ArrayList(); @@ -3177,8 +3302,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("Invalid service provider: " + prvNameStr); } - if (provider == Provider.JuniperSRX) { - firewallProvider = Provider.JuniperSRX; + if (provider == Provider.JuniperSRX || provider == Provider.CiscoVnmc) { + firewallProvider = provider; } if ((service == Service.PortForwarding || service == Service.StaticNat) && provider == Provider.VirtualRouter){ @@ -3308,20 +3433,34 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati void validateStaticNatServiceCapablities(Map staticNatServiceCapabilityMap) { if (staticNatServiceCapabilityMap != null && !staticNatServiceCapabilityMap.isEmpty()) { - if (staticNatServiceCapabilityMap.keySet().size() > 1) { - throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " capability can be specified for static nat service"); + if (staticNatServiceCapabilityMap.keySet().size() > 2) { + throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " and " + Capability.AssociatePublicIP.getName() + " capabilitiy can be sepcified for static nat service"); } + boolean eipEnabled = false; + boolean eipDisabled = false; + boolean associatePublicIP = true; for (Capability capability : staticNatServiceCapabilityMap.keySet()) { String value = staticNatServiceCapabilityMap.get(capability); if (capability == Capability.ElasticIp) { - boolean enabled = value.contains("true"); - boolean disabled = value.contains("false"); - if (!enabled && !disabled) { + eipEnabled = value.contains("true"); + eipDisabled = value.contains("false"); + if (!eipEnabled && !eipDisabled) { throw new InvalidParameterValueException("Unknown specified value for " + Capability.ElasticIp.getName()); } + } else if (capability == Capability.AssociatePublicIP) { + if (value.contains("true")) { + associatePublicIP = true; + } else if (value.contains("false")) { + associatePublicIP = false; + } else { + throw new InvalidParameterValueException("Unknown specified value for " + Capability.AssociatePublicIP.getName()); + } } else { - throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " capability can be specified for static nat service"); + throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " and " + Capability.AssociatePublicIP.getName() + " capabilitiy can be sepcified for static nat service"); + } + if (eipDisabled && associatePublicIP) { + throw new InvalidParameterValueException("Capability " + Capability.AssociatePublicIP.getName() + " can only be set when capability " + Capability.ElasticIp.getName() + " is true"); } } } @@ -3383,6 +3522,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati boolean sharedSourceNat = false; boolean redundantRouter = false; boolean elasticIp = false; + boolean associatePublicIp = false; boolean inline = false; if (serviceCapabilityMap != null && !serviceCapabilityMap.isEmpty()) { Map lbServiceCapabilityMap = serviceCapabilityMap.get(Service.Lb); @@ -3432,13 +3572,17 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati String param = staticNatServiceCapabilityMap.get(Capability.ElasticIp); if (param != null) { elasticIp = param.contains("true"); + String associatePublicIP = staticNatServiceCapabilityMap.get(Capability.AssociatePublicIP); + if (associatePublicIP != null) { + associatePublicIp = associatePublicIP.contains("true"); + } } } } NetworkOfferingVO offering = new NetworkOfferingVO(name, displayText, trafficType, systemOnly, specifyVlan, networkRate, multicastRate, isDefault, availability, tags, type, conserveMode, dedicatedLb, - sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline, isPersistent); + sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline, isPersistent, associatePublicIp); if (serviceOfferingId != null) { offering.setServiceOfferingId(serviceOfferingId); @@ -3957,14 +4101,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override @DB - public boolean deleteAccountSpecificVirtualRanges(long accountId) { + public boolean releaseAccountSpecificVirtualRanges(long accountId) { List maps = _accountVlanMapDao.listAccountVlanMapsByAccount(accountId); boolean result = true; if (maps != null && !maps.isEmpty()) { Transaction txn = Transaction.currentTxn(); txn.start(); for (AccountVlanMapVO map : maps) { - if (!deleteVlanAndPublicIpRange(_accountMgr.getSystemUser().getId(), map.getVlanDbId(), + if (!releasePublicIpRange(map.getVlanDbId(), _accountMgr.getSystemUser().getId(), _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM))) { result = false; } @@ -3972,10 +4116,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (result) { txn.commit(); } else { - s_logger.error("Failed to delete account specific virtual ip ranges for account id=" + accountId); + s_logger.error("Failed to release account specific virtual ip ranges for account id=" + accountId); } } else { - s_logger.trace("Account id=" + accountId + " has no account specific virtual ip ranges, nothing to delete"); + s_logger.trace("Account id=" + accountId + " has no account specific virtual ip ranges, nothing to release"); } return result; } diff --git a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java index ff6e64eca94..df53e0d7d81 100755 --- a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java +++ b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java @@ -33,6 +33,7 @@ import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.info.ConsoleProxyInfo; import com.cloud.keystore.KeystoreManager; +import com.cloud.server.ManagementServer; import com.cloud.utils.NumbersUtil; import com.cloud.utils.component.ManagerBase; import com.cloud.vm.ConsoleProxyVO; @@ -69,12 +70,13 @@ public class AgentBasedConsoleProxyManager extends ManagerBase implements Consol protected KeystoreManager _ksMgr; @Inject ConfigurationDao _configDao; + @Inject ManagementServer _ms; public class AgentBasedAgentHook extends AgentHookBase { public AgentBasedAgentHook(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, - KeystoreManager ksMgr, AgentManager agentMgr) { - super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr); + KeystoreManager ksMgr, AgentManager agentMgr, ManagementServer ms) { + super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr, ms); } @Override @@ -120,7 +122,7 @@ public class AgentBasedConsoleProxyManager extends ManagerBase implements Consol _consoleProxyUrlDomain = configs.get("consoleproxy.url.domain"); _listener = - new ConsoleProxyListener(new AgentBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr, _agentMgr)); + new ConsoleProxyListener(new AgentBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr, _agentMgr, _ms)); _agentMgr.registerForHostEvents(_listener, true, true, false); if (s_logger.isInfoEnabled()) { diff --git a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java.orig b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java.orig deleted file mode 100755 index 134d59d0065..00000000000 --- a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java.orig +++ /dev/null @@ -1,298 +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.consoleproxy; - -import java.util.Map; - -import javax.ejb.Local; -import javax.inject.Inject; -import javax.naming.ConfigurationException; - -import org.apache.log4j.Logger; - -import com.cloud.agent.AgentManager; -import com.cloud.agent.api.GetVncPortAnswer; -import com.cloud.agent.api.GetVncPortCommand; -import com.cloud.agent.api.StartupProxyCommand; -import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.host.HostVO; -import com.cloud.host.dao.HostDao; -import com.cloud.info.ConsoleProxyInfo; -import com.cloud.keystore.KeystoreManager; -import com.cloud.utils.NumbersUtil; -import com.cloud.utils.component.ManagerBase; -import com.cloud.vm.ConsoleProxyVO; -import com.cloud.vm.UserVmVO; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachineManager; -import com.cloud.vm.dao.ConsoleProxyDao; -import com.cloud.vm.dao.UserVmDao; -import com.cloud.vm.dao.VMInstanceDao; - -@Local(value = { ConsoleProxyManager.class }) -public class AgentBasedConsoleProxyManager extends ManagerBase implements ConsoleProxyManager { - private static final Logger s_logger = Logger.getLogger(AgentBasedConsoleProxyManager.class); - - @Inject - protected HostDao _hostDao; - @Inject - protected UserVmDao _userVmDao; - private String _instance; - protected String _consoleProxyUrlDomain; - @Inject - private VMInstanceDao _instanceDao; - private ConsoleProxyListener _listener; - protected int _consoleProxyUrlPort = ConsoleProxyManager.DEFAULT_PROXY_URL_PORT; - protected int _consoleProxyPort = ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT; - protected boolean _sslEnabled = false; - @Inject - AgentManager _agentMgr; - @Inject - VirtualMachineManager _itMgr; - @Inject - protected ConsoleProxyDao _cpDao; - @Inject - protected KeystoreManager _ksMgr; - - @Inject ConfigurationDao _configDao; - - public class AgentBasedAgentHook extends AgentHookBase { - - public AgentBasedAgentHook(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, - KeystoreManager ksMgr, AgentManager agentMgr) { - super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr); - } - - @Override - protected HostVO findConsoleProxyHost(StartupProxyCommand cmd) { - return _hostDao.findByGuid(cmd.getGuid()); - } - - } - - public int getVncPort(VMInstanceVO vm) { - if (vm.getHostId() == null) { - return -1; - } - GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getHostName())); - return (answer == null || !answer.getResult()) ? -1 : answer.getPort(); - } - - @Override - public boolean configure(String name, Map params) throws ConfigurationException { - - if (s_logger.isInfoEnabled()) { - s_logger.info("Start configuring AgentBasedConsoleProxyManager"); - } - - Map configs = _configDao.getConfiguration("management-server", params); - String value = configs.get("consoleproxy.url.port"); - if (value != null) { - _consoleProxyUrlPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_URL_PORT); - } - - value = configs.get("consoleproxy.port"); - if (value != null) { - _consoleProxyPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT); - } - - value = configs.get("consoleproxy.sslEnabled"); - if (value != null && value.equalsIgnoreCase("true")) { - _sslEnabled = true; - } - - _instance = configs.get("instance.name"); - - _consoleProxyUrlDomain = configs.get("consoleproxy.url.domain"); - - _listener = - new ConsoleProxyListener(new AgentBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr, _agentMgr)); - _agentMgr.registerForHostEvents(_listener, true, true, false); - - if (s_logger.isInfoEnabled()) { - s_logger.info("AgentBasedConsoleProxyManager has been configured. SSL enabled: " + _sslEnabled); - } - return true; - } - - HostVO findHost(VMInstanceVO vm) { - return _hostDao.findById(vm.getHostId()); - } - - @Override - public ConsoleProxyInfo assignProxy(long dataCenterId, long userVmId) { - UserVmVO userVm = _userVmDao.findById(userVmId); - if (userVm == null) { - s_logger.warn("User VM " + userVmId + " no longer exists, return a null proxy for user vm:" + userVmId); - return null; - } - - HostVO host = findHost(userVm); - if (host != null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Assign embedded console proxy running at " + host.getName() + " to user vm " + userVmId + " with public IP " - + host.getPublicIpAddress()); - } - - // only private IP, public IP, host id have meaningful values, rest - // of all are place-holder values - String publicIp = host.getPublicIpAddress(); - if (publicIp == null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Host " + host.getName() + "/" + host.getPrivateIpAddress() - + " does not have public interface, we will return its private IP for cosole proxy."); - } - publicIp = host.getPrivateIpAddress(); - } - - int urlPort = _consoleProxyUrlPort; - - if (host.getProxyPort() != null && host.getProxyPort().intValue() > 0) { - urlPort = host.getProxyPort().intValue(); - } - - return new ConsoleProxyInfo(_sslEnabled, publicIp, _consoleProxyPort, urlPort, _consoleProxyUrlDomain); - } else { - s_logger.warn("Host that VM is running is no longer available, console access to VM " + userVmId + " will be temporarily unavailable."); - } - return null; - } - - - - - @Override - public ConsoleProxyVO startProxy(long proxyVmId) { - return null; - } - - @Override - public boolean destroyProxy(long proxyVmId) { - return false; - } - - @Override - public boolean rebootProxy(long proxyVmId) { - return false; - } - - @Override - public boolean stopProxy(long proxyVmId) { - return false; - } - - @Override - public void setManagementState(ConsoleProxyManagementState state) { - } - - @Override - public ConsoleProxyManagementState getManagementState() { - return null; - } - - @Override - public void resumeLastManagementState() { - } - - @Override - public String getName() { - return _name; - } -<<<<<<< HEAD - - @Override - public Long convertToId(String vmName) { - if (!VirtualMachineName.isValidConsoleProxyName(vmName, _instance)) { - return null; - } - return VirtualMachineName.getConsoleProxyId(vmName); - } - - @Override - public ConsoleProxyVO findByName(String name) { - // TODO Auto-generated method stub - return null; - } - - @Override - public ConsoleProxyVO findById(long id) { - // TODO Auto-generated method stub - return null; - } - - @Override - public ConsoleProxyVO persist(ConsoleProxyVO vm) { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { - // TODO Auto-generated method stub - } - - @Override - public void finalizeExpunge(ConsoleProxyVO proxy) { - } - - @Override - public boolean plugNic(Network network, NicTO nic, VirtualMachineTO vm, - ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException, - InsufficientCapacityException { - //not supported - throw new UnsupportedOperationException("Plug nic is not supported for vm of type " + vm.getType()); - } - - - @Override - public boolean unplugNic(Network network, NicTO nic, VirtualMachineTO vm, - ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException { - //not supported - throw new UnsupportedOperationException("Unplug nic is not supported for vm of type " + vm.getType()); - } - - @Override - public void prepareStop(VirtualMachineProfile profile) { - } -} -======= -} ->>>>>>> QuickCloud: refactor to avoid copy paste of authentication and startup code diff --git a/server/src/com/cloud/consoleproxy/AgentHookBase.java b/server/src/com/cloud/consoleproxy/AgentHookBase.java index b969f6da2ce..2748a8cb68c 100644 --- a/server/src/com/cloud/consoleproxy/AgentHookBase.java +++ b/server/src/com/cloud/consoleproxy/AgentHookBase.java @@ -42,10 +42,14 @@ import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.keystore.KeystoreManager; +import com.cloud.server.ManagementServer; +import com.cloud.servlet.ConsoleProxyPasswordBasedEncryptor; import com.cloud.servlet.ConsoleProxyServlet; import com.cloud.utils.Ternary; import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.VMInstanceDao; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; /** * Utility class to manage interactions with agent-based console access @@ -60,28 +64,19 @@ public abstract class AgentHookBase implements AgentHook { ConfigurationDao _configDao; AgentManager _agentMgr; KeystoreManager _ksMgr; + ManagementServer _ms; final Random _random = new Random(System.currentTimeMillis()); private String _hashKey; public AgentHookBase(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, KeystoreManager ksMgr, - AgentManager agentMgr) { + AgentManager agentMgr, ManagementServer ms) { this._instanceDao = instanceDao; this._hostDao = hostDao; this._agentMgr = agentMgr; this._configDao = cfgDao; this._ksMgr = ksMgr; - } - - public String getHashKey() { - // although we may have race condition here, database transaction - // serialization should give us the same key - if (_hashKey == null) { - _hashKey = - _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), Config.HashKey.getCategory(), UUID - .randomUUID().toString()); - } - return _hashKey; + this._ms = ms; } public AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd) { @@ -212,10 +207,10 @@ public abstract class AgentHookBase implements AgentHook { s_logger.error("Could not find and construct a valid SSL certificate"); } cmd = new StartConsoleProxyAgentHttpHandlerCommand(ksBits, storePassword); - cmd.setEncryptorPassword(getHashKey()); + cmd.setEncryptorPassword(getEncryptorPassword()); } else { cmd = new StartConsoleProxyAgentHttpHandlerCommand(); - cmd.setEncryptorPassword(getHashKey()); + cmd.setEncryptorPassword(getEncryptorPassword()); } try { @@ -246,6 +241,33 @@ public abstract class AgentHookBase implements AgentHook { + startupCmd.getProxyVmId(), e); } } + + private String getEncryptorPassword() { + String key; + String iv; + ConsoleProxyPasswordBasedEncryptor.KeyIVPair keyIvPair = null; + + // if we failed after reset, something is definitely wrong + for(int i = 0; i < 2; i++) { + key = _ms.getEncryptionKey(); + iv = _ms.getEncryptionIV(); + + keyIvPair = new ConsoleProxyPasswordBasedEncryptor.KeyIVPair(key, iv); + + if(keyIvPair.getIvBytes() == null || keyIvPair.getIvBytes().length != 16 || + keyIvPair.getKeyBytes() == null || keyIvPair.getKeyBytes().length != 16) { + + s_logger.warn("Console access AES KeyIV sanity check failed, reset and regenerate"); + _ms.resetEncryptionKeyIV(); + } else { + break; + } + } + + Gson gson = new GsonBuilder().create(); + return gson.toJson(keyIvPair); + } + protected abstract HostVO findConsoleProxyHost(StartupProxyCommand cmd); diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 9740d28a94f..c4ad8170d6d 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -95,8 +95,10 @@ import com.cloud.resource.ResourceManager; import com.cloud.resource.ResourceStateAdapter; import com.cloud.resource.ServerResource; import com.cloud.resource.UnableDeleteHostException; +import com.cloud.server.ManagementServer; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.servlet.ConsoleProxyPasswordBasedEncryptor; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.VMTemplateHostVO; @@ -220,6 +222,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy TemplateManager templateMgr; @Inject IPAddressDao _ipAddressDao; + @Inject + ManagementServer _ms; private ConsoleProxyListener _listener; @@ -254,7 +258,6 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy private Map _zoneProxyCountMap; // map private Map _zoneVmCountMap; // map - private String _hashKey; private String _staticPublicIp; private int _staticPort; @@ -448,8 +451,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy public class VmBasedAgentHook extends AgentHookBase { public VmBasedAgentHook(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, - KeystoreManager ksMgr, AgentManager agentMgr) { - super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr); + KeystoreManager ksMgr, AgentManager agentMgr, ManagementServer ms) { + super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr, ms); } @Override @@ -1439,7 +1442,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy _listener = new ConsoleProxyListener(new VmBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr, - _agentMgr)); + _agentMgr, _ms)); _agentMgr.registerForHostEvents(_listener, true, true, false); _itMgr.registerGuru(VirtualMachine.Type.ConsoleProxy, this); @@ -1884,15 +1887,6 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy return sc.find(); } - public String getHashKey() { - // although we may have race conditioning here, database transaction serialization should - // give us the same key - if (_hashKey == null) { - _hashKey = _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), Config.HashKey.getCategory(), UUID.randomUUID().toString()); - } - return _hashKey; - } - @Override public boolean plugNic(Network network, NicTO nic, VirtualMachineTO vm, ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException, @@ -1912,4 +1906,5 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy @Override public void prepareStop(VirtualMachineProfile profile) { } + } diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManager.java b/server/src/com/cloud/deploy/DeploymentPlanningManager.java new file mode 100644 index 00000000000..13f1c67d613 --- /dev/null +++ b/server/src/com/cloud/deploy/DeploymentPlanningManager.java @@ -0,0 +1,45 @@ +// 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.deploy; + +import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.exception.AffinityConflictException; +import com.cloud.exception.InsufficientServerCapacityException; +import com.cloud.utils.component.Manager; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; + +public interface DeploymentPlanningManager extends Manager { + + /** + * Manages vm deployment stages: First Process Affinity/Anti-affinity - Call + * the chain of AffinityGroupProcessor adapters to set deploymentplan scope + * and exclude list Secondly, Call DeploymentPlanner - to use heuristics to + * find the best spot to place the vm/volume. Planner will drill down to the + * write set of clusters to look for placement based on various heuristics. + * Lastly, Call Allocators - Given a cluster, allocators matches the + * requirements to capabilities of the physical resource (host, storage + * pool). + * + * @throws AffinityConflictException + * + * + * + */ + DeployDestination planDeployment(VirtualMachineProfile vmProfile, DeploymentPlan plan, + ExcludeList avoids) throws InsufficientServerCapacityException, AffinityConflictException; +} diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java new file mode 100644 index 00000000000..c7162a2003f --- /dev/null +++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -0,0 +1,106 @@ +// 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.deploy; + +import java.util.List; + +import javax.ejb.Local; +import javax.inject.Inject; + +import org.apache.cloudstack.affinity.AffinityGroupProcessor; +import org.apache.cloudstack.affinity.AffinityGroupVMMapVO; +import org.apache.cloudstack.affinity.dao.AffinityGroupDao; +import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; +import org.apache.log4j.Logger; + +import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.exception.AffinityConflictException; +import com.cloud.exception.InsufficientServerCapacityException; +import com.cloud.utils.component.Manager; +import com.cloud.utils.component.ManagerBase; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachineProfile; +import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.dao.VMInstanceDao; + +@Local(value = { DeploymentPlanningManager.class }) +public class DeploymentPlanningManagerImpl extends ManagerBase implements DeploymentPlanningManager, Manager { + + private static final Logger s_logger = Logger.getLogger(DeploymentPlanningManagerImpl.class); + @Inject + protected UserVmDao _vmDao; + @Inject + protected VMInstanceDao _vmInstanceDao; + @Inject + protected AffinityGroupDao _affinityGroupDao; + @Inject + protected AffinityGroupVMMapDao _affinityGroupVMMapDao; + + protected List _planners; + public List getPlanners() { + return _planners; + } + public void setPlanners(List _planners) { + this._planners = _planners; + } + + protected List _affinityProcessors; + public List getAffinityGroupProcessors() { + return _affinityProcessors; + } + public void setAffinityGroupProcessors(List affinityProcessors) { + this._affinityProcessors = affinityProcessors; + } + + @Override + public DeployDestination planDeployment(VirtualMachineProfile vmProfile, + DeploymentPlan plan, ExcludeList avoids) throws InsufficientServerCapacityException, + AffinityConflictException { + + // call affinitygroup chain + VirtualMachine vm = vmProfile.getVirtualMachine(); + long vmGroupCount = _affinityGroupVMMapDao.countAffinityGroupsForVm(vm.getId()); + + if (vmGroupCount > 0) { + for (AffinityGroupProcessor processor : _affinityProcessors) { + processor.process(vmProfile, plan, avoids); + } + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Deploy avoids pods: " + avoids.getPodsToAvoid() + ", clusters: " + + avoids.getClustersToAvoid() + ", hosts: " + avoids.getHostsToAvoid()); + } + + // call planners + DeployDestination dest = null; + for (DeploymentPlanner planner : _planners) { + if (planner.canHandle(vmProfile, plan, avoids)) { + dest = planner.plan(vmProfile, plan, avoids); + } else { + continue; + } + if (dest != null) { + avoids.addHost(dest.getHost().getId()); + break; + } + + } + return dest; + } + +} diff --git a/server/src/com/cloud/deploy/FirstFitPlanner.java b/server/src/com/cloud/deploy/FirstFitPlanner.java index 2dffe70fb46..1647cf7dba9 100755 --- a/server/src/com/cloud/deploy/FirstFitPlanner.java +++ b/server/src/com/cloud/deploy/FirstFitPlanner.java @@ -161,38 +161,44 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { + hostIdSpecified); } HostVO host = _hostDao.findById(hostIdSpecified); - if (s_logger.isDebugEnabled()) { - if(host == null){ - s_logger.debug("The specified host cannot be found"); - }else{ + if (host == null) { + s_logger.debug("The specified host cannot be found"); + } else if (avoid.shouldAvoid(host)) { + s_logger.debug("The specified host is in avoid set"); + } else { + if (s_logger.isDebugEnabled()) { s_logger.debug("Looking for suitable pools for this host under zone: "+host.getDataCenterId() +", pod: "+ host.getPodId()+", cluster: "+ host.getClusterId()); } - } - //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, plan.getReservationContext()); + // 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, plan.getReservationContext()); - Pair>, List> result = findSuitablePoolsForVolumes(vmProfile, lastPlan, avoid, HostAllocator.RETURN_UPTO_ALL); - Map> suitableVolumeStoragePools = result.first(); - List readyAndReusedVolumes = result.second(); + Pair>, List> result = findSuitablePoolsForVolumes(vmProfile, + lastPlan, avoid, HostAllocator.RETURN_UPTO_ALL); + Map> suitableVolumeStoragePools = result.first(); + List readyAndReusedVolumes = result.second(); - //choose the potential pool for this VM for this host - if(!suitableVolumeStoragePools.isEmpty()){ - List suitableHosts = new ArrayList(); - suitableHosts.add(host); + // choose the potential pool for this VM for this host + if (!suitableVolumeStoragePools.isEmpty()) { + List suitableHosts = new ArrayList(); + suitableHosts.add(host); - Pair> potentialResources = findPotentialDeploymentResources(suitableHosts, suitableVolumeStoragePools); - 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. - for(Volume vol : readyAndReusedVolumes){ - storageVolMap.remove(vol); + Pair> potentialResources = findPotentialDeploymentResources( + suitableHosts, suitableVolumeStoragePools); + 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. + for (Volume vol : readyAndReusedVolumes) { + storageVolMap.remove(vol); + } + DeployDestination dest = new DeployDestination(dc, pod, cluster, host, storageVolMap); + s_logger.debug("Returning Deployment Destination: " + dest); + return dest; } - DeployDestination dest = new DeployDestination(dc, pod, cluster, host, storageVolMap); - s_logger.debug("Returning Deployment Destination: "+ dest); - return dest; } } s_logger.debug("Cannnot deploy to specified host, returning."); diff --git a/server/src/com/cloud/domain/dao/DomainDaoImpl.java b/server/src/com/cloud/domain/dao/DomainDaoImpl.java index 79ef17ed2a6..c30ca5ef49a 100644 --- a/server/src/com/cloud/domain/dao/DomainDaoImpl.java +++ b/server/src/com/cloud/domain/dao/DomainDaoImpl.java @@ -262,11 +262,14 @@ public class DomainDaoImpl extends GenericDaoBase implements Dom public Set getDomainParentIds(long domainId) { Set parentDomains = new HashSet(); Domain domain = findById(domainId); - parentDomains.add(domain.getId()); - - while (domain.getParent() != null) { - domain = findById(domain.getParent()); + + if (domain != null) { parentDomains.add(domain.getId()); + + while (domain.getParent() != null) { + domain = findById(domain.getParent()); + parentDomains.add(domain.getId()); + } } return parentDomains; diff --git a/server/src/com/cloud/network/ExteralIpAddressAllocator.java b/server/src/com/cloud/network/ExternalIpAddressAllocator.java similarity index 96% rename from server/src/com/cloud/network/ExteralIpAddressAllocator.java rename to server/src/com/cloud/network/ExternalIpAddressAllocator.java index 2b78712b86f..f24fa2d29b9 100644 --- a/server/src/com/cloud/network/ExteralIpAddressAllocator.java +++ b/server/src/com/cloud/network/ExternalIpAddressAllocator.java @@ -37,8 +37,8 @@ import com.cloud.utils.component.AdapterBase; import com.cloud.utils.exception.CloudRuntimeException; @Local(value=IpAddrAllocator.class) -public class ExteralIpAddressAllocator extends AdapterBase implements IpAddrAllocator{ - private static final Logger s_logger = Logger.getLogger(ExteralIpAddressAllocator.class); +public class ExternalIpAddressAllocator extends AdapterBase implements IpAddrAllocator{ + private static final Logger s_logger = Logger.getLogger(ExternalIpAddressAllocator.class); String _name; @Inject ConfigurationDao _configDao = null; @Inject IPAddressDao _ipAddressDao = null; @@ -135,7 +135,7 @@ public class ExteralIpAddressAllocator extends AdapterBase implements IpAddrAllo } @Override - public boolean exteralIpAddressAllocatorEnabled() { + public boolean externalIpAddressAllocatorEnabled() { return _isExternalIpAllocatorEnabled; } diff --git a/server/src/com/cloud/network/IpAddrAllocator.java b/server/src/com/cloud/network/IpAddrAllocator.java index d79125b3741..6cdf5972080 100644 --- a/server/src/com/cloud/network/IpAddrAllocator.java +++ b/server/src/com/cloud/network/IpAddrAllocator.java @@ -52,5 +52,5 @@ public interface IpAddrAllocator extends Adapter { public IpAddr getPrivateIpAddress(String macAddr, long dcId, long podId); public boolean releasePublicIpAddress(String ip, long dcId, long podId); public boolean releasePrivateIpAddress(String ip, long dcId, long podId); - public boolean exteralIpAddressAllocatorEnabled(); + public boolean externalIpAddressAllocatorEnabled(); } diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index a97f2ce13e4..7332ef3e9cf 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -16,42 +16,9 @@ // under the License. package com.cloud.network; -import java.net.URI; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import javax.ejb.Local; -import javax.inject.Inject; -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; -import com.cloud.agent.api.AgentControlAnswer; -import com.cloud.agent.api.AgentControlCommand; -import com.cloud.agent.api.Answer; -import com.cloud.agent.api.CheckNetworkAnswer; -import com.cloud.agent.api.CheckNetworkCommand; -import com.cloud.agent.api.Command; -import com.cloud.agent.api.StartupCommand; -import com.cloud.agent.api.StartupRoutingCommand; +import com.cloud.agent.api.*; import com.cloud.agent.api.to.NicTO; import com.cloud.alert.AlertManager; import com.cloud.api.ApiDBUtils; @@ -59,15 +26,9 @@ import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.Resource.ResourceType; import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.dc.AccountVlanMapVO; -import com.cloud.dc.DataCenter; +import com.cloud.dc.*; import com.cloud.dc.DataCenter.NetworkType; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.Pod; -import com.cloud.dc.PodVlanMapVO; -import com.cloud.dc.Vlan; import com.cloud.dc.Vlan.VlanType; -import com.cloud.dc.VlanVO; import com.cloud.dc.dao.AccountVlanMapDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.PodVlanMapDao; @@ -80,66 +41,25 @@ import com.cloud.domain.dao.DomainDao; import com.cloud.event.EventTypes; import com.cloud.event.UsageEventUtils; import com.cloud.event.dao.UsageEventDao; -import com.cloud.exception.AccountLimitException; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.ConnectionException; -import com.cloud.exception.InsufficientAddressCapacityException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InsufficientVirtualNetworkCapcityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.PermissionDeniedException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.exception.UnsupportedServiceException; +import com.cloud.exception.*; import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.IpAddress.State; -import com.cloud.network.Network.Capability; -import com.cloud.network.Network.Event; -import com.cloud.network.Network.GuestType; -import com.cloud.network.Network.Provider; -import com.cloud.network.Network.Service; +import com.cloud.network.Network.*; import com.cloud.network.Networks.AddressFormat; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.IsolationType; import com.cloud.network.Networks.TrafficType; import com.cloud.network.addr.PublicIp; -import com.cloud.network.dao.FirewallRulesDao; -import com.cloud.network.dao.IPAddressDao; -import com.cloud.network.dao.IPAddressVO; -import com.cloud.network.dao.LoadBalancerDao; -import com.cloud.network.dao.NetworkDao; -import com.cloud.network.dao.NetworkDomainDao; -import com.cloud.network.dao.NetworkServiceMapDao; -import com.cloud.network.dao.NetworkServiceMapVO; -import com.cloud.network.dao.NetworkVO; -import com.cloud.network.dao.PhysicalNetworkDao; -import com.cloud.network.dao.PhysicalNetworkServiceProviderDao; -import com.cloud.network.dao.PhysicalNetworkTrafficTypeDao; -import com.cloud.network.dao.PhysicalNetworkTrafficTypeVO; -import com.cloud.network.dao.PhysicalNetworkVO; -import com.cloud.network.dao.UserIpv6AddressDao; -import com.cloud.network.element.DhcpServiceProvider; -import com.cloud.network.element.IpDeployer; -import com.cloud.network.element.IpDeployingRequester; -import com.cloud.network.element.LoadBalancingServiceProvider; -import com.cloud.network.element.NetworkElement; -import com.cloud.network.element.StaticNatServiceProvider; -import com.cloud.network.element.UserDataServiceProvider; +import com.cloud.network.dao.*; +import com.cloud.network.element.*; import com.cloud.network.guru.NetworkGuru; import com.cloud.network.lb.LoadBalancingRulesManager; -import com.cloud.network.rules.FirewallManager; -import com.cloud.network.rules.FirewallRule; +import com.cloud.network.rules.*; import com.cloud.network.rules.FirewallRule.Purpose; -import com.cloud.network.rules.FirewallRuleVO; -import com.cloud.network.rules.PortForwardingRuleVO; -import com.cloud.network.rules.RulesManager; -import com.cloud.network.rules.StaticNat; -import com.cloud.network.rules.StaticNatRule; -import com.cloud.network.rules.StaticNatRuleImpl; import com.cloud.network.rules.dao.PortForwardingRulesDao; import com.cloud.network.vpc.NetworkACLManager; import com.cloud.network.vpc.VpcManager; @@ -152,49 +72,40 @@ import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; import com.cloud.org.Grouping; -import com.cloud.user.Account; -import com.cloud.user.AccountManager; -import com.cloud.user.ResourceLimitService; -import com.cloud.user.User; -import com.cloud.user.UserContext; -import com.cloud.user.UserVO; +import com.cloud.user.*; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserDao; import com.cloud.utils.Journal; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.component.AdapterBase; -import com.cloud.utils.component.ComponentContext; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; -import com.cloud.utils.db.DB; -import com.cloud.utils.db.Filter; +import com.cloud.utils.db.*; import com.cloud.utils.db.JoinBuilder.JoinType; -import com.cloud.utils.db.SearchBuilder; -import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Op; -import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.StateMachine2; import com.cloud.utils.net.Ip; import com.cloud.utils.net.NetUtils; -import com.cloud.vm.Nic; +import com.cloud.vm.*; import com.cloud.vm.Nic.ReservationStrategy; -import com.cloud.vm.NicProfile; -import com.cloud.vm.NicVO; -import com.cloud.vm.ReservationContext; -import com.cloud.vm.ReservationContextImpl; -import com.cloud.vm.UserVmVO; -import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Type; -import com.cloud.vm.VirtualMachineProfile; -import com.cloud.vm.dao.NicDao; -import com.cloud.vm.dao.NicSecondaryIpDao; -import com.cloud.vm.dao.NicSecondaryIpVO; -import com.cloud.vm.dao.UserVmDao; -import com.cloud.vm.dao.VMInstanceDao; +import com.cloud.vm.dao.*; +import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import java.net.URI; +import java.util.*; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; /** * NetworkManagerImpl implements NetworkManager. @@ -348,7 +259,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } @DB - public PublicIp fetchNewPublicIp(long dcId, Long podId, Long vlanDbId, Account owner, VlanType vlanUse, + public PublicIp fetchNewPublicIp(long dcId, Long podId, List vlanDbIds, Account owner, VlanType vlanUse, Long guestNetworkId, boolean sourceNat, boolean assign, String requestedIp, boolean isSystem, Long vpcId) throws InsufficientAddressCapacityException { StringBuilder errorMessage = new StringBuilder("Unable to get ip adress in "); @@ -364,9 +275,9 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L errorMessage.append(" zone id=" + dcId); } - if (vlanDbId != null) { - sc.addAnd("vlanId", SearchCriteria.Op.EQ, vlanDbId); - errorMessage.append(", vlanId id=" + vlanDbId); + if ( vlanDbIds != null && !vlanDbIds.isEmpty() ) { + sc.setParameters("vlanId", vlanDbIds.toArray()); + errorMessage.append(", vlanId id=" + vlanDbIds.toArray()); } sc.setParameters("dc", dcId); @@ -526,14 +437,14 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } // If account has Account specific ip ranges, try to allocate ip from there - Long vlanId = null; + List vlanIds = new ArrayList(); List maps = _accountVlanMapDao.listAccountVlanMapsByAccount(ownerId); if (maps != null && !maps.isEmpty()) { - vlanId = maps.get(0).getVlanDbId(); + vlanIds.add(maps.get(0).getVlanDbId()); } - ip = fetchNewPublicIp(dcId, null, vlanId, owner, VlanType.VirtualNetwork, guestNtwkId, + ip = fetchNewPublicIp(dcId, null, vlanIds, owner, VlanType.VirtualNetwork, guestNtwkId, isSourceNat, false, null, false, vpcId); IPAddressVO publicIp = ip.ip(); @@ -663,12 +574,13 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L @DB @Override - public IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerUserId, DataCenter zone) + public IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerUserId, DataCenter zone) throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException { VlanType vlanType = VlanType.VirtualNetwork; boolean assign = false; + boolean allocateFromDedicatedRange = false; if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) { // zone is of type DataCenter. See DataCenterVO.java. @@ -702,8 +614,32 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L txn.start(); - ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, null, - false, assign, null, isSystem, null); + // If account has dedicated Public IP ranges, allocate IP from the dedicated range + List vlanDbIds = new ArrayList(); + List maps = _accountVlanMapDao.listAccountVlanMapsByAccount(ipOwner.getId()); + for (AccountVlanMapVO map : maps) { + vlanDbIds.add(map.getVlanDbId()); + } + if (vlanDbIds != null && !vlanDbIds.isEmpty()) { + allocateFromDedicatedRange = true; + } + + try { + if (allocateFromDedicatedRange) { + ip = fetchNewPublicIp(zone.getId(), null, vlanDbIds, ipOwner, vlanType, null, + false, assign, null, isSystem, null); + } + } catch(InsufficientAddressCapacityException e) { + s_logger.warn("All IPs dedicated to account " + ipOwner.getId() + " has been acquired." + + " Now acquiring from the system pool"); + txn.close(); + allocateFromDedicatedRange = false; + } + + if (!allocateFromDedicatedRange) { + ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, null, false, assign, null, + isSystem, null); + } if (ip == null) { @@ -763,7 +699,22 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L IPAddressVO ipToAssoc = _ipAddressDao.findById(ipId); if (ipToAssoc != null) { - _accountMgr.checkAccess(caller, null, true, ipToAssoc); + Network network = _networksDao.findById(networkId); + if (network == null) { + throw new InvalidParameterValueException("Invalid network id is given"); + } + + DataCenter zone = _configMgr.getZone(network.getDataCenterId()); + if (network.getGuestType() == Network.GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced) { + if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) { + _accountMgr.checkAccess(UserContext.current().getCaller(), AccessType.UseNetwork, false, 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); + } owner = _accountMgr.getAccount(ipToAssoc.getAllocatedToAccountId()); } else { s_logger.debug("Unable to find ip address by id: " + ipId); @@ -790,16 +741,21 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L throw new InvalidParameterValueException("Ip address can be associated to the network with trafficType " + TrafficType.Guest); } - // Check that network belongs to IP owner - skip this check for Basic zone as there is just one guest network, - // and it belongs to the system - if (zone.getNetworkType() != NetworkType.Basic && network.getAccountId() != owner.getId()) { - throw new InvalidParameterValueException("The owner of the network is not the same as owner of the IP"); + // Check that network belongs to IP owner - skip this check + // - if zone is basic zone as there is just one guest network, + // - if shared network in Advanced zone + // - and it belongs to the system + if (network.getAccountId() != owner.getId()) { + if (zone.getNetworkType() != NetworkType.Basic && !(zone.getNetworkType() == NetworkType.Advanced && network.getGuestType() == Network.GuestType.Shared)) { + throw new InvalidParameterValueException("The owner of the network is not the same as owner of the IP"); + } } - // In Advance zone only allow to do IP assoc for Isolated networks with source nat service enabled + // In Advance zone only allow to do IP assoc + // - for Isolated networks with source nat service enabled + // - for shared networks with source nat service enabled if (zone.getNetworkType() == NetworkType.Advanced && - !(network.getGuestType() == GuestType.Isolated && _networkModel.areServicesSupportedInNetwork(network.getId(), - Service.SourceNat))) { + !(_networkModel.areServicesSupportedInNetwork(network.getId(), Service.SourceNat))) { throw new InvalidParameterValueException("In zone of type " + NetworkType.Advanced + " ip address can be associated only to the network of guest type " + GuestType.Isolated + " with the " + Service.SourceNat.getName() + " enabled"); @@ -1082,7 +1038,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L AssignIpAddressSearch = _ipAddressDao.createSearchBuilder(); AssignIpAddressSearch.and("dc", AssignIpAddressSearch.entity().getDataCenterId(), Op.EQ); AssignIpAddressSearch.and("allocated", AssignIpAddressSearch.entity().getAllocatedTime(), Op.NULL); - AssignIpAddressSearch.and("vlanId", AssignIpAddressSearch.entity().getVlanId(), Op.EQ); + AssignIpAddressSearch.and("vlanId", AssignIpAddressSearch.entity().getVlanId(), Op.IN); SearchBuilder vlanSearch = _vlanDao.createSearchBuilder(); vlanSearch.and("type", vlanSearch.entity().getVlanType(), Op.EQ); vlanSearch.and("networkId", vlanSearch.entity().getNetworkId(), Op.EQ); @@ -1471,12 +1427,21 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L try { NetworkGuru guru = AdapterBase.getAdapterByName(_networkGurus, network.getGuruName()); Network.State state = network.getState(); - if (state == Network.State.Implemented || state == Network.State.Setup || state == Network.State.Implementing) { + if (state == Network.State.Implemented || state == Network.State.Implementing) { s_logger.debug("Network id=" + networkId + " is already implemented"); implemented.set(guru, network); return implemented; } + if (state == Network.State.Setup) { + DataCenterVO zone = _dcDao.findById(network.getDataCenterId()); + if (!isSharedNetworkOfferingWithServices(network.getNetworkOfferingId()) || (zone.getNetworkType() == NetworkType.Basic)) { + s_logger.debug("Network id=" + networkId + " is already implemented"); + implemented.set(guru, network); + return implemented; + } + } + if (s_logger.isDebugEnabled()) { s_logger.debug("Asking " + guru.getName() + " to implement " + network); } @@ -1484,7 +1449,11 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId()); network.setReservationId(context.getReservationId()); - stateTransitTo(network, Event.ImplementNetwork); + if (isSharedNetworkWithServices(network)) { + network.setState(Network.State.Implementing); + } else { + stateTransitTo(network, Event.ImplementNetwork); + } Network result = guru.implement(network, offering, dest, context); network.setCidr(result.getCidr()); @@ -1497,7 +1466,11 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L // implement network elements and re-apply all the network rules implementNetworkElementsAndResources(dest, context, network, offering); - stateTransitTo(network,Event.OperationSucceeded); + if (isSharedNetworkWithServices(network)) { + network.setState(Network.State.Implemented); + } else { + stateTransitTo(network,Event.OperationSucceeded); + } network.setRestartRequired(false); _networksDao.update(network.getId(), network); @@ -1510,7 +1483,12 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L if (implemented.first() == null) { s_logger.debug("Cleaning up because we're unable to implement the network " + network); try { - stateTransitTo(network,Event.OperationFailed); + if (isSharedNetworkWithServices(network)) { + network.setState(Network.State.Shutdown); + _networksDao.update(networkId, network); + } else { + stateTransitTo(network,Event.OperationFailed); + } } catch (NoTransitionException e) { s_logger.error(e.getMessage()); } @@ -1535,14 +1513,17 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L NetworkVO network, NetworkOfferingVO offering) throws ConcurrentOperationException, InsufficientAddressCapacityException, ResourceUnavailableException, InsufficientCapacityException { - // If this is a 1) guest virtual network 2) network has sourceNat service 3) network offering does not support a - // Shared source NAT rule, - // associate a source NAT IP (if one isn't already associated with the network) + // Associate a source NAT IP (if one isn't already associated with the network) if this is a + // 1) 'Isolated' or 'Shared' guest virtual network in the advance zone + // 2) network has sourceNat service + // 3) network offering does not support a shared source NAT rule boolean sharedSourceNat = offering.getSharedSourceNat(); - if (network.getGuestType() == Network.GuestType.Isolated - && _networkModel.areServicesSupportedInNetwork(network.getId(), Service.SourceNat) - && !sharedSourceNat) { + DataCenter zone = _dcDao.findById(network.getDataCenterId()); + + if (!sharedSourceNat && _networkModel.areServicesSupportedInNetwork(network.getId(), Service.SourceNat) + && (network.getGuestType() == Network.GuestType.Isolated || + (network.getGuestType() == Network.GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced))) { List ips = null; if (network.getVpcId() != null) { @@ -2006,10 +1987,12 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L throw new InvalidParameterValueException("Network with vlan " + vlanId + " already exists in zone " + zoneId); } } else { - //don't allow to create Shared network with Vlan that already exists in the zone for Isolated networks - if (_networksDao.countByZoneUriAndGuestType(zoneId, uri, GuestType.Isolated) > 0) { - throw new InvalidParameterValueException("Isolated network with vlan " + vlanId + " already exists " + - "in zone " + zoneId); + // don't allow to creating shared network with given Vlan ID, if there already exists a isolated network or + // shared network with same Vlan ID in the zone + if (_networksDao.countByZoneUriAndGuestType(zoneId, uri, GuestType.Isolated) > 0 || + _networksDao.countByZoneUriAndGuestType(zoneId, uri, GuestType.Shared) > 0) { + throw new InvalidParameterValueException("There is a isolated/shared network with vlan id: " + + vlanId + " already exists " + "in zone " + zoneId); } } } @@ -2141,6 +2124,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L @DB public boolean shutdownNetwork(long networkId, ReservationContext context, boolean cleanupElements) { boolean result = false; + Transaction txn = Transaction.currentTxn(); NetworkVO network = _networksDao.lockRow(networkId, true); if (network == null) { @@ -2151,16 +2135,23 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L s_logger.debug("Network is not implemented: " + network); return false; } - try { - stateTransitTo(network, Event.DestroyNetwork); - } catch (NoTransitionException e) { + + txn.start(); + if (isSharedNetworkWithServices(network)) { network.setState(Network.State.Shutdown); _networksDao.update(network.getId(), network); + } else { + try { + stateTransitTo(network, Event.DestroyNetwork); + } catch (NoTransitionException e) { + network.setState(Network.State.Shutdown); + _networksDao.update(network.getId(), network); + } } + txn.commit(); boolean success = shutdownNetworkElementsAndResources(context, cleanupElements, network); - Transaction txn = Transaction.currentTxn(); txn.start(); if (success) { if (s_logger.isDebugEnabled()) { @@ -2171,11 +2162,16 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L guru.shutdown(profile, _networkOfferingDao.findById(network.getNetworkOfferingId())); applyProfileToNetwork(network, profile); - try { - stateTransitTo(network, Event.OperationSucceeded); - } catch (NoTransitionException e) { - network.setState(Network.State.Allocated); - network.setRestartRequired(false); + DataCenterVO zone = _dcDao.findById(network.getDataCenterId()); + if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId()) && (zone.getNetworkType() == NetworkType.Advanced)) { + network.setState(Network.State.Setup); + } else { + try { + stateTransitTo(network, Event.OperationSucceeded); + } catch (NoTransitionException e) { + network.setState(Network.State.Allocated); + network.setRestartRequired(false); + } } _networksDao.update(network.getId(), network); _networksDao.clearCheckForGc(networkId); @@ -2791,6 +2787,17 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return (UserDataServiceProvider)_networkModel.getElementImplementingProvider(SSHKeyProvider); } + protected boolean isSharedNetworkWithServices(Network network) { + assert(network != null); + DataCenter zone = _configMgr.getZone(network.getDataCenterId()); + if (network.getGuestType() == Network.GuestType.Shared && + zone.getNetworkType() == NetworkType.Advanced && + isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) { + return true; + } + return false; + } + protected boolean isSharedNetworkOfferingWithServices(long networkOfferingId) { NetworkOfferingVO networkOffering = _networkOfferingDao.findById(networkOfferingId); if ( (networkOffering.getGuestType() == Network.GuestType.Shared) && ( diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java old mode 100644 new mode 100755 index 4c13c9179a0..c5930d9315c --- a/server/src/com/cloud/network/NetworkModelImpl.java +++ b/server/src/com/cloud/network/NetworkModelImpl.java @@ -88,7 +88,9 @@ import com.cloud.offerings.NetworkOfferingServiceMapVO; import com.cloud.offerings.NetworkOfferingVO; import com.cloud.offerings.dao.NetworkOfferingDao; import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; +import com.cloud.projects.dao.ProjectAccountDao; import com.cloud.user.Account; +import com.cloud.user.AccountVO; import com.cloud.user.DomainManager; import com.cloud.user.dao.AccountDao; import com.cloud.utils.component.AdapterBase; @@ -178,7 +180,8 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { UserIpv6AddressDao _ipv6Dao; @Inject NicSecondaryIpDao _nicSecondaryIpDao;; - + @Inject + private ProjectAccountDao _projectAccountDao; private final HashMap _systemNetworks = new HashMap(5); static Long _privateOfferingId = null; @@ -1010,7 +1013,10 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { Set supportedProviders = new HashSet(); if (service != null) { - supportedProviders.addAll(s_serviceToImplementedProvidersMap.get(service)); + List providers = s_serviceToImplementedProvidersMap.get(service); + if (providers != null && !providers.isEmpty()) { + supportedProviders.addAll(providers); + } } else { for (List pList : s_serviceToImplementedProvidersMap.values()) { supportedProviders.addAll(pList); @@ -1472,10 +1478,20 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { public void checkNetworkPermissions(Account owner, Network network) { // Perform account permission check if (network.getGuestType() != Network.GuestType.Shared) { - List networkMap = _networksDao.listBy(owner.getId(), network.getId()); - if (networkMap == null || networkMap.isEmpty()) { - throw new PermissionDeniedException("Unable to use network with id= " + network.getUuid() + ", permission denied"); + AccountVO networkOwner = _accountDao.findById(network.getAccountId()); + if(networkOwner == null) + throw new PermissionDeniedException("Unable to use network with id= " + network.getId() + ", 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= " + network.getId() + ", permission denied"); + } + }else{ + List networkMap = _networksDao.listBy(owner.getId(), network.getId()); + if (networkMap == null || networkMap.isEmpty()) { + throw new PermissionDeniedException("Unable to use network with id= " + network.getId() + ", permission denied"); + } } + } else { if (!isNetworkAvailableInDomain(network.getId(), owner.getDomainId())) { throw new PermissionDeniedException("Shared network id=" + network.getUuid() + " is not available in domain id=" + owner.getDomainId()); diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 4eb620c4243..70d1d0d432c 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -16,44 +16,13 @@ // under the License. package com.cloud.network; -import java.net.InetAddress; -import java.net.Inet6Address; -import java.net.UnknownHostException; -import java.security.InvalidParameterException; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import javax.ejb.Local; -import javax.inject.Inject; -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; -import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; -import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; -import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; -import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; -import org.bouncycastle.util.IPAddress; - import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.dc.DataCenter; -import com.cloud.dc.Pod; import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.DataCenterVO; +import com.cloud.dc.Pod; import com.cloud.dc.Vlan.VlanType; import com.cloud.dc.VlanVO; import com.cloud.dc.dao.AccountVlanMapDao; @@ -70,10 +39,8 @@ import com.cloud.event.UsageEventUtils; import com.cloud.event.dao.EventDao; import com.cloud.event.dao.UsageEventDao; import com.cloud.exception.*; -import com.cloud.host.Host; import com.cloud.host.dao.HostDao; import com.cloud.network.IpAddress.State; -import com.cloud.vm.Nic; import com.cloud.network.Network.Capability; import com.cloud.network.Network.GuestType; import com.cloud.network.Network.Provider; @@ -89,10 +56,10 @@ import com.cloud.network.element.VirtualRouterElement; import com.cloud.network.element.VpcVirtualRouterElement; import com.cloud.network.guru.NetworkGuru; import com.cloud.network.rules.FirewallRule.Purpose; -import com.cloud.network.rules.dao.PortForwardingRulesDao; import com.cloud.network.rules.FirewallRuleVO; import com.cloud.network.rules.PortForwardingRuleVO; import com.cloud.network.rules.RulesManager; +import com.cloud.network.rules.dao.PortForwardingRulesDao; import com.cloud.network.vpc.PrivateIpVO; import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.VpcManager; @@ -114,19 +81,33 @@ import com.cloud.utils.AnnotationHelper; import com.cloud.utils.Journal; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; -import com.cloud.utils.component.ComponentContext; -import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.*; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.vm.*; -import com.cloud.vm.dao.NicDao; -import com.cloud.vm.dao.NicSecondaryIpDao; -import com.cloud.vm.dao.NicSecondaryIpVO; -import com.cloud.vm.dao.UserVmDao; -import com.cloud.vm.dao.VMInstanceDao; +import com.cloud.vm.dao.*; +import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; +import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; +import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; +import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; +import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.security.InvalidParameterException; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; import java.util.*; /** @@ -433,7 +414,40 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { @Override @ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "allocating Ip", create = true) - public IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) + public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) + throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { + + if (networkId != null) { + Network network = _networksDao.findById(networkId); + if (network == null) { + throw new InvalidParameterValueException("Invalid network id is given"); + } + if (network.getGuestType() == Network.GuestType.Shared) { + DataCenter zone = _configMgr.getZone(zoneId); + if (zone == null) { + throw new InvalidParameterValueException("Invalid zone Id is given"); + } + + // if shared network in the advanced zone, then check the caller against the network for 'AccessType.UseNetwork' + if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId()) && zone.getNetworkType() == NetworkType.Advanced) { + Account caller = UserContext.current().getCaller(); + long callerUserId = UserContext.current().getCallerUserId(); + _accountMgr.checkAccess(caller, AccessType.UseNetwork, false, network); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId()); + } + return _networkMgr.allocateIp(ipOwner, false, caller, callerUserId, zone); + } else { + throw new InvalidParameterValueException("Associate IP address can only be called on the shared networks in the advanced zone" + + " with Firewall/Source Nat/Static Nat/Port Forwarding/Load balancing services enabled"); + } + } + } + + return allocateIP(ipOwner, false, zoneId); + } + + public IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { Account caller = UserContext.current().getCaller(); // check permissions @@ -697,15 +711,6 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { throw new IllegalArgumentException("only ip addresses that belong to a virtual network may be disassociated."); } - // Check for account wide pool. It will have an entry for account_vlan_map. - if (_accountVlanMapDao.findAccountVlanMap(ipVO.getAllocatedToAccountId(), ipVO.getVlanId()) != null) { - //see IPaddressVO.java - InvalidParameterValueException ex = new InvalidParameterValueException("Sepcified IP address uuid belongs to" + - " Account wide IP pool and cannot be disassociated"); - ex.addProxyObject("user_ip_address", ipAddressId, "ipAddressId"); - throw ex; - } - // don't allow releasing system ip address if (ipVO.getSystem()) { InvalidParameterValueException ex = new InvalidParameterValueException("Can't release system IP address with specified id"); diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index 29ed5f36d5e..8636d8503a3 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -1215,11 +1215,13 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules Network guestNetwork = _networkModel.getNetwork(ipAddress.getAssociatedWithNetworkId()); NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId()); if (offering.getElasticIp()) { - getSystemIpAndEnableStaticNatForVm(_vmDao.findById(vmId), true); - return true; - } else { - return disableStaticNat(ipId, caller, ctx.getCallerUserId(), false); + if (offering.getAssociatePublicIP()) { + getSystemIpAndEnableStaticNatForVm(_vmDao.findById(vmId), true); + return true; + } } + + return disableStaticNat(ipId, caller, ctx.getCallerUserId(), false); } @Override @@ -1410,6 +1412,11 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules Network guestNetwork = _networkModel.getNetwork(nic.getNetworkId()); NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId()); if (offering.getElasticIp()) { + boolean isSystemVM = (vm.getType() == Type.ConsoleProxy || vm.getType() == Type.SecondaryStorageVm); + // for user VM's associate public IP only if offering is marked to associate a public IP by default on start of VM + if (!isSystemVM && !offering.getAssociatePublicIP()) { + continue; + } // check if there is already static nat enabled if (_ipAddressDao.findByAssociatedVmId(vm.getId()) != null && !getNewIp) { s_logger.debug("Vm " + vm + " already has ip associated with it in guest network " + guestNetwork); @@ -1424,7 +1431,6 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules s_logger.debug("Allocated system ip " + ip + ", now enabling static nat on it for vm " + vm); - boolean isSystemVM = (vm.getType() == Type.ConsoleProxy || vm.getType() == Type.SecondaryStorageVm); try { success = enableStaticNat(ip.getId(), vm.getId(), guestNetwork.getId(), isSystemVM, null); } catch (NetworkRuleConflictException ex) { diff --git a/server/src/com/cloud/offerings/NetworkOfferingVO.java b/server/src/com/cloud/offerings/NetworkOfferingVO.java index 5de76a526b5..c015989c5c5 100755 --- a/server/src/com/cloud/offerings/NetworkOfferingVO.java +++ b/server/src/com/cloud/offerings/NetworkOfferingVO.java @@ -110,6 +110,9 @@ public class NetworkOfferingVO implements NetworkOffering { @Column(name = "elastic_ip_service") boolean elasticIp; + @Column(name = "eip_associate_public_ip") + boolean eipAssociatePublicIp; + @Column(name = "elastic_lb_service") boolean elasticLb; @@ -278,6 +281,7 @@ public class NetworkOfferingVO implements NetworkOffering { this.sharedSourceNat = false; this.redundantRouter = false; this.elasticIp = false; + this.eipAssociatePublicIp = true; this.elasticLb = false; this.inline = false; this.specifyIpRanges = specifyIpRanges; @@ -286,7 +290,7 @@ public class NetworkOfferingVO implements NetworkOffering { 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 specifyIpRanges, boolean inline, boolean isPersistent, boolean associatePublicIP) { this(name, displayText, trafficType, systemOnly, specifyVlan, rateMbps, multicastRateMbps, isDefault, availability, tags, guestType, conserveMode, specifyIpRanges, isPersistent); this.dedicatedLB = dedicatedLb; this.sharedSourceNat = sharedSourceNat; @@ -294,6 +298,7 @@ public class NetworkOfferingVO implements NetworkOffering { this.elasticIp = elasticIp; this.elasticLb = elasticLb; this.inline = inline; + this.eipAssociatePublicIp = associatePublicIP; } public NetworkOfferingVO() { @@ -355,6 +360,11 @@ public class NetworkOfferingVO implements NetworkOffering { return elasticIp; } + @Override + public boolean getAssociatePublicIP() { + return eipAssociatePublicIp; + } + @Override public boolean getElasticLb() { return elasticLb; diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index 82bca5194bf..c9c3f9c3722 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -1181,29 +1181,17 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, } } - ClusterDetailsVO memory_detail = _clusterDetailsDao.findDetail(cluster.getId(),"memoryOvercommitRatio"); - if( memory_detail == null){ - if (memoryovercommitratio.compareTo(1f) > 0){ - memory_detail = new ClusterDetailsVO(cluster.getId(),"memoryOvercommitRatio",Float.toString(memoryovercommitratio)); - _clusterDetailsDao.persist(memory_detail); - } - } - else { + if (memoryovercommitratio != null) { + ClusterDetailsVO memory_detail = _clusterDetailsDao.findDetail(cluster.getId(),"memoryOvercommitRatio"); memory_detail.setValue(Float.toString(memoryovercommitratio)); _clusterDetailsDao.update(memory_detail.getId(),memory_detail); } - ClusterDetailsVO cpu_detail = _clusterDetailsDao.findDetail(cluster.getId(),"cpuOvercommitRatio"); - if( cpu_detail == null){ - if (cpuovercommitratio.compareTo(1f) > 0){ - cpu_detail = new ClusterDetailsVO(cluster.getId(),"cpuOvercommitRatio",Float.toString(cpuovercommitratio)); - _clusterDetailsDao.persist(cpu_detail); - } - } - else { + if (cpuovercommitratio != null) { + ClusterDetailsVO cpu_detail = _clusterDetailsDao.findDetail(cluster.getId(),"cpuOvercommitRatio"); cpu_detail.setValue(Float.toString(cpuovercommitratio)); _clusterDetailsDao.update(cpu_detail.getId(),cpu_detail); - } + } if (doUpdate) { diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 53df3b970a8..852c00b4c5d 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -148,8 +148,6 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio @DB public void persistDefaultValues() throws InternalErrorException { - fixupScriptFileAttribute(); - // Create system user and admin user saveUser(); @@ -701,24 +699,6 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio } - private void fixupScriptFileAttribute() { - // TODO : this is a hacking fix to workaround that executable bit is not preserved in WAR package - String scriptPath = Script.findScript("", "scripts/vm/systemvm/injectkeys.sh"); - if(scriptPath != null) { - File file = new File(scriptPath); - if(!file.canExecute()) { - s_logger.info("Some of the shell script files may not have executable bit set. Fixup..."); - - String cmd = "sudo chmod ugo+x " + scriptPath; - s_logger.info("Executing " + cmd); - String result = Script.runSimpleBashScript(cmd); - if (result != null) { - s_logger.warn("Failed to fixup shell script executable bits " + result); - } - } - } - } - private void updateKeyPairsOnDisk(String homeDir) { File keyDir = new File(homeDir + "/.ssh"); Boolean devel = Boolean.valueOf(_configDao.getValue("developer")); @@ -749,7 +729,8 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio if (systemVmIsoPath == null) { throw new CloudRuntimeException("Unable to find systemvm iso vms/systemvm.iso"); } - final Script command = new Script(scriptPath, s_logger); + final Script command = new Script("/bin/bash", s_logger); + command.add(scriptPath); command.add(publicKeyPath); command.add(privKeyPath); command.add(systemVmIsoPath); @@ -1027,7 +1008,7 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio "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); + null, Network.GuestType.Shared, true, false, false, false, true, true, true, false, false, true); defaultNetscalerNetworkOffering.setState(NetworkOffering.State.Enabled); defaultNetscalerNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNetscalerNetworkOffering); diff --git a/server/src/com/cloud/server/ManagementServer.java b/server/src/com/cloud/server/ManagementServer.java index 6773725f361..240464e4938 100755 --- a/server/src/com/cloud/server/ManagementServer.java +++ b/server/src/com/cloud/server/ManagementServer.java @@ -95,6 +95,9 @@ public interface ManagementServer extends ManagementService, PluggableService { Pair, Integer> searchForStoragePools(Criteria c); String getHashKey(); + String getEncryptionKey(); + String getEncryptionIV(); + void resetEncryptionKeyIV(); public void enableAdminUser(String password); } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index af77ba5645f..5ed0c923cc0 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -22,6 +22,8 @@ import java.net.InetAddress; import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.ArrayList; import java.util.Calendar; import java.util.Comparator; @@ -37,14 +39,9 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import javax.annotation.PostConstruct; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.inject.Inject; -import javax.management.InstanceAlreadyExistsException; -import javax.management.MBeanRegistrationException; -import javax.management.MalformedObjectNameException; -import javax.management.NotCompliantMBeanException; import javax.naming.ConfigurationException; import com.cloud.storage.dao.*; @@ -54,60 +51,44 @@ import org.apache.cloudstack.api.ApiConstants; import com.cloud.event.ActionEventUtils; import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; import org.apache.cloudstack.api.command.admin.account.*; -import org.apache.cloudstack.api.command.admin.autoscale.*; -import org.apache.cloudstack.api.command.admin.cluster.*; -import org.apache.cloudstack.api.command.admin.config.*; import org.apache.cloudstack.api.command.admin.domain.*; import org.apache.cloudstack.api.command.admin.host.*; -import org.apache.cloudstack.api.command.admin.ldap.*; import org.apache.cloudstack.api.command.admin.network.*; import org.apache.cloudstack.api.command.admin.offering.*; -import org.apache.cloudstack.api.command.admin.pod.*; -import org.apache.cloudstack.api.command.admin.region.*; import org.apache.cloudstack.api.command.admin.resource.*; import org.apache.cloudstack.api.command.admin.router.*; import org.apache.cloudstack.api.command.admin.storage.*; -import org.apache.cloudstack.api.command.admin.swift.*; import org.apache.cloudstack.api.command.admin.systemvm.*; -import org.apache.cloudstack.api.command.admin.template.*; import org.apache.cloudstack.api.command.admin.usage.*; import org.apache.cloudstack.api.command.admin.user.*; import org.apache.cloudstack.api.command.admin.vlan.*; -import org.apache.cloudstack.api.command.admin.vm.*; import org.apache.cloudstack.api.command.admin.vpc.*; -import org.apache.cloudstack.api.command.admin.zone.*; -import org.apache.cloudstack.api.command.user.account.*; -import org.apache.cloudstack.api.command.user.address.*; import org.apache.cloudstack.api.command.user.autoscale.*; -import org.apache.cloudstack.api.command.user.config.*; -import org.apache.cloudstack.api.command.user.event.*; import org.apache.cloudstack.api.command.user.firewall.*; -import org.apache.cloudstack.api.command.user.guest.*; import org.apache.cloudstack.api.command.user.iso.*; -import org.apache.cloudstack.api.command.user.job.*; import org.apache.cloudstack.api.command.user.loadbalancer.*; import org.apache.cloudstack.api.command.user.nat.*; import org.apache.cloudstack.api.command.user.network.*; -import org.apache.cloudstack.api.command.user.offering.*; import org.apache.cloudstack.api.command.user.project.*; -import org.apache.cloudstack.api.command.user.region.*; import org.apache.cloudstack.api.command.user.resource.*; import org.apache.cloudstack.api.command.user.securitygroup.*; import org.apache.cloudstack.api.command.user.snapshot.*; -import org.apache.cloudstack.api.command.user.ssh.*; -import org.apache.cloudstack.api.command.user.tag.*; import org.apache.cloudstack.api.command.user.template.*; import org.apache.cloudstack.api.command.user.vm.*; -import org.apache.cloudstack.api.command.user.vmgroup.*; import org.apache.cloudstack.api.command.user.volume.*; import org.apache.cloudstack.api.command.user.vpc.*; import org.apache.cloudstack.api.command.user.vpn.*; -import org.apache.cloudstack.api.command.user.zone.*; import org.apache.cloudstack.api.response.ExtractResponse; import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; +import org.apache.cloudstack.affinity.AffinityGroupProcessor; +import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; +import org.apache.cloudstack.api.command.user.affinitygroup.CreateAffinityGroupCmd; +import org.apache.cloudstack.api.command.user.affinitygroup.DeleteAffinityGroupCmd; +import org.apache.cloudstack.api.command.user.affinitygroup.ListAffinityGroupTypesCmd; +import org.apache.cloudstack.api.command.user.affinitygroup.ListAffinityGroupsCmd; +import org.apache.cloudstack.api.command.user.affinitygroup.UpdateVMAffinityGroupCmd; import com.cloud.agent.AgentManager; import com.cloud.agent.api.GetVncPortAnswer; import com.cloud.agent.api.GetVncPortCommand; @@ -136,11 +117,11 @@ import com.cloud.dc.*; import com.cloud.dc.Vlan.VlanType; import com.cloud.dc.dao.*; import com.cloud.deploy.DataCenterDeployment; +import com.cloud.deploy.DeploymentPlanner; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; -import com.cloud.event.ActionEventUtils; import com.cloud.event.EventTypes; import com.cloud.event.EventVO; import com.cloud.event.dao.EventDao; @@ -175,7 +156,6 @@ import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.*; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Upload.Mode; -import com.cloud.storage.dao.*; import com.cloud.storage.s3.S3Manager; import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.storage.snapshot.SnapshotManager; @@ -193,11 +173,7 @@ import com.cloud.utils.EnumUtils; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; import com.cloud.utils.PasswordGenerator; -import com.cloud.utils.ReflectUtil; import com.cloud.utils.Ternary; -import com.cloud.utils.component.Adapter; -import com.cloud.utils.component.AdapterBase; -import com.cloud.utils.component.ComponentContext; import com.cloud.utils.component.ComponentLifecycle; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.concurrency.NamedThreadFactory; @@ -214,10 +190,6 @@ import com.cloud.vm.dao.*; import edu.emory.mathcs.backport.java.util.Arrays; import edu.emory.mathcs.backport.java.util.Collections; import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.acl.SecurityChecker.AccessType; -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd; -import org.apache.cloudstack.api.command.admin.account.*; import org.apache.cloudstack.api.command.admin.autoscale.CreateCounterCmd; import org.apache.cloudstack.api.command.admin.autoscale.DeleteCounterCmd; import org.apache.cloudstack.api.command.admin.cluster.AddClusterCmd; @@ -228,12 +200,8 @@ import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd; import org.apache.cloudstack.api.command.admin.config.ListHypervisorCapabilitiesCmd; import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; import org.apache.cloudstack.api.command.admin.config.UpdateHypervisorCapabilitiesCmd; -import org.apache.cloudstack.api.command.admin.domain.*; -import org.apache.cloudstack.api.command.admin.host.*; import org.apache.cloudstack.api.command.admin.ldap.LDAPConfigCmd; import org.apache.cloudstack.api.command.admin.ldap.LDAPRemoveCmd; -import org.apache.cloudstack.api.command.admin.network.*; -import org.apache.cloudstack.api.command.admin.offering.*; import org.apache.cloudstack.api.command.admin.pod.CreatePodCmd; import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd; import org.apache.cloudstack.api.command.admin.pod.ListPodsByCmd; @@ -241,22 +209,15 @@ import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd; import org.apache.cloudstack.api.command.admin.region.AddRegionCmd; import org.apache.cloudstack.api.command.admin.region.RemoveRegionCmd; import org.apache.cloudstack.api.command.admin.region.UpdateRegionCmd; -import org.apache.cloudstack.api.command.admin.resource.*; -import org.apache.cloudstack.api.command.admin.router.*; -import org.apache.cloudstack.api.command.admin.storage.*; import org.apache.cloudstack.api.command.admin.swift.AddSwiftCmd; import org.apache.cloudstack.api.command.admin.swift.ListSwiftsCmd; -import org.apache.cloudstack.api.command.admin.systemvm.*; import org.apache.cloudstack.api.command.admin.template.PrepareTemplateCmd; -import org.apache.cloudstack.api.command.admin.usage.*; -import org.apache.cloudstack.api.command.admin.user.*; import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd; 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.vm.AssignVMCmd; import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd; import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; -import org.apache.cloudstack.api.command.admin.vpc.*; 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.MarkDefaultZoneForAccountCmd; @@ -268,29 +229,19 @@ import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd; import org.apache.cloudstack.api.command.user.address.AssociateIPAddrCmd; import org.apache.cloudstack.api.command.user.address.DisassociateIPAddrCmd; import org.apache.cloudstack.api.command.user.address.ListPublicIpAddressesCmd; -import org.apache.cloudstack.api.command.user.autoscale.*; import org.apache.cloudstack.api.command.user.config.ListCapabilitiesCmd; import org.apache.cloudstack.api.command.user.event.ArchiveEventsCmd; import org.apache.cloudstack.api.command.user.event.DeleteEventsCmd; import org.apache.cloudstack.api.command.user.event.ListEventTypesCmd; import org.apache.cloudstack.api.command.user.event.ListEventsCmd; -import org.apache.cloudstack.api.command.user.firewall.*; import org.apache.cloudstack.api.command.user.guest.ListGuestOsCategoriesCmd; import org.apache.cloudstack.api.command.user.guest.ListGuestOsCmd; -import org.apache.cloudstack.api.command.user.iso.*; import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd; import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; -import org.apache.cloudstack.api.command.user.loadbalancer.*; -import org.apache.cloudstack.api.command.user.nat.*; -import org.apache.cloudstack.api.command.user.network.*; import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd; import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd; -import org.apache.cloudstack.api.command.user.project.*; import org.apache.cloudstack.api.command.user.region.ListRegionsCmd; import org.apache.cloudstack.api.command.user.region.ha.gslb.*; -import org.apache.cloudstack.api.command.user.resource.*; -import org.apache.cloudstack.api.command.user.securitygroup.*; -import org.apache.cloudstack.api.command.user.snapshot.*; import org.apache.cloudstack.api.command.user.ssh.CreateSSHKeyPairCmd; import org.apache.cloudstack.api.command.user.ssh.DeleteSSHKeyPairCmd; import org.apache.cloudstack.api.command.user.ssh.ListSSHKeyPairsCmd; @@ -298,8 +249,6 @@ import org.apache.cloudstack.api.command.user.ssh.RegisterSSHKeyPairCmd; import org.apache.cloudstack.api.command.user.tag.CreateTagsCmd; import org.apache.cloudstack.api.command.user.tag.DeleteTagsCmd; import org.apache.cloudstack.api.command.user.tag.ListTagsCmd; -import org.apache.cloudstack.api.command.user.template.*; -import org.apache.cloudstack.api.command.user.vm.*; import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd; import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd; import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd; @@ -308,27 +257,10 @@ import org.apache.cloudstack.api.command.user.vmsnapshot.CreateVMSnapshotCmd; import org.apache.cloudstack.api.command.user.vmsnapshot.DeleteVMSnapshotCmd; import org.apache.cloudstack.api.command.user.vmsnapshot.ListVMSnapshotCmd; import org.apache.cloudstack.api.command.user.vmsnapshot.RevertToSnapshotCmd; -import org.apache.cloudstack.api.command.user.volume.*; -import org.apache.cloudstack.api.command.user.vpc.*; -import org.apache.cloudstack.api.command.user.vpn.*; import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd; -import org.apache.cloudstack.api.response.ExtractResponse; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; -import org.apache.commons.codec.binary.Base64; -import org.apache.log4j.Logger; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import javax.inject.Inject; -import javax.naming.ConfigurationException; -import java.lang.reflect.Field; -import java.net.*; -import java.util.*; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; public class ManagementServerImpl extends ManagerBase implements ManagementServer { public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName()); @@ -460,17 +392,38 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe private List _userAuthenticators; private List _userPasswordEncoders; + protected List _planners; + public List getPlanners() { + return _planners; + } + public void setPlanners(List _planners) { + this._planners = _planners; + } + @Inject ClusterManager _clusterMgr; private String _hashKey = null; + private String _encryptionKey = null; + private String _encryptionIV = null; + + @Inject + protected AffinityGroupVMMapDao _affinityGroupVMMapDao; + + protected List _affinityProcessors; + public List getAffinityGroupProcessors() { + return _affinityProcessors; + } + public void setAffinityGroupProcessors(List affinityProcessors) { + this._affinityProcessors = affinityProcessors; + } public ManagementServerImpl() { setRunLevel(ComponentLifecycle.RUN_LEVEL_APPLICATION_MAINLOOP); } - + public List getUserAuthenticators() { return _userAuthenticators; } - + public void setUserAuthenticators(List authenticators) { _userAuthenticators = authenticators; } @@ -821,6 +774,15 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe ExcludeList excludes = new ExcludeList(); excludes.addHost(srcHostId); + // call affinitygroup chain + long vmGroupCount = _affinityGroupVMMapDao.countAffinityGroupsForVm(vm.getId()); + + if (vmGroupCount > 0) { + for (AffinityGroupProcessor processor : _affinityProcessors) { + processor.process(vmProfile, plan, excludes); + } + } + for (HostAllocator allocator : _hostAllocators) { suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, HostAllocator.RETURN_UPTO_ALL, false); if (suitableHosts != null && !suitableHosts.isEmpty()) { @@ -2090,6 +2052,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe cmdList.add(CreateVlanIpRangeCmd.class); cmdList.add(DeleteVlanIpRangeCmd.class); cmdList.add(ListVlanIpRangesCmd.class); + cmdList.add(DedicatePublicIpRangeCmd.class); + cmdList.add(ReleasePublicIpRangeCmd.class); cmdList.add(AssignVMCmd.class); cmdList.add(MigrateVMCmd.class); cmdList.add(RecoverVMCmd.class); @@ -2301,6 +2265,12 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe cmdList.add(AssignToGlobalLoadBalancerRuleCmd.class); cmdList.add(RemoveFromGlobalLoadBalancerRuleCmd.class); cmdList.add(ListStorageProvidersCmd.class); + cmdList.add(CreateAffinityGroupCmd.class); + cmdList.add(DeleteAffinityGroupCmd.class); + cmdList.add(ListAffinityGroupsCmd.class); + cmdList.add(UpdateVMAffinityGroupCmd.class); + cmdList.add(ListAffinityGroupTypesCmd.class); + return cmdList; } @@ -3034,15 +3004,66 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Override public String getHashKey() { - // although we may have race conditioning here, database transaction - // serialization should + // although we may have race conditioning here, database transaction serialization should // give us the same key if (_hashKey == null) { - _hashKey = _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), Config.HashKey.getCategory(), UUID.randomUUID().toString()); + _hashKey = _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), Config.HashKey.getCategory(), + getBase64EncodedRandomKey(128)); } return _hashKey; } + @Override + public String getEncryptionKey() { + if (_encryptionKey == null) { + _encryptionKey = _configDao.getValueAndInitIfNotExist(Config.EncryptionKey.key(), + Config.EncryptionKey.getCategory(), + getBase64EncodedRandomKey(128)); + } + return _encryptionKey; + } + + @Override + public String getEncryptionIV() { + if (_encryptionIV == null) { + _encryptionIV = _configDao.getValueAndInitIfNotExist(Config.EncryptionIV.key(), + Config.EncryptionIV.getCategory(), + getBase64EncodedRandomKey(128)); + } + return _encryptionIV; + } + + @Override + @DB + public void resetEncryptionKeyIV() { + + SearchBuilder sb = _configDao.createSearchBuilder(); + sb.and("name1", sb.entity().getName(), SearchCriteria.Op.EQ); + sb.or("name2", sb.entity().getName(), SearchCriteria.Op.EQ); + sb.done(); + + SearchCriteria sc = sb.create(); + sc.setParameters("name1", Config.EncryptionKey.key()); + sc.setParameters("name2", Config.EncryptionIV.key()); + + _configDao.expunge(sc); + _encryptionKey = null; + _encryptionIV = null; + } + + private static String getBase64EncodedRandomKey(int nBits) { + SecureRandom random; + try { + random = SecureRandom.getInstance("SHA1PRNG"); + byte[] keyBytes = new byte[nBits/8]; + random.nextBytes(keyBytes); + return Base64.encodeBase64URLSafeString(keyBytes); + } catch (NoSuchAlgorithmException e) { + s_logger.error("Unhandled exception: ", e); + } + return null; + } + @Override public SSHKeyPair createSSHKeyPair(CreateSSHKeyPairCmd cmd) { Account caller = UserContext.current().getCaller(); @@ -3366,4 +3387,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } + @Override + public List listDeploymentPlanners() { + List plannersAvailable = new ArrayList(); + for (DeploymentPlanner planner : _planners) { + plannersAvailable.add(planner.getName()); + } + + return plannersAvailable; + } + } diff --git a/server/src/com/cloud/service/ServiceOfferingVO.java b/server/src/com/cloud/service/ServiceOfferingVO.java index 7be939c3a15..a3da904688c 100755 --- a/server/src/com/cloud/service/ServiceOfferingVO.java +++ b/server/src/com/cloud/service/ServiceOfferingVO.java @@ -34,25 +34,25 @@ import com.cloud.vm.VirtualMachine; public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering { @Column(name="cpu") private int cpu; - + @Column(name="speed") private int speed; - + @Column(name="ram_size") private int ramSize; - + @Column(name="nw_rate") private Integer rateMbps; - + @Column(name="mc_rate") private Integer multicastRateMbps; - + @Column(name="ha_enabled") private boolean offerHA; @Column(name="limit_cpu_use") - private boolean limitCpuUse; - + private boolean limitCpuUse; + @Column(name="is_volatile") private boolean volatileVm; @@ -64,10 +64,13 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering @Column(name="vm_type") private String vm_type; - + @Column(name="sort_key") int sortKey; - + + @Column(name = "deployment_planner") + private String deploymentPlanner = "FirstFitPlanner"; + protected ServiceOfferingVO() { super(); } @@ -80,10 +83,11 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering this.rateMbps = rateMbps; this.multicastRateMbps = multicastRateMbps; this.offerHA = offerHA; - this.limitCpuUse = false; + this.limitCpuUse = false; this.volatileVm = false; this.default_use = defaultUse; this.vm_type = vm_type == null ? null : vm_type.toString().toLowerCase(); + this.deploymentPlanner = "FirstFitPlanner"; } public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, boolean limitCpuUse, boolean volatileVm, String displayText, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, Long domainId) { @@ -94,39 +98,54 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering this.rateMbps = rateMbps; this.multicastRateMbps = multicastRateMbps; this.offerHA = offerHA; - this.limitCpuUse = limitCpuUse; + this.limitCpuUse = limitCpuUse; this.volatileVm = volatileVm; this.vm_type = vm_type == null ? null : vm_type.toString().toLowerCase(); + this.deploymentPlanner = "FirstFitPlanner"; } public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, boolean limitResourceUse, boolean volatileVm, String displayText, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, Long domainId, String hostTag) { this(name, cpu, ramSize, speed, rateMbps, multicastRateMbps, offerHA, limitResourceUse, volatileVm, displayText, useLocalStorage, recreatable, tags, systemUse, vm_type, domainId); this.hostTag = hostTag; - } + this.deploymentPlanner = "FirstFitPlanner"; + } + + public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, Integer rateMbps, Integer multicastRateMbps, + boolean offerHA, boolean limitResourceUse, boolean volatileVm, String displayText, boolean useLocalStorage, + boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, Long domainId, + String hostTag, String deploymentPlanner) { + this(name, cpu, ramSize, speed, rateMbps, multicastRateMbps, offerHA, limitResourceUse, volatileVm, + displayText, useLocalStorage, recreatable, tags, systemUse, vm_type, domainId, hostTag); + if (deploymentPlanner != null) { + this.deploymentPlanner = deploymentPlanner; + } else { + this.deploymentPlanner = "FirstFitPlanner"; + } + } @Override public boolean getOfferHA() { return offerHA; } - + public void setOfferHA(boolean offerHA) { this.offerHA = offerHA; } - @Override + @Override public boolean getLimitCpuUse() { return limitCpuUse; } - + public void setLimitResourceUse(boolean limitCpuUse) { this.limitCpuUse = limitCpuUse; } - - @Override + + @Override public boolean getDefaultUse() { return default_use; } - + @Override @Transient public String[] getTagsArray() { @@ -134,15 +153,15 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering if (tags == null || tags.length() == 0) { return new String[0]; } - + return tags.split(","); } - + @Override public int getCpu() { return cpu; } - + public void setCpu(int cpu) { this.cpu = cpu; } @@ -154,17 +173,17 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering public void setRamSize(int ramSize) { this.ramSize = ramSize; } - + @Override public int getSpeed() { return speed; } - + @Override public int getRamSize() { return ramSize; } - + public void setRateMbps(Integer rateMbps) { this.rateMbps = rateMbps; } @@ -177,7 +196,7 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering public void setMulticastRateMbps(Integer multicastRateMbps) { this.multicastRateMbps = multicastRateMbps; } - + @Override public Integer getMulticastRateMbps() { return multicastRateMbps; @@ -185,12 +204,12 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering public void setHostTag(String hostTag) { this.hostTag = hostTag; - } - + } + public String getHostTag() { return hostTag; } - + public String getSystemVmType(){ return vm_type; } @@ -202,10 +221,14 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering public int getSortKey() { return sortKey; } - + @Override public boolean getVolatileVm() { return volatileVm; } + public String getDeploymentPlanner() { + return deploymentPlanner; + } + } diff --git a/server/src/com/cloud/servlet/ConsoleProxyPasswordBasedEncryptor.java b/server/src/com/cloud/servlet/ConsoleProxyPasswordBasedEncryptor.java index 2638c8b31b9..7463ec097f3 100644 --- a/server/src/com/cloud/servlet/ConsoleProxyPasswordBasedEncryptor.java +++ b/server/src/com/cloud/servlet/ConsoleProxyPasswordBasedEncryptor.java @@ -16,13 +16,16 @@ // under the License. package com.cloud.servlet; +import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; @@ -35,26 +38,26 @@ import com.google.gson.GsonBuilder; public class ConsoleProxyPasswordBasedEncryptor { private static final Logger s_logger = Logger.getLogger(ConsoleProxyPasswordBasedEncryptor.class); - private String password; private Gson gson; + // key/IV will be set in 128 bit strength + private KeyIVPair keyIvPair; + public ConsoleProxyPasswordBasedEncryptor(String password) { - this.password = password; gson = new GsonBuilder().create(); + keyIvPair = gson.fromJson(password, KeyIVPair.class); } public String encryptText(String text) { if(text == null || text.isEmpty()) return text; - assert(password != null); - assert(!password.isEmpty()); - try { - Cipher cipher = Cipher.getInstance("DES"); - int maxKeySize = 8; - SecretKeySpec keySpec = new SecretKeySpec(normalizeKey(password.getBytes(), maxKeySize), "DES"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKeySpec keySpec = new SecretKeySpec(keyIvPair.getKeyBytes(), "AES"); + + cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(keyIvPair.getIvBytes())); + byte[] encryptedBytes = cipher.doFinal(text.getBytes()); return Base64.encodeBase64URLSafeString(encryptedBytes); } catch (NoSuchAlgorithmException e) { @@ -72,6 +75,9 @@ public class ConsoleProxyPasswordBasedEncryptor { } catch (InvalidKeyException e) { s_logger.error("Unexpected exception ", e); return null; + } catch (InvalidAlgorithmParameterException e) { + s_logger.error("Unexpected exception ", e); + return null; } } @@ -79,14 +85,10 @@ public class ConsoleProxyPasswordBasedEncryptor { if(encryptedText == null || encryptedText.isEmpty()) return encryptedText; - assert(password != null); - assert(!password.isEmpty()); - try { - Cipher cipher = Cipher.getInstance("DES"); - int maxKeySize = 8; - SecretKeySpec keySpec = new SecretKeySpec(normalizeKey(password.getBytes(), maxKeySize), "DES"); - cipher.init(Cipher.DECRYPT_MODE, keySpec); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKeySpec keySpec = new SecretKeySpec(keyIvPair.getKeyBytes(), "AES"); + cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(keyIvPair.getIvBytes())); byte[] encryptedBytes = Base64.decodeBase64(encryptedText); return new String(cipher.doFinal(encryptedBytes)); @@ -105,6 +107,9 @@ public class ConsoleProxyPasswordBasedEncryptor { } catch (InvalidKeyException e) { s_logger.error("Unexpected exception ", e); return null; + } catch (InvalidAlgorithmParameterException e) { + s_logger.error("Unexpected exception ", e); + return null; } } @@ -125,13 +130,63 @@ public class ConsoleProxyPasswordBasedEncryptor { return (T)gson.fromJson(json, clz); } - private static byte[] normalizeKey(byte[] keyBytes, int keySize) { - assert(keySize > 0); - byte[] key = new byte[keySize]; + public static class KeyIVPair { + String base64EncodedKeyBytes; + String base64EncodedIvBytes; - for(int i = 0; i < keyBytes.length; i++) - key[i%keySize] ^= keyBytes[i]; + public KeyIVPair() { + } - return key; + public KeyIVPair(String base64EncodedKeyBytes, String base64EncodedIvBytes) { + this.base64EncodedKeyBytes = base64EncodedKeyBytes; + this.base64EncodedIvBytes = base64EncodedIvBytes; + } + + public byte[] getKeyBytes() { + return Base64.decodeBase64(base64EncodedKeyBytes); + } + + public void setKeyBytes(byte[] keyBytes) { + base64EncodedKeyBytes = Base64.encodeBase64URLSafeString(keyBytes); + } + + public byte[] getIvBytes() { + return Base64.decodeBase64(base64EncodedIvBytes); + } + + public void setIvBytes(byte[] ivBytes) { + base64EncodedIvBytes = Base64.encodeBase64URLSafeString(ivBytes); + } } + + public static void main(String[] args) { + SecureRandom random; + try { + random = SecureRandom.getInstance("SHA1PRNG"); + byte[] keyBytes = new byte[16]; + random.nextBytes(keyBytes); + + byte[] ivBytes = new byte[16]; + random.nextBytes(ivBytes); + + KeyIVPair keyIvPair = new KeyIVPair("8x/xUBgX0Up+3UEo39dSeG277JhVj31+ElHkN5+EC0Q=", "Y2SUiIN6JXTdKNK/ZMDyVtLB7gAM9MCCiyrP1xd3bSQ="); + //keyIvPair.setKeyBytes(keyBytes); + //keyIvPair.setIvBytes(ivBytes); + + Gson gson = new GsonBuilder().create(); + ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(gson.toJson(keyIvPair)); + + String encrypted = encryptor.encryptText("Hello, world"); + + System.out.println("Encrypted result: " + encrypted); + + String decrypted = encryptor.decryptText(encrypted); + + System.out.println("Decrypted result: " + decrypted); + + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + } } + diff --git a/server/src/com/cloud/servlet/ConsoleProxyServlet.java b/server/src/com/cloud/servlet/ConsoleProxyServlet.java index c4b93349080..ebb91746268 100644 --- a/server/src/com/cloud/servlet/ConsoleProxyServlet.java +++ b/server/src/com/cloud/servlet/ConsoleProxyServlet.java @@ -55,6 +55,8 @@ import com.cloud.utils.db.Transaction; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineManager; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; /** * Thumbnail access : /console?cmd=thumbnail&vm=xxx&w=xxx&h=xxx @@ -75,6 +77,8 @@ public class ConsoleProxyServlet extends HttpServlet { static ManagementServer s_ms; + private Gson _gson = new GsonBuilder().create(); + public ConsoleProxyServlet() { } @@ -327,6 +331,14 @@ public class ConsoleProxyServlet extends HttpServlet { return new Ternary(host, tunnelUrl, tunnelSession); } + private String getEncryptorPassword() { + String key = _ms.getEncryptionKey(); + String iv = _ms.getEncryptionIV(); + + ConsoleProxyPasswordBasedEncryptor.KeyIVPair keyIvPair = new ConsoleProxyPasswordBasedEncryptor.KeyIVPair(key, iv); + return _gson.toJson(keyIvPair); + } + private String composeThumbnailUrl(String rootUrl, VMInstanceVO vm, HostVO hostVo, int w, int h) { StringBuffer sb = new StringBuffer(rootUrl); @@ -340,7 +352,7 @@ public class ConsoleProxyServlet extends HttpServlet { tag = _identityService.getIdentityUuid("vm_instance", tag); String ticket = genAccessTicket(host, String.valueOf(portInfo.second()), sid, tag); - ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(_ms.getHashKey()); + ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(getEncryptorPassword()); ConsoleProxyClientParam param = new ConsoleProxyClientParam(); param.setClientHostAddress(parsedHostInfo.first()); param.setClientHostPort(portInfo.second()); @@ -376,7 +388,7 @@ public class ConsoleProxyServlet extends HttpServlet { String tag = String.valueOf(vm.getId()); tag = _identityService.getIdentityUuid("vm_instance", tag); String ticket = genAccessTicket(host, String.valueOf(portInfo.second()), sid, tag); - ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(_ms.getHashKey()); + ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(getEncryptorPassword()); ConsoleProxyClientParam param = new ConsoleProxyClientParam(); param.setClientHostAddress(parsedHostInfo.first()); param.setClientHostPort(portInfo.second()); diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index 3a453d50a72..490948ba5ae 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -181,9 +181,8 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, private ResourceTagDao _resourceTagDao; @Inject private ConfigurationDao _configDao; - - @Inject - private VMSnapshotDao _vmSnapshotDao; + @Inject + private PrimaryDataStoreDao _primaryDataStoreDao; String _name; @Inject TemplateManager templateMgr; @@ -694,11 +693,11 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, S3TO s3 = _s3Mgr.getS3TO(); checkObjectStorageConfiguration(swift, s3); - + StoragePoolVO pool = _primaryDataStoreDao.findById(volume.getPoolId()); if (swift == null && s3 == null) { for (HostVO ssHost : ssHosts) { DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand( - null, null, ssHost.getStorageUrl(), dcId, + pool,null, null, ssHost.getStorageUrl(), dcId, accountId, volumeId, "", true); Answer answer = null; try { @@ -717,7 +716,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, } } else { DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand( - swift, s3, "", dcId, accountId, volumeId, "", true); + pool,swift, s3, "", dcId, accountId, volumeId, "", true); Answer answer = null; try { answer = _agentMgr.sendToSSVM(dcId, cmd); diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index 2892e0081c2..576440a2ce7 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -273,7 +273,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, if (type == HypervisorType.BareMetal) { adapter = AdapterBase.getAdapterByName(_adapters, TemplateAdapterType.BareMetal.getName()); } else { - // see HyervisorTemplateAdapter + // see HypervisorTemplateAdapter adapter = AdapterBase.getAdapterByName(_adapters, TemplateAdapterType.Hypervisor.getName()); } diff --git a/server/src/com/cloud/upgrade/dao/Upgrade410to420.java b/server/src/com/cloud/upgrade/dao/Upgrade410to420.java index b43e494893b..05e2b49ffe4 100644 --- a/server/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/server/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -17,6 +17,10 @@ package com.cloud.upgrade.dao; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; +import org.apache.log4j.Logger; + import java.io.File; import java.sql.Connection; import java.sql.PreparedStatement; @@ -24,11 +28,6 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.UUID; -import org.apache.log4j.Logger; - -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.script.Script; - public class Upgrade410to420 implements DbUpgrade { final static Logger s_logger = Logger.getLogger(Upgrade410to420.class); @@ -66,6 +65,7 @@ public class Upgrade410to420 implements DbUpgrade { updateCluster_details(conn); updatePrimaryStore(conn); addEgressFwRulesForSRXGuestNw(conn); + upgradeEIPNetworkOfferings(conn); } private void updateSystemVmTemplates(Connection conn) { @@ -365,4 +365,38 @@ public class Upgrade410to420 implements DbUpgrade { } } } + + private void upgradeEIPNetworkOfferings(Connection conn) { + + PreparedStatement pstmt = null; + ResultSet rs = null; + + try { + pstmt = conn.prepareStatement("select id, elastic_ip_service from `cloud`.`network_offerings` where traffic_type='Guest'"); + rs = pstmt.executeQuery(); + while (rs.next()) { + long id = rs.getLong(1); + // check if elastic IP service is enabled for network offering + if (rs.getLong(2) != 0) { + //update network offering with eip_associate_public_ip set to true + pstmt = conn.prepareStatement("UPDATE `cloud`.`network_offerings` set eip_associate_public_ip=? where id=?"); + pstmt.setBoolean(1, true); + pstmt.setLong(2, id); + pstmt.executeUpdate(); + } + } + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to set elastic_ip_service for network offerings with EIP service enabled.", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + } } diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index bc93df8e756..e74c49124f7 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -42,6 +42,7 @@ import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.affinity.dao.AffinityGroupDao; import org.apache.cloudstack.api.command.admin.account.UpdateAccountCmd; import org.apache.cloudstack.api.command.admin.user.DeleteUserCmd; import org.apache.cloudstack.api.command.admin.user.RegisterCmd; @@ -220,6 +221,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M @Inject private AutoScaleManager _autoscaleMgr; @Inject VolumeManager volumeMgr; + @Inject + private AffinityGroupDao _affinityGroupDao; private List _userAuthenticators; List _userPasswordEncoders; @@ -238,7 +241,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M public List getUserAuthenticators() { return _userAuthenticators; } - + public void setUserAuthenticators(List authenticators) { _userAuthenticators = authenticators; } @@ -623,6 +626,10 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M int numRemoved = _securityGroupDao.removeByAccountId(accountId); s_logger.info("deleteAccount: Deleted " + numRemoved + " network groups for account " + accountId); + // Cleanup affinity groups + int numAGRemoved = _affinityGroupDao.removeByAccountId(accountId); + s_logger.info("deleteAccount: Deleted " + numAGRemoved + " affinity groups for account " + accountId); + // Delete all the networks boolean networksDeleted = true; s_logger.debug("Deleting networks for account " + account.getId()); @@ -683,13 +690,13 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M accountCleanupNeeded = true; } - // delete account specific Virtual vlans (belong to system Public Network) - only when networks are cleaned + // release account specific Virtual vlans (belong to system Public Network) - only when networks are cleaned // up successfully if (networksDeleted) { - if (!_configMgr.deleteAccountSpecificVirtualRanges(accountId)) { + if (!_configMgr.releaseAccountSpecificVirtualRanges(accountId)) { accountCleanupNeeded = true; } else { - s_logger.debug("Account specific Virtual IP ranges " + " are successfully deleted as a part of account id=" + accountId + " cleanup."); + s_logger.debug("Account specific Virtual IP ranges " + " are successfully released as a part of account id=" + accountId + " cleanup."); } } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 1c3764a8391..53a57c8e9cb 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -35,6 +35,9 @@ import javax.naming.ConfigurationException; import com.cloud.api.ApiDBUtils; import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.acl.SecurityChecker.AccessType; +import org.apache.cloudstack.affinity.AffinityGroupVO; +import org.apache.cloudstack.affinity.dao.AffinityGroupDao; +import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; import org.apache.cloudstack.api.command.user.vm.*; @@ -369,7 +372,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use VpcManager _vpcMgr; @Inject TemplateManager templateMgr; - @Inject + @Inject protected GuestOSCategoryDao _guestOSCategoryDao; @Inject UsageEventDao _usageEventDao; @@ -378,6 +381,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use @Inject protected VMSnapshotManager _vmSnapshotMgr; + @Inject + AffinityGroupVMMapDao _affinityGroupVMMapDao; + @Inject + AffinityGroupDao _affinityGroupDao; + @Inject List plannerSelectors; @@ -684,7 +692,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use try { VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid()); - status = vmEntity.stop(new Long(userId).toString()); + status = vmEntity.stop(new Long(userId).toString()); } catch (ResourceUnavailableException e) { s_logger.debug("Unable to stop due to ", e); status = false; @@ -1916,7 +1924,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use @Override public UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List securityGroupIdList, Account owner, - String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map requestedIps, IpAddresses defaultIps, String keyboard) + String hostName, + String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, + String userData, String sshKeyPair, Map requestedIps, IpAddresses defaultIps, + String keyboard, List affinityGroupIdList) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException { Account caller = UserContext.current().getCaller(); @@ -1966,13 +1977,17 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId, - diskSize, networkList, securityGroupIdList, group, userData, sshKeyPair, hypervisor, caller, requestedIps, defaultIps, keyboard); + diskSize, networkList, securityGroupIdList, group, userData, sshKeyPair, hypervisor, caller, + requestedIps, defaultIps, keyboard, affinityGroupIdList); } @Override public UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List networkIdList, List securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, - String sshKeyPair, Map requestedIps, IpAddresses defaultIps, String keyboard) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, + String sshKeyPair, Map requestedIps, + IpAddresses defaultIps, String keyboard, List affinityGroupIdList) + throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, + StorageUnavailableException, ResourceAllocationException { Account caller = UserContext.current().getCaller(); @@ -2018,7 +2033,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use isSecurityGroupEnabledNetworkUsed = true; } else { - // Verify that all the networks are Shared/Guest; can't create combination of SG enabled and disabled networks + // Verify that all the networks are Shared/Guest; can't create combination of SG enabled and disabled networks for (Long networkId : networkIdList) { NetworkVO network = _networkDao.findById(networkId); @@ -2034,7 +2049,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } isSecurityGroupEnabledNetworkUsed = true; - } + } if (!(network.getTrafficType() == TrafficType.Guest && network.getGuestType() == Network.GuestType.Shared)) { throw new InvalidParameterValueException("Can specify only Shared Guest networks when" + @@ -2079,12 +2094,15 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId, - diskSize, networkList, securityGroupIdList, group, userData, sshKeyPair, hypervisor, caller, requestedIps, defaultIps, keyboard); + diskSize, networkList, securityGroupIdList, group, userData, sshKeyPair, hypervisor, caller, + requestedIps, defaultIps, keyboard, affinityGroupIdList); } @Override public UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List networkIdList, Account owner, String hostName, - String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map requestedIps, IpAddresses defaultIps, String keyboard) + String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, + String userData, String sshKeyPair, Map requestedIps, IpAddresses defaultIps, + String keyboard, List affinityGroupIdList) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException { Account caller = UserContext.current().getCaller(); @@ -2192,7 +2210,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } } - return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId, diskSize, networkList, null, group, userData, sshKeyPair, hypervisor, caller, requestedIps, defaultIps, keyboard); + return createVirtualMachine(zone, serviceOffering, template, hostName, displayName, owner, diskOfferingId, + diskSize, networkList, null, group, userData, sshKeyPair, hypervisor, caller, requestedIps, defaultIps, + keyboard, affinityGroupIdList); } @@ -2205,7 +2225,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use @DB @ActionEvent(eventType = EventTypes.EVENT_VM_CREATE, eventDescription = "deploying Vm", create = true) protected UserVm createVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, String hostName, String displayName, Account owner, Long diskOfferingId, - Long diskSize, List networkList, List securityGroupIdList, String group, String userData, String sshKeyPair, HypervisorType hypervisor, Account caller, Map requestedIps, IpAddresses defaultIps, String keyboard) + Long diskSize, List networkList, List securityGroupIdList, String group, String userData, + String sshKeyPair, HypervisorType hypervisor, Account caller, Map requestedIps, + IpAddresses defaultIps, String keyboard, List affinityGroupIdList) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, StorageUnavailableException, ResourceAllocationException { _accountMgr.checkAccess(caller, null, true, owner); @@ -2261,6 +2283,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } } + // check that the affinity groups exist + if (affinityGroupIdList != null) { + for (Long affinityGroupId : affinityGroupIdList) { + AffinityGroupVO ag = _affinityGroupDao.findById(affinityGroupId); + if (ag == null) { + throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupId); + } else { + // verify permissions + _accountMgr.checkAccess(caller, null, true, owner, ag); + } + } + } + if (template.getHypervisorType() != null && template.getHypervisorType() != HypervisorType.BareMetal) { // check if we have available pools for vm deployment long availablePools = _storagePoolDao.countPoolsByStatus(StoragePoolStatus.Up); @@ -2438,7 +2473,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use // * verify that there are no duplicates if (hostNames.contains(hostName)) { throw new InvalidParameterValueException("The vm with hostName " + hostName - + " already exists in the network domain: " + ntwkDomain + "; network=" + + " already exists in the network domain: " + ntwkDomain + "; network=" + _networkModel.getNetwork(ntwkId)); } } @@ -2510,7 +2545,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use List computeTags = new ArrayList(); computeTags.add(offering.getHostTag()); - List rootDiskTags = new ArrayList(); + List rootDiskTags = new ArrayList(); rootDiskTags.add(offering.getTags()); if(isIso){ @@ -2552,6 +2587,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use _securityGroupMgr.addInstanceToGroups(vm.getId(), securityGroupIdList); + if (affinityGroupIdList != null && !affinityGroupIdList.isEmpty()) { + _affinityGroupVMMapDao.updateMap(vm.getId(), affinityGroupIdList); + } + return vm; } @@ -2829,7 +2868,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use try { VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid()); - vmEntity.stop(new Long(userId).toString()); + vmEntity.stop(new Long(userId).toString()); } catch (ResourceUnavailableException e) { throw new CloudRuntimeException( "Unable to contact the agent to stop the virtual machine " @@ -2851,6 +2890,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (ip != null && ip.getSystem()) { UserContext ctx = UserContext.current(); try { + long networkId = ip.getAssociatedWithNetworkId(); + Network guestNetwork = _networkDao.findById(networkId); + NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId()); + assert (offering.getAssociatePublicIP() == true) : "User VM should not have system owned public IP associated with it when offering configured not to associate public IP."; _rulesMgr.disableStaticNat(ip.getId(), ctx.getCaller(), ctx.getCallerUserId(), true); } catch (Exception ex) { s_logger.warn( @@ -3044,7 +3087,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use try { VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid()); - status = vmEntity.destroy(new Long(userId).toString()); + status = vmEntity.destroy(new Long(userId).toString()); } catch (CloudException e) { CloudRuntimeException ex = new CloudRuntimeException( "Unable to destroy with specified vmId", e); diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index af2271660fa..40725314f46 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -5,7 +5,7 @@ // 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, @@ -68,7 +68,9 @@ import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner; import com.cloud.deploy.DeploymentPlanner.ExcludeList; +import com.cloud.deploy.DeploymentPlanningManager; import com.cloud.domain.dao.DomainDao; +import com.cloud.exception.AffinityConflictException; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.ConnectionException; @@ -226,8 +228,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @Inject protected ResourceManager _resourceMgr; - - @Inject + + @Inject protected VMSnapshotManager _vmSnapshotMgr = null; @Inject protected ClusterDetailsDao _clusterDetailsDao; @@ -239,6 +241,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @Inject VolumeManager volumeMgr; + @Inject + DeploymentPlanningManager _dpMgr; + Map> _vmGurus = new HashMap>(); protected StateMachine2 _stateMachine; @@ -586,7 +591,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac ConcurrentOperationException, ResourceUnavailableException { return advanceStart(vm, params, caller, account, null); } - + @Override public T advanceStart(T vm, Map params, User caller, Account account, DeploymentPlan planToDeploy) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { @@ -695,17 +700,13 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vm, template, offering, account, params); DeployDestination dest = null; - for (DeploymentPlanner planner : _planners) { - if (planner.canHandle(vmProfile, plan, avoids)) { - dest = planner.plan(vmProfile, plan, avoids); - } else { - continue; - } - if (dest != null) { - avoids.addHost(dest.getHost().getId()); - journal.record("Deployment found ", vmProfile, dest); - break; - } + try { + dest = _dpMgr.planDeployment(vmProfile, plan, avoids); + } catch (AffinityConflictException e2) { + s_logger.warn("Unable to create deployment, affinity rules associted to the VM conflict", e2); + throw new CloudRuntimeException( + "Unable to create deployment, affinity rules associted to the VM conflict"); + } if (dest == null) { @@ -719,6 +720,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId()); } + if (dest != null) { + avoids.addHost(dest.getHost().getId()); + journal.record("Deployment found ", vmProfile, dest); + } + long destHostId = dest.getHost().getId(); vm.setPodId(dest.getPod().getId()); Long cluster_id = dest.getCluster().getId(); @@ -739,7 +745,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac if (s_logger.isDebugEnabled()) { s_logger.debug("VM is being created in podId: " + vm.getPodIdToDeployIn()); } - _networkMgr.prepare(vmProfile, dest, ctx); + _networkMgr.prepare(vmProfile, dest, ctx); if (vm.getHypervisorType() != HypervisorType.BareMetal) { this.volumeMgr.prepare(vmProfile, dest); } @@ -797,7 +803,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac StopCommand cmd = new StopCommand(vm); StopAnswer answer = (StopAnswer) _agentMgr.easySend(destHostId, cmd); if (answer == null || !answer.getResult()) { - s_logger.warn("Unable to stop " + vm + " due to " + (answer != null ? answer.getDetails() : "no answers")); + s_logger.warn("Unable to stop " + vm + " due to " + (answer != null ? answer.getDetails() : "no answers")); _haMgr.scheduleStop(vm, destHostId, WorkType.ForceStop); throw new ExecutionException("Unable to stop " + vm + " so we are unable to retry the start operation"); } @@ -1144,7 +1150,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac s_logger.error("State transit with event: " + e + " failed due to: " + vm.getInstanceName() + " has active VM snapshots tasks"); return false; } - + State oldState = vm.getState(); if (oldState == State.Starting) { if (e == Event.OperationSucceeded) { @@ -1179,12 +1185,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac s_logger.debug("Unable to stop " + vm); return false; } - + if (!_vmSnapshotMgr.deleteAllVMSnapshots(vm.getId(),null)){ s_logger.debug("Unable to delete all snapshots for " + vm); return false; } - + try { if (!stateTransitTo(vm, VirtualMachine.Event.DestroyRequested, vm.getHostId())) { s_logger.debug("Unable to destroy the vm because it is not in the correct state: " + vm); @@ -1487,25 +1493,23 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac DeployDestination dest = null; while (true) { - for (DeploymentPlanner planner : _planners) { - if (planner.canHandle(profile, plan, excludes)) { - dest = planner.plan(profile, plan, excludes); - } else { - continue; - } - if (dest != null) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Planner " + planner + " found " + dest + " for migrating to."); - } - break; - } - if (s_logger.isDebugEnabled()) { - s_logger.debug("Planner " + planner + " was unable to find anything."); - } + try { + dest = _dpMgr.planDeployment(profile, plan, excludes); + } catch (AffinityConflictException e2) { + s_logger.warn("Unable to create deployment, affinity rules associted to the VM conflict", e2); + throw new CloudRuntimeException( + "Unable to create deployment, affinity rules associted to the VM conflict"); } - if (dest == null) { + if (dest != null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Found destination " + dest + " for migrating to."); + } + } else { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Unable to find destination for migrating the vm " + profile); + } throw new InsufficientServerCapacityException("Unable to find a server to migrate to.", host.getClusterId()); } @@ -1559,7 +1563,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @Override public boolean isVirtualMachineUpgradable(VirtualMachine vm, ServiceOffering offering) { - boolean isMachineUpgradable = true; + boolean isMachineUpgradable = true; for(HostAllocator allocator : _hostAllocators) { isMachineUpgradable = allocator.isVirtualMachineUpgradable(vm, offering); if(isMachineUpgradable) @@ -1628,7 +1632,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac return new StopCommand(vmName); } - public Commands fullHostSync(final long hostId, StartupRoutingCommand startup) { + public Commands fullHostSync(final long hostId, StartupRoutingCommand startup) { Commands commands = new Commands(OnError.Continue); Map infos = convertToInfos(startup); @@ -1637,7 +1641,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac s_logger.debug("Found " + vms.size() + " VMs for host " + hostId); for (VMInstanceVO vm : vms) { AgentVmInfo info = infos.remove(vm.getId()); - + // sync VM Snapshots related transient states List vmSnapshotsInTrasientStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging,VMSnapshot.State.Reverting, VMSnapshot.State.Creating); if(vmSnapshotsInTrasientStates.size() > 1){ @@ -1649,11 +1653,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac s_logger.info("Successfully sync VM with transient snapshot: " + vm.getInstanceName()); } } - + VMInstanceVO castedVm = null; if (info == null) { info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped); - } + } castedVm = info.guru.findById(vm.getId()); HypervisorGuru hvGuru = _hvGuruMgr.getGuru(castedVm.getHypervisorType()); @@ -1767,7 +1771,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac for (VMInstanceVO vm : set_vms) { AgentVmInfo info = infos.remove(vm.getId()); VMInstanceVO castedVm = null; - + // sync VM Snapshots related transient states List vmSnapshotsInExpungingStates = _vmSnapshotDao.listByInstanceId(vm.getId(), VMSnapshot.State.Expunging, VMSnapshot.State.Creating,VMSnapshot.State.Reverting); if(vmSnapshotsInExpungingStates.size() > 0){ @@ -1785,9 +1789,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac s_logger.info("Successfully sync VM with transient snapshot: " + vm.getInstanceName()); } } - - if ((info == null && (vm.getState() == State.Running || vm.getState() == State.Starting )) - || (info != null && (info.state == State.Running && vm.getState() == State.Starting))) + + if ((info == null && (vm.getState() == State.Running || vm.getState() == State.Starting )) + || (info != null && (info.state == State.Running && vm.getState() == State.Starting))) { s_logger.info("Found vm " + vm.getInstanceName() + " in inconsistent state. " + vm.getState() + " on CS while " + (info == null ? "Stopped" : "Running") + " on agent"); info = new AgentVmInfo(vm.getInstanceName(), getVmGuru(vm), vm, State.Stopped); @@ -1925,7 +1929,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac return map; } - protected Map convertToInfos(StartupRoutingCommand cmd) { + protected Map convertToInfos(StartupRoutingCommand cmd) { final Map states = cmd.getVmStates(); final HashMap map = new HashMap(); if (states == null) { @@ -1989,7 +1993,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac * compareState does as its name suggests and compares the states between * management server and agent. It returns whether something should be * cleaned up - * + * */ protected Command compareState(long hostId, VMInstanceVO vm, final AgentVmInfo info, final boolean fullSync, boolean trackExternalChange) { State agentState = info.state; @@ -2192,7 +2196,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac List nics = _nicsDao.listByVmId(profile.getId()); for (NicVO nic : nics) { Network network = _networkModel.getNetwork(nic.getNetworkId()); - NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), null, + NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), null, _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(profile.getHypervisorType(), network)); profile.addNic(nicProfile); } @@ -2319,7 +2323,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac s_logger.fatal("The Cluster VM sync process failed for cluster id " + clusterId + " with ", e); } } - else { // for others KVM and VMWare + else { // for others KVM and VMWare StartupRoutingCommand startup = (StartupRoutingCommand) cmd; Commands commands = fullHostSync(agentId, startup); @@ -2492,7 +2496,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } @Override - public NicProfile addVmToNetwork(VirtualMachine vm, Network network, NicProfile requested) throws ConcurrentOperationException, + public NicProfile addVmToNetwork(VirtualMachine vm, Network network, NicProfile requested) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { s_logger.debug("Adding vm " + vm + " to network " + network + "; requested nic profile " + requested); @@ -2502,14 +2506,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } else { vmVO = _vmDao.findById(vm.getId()); } - ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), + ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)); - VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, + VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, null, null, null); DataCenter dc = _configMgr.getZone(network.getDataCenterId()); - Host host = _hostDao.findById(vm.getHostId()); + Host host = _hostDao.findById(vm.getHostId()); DeployDestination dest = new DeployDestination(dc, null, null, host); //check vm state @@ -2557,14 +2561,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac public boolean removeNicFromVm(VirtualMachine vm, NicVO nic) throws ConcurrentOperationException, ResourceUnavailableException { VMInstanceVO vmVO = _vmDao.findById(vm.getId()); NetworkVO network = _networkDao.findById(nic.getNetworkId()); - ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), + ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)); - VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, + VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, null, null, null); DataCenter dc = _configMgr.getZone(network.getDataCenterId()); - Host host = _hostDao.findById(vm.getHostId()); + Host host = _hostDao.findById(vm.getHostId()); DeployDestination dest = new DeployDestination(dc, null, null, host); VirtualMachineGuru vmGuru = getVmGuru(vmVO); HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType()); @@ -2576,9 +2580,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default."); } - NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), - _networkModel.getNetworkRate(network.getId(), vm.getId()), - _networkModel.isSecurityGroupSupportedInNetwork(network), + NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), + _networkModel.getNetworkRate(network.getId(), vm.getId()), + _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network)); //1) Unplug the nic @@ -2611,14 +2615,14 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @Override public boolean removeVmFromNetwork(VirtualMachine vm, Network network, URI broadcastUri) throws ConcurrentOperationException, ResourceUnavailableException { VMInstanceVO vmVO = _vmDao.findById(vm.getId()); - ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), + ReservationContext context = new ReservationContextImpl(null, null, _accountMgr.getActiveUser(User.UID_SYSTEM), _accountMgr.getAccount(Account.ACCOUNT_ID_SYSTEM)); - VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, + VirtualMachineProfileImpl vmProfile = new VirtualMachineProfileImpl(vmVO, null, null, null, null); DataCenter dc = _configMgr.getZone(network.getDataCenterId()); - Host host = _hostDao.findById(vm.getHostId()); + Host host = _hostDao.findById(vm.getHostId()); DeployDestination dest = new DeployDestination(dc, null, null, host); VirtualMachineGuru vmGuru = getVmGuru(vmVO); HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vmProfile.getVirtualMachine().getHypervisorType()); @@ -2643,9 +2647,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac throw new CloudRuntimeException("Failed to remove nic from " + vm + " in " + network + ", nic is default."); } - NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), - _networkModel.getNetworkRate(network.getId(), vm.getId()), - _networkModel.isSecurityGroupSupportedInNetwork(network), + NicProfile nicProfile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), + _networkModel.getNetworkRate(network.getId(), vm.getId()), + _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vmProfile.getVirtualMachine().getHypervisorType(), network)); //1) Unplug the nic diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java new file mode 100644 index 00000000000..2b490efe6e5 --- /dev/null +++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java @@ -0,0 +1,346 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.cloudstack.affinity.dao.AffinityGroupDao; +import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; +import org.apache.log4j.Logger; +import org.springframework.context.annotation.Primary; + + +import com.cloud.deploy.DeploymentPlanner; +import com.cloud.event.ActionEvent; +import com.cloud.event.EventTypes; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceInUseException; +import com.cloud.network.security.SecurityGroup; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.UserContext; +import com.cloud.uservm.UserVm; +import com.cloud.utils.Pair; +import com.cloud.utils.component.ComponentContext; +import com.cloud.utils.component.Manager; +import com.cloud.utils.component.ManagerBase; +import com.cloud.utils.db.DB; +import com.cloud.utils.db.Filter; +import com.cloud.utils.db.JoinBuilder; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.fsm.StateListener; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.VirtualMachine.Event; +import com.cloud.vm.VirtualMachine.State; +import com.cloud.vm.dao.UserVmDao; + +@Local(value = { AffinityGroupService.class }) +public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGroupService, Manager, + StateListener { + + public static final Logger s_logger = Logger.getLogger(AffinityGroupServiceImpl.class); + private String _name; + + @Inject + AccountManager _accountMgr; + + @Inject + AffinityGroupDao _affinityGroupDao; + + @Inject + AffinityGroupVMMapDao _affinityGroupVMMapDao; + + @Inject + private UserVmDao _userVmDao; + + @Override + @ActionEvent(eventType = EventTypes.EVENT_AFFINITY_GROUP_CREATE, eventDescription = "Creating Affinity Group", create = true) + public AffinityGroup createAffinityGroup(String account, Long domainId, String affinityGroupName, + String affinityGroupType, String description) { + + Account caller = UserContext.current().getCaller(); + Account owner = _accountMgr.finalizeOwner(caller, account, domainId, null); + + if (_affinityGroupDao.isNameInUse(owner.getAccountId(), owner.getDomainId(), affinityGroupName)) { + throw new InvalidParameterValueException("Unable to create affinity group, a group with name " + + affinityGroupName + + " already exisits."); + } + + + //validate the affinityGroupType + Map typeProcessorMap = getAffinityTypeToProcessorMap(); + if (typeProcessorMap != null && !typeProcessorMap.isEmpty()) { + if (!typeProcessorMap.containsKey(affinityGroupType)) { + throw new InvalidParameterValueException("Unable to create affinity group, invalid affinity group type" + + affinityGroupType); + } + } else { + throw new InvalidParameterValueException( + "Unable to create affinity group, no Affinity Group Types configured"); + } + + if (domainId == null) { + domainId = owner.getDomainId(); + } + + AffinityGroupVO group = new AffinityGroupVO(affinityGroupName, affinityGroupType, description, domainId, + owner.getId()); + _affinityGroupDao.persist(group); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Created affinity group =" + affinityGroupName); + } + + return group; + } + + @DB + @Override + @ActionEvent(eventType = EventTypes.EVENT_AFFINITY_GROUP_DELETE, eventDescription = "Deleting affinity group") + public boolean deleteAffinityGroup(Long affinityGroupId, String account, Long domainId, String affinityGroupName) + throws ResourceInUseException { + + Account caller = UserContext.current().getCaller(); + Account owner = _accountMgr.finalizeOwner(caller, account, domainId, null); + + AffinityGroupVO group = null; + if (affinityGroupId != null) { + group = _affinityGroupDao.findById(affinityGroupId); + if (group == null) { + throw new InvalidParameterValueException("Unable to find affinity group: " + affinityGroupId + + "; failed to delete group."); + } + } else if (affinityGroupName != null) { + group = _affinityGroupDao.findByAccountAndName(owner.getAccountId(), affinityGroupName); + if (group == null) { + throw new InvalidParameterValueException("Unable to find affinity group: " + affinityGroupName + + "; failed to delete group."); + } + } else { + throw new InvalidParameterValueException( + "Either the affinity group Id or group name must be specified to delete the group"); + } + if (affinityGroupId == null) { + affinityGroupId = group.getId(); + } + // check permissions + _accountMgr.checkAccess(caller, null, true, group); + + final Transaction txn = Transaction.currentTxn(); + txn.start(); + + group = _affinityGroupDao.lockRow(affinityGroupId, true); + if (group == null) { + throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupId); + } + + List affinityGroupVmMap = _affinityGroupVMMapDao.listByAffinityGroup(affinityGroupId); + if (!affinityGroupVmMap.isEmpty()) { + throw new ResourceInUseException("Cannot delete affinity group when it's in use by virtual machines"); + } + + _affinityGroupDao.expunge(affinityGroupId); + txn.commit(); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Deleted affinity group id=" + affinityGroupId); + } + return true; + } + + @Override + public Pair, Integer> listAffinityGroups(Long affinityGroupId, String affinityGroupName, String affinityGroupType, Long vmId, Long startIndex, Long pageSize) { + Filter searchFilter = new Filter(AffinityGroupVO.class, "id", Boolean.TRUE, startIndex, pageSize); + + Account caller = UserContext.current().getCaller(); + + Long accountId = caller.getAccountId(); + Long domainId = caller.getDomainId(); + + SearchBuilder vmInstanceSearch = _affinityGroupVMMapDao.createSearchBuilder(); + vmInstanceSearch.and("instanceId", vmInstanceSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); + + SearchBuilder groupSearch = _affinityGroupDao.createSearchBuilder(); + + SearchCriteria sc = groupSearch.create(); + + if (accountId != null) { + sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId); + } + + if (domainId != null) { + sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); + } + + if (affinityGroupId != null) { + sc.addAnd("id", SearchCriteria.Op.EQ, affinityGroupId); + } + + if (affinityGroupName != null) { + sc.addAnd("name", SearchCriteria.Op.EQ, affinityGroupName); + } + + if (affinityGroupType != null) { + sc.addAnd("type", SearchCriteria.Op.EQ, affinityGroupType); + } + + if (vmId != null) { + UserVmVO userVM = _userVmDao.findById(vmId); + 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); + // add join to affinity_groups_vm_map + groupSearch.join("vmInstanceSearch", vmInstanceSearch, groupSearch.entity().getId(), vmInstanceSearch + .entity().getAffinityGroupId(), JoinBuilder.JoinType.INNER); + sc.setJoinParameters("vmInstanceSearch", "instanceId", vmId); + } + + Pair, Integer> result = _affinityGroupDao.searchAndCount(sc, searchFilter); + return new Pair, Integer>(result.first(), result.second()); + } + + + @Override + public List listAffinityGroupTypes() { + List types = new ArrayList(); + Map componentMap = ComponentContext.getComponentsOfType(AffinityGroupProcessor.class); + + if (componentMap.size() > 0) { + for (Entry entry : componentMap.entrySet()) { + types.add(entry.getValue().getType()); + } + + } + return types; + } + + protected Map getAffinityTypeToProcessorMap() { + Map typeProcessorMap = new HashMap(); + Map componentMap = ComponentContext + .getComponentsOfType(AffinityGroupProcessor.class); + + if (componentMap.size() > 0) { + for (Entry entry : componentMap.entrySet()) { + typeProcessorMap.put(entry.getValue().getType(), entry.getValue()); + } + } + return typeProcessorMap; + } + + @Override + public boolean configure(final String name, final Map params) throws ConfigurationException { + _name = name; + VirtualMachine.State.getStateMachine().registerListener(this); + return true; + } + + @Override + public boolean start() { + return true; + } + + @Override + public boolean stop() { + return true; + } + + @Override + public String getName() { + return _name; + } + + @Override + public AffinityGroup getAffinityGroup(Long groupId) { + return _affinityGroupDao.findById(groupId); + } + + @Override + public boolean preStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, + boolean status, Object opaque) { + return true; + } + + @Override + public boolean postStateTransitionEvent(State oldState, Event event, State newState, VirtualMachine vo, + boolean status, Object opaque) { + if (!status) { + return false; + } + if ((newState == State.Expunging)) { + // cleanup all affinity groups associations of the Expunged VM + SearchCriteria sc = _affinityGroupVMMapDao.createSearchCriteria(); + sc.addAnd("instanceId", SearchCriteria.Op.EQ, vo.getId()); + _affinityGroupVMMapDao.expunge(sc); + } + return true; + } + + @Override + public UserVm updateVMAffinityGroups(Long vmId, List affinityGroupIds) { + // Verify input parameters + UserVmVO vmInstance = _userVmDao.findById(vmId); + if (vmInstance == null) { + throw new InvalidParameterValueException("unable to find a virtual machine with id " + vmId); + } + + // Check that the VM is stopped + if (!vmInstance.getState().equals(State.Stopped)) { + s_logger.warn("Unable to update affinity groups of the virtual machine " + vmInstance.toString() + + " in state " + vmInstance.getState()); + throw new InvalidParameterValueException("Unable update affinity groups of the virtual machine " + + vmInstance.toString() + " " + "in state " + vmInstance.getState() + + "; make sure the virtual machine is stopped and not in an error state before updating."); + } + + Account caller = UserContext.current().getCaller(); + Account owner = _accountMgr.getAccount(vmInstance.getAccountId()); + + // check that the affinity groups exist + for (Long affinityGroupId : affinityGroupIds) { + AffinityGroupVO ag = _affinityGroupDao.findById(affinityGroupId); + if (ag == null) { + throw new InvalidParameterValueException("Unable to find affinity group by id " + affinityGroupId); + } else { + // verify permissions + _accountMgr.checkAccess(caller, null, true, owner, ag); + } + } + _affinityGroupVMMapDao.updateMap(vmId, affinityGroupIds); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Updated VM :" + vmId + " affinity groups to =" + affinityGroupIds); + } + // APIResponseHelper will pull out the updated affinitygroups. + return vmInstance; + + } + +} diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupVMMapVO.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupVMMapVO.java new file mode 100644 index 00000000000..f84e4c351aa --- /dev/null +++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupVMMapVO.java @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.PrimaryKeyJoinColumn; +import javax.persistence.SecondaryTable; +import javax.persistence.SecondaryTables; +import javax.persistence.Table; + +import org.apache.cloudstack.api.InternalIdentity; + +@Entity +@Table(name = ("affinity_group_vm_map")) +public class AffinityGroupVMMapVO implements InternalIdentity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private Long id; + + @Column(name = "affinity_group_id") + private long affinityGroupId; + + @Column(name = "instance_id") + private long instanceId; + + public AffinityGroupVMMapVO() { + } + + public AffinityGroupVMMapVO(long affinityGroupId, long instanceId) { + this.affinityGroupId = affinityGroupId; + this.instanceId = instanceId; + } + + public long getId() { + return id; + } + + public long getAffinityGroupId() { + return affinityGroupId; + } + + + public long getInstanceId() { + return instanceId; + } + +} diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupVO.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupVO.java new file mode 100644 index 00000000000..b6c4a027484 --- /dev/null +++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupVO.java @@ -0,0 +1,114 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity; + +import java.util.UUID; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + + +@Entity +@Table(name = ("affinity_group")) +public class AffinityGroupVO implements AffinityGroup { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private long id; + + @Column(name = "name") + private String name; + + @Column(name = "type") + private String type; + + @Column(name = "description") + private String description; + + @Column(name = "domain_id") + private long domainId; + + @Column(name = "account_id") + private long accountId; + + @Column(name = "uuid") + private String uuid; + + public AffinityGroupVO() { + this.uuid = UUID.randomUUID().toString(); + } + + public AffinityGroupVO(String name, String type, String description, long domainId, long accountId) { + this.name = name; + this.description = description; + this.domainId = domainId; + this.accountId = accountId; + this.uuid = UUID.randomUUID().toString(); + this.type = type; + } + + @Override + public long getId() { + return id; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public long getDomainId() { + return domainId; + } + + @Override + public long getAccountId() { + return accountId; + } + + @Override + public String getUuid() { + return this.uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + @Override + public String getType() { + return type; + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder("AffinityGroup["); + buf.append(id).append("|").append(name).append("|").append(type).append("]"); + return buf.toString(); + } + +} diff --git a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDao.java b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDao.java new file mode 100644 index 00000000000..296e7b1d043 --- /dev/null +++ b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDao.java @@ -0,0 +1,30 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity.dao; + +import java.util.List; + +import org.apache.cloudstack.affinity.AffinityGroupVO; +import com.cloud.utils.db.GenericDao; + +public interface AffinityGroupDao extends GenericDao { + List listByAccountId(long accountId); + boolean isNameInUse(Long accountId, Long domainId, String name); + AffinityGroupVO findByAccountAndName(Long accountId, String name); + List findByAccountAndNames(Long accountId, String... names); + int removeByAccountId(long accountId); +} diff --git a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java new file mode 100644 index 00000000000..d189d609ff2 --- /dev/null +++ b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupDaoImpl.java @@ -0,0 +1,102 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity.dao; + +import java.util.List; + +import javax.annotation.PostConstruct; +import javax.ejb.Local; +import org.apache.cloudstack.affinity.AffinityGroupVO; +import org.springframework.stereotype.Component; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; + +@Local(value = { AffinityGroupDao.class }) +public class AffinityGroupDaoImpl extends GenericDaoBase implements AffinityGroupDao { + private SearchBuilder AccountIdSearch; + private SearchBuilder AccountIdNameSearch; + private SearchBuilder AccountIdNamesSearch; + + + public AffinityGroupDaoImpl() { + + } + + @PostConstruct + protected void init() { + AccountIdSearch = createSearchBuilder(); + AccountIdSearch.and("accountId", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + AccountIdSearch.done(); + + AccountIdNameSearch = createSearchBuilder(); + AccountIdNameSearch.and("accountId", AccountIdNameSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + AccountIdNameSearch.and("name", AccountIdNameSearch.entity().getName(), SearchCriteria.Op.EQ); + + AccountIdNamesSearch = createSearchBuilder(); + AccountIdNamesSearch.and("accountId", AccountIdNamesSearch.entity().getAccountId(), SearchCriteria.Op.EQ); + AccountIdNamesSearch.and("groupNames", AccountIdNamesSearch.entity().getName(), SearchCriteria.Op.IN); + AccountIdNameSearch.done(); + } + + @Override + public List listByAccountId(long accountId) { + SearchCriteria sc = AccountIdSearch.create(); + sc.setParameters("accountId", accountId); + return listBy(sc); + } + + @Override + public boolean isNameInUse(Long accountId, Long domainId, String name) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("name", SearchCriteria.Op.EQ, name); + if (accountId != null) { + sc.addAnd("accountId", SearchCriteria.Op.EQ, accountId); + } else { + sc.addAnd("domainId", SearchCriteria.Op.EQ, domainId); + sc.addAnd("accountId", SearchCriteria.Op.NULL); + } + + List AffinityGroups = listBy(sc); + return ((AffinityGroups != null) && !AffinityGroups.isEmpty()); + } + + @Override + public AffinityGroupVO findByAccountAndName(Long accountId, String name) { + SearchCriteria sc = AccountIdNameSearch.create(); + sc.setParameters("accountId", accountId); + sc.setParameters("name", name); + + return findOneIncludingRemovedBy(sc); + } + + @Override + public List findByAccountAndNames(Long accountId, String... names) { + SearchCriteria sc = AccountIdNamesSearch.create(); + sc.setParameters("accountId", accountId); + + sc.setParameters("groupNames", (Object [])names); + + return listBy(sc); + } + @Override + public int removeByAccountId(long accountId) { + SearchCriteria sc = AccountIdSearch.create(); + sc.setParameters("accountId", accountId); + return expunge(sc); + } +} diff --git a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDao.java b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDao.java new file mode 100644 index 00000000000..f2951bc8d91 --- /dev/null +++ b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDao.java @@ -0,0 +1,47 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity.dao; + +import java.util.List; + +import org.apache.cloudstack.affinity.AffinityGroupVMMapVO; + +import com.cloud.utils.Pair; +import com.cloud.utils.db.Filter; +import com.cloud.utils.db.GenericDao; +import com.cloud.vm.VirtualMachine.State; + +public interface AffinityGroupVMMapDao extends GenericDao { + + List listByInstanceId(long instanceId); + + Pair, Integer> listByInstanceId(long instanceId, Filter filter); + + List listByAffinityGroup(long affinityGroupId); + + List listVmIdsByAffinityGroup(long affinityGroupId); + + AffinityGroupVMMapVO findByVmIdGroupId(long instanceId, long affinityGroupId); + + long countAffinityGroupsForVm(long instanceId); + + int deleteVM(long instanceId); + + List findByVmIdType(long instanceId, String type); + + void updateMap(Long vmId, List affinityGroupIds); +} diff --git a/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java new file mode 100644 index 00000000000..e03e73c6320 --- /dev/null +++ b/server/src/org/apache/cloudstack/affinity/dao/AffinityGroupVMMapDaoImpl.java @@ -0,0 +1,167 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity.dao; + +import java.util.List; + +import javax.annotation.PostConstruct; +import javax.ejb.Local; +import javax.inject.Inject; + +import org.apache.cloudstack.affinity.AffinityGroupVMMapVO; +import org.apache.cloudstack.affinity.AffinityGroupVO; +import org.springframework.stereotype.Component; + +import com.cloud.host.HostTagVO; +import com.cloud.utils.Pair; +import com.cloud.utils.db.Filter; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.utils.db.GenericSearchBuilder; +import com.cloud.utils.db.JoinBuilder.JoinType; +import com.cloud.utils.db.SearchBuilder; +import com.cloud.utils.db.SearchCriteria; +import com.cloud.utils.db.SearchCriteria.Func; +import com.cloud.utils.db.Transaction; + +@Local(value = { AffinityGroupVMMapDao.class }) +public class AffinityGroupVMMapDaoImpl extends GenericDaoBase implements + AffinityGroupVMMapDao { + private SearchBuilder ListByVmId; + private SearchBuilder ListByVmIdGroupId; + protected GenericSearchBuilder CountSGForVm; + private GenericSearchBuilder ListVmIdByAffinityGroup; + private SearchBuilder ListByAffinityGroup; + private SearchBuilder ListByVmIdType; + + @Inject + protected AffinityGroupDao _affinityGroupDao; + + public AffinityGroupVMMapDaoImpl() { + } + + @PostConstruct + protected void init() { + ListVmIdByAffinityGroup = createSearchBuilder(Long.class); + ListVmIdByAffinityGroup.and("affinityGroupId", ListVmIdByAffinityGroup.entity().getAffinityGroupId(), + SearchCriteria.Op.EQ); + ListVmIdByAffinityGroup.selectField(ListVmIdByAffinityGroup.entity().getInstanceId()); + ListVmIdByAffinityGroup.done(); + + ListByAffinityGroup = createSearchBuilder(); + ListByAffinityGroup.and("affinityGroupId", ListByAffinityGroup.entity().getAffinityGroupId(), + SearchCriteria.Op.EQ); + ListByAffinityGroup.done(); + + ListByVmId = createSearchBuilder(); + ListByVmId.and("instanceId", ListByVmId.entity().getInstanceId(), SearchCriteria.Op.EQ); + ListByVmId.done(); + + ListByVmIdGroupId = createSearchBuilder(); + ListByVmIdGroupId.and("instanceId", ListByVmIdGroupId.entity().getInstanceId(), SearchCriteria.Op.EQ); + ListByVmIdGroupId.and("affinityGroupId", ListByVmIdGroupId.entity().getAffinityGroupId(), SearchCriteria.Op.EQ); + ListByVmIdGroupId.done(); + + SearchBuilder groupSearch = _affinityGroupDao.createSearchBuilder(); + groupSearch.and("type", groupSearch.entity().getType(), SearchCriteria.Op.EQ); + + ListByVmIdType = createSearchBuilder(); + ListByVmIdType.and("instanceId", ListByVmIdType.entity().getInstanceId(), SearchCriteria.Op.EQ); + ListByVmIdType.join("groupSearch", groupSearch, ListByVmIdType.entity().getAffinityGroupId(), groupSearch.entity().getId(), JoinType.INNER); + ListByVmIdType.done(); + + CountSGForVm = createSearchBuilder(Long.class); + CountSGForVm.select(null, Func.COUNT, null); + CountSGForVm.and("vmId", CountSGForVm.entity().getInstanceId(), SearchCriteria.Op.EQ); + CountSGForVm.done(); + } + + @Override + public List listByAffinityGroup(long affinityGroupId) { + SearchCriteria sc = ListByAffinityGroup.create(); + sc.setParameters("affinityGroupId", affinityGroupId); + return listBy(sc); + } + + @Override + public List listByInstanceId(long vmId) { + SearchCriteria sc = ListByVmId.create(); + sc.setParameters("instanceId", vmId); + return listBy(sc); + } + + @Override + public Pair, Integer> listByInstanceId(long instanceId, Filter filter) { + SearchCriteria sc = ListByVmId.create(); + sc.setParameters("instanceId", instanceId); + return this.searchAndCount(sc, filter); + } + + @Override + public int deleteVM(long instanceId) { + SearchCriteria sc = ListByVmId.create(); + sc.setParameters("instanceId", instanceId); + return super.expunge(sc); + } + + @Override + public List listVmIdsByAffinityGroup(long affinityGroupId) { + SearchCriteria sc = ListVmIdByAffinityGroup.create(); + sc.setParameters("affinityGroupId", affinityGroupId); + return customSearchIncludingRemoved(sc, null); + } + + @Override + public AffinityGroupVMMapVO findByVmIdGroupId(long instanceId, long affinityGroupId) { + SearchCriteria sc = ListByVmIdGroupId.create(); + sc.setParameters("affinityGroupId", affinityGroupId); + sc.setParameters("instanceId", instanceId); + return findOneIncludingRemovedBy(sc); + } + + @Override + public long countAffinityGroupsForVm(long instanceId) { + SearchCriteria sc = CountSGForVm.create(); + sc.setParameters("vmId", instanceId); + return customSearch(sc, null).get(0); + } + + @Override + public List findByVmIdType(long instanceId, String type) { + SearchCriteria sc = ListByVmIdType.create(); + sc.setParameters("instanceId", instanceId); + sc.setJoinParameters("groupSearch", "type", type); + return listBy(sc); + } + + @Override + public void updateMap(Long vmId, List affinityGroupIds) { + Transaction txn = Transaction.currentTxn(); + txn.start(); + + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("instanceId", SearchCriteria.Op.EQ, vmId); + expunge(sc); + + for (Long groupId : affinityGroupIds) { + AffinityGroupVMMapVO vo = new AffinityGroupVMMapVO(groupId, vmId); + persist(vo); + } + + txn.commit(); + + } +} diff --git a/server/test/com/cloud/configuration/ConfigurationManagerTest.java b/server/test/com/cloud/configuration/ConfigurationManagerTest.java new file mode 100755 index 00000000000..ee98d53c922 --- /dev/null +++ b/server/test/com/cloud/configuration/ConfigurationManagerTest.java @@ -0,0 +1,413 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package com.cloud.configuration; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.lang.reflect.Field; + +import org.apache.cloudstack.api.command.admin.vlan.DedicatePublicIpRangeCmd; +import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd; +import org.apache.log4j.Logger; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import com.cloud.configuration.Resource.ResourceType; +import com.cloud.dc.AccountVlanMapVO; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.Vlan; +import com.cloud.dc.VlanVO; +import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.dao.AccountVlanMapDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.VlanDao; +import com.cloud.network.NetworkManager; +import com.cloud.network.dao.FirewallRulesDao; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.network.dao.IPAddressVO; +import com.cloud.projects.ProjectManager; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountVO; +import com.cloud.user.ResourceLimitService; +import com.cloud.user.UserContext; +import com.cloud.user.dao.AccountDao; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.net.Ip; + +import junit.framework.Assert; + +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.doNothing; + +public class ConfigurationManagerTest { + + private static final Logger s_logger = Logger.getLogger(ConfigurationManagerTest.class); + + ConfigurationManagerImpl configurationMgr = new ConfigurationManagerImpl(); + + DedicatePublicIpRangeCmd dedicatePublicIpRangesCmd = new DedicatePublicIpRangeCmdExtn(); + Class _dedicatePublicIpRangeClass = dedicatePublicIpRangesCmd.getClass().getSuperclass(); + + ReleasePublicIpRangeCmd releasePublicIpRangesCmd = new ReleasePublicIpRangeCmdExtn(); + Class _releasePublicIpRangeClass = releasePublicIpRangesCmd.getClass().getSuperclass(); + + @Mock AccountManager _accountMgr; + @Mock ProjectManager _projectMgr; + @Mock ResourceLimitService _resourceLimitMgr; + @Mock NetworkManager _networkMgr; + @Mock AccountDao _accountDao; + @Mock VlanDao _vlanDao; + @Mock AccountVlanMapDao _accountVlanMapDao; + @Mock IPAddressDao _publicIpAddressDao; + @Mock DataCenterDao _zoneDao; + @Mock FirewallRulesDao _firewallDao; + + VlanVO vlan = new VlanVO(Vlan.VlanType.VirtualNetwork, "vlantag", "vlangateway","vlannetmask", 1L, "iprange", 1L, 1L, null, null, null); + + @Before + public void setup() throws Exception { + MockitoAnnotations.initMocks(this); + configurationMgr._accountMgr = _accountMgr; + configurationMgr._projectMgr = _projectMgr; + configurationMgr._resourceLimitMgr = _resourceLimitMgr; + configurationMgr._networkMgr = _networkMgr; + configurationMgr._accountDao = _accountDao; + configurationMgr._vlanDao = _vlanDao; + configurationMgr._accountVlanMapDao = _accountVlanMapDao; + configurationMgr._publicIpAddressDao = _publicIpAddressDao; + configurationMgr._zoneDao = _zoneDao; + configurationMgr._firewallDao = _firewallDao; + + Account account = (Account) new AccountVO("testaccount", 1, "networkdomain", (short) 0, UUID.randomUUID().toString()); + when(configurationMgr._accountMgr.getAccount(anyLong())).thenReturn(account); + when(configurationMgr._accountDao.findActiveAccount(anyString(), anyLong())).thenReturn(account); + when(configurationMgr._accountMgr.getActiveAccountById(anyLong())).thenReturn(account); + + when(configurationMgr._publicIpAddressDao.countIPs(anyLong(), anyLong(), anyBoolean())).thenReturn(1); + + doNothing().when(configurationMgr._resourceLimitMgr).checkResourceLimit(any(Account.class), + any(ResourceType.class), anyLong()); + + when(configurationMgr._accountVlanMapDao.persist(any(AccountVlanMapVO.class))).thenReturn(new AccountVlanMapVO()); + + when(configurationMgr._vlanDao.acquireInLockTable(anyLong(), anyInt())).thenReturn(vlan); + + UserContext.registerContext(1, account, null, true); + + Field dedicateIdField = _dedicatePublicIpRangeClass.getDeclaredField("id"); + dedicateIdField.setAccessible(true); + dedicateIdField.set(dedicatePublicIpRangesCmd, 1L); + + Field accountNameField = _dedicatePublicIpRangeClass.getDeclaredField("accountName"); + accountNameField.setAccessible(true); + accountNameField.set(dedicatePublicIpRangesCmd, "accountname"); + + Field projectIdField = _dedicatePublicIpRangeClass.getDeclaredField("projectId"); + projectIdField.setAccessible(true); + projectIdField.set(dedicatePublicIpRangesCmd, null); + + Field domainIdField = _dedicatePublicIpRangeClass.getDeclaredField("domainId"); + domainIdField.setAccessible(true); + domainIdField.set(dedicatePublicIpRangesCmd, 1L); + + Field releaseIdField = _releasePublicIpRangeClass.getDeclaredField("id"); + releaseIdField.setAccessible(true); + releaseIdField.set(releasePublicIpRangesCmd, 1L); + } + + @Test + public void testDedicatePublicIpRange() throws Exception { + + s_logger.info("Running tests for DedicatePublicIpRange API"); + + /* + * TEST 1: given valid parameters DedicatePublicIpRange should succeed + */ + runDedicatePublicIpRangePostiveTest(); + + /* + * TEST 2: given invalid public ip range DedicatePublicIpRange should fail + */ + runDedicatePublicIpRangeInvalidRange(); + /* + * TEST 3: given public IP range that is already dedicated to a different account DedicatePublicIpRange should fail + */ + runDedicatePublicIpRangeDedicatedRange(); + + /* + * TEST 4: given zone is of type Basic DedicatePublicIpRange should fail + */ + runDedicatePublicIpRangeInvalidZone(); + + /* + * TEST 5: given range is already allocated to a different account DedicatePublicIpRange should fail + */ + runDedicatePublicIpRangeIPAdressAllocated(); + } + + @Test + public void testReleasePublicIpRange() throws Exception { + + s_logger.info("Running tests for DedicatePublicIpRange API"); + + /* + * TEST 1: given valid parameters and no allocated public ip's in the range ReleasePublicIpRange should succeed + */ + runReleasePublicIpRangePostiveTest1(); + + /* + * TEST 2: given valid parameters ReleasePublicIpRange should succeed + */ + runReleasePublicIpRangePostiveTest2(); + + /* + * TEST 3: given range doesn't exist + */ + runReleasePublicIpRangeInvalidIpRange(); + + /* + * TEST 4: given range is not dedicated to any account + */ + runReleaseNonDedicatedPublicIpRange(); + } + + void runDedicatePublicIpRangePostiveTest() throws Exception { + Transaction txn = Transaction.open("runDedicatePublicIpRangePostiveTest"); + + when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(vlan); + + when(configurationMgr._accountVlanMapDao.listAccountVlanMapsByAccount(anyLong())).thenReturn(null); + + DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24", + null, null, NetworkType.Advanced, null, null, true, true, null, null); + when(configurationMgr._zoneDao.findById(anyLong())).thenReturn(dc); + + List ipAddressList = new ArrayList(); + IPAddressVO ipAddress = new IPAddressVO(new Ip("75.75.75.75"), 1, 0xaabbccddeeffL, 10, false); + ipAddressList.add(ipAddress); + when(configurationMgr._publicIpAddressDao.listByVlanId(anyLong())).thenReturn(ipAddressList); + + try { + Vlan result = configurationMgr.dedicatePublicIpRange(dedicatePublicIpRangesCmd); + Assert.assertNotNull(result); + } catch (Exception e) { + s_logger.info("exception in testing runDedicatePublicIpRangePostiveTest message: " + e.toString()); + } finally { + txn.close("runDedicatePublicIpRangePostiveTest"); + } + } + + void runDedicatePublicIpRangeInvalidRange() throws Exception { + Transaction txn = Transaction.open("runDedicatePublicIpRangeInvalidRange"); + + when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(null); + try { + configurationMgr.dedicatePublicIpRange(dedicatePublicIpRangesCmd); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("Please specify a valid Public IP range id")); + } finally { + txn.close("runDedicatePublicIpRangeInvalidRange"); + } + } + + void runDedicatePublicIpRangeDedicatedRange() throws Exception { + Transaction txn = Transaction.open("runDedicatePublicIpRangeDedicatedRange"); + + when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(vlan); + + // public ip range is already dedicated + List accountVlanMaps = new ArrayList(); + AccountVlanMapVO accountVlanMap = new AccountVlanMapVO(1, 1); + accountVlanMaps.add(accountVlanMap); + when(configurationMgr._accountVlanMapDao.listAccountVlanMapsByVlan(anyLong())).thenReturn(accountVlanMaps); + + DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24", + null, null, NetworkType.Advanced, null, null, true, true, null, null); + when(configurationMgr._zoneDao.findById(anyLong())).thenReturn(dc); + + List ipAddressList = new ArrayList(); + IPAddressVO ipAddress = new IPAddressVO(new Ip("75.75.75.75"), 1, 0xaabbccddeeffL, 10, false); + ipAddressList.add(ipAddress); + when(configurationMgr._publicIpAddressDao.listByVlanId(anyLong())).thenReturn(ipAddressList); + + try { + configurationMgr.dedicatePublicIpRange(dedicatePublicIpRangesCmd); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("Public IP range has already been dedicated")); + } finally { + txn.close("runDedicatePublicIpRangePublicIpRangeDedicated"); + } + } + + void runDedicatePublicIpRangeInvalidZone() throws Exception { + Transaction txn = Transaction.open("runDedicatePublicIpRangeInvalidZone"); + + when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(vlan); + + when(configurationMgr._accountVlanMapDao.listAccountVlanMapsByVlan(anyLong())).thenReturn(null); + + // public ip range belongs to zone of type basic + DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24", + null, null, NetworkType.Basic, null, null, true, true, null, null); + when(configurationMgr._zoneDao.findById(anyLong())).thenReturn(dc); + + List ipAddressList = new ArrayList(); + IPAddressVO ipAddress = new IPAddressVO(new Ip("75.75.75.75"), 1, 0xaabbccddeeffL, 10, false); + ipAddressList.add(ipAddress); + when(configurationMgr._publicIpAddressDao.listByVlanId(anyLong())).thenReturn(ipAddressList); + + try { + configurationMgr.dedicatePublicIpRange(dedicatePublicIpRangesCmd); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("Public IP range can be dedicated to an account only in the zone of type Advanced")); + } finally { + txn.close("runDedicatePublicIpRangeInvalidZone"); + } + } + + void runDedicatePublicIpRangeIPAdressAllocated() throws Exception { + Transaction txn = Transaction.open("runDedicatePublicIpRangeIPAdressAllocated"); + + when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(vlan); + + when(configurationMgr._accountVlanMapDao.listAccountVlanMapsByAccount(anyLong())).thenReturn(null); + + DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24", + null, null, NetworkType.Advanced, null, null, true, true, null, null); + when(configurationMgr._zoneDao.findById(anyLong())).thenReturn(dc); + + // one of the ip addresses of the range is allocated to different account + List ipAddressList = new ArrayList(); + IPAddressVO ipAddress = new IPAddressVO(new Ip("75.75.75.75"), 1, 0xaabbccddeeffL, 10, false); + ipAddress.setAllocatedToAccountId(1L); + ipAddressList.add(ipAddress); + when(configurationMgr._publicIpAddressDao.listByVlanId(anyLong())).thenReturn(ipAddressList); + + try { + configurationMgr.dedicatePublicIpRange(dedicatePublicIpRangesCmd); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("Public IP address in range is already allocated to another account")); + } finally { + txn.close("runDedicatePublicIpRangeIPAdressAllocated"); + } + } + + void runReleasePublicIpRangePostiveTest1() throws Exception { + Transaction txn = Transaction.open("runReleasePublicIpRangePostiveTest1"); + + when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(vlan); + + List accountVlanMaps = new ArrayList(); + AccountVlanMapVO accountVlanMap = new AccountVlanMapVO(1, 1); + accountVlanMaps.add(accountVlanMap); + when(configurationMgr._accountVlanMapDao.listAccountVlanMapsByVlan(anyLong())).thenReturn(accountVlanMaps); + + // no allocated ip's + when(configurationMgr._publicIpAddressDao.countIPs(anyLong(), anyLong(), anyBoolean())).thenReturn(0); + + when(configurationMgr._accountVlanMapDao.remove(anyLong())).thenReturn(true); + try { + Boolean result = configurationMgr.releasePublicIpRange(releasePublicIpRangesCmd); + Assert.assertTrue(result); + } catch (Exception e) { + s_logger.info("exception in testing runReleasePublicIpRangePostiveTest1 message: " + e.toString()); + } finally { + txn.close("runReleasePublicIpRangePostiveTest1"); + } + } + + void runReleasePublicIpRangePostiveTest2() throws Exception { + Transaction txn = Transaction.open("runReleasePublicIpRangePostiveTest2"); + + when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(vlan); + + List accountVlanMaps = new ArrayList(); + AccountVlanMapVO accountVlanMap = new AccountVlanMapVO(1, 1); + accountVlanMaps.add(accountVlanMap); + when(configurationMgr._accountVlanMapDao.listAccountVlanMapsByVlan(anyLong())).thenReturn(accountVlanMaps); + + when(configurationMgr._publicIpAddressDao.countIPs(anyLong(), anyLong(), anyBoolean())).thenReturn(1); + + List ipAddressList = new ArrayList(); + IPAddressVO ipAddress = new IPAddressVO(new Ip("75.75.75.75"), 1, 0xaabbccddeeffL, 10, false); + ipAddressList.add(ipAddress); + when(configurationMgr._publicIpAddressDao.listByVlanId(anyLong())).thenReturn(ipAddressList); + + when(configurationMgr._firewallDao.countRulesByIpId(anyLong())).thenReturn(0L); + + when(configurationMgr._networkMgr.disassociatePublicIpAddress(anyLong(), anyLong(), any(Account.class))).thenReturn(true); + + when(configurationMgr._vlanDao.releaseFromLockTable(anyLong())).thenReturn(true); + + when(configurationMgr._accountVlanMapDao.remove(anyLong())).thenReturn(true); + try { + Boolean result = configurationMgr.releasePublicIpRange(releasePublicIpRangesCmd); + Assert.assertTrue(result); + } catch (Exception e) { + s_logger.info("exception in testing runReleasePublicIpRangePostiveTest2 message: " + e.toString()); + } finally { + txn.close("runReleasePublicIpRangePostiveTest2"); + } + } + + void runReleasePublicIpRangeInvalidIpRange() throws Exception { + Transaction txn = Transaction.open("runReleasePublicIpRangeInvalidIpRange"); + + when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(null); + try { + configurationMgr.releasePublicIpRange(releasePublicIpRangesCmd); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("Please specify a valid IP range id")); + } finally { + txn.close("runReleasePublicIpRangeInvalidIpRange"); + } + } + + void runReleaseNonDedicatedPublicIpRange() throws Exception { + Transaction txn = Transaction.open("runReleaseNonDedicatedPublicIpRange"); + + when(configurationMgr._vlanDao.findById(anyLong())).thenReturn(vlan); + + when(configurationMgr._accountVlanMapDao.listAccountVlanMapsByVlan(anyLong())).thenReturn(null); + try { + configurationMgr.releasePublicIpRange(releasePublicIpRangesCmd); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains("as it not dedicated to any account")); + } finally { + txn.close("runReleaseNonDedicatedPublicIpRange"); + } + } + + + public class DedicatePublicIpRangeCmdExtn extends DedicatePublicIpRangeCmd { + public long getEntityOwnerId() { + return 1; + } + } + + public class ReleasePublicIpRangeCmdExtn extends ReleasePublicIpRangeCmd { + public long getEntityOwnerId() { + return 1; + } + } +} diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java index 18eae085879..9042f03d4a7 100755 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java @@ -16,33 +16,13 @@ // under the License. package com.cloud.network; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.ejb.Local; -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; -import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; -import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; -import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; -import org.springframework.stereotype.Component; -import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; - import com.cloud.dc.DataCenter; import com.cloud.dc.Pod; import com.cloud.dc.Vlan.VlanType; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientAddressCapacityException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InsufficientVirtualNetworkCapcityException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.*; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.Networks.TrafficType; @@ -62,7 +42,6 @@ import com.cloud.offerings.NetworkOfferingVO; import com.cloud.user.Account; import com.cloud.user.User; import com.cloud.utils.Pair; -import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.vm.Nic; import com.cloud.vm.NicProfile; @@ -74,6 +53,19 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Type; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.VirtualMachineProfileImpl; +import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; +import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; +import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; +import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; +import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import javax.naming.ConfigurationException; +import java.util.List; +import java.util.Map; +import java.util.Set; @Component @Local(value = { NetworkManager.class, NetworkService.class }) @@ -824,7 +816,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage * @see com.cloud.network.NetworkService#allocateIP(com.cloud.user.Account, boolean, long) */ @Override - public IpAddress allocateIP(Account ipOwner, boolean isSystem, long zoneId) throws ResourceAllocationException, + public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { // TODO Auto-generated method stub return null; diff --git a/server/test/com/cloud/vm/MockUserVmManagerImpl.java b/server/test/com/cloud/vm/MockUserVmManagerImpl.java index dd8dd83df58..fd826d9e86e 100644 --- a/server/test/com/cloud/vm/MockUserVmManagerImpl.java +++ b/server/test/com/cloud/vm/MockUserVmManagerImpl.java @@ -253,13 +253,13 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager, // TODO Auto-generated method stub return null; } - + @Override public UserVm removeNicFromVirtualMachine(RemoveNicFromVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, CloudRuntimeException { // TODO Auto-generated method stub return null; } - + @Override public UserVm updateDefaultNicForVirtualMachine(UpdateDefaultNicForVMCmd cmd) throws InvalidParameterValueException, CloudRuntimeException { // TODO Auto-generated method stub @@ -330,7 +330,9 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager, @Override public UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map requestedIps, - IpAddresses defaultIp, String keyboard) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, + IpAddresses defaultIp, + String keyboard, List affinityGroupIdList) throws InsufficientCapacityException, + ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException { // TODO Auto-generated method stub return null; @@ -339,7 +341,9 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager, @Override public UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List networkIdList, List securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, - String sshKeyPair, Map requestedIps, IpAddresses defaultIps, String keyboard) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, + String sshKeyPair, Map requestedIps, + IpAddresses defaultIps, String keyboard, List affinityGroupIdList) + throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException { // TODO Auto-generated method stub return null; @@ -348,7 +352,9 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager, @Override public UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List networkIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, String userData, String sshKeyPair, Map requestedIps, IpAddresses defaultIps, - String keyboard) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException { + String keyboard, List affinityGroupIdList) throws InsufficientCapacityException, + ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, + ResourceAllocationException { // TODO Auto-generated method stub return null; } diff --git a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java old mode 100644 new mode 100755 index d96e831cfeb..a03e361d8c1 --- a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java +++ b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java @@ -40,7 +40,9 @@ import org.apache.cloudstack.api.command.admin.offering.UpdateServiceOfferingCmd import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd; import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd; import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd; +import org.apache.cloudstack.api.command.admin.vlan.DedicatePublicIpRangeCmd; import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd; +import org.apache.cloudstack.api.command.admin.vlan.ReleasePublicIpRangeCmd; 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.UpdateZoneCmd; @@ -433,7 +435,7 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu */ @Override public ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, Type vm_typeType, String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired, boolean offerHA, - boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate) { + boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner) { // TODO Auto-generated method stub return null; } @@ -544,7 +546,7 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu * @see com.cloud.configuration.ConfigurationManager#deleteAccountSpecificVirtualRanges(long) */ @Override - public boolean deleteAccountSpecificVirtualRanges(long accountId) { + public boolean releaseAccountSpecificVirtualRanges(long accountId) { // TODO Auto-generated method stub return false; } @@ -613,5 +615,24 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu return null; } + @Override + public Vlan dedicatePublicIpRange(DedicatePublicIpRangeCmd cmd) + throws ResourceAllocationException { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean releasePublicIpRange(ReleasePublicIpRangeCmd cmd) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean releasePublicIpRange(long userId, long vlanDbId, + Account caller) { + // TODO Auto-generated method stub + return false; + } } diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index bd4fd678d48..3a585ce708a 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -16,49 +16,17 @@ // under the License. package com.cloud.vpc; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.ejb.Local; -import javax.inject.Inject; -import javax.naming.ConfigurationException; - -import org.apache.cloudstack.acl.ControlledEntity.ACLType; -import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; -import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; -import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; -import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; -import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; -import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; - import com.cloud.dc.DataCenter; import com.cloud.dc.Pod; import com.cloud.dc.Vlan.VlanType; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientAddressCapacityException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InsufficientVirtualNetworkCapcityException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.exception.ResourceUnavailableException; -import com.cloud.network.IpAddress; -import com.cloud.network.Network; +import com.cloud.exception.*; +import com.cloud.network.*; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; -import com.cloud.network.NetworkManager; -import com.cloud.network.NetworkProfile; -import com.cloud.network.NetworkRuleApplier; -import com.cloud.network.NetworkService; import com.cloud.network.Networks.TrafficType; -import com.cloud.network.PhysicalNetwork; -import com.cloud.network.PhysicalNetworkServiceProvider; -import com.cloud.network.PhysicalNetworkTrafficType; -import com.cloud.network.PublicIpAddress; -import com.cloud.network.UserIpv6Address; import com.cloud.network.addr.PublicIp; import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.NetworkServiceMapDao; @@ -78,7 +46,6 @@ import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; import com.cloud.user.Account; import com.cloud.user.User; import com.cloud.utils.Pair; -import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.vm.Nic; import com.cloud.vm.NicProfile; @@ -90,6 +57,21 @@ import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Type; import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.VirtualMachineProfileImpl; +import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; +import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; +import org.apache.cloudstack.api.command.user.network.ListNetworksCmd; +import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd; +import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; @Component @Local(value = { NetworkManager.class, NetworkService.class }) @@ -188,7 +170,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage * @see com.cloud.network.NetworkService#allocateIP(com.cloud.user.Account, long, java.lang.Long) */ @Override - public IpAddress allocateIP(Account ipOwner, boolean isSystem, long networkId) throws ResourceAllocationException, + public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { // TODO Auto-generated method stub return null; diff --git a/server/test/org/apache/cloudstack/affinity/AffinityApiTestConfiguration.java b/server/test/org/apache/cloudstack/affinity/AffinityApiTestConfiguration.java new file mode 100644 index 00000000000..fb294697cc6 --- /dev/null +++ b/server/test/org/apache/cloudstack/affinity/AffinityApiTestConfiguration.java @@ -0,0 +1,344 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity; + +import java.io.IOException; + +import org.apache.cloudstack.acl.SecurityChecker; +import org.apache.cloudstack.affinity.dao.AffinityGroupDao; +import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDaoImpl; +import org.mockito.Mockito; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; +import org.springframework.context.annotation.ComponentScan.Filter; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.core.type.filter.TypeFilter; +import com.cloud.utils.component.ComponentContext; +import com.cloud.agent.AgentManager; +import com.cloud.alert.AlertManager; +import com.cloud.api.query.dao.UserAccountJoinDaoImpl; +import com.cloud.capacity.dao.CapacityDaoImpl; +import com.cloud.cluster.agentlb.dao.HostTransferMapDaoImpl; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.dao.AccountVlanMapDaoImpl; +import com.cloud.dc.dao.ClusterDaoImpl; +import com.cloud.dc.dao.DataCenterDaoImpl; +import com.cloud.dc.dao.DataCenterIpAddressDaoImpl; +import com.cloud.dc.dao.DataCenterLinkLocalIpAddressDao; +import com.cloud.dc.dao.DataCenterLinkLocalIpAddressDaoImpl; +import com.cloud.dc.dao.DataCenterVnetDaoImpl; +import com.cloud.dc.dao.DcDetailsDaoImpl; +import com.cloud.dc.dao.HostPodDaoImpl; +import com.cloud.dc.dao.PodVlanDaoImpl; +import com.cloud.dc.dao.PodVlanMapDaoImpl; +import com.cloud.dc.dao.VlanDaoImpl; +import com.cloud.domain.dao.DomainDaoImpl; +import com.cloud.event.EventUtils; +import com.cloud.event.dao.EventDao; +import com.cloud.event.dao.EventDaoImpl; +import com.cloud.event.dao.UsageEventDaoImpl; +import com.cloud.host.dao.HostDaoImpl; +import com.cloud.host.dao.HostDetailsDaoImpl; +import com.cloud.host.dao.HostTagsDaoImpl; +import com.cloud.network.Ipv6AddressManager; +import com.cloud.network.NetworkManager; +import com.cloud.network.NetworkModel; +import com.cloud.network.NetworkService; +import com.cloud.network.StorageNetworkManager; +import com.cloud.network.dao.FirewallRulesCidrsDaoImpl; +import com.cloud.network.dao.FirewallRulesDaoImpl; +import com.cloud.network.dao.IPAddressDaoImpl; +import com.cloud.network.dao.LoadBalancerDaoImpl; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.NetworkDomainDaoImpl; +import com.cloud.network.dao.NetworkServiceMapDaoImpl; +import com.cloud.network.dao.PhysicalNetworkDaoImpl; +import com.cloud.network.dao.PhysicalNetworkServiceProviderDaoImpl; +import com.cloud.network.dao.PhysicalNetworkTrafficTypeDaoImpl; +import com.cloud.network.dao.UserIpv6AddressDaoImpl; +import com.cloud.network.element.DhcpServiceProvider; +import com.cloud.network.element.IpDeployer; +import com.cloud.network.element.NetworkElement; +import com.cloud.network.guru.NetworkGuru; +import com.cloud.network.lb.LoadBalancingRulesManager; +import com.cloud.network.rules.FirewallManager; +import com.cloud.network.rules.RulesManager; +import com.cloud.network.rules.dao.PortForwardingRulesDaoImpl; +import com.cloud.network.vpc.NetworkACLManager; +import com.cloud.network.vpc.VpcManager; +import com.cloud.network.vpc.dao.PrivateIpDaoImpl; +import com.cloud.network.vpn.RemoteAccessVpnService; +import com.cloud.offerings.dao.NetworkOfferingDao; +import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; +import com.cloud.projects.ProjectManager; +import com.cloud.service.dao.ServiceOfferingDaoImpl; +import com.cloud.storage.dao.DiskOfferingDaoImpl; +import com.cloud.storage.dao.S3DaoImpl; +import com.cloud.storage.dao.SnapshotDaoImpl; +import com.cloud.storage.dao.StoragePoolDetailsDaoImpl; +import com.cloud.storage.dao.SwiftDaoImpl; +import com.cloud.storage.dao.VolumeDaoImpl; +import com.cloud.storage.s3.S3Manager; +import com.cloud.storage.secondary.SecondaryStorageVmManager; +import com.cloud.storage.swift.SwiftManager; +import com.cloud.tags.dao.ResourceTagsDaoImpl; +import com.cloud.user.AccountManager; +import com.cloud.user.ResourceLimitService; +import com.cloud.user.UserContext; +import com.cloud.user.UserContextInitializer; +import com.cloud.user.dao.AccountDao; +import com.cloud.user.dao.AccountDaoImpl; +import com.cloud.user.dao.UserDaoImpl; +import com.cloud.utils.component.SpringComponentScanUtils; +import com.cloud.utils.db.GenericDao; +import com.cloud.utils.db.GenericDaoBase; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.dao.InstanceGroupDaoImpl; +import com.cloud.vm.dao.NicDaoImpl; +import com.cloud.vm.dao.NicSecondaryIpDaoImpl; +import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.dao.VMInstanceDaoImpl; + +@Configuration +@ComponentScan(basePackageClasses = { AccountVlanMapDaoImpl.class, VolumeDaoImpl.class, HostPodDaoImpl.class, + DomainDaoImpl.class, SwiftDaoImpl.class, ServiceOfferingDaoImpl.class, VlanDaoImpl.class, + IPAddressDaoImpl.class, ResourceTagsDaoImpl.class, InstanceGroupDaoImpl.class, + UserAccountJoinDaoImpl.class, CapacityDaoImpl.class, SnapshotDaoImpl.class, HostDaoImpl.class, + VMInstanceDaoImpl.class, HostTransferMapDaoImpl.class, PortForwardingRulesDaoImpl.class, + PrivateIpDaoImpl.class, UsageEventDaoImpl.class, PodVlanMapDaoImpl.class, DiskOfferingDaoImpl.class, + DataCenterDaoImpl.class, DataCenterIpAddressDaoImpl.class, + DataCenterVnetDaoImpl.class, PodVlanDaoImpl.class, DcDetailsDaoImpl.class, NicSecondaryIpDaoImpl.class, + UserIpv6AddressDaoImpl.class, S3DaoImpl.class, UserDaoImpl.class, NicDaoImpl.class, NetworkDomainDaoImpl.class, + HostDetailsDaoImpl.class, HostTagsDaoImpl.class, ClusterDaoImpl.class, FirewallRulesDaoImpl.class, + FirewallRulesCidrsDaoImpl.class, PhysicalNetworkDaoImpl.class, PhysicalNetworkTrafficTypeDaoImpl.class, + PhysicalNetworkServiceProviderDaoImpl.class, LoadBalancerDaoImpl.class, NetworkServiceMapDaoImpl.class, + PrimaryDataStoreDaoImpl.class, StoragePoolDetailsDaoImpl.class, AffinityGroupServiceImpl.class, + ComponentContext.class, AffinityGroupProcessor.class, UserVmVO.class, EventUtils.class, UserVmVO.class + }, includeFilters = { @Filter(value = AffinityApiTestConfiguration.Library.class, type = FilterType.CUSTOM) }, useDefaultFilters = false) +public class AffinityApiTestConfiguration { + + @Bean + public AccountDao accountDao() { + return Mockito.mock(AccountDao.class); + } + + @Bean + public EventUtils eventUtils() { + return Mockito.mock(EventUtils.class); + } + + @Bean + public AffinityGroupProcessor affinityGroupProcessor() { + return Mockito.mock(AffinityGroupProcessor.class); + } + + @Bean + public ComponentContext componentContext() { + return Mockito.mock(ComponentContext.class); + } + + + @Bean + public UserContextInitializer userContextInitializer() { + return Mockito.mock(UserContextInitializer.class); + } + + @Bean + public UserVmVO userVmVO() { + return Mockito.mock(UserVmVO.class); + } + + @Bean + public AffinityGroupDao affinityGroupDao() { + return Mockito.mock(AffinityGroupDao.class); + } + + @Bean + public AffinityGroupVMMapDao affinityGroupVMMapDao() { + return Mockito.mock(AffinityGroupVMMapDao.class); + } + + @Bean + public AccountManager acctMgr() { + return Mockito.mock(AccountManager.class); + } + + @Bean + public NetworkService ntwkSvc() { + return Mockito.mock(NetworkService.class); + } + + @Bean + public NetworkModel ntwkMdl() { + return Mockito.mock(NetworkModel.class); + } + + @Bean + public AlertManager alertMgr() { + return Mockito.mock(AlertManager.class); + } + + @Bean + public SecurityChecker securityChkr() { + return Mockito.mock(SecurityChecker.class); + } + + @Bean + public ResourceLimitService resourceSvc() { + return Mockito.mock(ResourceLimitService.class); + } + + @Bean + public ProjectManager projectMgr() { + return Mockito.mock(ProjectManager.class); + } + + @Bean + public SecondaryStorageVmManager ssvmMgr() { + return Mockito.mock(SecondaryStorageVmManager.class); + } + + @Bean + public SwiftManager swiftMgr() { + return Mockito.mock(SwiftManager.class); + } + + @Bean + public S3Manager s3Mgr() { + return Mockito.mock(S3Manager.class); + } + + @Bean + public VpcManager vpcMgr() { + return Mockito.mock(VpcManager.class); + } + + @Bean + public UserVmDao userVMDao() { + return Mockito.mock(UserVmDao.class); + } + + @Bean + public RulesManager rulesMgr() { + return Mockito.mock(RulesManager.class); + } + + @Bean + public LoadBalancingRulesManager lbRulesMgr() { + return Mockito.mock(LoadBalancingRulesManager.class); + } + + @Bean + public RemoteAccessVpnService vpnMgr() { + return Mockito.mock(RemoteAccessVpnService.class); + } + + @Bean + public NetworkGuru ntwkGuru() { + return Mockito.mock(NetworkGuru.class); + } + + @Bean + public NetworkElement ntwkElement() { + return Mockito.mock(NetworkElement.class); + } + + @Bean + public IpDeployer ipDeployer() { + return Mockito.mock(IpDeployer.class); + } + + @Bean + public DhcpServiceProvider dhcpProvider() { + return Mockito.mock(DhcpServiceProvider.class); + } + + @Bean + public FirewallManager firewallMgr() { + return Mockito.mock(FirewallManager.class); + } + + @Bean + public AgentManager agentMgr() { + return Mockito.mock(AgentManager.class); + } + + @Bean + public StorageNetworkManager storageNtwkMgr() { + return Mockito.mock(StorageNetworkManager.class); + } + + @Bean + public NetworkACLManager ntwkAclMgr() { + return Mockito.mock(NetworkACLManager.class); + } + + @Bean + public Ipv6AddressManager ipv6Mgr() { + return Mockito.mock(Ipv6AddressManager.class); + } + + @Bean + public ConfigurationDao configDao() { + return Mockito.mock(ConfigurationDao.class); + } + + @Bean + public NetworkManager networkManager() { + return Mockito.mock(NetworkManager.class); + } + + @Bean + public NetworkOfferingDao networkOfferingDao() { + return Mockito.mock(NetworkOfferingDao.class); + } + + @Bean + public EventDao eventDao() { + return Mockito.mock(EventDao.class); + } + + @Bean + public NetworkDao networkDao() { + return Mockito.mock(NetworkDao.class); + } + + @Bean + public NetworkOfferingServiceMapDao networkOfferingServiceMapDao() { + return Mockito.mock(NetworkOfferingServiceMapDao.class); + } + + @Bean + public DataCenterLinkLocalIpAddressDao datacenterLinkLocalIpAddressDao() { + return Mockito.mock(DataCenterLinkLocalIpAddressDao.class); + } + + public static class Library implements TypeFilter { + + @Override + public boolean match(MetadataReader mdr, MetadataReaderFactory arg1) throws IOException { + mdr.getClassMetadata().getClassName(); + ComponentScan cs = AffinityApiTestConfiguration.class.getAnnotation(ComponentScan.class); + return SpringComponentScanUtils.includedInBasePackageClasses(mdr.getClassMetadata().getClassName(), cs); + } + + } +} diff --git a/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java b/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java new file mode 100644 index 00000000000..a5e6d15bf0b --- /dev/null +++ b/server/test/org/apache/cloudstack/affinity/AffinityApiUnitTest.java @@ -0,0 +1,187 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package org.apache.cloudstack.affinity; + +import static org.junit.Assert.*; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Mockito.*; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.cloudstack.affinity.dao.AffinityGroupDao; +import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.cloud.event.EventUtils; +import com.cloud.event.EventVO; +import com.cloud.event.dao.EventDao; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ResourceInUseException; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.user.Account; +import com.cloud.user.AccountManager; +import com.cloud.user.AccountVO; +import com.cloud.user.UserContext; +import com.cloud.user.dao.AccountDao; +import com.cloud.utils.component.ComponentContext; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.dao.UserVmDao; + +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "classpath:/affinityContext.xml") +public class AffinityApiUnitTest { + + @Inject + AffinityGroupServiceImpl _affinityService; + + @Inject + AccountManager _acctMgr; + + @Inject + AffinityGroupProcessor _processor; + + @Inject + AffinityGroupDao _groupDao; + + @Inject + UserVmDao _vmDao; + + @Inject + AffinityGroupVMMapDao _affinityGroupVMMapDao; + + @Inject + AffinityGroupDao _affinityGroupDao; + + @Inject + EventUtils _eventUtils; + + @Inject + AccountDao _accountDao; + + @Inject + EventDao _eventDao; + + private static long domainId = 5L; + + + @BeforeClass + public static void setUp() throws ConfigurationException { + + } + + @Before + public void testSetUp() { + ComponentContext.initComponentsLifeCycle(); + AccountVO acct = new AccountVO(200L); + acct.setType(Account.ACCOUNT_TYPE_NORMAL); + acct.setAccountName("user"); + acct.setDomainId(domainId); + + UserContext.registerContext(1, acct, null, true); + + when(_acctMgr.finalizeOwner((Account) anyObject(), anyString(), anyLong(), anyLong())).thenReturn(acct); + when(_processor.getType()).thenReturn("mock"); + when(_accountDao.findByIdIncludingRemoved(0L)).thenReturn(acct); + + AffinityGroupVO group = new AffinityGroupVO("group1", "mock", "mock group", domainId, 200L); + Mockito.when(_affinityGroupDao.persist(Mockito.any(AffinityGroupVO.class))).thenReturn(group); + Mockito.when(_affinityGroupDao.findById(Mockito.anyLong())).thenReturn(group); + Mockito.when(_affinityGroupDao.findByAccountAndName(Mockito.anyLong(), Mockito.anyString())).thenReturn(group); + Mockito.when(_affinityGroupDao.lockRow(Mockito.anyLong(), anyBoolean())).thenReturn(group); + Mockito.when(_affinityGroupDao.expunge(Mockito.anyLong())).thenReturn(true); + Mockito.when(_eventDao.persist(Mockito.any(EventVO.class))).thenReturn(new EventVO()); + } + + @Test + public void createAffinityGroupTest() { + AffinityGroup group = _affinityService.createAffinityGroup("user", domainId, "group1", "mock", + "affinity group one"); + assertNotNull("Affinity group 'group1' of type 'mock' failed to create ", group); + + } + + @Test(expected = InvalidParameterValueException.class) + public void invalidAffinityTypeTest() { + AffinityGroup group = _affinityService.createAffinityGroup("user", domainId, "group1", "invalid", + "affinity group one"); + + } + + @Test(expected = InvalidParameterValueException.class) + public void uniqueAffinityNameTest() { + when(_groupDao.isNameInUse(anyLong(), anyLong(), eq("group1"))).thenReturn(true); + AffinityGroup group2 = _affinityService.createAffinityGroup("user", domainId, "group1", "mock", + "affinity group two"); + } + + @Test(expected = InvalidParameterValueException.class) + public void deleteAffinityGroupInvalidIdTest() throws ResourceInUseException { + when(_groupDao.findById(20L)).thenReturn(null); + _affinityService.deleteAffinityGroup(20L, "user", domainId, "group1"); + } + + @Test(expected = InvalidParameterValueException.class) + public void deleteAffinityGroupInvalidIdName() throws ResourceInUseException { + when(_groupDao.findByAccountAndName(200L, "group1")).thenReturn(null); + _affinityService.deleteAffinityGroup(null, "user", domainId, "group1"); + } + + @Test(expected = InvalidParameterValueException.class) + public void deleteAffinityGroupNullIdName() throws ResourceInUseException { + _affinityService.deleteAffinityGroup(null, "user", domainId, null); + } + + @Test(expected = ResourceInUseException.class) + public void deleteAffinityGroupInUse() throws ResourceInUseException { + List affinityGroupVmMap = new ArrayList(); + AffinityGroupVMMapVO mapVO = new AffinityGroupVMMapVO(20L, 10L); + affinityGroupVmMap.add(mapVO); + when(_affinityGroupVMMapDao.listByAffinityGroup(20L)).thenReturn(affinityGroupVmMap); + + AffinityGroupVO groupVO = new AffinityGroupVO(); + when(_groupDao.findById(20L)).thenReturn(groupVO); + when(_groupDao.lockRow(20L, true)).thenReturn(groupVO); + + _affinityService.deleteAffinityGroup(20L, "user", domainId, null); + } + + @Test(expected = InvalidParameterValueException.class) + public void updateAffinityGroupVMRunning() throws ResourceInUseException { + + UserVmVO vm = new UserVmVO(10L, "test", "test", 101L, HypervisorType.Any, 21L, false, false, domainId, 200L, + 5L, "", "test", 1L); + vm.setState(VirtualMachine.State.Running); + when(_vmDao.findById(10L)).thenReturn(vm); + + List affinityGroupIds = new ArrayList(); + affinityGroupIds.add(20L); + + _affinityService.updateVMAffinityGroups(10L, affinityGroupIds); + } + +} diff --git a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java index 895a5d4416d..f1163ef35ee 100644 --- a/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java +++ b/server/test/org/apache/cloudstack/networkoffering/ChildTestConfiguration.java @@ -41,6 +41,7 @@ import com.cloud.dc.dao.AccountVlanMapDaoImpl; import com.cloud.dc.dao.ClusterDaoImpl; import com.cloud.dc.dao.DataCenterDaoImpl; import com.cloud.dc.dao.DataCenterIpAddressDaoImpl; +import com.cloud.dc.dao.DataCenterLinkLocalIpAddressDao; import com.cloud.dc.dao.DataCenterLinkLocalIpAddressDaoImpl; import com.cloud.dc.dao.DataCenterVnetDaoImpl; import com.cloud.dc.dao.DcDetailsDaoImpl; @@ -135,7 +136,6 @@ import com.cloud.vm.dao.VMInstanceDaoImpl; DiskOfferingDaoImpl.class, DataCenterDaoImpl.class, DataCenterIpAddressDaoImpl.class, - DataCenterLinkLocalIpAddressDaoImpl.class, DataCenterVnetDaoImpl.class, PodVlanDaoImpl.class, DcDetailsDaoImpl.class, @@ -319,6 +319,11 @@ public class ChildTestConfiguration { return Mockito.mock(NetworkOfferingServiceMapDao.class); } + @Bean + public DataCenterLinkLocalIpAddressDao datacenterLinkLocalIpAddressDao() { + return Mockito.mock(DataCenterLinkLocalIpAddressDao.class); + } + public static class Library implements TypeFilter { @Override diff --git a/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java b/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java index 67fae3349c1..cbb6c00e397 100644 --- a/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java +++ b/server/test/org/apache/cloudstack/networkoffering/CreateNetworkOfferingTest.java @@ -49,7 +49,6 @@ import com.cloud.offerings.dao.NetworkOfferingServiceMapDao; import com.cloud.user.AccountManager; import com.cloud.user.AccountVO; import com.cloud.user.UserContext; -import com.cloud.user.UserContextInitializer; import com.cloud.user.UserVO; import com.cloud.utils.component.ComponentContext; diff --git a/server/test/resources/affinityContext.xml b/server/test/resources/affinityContext.xml new file mode 100644 index 00000000000..15476c1a1b3 --- /dev/null +++ b/server/test/resources/affinityContext.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/server/test/resources/network-mgr-component.xml b/server/test/resources/network-mgr-component.xml index 42d3c2ebdb1..b55a68b0fcf 100644 --- a/server/test/resources/network-mgr-component.xml +++ b/server/test/resources/network-mgr-component.xml @@ -78,7 +78,7 @@ under the License. - + diff --git a/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyPasswordBasedEncryptor.java b/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyPasswordBasedEncryptor.java index 29826f0ea92..5a7241ac7e5 100644 --- a/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyPasswordBasedEncryptor.java +++ b/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyPasswordBasedEncryptor.java @@ -16,13 +16,16 @@ // under the License. package com.cloud.consoleproxy; +import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; @@ -33,110 +36,162 @@ import com.google.gson.GsonBuilder; /** * - * A simple password based encyrptor based on DES. It can serialize simple POJO object into URL safe string + * @author Kelven Yang + * A simple password based encyrptor based on AES/CBC. It can serialize simple POJO object into URL safe string * and deserialize it back. * */ public class ConsoleProxyPasswordBasedEncryptor { - private static final Logger s_logger = Logger.getLogger(ConsoleProxyPasswordBasedEncryptor.class); - - private String password; - private Gson gson; - - public ConsoleProxyPasswordBasedEncryptor(String password) { - this.password = password; - gson = new GsonBuilder().create(); - } - - public String encryptText(String text) { - if(text == null || text.isEmpty()) - return text; - - assert(password != null); - assert(!password.isEmpty()); - - try { - Cipher cipher = Cipher.getInstance("DES"); - int maxKeySize = 8; - SecretKeySpec keySpec = new SecretKeySpec(normalizeKey(password.getBytes(), maxKeySize), "DES"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec); - byte[] encryptedBytes = cipher.doFinal(text.getBytes()); - return Base64.encodeBase64URLSafeString(encryptedBytes); - } catch (NoSuchAlgorithmException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (NoSuchPaddingException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (IllegalBlockSizeException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (BadPaddingException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (InvalidKeyException e) { - s_logger.error("Unexpected exception ", e); - return null; - } - } + private static final Logger s_logger = Logger.getLogger(ConsoleProxyPasswordBasedEncryptor.class); + + private Gson gson; + + // key/IV will be set in 128 bit strength + private KeyIVPair keyIvPair; + + public ConsoleProxyPasswordBasedEncryptor(String password) { + gson = new GsonBuilder().create(); + keyIvPair = gson.fromJson(password, KeyIVPair.class); + } + + public String encryptText(String text) { + if(text == null || text.isEmpty()) + return text; + + try { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKeySpec keySpec = new SecretKeySpec(keyIvPair.getKeyBytes(), "AES"); - public String decryptText(String encryptedText) { - if(encryptedText == null || encryptedText.isEmpty()) - return encryptedText; + cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(keyIvPair.getIvBytes())); + + byte[] encryptedBytes = cipher.doFinal(text.getBytes()); + return Base64.encodeBase64URLSafeString(encryptedBytes); + } catch (NoSuchAlgorithmException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (NoSuchPaddingException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (IllegalBlockSizeException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (BadPaddingException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (InvalidKeyException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (InvalidAlgorithmParameterException e) { + s_logger.error("Unexpected exception ", e); + return null; + } + } - assert(password != null); - assert(!password.isEmpty()); + public String decryptText(String encryptedText) { + if(encryptedText == null || encryptedText.isEmpty()) + return encryptedText; - try { - Cipher cipher = Cipher.getInstance("DES"); - int maxKeySize = 8; - SecretKeySpec keySpec = new SecretKeySpec(normalizeKey(password.getBytes(), maxKeySize), "DES"); - cipher.init(Cipher.DECRYPT_MODE, keySpec); - - byte[] encryptedBytes = Base64.decodeBase64(encryptedText); - return new String(cipher.doFinal(encryptedBytes)); - } catch (NoSuchAlgorithmException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (NoSuchPaddingException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (IllegalBlockSizeException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (BadPaddingException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (InvalidKeyException e) { - s_logger.error("Unexpected exception ", e); - return null; - } - } - - public String encryptObject(Class clz, T obj) { - if(obj == null) - return null; - - String json = gson.toJson(obj); - return encryptText(json); - } - - @SuppressWarnings("unchecked") - public T decryptObject(Class clz, String encrypted) { - if(encrypted == null || encrypted.isEmpty()) - return null; - - String json = decryptText(encrypted); - return (T)gson.fromJson(json, clz); - } - - private static byte[] normalizeKey(byte[] keyBytes, int keySize) { - assert(keySize > 0); - byte[] key = new byte[keySize]; - - for(int i = 0; i < keyBytes.length; i++) - key[i%keySize] ^= keyBytes[i]; - - return key; - } + try { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKeySpec keySpec = new SecretKeySpec(keyIvPair.getKeyBytes(), "AES"); + cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(keyIvPair.getIvBytes())); + + byte[] encryptedBytes = Base64.decodeBase64(encryptedText); + return new String(cipher.doFinal(encryptedBytes)); + } catch (NoSuchAlgorithmException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (NoSuchPaddingException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (IllegalBlockSizeException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (BadPaddingException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (InvalidKeyException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (InvalidAlgorithmParameterException e) { + s_logger.error("Unexpected exception ", e); + return null; + } + } + + public String encryptObject(Class clz, T obj) { + if(obj == null) + return null; + + String json = gson.toJson(obj); + return encryptText(json); + } + + @SuppressWarnings("unchecked") + public T decryptObject(Class clz, String encrypted) { + if(encrypted == null || encrypted.isEmpty()) + return null; + + String json = decryptText(encrypted); + return (T)gson.fromJson(json, clz); + } + + public static class KeyIVPair { + String base64EncodedKeyBytes; + String base64EncodedIvBytes; + + public KeyIVPair() { + } + + public KeyIVPair(String base64EncodedKeyBytes, String base64EncodedIvBytes) { + this.base64EncodedKeyBytes = base64EncodedKeyBytes; + this.base64EncodedIvBytes = base64EncodedIvBytes; + } + + public byte[] getKeyBytes() { + return Base64.decodeBase64(base64EncodedKeyBytes); + } + + public void setKeyBytes(byte[] keyBytes) { + base64EncodedKeyBytes = Base64.encodeBase64URLSafeString(keyBytes); + } + + public byte[] getIvBytes() { + return Base64.decodeBase64(base64EncodedIvBytes); + } + + public void setIvBytes(byte[] ivBytes) { + base64EncodedIvBytes = Base64.encodeBase64URLSafeString(ivBytes); + } + } + + public static void main(String[] args) { + SecureRandom random; + try { + random = SecureRandom.getInstance("SHA1PRNG"); + byte[] keyBytes = new byte[16]; + random.nextBytes(keyBytes); + + byte[] ivBytes = new byte[16]; + random.nextBytes(ivBytes); + + KeyIVPair keyIvPair = new KeyIVPair("8x/xUBgX0Up+3UEo39dSeG277JhVj31+ElHkN5+EC0Q=", "Y2SUiIN6JXTdKNK/ZMDyVtLB7gAM9MCCiyrP1xd3bSQ="); + //keyIvPair.setKeyBytes(keyBytes); + //keyIvPair.setIvBytes(ivBytes); + + Gson gson = new GsonBuilder().create(); + ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(gson.toJson(keyIvPair)); + + String encrypted = encryptor.encryptText("Hello, world"); + + System.out.println("Encrypted result: " + encrypted); + + String decrypted = encryptor.decryptText(encrypted); + + System.out.println("Decrypted result: " + decrypted); + + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + } } diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index c7c8b5b49ca..79a2279eac1 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -142,9 +142,32 @@ CREATE TABLE `cloud`.`user_vm_clone_setting` ( INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'UserVmManager', 'vmware.create.full.clone' , 'false', 'If set to true, creates VMs as full clones on ESX hypervisor'); --- Re-enable foreign key checking, at the end of the upgrade path -SET foreign_key_checks = 1; +CREATE TABLE `cloud`.`affinity_group` ( + `id` bigint unsigned NOT NULL auto_increment, + `name` varchar(255) NOT NULL, + `type` varchar(255) NOT NULL, + `uuid` varchar(40), + `description` varchar(4096) NULL, + `domain_id` bigint unsigned NOT NULL, + `account_id` bigint unsigned NOT NULL, + UNIQUE (`name`, `account_id`), + PRIMARY KEY (`id`), + CONSTRAINT `fk_affinity_group__account_id` FOREIGN KEY(`account_id`) REFERENCES `account`(`id`), + CONSTRAINT `fk_affinity_group__domain_id` FOREIGN KEY(`domain_id`) REFERENCES `domain`(`id`), + CONSTRAINT `uc_affinity_group__uuid` UNIQUE (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `cloud`.`affinity_group_vm_map` ( + `id` bigint unsigned NOT NULL auto_increment, + `affinity_group_id` bigint unsigned NOT NULL, + `instance_id` bigint unsigned NOT NULL, + PRIMARY KEY (`id`), + CONSTRAINT `fk_agvm__group_id` FOREIGN KEY(`affinity_group_id`) REFERENCES `affinity_group`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_affinity_group_vm_map___instance_id` FOREIGN KEY(`instance_id`) REFERENCES `user_vm` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +ALTER TABLE `cloud`.`service_offering` ADD COLUMN `deployment_planner` varchar(255) NOT NULL DEFAULT 'FirstFitPlanner' COMMENT 'Planner heuristics used to deploy a VM of this offering'; CREATE TABLE nic_secondary_ips ( `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT, @@ -448,3 +471,253 @@ CREATE TABLE `cloud`.`vm_snapshots` ( ALTER TABLE `cloud`.`hypervisor_capabilities` ADD COLUMN `vm_snapshot_enabled` tinyint(1) DEFAULT 0 NOT NULL COMMENT 'Whether VM snapshot is supported by hypervisor'; UPDATE `cloud`.`hypervisor_capabilities` SET `vm_snapshot_enabled`=1 WHERE `hypervisor_type` in ('VMware', 'XenServer'); + +DROP VIEW IF EXISTS `cloud`.`user_vm_view`; +CREATE VIEW `cloud`.`user_vm_view` AS + select + vm_instance.id id, + vm_instance.name name, + user_vm.display_name display_name, + user_vm.user_data user_data, + account.id account_id, + account.uuid account_uuid, + account.account_name account_name, + account.type account_type, + domain.id domain_id, + domain.uuid domain_uuid, + domain.name domain_name, + domain.path domain_path, + projects.id project_id, + projects.uuid project_uuid, + projects.name project_name, + instance_group.id instance_group_id, + instance_group.uuid instance_group_uuid, + instance_group.name instance_group_name, + vm_instance.uuid uuid, + vm_instance.last_host_id last_host_id, + vm_instance.vm_type type, + vm_instance.vnc_password vnc_password, + vm_instance.limit_cpu_use limit_cpu_use, + vm_instance.created created, + vm_instance.state state, + vm_instance.removed removed, + vm_instance.ha_enabled ha_enabled, + vm_instance.hypervisor_type hypervisor_type, + vm_instance.instance_name instance_name, + vm_instance.guest_os_id guest_os_id, + guest_os.uuid guest_os_uuid, + vm_instance.pod_id pod_id, + host_pod_ref.uuid pod_uuid, + vm_instance.private_ip_address private_ip_address, + vm_instance.private_mac_address private_mac_address, + vm_instance.vm_type vm_type, + data_center.id data_center_id, + data_center.uuid data_center_uuid, + data_center.name data_center_name, + data_center.is_security_group_enabled security_group_enabled, + host.id host_id, + host.uuid host_uuid, + host.name host_name, + vm_template.id template_id, + vm_template.uuid template_uuid, + vm_template.name template_name, + vm_template.display_text template_display_text, + vm_template.enable_password password_enabled, + iso.id iso_id, + iso.uuid iso_uuid, + iso.name iso_name, + iso.display_text iso_display_text, + service_offering.id service_offering_id, + disk_offering.uuid service_offering_uuid, + service_offering.cpu cpu, + service_offering.speed speed, + service_offering.ram_size ram_size, + disk_offering.name service_offering_name, + storage_pool.id pool_id, + storage_pool.uuid pool_uuid, + storage_pool.pool_type pool_type, + volumes.id volume_id, + volumes.uuid volume_uuid, + volumes.device_id volume_device_id, + volumes.volume_type volume_type, + security_group.id security_group_id, + security_group.uuid security_group_uuid, + security_group.name security_group_name, + security_group.description security_group_description, + nics.id nic_id, + nics.uuid nic_uuid, + nics.network_id network_id, + nics.ip4_address ip_address, + nics.ip6_address ip6_address, + nics.ip6_gateway ip6_gateway, + nics.ip6_cidr ip6_cidr, + nics.default_nic is_default_nic, + nics.gateway gateway, + nics.netmask netmask, + nics.mac_address mac_address, + nics.broadcast_uri broadcast_uri, + nics.isolation_uri isolation_uri, + vpc.id vpc_id, + vpc.uuid vpc_uuid, + networks.uuid network_uuid, + networks.name network_name, + networks.traffic_type traffic_type, + networks.guest_type guest_type, + user_ip_address.id public_ip_id, + user_ip_address.uuid public_ip_uuid, + user_ip_address.public_ip_address public_ip_address, + ssh_keypairs.keypair_name keypair_name, + resource_tags.id tag_id, + resource_tags.uuid tag_uuid, + resource_tags.key tag_key, + resource_tags.value tag_value, + resource_tags.domain_id tag_domain_id, + resource_tags.account_id tag_account_id, + resource_tags.resource_id tag_resource_id, + resource_tags.resource_uuid tag_resource_uuid, + resource_tags.resource_type tag_resource_type, + resource_tags.customer tag_customer, + async_job.id job_id, + async_job.uuid job_uuid, + async_job.job_status job_status, + async_job.account_id job_account_id, + affinity_group.id affinity_group_id, + affinity_group.uuid affinity_group_uuid, + affinity_group.name affinity_group_name, + affinity_group.description affinity_group_description + from + `cloud`.`user_vm` + inner join + `cloud`.`vm_instance` ON vm_instance.id = user_vm.id + and vm_instance.removed is NULL + inner join + `cloud`.`account` ON vm_instance.account_id = account.id + inner join + `cloud`.`domain` ON vm_instance.domain_id = domain.id + left join + `cloud`.`guest_os` ON vm_instance.guest_os_id = guest_os.id + left join + `cloud`.`host_pod_ref` ON vm_instance.pod_id = host_pod_ref.id + left join + `cloud`.`projects` ON projects.project_account_id = account.id + left join + `cloud`.`instance_group_vm_map` ON vm_instance.id = instance_group_vm_map.instance_id + left join + `cloud`.`instance_group` ON instance_group_vm_map.group_id = instance_group.id + left join + `cloud`.`data_center` ON vm_instance.data_center_id = data_center.id + left join + `cloud`.`host` ON vm_instance.host_id = host.id + left join + `cloud`.`vm_template` ON vm_instance.vm_template_id = vm_template.id + left join + `cloud`.`vm_template` iso ON iso.id = user_vm.iso_id + left join + `cloud`.`service_offering` ON vm_instance.service_offering_id = service_offering.id + left join + `cloud`.`disk_offering` ON vm_instance.service_offering_id = disk_offering.id + left join + `cloud`.`volumes` ON vm_instance.id = volumes.instance_id + left join + `cloud`.`storage_pool` ON volumes.pool_id = storage_pool.id + left join + `cloud`.`security_group_vm_map` ON vm_instance.id = security_group_vm_map.instance_id + left join + `cloud`.`security_group` ON security_group_vm_map.security_group_id = security_group.id + left join + `cloud`.`nics` ON vm_instance.id = nics.instance_id + left join + `cloud`.`networks` ON nics.network_id = networks.id + left join + `cloud`.`vpc` ON networks.vpc_id = vpc.id + left join + `cloud`.`user_ip_address` ON user_ip_address.vm_id = vm_instance.id + left join + `cloud`.`user_vm_details` ON user_vm_details.vm_id = vm_instance.id + and user_vm_details.name = 'SSH.PublicKey' + left join + `cloud`.`ssh_keypairs` ON ssh_keypairs.public_key = user_vm_details.value + left join + `cloud`.`resource_tags` ON resource_tags.resource_id = vm_instance.id + and resource_tags.resource_type = 'UserVm' + left join + `cloud`.`async_job` ON async_job.instance_id = vm_instance.id + and async_job.instance_type = 'VirtualMachine' + and async_job.job_status = 0 + left join + `cloud`.`affinity_group_vm_map` ON vm_instance.id = affinity_group_vm_map.instance_id + left join + `cloud`.`affinity_group` ON affinity_group_vm_map.affinity_group_id = affinity_group.id; + +DROP VIEW IF EXISTS `cloud`.`affinity_group_view`; +CREATE VIEW `cloud`.`affinity_group_view` AS + select + affinity_group.id id, + affinity_group.name name, + affinity_group.description description, + affinity_group.uuid uuid, + account.id account_id, + account.uuid account_uuid, + account.account_name account_name, + account.type account_type, + domain.id domain_id, + domain.uuid domain_uuid, + domain.name domain_name, + domain.path domain_path, + vm_instance.id vm_id, + vm_instance.uuid vm_uuid, + vm_instance.name vm_name, + vm_instance.state vm_state, + user_vm.display_name vm_display_name + from + `cloud`.`affinity_group` + inner join + `cloud`.`account` ON affinity_group.account_id = account.id + inner join + `cloud`.`domain` ON affinity_group.domain_id = domain.id + left join + `cloud`.`affinity_group_vm_map` ON affinity_group.id = affinity_group_vm_map.affinity_group_id + left join + `cloud`.`vm_instance` ON vm_instance.id = affinity_group_vm_map.instance_id + left join + `cloud`.`user_vm` ON user_vm.id = vm_instance.id; + +CREATE TABLE `cloud`.`external_cisco_vnmc_devices` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `uuid` varchar(255) UNIQUE, + `physical_network_id` bigint unsigned NOT NULL COMMENT 'id of the physical network in to which cisco vnmc device is added', + `provider_name` varchar(255) NOT NULL COMMENT 'Service Provider name corresponding to this cisco vnmc device', + `device_name` varchar(255) NOT NULL COMMENT 'name of the cisco vnmc device', + `host_id` bigint unsigned NOT NULL COMMENT 'host id coresponding to the external cisco vnmc device', + PRIMARY KEY (`id`), + CONSTRAINT `fk_external_cisco_vnmc_devices__host_id` FOREIGN KEY (`host_id`) REFERENCES `host`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_external_cisco_vnmc_devices__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`external_cisco_asa1000v_devices` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `uuid` varchar(255) UNIQUE, + `physical_network_id` bigint unsigned NOT NULL COMMENT 'id of the physical network in to which cisco asa1kv device is added', + `management_ip` varchar(255) UNIQUE NOT NULL COMMENT 'mgmt. ip of cisco asa1kv device', + `in_port_profile` varchar(255) NOT NULL COMMENT 'inside port profile name of cisco asa1kv device', + `cluster_id` bigint unsigned NOT NULL COMMENT 'id of the Vmware cluster to which cisco asa1kv device is attached (cisco n1kv switch)', + PRIMARY KEY (`id`), + CONSTRAINT `fk_external_cisco_asa1000v_devices__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_external_cisco_asa1000v_devices__cluster_id` FOREIGN KEY (`cluster_id`) REFERENCES `cluster`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `cloud`.`network_asa1000v_map` ( + `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id', + `network_id` bigint unsigned NOT NULL UNIQUE COMMENT 'id of guest network', + `asa1000v_id` bigint unsigned NOT NULL UNIQUE COMMENT 'id of asa1000v device', + PRIMARY KEY (`id`), + CONSTRAINT `fk_network_asa1000v_map__network_id` FOREIGN KEY (`network_id`) REFERENCES `networks`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_network_asa1000v_map__asa1000v_id` FOREIGN KEY (`asa1000v_id`) REFERENCES `external_cisco_asa1000v_devices`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +ALTER TABLE `cloud`.`network_offerings` ADD COLUMN `eip_associate_public_ip` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if public IP is associated with user VM creation by default when EIP service is enabled.' AFTER `elastic_ip_service`; + +-- Re-enable foreign key checking, at the end of the upgrade path +SET foreign_key_checks = 1; + diff --git a/test/integration/component/test_asa1000v_fw.py b/test/integration/component/test_asa1000v_fw.py new file mode 100755 index 00000000000..0b66f971946 --- /dev/null +++ b/test/integration/component/test_asa1000v_fw.py @@ -0,0 +1,134 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" Cisco ASA1000v external firewall +""" +#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.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test Cisco ASA1000v services + """ + + def __init__(self): + self.services = { + "vnmc": { + "ipaddress": '10.147.28.236', + "username": 'admin', + "password": 'Password_123', + }, + "asa": { + "ipaddress": '10.147.28.238', + "insideportprofile": 'asa-in123', + }, + "network_offering": { + "name": 'CiscoVnmc', + "displaytext": 'CiscoVnmc', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Firewall,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList": { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'CiscoVnmc', + "PortForwarding": 'CiscoVnmc', + "Firewall": 'CiscoVnmc', + "UserData": 'VirtualRouter', + "StaticNat": 'CiscoVnmc', + }, + }, + "network": { + "name": "CiscoVnmc", + "displaytext": "CiscoVnmc", + }, + } + +class TestASASetup(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.apiclient = super( + TestASASetup, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + cls.network_offering = NetworkOffering.create( + cls.apiclient, + cls.services["network_offering"], + conservemode=True) + # Enable network offering + cls.network_offering.update(cls.apiclient, state='Enabled') + + cls._cleanup = [ + cls.network_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup + cleanup_resources(cls.apiclient, 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.zone = get_zone(self.apiclient, self.services) + self.physicalnetworks = PhysicalNetwork.list(self.apiclient, zoneid=self.zone.id) + self.assertNotEqual(len(self.physicalnetworks), 0, "Check if the list physical network API returns a non-empty response") + self.clusters = Cluster.list(self.apiclient, hypervisor='VMware') + self.assertNotEqual(len(self.clusters), 0, "Check if the list cluster API returns a non-empty response") + + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + # Cleanup + cleanup_resources(self.apiclient, self._cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_registerVnmc(self): + Vnmc = VNMC.create(self.apiclient, self.services["vnmc"]["ipaddress"], self.services["vnmc"]["username"], self.services["vnmc"]["password"], self.physicalnetworks[0].id) + self.debug("Cisco VNMC appliance with id %s deployed"%(Vnmc.id)) + VnmcList = VNMC.list(self.apiclient, physicalnetworkid = self.physicalnetworks[0].id) + self.assertNotEqual(len(VnmcList), 0, "List VNMC API returned an empty response") + Vnmc.delete(self.apiclient) + + def test_registerAsa1000v(self): + Asa = ASA1000V.create(self.apiclient, self.services["asa"]["ipaddress"], self.services["asa"]["insideportprofile"], self.clusters[0].id, self.physicalnetworks[0].id) + self.debug("Cisco ASA 1000v appliance with id %s deployed"%(Asa.id)) + AsaList = ASA1000V.list(self.apiclient, physicalnetworkid = self.physicalnetworks[0].id) + self.assertNotEqual(len(AsaList), 0, "List ASA 1000v API returned an empty response") + Asa.delete(self.apiclient) \ No newline at end of file diff --git a/test/integration/smoke/test_ScaleVm.py b/test/integration/smoke/test_ScaleVm.py index 710d2add7b6..64fe4dc9aa4 100644 --- a/test/integration/smoke/test_ScaleVm.py +++ b/test/integration/smoke/test_ScaleVm.py @@ -91,7 +91,7 @@ class Services: "sleep": 60, "timeout": 10, #Migrate VM to hostid - "ostype": 'CentOS 5.6 (64-bit)', + "ostype": 'CentOS 5.3 (64-bit)', # CentOS 5.3 (64-bit) } @@ -164,7 +164,7 @@ class TestScaleVm(cloudstackTestCase): cleanup_resources(self.apiclient, self.cleanup) return - @attr(tags = ["advanced", "basic", "multicluster", "storagemotion", "xenserver"]) + @attr(tags = ["xenserver", "advanced", "basic"]) def test_01_scale_vm(self): """Test scale virtual machine """ diff --git a/test/integration/smoke/test_affinity_groups.py b/test/integration/smoke/test_affinity_groups.py new file mode 100644 index 00000000000..832c4a4e1fa --- /dev/null +++ b/test/integration/smoke/test_affinity_groups.py @@ -0,0 +1,194 @@ +#!/usr/bin/env 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. + +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 import remoteSSHClient +from nose.plugins.attrib import attr + +class Services: + """Test Account Services + """ + + def __init__(self): + self.services = { + "domain": { + "name": "Domain", + }, + "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, + # in MHz + "memory": 64, + # In MBs + }, + "ostype": 'CentOS 5.3 (64-bit)', + "virtual_machine" : { + "affinity": { + "name": "webvms", + "type": "host anti-affinity", + }, + "hypervisor" : "XenServer", + } + } + + +class TestDeployVmWithAffinityGroup(cloudstackTestCase): + """ + This test deploys a virtual machine into a user account + using the small service offering and builtin template + """ + + @classmethod + def setUpClass(cls): + cls.api_client = super(TestDeployVmWithAffinityGroup, 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["template"] = cls.template.id + cls.services["zoneid"] = cls.zone.id + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + + cls.ag = AffinityGroup.create(cls.api_client, cls.services["virtual_machine"]["affinity"], + account=cls.services["account"], domainid=cls.domain.id) + + cls._cleanup = [ + cls.service_offering, + cls.account, + ] + return + + @attr(tags=["simulator", "basic", "advanced", "multihost"]) + def test_DeployVmAntiAffinityGroup(self): + """ + test DeployVM in anti-affinity groups + + deploy VM1 and VM2 in the same host-anti-affinity groups + Verify that the vms are deployed on separate hosts + """ + #deploy VM1 in affinity group created in setUp + vm1 = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + affinitygroupnames=[self.ag.name] + ) + + list_vm1 = list_virtual_machines( + self.api_client, + id=vm1.id + ) + self.assertEqual( + isinstance(list_vm1, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + len(list_vm1), + 0, + "Check VM available in List Virtual Machines" + ) + vm1_response = list_vm1[0] + self.assertEqual( + vm1_response.state, + 'Running', + msg="VM is not in Running state" + ) + host_of_vm1 = vm1_response.hostid + + #deploy VM2 in affinity group created in setUp + vm2 = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + affinitygroupnames=[self.ag.name] + ) + list_vm2 = list_virtual_machines( + self.api_client, + id=vm2.id + ) + self.assertEqual( + isinstance(list_vm2, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + len(list_vm2), + 0, + "Check VM available in List Virtual Machines" + ) + vm2_response = list_vm2[0] + self.assertEqual( + vm2_response.state, + 'Running', + msg="VM is not in Running state" + ) + host_of_vm2 = vm2_response.hostid + + self.assertNotEqual(host_of_vm1, host_of_vm2, + msg="Both VMs of affinity group %s are on the same host" % self.ag.name) + + + @classmethod + def tearDown(cls): + try: + cls.api_client = super(TestDeployVmWithAffinityGroup, cls).getClsTestClient().getApiClient() + #Clean up, terminate the created templates + cleanup_resources(cls.api_client, cls.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) diff --git a/test/integration/smoke/test_iso.py b/test/integration/smoke/test_iso.py index 5bd7bb358be..3f8f11abdf9 100644 --- a/test/integration/smoke/test_iso.py +++ b/test/integration/smoke/test_iso.py @@ -79,8 +79,6 @@ class Services: "timeout": 10, "ostype": "CentOS 5.3 (64-bit)", # CentOS 5.3 (64 bit) - "mode": 'advanced' - # Networking mode: Basic or Advanced } @@ -93,6 +91,7 @@ class TestCreateIso(cloudstackTestCase): # Get Zone, Domain and templates self.domain = get_domain(self.apiclient, self.services) self.zone = get_zone(self.apiclient, self.services) + self.services['mode'] = zone.networktype self.services["domainid"] = self.domain.id self.services["iso_2"]["zoneid"] = self.zone.id diff --git a/test/integration/smoke/test_network.py b/test/integration/smoke/test_network.py index e78cc43fe33..e2c63a4b5b4 100644 --- a/test/integration/smoke/test_network.py +++ b/test/integration/smoke/test_network.py @@ -38,8 +38,6 @@ class Services: self.services = { "ostype": "CentOS 5.3 (64-bit)", # Cent OS 5.3 (64 bit) - "mode": 'advanced', - # Networking mode: Basic or advanced "lb_switch_wait": 10, # Time interval after which LB switches the requests "sleep": 60, @@ -120,7 +118,7 @@ class TestPublicIP(cloudstackTestCase): # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) - + cls.services['mode'] = zone.networktype # Create Accounts & networks cls.account = Account.create( cls.api_client, diff --git a/test/integration/smoke/test_public_ip_range.py b/test/integration/smoke/test_public_ip_range.py new file mode 100644 index 00000000000..a7aad6b795c --- /dev/null +++ b/test/integration/smoke/test_public_ip_range.py @@ -0,0 +1,173 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +""" P1 tests for Dedicating Public IP addresses +""" +#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 * +import datetime + +class Services: + """Test Dedicating Public IP addresses + """ + + def __init__(self): + self.services = { + "domain": { + "name": "Domain", + }, + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + "password": "password", + }, + "gateway": "10.102.197.1", + "netmask": "255.255.255.0", + "forvirtualnetwork": "true", + "startip": "10.102.197.70", + "endip": "10.102.197.73", + "zoneid": "1", + "podid": "", + "vlan": "101", + } + +class TesDedicatePublicIPRange(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super(TesDedicatePublicIPRange, cls).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + # Create Account + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls._cleanup = [ + cls.account, + ] + 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 = [] + return + + def tearDown(self): + try: + # Clean up + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["simulator", "publiciprange", "dedicate", "release"]) + def test_dedicatePublicIpRange(self): + """Test public IP range dedication + """ + + # Validate the following: + # 1. Create a Public IP range + # 2. Created IP range should be present, verify with listVlanIpRanges + # 3. Dedicate the created IP range to user account + # 4. Verify IP range is dedicated, verify with listVlanIpRanges + # 5. Release the dedicated Public IP range back to the system + # 6. Verify IP range has been released, verify with listVlanIpRanges + # 7. Delete the Public IP range + + self.debug("Creating Public IP range") + self.public_ip_range = PublicIpRange.create( + self.api_client, + self.services + ) + list_public_ip_range_response = PublicIpRange.list( + self.apiclient, + id=self.public_ip_range.vlan.id + ) + self.debug( + "Verify listPublicIpRanges response for public ip ranges: %s" \ + % self.public_ip_range.vlan.id + ) + self.assertEqual( + isinstance(list_public_ip_range_response, list), + True, + "Check for list Public IP range response" + ) + public_ip_response = list_public_ip_range_response[0] + self.assertEqual( + public_ip_response.id, + self.public_ip_range.vlan.id, + "Check public ip range response id is in listVlanIpRanges" + ) + + self.debug("Dedicating Public IP range"); + dedicate_public_ip_range_response = PublicIpRange.dedicate( + self.apiclient, + self.public_ip_range.vlan.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + list_public_ip_range_response = PublicIpRange.list( + self.apiclient, + id=self.public_ip_range.vlan.id + ) + public_ip_response = list_public_ip_range_response[0] + self.assertEqual( + public_ip_response.account, + self.account.account.name, + "Check account name is in listVlanIpRanges as the account public ip range is dedicated to" + ) + + self.debug("Releasing Public IP range"); + self.public_ip_range.release(self.apiclient) + list_public_ip_range_response = PublicIpRange.list( + self.apiclient, + id=self.public_ip_range.vlan.id + ) + public_ip_response = list_public_ip_range_response[0] + self.assertEqual( + public_ip_response.account, + "system", + "Check account name is system account in listVlanIpRanges" + ) + + self.debug("Deleting Public IP range"); + self.public_ip_range.delete(self.apiclient) + + return + diff --git a/test/integration/smoke/test_routers.py b/test/integration/smoke/test_routers.py index 435c7e41a43..93116bfd58a 100644 --- a/test/integration/smoke/test_routers.py +++ b/test/integration/smoke/test_routers.py @@ -64,7 +64,6 @@ class Services: "ostype": "CentOS 5.3 (64-bit)", "sleep": 60, "timeout": 10, - "mode": 'advanced', #Networking mode: Basic, Advanced } @@ -81,6 +80,7 @@ class TestRouterServices(cloudstackTestCase): # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) + self.services['mode'] = zone.networktype template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/smoke/test_templates.py b/test/integration/smoke/test_templates.py index 663b174ed78..2b0e2f5ce97 100644 --- a/test/integration/smoke/test_templates.py +++ b/test/integration/smoke/test_templates.py @@ -93,8 +93,6 @@ class Services: "bootable": True, "passwordenabled": True, "ostype": "CentOS 5.3 (64-bit)", - "mode": 'advanced', - # Networking mode: Advanced, basic "sleep": 30, "timeout": 10, } @@ -126,6 +124,7 @@ class TestCreateTemplate(cloudstackTestCase): # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, cls.services["disk_offering"] diff --git a/test/integration/smoke/test_vm_life_cycle.py b/test/integration/smoke/test_vm_life_cycle.py index 564f6e854a5..cf9fd7530f1 100644 --- a/test/integration/smoke/test_vm_life_cycle.py +++ b/test/integration/smoke/test_vm_life_cycle.py @@ -1038,4 +1038,4 @@ class TestVMLifeCycle(cloudstackTestCase): False, "Check if ISO is detached from virtual machine" ) - return \ No newline at end of file + return diff --git a/test/integration/smoke/test_volumes.py b/test/integration/smoke/test_volumes.py index 36eb5ded263..9aa44eb6f1f 100644 --- a/test/integration/smoke/test_volumes.py +++ b/test/integration/smoke/test_volumes.py @@ -78,13 +78,12 @@ class Services: "password": "password", "ssh_port": 22, "diskname": "TestDiskServ", - "hypervisor": 'XenServer', + "hypervisor": 'KVM', "privateport": 22, "publicport": 22, "protocol": 'TCP', "diskdevice": "/dev/xvdb", - "ostype": 'CentOS 5.3 (64-bit)', - "mode": 'basic', + "ostype": 'CentOS 5.5 (64-bit)', "sleep": 10, "timeout": 600, } @@ -100,6 +99,7 @@ class TestCreateVolume(cloudstackTestCase): # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, cls.services["disk_offering"] @@ -358,6 +358,12 @@ class TestVolumes(cloudstackTestCase): def setUp(self): self.apiClient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + + def tearDown(self): + #Clean up, terminate the created volumes + cleanup_resources(self.apiClient, self.cleanup) + return @attr(tags = ["advanced", "advancedns", "smoke"]) def test_02_attach_volume(self): @@ -535,9 +541,13 @@ class TestVolumes(cloudstackTestCase): try: response = self.apiClient.resizeVolume(cmd) except Exception as ex: - if str(ex) == "HTTP Error 431: 431": + #print str(ex) + if "HTTP Error 431:" in str(ex): success = True - self.assertEqual(success, True, "ResizeVolume - verify invalid id is handled appropriately") + self.assertEqual( + success, + True, + "ResizeVolume - verify invalid id is handled appropriately") # Next, we'll try an invalid disk offering id cmd.id = self.volume.id @@ -546,16 +556,29 @@ class TestVolumes(cloudstackTestCase): try: response = self.apiClient.resizeVolume(cmd) except Exception as ex: - if "need to specify a disk offering" in str(ex): + if "HTTP Error 431:" in str(ex): success = True - self.assertEqual(success, True, "ResizeVolume - verify disk offering is handled appropriately") - + self.assertEqual( + success, + True, + "ResizeVolume - verify disk offering is handled appropriately") # Ok, now let's try and resize a volume that is not custom. cmd.id = self.volume.id cmd.diskofferingid = self.services['diskofferingid'] cmd.size = 4 currentSize = self.volume.size + self.debug( + "Attaching volume (ID: %s) to VM (ID: %s)" % ( + self.volume.id, + self.virtual_machine.id) + ) + #attach the volume + self.virtual_machine.attach_volume(self.apiClient, self.volume) + #stop the vm if it is on xenserver + if self.services['hypervisor'].lower() == "xenserver": + self.virtual_machine.stop(self.apiClient) + self.apiClient.resizeVolume(cmd) count = 0 success = True @@ -566,7 +589,7 @@ class TestVolumes(cloudstackTestCase): type='DATADISK' ) for vol in list_volume_response: - if vol.id == self.volume.id and vol.size != currentSize: + if vol.id == self.volume.id and vol.size != currentSize and vol.state != "Resizing": success = False if success: break @@ -579,12 +602,21 @@ class TestVolumes(cloudstackTestCase): True, "Verify the volume did not resize" ) - + self.virtual_machine.detach_volume(self.apiClient, self.volume) + self.cleanup.append(self.volume) @attr(tags = ["advanced", "advancedns", "smoke"]) def test_08_resize_volume(self): """Resize a volume""" # Verify the size is the new size is what we wanted it to be. + self.debug( + "Attaching volume (ID: %s) to VM (ID: %s)" % ( + self.volume.id, + self.virtual_machine.id + )) + self.virtual_machine.attach_volume(self.apiClient, self.volume) + if self.services['hypervisor'].lower() == "xenserver": + self.virtual_machine.stop(self.apiClient) self.debug("Resize Volume ID: %s" % self.volume.id) cmd = resizeVolume.resizeVolumeCmd() @@ -616,6 +648,9 @@ class TestVolumes(cloudstackTestCase): "Check if the volume resized appropriately" ) + self.virtual_machine.detach_volume(self.apiClient, self.volume) + self.cleanup.append(self.volume) + @attr(tags = ["advanced", "advancedns", "smoke"]) def test_09_delete_detached_volume(self): """Delete a Volume unattached to an VM diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py index ab2456dd3eb..5403adb99df 100644 --- a/tools/apidoc/gen_toc.py +++ b/tools/apidoc/gen_toc.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/cygdrive/c/Python27 # 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 @@ -83,6 +83,7 @@ known_categories = { 'Configuration': 'Configuration', 'Capabilities': 'Configuration', 'Pod': 'Pod', + 'PublicIpRange': 'Network', 'Zone': 'Zone', 'NetworkOffering': 'Network Offering', 'NetworkACL': 'Network ACL', @@ -137,6 +138,7 @@ known_categories = { 'addIpToNic': 'Nic', 'removeIpFromNic': 'Nic', 'listNics':'Nic', + 'AffinityGroup': 'Affinity Group', } diff --git a/tools/build/build_asf.sh b/tools/build/build_asf.sh index c652a20bf42..c692febb143 100755 --- a/tools/build/build_asf.sh +++ b/tools/build/build_asf.sh @@ -81,21 +81,21 @@ fi cd $sourcedir echo 'archiving' -git archive --format=tar --prefix=apache-cloudstack-$version-incubating-src/ $branch > $outputdir/apache-cloudstack-$version-incubating-src.tar -bzip2 $outputdir/apache-cloudstack-$version-incubating-src.tar +git archive --format=tar --prefix=apache-cloudstack-$version-src/ $branch > $outputdir/apache-cloudstack-$version-src.tar +bzip2 $outputdir/apache-cloudstack-$version-src.tar cd $outputdir echo 'armor' -gpg -v $keyid --armor --output apache-cloudstack-$version-incubating-src.tar.bz2.asc --detach-sig apache-cloudstack-$version-incubating-src.tar.bz2 +gpg -v $keyid --armor --output apache-cloudstack-$version-src.tar.bz2.asc --detach-sig apache-cloudstack-$version-src.tar.bz2 echo 'md5' -gpg -v --print-md MD5 apache-cloudstack-$version-incubating-src.tar.bz2 > apache-cloudstack-$version-incubating-src.tar.bz2.md5 +gpg -v --print-md MD5 apache-cloudstack-$version-src.tar.bz2 > apache-cloudstack-$version-src.tar.bz2.md5 echo 'sha' -gpg -v --print-md SHA512 apache-cloudstack-$version-incubating-src.tar.bz2 > apache-cloudstack-$version-incubating-src.tar.bz2.sha +gpg -v --print-md SHA512 apache-cloudstack-$version-src.tar.bz2 > apache-cloudstack-$version-src.tar.bz2.sha echo 'verify' -gpg -v --verify apache-cloudstack-$version-incubating-src.tar.bz2.asc apache-cloudstack-$version-incubating-src.tar.bz2 +gpg -v --verify apache-cloudstack-$version-src.tar.bz2.asc apache-cloudstack-$version-src.tar.bz2 if [ $tag == 'yes' ]; then echo 'tag' diff --git a/tools/build/build_docs.sh b/tools/build/build_docs.sh index 8bb63e30e87..11b24141d95 100755 --- a/tools/build/build_docs.sh +++ b/tools/build/build_docs.sh @@ -19,22 +19,28 @@ sourcedir=~/incubator-cloudstack/ common_content_dir=/usr/share/publican/Common_Content publican_path=/usr/bin/publican +output_format="html,pdf" +config="publican-adminguide.cfg" usage(){ echo "usage: $0 [-s source dir] [-c publican common content] [-p path to publican]" echo " -s sets the source directory (defaults to $sourcedir)" echo " -c sets the public common content directory (defaults to $common_content_dir)" echo " -p sets the path to the publican binary (defaults to $publican_path)" - echo " -h" + echo " -f sets the output format (defaults to $output_format)" + echo " -g sets the publican config file (defaults to $config)" + echo " -h show this help" } -while getopts v:s:c:p:h opt +while getopts v:s:c:p:f:g:h opt do case "$opt" in v) version="$OPTARG";; s) sourcedir="$OPTARG";; c) common_content_dir="$OPTARG";; p) publican_path="$OPTARG";; + f) output_format="$OPTARG";; + g) config="$OPTARG";; h) usage exit 0;; \?) @@ -48,8 +54,13 @@ if [ ! -x "$publican_path" ]; then exit 1 fi +if [ ! -d "$sourcedir/docs" ]; then + echo "$sourcedir/docs doesn't seem to exist? Maybe set -s?" + exit 1 +fi + cd $sourcedir/docs cp -R /usr/share/publican/Common_Content . ln -s $sourcedir/docs/publican-cloudstack Common_Content/cloudstack -publican build --config=publican-installation.cfg --formats html,pdf --langs en-US --common_content=$sourcedir/docs/Common_Content -rm -r Common_Content \ No newline at end of file +publican build --config=$config --formats $output_format --langs en-US --common_content=$sourcedir/docs/Common_Content +rm -r Common_Content diff --git a/tools/cli/cloudmonkey/requester.py b/tools/cli/cloudmonkey/requester.py index 88967fed74d..d2dae6dfc3f 100644 --- a/tools/cli/cloudmonkey/requester.py +++ b/tools/cli/cloudmonkey/requester.py @@ -61,11 +61,11 @@ def make_request(command, args, logger, host, port, args["apiKey"] = apikey args["response"] = "json" request = zip(args.keys(), args.values()) - request.sort(key=lambda x: str.lower(x[0])) + request.sort(key=lambda x: x[0].lower()) request_url = "&".join(["=".join([r[0], urllib.quote_plus(str(r[1]))]) for r in request]) - hashStr = "&".join(["=".join([str.lower(r[0]), + hashStr = "&".join(["=".join([r[0].lower(), str.lower(urllib.quote_plus(str(r[1]))).replace("+", "%20")]) for r in request]) diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py old mode 100644 new mode 100755 index f3370eb3190..0185c87fed9 --- a/tools/marvin/marvin/integration/lib/base.py +++ b/tools/marvin/marvin/integration/lib/base.py @@ -90,10 +90,7 @@ class Account: cmd.firstname = services["firstname"] cmd.lastname = services["lastname"] - # Password Encoding - mdf = hashlib.md5() - mdf.update(services["password"]) - cmd.password = mdf.hexdigest() + cmd.password = services["password"] cmd.username = "-".join([services["username"], random_gen()]) if domainid: @@ -223,7 +220,7 @@ class VirtualMachine: def create(cls, apiclient, services, templateid=None, accountid=None, domainid=None, zoneid=None, networkids=None, serviceofferingid=None, securitygroupids=None, projectid=None, startvm=None, - diskofferingid=None, hostid=None, mode='basic'): + diskofferingid=None, affinitygroupnames=None, hostid=None, mode='basic'): """Create the instance""" cmd = deployVirtualMachine.deployVirtualMachineCmd() @@ -268,6 +265,11 @@ class VirtualMachine: if "userdata" in services: cmd.userdata = base64.b64encode(services["userdata"]) + if "affinitygroupnames" in services: + cmd.affinitygroupnames = services["affinitygroupnames"] + elif affinitygroupnames: + cmd.affinitygroupnames = affinitygroupnames + if projectid: cmd.projectid = projectid @@ -1871,7 +1873,7 @@ class PublicIpRange: """Delete VlanIpRange""" cmd = deleteVlanIpRange.deleteVlanIpRangeCmd() - cmd.id = self.id + cmd.id = self.vlan.id apiclient.deleteVlanIpRange(cmd) @classmethod @@ -1882,6 +1884,23 @@ class PublicIpRange: [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listVlanIpRanges(cmd)) + @classmethod + def dedicate(cls, apiclient, id, account=None, domainid=None, projectid=None): + """Dedicate VLAN IP range""" + + cmd = dedicatePublicIpRange.dedicatePublicIpRangeCmd() + cmd.id = id + cmd.account = account + cmd.domainid = domainid + cmd.projectid = projectid + return PublicIpRange(apiclient.dedicatePublicIpRange(cmd).__dict__) + + def release(self, apiclient): + """Release VLAN IP range""" + + cmd = releasePublicIpRange.releasePublicIpRangeCmd() + cmd.id = self.vlan.id + return apiclient.releasePublicIpRange(cmd) class SecondaryStorage: """Manage Secondary storage""" @@ -2424,3 +2443,94 @@ class VPC: cmd = listVPCs.listVPCsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listVPCs(cmd)) + +class AffinityGroup: + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(cls, apiclient, services, account=None, domainid=None): + agCmd = createAffinityGroup.createAffinityGroupCmd() + agCmd.name = services['name'] + agCmd.displayText = services['displaytext'] if 'displaytext' in services else services['name'] + agCmd.type = services['type'] + agCmd.account = services['account'] if 'account' in services else account + agCmd.domainid = services['domainid'] if 'domainid' in services else domainid + return AffinityGroup(apiclient.createAffinityGroup(agCmd).__dict__) + + def update(self, apiclient): + pass + + def delete(self, apiclient): + cmd = deleteAffinityGroup.deleteAffinityGroupCmd() + cmd.id = self.id + return apiclient.deleteVPC(cmd) + + @classmethod + def list(cls, apiclient, **kwargs): + cmd = listAffinityGroups.listAffinityGroupsCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listVPCs(cmd)) + +class VNMC: + """Manage VNMC lifecycle""" + + def __init__(self, items): + self.__dict__.update(items) + + def create(cls, apiclient, hostname, username, password, physicalnetworkid): + """Registers VNMC appliance""" + + cmd = addCiscoVnmcResource.addCiscoVnmcResourceCmd() + cmd.hostname = hostname + cmd.username = username + cmd.password = password + cmd.physicalnetworkid = physicalnetworkid + return VNMC(apiclient.addCiscoVnmcResource(cmd)) + + def delete(self, apiclient): + """Removes VNMC appliance""" + + cmd = deleteCiscoVnmcResource.deleteCiscoVnmcResourceCmd() + cmd.resourceid = self.resourceid + return apiclient.deleteCiscoVnmcResource(cmd) + + @classmethod + def list(cls, apiclient, **kwargs): + """List VNMC appliances""" + + cmd = listCiscoVnmcResources.listCiscoVnmcResourcesCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listCiscoVnmcResources(cmd)) + +class ASA1000V: + """Manage ASA 1000v lifecycle""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(cls, apiclient, hostname, insideportprofile, clusterid, physicalnetworkid): + """Registers ASA 1000v appliance""" + + cmd = addCiscoAsa1000vResource.addCiscoAsa1000vResourceCmd() + cmd.hostname = hostname + cmd.insideportprofile = insideportprofile + cmd.clusterid = clusterid + cmd.physicalnetworkid = physicalnetworkid + return ASA1000V(apiclient.addCiscoAsa1000vResource(cmd)) + + def delete(self, apiclient): + """Removes ASA 1000v appliance""" + + cmd = deleteCiscoAsa1000vResource.deleteCiscoAsa1000vResourceCmd() + cmd.resourceid = self.resourceid + return apiclient.deleteCiscoAsa1000vResource(cmd) + + @classmethod + def list(cls, apiclient, **kwargs): + """List ASA 1000v appliances""" + + cmd = listCiscoAsa1000vResources.listCiscoAsa1000vResourcesCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listCiscoAsa1000vResources(cmd)) diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 32111309c2e..eda02217031 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -1697,7 +1697,7 @@ div.list-view td.state.off span { } .detail-view .main-groups { - max-height: 455px; + max-height: 407px; overflow: auto; overflow-x: hidden; margin-right: 12px; @@ -1754,6 +1754,10 @@ div.list-view td.state.off span { width: 245px; } +.detail-group .main-groups table td.value > span select { + width: 100% !important; +} + .detail-group .main-groups table td.value .view-all { cursor: pointer; /*[empty]height:;*/ diff --git a/ui/index.jsp b/ui/index.jsp index 6b7d431c7fa..41ad4915536 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -56,7 +56,7 @@ under the License.
- +
diff --git a/ui/scripts/cloudStack.js b/ui/scripts/cloudStack.js index 0cf80b02066..a8bca91769c 100644 --- a/ui/scripts/cloudStack.js +++ b/ui/scripts/cloudStack.js @@ -255,11 +255,11 @@ array1.push("&domain=" + encodeURIComponent("/")); } - g_loginCmdText = array1.join(""); + var loginCmdText = array1.join(""); $.ajax({ type: "POST", - data: "command=login" + g_loginCmdText + "&response=json", + data: "command=login" + loginCmdText + "&response=json", dataType: "json", async: false, success: function(json) { diff --git a/ui/scripts/dashboard.js b/ui/scripts/dashboard.js index 845ae52259b..e8ab6c531f9 100644 --- a/ui/scripts/dashboard.js +++ b/ui/scripts/dashboard.js @@ -238,7 +238,7 @@ return { zoneID: capacity.zoneid, // Temporary fix for dashboard zoneName: capacity.zonename, - type: cloudStack.converters.toAlertType(capacity.type), + type: cloudStack.converters.toCapacityCountType(capacity.type), percent: parseInt(capacity.percentused), used: cloudStack.converters.convertByType(capacity.type, capacity.capacityused), total: cloudStack.converters.convertByType(capacity.type, capacity.capacitytotal) diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js index 1c4c38c75fd..21b58aee039 100644 --- a/ui/scripts/instances.js +++ b/ui/scripts/instances.js @@ -1082,9 +1082,36 @@ scaleUp:{ label:'scaleUp VM', + createForm:{ + title:'Scale UP Virtual Machine', + label:'Scale UP Virtual Machine', + fields:{ + serviceOffering: { + label: 'label.compute.offering', + select: function(args) { + $.ajax({ + url: createURL("listServiceOfferings&VirtualMachineId=" + args.context.instances[0].id), + dataType: "json", + async: true, + success: function(json) { + var serviceofferings = json.listserviceofferingsresponse.serviceoffering; + var items = []; + $(serviceofferings).each(function() { + items.push({id: this.id, description: this.displaytext}); + }); + args.response.success({data: items}); + } + }); + } + } + + + } + }, + action: function(args) { $.ajax({ - url: createURL("scaleVirtualMachine&id=" + args.context.instances[0].id + "&serviceofferingid=" + args.context.instances[0].serviceofferingid), + url: createURL("scaleVirtualMachine&id=" + args.context.instances[0].id + "&serviceofferingid=" + args.data.serviceOffering), dataType: "json", async: true, success: function(json) { diff --git a/ui/scripts/network.js b/ui/scripts/network.js index a9a1a6b015f..f9a8778a806 100755 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -893,7 +893,7 @@ hiddenTabs.push("addloadBalancer"); } - if (isVPC || isAdvancedSGZone || hasSRXFirewall) { + if (isVPC || isAdvancedSGZone ) { hiddenTabs.push('egressRules'); } @@ -1524,7 +1524,9 @@ data.queryasyncjobresultresponse.jobresult.nicsecondaryip, { zoneid: args.context.instances[0].zoneid, - virtualmachinedisplayname: args.context.instances[0].displayname + virtualmachinedisplayname: args.context.instances[0].displayname ? + args.context.instances[0].displayname : + args.context.instances[0].name } ); }, @@ -1557,7 +1559,9 @@ data: $(ips).map(function(index, ip) { return $.extend(ip, { zoneid: args.context.instances[0].zoneid, - virtualmachinedisplayname: args.context.instances[0].displayname + virtualmachinedisplayname: args.context.instances[0].displayname ? + args.context.instances[0].displayname : + args.context.instances[0].name }); }) }); diff --git a/ui/scripts/regions.js b/ui/scripts/regions.js index 0aaece009f7..ec5e21b7d4c 100644 --- a/ui/scripts/regions.js +++ b/ui/scripts/regions.js @@ -55,6 +55,12 @@ actions: { add: { label: 'label.add.region', + preFilter: function(args) { + if(isAdmin()) + return true; + else + return false; + }, messages: { notification: function() { return 'label.add.region'; } }, @@ -98,10 +104,9 @@ $.ajax({ url: createURL('listRegions&listAll=true'), success: function(json) { - var regions = json.listregionsresponse.region - - args.response.success({ - data: regions ? regions : [] + var items = json.listregionsresponse.region; + args.response.success({ + data: items }); }, error: function(json) { @@ -193,6 +198,7 @@ var region = json.listregionsresponse.region args.response.success({ + actionFilter: regionActionfilter, data: region ? region[0] : {} }); }, @@ -214,8 +220,148 @@ id: 'GSLB', label: 'GSLB', fields: { - name: { label: 'label.name' } + name: { label: 'label.name' }, + gslbdomainname: { label: 'GSLB Domain Name' }, + gslblbmethod: { label: 'Algorithm' } + }, + actions: { + add: { + label: 'Add GSLB', + + messages: { + confirm: function(args) { + return 'Add GSLB'; + }, + notification: function(args) { + return 'Add GSLB'; + } + }, + + createForm: { + title: 'Add GSLB', + fields: { + name: { + label: 'label.name', + validation: { required: true } + }, + description: { + label: 'label.description' + }, + /* + domainid: { + label: 'Domain', + select: function(args) { + if(isAdmin() || isDomainAdmin()) { + $.ajax({ + url: createURL('listDomains'), + data: { + listAll: true, + details: 'min' + }, + success: function(json) { + var array1 = [{id: '', description: ''}]; + var domains = json.listdomainsresponse.domain; + if(domains != null && domains.length > 0) { + for(var i = 0; i < domains.length; i++) { + array1.push({id: domains[i].id, description: domains[i].path}); + } + } + args.response.success({ + data: array1 + }); + } + }); + } + else { + args.response.success({ + data: null + }); + } + }, + isHidden: function(args) { + if(isAdmin() || isDomainAdmin()) + return false; + else + return true; + } + }, + account: { + label: 'Account', + isHidden: function(args) { + if(isAdmin() || isDomainAdmin()) + return false; + else + return true; + } + }, + */ + gslblbmethod: { + label: 'Algorithm', + select: function(args) { + var array1 = [{id: 'roundrobin', description: 'roundrobin'}, {id: 'leastconn', description: 'leastconn'}, {id: 'proximity', description: 'proximity'}]; + args.response.success({ + data: array1 + }); + } + }, + gslbdomainname: { + label: 'GSLB Domain Name', + validation: { required: true } + }, + gslbservicetype: { + label: 'Service Type', + select: function(args) { + var array1 = [{id: 'tcp', description: 'tcp'}, {id: 'udp', description: 'udp'}]; + args.response.success({ + data: array1 + }); + }, + validation: { required: true } + } + } + }, + action: function(args) { + var data = { + name: args.data.name, + regionid: args.context.regions[0].id, + gslblbmethod: args.data.gslblbmethod, + gslbstickysessionmethodname: 'sourceip', + gslbdomainname: args.data.gslbdomainname, + gslbservicetype: args.data.gslbservicetype + }; + if(args.data.description != null && args.data.description.length > 0) + $.extend(data, { description: args.data.description }); + /* + if(args.data.domainid != null && args.data.domainid.length > 0) + $.extend(data, { domainid: args.data.domainid }); + if(args.data.account != null && args.data.account.length > 0) + $.extend(data, { account: args.data.account }); + */ + $.ajax({ + url: createURL('createGlobalLoadBalancerRule'), + data: data, + success: function(json) { + var jid = json.creategloballoadbalancerruleresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.globalloadbalancerrule; + } + } + } + ); + } + }); + }, + notification: { + poll: function(args) { + poll: pollAsyncJobResult + } + } + } }, + dataProvider: function(args) { if('regions' in args.context) { var data = { @@ -224,8 +370,7 @@ $.ajax({ url: createURL('listGlobalLoadBalancerRules'), data: data, - success: function(json) { - debugger; + success: function(json) { var items = json.listgloballoadbalancerrulesresponse.globalloadbalancerrule; args.response.success({ data: items @@ -243,4 +388,14 @@ } } }; + + var regionActionfilter = function(args) { + var allowedActions = []; + if(isAdmin()) { + allowedActions.push("edit"); + allowedActions.push("remove"); + } + return allowedActions; + } + })(cloudStack); diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index 86fe7f6416c..74675314040 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -325,7 +325,8 @@ cloudStack.converters = { if(g_timezoneoffset != null) localDate = disconnected.getTimePlusTimezoneOffset(g_timezoneoffset); else - localDate = disconnected.getTimePlusTimezoneOffset(0); + localDate = disconnected.toUTCString(); + // localDate = disconnected.getTimePlusTimezoneOffset(0); } return localDate; }, @@ -425,6 +426,31 @@ cloudStack.converters = { case 26 : return "Resource Limit Exceeded"; } }, + + toCapacityCountType:function(capacityCode){ + switch(capacityCode){ + case 0 : return _l('label.memory'); + case 1 : return _l('label.cpu'); + case 2 : return _l('label.storage'); + case 3 : return _l('label.primary.storage'); + case 4 : return _l('label.public.ips'); + case 5 : return _l('label.management.ips'); + case 6 : return _l('label.secondary.storage'); + case 7 : return _l('label.vlan'); + case 8 : return _l('label.direct.ips'); + case 9 : return _l('label.local.storage'); + case 10 : return "Routing Host"; + case 11 : return "Storage"; + case 12 : return "Usage Server"; + case 13 : return "Management Server"; + case 14 : return "Domain Router"; + case 15 : return "Console Proxy"; + case 16 : return "User VM"; + case 17 : return "VLAN"; + case 18 : return "Secondary Storage VM"; + } + }, + convertByType: function(alertCode, value) { switch(alertCode) { case 0: return cloudStack.converters.convertBytes(value); diff --git a/ui/scripts/system.js b/ui/scripts/system.js index f74711d273d..a9054125774 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -597,7 +597,7 @@ }); } }, - /* + releaseFromAccount: { label: 'Release from Account', action: function(args) { @@ -622,6 +622,7 @@ }); } }, + addAccount: { label: 'Add Account', createForm: { @@ -675,7 +676,7 @@ }); } } - */ + }, dataProvider: function(args) { $.ajax({ diff --git a/ui/scripts/ui-custom/regions.js b/ui/scripts/ui-custom/regions.js index 2f61dfddeaf..0469638f8f2 100644 --- a/ui/scripts/ui-custom/regions.js +++ b/ui/scripts/ui-custom/regions.js @@ -89,7 +89,7 @@ closeRegionSelector({ complete: function() { $('#container').prepend($('
').addClass('loading-overlay')); - window.name = g_loginCmdText; + //window.name = g_loginCmdText; document.location.href = url; } }); diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js index 1c74056c75b..c5e0561606f 100644 --- a/ui/scripts/ui/widgets/listView.js +++ b/ui/scripts/ui/widgets/listView.js @@ -863,16 +863,14 @@ var uiCustom = listViewArgs.uiCustom; var subselect = uiCustom ? listViewArgs.listView.subselect : null; - if (!data || !data.length) { + if (!(data && data.length)) { if (!$tbody.find('tr').size()) { return [ - $('').addClass('empty').append( + $('').addClass('empty last').append( $('').html(_l('label.no.data')) ).appendTo($tbody) ]; } - - return $tbody.find('tr:last').addClass('last'); } $tbody.find('tr.empty').remove(); diff --git a/usage/pom.xml b/usage/pom.xml index 37501fe2744..0ad59b4cf70 100644 --- a/usage/pom.xml +++ b/usage/pom.xml @@ -37,6 +37,11 @@ ${cs.mysql.version} runtime + + commons-daemon + commons-daemon + 1.0.10 + install diff --git a/usage/src/com/cloud/usage/UsageServer.java b/usage/src/com/cloud/usage/UsageServer.java index 3f2b43e2bc9..8a7c852d9e9 100644 --- a/usage/src/com/cloud/usage/UsageServer.java +++ b/usage/src/com/cloud/usage/UsageServer.java @@ -19,6 +19,9 @@ package com.cloud.usage; import java.io.File; import java.io.FileNotFoundException; +import org.apache.commons.daemon.Daemon; +import org.apache.commons.daemon.DaemonContext; +import org.apache.commons.daemon.DaemonInitException; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; import org.apache.log4j.xml.DOMConfigurator; @@ -29,7 +32,7 @@ import org.springframework.util.Log4jConfigurer; import com.cloud.utils.PropertiesUtil; import com.cloud.utils.component.ComponentContext; -public class UsageServer { +public class UsageServer implements Daemon { private static final Logger s_logger = Logger.getLogger(UsageServer.class.getName()); public static final String Name = "usage-server"; @@ -39,15 +42,17 @@ public class UsageServer { * @param args */ public static void main(String[] args) { - initLog4j(); + initLog4j(); UsageServer usage = new UsageServer(); - usage.init(args); usage.start(); } - public void init(String[] args) { + @Override + public void init(DaemonContext arg0) throws DaemonInitException, Exception { + initLog4j(); } + @Override public void start() { ApplicationContext appContext = new ClassPathXmlApplicationContext("usageApplicationContext.xml"); @@ -66,10 +71,12 @@ public class UsageServer { } } + @Override public void stop() { } + @Override public void destroy() { } @@ -96,4 +103,5 @@ public class UsageServer { } } } + } diff --git a/utils/src/com/cloud/utils/SerialVersionUID.java b/utils/src/com/cloud/utils/SerialVersionUID.java index 35e9446b17e..856d5639c50 100755 --- a/utils/src/com/cloud/utils/SerialVersionUID.java +++ b/utils/src/com/cloud/utils/SerialVersionUID.java @@ -61,4 +61,5 @@ public interface SerialVersionUID { public static final long CloudExecutionException = Base | 0x27; public static final long CallFailedException = Base | 0x28; public static final long UnableDeleteHostException = Base | 0x29; + public static final long AffinityConflictException = Base | 0x2a; } diff --git a/utils/src/com/cloud/utils/cisco/n1kv/vsm/NetconfHelper.java b/utils/src/com/cloud/utils/cisco/n1kv/vsm/NetconfHelper.java index be8d68a5648..06718d0f35e 100644 --- a/utils/src/com/cloud/utils/cisco/n1kv/vsm/NetconfHelper.java +++ b/utils/src/com/cloud/utils/cisco/n1kv/vsm/NetconfHelper.java @@ -79,6 +79,17 @@ public class NetconfHelper { parseOkReply(receive()); } + public void addPortProfile(String name, PortProfileType type, BindingType binding, + SwitchPortMode mode, int vlanid, String vdc, String espName) throws CloudRuntimeException { + String command = VsmCommand.getAddPortProfile(name, type, binding, mode, vlanid, vdc, espName); + if (command != null) { + command = command.concat(SSH_NETCONF_TERMINATOR); + parseOkReply(sendAndReceive(command)); + } else { + throw new CloudRuntimeException("Error generating rpc request for adding port profile."); + } + } + public void addPortProfile(String name, PortProfileType type, BindingType binding, SwitchPortMode mode, int vlanid) throws CloudRuntimeException { String command = VsmCommand.getAddPortProfile(name, type, binding, mode, vlanid); @@ -160,6 +171,17 @@ public class NetconfHelper { } } + public void addVServiceNode(String vlanId, String ipAddr) + throws CloudRuntimeException { + String command = VsmCommand.getVServiceNode(vlanId, ipAddr); + if (command != null) { + command = command.concat(SSH_NETCONF_TERMINATOR); + parseOkReply(sendAndReceive(command)); + } else { + throw new CloudRuntimeException("Error generating rpc request for adding vservice node for vlan " + vlanId); + } + } + public PortProfile getPortProfileByName(String name) throws CloudRuntimeException { String command = VsmCommand.getPortProfile(name); if (command != null) { diff --git a/utils/src/com/cloud/utils/cisco/n1kv/vsm/VsmCommand.java b/utils/src/com/cloud/utils/cisco/n1kv/vsm/VsmCommand.java index d1887f6417d..fdab390557d 100644 --- a/utils/src/com/cloud/utils/cisco/n1kv/vsm/VsmCommand.java +++ b/utils/src/com/cloud/utils/cisco/n1kv/vsm/VsmCommand.java @@ -69,6 +69,40 @@ public class VsmCommand { removevlanid } + public static String getAddPortProfile(String name, PortProfileType type, + BindingType binding, SwitchPortMode mode, int vlanid, String vdc, String espName) { + try { + // Create the document and root element. + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + DOMImplementation domImpl = docBuilder.getDOMImplementation(); + Document doc = createDocument(domImpl); + + // Edit configuration command. + Element editConfig = doc.createElement("nf:edit-config"); + doc.getDocumentElement().appendChild(editConfig); + + // Command to get into exec configure mode. + Element target = doc.createElement("nf:target"); + Element running = doc.createElement("nf:running"); + target.appendChild(running); + editConfig.appendChild(target); + + // Command to create the port profile with the desired configuration. + Element config = doc.createElement("nf:config"); + config.appendChild(configPortProfileDetails(doc, name, type, binding, mode, vlanid, vdc, espName)); + editConfig.appendChild(config); + + return serialize(domImpl, doc); + } catch (ParserConfigurationException e) { + s_logger.error("Error while creating add port profile message : " + e.getMessage()); + return null; + } catch (DOMException e) { + s_logger.error("Error while creating add port profile message : " + e.getMessage()); + return null; + } + } + public static String getAddPortProfile(String name, PortProfileType type, BindingType binding, SwitchPortMode mode, int vlanid) { try { @@ -366,6 +400,184 @@ public class VsmCommand { } } + public static String getVServiceNode(String vlanId, String ipAddr) { + try { + // Create the document and root element. + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); + DOMImplementation domImpl = docBuilder.getDOMImplementation(); + Document doc = createDocument(domImpl); + + // Edit configuration command. + Element editConfig = doc.createElement("nf:edit-config"); + doc.getDocumentElement().appendChild(editConfig); + + // Command to get into exec configure mode. + Element target = doc.createElement("nf:target"); + Element running = doc.createElement("nf:running"); + target.appendChild(running); + editConfig.appendChild(target); + + // Command to create the port profile with the desired configuration. + Element config = doc.createElement("nf:config"); + config.appendChild(configVServiceNodeDetails(doc, vlanId, ipAddr)); + editConfig.appendChild(config); + + return serialize(domImpl, doc); + } catch (ParserConfigurationException e) { + s_logger.error("Error while adding vservice node for vlan " + vlanId + ", " + e.getMessage()); + return null; + } catch (DOMException e) { + s_logger.error("Error while adding vservice node for vlan " + vlanId + ", " + e.getMessage()); + return null; + } + } + + private static Element configVServiceNodeDetails(Document doc, String vlanId, String ipAddr) { + // In mode, exec_configure. + Element configure = doc.createElementNS(s_ciscons, "nxos:configure"); + Element modeConfigure = doc.createElement("nxos:" + s_configuremode); + configure.appendChild(modeConfigure); + + // vservice node %name% type asa + Element vservice = doc.createElement("vservice"); + vservice.appendChild(doc.createElement("node")) + .appendChild(doc.createElement("ASA_" + vlanId)) + .appendChild(doc.createElement("type")) + .appendChild(doc.createElement("asa")); + modeConfigure.appendChild(vservice); + + Element address = doc.createElement(s_paramvalue); + address.setAttribute("isKey", "true"); + address.setTextContent(ipAddr); + + // ip address %ipAddr% + modeConfigure.appendChild(doc.createElement("ip")) + .appendChild(doc.createElement("address")) + .appendChild(doc.createElement("value")) + .appendChild(address); + + Element vlan = doc.createElement(s_paramvalue); + vlan.setAttribute("isKey", "true"); + vlan.setTextContent(vlanId); + + // adjacency l2 vlan %vlanId% + modeConfigure.appendChild(doc.createElement("adjacency")) + .appendChild(doc.createElement("l2")) + .appendChild(doc.createElement("vlan")) + .appendChild(doc.createElement("value")) + .appendChild(vlan); + + // fail-mode close + modeConfigure.appendChild(doc.createElement("fail-mode")) + .appendChild(doc.createElement("close")); + + // Persist the configuration across reboots. + modeConfigure.appendChild(persistConfiguration(doc)); + + return configure; + } + + private static Element configPortProfileDetails(Document doc, String name, PortProfileType type, + BindingType binding, SwitchPortMode mode, int vlanid, String vdc, String espName) { + + // In mode, exec_configure. + Element configure = doc.createElementNS(s_ciscons, "nxos:configure"); + Element modeConfigure = doc.createElement("nxos:" + s_configuremode); + configure.appendChild(modeConfigure); + + // Port profile name and type configuration. + Element portProfile = doc.createElement("port-profile"); + modeConfigure.appendChild(portProfile); + + // Port profile type. + Element portDetails = doc.createElement("name"); + switch (type) { + case none: + portProfile.appendChild(portDetails); + break; + case ethernet: + { + Element typetag = doc.createElement("type"); + Element ethernettype = doc.createElement("ethernet"); + portProfile.appendChild(typetag); + typetag.appendChild(ethernettype); + ethernettype.appendChild(portDetails); + } + break; + case vethernet: + { + Element typetag = doc.createElement("type"); + Element ethernettype = doc.createElement("vethernet"); + portProfile.appendChild(typetag); + typetag.appendChild(ethernettype); + ethernettype.appendChild(portDetails); + } + break; + } + + // Port profile name. + Element value = doc.createElement(s_paramvalue); + value.setAttribute("isKey", "true"); + value.setTextContent(name); + portDetails.appendChild(value); + + // element for port prof mode. + Element portProf = doc.createElement(s_portprofmode); + portDetails.appendChild(portProf); + + // Binding type. + if (binding != BindingType.none) { + portProf.appendChild(getBindingType(doc, binding)); + } + + if (mode != SwitchPortMode.none) { + // Switchport mode. + portProf.appendChild(getSwitchPortMode(doc, mode)); + // Adding vlan details. + if (vlanid > 0) { + portProf.appendChild(getAddVlanDetails(doc, mode, Integer.toString(vlanid))); + } + } + + // Command "vmware port-group". + Element vmware = doc.createElement("vmware"); + Element portgroup = doc.createElement("port-group"); + vmware.appendChild(portgroup); + portProf.appendChild(vmware); + + // org root/%vdc% + // vservice node profile + Element org = doc.createElement("org"); + org.appendChild(doc.createElement(vdc)); + portProf.appendChild(org); + + String asaNodeName = "ASA_" + vlanid; + Element vservice = doc.createElement("vservice"); + vservice.appendChild(doc.createElement("node")) + .appendChild(doc.createElement(asaNodeName)) + .appendChild(doc.createElement("profile")) + .appendChild(doc.createElement(espName)); + portProf.appendChild(vservice); + + // no shutdown. + Element no = doc.createElement("no"); + Element shutdown = doc.createElement("shutdown"); + no.appendChild(shutdown); + portProf.appendChild(no); + + // Enable the port profile. + Element state = doc.createElement("state"); + Element enabled = doc.createElement("enabled"); + state.appendChild(enabled); + portProf.appendChild(state); + + // Persist the configuration across reboots. + modeConfigure.appendChild(persistConfiguration(doc)); + + return configure; + } + private static Element configPortProfileDetails(Document doc, String name, PortProfileType type, BindingType binding, SwitchPortMode mode, int vlanid) { @@ -433,6 +645,7 @@ public class VsmCommand { Element portgroup = doc.createElement("port-group"); vmware.appendChild(portgroup); portProf.appendChild(vmware); + // no shutdown. Element no = doc.createElement("no"); diff --git a/utils/src/com/cloud/utils/component/ComponentContext.java b/utils/src/com/cloud/utils/component/ComponentContext.java index 796d4ec0282..5c5194cca2d 100644 --- a/utils/src/com/cloud/utils/component/ComponentContext.java +++ b/utils/src/com/cloud/utils/component/ComponentContext.java @@ -71,14 +71,14 @@ public class ComponentContext implements ApplicationContextAware { beanFactory.configureBean(bean, entry.getKey()); } - Map lifecyleComponents = getApplicationContext().getBeansOfType(ComponentLifecycle.class); + Map lifecycleComponents = getApplicationContext().getBeansOfType(ComponentLifecycle.class); Map[] classifiedComponents = new Map[ComponentLifecycle.MAX_RUN_LEVELS]; for(int i = 0; i < ComponentLifecycle.MAX_RUN_LEVELS; i++) { classifiedComponents[i] = new HashMap(); } - for(Map.Entry entry : lifecyleComponents.entrySet()) { + for(Map.Entry entry : lifecycleComponents.entrySet()) { classifiedComponents[entry.getValue().getRunLevel()].put(entry.getKey(), entry.getValue()); } diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java index 621c091481a..7f323c5e400 100755 --- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java @@ -163,7 +163,8 @@ public class HypervisorHostHelper { } public static void createPortProfile(VmwareContext context, String ethPortProfileName, String networkName, - Integer vlanId, Integer networkRateMbps, long peakBandwidth, long burstSize) throws Exception { + Integer vlanId, Integer networkRateMbps, long peakBandwidth, long burstSize, + String gateway, boolean configureVServiceInNexus) throws Exception { Map vsmCredentials = getValidatedVsmCredentials(context); String vsmIp = vsmCredentials.get("vsmip"); String vsmUserName = vsmCredentials.get("vsmusername"); @@ -233,8 +234,18 @@ public class HypervisorHostHelper { s_logger.info("Adding port profile configured over untagged VLAN."); netconfClient.addPortProfile(networkName, PortProfileType.vethernet, BindingType.portbindingstatic, SwitchPortMode.access, 0); } else { - s_logger.info("Adding port profile configured over VLAN : " + vlanId.toString()); - netconfClient.addPortProfile(networkName, PortProfileType.vethernet, BindingType.portbindingstatic, SwitchPortMode.access, vlanId.intValue()); + if (!configureVServiceInNexus) { + s_logger.info("Adding port profile configured over VLAN : " + vlanId.toString()); + netconfClient.addPortProfile(networkName, PortProfileType.vethernet, BindingType.portbindingstatic, SwitchPortMode.access, vlanId.intValue()); + } else { + String tenant = "vlan-" + vlanId.intValue(); + String vdc = "root/" + tenant + "/VDC-" + tenant; + String esp = "ESP-" + tenant; + s_logger.info("Adding vservice node in Nexus VSM for VLAN : " + vlanId.toString()); + netconfClient.addVServiceNode(vlanId.toString(), gateway); + s_logger.info("Adding port profile with vservice details configured over VLAN : " + vlanId.toString()); + netconfClient.addPortProfile(networkName, PortProfileType.vethernet, BindingType.portbindingstatic, SwitchPortMode.access, vlanId.intValue(), vdc, esp); + } } } catch (CloudRuntimeException e) { msg = "Failed to add vEthernet port profile " + networkName + "." + ". Exception: " + e.toString(); @@ -402,7 +413,7 @@ public class HypervisorHostHelper { public static Pair prepareNetwork(String physicalNetwork, String namePrefix, HostMO hostMo, String vlanId, Integer networkRateMbps, Integer networkRateMulticastMbps, long timeOutMs, - VirtualSwitchType vSwitchType, int numPorts) throws Exception { + VirtualSwitchType vSwitchType, int numPorts, String gateway, boolean configureVServiceInNexus) throws Exception { ManagedObjectReference morNetwork = null; VmwareContext context = hostMo.getContext(); ManagedObjectReference dcMor = hostMo.getHyperHostDatacenter(); @@ -504,22 +515,22 @@ public class HypervisorHostHelper { } else { s_logger.info("Found Ethernet port profile " + ethPortProfileName); } - long averageBandwidth = 0L; - if (networkRateMbps != null && networkRateMbps.intValue() > 0) { - averageBandwidth = (long) (networkRateMbps.intValue() * 1024L * 1024L); - } - // We chose 50% higher allocation than average bandwidth. + long averageBandwidth = 0L; + if (networkRateMbps != null && networkRateMbps.intValue() > 0) { + averageBandwidth = (long) (networkRateMbps.intValue() * 1024L * 1024L); + } + // We chose 50% higher allocation than average bandwidth. // TODO(sateesh): Optionally let user specify the peak coefficient - long peakBandwidth = (long) (averageBandwidth * 1.5); + long peakBandwidth = (long) (averageBandwidth * 1.5); // TODO(sateesh): Optionally let user specify the burst coefficient - long burstSize = 5 * averageBandwidth / 8; + long burstSize = 5 * averageBandwidth / 8; - if (!dataCenterMo.hasDvPortGroup(networkName)) { - s_logger.info("Port profile " + networkName + " not found."); - createPortProfile(context, physicalNetwork, networkName, vid, networkRateMbps, peakBandwidth, burstSize); - bWaitPortGroupReady = true; - } else { - s_logger.info("Port profile " + networkName + " found."); + if (!dataCenterMo.hasDvPortGroup(networkName)) { + s_logger.info("Port profile " + networkName + " not found."); + createPortProfile(context, physicalNetwork, networkName, vid, networkRateMbps, peakBandwidth, burstSize, gateway, configureVServiceInNexus); + bWaitPortGroupReady = true; + } else { + s_logger.info("Port profile " + networkName + " found."); updatePortProfile(context, physicalNetwork, networkName, vid, networkRateMbps, peakBandwidth, burstSize); } }