From 540f4e1431ef059b74ca2d73a75d10d54a7c4758 Mon Sep 17 00:00:00 2001 From: Nitin Mehta Date: Tue, 1 May 2012 18:36:31 +0530 Subject: [PATCH 01/16] bug CS-10789: Put zone id in the volumehost ref table. make list volume to show the percent uploaded. --- .../cloud/api/commands/UploadVolumeCmd.java | 7 ----- .../cloud/api/response/VolumeResponse.java | 10 ++++++- core/src/com/cloud/storage/VolumeHostVO.java | 20 +++++++++++--- server/src/com/cloud/api/ApiDBUtils.java | 9 ++++++- .../src/com/cloud/api/ApiResponseHelper.java | 26 +++++++++++++++++-- .../com/cloud/storage/dao/VolumeHostDao.java | 2 ++ .../cloud/storage/dao/VolumeHostDaoImpl.java | 16 ++++++++++++ .../storage/download/DownloadMonitorImpl.java | 4 +-- setup/db/create-schema.sql | 1 + 9 files changed, 79 insertions(+), 16 deletions(-) diff --git a/api/src/com/cloud/api/commands/UploadVolumeCmd.java b/api/src/com/cloud/api/commands/UploadVolumeCmd.java index fedff6ccc7b..6bebac726aa 100755 --- a/api/src/com/cloud/api/commands/UploadVolumeCmd.java +++ b/api/src/com/cloud/api/commands/UploadVolumeCmd.java @@ -33,9 +33,6 @@ public class UploadVolumeCmd extends BaseCmd { @Parameter(name=ApiConstants.FORMAT, type=CommandType.STRING, required=true, description="the format for the volume. Possible values include QCOW2, OVA, and VHD.") private String format; - @Parameter(name=ApiConstants.HYPERVISOR, type=CommandType.STRING, required=true, description="the target hypervisor for the volume") - private String hypervisor; - @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="the name of the volume") private String volumeName; @@ -64,10 +61,6 @@ public class UploadVolumeCmd extends BaseCmd { return format; } - public String getHypervisor() { - return hypervisor; - } - public String getVolumeName() { return volumeName; } diff --git a/api/src/com/cloud/api/response/VolumeResponse.java b/api/src/com/cloud/api/response/VolumeResponse.java index 9b53a65bed9..471fba7a70e 100755 --- a/api/src/com/cloud/api/response/VolumeResponse.java +++ b/api/src/com/cloud/api/response/VolumeResponse.java @@ -142,6 +142,10 @@ public class VolumeResponse extends BaseResponse implements ControlledEntityResp @SerializedName("isextractable") @Param(description = "true if the volume is extractable, false otherwise") private Boolean extractable; + + @SerializedName(ApiConstants.STATUS) + @Param(description="the status of the volume") + private String status; @Override public Long getObjectId() { @@ -260,7 +264,11 @@ public class VolumeResponse extends BaseResponse implements ControlledEntityResp this.serviceOfferingName = serviceOfferingName; } - public void setServiceOfferingDisplayText(String serviceOfferingDisplayText) { + public void setStatus(String status) { + this.status = status; + } + + public void setServiceOfferingDisplayText(String serviceOfferingDisplayText) { this.serviceOfferingDisplayText = serviceOfferingDisplayText; } diff --git a/core/src/com/cloud/storage/VolumeHostVO.java b/core/src/com/cloud/storage/VolumeHostVO.java index 731e7cc84d9..3bba4e18d6e 100755 --- a/core/src/com/cloud/storage/VolumeHostVO.java +++ b/core/src/com/cloud/storage/VolumeHostVO.java @@ -14,6 +14,7 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; //import com.cloud.storage.VMVolumeStorageResourceAssoc.Status; +import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.utils.db.GenericDaoBase; @@ -35,6 +36,9 @@ public class VolumeHostVO { @Column(name="volume_id") private long volumeId; + @Column(name="zone_id") + private long zoneId; + @Column(name=GenericDaoBase.CREATED_COLUMN) private Date created = null; @@ -103,7 +107,15 @@ public class VolumeHostVO { } - public int getDownloadPercent() { + public long getZoneId() { + return zoneId; + } + + public void setZoneId(long zoneId) { + this.zoneId = zoneId; + } + + public int getDownloadPercent() { return downloadPercent; } @@ -161,13 +173,14 @@ public class VolumeHostVO { this.volumeId = volumeId; } - public VolumeHostVO(long hostId, long volumeId, Date lastUpdated, + public VolumeHostVO(long hostId, long volumeId, long zoneId, Date lastUpdated, int downloadPercent, Status downloadState, String localDownloadPath, String errorString, String jobId, - String installPath, String downloadUrl, String checksum) { + String installPath, String downloadUrl, String checksum, ImageFormat format) { //super(); this.hostId = hostId; this.volumeId = volumeId; + this.zoneId = zoneId; this.lastUpdated = lastUpdated; this.downloadPercent = downloadPercent; this.downloadState = downloadState; @@ -177,6 +190,7 @@ public class VolumeHostVO { this.installPath = installPath; this.setDownloadUrl(downloadUrl); this.checksum = checksum; + this.format = format; } protected VolumeHostVO() { diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 25a6b5119d2..2404535221d 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -91,6 +91,7 @@ import com.cloud.storage.UploadVO; import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.VMTemplateSwiftVO; import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.VolumeHostVO; import com.cloud.storage.Volume.Type; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.DiskOfferingDao; @@ -104,6 +105,7 @@ import com.cloud.storage.dao.VMTemplateDetailsDao; import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.storage.dao.VMTemplateSwiftDao; import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.dao.VolumeHostDao; import com.cloud.user.Account; import com.cloud.user.AccountDetailsDao; import com.cloud.user.AccountVO; @@ -170,6 +172,7 @@ public class ApiDBUtils { private static UserVmDao _userVmDao; private static VlanDao _vlanDao; private static VolumeDao _volumeDao; + private static VolumeHostDao _volumeHostDao; private static DataCenterDao _zoneDao; private static NetworkOfferingDao _networkOfferingDao; private static NetworkDao _networkDao; @@ -222,6 +225,7 @@ public class ApiDBUtils { _userVmDao = locator.getDao(UserVmDao.class); _vlanDao = locator.getDao(VlanDao.class); _volumeDao = locator.getDao(VolumeDao.class); + _volumeHostDao = locator.getDao(VolumeHostDao.class); _zoneDao = locator.getDao(DataCenterDao.class); _securityGroupDao = locator.getDao(SecurityGroupDao.class); _networkOfferingDao = locator.getDao(NetworkOfferingDao.class); @@ -496,7 +500,7 @@ public class ApiDBUtils { public static VMTemplateHostVO findTemplateHostRef(long templateId, long zoneId) { return findTemplateHostRef(templateId, zoneId, false); } - + public static VMTemplateHostVO findTemplateHostRef(long templateId, long zoneId, boolean readyOnly) { VMTemplateVO vmTemplate = findTemplateById(templateId); if (vmTemplate.getHypervisorType() == HypervisorType.BareMetal) { @@ -508,6 +512,9 @@ public class ApiDBUtils { } + public static VolumeHostVO findVolumeHostRef(long volumeId, long zoneId) { + return _volumeHostDao.findVolumeByZone(volumeId, zoneId); + } public static VMTemplateSwiftVO findTemplateSwiftRef(long templateId) { return _templateSwiftDao.findOneByTemplateId(templateId); diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index a230f808021..2be058de276 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -1020,13 +1020,35 @@ public class ApiResponseHelper implements ResponseGenerator { volResponse.setCreated(volume.getCreated()); volResponse.setState(volume.getState().toString()); - + if(volume.getState() == Volume.State.Uploading || volume.getState() == Volume.State.Uploaded){ + com.cloud.storage.VolumeHostVO volumeHostRef = ApiDBUtils.findVolumeHostRef(volume.getId(), volume.getDataCenterId()); + volResponse.setSize(volumeHostRef.getSize()); + volResponse.setCreated(volumeHostRef.getCreated()); + if (volumeHostRef.getDownloadState() != Status.DOWNLOADED) { + String volumeStatus = "Processing"; + if (volumeHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOAD_IN_PROGRESS) { + if (volumeHostRef.getDownloadPercent() == 100) { + volumeStatus = "Checking Volume"; + } else { + volumeStatus = volumeHostRef.getDownloadPercent() + "% Uploaded"; + } + } else { + volumeStatus = volumeHostRef.getErrorString(); + } + volResponse.setStatus(volumeStatus); + } else if (volumeHostRef.getDownloadState() == VMTemplateHostVO.Status.DOWNLOADED) { + volResponse.setStatus("Upload Complete"); + } else { + volResponse.setStatus("Successfully Installed"); + } + } + populateOwner(volResponse, volume); String storageType; try { if (volume.getPoolId() == null) { - if (volume.getState() == Volume.State.Allocated) { + if (volume.getState() == Volume.State.Allocated || volume.getState() == Volume.State.Uploaded || volume.getState() == Volume.State.Uploading) { /* set it as shared, so the UI can attach it to VM */ storageType = "shared"; } else { diff --git a/server/src/com/cloud/storage/dao/VolumeHostDao.java b/server/src/com/cloud/storage/dao/VolumeHostDao.java index f4d667ad021..5dfe2674680 100755 --- a/server/src/com/cloud/storage/dao/VolumeHostDao.java +++ b/server/src/com/cloud/storage/dao/VolumeHostDao.java @@ -16,4 +16,6 @@ public interface VolumeHostDao extends GenericDao { List listDestroyed(long hostId); + VolumeHostVO findVolumeByZone(long zoneId, long volumeId); + } diff --git a/server/src/com/cloud/storage/dao/VolumeHostDaoImpl.java b/server/src/com/cloud/storage/dao/VolumeHostDaoImpl.java index 5c205fd0561..95c6efa8e9d 100755 --- a/server/src/com/cloud/storage/dao/VolumeHostDaoImpl.java +++ b/server/src/com/cloud/storage/dao/VolumeHostDaoImpl.java @@ -15,6 +15,7 @@ import com.cloud.utils.db.SearchCriteria; public class VolumeHostDaoImpl extends GenericDaoBase implements VolumeHostDao { protected final SearchBuilder HostVolumeSearch; + protected final SearchBuilder ZoneVolumeSearch; protected final SearchBuilder VolumeSearch; protected final SearchBuilder HostSearch; protected final SearchBuilder HostDestroyedSearch; @@ -26,6 +27,12 @@ public class VolumeHostDaoImpl extends GenericDaoBase implem HostVolumeSearch.and("destroyed", HostVolumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); HostVolumeSearch.done(); + ZoneVolumeSearch = createSearchBuilder(); + ZoneVolumeSearch.and("zone_id", ZoneVolumeSearch.entity().getZoneId(), SearchCriteria.Op.EQ); + ZoneVolumeSearch.and("volume_id", ZoneVolumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); + ZoneVolumeSearch.and("destroyed", ZoneVolumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + ZoneVolumeSearch.done(); + HostSearch = createSearchBuilder(); HostSearch.and("host_id", HostSearch.entity().getHostId(), SearchCriteria.Op.EQ); HostSearch.and("destroyed", HostSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); @@ -53,6 +60,15 @@ public class VolumeHostDaoImpl extends GenericDaoBase implem return findOneIncludingRemovedBy(sc); } + @Override + public VolumeHostVO findVolumeByZone(long volumeId, long zoneId) { + SearchCriteria sc = ZoneVolumeSearch.create(); + sc.setParameters("zone_id", zoneId); + sc.setParameters("volume_id", volumeId); + sc.setParameters("destroyed", false); + return findOneIncludingRemovedBy(sc); + } + @Override public VolumeHostVO findByVolumeId(long volumeId) { SearchCriteria sc = VolumeSearch.create(); diff --git a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java index 927a6e5f014..8501fd224ef 100755 --- a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java +++ b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java @@ -435,8 +435,8 @@ public class DownloadMonitorImpl implements DownloadMonitor { volumeHost = _volumeHostDao.findByHostVolume(sserver.getId(), volume.getId()); if (volumeHost == null) { - volumeHost = new VolumeHostVO(sserver.getId(), volume.getId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null, - "jobid0000", null, url, checkSum); + volumeHost = new VolumeHostVO(sserver.getId(), volume.getId(), sserver.getDataCenterId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null, + "jobid0000", null, url, checkSum, format); _volumeHostDao.persist(volumeHost); } else if ((volumeHost.getJobId() != null) && (volumeHost.getJobId().length() > 2)) { downloadJobExists = true; diff --git a/setup/db/create-schema.sql b/setup/db/create-schema.sql index d7878f71f28..5c4bab5ebc7 100755 --- a/setup/db/create-schema.sql +++ b/setup/db/create-schema.sql @@ -1125,6 +1125,7 @@ CREATE TABLE `cloud`.`volume_host_ref` ( `id` bigint unsigned NOT NULL auto_increment, `host_id` bigint unsigned NOT NULL, `volume_id` bigint unsigned NOT NULL, + `zone_id` bigint unsigned NOT NULL, `created` DATETIME NOT NULL, `last_updated` DATETIME, `job_id` varchar(255), From 22f20e5fb95d2bcb55770af90a17c6b7dd3d29b9 Mon Sep 17 00:00:00 2001 From: frank Date: Tue, 1 May 2012 09:28:28 -0700 Subject: [PATCH 02/16] add CloudStack.cfg.xml from cloudbridge conf folder to cloudstack conf folder --- cloud.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloud.spec b/cloud.spec index 49eb8259b5d..ded39fb0430 100644 --- a/cloud.spec +++ b/cloud.spec @@ -442,7 +442,7 @@ if [ "$1" == "1" ] ; then cp -f $root/lib/$j $root/webapps/awsapi/WEB-INF/lib/ done - confs="cloud-bridge.properties ec2-service.properties hibernate.cfg.xml log4j-cloud-bridge.xml" + confs="cloud-bridge.properties ec2-service.properties hibernate.cfg.xml log4j-cloud-bridge.xml CloudStack.cfg.xml" for c in $confs do cp -f $root/conf/$c $target/conf From 97b54c9c2bb0086fbcc6ab6c0449a543078a1d59 Mon Sep 17 00:00:00 2001 From: frank Date: Tue, 1 May 2012 09:48:18 -0700 Subject: [PATCH 03/16] remove log4j-cloud-bridge.xml CloudBridge no longer uses separate log4j configure --- cloud.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cloud.spec b/cloud.spec index ded39fb0430..f6fbf9f5ad5 100644 --- a/cloud.spec +++ b/cloud.spec @@ -442,7 +442,7 @@ if [ "$1" == "1" ] ; then cp -f $root/lib/$j $root/webapps/awsapi/WEB-INF/lib/ done - confs="cloud-bridge.properties ec2-service.properties hibernate.cfg.xml log4j-cloud-bridge.xml CloudStack.cfg.xml" + confs="cloud-bridge.properties ec2-service.properties hibernate.cfg.xml CloudStack.cfg.xml" for c in $confs do cp -f $root/conf/$c $target/conf From c32611abf96222a219afa7faeb6cdb3bdc9783ca Mon Sep 17 00:00:00 2001 From: bfederle Date: Tue, 1 May 2012 13:02:47 -0700 Subject: [PATCH 04/16] Infrastructure UI: remove button Remove old 'view all' button from corner of infrastructure chart --- ui/index.jsp | 3 --- 1 file changed, 3 deletions(-) diff --git a/ui/index.jsp b/ui/index.jsp index 041a672111a..63b9973087f 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -951,9 +951,6 @@
-
  • From c45412cc7c8df8cc22bc55a0ac08cf2d92f4189c Mon Sep 17 00:00:00 2001 From: bfederle Date: Tue, 1 May 2012 13:35:52 -0700 Subject: [PATCH 05/16] Better tab BG appearance for VLAN range step --- ui/css/cloudstack3.css | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 2a42d471136..057508f72d9 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -5446,7 +5446,11 @@ label.error { .multi-wizard.zone-wizard .select-container { height: 333px; overflow: auto; - /*[empty]display:;*/ +} + +.multi-wizard.zone-wizard .setup-guest-traffic .select-container { + background: #E9EAEB; + overflow: hidden; } .multi-wizard.zone-wizard .main-desc { @@ -6027,7 +6031,7 @@ label.error { /*** Configure guest network -- tabs*/ .multi-wizard.zone-wizard .setup-guest-traffic .ui-widget-content { width: 682px; - height: 244px; + height: 281px; border-bottom: none; border-right: none; /*+placement:shift -1px -7px;*/ From 90774621f1391650dba1365f94319b111dc9500d Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Tue, 1 May 2012 15:36:35 -0700 Subject: [PATCH 06/16] Fix keepalived process not started issue --- .../config/opt/cloud/bin/patchsystemvm.sh | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/patches/systemvm/debian/config/opt/cloud/bin/patchsystemvm.sh b/patches/systemvm/debian/config/opt/cloud/bin/patchsystemvm.sh index 545ba841b63..6f0a0f234af 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/patchsystemvm.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/patchsystemvm.sh @@ -40,6 +40,8 @@ consoleproxy_svcs() { chkconfig apache2 off chkconfig nfs-common off chkconfig portmap off + chkconfig keepalived off + chkconfig conntrackd off echo "cloud postinit ssh" > /var/cache/cloud/enabled_svcs echo "cloud-passwd-srvr haproxy dnsmasq apache2 nfs-common portmap" > /var/cache/cloud/disabled_svcs mkdir -p /var/log/cloud @@ -55,6 +57,8 @@ secstorage_svcs() { chkconfig nfs-common on chkconfig ssh on chkconfig apache2 off + chkconfig keepalived off + chkconfig conntrackd off echo "cloud postinit ssh nfs-common portmap" > /var/cache/cloud/enabled_svcs echo "cloud-passwd-srvr haproxy dnsmasq" > /var/cache/cloud/disabled_svcs mkdir -p /var/log/cloud @@ -72,14 +76,19 @@ routing_svcs() { if [ $RROUTER -eq 0 ] then chkconfig dnsmasq off + chkconfig keepalived on + chkconfig conntrackd on chkconfig postinit on - echo "postinit" > /var/cache/cloud/enabled_svcs + echo "keepalived conntrackd postinit" > /var/cache/cloud/enabled_svcs + echo "dnsmasq " > /var/cache/cloud/disabled_svcs else chkconfig dnsmasq on chkconfig keepalived off chkconfig conntrackd off + echo "dnsmasq " > /var/cache/cloud/enabled_svcs + echo "keepalived conntrackd " > /var/cache/cloud/disabled_svcs fi - echo "cloud-passwd-srvr ssh dnsmasq haproxy apache2" >> /var/cache/cloud/enabled_svcs + echo "cloud-passwd-srvr ssh haproxy apache2" >> /var/cache/cloud/enabled_svcs echo "cloud nfs-common portmap" > /var/cache/cloud/disabled_svcs } @@ -91,6 +100,8 @@ dhcpsrvr_svcs() { chkconfig ssh on chkconfig nfs-common off chkconfig portmap off + chkconfig keepalived off + chkconfig conntrackd off echo "cloud-passwd-srvr ssh dnsmasq apache2" > /var/cache/cloud/enabled_svcs echo "cloud nfs-common haproxy portmap" > /var/cache/cloud/disabled_svcs } @@ -101,6 +112,8 @@ elbvm_svcs() { chkconfig ssh on chkconfig nfs-common off chkconfig portmap off + chkconfig keepalived off + chkconfig conntrackd off echo "ssh haproxy" > /var/cache/cloud/enabled_svcs echo "cloud cloud-passwd-srvr dnsmasq apache2 nfs-common portmap" > /var/cache/cloud/disabled_svcs } From e34fcff9b961d768316f31740db2bcdaec32ad7f Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Tue, 1 May 2012 15:39:47 -0700 Subject: [PATCH 07/16] Don't bring up eth2 for booting process of redundant router --- patches/systemvm/debian/config/etc/init.d/cloud-early-config | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/patches/systemvm/debian/config/etc/init.d/cloud-early-config b/patches/systemvm/debian/config/etc/init.d/cloud-early-config index 6033402b458..9c0d189046f 100755 --- a/patches/systemvm/debian/config/etc/init.d/cloud-early-config +++ b/patches/systemvm/debian/config/etc/init.d/cloud-early-config @@ -205,10 +205,9 @@ setup_interface() { ifdown $intf else ifdown $intf - ifup $intf - if [ "$RROUTER" == "1" -a "$1" == "2" ] + if [ "$RROUTER" != "1" -o "$1" != "2" ] then - ifdown $intf + ifup $intf fi fi } From 57892fef6b7fab87157828e9523efc9869c61b4f Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Tue, 1 May 2012 16:50:47 -0700 Subject: [PATCH 08/16] Added another testclient --- build/build-tests.xml | 2 + test/conf/demo/commandstype.properties | 4 + test/conf/demo/setup.properties | 9 + test/src/com/cloud/test/demo/Demo.java | 211 ++++++++++++++++++ .../com/cloud/test/utils/UtilsForTest.java | 60 +++++ 5 files changed, 286 insertions(+) create mode 100644 test/conf/demo/commandstype.properties create mode 100644 test/conf/demo/setup.properties create mode 100644 test/src/com/cloud/test/demo/Demo.java diff --git a/build/build-tests.xml b/build/build-tests.xml index 544a496c69a..fa375479a7a 100755 --- a/build/build-tests.xml +++ b/build/build-tests.xml @@ -132,6 +132,8 @@ + + diff --git a/test/conf/demo/commandstype.properties b/test/conf/demo/commandstype.properties new file mode 100644 index 00000000000..6d70b267356 --- /dev/null +++ b/test/conf/demo/commandstype.properties @@ -0,0 +1,4 @@ +deployVirtualMachine=async +listPublicIpAddresses=sync +associateIPAddress=sync +createPortForwardingRule=async \ No newline at end of file diff --git a/test/conf/demo/setup.properties b/test/conf/demo/setup.properties new file mode 100644 index 00000000000..e6802e343a5 --- /dev/null +++ b/test/conf/demo/setup.properties @@ -0,0 +1,9 @@ +hostname=localhost +apikey=p62of2UV0INfl9Jyg-vl90nAnhPMg9vioiHc5QBcx4DyeUl_OZLEWxMVzqtdzmLlgIoMz5yNmrSUy0z1bdIOHA +secretkey=UZeggpLS1n5XqzQ-CDGJt04Vk8i3kwF-Q7FGy0whGf_awy_rWTqt4Ui3cEJNEPLu5gt9m34kZNVOl5wptauaEg +account=admin +domainId=1 +serviceOfferingId=1 +networkId=204 +templateId=5 +zoneId==1 \ No newline at end of file diff --git a/test/src/com/cloud/test/demo/Demo.java b/test/src/com/cloud/test/demo/Demo.java new file mode 100644 index 00000000000..1545d7c7e45 --- /dev/null +++ b/test/src/com/cloud/test/demo/Demo.java @@ -0,0 +1,211 @@ +// Copyright 2012 Citrix Systems, Inc. Licensed under the +// Apache License, Version 2.0 (the "License"); you may not use this +// file except in compliance with the License. Citrix Systems, Inc. +// reserves all rights not expressly granted by the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Automatically generated by addcopyright.py at 04/03/2012 +package com.cloud.test.demo; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Properties; + +import com.cloud.test.utils.UtilsForTest; +import com.cloud.utils.PropertiesUtil; +import com.trilead.ssh2.ChannelCondition; +import com.trilead.ssh2.Connection; +import com.trilead.ssh2.Session; + +/** + * @author Alena Prokharchyk + */ +public class Demo { + private static HashMap _apiCommands = new HashMap(); + private static Properties properties = new Properties(); + + public static void main(String[] args){ + //read properties files + readCommandsType(); + readDeployConfig(); + String publicIp = createDeployment(); + //setup httpd on the user vms + //setupHttpd(publicIp, "password"); + + System.out.println("\nURL is " + "http://" + publicIp + "/cloudcom-faq.html"); + } + + private static void readCommandsType() { + Properties preProcessedCommands = new Properties(); + String configFile = "../conf/demo/commandstype.properties"; + File commandsFile = PropertiesUtil.findConfigFile(configFile); + try { + if (commandsFile != null) { + preProcessedCommands.load(new FileInputStream(commandsFile)); + for (Object key : preProcessedCommands.keySet()) { + String strKey = (String)key; + String asyncParams = (String)preProcessedCommands.getProperty(strKey); + boolean isAsync = false; + if (String.valueOf(asyncParams).equalsIgnoreCase("async")) { + isAsync=true; + } + _apiCommands.put(strKey, isAsync); + } + } + } catch (FileNotFoundException fnfex) { + System.exit(1); + } catch (IOException ex) { + System.out.println("ERROR: Error reading properites file " + configFile); + System.exit(1); + } finally { + if (commandsFile == null) { + System.out.println("ERROR: Unable to find properites file " + configFile); + } + } + } + + private static void readDeployConfig() { + String configFile = "../conf/demo/setup.properties"; + File commandsFile = PropertiesUtil.findConfigFile(configFile); + try { + if (commandsFile != null) { + properties.load(new FileInputStream(commandsFile)); + } + } catch (FileNotFoundException fnfex) { + System.exit(1); + } catch (IOException ex) { + System.out.println("ERROR: Error reading properites file " + configFile); + System.exit(1); + } finally { + if (commandsFile == null) { + System.out.println("ERROR: Unable to find properites file " + configFile); + } + } + } + + private static void setupHttpd(String host, String password) { + if (host == null) { + System.out.println("Did not receive a host back from test, ignoring ssh test"); + System.exit(1); + } + + if (password == null) { + System.out.println("Did not receive a password back from test, ignoring ssh test"); + System.exit(1); + } + + try { + System.out.println("Sleeping for 1 min before trying to ssh into linux host "); + //Thread.sleep(60000); + System.out.println("Attempting to SSH into linux host " + host); + + Connection conn = new Connection(host); + conn.connect(null, 60000, 60000); + + System.out.println("User root ssHed successfully into linux host " + host); + + boolean isAuthenticated = conn.authenticateWithPassword("root", password); + + if (isAuthenticated == false) { + System.out.println("ERROR: Authentication failed for root with password" + password); + System.exit(1); + } + + boolean success = false; + String linuxCommand = "yum install httpd -y && service httpd start && service iptables stop && cd /var/www/html && wget cloud.com"; + + Session sess = conn.openSession(); + System.out.println("User root executing : " + linuxCommand); + sess.execCommand(linuxCommand); + + InputStream stdout = sess.getStdout(); + InputStream stderr = sess.getStderr(); + + byte[] buffer = new byte[8192]; + while (true) { + if ((stdout.available() == 0) && (stderr.available() == 0)) { + int conditions = sess.waitForCondition(ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA | ChannelCondition.EOF, 120000); + + if ((conditions & ChannelCondition.TIMEOUT) != 0) { + System.out.println("ERROR: Timeout while waiting for data from peer."); + System.exit(1); + } + + if ((conditions & ChannelCondition.EOF) != 0) { + if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) { + break; + } + } + } + + while (stdout.available() > 0) { + success = true; + int len = stdout.read(buffer); + if (len > 0) + System.out.println(new String(buffer, 0, len)); + } + + while (stderr.available() > 0) { + /* int len = */stderr.read(buffer); + } + } + + sess.close(); + conn.close(); + + if (!success) { + System.out.println("ERROR: SSH Linux Network test failed: unable to setup httpd"); + System.exit(1); + } + } catch (Exception e) { + System.out.println("ERROR: SSH Linux Network test fail with error " + e.getMessage()); + System.exit(1); + } + System.out.println("Httpd is setup succesfully on the user vm"); + } + + public static String createDeployment() { + //1) deployVm + String urlToSign = "command=deployVirtualMachine&serviceOfferingId=" + properties.getProperty("serviceOfferingId") + + "&networkId=" + properties.getProperty("networkId") + + "&templateId=" + properties.getProperty("templateId") + "&zoneId=" + properties.getProperty("zoneId"); + String url = UtilsForTest.signUrl(urlToSign, properties.getProperty("apikey"), + properties.getProperty("secretkey")); + System.out.println("http://" + properties.getProperty("hostname") + ":8080/client/api?" + url); + long vmId=3; + + //2) List public IP address - source nat + urlToSign = "command=listPublicIpAddresses&zoneId=" + properties.getProperty("zoneId"); + url = UtilsForTest.signUrl(urlToSign, properties.getProperty("apikey"), + properties.getProperty("secretkey")); + System.out.println("http://" + properties.getProperty("hostname") + ":8080/client/api?" + url); + long ipId=67; + + //3) create portForwarding rules for port 22 and 80 + urlToSign = "command=createPortForwardingRule&privateport=22&publicport=22&protocol=tcp&ipaddressid=" + ipId + + "&virtualmachineid=" + vmId; + url = UtilsForTest.signUrl(urlToSign, properties.getProperty("apikey"), + properties.getProperty("secretkey")); + System.out.println("http://" + properties.getProperty("hostname") + ":8080/client/api?" + url); + + urlToSign = "command=createPortForwardingRule&privateport=80&publicport=80&protocol=tcp&ipaddressid=" + ipId + + "&virtualmachineid=" + vmId; + url = UtilsForTest.signUrl(urlToSign, properties.getProperty("apikey"), + properties.getProperty("secretkey")); + System.out.println("http://" + properties.getProperty("hostname") + ":8080/client/api?" + url); + + + return "10.223.153.76"; + } + +} + diff --git a/test/src/com/cloud/test/utils/UtilsForTest.java b/test/src/com/cloud/test/utils/UtilsForTest.java index 4c09b118fc0..90901da6e7a 100644 --- a/test/src/com/cloud/test/utils/UtilsForTest.java +++ b/test/src/com/cloud/test/utils/UtilsForTest.java @@ -14,12 +14,17 @@ package com.cloud.test.utils; import java.io.InputStream; import java.math.BigInteger; +import java.net.URLEncoder; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.TreeMap; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; @@ -228,6 +233,61 @@ public class UtilsForTest { ex.printStackTrace(); } return null; + } + + public static String signUrl(String url, String apiKey, String secretKey) { + + //sorted map (sort by key) + TreeMap param = new TreeMap(); + + String temp = ""; + param.put("apikey", apiKey); + + //1) Parse the URL and put all parameters to sorted map + StringTokenizer str1 = new StringTokenizer (url, "&"); + while(str1.hasMoreTokens()) { + String newEl = str1.nextToken(); + StringTokenizer str2 = new StringTokenizer(newEl, "="); + String name = str2.nextToken(); + String value= str2.nextToken(); + param.put(name, value); + } + + //2) URL encode parameters' values + Set> c = param.entrySet(); + Iterator> it = c.iterator(); + while (it.hasNext()) { + Map.Entry me = (Map.Entry)it.next(); + String key = (String) me.getKey(); + String value = (String) me.getValue(); + try { + temp = temp + key + "=" + URLEncoder.encode(value, "UTF-8") + "&"; + } catch (Exception ex) { + System.out.println("Unable to set parameter " + value + " for the command " + param.get("command")); + System.exit(1); + } + + } + temp = temp.substring(0, temp.length()-1 ); + + //3) Lower case the request + String requestToSign = temp.toLowerCase(); + + //4) Generate the signature + String signature = UtilsForTest.signRequest(requestToSign, secretKey); + + //5) Encode the signature + String encodedSignature = ""; + try { + encodedSignature = URLEncoder.encode(signature, "UTF-8"); + } catch (Exception ex) { + System.out.println(ex); + System.exit(1); + } + + //6) append the signature to the url + url = temp + "&signature=" + encodedSignature; + return url; } } From 8cb97f47dc160537e517682138c64ad993440128 Mon Sep 17 00:00:00 2001 From: Alena Prokharchyk Date: Tue, 1 May 2012 17:08:32 -0700 Subject: [PATCH 09/16] build-all: give more RAM to compile-aws --- build/build-common.xml | 4 +++- wscript | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/build/build-common.xml b/build/build-common.xml index e22db9dd0b6..8cf0bbcf6a9 100755 --- a/build/build-common.xml +++ b/build/build-common.xml @@ -46,7 +46,9 @@ - + diff --git a/wscript b/wscript index ca74cc2b76e..edabbdaf1ff 100644 --- a/wscript +++ b/wscript @@ -3,7 +3,7 @@ # the following two variables are used by the target "waf dist" # if you change 'em here, you need to change it also in cloud.spec, add a %changelog entry there, and add an entry in debian/changelog -VERSION = '3.0.1.2012-04-18T22:05:29Z' +VERSION = '3.0.3.2012-05-02T00:07:57Z' APPNAME = 'cloud' import shutil,os From 3eb95b9b5f2ff47d85448007759331101615af50 Mon Sep 17 00:00:00 2001 From: prachi Date: Tue, 1 May 2012 19:04:53 -0700 Subject: [PATCH 10/16] More changes to testclient --- .../cloud/test/demo/CloudStackHttpClient.java | 215 ++++++++ test/src/com/cloud/test/demo/Demo.java | 38 +- .../test/demo/response/ApiConstants.java | 505 ++++++++++++++++++ .../demo/response/CloudStackIngressRule.java | 87 +++ .../demo/response/CloudStackIpAddress.java | 151 ++++++ .../test/demo/response/CloudStackNic.java | 104 ++++ .../CloudStackPortForwardingRule.java | 153 ++++++ .../response/CloudStackSecurityGroup.java | 81 +++ .../response/CloudStackServiceOffering.java | 181 +++++++ .../test/demo/response/CloudStackUserVm.java | 397 ++++++++++++++ 10 files changed, 1906 insertions(+), 6 deletions(-) create mode 100644 test/src/com/cloud/test/demo/CloudStackHttpClient.java create mode 100644 test/src/com/cloud/test/demo/response/ApiConstants.java create mode 100644 test/src/com/cloud/test/demo/response/CloudStackIngressRule.java create mode 100644 test/src/com/cloud/test/demo/response/CloudStackIpAddress.java create mode 100644 test/src/com/cloud/test/demo/response/CloudStackNic.java create mode 100644 test/src/com/cloud/test/demo/response/CloudStackPortForwardingRule.java create mode 100644 test/src/com/cloud/test/demo/response/CloudStackSecurityGroup.java create mode 100644 test/src/com/cloud/test/demo/response/CloudStackServiceOffering.java create mode 100644 test/src/com/cloud/test/demo/response/CloudStackUserVm.java diff --git a/test/src/com/cloud/test/demo/CloudStackHttpClient.java b/test/src/com/cloud/test/demo/CloudStackHttpClient.java new file mode 100644 index 00000000000..806ea2b87a5 --- /dev/null +++ b/test/src/com/cloud/test/demo/CloudStackHttpClient.java @@ -0,0 +1,215 @@ +package com.cloud.test.demo; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Type; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.List; + + +import com.cloud.test.demo.response.ApiConstants; +import com.cloud.test.demo.response.CloudStackIpAddress; +import com.cloud.test.demo.response.CloudStackPortForwardingRule; +import com.cloud.test.demo.response.CloudStackUserVm; +import com.cloud.test.demo.response.CloudStackServiceOffering; +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.google.gson.reflect.TypeToken; + +public class CloudStackHttpClient { + + + /*public static void main (String[] args) { + + try { + //list serviceOfferings + String requestUrl = "http://localhost:8096/client/api?command=listServiceOfferings&issystem=false&response=json"; + List offerings = execute(requestUrl, "listserviceofferingsresponse", "serviceoffering", new TypeToken>() {}.getType()); + + for(CloudStackServiceOffering offering : offerings){ + System.out.println("id: "+ offering.getId()); + System.out.println("name: "+ offering.getName()); + } + + //list VMs + requestUrl = "http://localhost:8096/client/api?command=listVirtualMachines&listAll=true&response=json"; + List vmList = execute(requestUrl, "listvirtualmachinesresponse", "virtualmachine", new TypeToken>() {}.getType() ); + + for(CloudStackUserVm vm : vmList){ + System.out.println("id: "+ vm.getId()); + System.out.println("state: "+ vm.getState()); + } + /* + //list PF rules + requestUrl = "http://localhost:8096/client/api?command=listPortForwardingRules&response=json"; + List pfList = execute(requestUrl, "listportforwardingrulesresponse", "portforwardingrule", new TypeToken>() {}.getType() ); + + for(CloudStackPortForwardingRule pf : pfList){ + System.out.println("id: "+ pf.getId()); + } + + //list IP + requestUrl = "http://localhost:8096/client/api?command=listPublicIpAddresses&response=json"; + List ipList = execute(requestUrl, "listpublicipaddressesresponse", "publicipaddress", new TypeToken>() {}.getType() ); + + for(CloudStackIpAddress ipaddress : ipList){ + System.out.println("id: "+ ipaddress.getId()); + } + + requestUrl = "http://localhost:8096/client/api?command=deployVirtualMachine&response=json&serviceofferingid=afd925fa-995a-41d2-97f2-5ff475393946&zoneid=97356452-8f0d-429a-8b10-c8694d8a194c&templateid=83ad7959-c0ee-4625-b235-f9a66c0826d8&size=0"; + CloudStackUserVm vm = execute(requestUrl, true, "deployvirtualmachineresponse", "virtualmachine", CloudStackUserVm.class); + System.out.println("id: "+ vm.getId()); + + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + }*/ + + + public List execute(String request, String responseName, String responseObjName, Type collectionType){ + JsonElement jsonElement; + try { + jsonElement = execute(request); + + JsonElement response = getChildElement(jsonElement,responseName); + JsonElement responseObj = getChildElement(response,responseObjName); + + if(responseObj == null){ + return (new Gson()).fromJson(new JsonArray(), collectionType); + } + + if(responseObj.isJsonArray()){ + JsonArray responseObjElementArray = responseObj.getAsJsonArray(); + for(JsonElement responseObjElement : responseObjElementArray){ + System.out.println(responseObjName + ":" + responseObjElement.toString()); + } + return (new Gson()).fromJson(responseObjElementArray, collectionType); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return (new Gson()).fromJson(new JsonArray(), collectionType); + } + + return (new Gson()).fromJson(new JsonArray(), collectionType); + } + + private JsonElement getChildElement(JsonElement parent, String childName){ + JsonObject obj = parent.getAsJsonObject(); + JsonElement child = obj.get(childName); + return child; + } + + public T execute(String request, boolean followToAsyncResult, + String responseName, String responseObjName, Class responseClz){ + + assert(responseName != null); + long _pollTimeoutMs = 600000; + long _pollIntervalMs = 2000; // 1 second polling interval + + try{ + JsonElement jsonElement = execute(request); + if(followToAsyncResult) { + + long startMs = System.currentTimeMillis(); + + String queryJobResult = "http://localhost:8096/client/api?command=queryAsyncJobResult&response=json&jobId="; + + JsonElement response = getChildElement(jsonElement, responseName); + JsonElement jobIdEle = getChildElement(response, "jobid"); + + String jobId = jobIdEle.getAsString(); + queryJobResult = queryJobResult+jobId; + + while(System.currentTimeMillis() - startMs < _pollTimeoutMs) { + + JsonElement queryAsyncJobResponse = execute(queryJobResult); + JsonElement response2 = getChildElement(queryAsyncJobResponse, "queryasyncjobresultresponse"); + + + if(response2 != null) { + JsonElement jobStatusEle = getChildElement(response2, "jobstatus"); + int jobStatus = jobStatusEle.getAsInt(); + switch(jobStatus) { + case 2: + throw new Exception();//queryAsyncJobResponse.getAsString("queryasyncjobresultresponse.jobresult.errorcode") + " " + + //queryAsyncJobResponse.getAsString("queryasyncjobresultresponse.jobresult.errortext")); + + case 0 : + try { + Thread.sleep( _pollIntervalMs ); + } catch( Exception e ) {} + break; + + case 1 : + JsonElement jobresultObj = getChildElement(response2,"jobresult"); + if(jobresultObj == null){ + return null; + } + + JsonElement responseObj = getChildElement(jobresultObj,responseObjName); + return (T)(new Gson()).fromJson(responseObj, responseClz); + + default : + assert(false); + throw new Exception("Operation failed - invalid job status response"); + } + } else { + throw new Exception("Operation failed - invalid JSON response"); + } + } + + throw new Exception("Operation failed - async-job query timed out"); + } else { + + JsonElement response = getChildElement(jsonElement,responseName); + JsonElement responseObj = getChildElement(response,responseObjName); + if(responseObj == null){ + return null; + } + return (T)(new Gson()).fromJson(responseObj, responseClz); + } + }catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + } + + private JsonElement execute(String request) throws Exception { + JsonParser parser = new JsonParser(); + URL url = new URL(request); + + System.out.println("Cloud API call + [" + url.toString() + "]"); + + URLConnection connect = url.openConnection(); + + int statusCode; + statusCode = ((HttpURLConnection)connect).getResponseCode(); + if(statusCode >= 400) { + System.out.println("Cloud API call + [" + url.toString() + "] failed with status code: " + statusCode); + throw new IOException("CloudStack API call HTTP response error, HTTP status code: " + statusCode); + } + + InputStream inputStream = connect.getInputStream(); + JsonElement jsonElement = parser.parse(new InputStreamReader(inputStream)); + if(jsonElement == null) { + System.out.println("Cloud API call + [" + url.toString() + "] failed: unable to parse expected JSON response"); + + throw new IOException("CloudStack API call error : invalid JSON response"); + } + + System.out.println("Cloud API call + [" + url.toString() + "] returned: " + jsonElement.toString()); + return jsonElement; + + } + +} diff --git a/test/src/com/cloud/test/demo/Demo.java b/test/src/com/cloud/test/demo/Demo.java index 1545d7c7e45..1cacbf63ea3 100644 --- a/test/src/com/cloud/test/demo/Demo.java +++ b/test/src/com/cloud/test/demo/Demo.java @@ -18,10 +18,15 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; +import java.util.List; import java.util.Properties; +import com.cloud.test.demo.response.CloudStackPortForwardingRule; +import com.cloud.test.demo.response.CloudStackIpAddress; +import com.cloud.test.demo.response.CloudStackUserVm; import com.cloud.test.utils.UtilsForTest; import com.cloud.utils.PropertiesUtil; +import com.google.gson.reflect.TypeToken; import com.trilead.ssh2.ChannelCondition; import com.trilead.ssh2.Connection; import com.trilead.ssh2.Session; @@ -180,31 +185,52 @@ public class Demo { "&templateId=" + properties.getProperty("templateId") + "&zoneId=" + properties.getProperty("zoneId"); String url = UtilsForTest.signUrl(urlToSign, properties.getProperty("apikey"), properties.getProperty("secretkey")); - System.out.println("http://" + properties.getProperty("hostname") + ":8080/client/api?" + url); - long vmId=3; + String requestUrl = "http://" + properties.getProperty("hostname") + ":8080/client/api?" + url; + System.out.println(requestUrl); + + CloudStackHttpClient client = new CloudStackHttpClient(); + + CloudStackUserVm vm = client.execute(requestUrl, _apiCommands.get("deployVirtualMachine"), "deployvirtualmachineresponse", "virtualmachine", CloudStackUserVm.class); + + String vmId = null; + if(vm != null){ + vmId = vm.getId(); + } + //2) List public IP address - source nat urlToSign = "command=listPublicIpAddresses&zoneId=" + properties.getProperty("zoneId"); url = UtilsForTest.signUrl(urlToSign, properties.getProperty("apikey"), properties.getProperty("secretkey")); - System.out.println("http://" + properties.getProperty("hostname") + ":8080/client/api?" + url); + requestUrl = "http://" + properties.getProperty("hostname") + ":8080/client/api?" + url; + System.out.println(requestUrl); + + List ipList = client.execute(requestUrl,"listpublicipaddressesresponse", "publicipaddress", new TypeToken>(){}.getType()); + + long ipId=67; + String ip = "10.223.153.76"; //3) create portForwarding rules for port 22 and 80 urlToSign = "command=createPortForwardingRule&privateport=22&publicport=22&protocol=tcp&ipaddressid=" + ipId + "&virtualmachineid=" + vmId; url = UtilsForTest.signUrl(urlToSign, properties.getProperty("apikey"), properties.getProperty("secretkey")); - System.out.println("http://" + properties.getProperty("hostname") + ":8080/client/api?" + url); + requestUrl = "http://" + properties.getProperty("hostname") + ":8080/client/api?" + url; + System.out.println(requestUrl); + CloudStackPortForwardingRule pfrule1 = client.execute(requestUrl, _apiCommands.get("createPortForwardingRule"), "createportforwardingruleresponse", "portforwardingrule", CloudStackPortForwardingRule.class); urlToSign = "command=createPortForwardingRule&privateport=80&publicport=80&protocol=tcp&ipaddressid=" + ipId + "&virtualmachineid=" + vmId; url = UtilsForTest.signUrl(urlToSign, properties.getProperty("apikey"), properties.getProperty("secretkey")); - System.out.println("http://" + properties.getProperty("hostname") + ":8080/client/api?" + url); + + requestUrl = "http://" + properties.getProperty("hostname") + ":8080/client/api?" + url; + System.out.println(requestUrl); + CloudStackPortForwardingRule pfrule2 = client.execute(requestUrl, _apiCommands.get("createPortForwardingRule"), "createportforwardingruleresponse", "portforwardingrule", CloudStackPortForwardingRule.class); - return "10.223.153.76"; + return ip; } } diff --git a/test/src/com/cloud/test/demo/response/ApiConstants.java b/test/src/com/cloud/test/demo/response/ApiConstants.java new file mode 100644 index 00000000000..4486d9f51e5 --- /dev/null +++ b/test/src/com/cloud/test/demo/response/ApiConstants.java @@ -0,0 +1,505 @@ +/* + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.cloud.test.demo.response; + +public class ApiConstants { + public static final String ACCOUNT = "account"; + public static final String ACCOUNT_ID = "accountid"; + public static final String ACCOUNT_TYPE = "accounttype"; + public static final String ACCOUNTS = "accounts"; + public static final String ALGORITHM = "algorithm"; + public static final String ALLOCATED = "allocated"; + public static final String ALLOCATED_ONLY = "allocatedonly"; + public static final String ALLOCATION_STATE = "allocationstate"; + public static final String API_KEY = "apikey"; + public static final String APPLIED = "applied"; + public static final String ASSIGN_TO_LOAD_BALANCER_RULE = "assignToLoadBalancerRule"; + public static final String ASSIGN_TO_LOAD_BALANCER_RULE_RESPONSE = "assigntoloadbalancerruleresponse"; + public static final String ASSOCIATE_IP_ADDRESS = "associateIpAddress"; + public static final String ASSOCIATE_IP_ADDRESS_RESPONSE = "associateipaddressresponse"; + public static final String ASSOCIATED_NETWORK_ID = "associatednetworkid"; + public static final String ATTACH_ISO = "attachIso"; + public static final String ATTACH_ISO_RESPONSE = "attachisoresponse"; + public static final String ATTACH_VOLUME = "attachVolume"; + public static final String ATTACH_VOLUME_RESPONSE = "attachvolumeresponse"; + public static final String ATTACHED = "attached"; + public static final String AUTHORIZE_SECURITY_GROUP_INGRESS = "authorizeSecurityGroupIngress"; + public static final String AUTHORIZE_SECURITY_GROUP_INGRESS_RESPONSE = "authorizesecuritygroupingressresponse"; + public static final String AVAILABILITY = "availability"; + public static final String AVAILABLE = "available"; + public static final String BITS = "bits"; + public static final String BOOTABLE = "bootable"; + public static final String BROADCAST_DOMAIN_TYPE = "broadcastdomaintype"; + public static final String BROADCAST_URI = "broadcasturi"; + public static final String CAPABILITY = "capability"; + public static final String CATEGORY = "category"; + public static final String CERTIFICATE = "certificate"; + public static final String CHANGE_SERVICE_FOR_VIRTUAL_MACHINE = "changeServiceForVirtualMachine"; + public static final String CHANGE_SERVICE_FOR_VIRTUAL_MACHINE_RESPONSE = "changeserviceforvirtualmachineresponse"; + public static final String CHECKSUM="checksum"; + public static final String CIDR = "cidr"; + public static final String CIDR_LIST = "cidrlist"; + public static final String CLEANUP = "cleanup"; + public static final String CLOUD_IDENTIFIER = "cloudidentifier"; + public static final String CLOUD_STACK_VERSION = "cloudstackversion"; + public static final String CLUSTER_ID = "clusterid"; + public static final String CLUSTER_NAME = "clustername"; + public static final String CLUSTER_TYPE = "clustertype"; + public static final String COMPONENT = "component"; + public static final String COPY_ISO = "copyIso"; + public static final String COPY_ISO_RESPONSE = "copyisoresponse"; + public static final String COPY_TEMPLATE = "copyTemplate"; + public static final String COPY_TEMPLATE_RESPONSE = "copytemplateresponse"; + public static final String CPU_NUMBER = "cpunumber"; + public static final String CPU_SPEED = "cpuspeed"; + public static final String CPU_USED = "cpuused"; + public static final String CREATE_INSTANCE_GROUP = "createInstanceGroup"; + public static final String CREATE_INSTANCE_GROUP_RESPONSE = "createinstancegroupresponse"; + public static final String CREATE_IP_FORWARDING_RULE = "createIpForwardingRule"; + public static final String CREATE_IP_FORWARDING_RULE_RESPONSE = "createipforwardingruleresponse"; + public static final String CREATE_LOAD_BALANCER_RULE = "createLoadBalancerRule"; + public static final String CREATE_LOAD_BALANCER_RULE_RESPONSE = "createloadbalancerruleresponse"; + public static final String CREATE_NETWORK = "createNetwork"; + public static final String CREATE_NETWORK_RESPONSE = "createnetworkresponse"; + public static final String CREATE_PORT_FORWARDING_RULE = "createPortForwardingRule"; + public static final String CREATE_PORT_FORWARDING_RULE_RESPONSE = "createportforwardingruleresponse"; + public static final String CREATE_SECURITY_GROUP = "createSecurityGroup"; + public static final String CREATE_SECURITY_GROUP_RESPONSE = "createsecuritygroupresponse"; + public static final String CREATE_SNAPSHOT = "createSnapshot"; + public static final String CREATE_SNAPSHOT_POLICY = "createSnapshotPolicy"; + public static final String CREATE_SNAPSHOT_POLICY_RESPONSE = "createsnapshotpolicyresponse"; + public static final String CREATE_SNAPSHOT_RESPONSE = "createsnapshotresponse"; + public static final String CREATE_SSH_KEY_PAIR = "createSSHKeyPair"; + public static final String CREATE_SSH_KEY_PAIR_RESPONSE = "createsshkeypairresponse"; + public static final String CREATE_TEMPLATE = "createTemplate"; + public static final String CREATE_TEMPLATE_RESPONSE = "createtemplateresponse"; + public static final String CREATE_VOLUME = "createVolume"; + public static final String CREATE_VOLUME_RESPONSE = "createvolumeresponse"; + public static final String CREATED = "created"; + public static final String CROSS_ZONES = "crosszones"; + public static final String CUSTOMIZED = "customized"; + public static final String DEFAULT_USE = "defaultuse"; + public static final String DELETE_INSTANCE_GROUP = "deleteInstanceGroup"; + public static final String DELETE_INSTANCE_GROUP_RESPONSE = "deleteinstancegroupresponse"; + public static final String DELETE_IP_FORWARDING_RULE = "deleteIpForwardingRule"; + public static final String DELETE_IP_FORWARDING_RULE_RESPONSE = "deleteipforwardingruleresponse"; + public static final String DELETE_ISO = "deleteIso"; + public static final String DELETE_ISO_RESPONSE = "deleteisoresponse"; + public static final String DELETE_LOAD_BALANCER_RULE = "deleteLoadBalancerRule"; + public static final String DELETE_LOAD_BALANCER_RULE_RESPONSE = "deleteloadbalancerruleresponse"; + public static final String DELETE_NETWORK = "deleteNetwork"; + public static final String DELETE_NETWORK_RESPONSE = "deletenetworkresponse"; + public static final String DELETE_PORT_FORWARDING_RULE = "deletePortForwardingRule"; + public static final String DELETE_PORT_FORWARDING_RULE_RESPONSE = "deleteportforwardingruleresponse"; + public static final String DELETE_SECURITY_GROUP = "deleteSecurityGroup"; + public static final String DELETE_SECURITY_GROUP_RESPONSE = "deletesecuritygroupresponse"; + public static final String DELETE_SNAPSHOT = "deleteSnapshot"; + public static final String DELETE_SNAPSHOT_POLICIES = "deleteSnapshotPolicies"; + public static final String DELETE_SNAPSHOT_POLICIES_RESPONSE = "deletesnapshotpoliciesresponse"; + public static final String DELETE_SNAPSHOT_RESPONSE = "deletesnapshotresponse"; + public static final String DELETE_SSH_KEY_PAIR = "deleteSSHKeyPair"; + public static final String DELETE_SSH_KEY_PAIR_RESPONSE = "deletesshkeypairresponse"; + public static final String DELETE_TEMPLATE = "deleteTemplate"; + public static final String DELETE_TEMPLATE_RESPONSE = "deletetemplateresponse"; + public static final String DELETE_VOLUME = "deleteVolume"; + public static final String DELETE_VOLUME_RESPONSE = "deletevolumeresponse"; + public static final String DEPLOY_VIRTUAL_MACHINE = "deployVirtualMachine"; + public static final String DEPLOY_VIRTUAL_MACHINE_RESPONSE = "deployvirtualmachineresponse"; + public static final String DESCRIPTION = "description"; + public static final String DESTINATION_ZONE_ID = "destzoneid"; + public static final String DESTROY_VIRTUAL_MACHINE = "destroyVirtualMachine"; + public static final String DESTROY_VIRTUAL_MACHINE_RESPONSE = "destroyvirtualmachineresponse"; + public static final String DESTROYED = "destroyed"; + public static final String DETACH_ISO = "detachIso"; + public static final String DETACH_ISO_RESPONSE = "detachisoresponse"; + public static final String DETACH_VOLUME = "detachVolume"; + public static final String DETACH_VOLUME_RESPONSE = "detachvolumeresponse"; + public static final String DETAILS = "details"; + public static final String DEVICE_ID = "deviceid"; + public static final String DHCP_PROVIDER = "dhcpprovider"; + public static final String DHCP_SERVER_TYPE = "dhcpservertype"; + public static final String DISABLE_STATIC_NAT = "disableStaticNat"; + public static final String DISABLE_STATIC_NAT_RESPONSE = "disablestaticnatresponse"; + public static final String DISASSOCIATE_IP_ADDRESS = "disassociateIpAddress"; + public static final String DISASSOCIATE_IP_ADDRESS_RESPONSE = "disassociateipaddressresponse"; + public static final String DISK_OFFERING = "diskoffering"; + public static final String DISK_OFFERING_DISPLAY_TEXT = "diskofferingdisplaytext"; + public static final String DISK_OFFERING_ID = "diskofferingid"; + public static final String DISK_OFFERING_NAME = "diskofferingname"; + public static final String DISK_SIZE = "disksize"; + public static final String DISPLAY_NAME = "displayname"; + public static final String DISPLAY_TEXT = "displaytext"; + public static final String DNS1 = "dns1"; + public static final String DNS2 = "dns2"; + public static final String DOMAIN = "domain"; + public static final String DOMAIN_ID = "domainid"; + public static final String DURATION = "duration"; + public static final String EMAIL = "email"; + public static final String ENABLE_STATIC_NAT = "enableStaticNat"; + public static final String ENABLE_STATIC_NAT_RESPONSE = "enablestaticnatresponse"; + public static final String ENABLED = "enabled"; + public static final String ENCRYPTED_PASSWORD = "encryptedpassword"; + public static final String END_DATE = "enddate"; + public static final String END_IP = "endip"; + public static final String END_PORT = "endport"; + public static final String ENTRY_TIME = "entrytime"; + public static final String EVENT = "event"; + public static final String EVENT_TYPE = "eventtype"; + public static final String EXTRACT_ID = "extractid"; + public static final String EXTRACT_ISO = "extractIso"; + public static final String EXTRACT_ISO_RESPONSE = "extractisoresponse"; + public static final String EXTRACT_MODE = "extractmode"; + public static final String EXTRACT_TEMPLATE = "extractTemplate"; + public static final String EXTRACT_TEMPLATE_RESPONSE = "extracttemplateresponse"; + public static final String EXTRACT_VOLUME = "extractVolume"; + public static final String EXTRACT_VOLUME_RESPONSE = "extractvolumeresponse"; + public static final String FINGERPRINT = "fingerprint"; + public static final String FIRSTNAME = "firstname"; + public static final String FOR_VIRTUAL_NETWORK = "forvirtualnetwork"; + public static final String FORCED = "forced"; + public static final String FORMAT = "format"; + public static final String GATEWAY = "gateway"; + public static final String GET_CLOUD_IDENTIFIER = "getCloudIdentifier"; + public static final String GET_CLOUD_IDENTIFIER_RESPONSE = "getcloudidentifierresponse"; + public static final String GET_VM_PASSWORD = "getVMPassword"; + public static final String GET_VM_PASSWORD_RESPONSE = "getvmpasswordresponse"; + public static final String GROUP = "group"; + public static final String GROUP_ID = "groupid"; + public static final String GUEST_CIDR_ADDRESS = "guestcidraddress"; + public static final String GUEST_IP_TYPE = "guestiptype"; + public static final String GUEST_OS_ID = "guestosid"; + public static final String HA_ENABLE = "haenable"; + public static final String HOST_CPU_CAPACITY = "hostcpucapacity"; + public static final String HOST_CPU_NUM = "hostcpunum"; + public static final String HOST_ID = "hostid"; + public static final String HOST_MAC = "hostmac"; + public static final String HOST_MEM_CAPACITY = "hostmemcapacity"; + public static final String HOST_NAME = "hostname"; + public static final String HOST_TAG = "hosttag"; + public static final String HOST_TAGS = "hosttags"; + public static final String HYPERVISOR = "hypervisor"; + public static final String ICMP_CODE = "icmpcode"; + public static final String ICMP_TYPE = "icmptype"; + public static final String ID = "id"; + public static final String IDS = "ids"; + public static final String INGRESS_RULE = "ingressrule"; + public static final String INSTANCE = "instance"; + public static final String INSTANCE_GROUP = "instancegroup"; + public static final String INTERNAL_DNS1 = "internaldns1"; + public static final String INTERNAL_DNS2 = "internaldns2"; + public static final String INTERVAL_TYPE = "intervaltype"; + public static final String IP_ADDRESS = "ipaddress"; + public static final String IP_ADDRESS_ID = "ipaddressid"; + public static final String IP_AVAILABLE = "ipavailable"; + public static final String IP_FORWARDING_RULE = "ipforwardingrule"; + public static final String IP_LIMIT = "iplimit"; + public static final String IP_TOTAL = "iptotal"; + public static final String IS_CLEANUP_REQUIRED = "iscleanuprequired"; + public static final String IS_CUSTOMIZED = "iscustomized"; + public static final String IS_DEFAULT = "isdefault"; + public static final String IS_EXTRACTABLE = "isextractable"; + public static final String IS_FEATURED = "isfeatured"; + public static final String IS_PUBLIC = "ispublic"; + public static final String IS_READY = "isready"; + public static final String IS_RECURSIVE = "isrecursive"; + public static final String IS_SHARED = "isshared"; + public static final String IS_SOURCE_NAT = "issourcenat"; + public static final String IS_STATIC_NAT = "isstaticnat"; + public static final String IS_SYSTEM = "issystem"; + public static final String ISO_DISPLAY_TEXT = "isodisplaytext"; + public static final String ISO_FILTER = "isofilter"; + public static final String ISO_ID = "isoid"; + public static final String ISO_NAME = "isoname"; + public static final String ISOLATION_URI = "isolationuri"; + public static final String JOB_ID = "jobid"; + public static final String JOB_STATUS = "jobstatus"; + public static final String KEY_PAIR = "keypair"; + public static final String KEYWORD = "keyword"; + public static final String LASTNAME = "lastname"; + public static final String LEVEL = "level"; + public static final String LIMIT_CPU_USE = "limitcpuuse"; + public static final String LINK_LOCAL_IP = "linklocalip"; + public static final String LINK_LOCAL_MAC_ADDRESS = "linklocalmacaddress"; + public static final String LINK_LOCAL_MAC_NETMASK = "linklocalnetmask"; + public static final String LINK_LOCAL_NETWORK_ID = "linklocalnetworkid"; + public static final String LINMIN_APID = "linminapid"; + public static final String LINMIN_PASSWORD = "linminpassword"; + public static final String LINMIN_USERNAME = "linminusername"; + public static final String LIST_ACCOUNTS = "listAccounts"; + public static final String LIST_ACCOUNTS_RESPONSE = "listaccountsresponse"; + public static final String LIST_CAPABILITIES = "listCapabilities"; + public static final String LIST_CAPABILITIES_RESPONSE = "listcapabilitiesresponse"; + public static final String LIST_DISK_OFFERINGS = "listDiskOfferings"; + public static final String LIST_DISK_OFFERINGS_RESPONSE = "listdiskofferingsresponse"; + public static final String LIST_EVENT_TYPES = "listEventTypes"; + public static final String LIST_EVENT_TYPES_RESPONSE = "listeventtypesresponse"; + public static final String LIST_EVENTS = "listEvents"; + public static final String LIST_EVENTS_RESPONSE = "listeventsresponse"; + public static final String LIST_HYPERVISORS = "listHypervisors"; + public static final String LIST_HYPERVISORS_RESPONSE = "listhypervisorsresponse"; + public static final String LIST_INSTANCE_GROUPS = "listInstanceGroups"; + public static final String LIST_INSTANCE_GROUPS_RESPONSE = "listinstancegroupsresponse"; + public static final String LIST_IP_FORWARDING_RULES = "listIpForwardingRules"; + public static final String LIST_IP_FORWARDING_RULES_RESPONSE = "listipforwardingrulesresponse"; + public static final String LIST_ISO_PERMISSIONS = "listIsoPermissions"; + public static final String LIST_ISO_PERMISSIONS_RESPONSE = "listisopermissionsresponse"; + public static final String LIST_ISOS = "listIsos"; + public static final String LIST_ISOS_RESPONSE = "listisosresponse"; + public static final String LIST_LOAD_BALANCER_RULE_INSTANCES = "listLoadBalancerRuleInstances"; + public static final String LIST_LOAD_BALANCER_RULE_INSTANCES_RESPONSE = "listloadbalancerruleinstancesresponse"; + public static final String LIST_LOAD_BALANCER_RULES = "listLoadBalancerRules"; + public static final String LIST_LOAD_BALANCER_RULES_RESPONSE = "listloadbalancerrulesresponse"; + public static final String LIST_NETWORK_OFFERINGS = "listNetworkOfferings"; + public static final String LIST_NETWORK_OFFERINGS_RESPONSE = "listnetworkofferingsresponse"; + public static final String LIST_NETWORKS = "listNetworks"; + public static final String LIST_NETWORKS_RESPONSE = "listnetworksresponse"; + public static final String LIST_OS_CATEGORIES = "listOsCategories"; + public static final String LIST_OS_CATEGORIES_RESPONSE = "listoscategoriesresponse"; + public static final String LIST_OS_TYPES = "listOsTypes"; + public static final String LIST_OS_TYPES_RESPONSE = "listostypesresponse"; + public static final String LIST_PORT_FORWARDING_RULES = "listPortForwardingRules"; + public static final String LIST_PORT_FORWARDING_RULES_RESPONSE = "listportforwardingrulesresponse"; + public static final String LIST_PUBLIC_IP_ADDRESSES = "listPublicIpAddresses"; + public static final String LIST_PUBLIC_IP_ADDRESSES_RESPONSE = "listpublicipaddressesresponse"; + public static final String LIST_RESOURCE_LIMITS = "listResourceLimits"; + public static final String LIST_RESOURCE_LIMITS_RESPONSE = "listresourcelimitsresponse"; + public static final String LIST_SECURITY_GROUPS = "listSecurityGroups"; + public static final String LIST_SECURITY_GROUPS_RESPONSE = "listsecuritygroupsresponse"; + public static final String LIST_SERVICE_OFFERINGS = "listServiceOfferings"; + public static final String LIST_SERVICE_OFFERINGS_RESPONSE = "listserviceofferingsresponse"; + public static final String LIST_SNAPSHOT_POLICIES = "listSnapshotPolicies"; + public static final String LIST_SNAPSHOT_POLICIES_RESPONSE = "listsnapshotpoliciesresponse"; + public static final String LIST_SNAPSHOTS = "listSnapshots"; + public static final String LIST_SNAPSHOTS_RESPONSE = "listsnapshotsresponse"; + public static final String LIST_SSH_KEY_PAIRS = "listSSHKeyPairs"; + public static final String LIST_SSH_KEY_PAIRS_RESPONSE = "listsshkeypairsresponse"; + public static final String LIST_TEMPLATE_PERMISSIONS = "listTemplatePermissions"; + public static final String LIST_TEMPLATE_PERMISSIONS_RESPONSE = "listtemplatepermissionsresponse"; + public static final String LIST_TEMPLATES = "listTemplates"; + public static final String LIST_TEMPLATES_RESPONSE = "listtemplatesresponse"; + public static final String LIST_VIRTUAL_MACHINES = "listVirtualMachines"; + public static final String LIST_VIRTUAL_MACHINES_RESPONSE = "listvirtualmachinesresponse"; + public static final String LIST_VOLUMES = "listVolumes"; + public static final String LIST_VOLUMES_RESPONSE = "listvolumesresponse"; + public static final String LIST_ZONES = "listZones"; + public static final String LIST_ZONES_RESPONSE = "listzonesresponse"; + public static final String LOAD_BALANCER = "loadbalancer"; + public static final String LOCK = "lock"; + public static final String LUN = "lun"; + public static final String MAC_ADDRESS = "macaddress"; + public static final String MAX = "max"; + public static final String MAX_CONNECTIONS = "maxconnections"; + public static final String MAX_SNAPS = "maxsnaps"; + public static final String MEMORY = "memory"; + public static final String MODE = "mode"; + public static final String NAME = "name"; + public static final String NETMASK = "netmask"; + public static final String NETWORK = "network"; + public static final String NETWORK_DOMAIN = "networkdomain"; + public static final String NETWORK_ID = "networkid"; + public static final String NETWORK_IDS = "networkids"; + public static final String NETWORK_KBS_READ = "networkkbsread"; + public static final String NETWORK_KBS_WRITE = "networkkbswrite"; + public static final String NETWORK_OFFERING = "networkoffering"; + public static final String NETWORK_OFFERING_AVAILABILITY = "networkofferingavailability"; + public static final String NETWORK_OFFERING_DISPLAY_TEXT = "networkofferingdisplaytext"; + public static final String NETWORK_OFFERING_ID = "networkofferingid"; + public static final String NETWORK_OFFERING_NAME = "networkofferingname"; + public static final String NETWORK_TYPE = "networktype"; + public static final String NETWORKRATE = "networkrate"; + public static final String NEW_NAME = "newname"; + public static final String NIC = "nic"; + public static final String NUM_RETRIES = "numretries"; + public static final String OFFER_HA = "offerha"; + public static final String OP = "op"; + public static final String OS_CATEGORY = "oscategory"; + public static final String OS_CATEGORY_ID = "oscategoryid"; + public static final String OS_TYPE = "ostype"; + public static final String OS_TYPE_ID = "ostypeid"; + public static final String OS_TYPE_NAME = "ostypename"; + public static final String PAGE = "page"; + public static final String PAGE_SIZE = "pagesize"; + public static final String PARENT_DOMAIN_ID = "parentdomainid"; + public static final String PARENT_ID = "parentid"; + public static final String PASSWORD = "password"; + public static final String PASSWORD_ENABLED = "passwordenabled"; + public static final String PATH = "path"; + public static final String POD_ID = "podid"; + public static final String POLICY_ID = "policyid"; + public static final String PORT_FORWARDING_RULE = "portforwardingrule"; + public static final String PORT_FORWARDING_SERVICE_ID = "portforwardingserviceid"; + public static final String PORTAL = "portal"; + public static final String PRIVATE_END_PORT = "privateendport"; + public static final String PRIVATE_INTERFACE = "privateinterface"; + public static final String PRIVATE_IP = "privateip"; + public static final String PRIVATE_KEY = "privatekey"; + public static final String PRIVATE_MAC_ADDRESS = "privatemacaddress"; + public static final String PRIVATE_NETMASK = "privatenetmask"; + public static final String PRIVATE_NETWORK_ID = "privatenetworkid"; + public static final String PRIVATE_PORT = "privateport"; + public static final String PRIVATE_ZONE = "privatezone"; + public static final String PROTOCOL = "protocol"; + public static final String PUBLIC_END_PORT = "publicendport"; + public static final String PUBLIC_INTERFACE = "publicinterface"; + public static final String PUBLIC_IP = "publicip"; + public static final String PUBLIC_IP_ADDRESS = "publicipaddress"; + public static final String PUBLIC_IP_ID = "publicipid"; + public static final String PUBLIC_KEY = "publickey"; + public static final String PUBLIC_PORT = "publicport"; + public static final String PUBLIC_ZONE = "publiczone"; + public static final String PXE_SERVER_TYPE = "pxeservertype"; + public static final String REBOOT_VIRTUAL_MACHINE = "rebootVirtualMachine"; + public static final String REBOOT_VIRTUAL_MACHINE_RESPONSE = "rebootvirtualmachineresponse"; + public static final String RECEIVED_BYTES = "receivedbytes"; + public static final String REGISTER_ISO = "registerIso"; + public static final String REGISTER_ISO_RESPONSE = "registerisoresponse"; + public static final String REGISTER_SSH_KEY_PAIR = "registerSSHKeyPair"; + public static final String REGISTER_SSH_KEY_PAIR_RESPONSE = "registersshkeypairresponse"; + public static final String REGISTER_TEMPLATE = "registerTemplate"; + public static final String REGISTER_TEMPLATE_RESPONSE = "registertemplateresponse"; + public static final String RELATED = "related"; + public static final String REMOVE_FROM_LOAD_BALANCER_RULE = "removeFromLoadBalancerRule"; + public static final String REMOVE_FROM_LOAD_BALANCER_RULE_RESPONSE = "removefromloadbalancerruleresponse"; + public static final String REMOVED = "removed"; + public static final String REQUIRES_HVM = "requireshvm"; + public static final String RESET_PASSWORD_FOR_VIRTUAL_MACHINE = "resetPasswordForVirtualMachine"; + public static final String RESET_PASSWORD_FOR_VIRTUAL_MACHINE_RESPONSE = "resetpasswordforvirtualmachineresponse"; + public static final String RESOURCE_LIMIT = "resourcelimit"; + public static final String RESOURCE_TYPE = "resourcetype"; + public static final String RESTART_NETWORK = "restartNetwork"; + public static final String RESTART_NETWORK_RESPONSE = "restartnetworkresponse"; + public static final String REVOKE_SECURITY_GROUP_INGRESS = "revokeSecurityGroupIngress"; + public static final String REVOKE_SECURITY_GROUP_INGRESS_RESPONSE = "revokesecuritygroupingress"; + public static final String ROOT_DEVICE_ID = "rootdeviceid"; + public static final String ROOT_DEVICE_TYPE = "rootdevicetype"; + public static final String RULE_ID = "ruleid"; + public static final String SCHEDULE = "schedule"; + public static final String SCOPE = "scope"; + public static final String SECRET_KEY = "secretkey"; + public static final String SECURITY_GROUP = "securitygroup"; + public static final String SECURITY_GROUP_ENABLED = "securitygroupenabled"; + public static final String SECURITY_GROUP_ID = "securitygroupid"; + public static final String SECURITY_GROUP_IDS = "securitygroupids"; + public static final String SECURITY_GROUP_NAME = "securitygroupname"; + public static final String SECURITY_GROUP_NAMES = "securitygroupnames"; + public static final String SECURITY_GROUPS_ENABLED = "securitygroupsenabled"; + public static final String SENT = "sent"; + public static final String SENT_BYTES = "sentbytes"; + public static final String SERVICE = "service"; + public static final String SERVICE_OFFERING = "serviceoffering"; + public static final String SERVICE_OFFERING_DISPLAY_TEXT = "serviceofferingdisplaytext"; + public static final String SERVICE_OFFERING_ID = "serviceofferingid"; + public static final String SERVICE_OFFERING_NAME = "serviceofferingname"; + public static final String SIGNATURE = "signature"; + public static final String SIZE = "size"; + public static final String SNAPSHOT = "snapshot"; + public static final String SNAPSHOT_AVAILABLE = "snapshotavailable"; + public static final String SNAPSHOT_ID = "snapshotid"; + public static final String SNAPSHOT_LIMIT = "snapshotlimit"; + public static final String SNAPSHOT_POLICY_ID = "snapshotpolicyid"; + public static final String SNAPSHOT_TOTAL = "snapshottotal"; + public static final String SNAPSHOT_TYPE = "snapshottype"; + public static final String SOURCE_TEMPLATE_ID = "sourcetemplateid"; + public static final String SOURCE_ZONE_ID = "sourcezoneid"; + public static final String SPECIFY_VLAN = "specifyvlan"; + public static final String SSH_KEYPAIR = "keypair"; + public static final String START_DATE = "startdate"; + public static final String START_IP = "startip"; + public static final String START_PORT = "startport"; + public static final String START_VIRTUAL_MACHINE = "startVirtualMachine"; + public static final String START_VIRTUAL_MACHINE_RESPONSE = "startvirtualmachineresponse"; + public static final String STATE = "state"; + public static final String STATUS = "status"; + public static final String STOP_VIRTUAL_MACHINE = "stopVirtualMachine"; + public static final String STOP_VIRTUAL_MACHINE_RESPONSE = "stopvirtualmachineresponse"; + public static final String STORAGE = "storage"; + public static final String STORAGE_ID="storageid"; + public static final String STORAGE_TYPE = "storagetype"; + public static final String SUCCESS = "success"; + public static final String SYSTEM_VM_TYPE = "systemvmtype"; + public static final String TAGS = "tags"; + public static final String TARGET_IQN = "targetiqn"; + public static final String TEMPLATE = "template"; + public static final String TEMPLATE_AVAILABLE = "templateavailable"; + public static final String TEMPLATE_DISPLAY_TEXT = "templatedisplaytext"; + public static final String TEMPLATE_FILTER = "templatefilter"; + public static final String TEMPLATE_ID = "templateid"; + public static final String TEMPLATE_LIMIT = "templatelimit"; + public static final String TEMPLATE_NAME = "templatename"; + public static final String TEMPLATE_PERMISSION = "templatepermission"; + public static final String TEMPLATE_TOTAL = "templatetotal"; + public static final String TEMPLATE_TYPE = "templatetype"; + public static final String TIMEOUT = "timeout"; + public static final String TIMEZONE = "timezone"; + public static final String TRAFFIC_TYPE = "traffictype"; + public static final String TYPE = "type"; + public static final String UPDATE_INSTANCE_GROUP = "updateInstanceGroup"; + public static final String UPDATE_INSTANCE_GROUP_RESPONSE = "updateinstancegroupresponse"; + public static final String UPDATE_ISO = "updateIso"; + public static final String UPDATE_ISO_PERMISSIONS = "updateIsoPermissions"; + public static final String UPDATE_ISO_PERMISSIONS_RESPONSE = "updateisopermissionsresponse"; + public static final String UPDATE_ISO_RESPONSE = "updateisoresponse"; + public static final String UPDATE_LOAD_BALANCER_RULE = "updateLoadBalancerRule"; + public static final String UPDATE_LOAD_BALANCER_RULE_RESPONSE = "updateloadbalancerruleresponse"; + public static final String UPDATE_NETWORK = "updateNetwork"; + public static final String UPDATE_NETWORK_RESPONSE = "updatenetworkresponse"; + public static final String UPDATE_TEMPLATE = "updateTemplate"; + public static final String UPDATE_TEMPLATE_PERMISSIONS = "updateTemplatePermissions"; + public static final String UPDATE_TEMPLATE_PERMISSIONS_RESPONSE = "updatetemplatepermissionsresponse"; + public static final String UPDATE_TEMPLATE_RESPONSE = "updatetemplateresponse"; + public static final String UPDATE_VIRTUAL_MACHINE = "updateVirtualMachine"; + public static final String UPDATE_VIRTUAL_MACHINE_RESPONSE = "updatevirtualmachineresponse"; + public static final String UPLOAD_PERCENTAGE = "uploadpercentage"; + public static final String URL = "url"; + public static final String USAGE_INTERFACE = "usageinterface"; + public static final String USE_VIRTUAL_NETWORK = "usevirtualnetwork"; + public static final String USER = "user"; + public static final String USER_DATA = "userdata"; + public static final String USER_ID = "userid"; + public static final String USER_PUBLIC_TEMPLATE_ENABLED = "userpublictemplateenabled"; + public static final String USER_SECURITY_GROUP_LIST = "usersecuritygrouplist"; + public static final String USERNAME = "username"; + public static final String VALUE = "value"; + public static final String VIRTUAL_MACHINE = "virtualmachine"; + public static final String VIRTUAL_MACHINE_DISPLAY_NAME = "virtualmachinedisplayname"; + public static final String VIRTUAL_MACHINE_ID = "virtualmachineid"; + public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids"; + public static final String VIRTUAL_MACHINE_NAME = "virtualmachinename"; + public static final String VLAN = "vlan"; + public static final String VLAN_ID = "vlanid"; + public static final String VLAN_NAME = "vlanname"; + public static final String VM_AVAILABLE = "vmavailable"; + public static final String VM_DISPLAY_NAME = "vmdisplayname"; + public static final String VM_LIMIT = "vmlimit"; + public static final String VM_NAME = "vmname"; + public static final String VM_RUNNING = "vmrunning"; + public static final String VM_STATE = "vmstate"; + public static final String VM_STOPPED = "vmstopped"; + public static final String VM_TOTAL = "vmtotal"; + public static final String VNET = "vnet"; + public static final String VOLUME = "volume"; + public static final String VOLUME_AVAILABLE = "volumeavailable"; + public static final String VOLUME_ID = "volumeid"; + public static final String VOLUME_LIMIT = "volumelimit"; + public static final String VOLUME_NAME = "volumename"; + public static final String VOLUME_TOTAL = "volumetotal"; + public static final String VOLUME_TYPE = "volumetype"; + public static final String ZONE = "zone"; + public static final String ZONE_ID = "zoneid"; + public static final String ZONE_NAME = "zonename"; + public static final String ZONE_TOKEN = "zonetoken"; + +} diff --git a/test/src/com/cloud/test/demo/response/CloudStackIngressRule.java b/test/src/com/cloud/test/demo/response/CloudStackIngressRule.java new file mode 100644 index 00000000000..482e026e081 --- /dev/null +++ b/test/src/com/cloud/test/demo/response/CloudStackIngressRule.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.cloud.test.demo.response; + +import com.google.gson.annotations.SerializedName; + +public class CloudStackIngressRule { + + @SerializedName(ApiConstants.RULE_ID) + private String ruleId; + + @SerializedName(ApiConstants.PROTOCOL) + private String protocol; + + @SerializedName(ApiConstants.ICMP_TYPE) + private Integer icmpType; + + @SerializedName(ApiConstants.ICMP_CODE) + private Integer icmpCode; + + @SerializedName(ApiConstants.START_PORT) + private Integer startPort; + + @SerializedName(ApiConstants.END_PORT) + private Integer endPort; + + @SerializedName(ApiConstants.SECURITY_GROUP_NAME) + private String securityGroupName; + + @SerializedName(ApiConstants.ACCOUNT) + private String accountName; + + @SerializedName(ApiConstants.CIDR) + private String cidr; + + public CloudStackIngressRule() { + } + + public String getRuleId() { + return ruleId; + } + + public String getProtocol() { + return protocol; + } + + public Integer getIcmpType() { + return icmpType; + } + + public Integer getIcmpCode() { + return icmpCode; + } + + public Integer getStartPort() { + return startPort; + } + + public Integer getEndPort() { + return endPort; + } + + public String getSecurityGroupName() { + return securityGroupName; + } + + public String getAccountName() { + return accountName; + } + + public String getCidr() { + return cidr; + } +} diff --git a/test/src/com/cloud/test/demo/response/CloudStackIpAddress.java b/test/src/com/cloud/test/demo/response/CloudStackIpAddress.java new file mode 100644 index 00000000000..7ac0c109943 --- /dev/null +++ b/test/src/com/cloud/test/demo/response/CloudStackIpAddress.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.cloud.test.demo.response; + +import com.google.gson.annotations.SerializedName; + +public class CloudStackIpAddress { + + @SerializedName(ApiConstants.ID) + private String id; + @SerializedName(ApiConstants.ACCOUNT) + private String accountName; + @SerializedName(ApiConstants.ALLOCATED) + private String allocated; + @SerializedName(ApiConstants.ASSOCIATED_NETWORK_ID) + private String associatedNetworkId; + @SerializedName(ApiConstants.DOMAIN) + private String domainName; + @SerializedName(ApiConstants.DOMAIN_ID) + private String domainId; + @SerializedName(ApiConstants.FOR_VIRTUAL_NETWORK) + private Boolean forVirtualNetwork; + @SerializedName(ApiConstants.IP_ADDRESS) + private String ipAddress; + @SerializedName(ApiConstants.IS_SOURCE_NAT) + private Boolean sourceNat; + @SerializedName(ApiConstants.IS_STATIC_NAT) + private Boolean staticNat; + @SerializedName(ApiConstants.JOB_ID) + private String jobId; + @SerializedName(ApiConstants.JOB_STATUS) + private Integer jobStatus; + @SerializedName(ApiConstants.NETWORK_ID) + private String networkId; + @SerializedName(ApiConstants.STATE) + private String state; + @SerializedName(ApiConstants.VIRTUAL_MACHINE_DISPLAY_NAME) + private String virtualMachineDisplayName; + @SerializedName(ApiConstants.VIRTUAL_MACHINE_ID) + private String virtualMachineId; + @SerializedName(ApiConstants.VIRTUAL_MACHINE_NAME) + private String virtualMachineName; + @SerializedName(ApiConstants.VLAN_ID) + private String vlanId; + @SerializedName(ApiConstants.VLAN_NAME) + private String vlanName; + @SerializedName(ApiConstants.ZONE_ID) + private String zoneId; + @SerializedName(ApiConstants.ZONE_NAME) + private String zoneName; + + public CloudStackIpAddress() { + } + + public String getId() { + return id; + } + + public String getIpAddress() { + return ipAddress; + } + + public String getAllocated() { + return allocated; + } + + public String getZoneId() { + return zoneId; + } + + public String getZoneName() { + return zoneName; + } + + public Boolean getSourceNat() { + return sourceNat; + } + + public String getAccountName() { + return accountName; + } + + public String getDomainId() { + return domainId; + } + + public String getDomainName() { + return domainName; + } + + public Boolean getForVirtualNetwork() { + return forVirtualNetwork; + } + + public String getVlanId() { + return vlanId; + } + + public String getVlanName() { + return vlanName; + } + + public Boolean getStaticNat() { + return staticNat; + } + + public String getVirtualMachineId() { + return virtualMachineId; + } + + public String getVirtualMachineName() { + return virtualMachineName; + } + + public String getVirtualMachineDisplayName() { + return virtualMachineDisplayName; + } + + public String getAssociatedNetworkId() { + return associatedNetworkId; + } + + public String getNetworkId() { + return networkId; + } + + public String getState() { + return state; + } + + public String getJobId() { + return jobId; + } + + public Integer getJobStatus() { + return jobStatus; + } +} diff --git a/test/src/com/cloud/test/demo/response/CloudStackNic.java b/test/src/com/cloud/test/demo/response/CloudStackNic.java new file mode 100644 index 00000000000..7975faea947 --- /dev/null +++ b/test/src/com/cloud/test/demo/response/CloudStackNic.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.cloud.test.demo.response; + +import com.google.gson.annotations.SerializedName; + +public class CloudStackNic { + + @SerializedName(ApiConstants.ID) + private String id; + + @SerializedName(ApiConstants.BROADCAST_URI) + private String broadcastUri; + + @SerializedName(ApiConstants.GATEWAY) + private String gateway; + + @SerializedName(ApiConstants.IP_ADDRESS) + private String ipaddress; + + @SerializedName(ApiConstants.IS_DEFAULT) + private Boolean isDefault; + + @SerializedName(ApiConstants.ISOLATION_URI) + private String isolationUri; + + @SerializedName(ApiConstants.MAC_ADDRESS) + private String macAddress; + + @SerializedName(ApiConstants.NETMASK) + private String netmask; + + @SerializedName(ApiConstants.NETWORK_ID) + private String networkid; + + @SerializedName(ApiConstants.TRAFFIC_TYPE) + private String trafficType; + + @SerializedName(ApiConstants.TYPE) + private String type; + + public CloudStackNic() { + } + + public String getId() { + return id; + } + + public String getNetworkid() { + return networkid; + } + + public String getNetmask() { + return netmask; + } + + public String getGateway() { + return gateway; + } + + public String getIpaddress() { + return ipaddress; + } + + public String getIsolationUri() { + return isolationUri; + } + + public String getBroadcastUri() { + return broadcastUri; + } + + public String getTrafficType() { + return trafficType; + } + + public String getType() { + return type; + } + + public Boolean getIsDefault() { + return isDefault; + } + + /** + * @return the macAddress + */ + public String getMacAddress() { + return macAddress; + } +} diff --git a/test/src/com/cloud/test/demo/response/CloudStackPortForwardingRule.java b/test/src/com/cloud/test/demo/response/CloudStackPortForwardingRule.java new file mode 100644 index 00000000000..2bbb35c7167 --- /dev/null +++ b/test/src/com/cloud/test/demo/response/CloudStackPortForwardingRule.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.cloud.test.demo.response; + +import com.google.gson.annotations.SerializedName; + +/** + * @author slriv + * + */ +public class CloudStackPortForwardingRule { + @SerializedName(ApiConstants.ID) + private Long id; + @SerializedName(ApiConstants.CIDR_LIST) + private String cidrList; + @SerializedName(ApiConstants.IP_ADDRESS) + private String ipAddress; + @SerializedName(ApiConstants.IP_ADDRESS_ID) + private Long ipAddressId; + @SerializedName(ApiConstants.PRIVATE_END_PORT) + private Long privateEndPort; + @SerializedName(ApiConstants.PRIVATE_PORT) + private Long privatePort; + @SerializedName(ApiConstants.PROTOCOL) + private String protocol; + @SerializedName(ApiConstants.PUBLIC_END_PORT) + private Long publicEndPort; + @SerializedName(ApiConstants.PUBLIC_PORT) + private Long publicPort; + @SerializedName(ApiConstants.STATE) + private String state; + @SerializedName(ApiConstants.VIRTUAL_MACHINE_DISPLAY_NAME) + private String virtualMachineDisplayName; + @SerializedName(ApiConstants.VIRTUAL_MACHINE_ID) + private Long virtualMachineId; + @SerializedName(ApiConstants.VIRTUAL_MACHINE_NAME) + private String virtualMachineName; + + /** + * + */ + public CloudStackPortForwardingRule() { + // TODO Auto-generated constructor stub + } + + /** + * @return the id + */ + public Long getId() { + return id; + } + + /** + * @return the cidrList + */ + public String getCidrList() { + return cidrList; + } + + /** + * @return the ipAddress + */ + public String getIpAddress() { + return ipAddress; + } + + /** + * @return the ipAddressId + */ + public Long getIpAddressId() { + return ipAddressId; + } + + /** + * @return the privateEndPort + */ + public Long getPrivateEndPort() { + return privateEndPort; + } + + /** + * @return the privatePort + */ + public Long getPrivatePort() { + return privatePort; + } + + /** + * @return the protocol + */ + public String getProtocol() { + return protocol; + } + + /** + * @return the publicEndPort + */ + public Long getPublicEndPort() { + return publicEndPort; + } + + /** + * @return the publicPort + */ + public Long getPublicPort() { + return publicPort; + } + + /** + * @return the state + */ + public String getState() { + return state; + } + + /** + * @return the virtualMachineDisplayName + */ + public String getVirtualMachineDisplayName() { + return virtualMachineDisplayName; + } + + /** + * @return the virtualMachineId + */ + public Long getVirtualMachineId() { + return virtualMachineId; + } + + /** + * @return the virtualMachineName + */ + public String getVirtualMachineName() { + return virtualMachineName; + } + + + +} diff --git a/test/src/com/cloud/test/demo/response/CloudStackSecurityGroup.java b/test/src/com/cloud/test/demo/response/CloudStackSecurityGroup.java new file mode 100644 index 00000000000..4d540d1b4bd --- /dev/null +++ b/test/src/com/cloud/test/demo/response/CloudStackSecurityGroup.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.cloud.test.demo.response; + +import java.util.List; + +import com.google.gson.annotations.SerializedName; + +public class CloudStackSecurityGroup { + @SerializedName(ApiConstants.ID) + private String id; + @SerializedName(ApiConstants.ACCOUNT) + private String accountName; + @SerializedName(ApiConstants.DESCRIPTION) + private String description; + @SerializedName(ApiConstants.DOMAIN) + private String domainName; + @SerializedName(ApiConstants.DOMAIN_ID) + private String domainId; + @SerializedName(ApiConstants.JOB_ID) + private Long jobId; + @SerializedName(ApiConstants.JOB_STATUS) + private Integer jobStatus; + @SerializedName(ApiConstants.NAME) + private String name; + @SerializedName(ApiConstants.INGRESS_RULE) + private List ingressRules; + + + public CloudStackSecurityGroup() { + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getAccountName() { + return accountName; + } + + public String getDomainId() { + return domainId; + } + + public String getDomainName() { + return domainName; + } + + public Long getJobId() { + return jobId; + } + + public Integer getJobStatus() { + return jobStatus; + } + + public List getIngressRules() { + return ingressRules; + } +} diff --git a/test/src/com/cloud/test/demo/response/CloudStackServiceOffering.java b/test/src/com/cloud/test/demo/response/CloudStackServiceOffering.java new file mode 100644 index 00000000000..a824dd62ab9 --- /dev/null +++ b/test/src/com/cloud/test/demo/response/CloudStackServiceOffering.java @@ -0,0 +1,181 @@ +package com.cloud.test.demo.response; + +import com.google.gson.annotations.SerializedName; + +public class CloudStackServiceOffering { + + @SerializedName(ApiConstants.ID) + private String id; + @SerializedName(ApiConstants.CPU_NUMBER) + private Long cpuNumber; + @SerializedName(ApiConstants.CPU_SPEED) + private Long cpuSpeed; + @SerializedName(ApiConstants.CREATED) + private String created; + @SerializedName(ApiConstants.DEFAULT_USE) + private Boolean defaultUse; + @SerializedName(ApiConstants.DISPLAY_TEXT) + private String displayText; + @SerializedName(ApiConstants.DOMAIN) + private String domain; + @SerializedName(ApiConstants.DOMAIN_ID) + private String domainId; + @SerializedName(ApiConstants.HOST_TAGS) + private String hostTags; + @SerializedName(ApiConstants.IS_SYSTEM) + private Boolean isSystem; + @SerializedName(ApiConstants.LIMIT_CPU_USE) + private Boolean limitCpuUse; + @SerializedName(ApiConstants.MEMORY) + private Long memory; + @SerializedName(ApiConstants.NAME) + private String name; + @SerializedName(ApiConstants.OFFER_HA) + private Boolean offerHa; + @SerializedName(ApiConstants.STORAGE_TYPE) + private String storageType; + @SerializedName(ApiConstants.SYSTEM_VM_TYPE) + private String systemVmType; + @SerializedName(ApiConstants.TAGS) + private String tags; + + /** + * + */ + public CloudStackServiceOffering() { + // TODO Auto-generated constructor stub + } + + /** + * @return the id + */ + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + /** + * @return the cpuNumber + */ + public Long getCpuNumber() { + return cpuNumber; + } + + /** + * @return the cpuSpeed + */ + public Long getCpuSpeed() { + return cpuSpeed; + } + + /** + * @return the created + */ + public String getCreated() { + return created; + } + + /** + * @return the defaultUse + */ + public Boolean getDefaultUse() { + return defaultUse; + } + + /** + * @return the displayText + */ + public String getDisplayText() { + return displayText; + } + + /** + * @return the domain + */ + public String getDomain() { + return domain; + } + + /** + * @return the domainId + */ + public String getDomainId() { + return domainId; + } + + public void setDomainId(String domainId) { + this.domainId = domainId; + } + + /** + * @return the hostTags + */ + public String getHostTags() { + return hostTags; + } + + /** + * @return the isSystem + */ + public Boolean getIsSystem() { + return isSystem; + } + + /** + * @return the limitCpuUse + */ + public Boolean getLimitCpuUse() { + return limitCpuUse; + } + + /** + * @return the memory + */ + public Long getMemory() { + return memory; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + /** + * @return the offerHa + */ + public Boolean getOfferHa() { + return offerHa; + } + + /** + * @return the storageType + */ + public String getStorageType() { + return storageType; + } + + /** + * @return the systemVmType + */ + public String getSystemVmType() { + return systemVmType; + } + + /** + * @return the tags + */ + public String getTags() { + return tags; + } + + } + diff --git a/test/src/com/cloud/test/demo/response/CloudStackUserVm.java b/test/src/com/cloud/test/demo/response/CloudStackUserVm.java new file mode 100644 index 00000000000..cefcff19ae5 --- /dev/null +++ b/test/src/com/cloud/test/demo/response/CloudStackUserVm.java @@ -0,0 +1,397 @@ +/* + * Copyright (C) 2011 Citrix Systems, Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.cloud.test.demo.response; + +import java.util.List; + +import com.google.gson.annotations.SerializedName; + +public class CloudStackUserVm { + @SerializedName(ApiConstants.ID) + private String id; + @SerializedName(ApiConstants.ACCOUNT) + private String accountName; + @SerializedName(ApiConstants.CPU_NUMBER) + private Integer cpuNumber; + @SerializedName(ApiConstants.CPU_SPEED) + private Integer cpuSpeed; + @SerializedName(ApiConstants.CPU_USED) + private String cpuUsed; + @SerializedName(ApiConstants.CREATED) + private String created; + @SerializedName(ApiConstants.DISPLAY_NAME) + private String displayName; + @SerializedName(ApiConstants.DOMAIN) + private String domainName; + @SerializedName(ApiConstants.DOMAIN_ID) + private String domainId; + @SerializedName(ApiConstants.FOR_VIRTUAL_NETWORK) + private Boolean forVirtualNetwork; + @SerializedName(ApiConstants.GROUP) + private String group; + @SerializedName(ApiConstants.GROUP_ID) + private String groupId; + @SerializedName(ApiConstants.GUEST_OS_ID) + private String guestOsId; + @SerializedName(ApiConstants.HA_ENABLE) + private Boolean haEnable; + @SerializedName(ApiConstants.HOST_ID) + private String hostId; + @SerializedName(ApiConstants.HOST_NAME) + private String hostName; + @SerializedName(ApiConstants.HYPERVISOR) + private String hypervisor; + @SerializedName(ApiConstants.IP_ADDRESS) + private String ipAddress; + @SerializedName(ApiConstants.ISO_DISPLAY_TEXT) + private String isoDisplayText; + @SerializedName(ApiConstants.ISO_ID) + private String isoId; + @SerializedName(ApiConstants.ISO_NAME) + private String isoName; + @SerializedName(ApiConstants.JOB_ID) + private String jobId; + @SerializedName(ApiConstants.JOB_STATUS) + private Integer jobStatus; + @SerializedName(ApiConstants.MEMORY) + private Integer memory; + @SerializedName(ApiConstants.NAME) + private String name; + @SerializedName(ApiConstants.NETWORK_KBS_READ) + private Long networkKbsRead; + @SerializedName(ApiConstants.NETWORK_KBS_WRITE) + private Long networkKbsWrite; + @SerializedName(ApiConstants.PASSWORD) + private String password; + @SerializedName(ApiConstants.PASSWORD_ENABLED) + private Boolean passwordEnabled; + @SerializedName(ApiConstants.ROOT_DEVICE_ID) + private String rootDeviceId; + @SerializedName(ApiConstants.ROOT_DEVICE_TYPE) + private String rootDeviceType; + @SerializedName(ApiConstants.SERVICE_OFFERING_ID) + private String serviceOfferingId; + @SerializedName(ApiConstants.SERVICE_OFFERING_NAME) + private String serviceOfferingName; + @SerializedName(ApiConstants.STATE) + private String state; + @SerializedName(ApiConstants.TEMPLATE_DISPLAY_TEXT) + private String templateDisplayText; + @SerializedName(ApiConstants.TEMPLATE_ID) + private String templateId; + @SerializedName(ApiConstants.TEMPLATE_NAME) + private String templateName; + @SerializedName(ApiConstants.ZONE_ID) + private String zoneId; + @SerializedName(ApiConstants.ZONE_NAME) + private String zoneName; + @SerializedName(ApiConstants.NIC) + private List nics; + @SerializedName(ApiConstants.SECURITY_GROUP) + private List securityGroupList; + + public CloudStackUserVm() { + } + + /** + * @return the id + */ + public String getId() { + return id; + } + + /** + * @return the accountName + */ + public String getAccountName() { + return accountName; + } + + /** + * @return the cpuNumber + */ + public Integer getCpuNumber() { + return cpuNumber; + } + + /** + * @return the cpuSpeed + */ + public Integer getCpuSpeed() { + return cpuSpeed; + } + + /** + * @return the cpuUsed + */ + public String getCpuUsed() { + return cpuUsed; + } + + /** + * @return the created + */ + public String getCreated() { + return created; + } + + /** + * @return the displayName + */ + public String getDisplayName() { + return displayName; + } + + /** + * @return the domainName + */ + public String getDomainName() { + return domainName; + } + + /** + * @return the domainId + */ + public String getDomainId() { + return domainId; + } + + /** + * @return the forVirtualNetwork + */ + public Boolean getForVirtualNetwork() { + return forVirtualNetwork; + } + + /** + * @return the group + */ + public String getGroup() { + return group; + } + + /** + * @return the groupId + */ + public String getGroupId() { + return groupId; + } + + /** + * @return the guestOsId + */ + public String getGuestOsId() { + return guestOsId; + } + + /** + * @return the haEnable + */ + public Boolean getHaEnable() { + return haEnable; + } + + /** + * @return the hostId + */ + public String getHostId() { + return hostId; + } + + /** + * @return the hostName + */ + public String getHostName() { + return hostName; + } + + /** + * @return the hypervisor + */ + public String getHypervisor() { + return hypervisor; + } + + /** + * @return the ipAddress + */ + public String getIpAddress() { + return ipAddress; + } + + /** + * @return the isoDisplayText + */ + public String getIsoDisplayText() { + return isoDisplayText; + } + + /** + * @return the isoId + */ + public String getIsoId() { + return isoId; + } + + /** + * @return the isoName + */ + public String getIsoName() { + return isoName; + } + + /** + * @return the jobId + */ + public String getJobId() { + return jobId; + } + + /** + * @return the jobStatus + */ + public Integer getJobStatus() { + return jobStatus; + } + + /** + * @return the memory + */ + public Integer getMemory() { + return memory; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @return the networkKbsRead + */ + public Long getNetworkKbsRead() { + return networkKbsRead; + } + + /** + * @return the networkKbsWrite + */ + public Long getNetworkKbsWrite() { + return networkKbsWrite; + } + + /** + * @return the password + */ + public String getPassword() { + return password; + } + + /** + * @return the passwordEnabled + */ + public Boolean getPasswordEnabled() { + return passwordEnabled; + } + + /** + * @return the rootDeviceId + */ + public String getRootDeviceId() { + return rootDeviceId; + } + + /** + * @return the rootDeviceType + */ + public String getRootDeviceType() { + return rootDeviceType; + } + + /** + * @return the serviceOfferingId + */ + public String getServiceOfferingId() { + return serviceOfferingId; + } + + /** + * @return the serviceOfferingName + */ + public String getServiceOfferingName() { + return serviceOfferingName; + } + + /** + * @return the state + */ + public String getState() { + return state; + } + + /** + * @return the templateDisplayText + */ + public String getTemplateDisplayText() { + return templateDisplayText; + } + + /** + * @return the templateId + */ + public String getTemplateId() { + return templateId; + } + + /** + * @return the templateName + */ + public String getTemplateName() { + return templateName; + } + + /** + * @return the zoneId + */ + public String getZoneId() { + return zoneId; + } + + /** + * @return the zoneName + */ + public String getZoneName() { + return zoneName; + } + + /** + * @return the nics + */ + public List getNics() { + return nics; + } + + /** + * @return the securityGroupList + */ + public List getSecurityGroupList() { + return securityGroupList; + } + +} + From 7a06da852027b154772d9b4f2f34698b14bbcc77 Mon Sep 17 00:00:00 2001 From: Nitin Mehta Date: Wed, 2 May 2012 11:24:46 +0530 Subject: [PATCH 11/16] bug CS-10789: Some more code to make the Uploav volume more robust. --- api/src/com/cloud/storage/Volume.java | 1 + .../cloud/server/ConfigurationServerImpl.java | 2 +- .../com/cloud/storage/StorageManagerImpl.java | 19 ++++++++++++------- .../storage/download/DownloadMonitorImpl.java | 10 +++++++++- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/api/src/com/cloud/storage/Volume.java b/api/src/com/cloud/storage/Volume.java index 9b5f9afe3f6..25d64e8d891 100755 --- a/api/src/com/cloud/storage/Volume.java +++ b/api/src/com/cloud/storage/Volume.java @@ -62,6 +62,7 @@ public interface Volume extends ControlledEntity, BasedOn, StateObject Date: Wed, 2 May 2012 11:41:53 +0530 Subject: [PATCH 12/16] bug CS-10789: Some upgerade change that tdidnt get merged. --- setup/db/db/schema-302to303.sql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup/db/db/schema-302to303.sql b/setup/db/db/schema-302to303.sql index 8bce08bf801..70c551bf2e0 100755 --- a/setup/db/db/schema-302to303.sql +++ b/setup/db/db/schema-302to303.sql @@ -31,10 +31,12 @@ UPDATE `cloud`.`user_vm` SET update_parameters=0 where id>0; INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'ha.tag', NULL, 'HA tag defining that the host marked with this tag can be used for HA purposes only'); +# Changes for Upload Volume CREATE TABLE `cloud`.`volume_host_ref` ( `id` bigint unsigned NOT NULL auto_increment, `host_id` bigint unsigned NOT NULL, `volume_id` bigint unsigned NOT NULL, + `zone_id` bigint unsigned NOT NULL, `created` DATETIME NOT NULL, `last_updated` DATETIME, `job_id` varchar(255), @@ -56,7 +58,7 @@ CREATE TABLE `cloud`.`volume_host_ref` ( INDEX `i_volume_host_ref__volume_id`(`volume_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; -INSERT IGNORE INTO `cloud`.`disk_offering` (name, display_text, customized, unique_name, disk_size, system_use) VALUES ( "Custom", "Custom Disk", 1, "Cloud.com-Custom", 0, 1); +INSERT IGNORE INTO `cloud`.`disk_offering` (name, display_text, customized, unique_name, disk_size, system_use) VALUES ( "Custom", "Custom Disk", 1, "Cloud.com-Custom", 0, 0); # Changes for OVS tunnel manager # The Following tables are not used anymore From 9b1fd4d414dd58a343151b13c638efaaeff61b5b Mon Sep 17 00:00:00 2001 From: Nitin Mehta Date: Wed, 2 May 2012 11:47:32 +0530 Subject: [PATCH 13/16] bug CS-10789: Some upgerade change that tdidnt get merged. --- setup/db/db/schema-302to303.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup/db/db/schema-302to303.sql b/setup/db/db/schema-302to303.sql index 70c551bf2e0..2fd4c53159a 100755 --- a/setup/db/db/schema-302to303.sql +++ b/setup/db/db/schema-302to303.sql @@ -58,7 +58,8 @@ CREATE TABLE `cloud`.`volume_host_ref` ( INDEX `i_volume_host_ref__volume_id`(`volume_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; -INSERT IGNORE INTO `cloud`.`disk_offering` (name, display_text, customized, unique_name, disk_size, system_use) VALUES ( "Custom", "Custom Disk", 1, "Cloud.com-Custom", 0, 0); +INSERT IGNORE INTO `cloud`.`disk_offering` (name, display_text, customized, unique_name, disk_size, system_use) VALUES ( 'Custom', 'Custom Disk', 1, 'Cloud.com-Custom', 0, 0); +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Storage', 'DEFAULT', 'management-server', 'storage.max.volume.upload.size', 500, 'The maximum size for a uploaded volume(in GB).'); # Changes for OVS tunnel manager # The Following tables are not used anymore From 78616f56954fe38e8a8e1bb453e4746744ac718e Mon Sep 17 00:00:00 2001 From: Chirag Jog Date: Wed, 2 May 2012 03:57:48 -0700 Subject: [PATCH 14/16] 1. Support for egress rules, Network offerings and High Availability tests 2. Remove uneccesary code in project file. --- .../testcase/P1-tests/test_egress_rules.py | 2335 +++++++++++++++++ .../P1-tests/test_high_availability.py | 968 +++++++ .../P1-tests/test_network_offering.py | 1782 +++++++++++++ .../testcase/P1-tests/test_project_configs.py | 14 +- .../testcase/P1-tests/test_project_limits.py | 2 +- .../testcase/P1-tests/test_projects.py | 173 +- tools/testClient/testcase/libs/base.py | 85 +- 7 files changed, 5342 insertions(+), 17 deletions(-) create mode 100644 tools/testClient/testcase/P1-tests/test_egress_rules.py create mode 100644 tools/testClient/testcase/P1-tests/test_high_availability.py create mode 100644 tools/testClient/testcase/P1-tests/test_network_offering.py diff --git a/tools/testClient/testcase/P1-tests/test_egress_rules.py b/tools/testClient/testcase/P1-tests/test_egress_rules.py new file mode 100644 index 00000000000..1edb37a8626 --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_egress_rules.py @@ -0,0 +1,2335 @@ +# -*- encoding: utf-8 -*- +# Copyright 2012 Citrix Systems, Inc. Licensed under the +# Apache License, Version 2.0 (the "License"); you may not use this +# file except in compliance with the License. Citrix Systems, Inc. +# reserves all rights not expressly granted by the License. +# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Automatically generated by addcopyright.py at 04/03/2012 + +""" P1 for Egresss & Ingress rules +""" +#Import Local Modules +from cloudstackTestCase import * +from cloudstackAPI import * +import remoteSSHClient +from testcase.libs.utils import * +from testcase.libs.base import * +from testcase.libs.common import * + +#Import System modules +import time +import subprocess + + +class Services: + """Test Security groups Services + """ + + def __init__(self): + self.services = { + "disk_offering": { + "displaytext": "Small", + "name": "Small", + "disksize": 1 + }, + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended in create account to + # ensure unique username generated each time + "password": "fr3sca", + }, + "virtual_machine": { + # Create a small virtual machine instance with disk offering + "displayname": "Test VM", + "username": "root", # VM creds for SSH + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + "userdata": 'This is sample data', + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "security_group": { + "name": 'SSH', + "protocol": 'TCP', + "startport": 22, + "endport": 22, + "cidrlist": '0.0.0.0/0', + }, + "sg_invalid_port": { + "name": 'SSH', + "protocol": 'TCP', + "startport": -22, + "endport": -22, + "cidrlist": '0.0.0.0/0', + }, + "sg_invalid_cidr": { + "name": 'SSH', + "protocol": 'TCP', + "startport": 22, + "endport": 22, + "cidrlist": '0.0.0.10' + }, + "sg_cidr_anywhere": { + "name": 'SSH', + "protocol": 'TCP', + "startport": 22, + "endport": 22, + "cidrlist": '0.0.0.0/0' + }, + "sg_cidr_restricted": { + "name": 'SSH', + "protocol": 'TCP', + "startport": 22, + "endport": 22, + "cidrlist": '10.0.0.1/24', + }, + "sg_account": { + "name": 'SSH', + "protocol": 'TCP', + "startport": 22, + "endport": 22, + "cidrlist": '0.0.0.0/0', + }, + "mgmt_server": { + "username": "root", + "password": "fr3sca", + "ipaddress": "192.168.100.21" + }, + "ostypeid": '85cb528f-72ed-4df9-ac6a-f6ccf0892ff2', + # CentOS 5.3 (64-bit) + "sleep": 60, + "timeout": 10, + "mode": 'basic', + # Networking mode: Basic or Advanced + } + + +class TestDefaultSecurityGroupEgress(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = super( + TestDefaultSecurityGroupEgress, + cls + ).getClsTestClient().getApiClient() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_deployVM_InDefaultSecurityGroup(self): + """Test deploy VM in default security group with no egress rules + """ + + # Validate the following: + # 1. Deploy a VM. + # 2. Deployed VM should be running, verify with listVirtualMachiens + # 3. listSecurityGroups for this account. should list the default + # security group with no egress rules + # 4. listVirtualMachines should show that the VM belongs to default + # security group + + self.debug("Deploying VM in account: %s" % self.account.account.name) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.debug("Deployed VM with ID: %s" % self.virtual_machine.id) + self.cleanup.append(self.virtual_machine) + + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check for list VM response" + ) + vm_response = list_vm_response[0] + self.assertNotEqual( + len(list_vm_response), + 0, + "Check VM available in List Virtual Machines" + ) + + self.assertEqual( + + vm_response.id, + self.virtual_machine.id, + "Check virtual machine id in listVirtualMachines" + ) + + self.assertEqual( + vm_response.state, + 'Running', + "VM state should be running" + ) + self.assertEqual( + hasattr(vm_response, "securitygroup"), + True, + "List VM response should have atleast one security group" + ) + + # Verify listSecurity groups response + security_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(security_groups, list), + True, + "Check for list security groups response" + ) + self.assertEqual( + len(security_groups), + 1, + "Check List Security groups response" + ) + self.debug("List Security groups response: %s" % + str(security_groups)) + sec_grp = security_groups[0] + self.assertEqual( + sec_grp.name, + 'default', + "List Sec Group should only list default sec. group" + ) + return + + +class TestAuthorizeIngressRule(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = super( + TestAuthorizeIngressRule, + cls + ).getClsTestClient().getApiClient() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_authorizeIngressRule(self): + """Test authorize ingress rule + """ + + # Validate the following: + # 1. createaccount of type user + # 2. createsecuritygroup (ssh) for this account + # 3. authorizeSecurityGroupIngress to allow ssh access to the VM + # 4. deployVirtualMachine into this security group (ssh). deployed VM + # should be Running + # 5. listSecurityGroups should show two groups, default and ssh + # 6. verify that ssh-access into the VM is now allowed + # 7. verify from within the VM is able to ping outside world + # (ping www.google.com) + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + # Authorize Security group to SSH to VM + ingress_rule = security_group.authorize( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(ingress_rule, dict), + True, + "Check ingress rule created properly" + ) + + self.debug("Authorizing ingress rule for sec group ID: %s for ssh access" + % security_group.id) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id] + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % self.virtual_machine.ssh_ip) + ssh = self.virtual_machine.get_ssh_client() + + # Ping to outsite world + res = ssh.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machine.ipaddress, e) + ) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + return + + +class TestDefaultGroupEgress(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = super( + TestDefaultGroupEgress, + cls + ).getClsTestClient().getApiClient() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_01_default_group_with_egress(self): + """Test default group with egress rule before VM deploy and ping, ssh + """ + + # Validate the following: + # 1. createaccount of type user + # 2. createsecuritygroup (ssh) for this account + # 3. authorizeSecurityGroupIngress to allow ssh access to the VM + # 4. authorizeSecurityGroupEgress to allow ssh access only out to + # CIDR: 0.0.0.0/0 + # 5. deployVirtualMachine into this security group (ssh) + # 6. deployed VM should be Running, ssh should be allowed into the VM, + # ping out to google.com from the VM should fail, + # ssh from within VM to mgt server should pass + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + # Authorize Security group to SSH to VM + self.debug("Authorizing ingress rule for sec group ID: %s for ssh access" + % security_group.id) + ingress_rule = security_group.authorize( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + isinstance(ingress_rule, dict), + True, + "Check ingress rule created properly" + ) + + ssh_rule = (ingress_rule["ingressrule"][0]).__dict__ + + # Authorize Security group to SSH to VM + self.debug("Authorizing egress rule for sec group ID: %s for ssh access" + % security_group.id) + egress_rule = security_group.authorizeEgress( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + isinstance(egress_rule, dict), + True, + "Check egress rule created properly" + ) + ssh_egress_rule = (egress_rule["egressrule"][0]).__dict__ + + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id] + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % self.virtual_machine.ssh_ip) + + ssh = self.virtual_machine.get_ssh_client() + + self.debug("Ping to google.com from VM") + # Ping to outsite world + res = ssh.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machine.ipaddress, e) + ) + + result = str(res) + self.assertEqual( + result.count("0 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + try: + self.debug("SSHing into management server from VM") + res = ssh.execute("ssh %s@%s" % ( + self.services["mgmt_server"]["username"], + self.services["mgmt_server"]["ipaddress"] + )) + self.debug("SSH result: %s" % str(res)) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machine.ipaddress, e) + ) + result = str(res) + self.assertNotEqual( + result.count("No route to host"), + 1, + "SSH into management server from VM should be successful" + ) + return + + +class TestDefaultGroupEgressAfterDeploy(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = super( + TestDefaultGroupEgressAfterDeploy, + cls + ).getClsTestClient().getApiClient() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_01_default_group_with_egress(self): + """ Test default group with egress rule added after vm deploy and ping, + ssh test + """ + + # Validate the following: + # 1. createaccount of type user + # 2. createsecuritygroup (ssh) for this account + # 3. authorizeSecurityGroupIngress to allow ssh access to the VM + # 4. deployVirtualMachine into this security group (ssh) + # 5. authorizeSecurityGroupEgress to allow ssh access only out to + # CIDR: 0.0.0.0/0 + # 6. deployed VM should be Running, ssh should be allowed into the VM, + # ping out to google.com from the VM should fail + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + # Authorize Security group to SSH to VM + self.debug("Authorizing ingress rule for sec group ID: %s for ssh access" + % security_group.id) + ingress_rule = security_group.authorize( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + isinstance(ingress_rule, dict), + True, + "Check ingress rule created properly" + ) + + ssh_rule = (ingress_rule["ingressrule"][0]).__dict__ + + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id] + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Authorize Security group to SSH to VM + self.debug( + "Authorizing egress rule for sec group ID: %s for ssh access" + % security_group.id) + egress_rule = security_group.authorizeEgress( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + isinstance(egress_rule, dict), + True, + "Check egress rule created properly" + ) + ssh_egress_rule = (egress_rule["egressrule"][0]).__dict__ + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % self.virtual_machine.ssh_ip) + ssh = self.virtual_machine.get_ssh_client() + + self.debug("Ping to google.com from VM") + # Ping to outsite world + res = ssh.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + self.debug("SSH result: %s" % str(res)) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machine.ipaddress, e) + ) + + result = str(res) + self.assertEqual( + result.count("0 received"), + 1, + "Ping to outside world from VM should be successful" + ) + return + + +class TestRevokeEgressRule(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = super( + TestRevokeEgressRule, + cls + ).getClsTestClient().getApiClient() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_revoke_egress_rule(self): + """Test revoke security group egress rule + """ + + # Validate the following: + # 1. createaccount of type user + # 2. createsecuritygroup (ssh) for this account + # 3. authorizeSecurityGroupIngress to allow ssh access to the VM + # 4. authorizeSecurityGroupEgress to allow ssh access only out to + # CIDR: 0.0.0.0/0 + # 5. deployVirtualMachine into this security group (ssh) + # 6. deployed VM should be Running, ssh should be allowed into the VM, + # ping out to google.com from the VM should fail, + # ssh from within VM to mgt server should pass + # 7. Revoke egress rule. Verify ping and SSH access to management server + # is restored + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + # Authorize Security group to SSH to VM + self.debug( + "Authorizing ingress rule for sec group ID: %s for ssh access" + % security_group.id) + ingress_rule = security_group.authorize( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + isinstance(ingress_rule, dict), + True, + "Check ingress rule created properly" + ) + + ssh_rule = (ingress_rule["ingressrule"][0]).__dict__ + + # Authorize Security group to SSH to VM + self.debug( + "Authorizing egress rule for sec group ID: %s for ssh access" + % security_group.id) + egress_rule = security_group.authorizeEgress( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + isinstance(egress_rule, dict), + True, + "Check egress rule created properly" + ) + ssh_egress_rule = (egress_rule["egressrule"][0]).__dict__ + + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id] + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % self.virtual_machine.ssh_ip) + ssh = self.virtual_machine.get_ssh_client() + + self.debug("Ping to google.com from VM") + # Ping to outsite world + res = ssh.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + self.debug("SSH result: %s" % str(res)) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machine.ipaddress, e) + ) + + result = str(res) + self.assertEqual( + result.count("0 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + try: + self.debug("SSHing into management server from VM") + res = ssh.execute("ssh %s@%s" % ( + self.services["mgmt_server"]["username"], + self.services["mgmt_server"]["ipaddress"] + )) + self.debug("SSH result: %s" % str(res)) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machine.ipaddress, e) + ) + result = str(res) + self.assertNotEqual( + result.count("No route to host"), + 1, + "SSH into management server from VM should be successful" + ) + + self.debug( + "Revoke Egress Rule for Security Group %s for account: %s" \ + % ( + security_group.id, + self.account.account.name + )) + + result = security_group.revokeEgress( + self.apiclient, + id=ssh_egress_rule["ruleid"] + ) + self.debug("Revoke egress rule result: %s" % result) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % self.virtual_machine.ssh_ip) + ssh = self.virtual_machine.get_ssh_client(reconnect=True) + + self.debug("Ping to google.com from VM") + # Ping to outsite world + res = ssh.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machine.ipaddress, e) + ) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + try: + self.debug("SSHing into management server from VM") + res = ssh.execute("ssh %s@%s" % ( + self.services["mgmt_server"]["username"], + self.services["mgmt_server"]["ipaddress"] + )) + self.debug("SSH result: %s" % str(res)) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machine.ipaddress, e) + ) + result = str(res) + self.assertNotEqual( + result.count("No route to host"), + 1, + "SSH into management server from VM should be successful" + ) + return + + +class TestInvalidAccountAuthroize(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = super( + TestInvalidAccountAuthroize, + cls + ).getClsTestClient().getApiClient() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_invalid_account_authroize(self): + """Test invalid account authroize + """ + + # Validate the following: + # 1. createaccount of type user + # 2. createsecuritygroup (ssh) for this account + # 3. authorizeSecurityGroupEgress to allow ssh access only out to + # non-existent random account and default security group + # 4. listSecurityGroups should show ssh and default security groups + # 5. authorizeSecurityGroupEgress API should fail since there is no + # account + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + + # Authorize Security group to SSH to VM + self.debug( + "Authorizing egress rule for sec group ID: %s for ssh access" + % security_group.id) + with self.assertRaises(Exception): + egress_rule = security_group.authorizeEgress( + self.apiclient, + self.services["security_group"], + account=random_gen(), + domainid=self.account.account.domainid + ) + return + + +class TestMultipleAccountsEgressRuleNeg(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = super( + TestMultipleAccountsEgressRuleNeg, + cls + ).getClsTestClient().getApiClient() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.accountA = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.accountB = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.accountA.account.name + cls._cleanup = [ + cls.accountA, + cls.accountB, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_multiple_account_egress_rule_negative(self): + """Test multiple account egress rules negative case + """ + + # Validate the following: + # 1. createaccount of type user A + # 2. createaccount of type user B + # 3. createsecuritygroup (SSH-A) for account A + # 4. authorizeSecurityGroupEgress in account A to allow ssh access + # only out to VMs in account B's default security group + # 5. authorizeSecurityGroupIngress in account A to allow ssh incoming + # access from anywhere into Vm's of account A. listSecurityGroups + # for account A should show two groups (default and ssh-a) and ssh + # ingress rule and account based egress rule + # 6. deployVM in account A into security group SSH-A. deployed VM + # should be Running + # 7. deployVM in account B. deployed VM should be Running + # 8. ssh into VM in account A and from there ssh to VM in account B. + # ssh should fail + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.accountA.account.name, + domainid=self.accountA.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.accountA.account.name, + domainid=self.accountA.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + # Authorize Security group to SSH to VM + self.debug( + "Authorizing egress rule for sec group ID: %s for ssh access" + % security_group.id) + # Authorize to only account not CIDR + user_secgrp_list = {self.accountB.account.name: 'default'} + + egress_rule = security_group.authorizeEgress( + self.apiclient, + self.services["sg_account"], + account=self.accountA.account.name, + domainid=self.accountA.account.domainid, + user_secgrp_list=user_secgrp_list + ) + + self.assertEqual( + isinstance(egress_rule, dict), + True, + "Check egress rule created properly" + ) + ssh_egress_rule = (egress_rule["egressrule"][0]).__dict__ + + # Authorize Security group to SSH to VM + self.debug( + "Authorizing ingress rule for sec group ID: %s for ssh access" + % security_group.id) + ingress_rule = security_group.authorize( + self.apiclient, + self.services["security_group"], + account=self.accountA.account.name, + domainid=self.accountA.account.domainid + ) + + self.assertEqual( + isinstance(ingress_rule, dict), + True, + "Check ingress rule created properly" + ) + + ssh_rule = (ingress_rule["ingressrule"][0]).__dict__ + + self.virtual_machineA = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.accountA.account.name, + domainid=self.accountA.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id] + ) + self.cleanup.append(self.virtual_machineA) + self.debug("Deploying VM in account: %s" % self.accountA.account.name) + vms = VirtualMachine.list( + self.apiclient, + id=self.virtual_machineA.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VM should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "VM state after deployment should be running" + ) + self.debug("VM: %s state: %s" % (vm.id, vm.state)) + + self.virtual_machineB = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.accountB.account.name, + domainid=self.accountB.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(self.virtual_machineB) + self.debug("Deploying VM in account: %s" % self.accountB.account.name) + + vms = VirtualMachine.list( + self.apiclient, + id=self.virtual_machineB.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VM should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "VM state after deployment should be running" + ) + self.debug("VM: %s state: %s" % (vm.id, vm.state)) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % self.virtual_machineA.ssh_ip) + ssh = self.virtual_machineA.get_ssh_client() + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machineA.ipaddress, e) + ) + + try: + self.debug("SSHing into VM type B from VM A") + self.debug("VM IP: %s" % self.virtual_machineB.ssh_ip) + res = ssh.execute("ssh %s@%s" % ( + self.services["virtual_machine"]["username"], + self.virtual_machineB.ssh_ip + )) + self.debug("SSH result: %s" % str(res)) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machineA.ipaddress, e) + ) + result = str(res) + self.assertEqual( + result.count("Connection timed out"), + 1, + "SSH into management server from VM should not be successful" + ) + return + + +class TestMultipleAccountsEgressRule(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = super( + TestMultipleAccountsEgressRule, + cls + ).getClsTestClient().getApiClient() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.accountA = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.accountB = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.accountA.account.name + cls._cleanup = [ + cls.accountA, + cls.accountB, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_multiple_account_egress_rule_positive(self): + """Test multiple account egress rules positive case + """ + + # Validate the following: + # 1. createaccount of type user A + # 2. createaccount of type user B + # 3. createsecuritygroup (SSH-A) for account A + # 4. authorizeSecurityGroupEgress in account A to allow ssh access + # only out to VMs in account B's default security group + # 5. authorizeSecurityGroupIngress in account A to allow ssh incoming + # access from anywhere into Vm's of account A. listSecurityGroups + # for account A should show two groups (default and ssh-a) and ssh + # ingress rule and account based egress rule + # 6. deployVM in account A into security group SSH-A. deployed VM + # should be Running + # 7. deployVM in account B. deployed VM should be Running + # 8. ssh into VM in account A and from there ssh to VM in account B. + # ssh should fail + + security_groupA = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.accountA.account.name, + domainid=self.accountA.account.domainid + ) + self.debug("Created security group with ID: %s" % security_groupA.id) + + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.accountA.account.name, + domainid=self.accountA.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + + security_groupB = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.accountB.account.name, + domainid=self.accountB.account.domainid + ) + self.debug("Created security group with ID: %s" % security_groupB.id) + + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.accountB.account.name, + domainid=self.accountB.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + + # Authorize Security group to SSH to VM + self.debug( + "Authorizing egress rule for sec group ID: %s for ssh access" + % security_groupA.id) + # Authorize to only account not CIDR + user_secgrp_list = {self.accountB.account.name: security_groupB.name} + + egress_rule = security_groupA.authorizeEgress( + self.apiclient, + self.services["sg_account"], + account=self.accountA.account.name, + domainid=self.accountA.account.domainid, + user_secgrp_list=user_secgrp_list + ) + + self.assertEqual( + isinstance(egress_rule, dict), + True, + "Check egress rule created properly" + ) + ssh_egress_rule = (egress_rule["egressrule"][0]).__dict__ + + # Authorize Security group to SSH to VM + self.debug( + "Authorizing ingress rule for sec group ID: %s for ssh access" + % security_groupA.id) + ingress_ruleA = security_groupA.authorize( + self.apiclient, + self.services["security_group"], + account=self.accountA.account.name, + domainid=self.accountA.account.domainid + ) + + self.assertEqual( + isinstance(ingress_ruleA, dict), + True, + "Check ingress rule created properly" + ) + + ssh_ruleA = (ingress_ruleA["ingressrule"][0]).__dict__ + + self.virtual_machineA = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.accountA.account.name, + domainid=self.accountA.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_groupA.id] + ) + self.cleanup.append(self.virtual_machineA) + self.debug("Deploying VM in account: %s" % self.accountA.account.name) + + vms = VirtualMachine.list( + self.apiclient, + id=self.virtual_machineA.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VM should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "VM state after deployment should be running" + ) + self.debug("VM: %s state: %s" % (vm.id, vm.state)) + + # Authorize Security group to SSH to VM + self.debug( + "Authorizing ingress rule for sec group ID: %s for ssh access" + % security_groupB.id) + ingress_ruleB = security_groupB.authorize( + self.apiclient, + self.services["security_group"], + account=self.accountB.account.name, + domainid=self.accountB.account.domainid + ) + + self.assertEqual( + isinstance(ingress_ruleB, dict), + True, + "Check ingress rule created properly" + ) + + ssh_ruleB = (ingress_ruleB["ingressrule"][0]).__dict__ + + self.virtual_machineB = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.accountB.account.name, + domainid=self.accountB.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_groupB.id] + ) + self.cleanup.append(self.virtual_machineB) + self.debug("Deploying VM in account: %s" % self.accountB.account.name) + + vms = VirtualMachine.list( + self.apiclient, + id=self.virtual_machineB.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VM should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "VM state after deployment should be running" + ) + self.debug("VM: %s state: %s" % (vm.id, vm.state)) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % self.virtual_machineA.ssh_ip) + ssh = self.virtual_machineA.get_ssh_client() + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machineA.ipaddress, e) + ) + + try: + self.debug("SSHing into VB type B from VM A") + self.debug("VM IP: %s" % self.virtual_machineB.ssh_ip) + + res = ssh.execute("ssh %s@%s" % ( + self.services["virtual_machine"]["username"], + self.virtual_machineB.ssh_ip + )) + self.debug("SSH result: %s" % str(res)) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machineA.ipaddress, e) + ) + result = str(res) + self.assertNotEqual( + result.count("Connection timed out"), + 1, + "SSH into management server from VM should be successful" + ) + return + + +class TestStartStopVMWithEgressRule(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = super( + TestStartStopVMWithEgressRule, + cls + ).getClsTestClient().getApiClient() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_start_stop_vm_egress(self): + """ Test stop start Vm with egress rules + """ + + # Validate the following: + # 1. createaccount of type user + # 2. createsecuritygroup (ssh) for this account + # 3. authorizeSecurityGroupIngress to allow ssh access to the VM + # 4. authorizeSecurityGroupEgress to allow ssh access only out to + # CIDR: 0.0.0.0/0 + # 5. deployVirtualMachine into this security group (ssh) + # 6. stopVirtualMachine + # 7. startVirtualMachine + # 8. ssh in to VM + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + # Authorize Security group to SSH to VM + self.debug( + "Authorizing ingress rule for sec group ID: %s for ssh access" + % security_group.id) + ingress_rule = security_group.authorize( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + isinstance(ingress_rule, dict), + True, + "Check ingress rule created properly" + ) + + ssh_rule = (ingress_rule["ingressrule"][0]).__dict__ + + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id] + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Authorize Security group to SSH to VM + self.debug( + "Authorizing egress rule for sec group ID: %s for ssh access" + % security_group.id) + egress_rule = security_group.authorizeEgress( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + isinstance(egress_rule, dict), + True, + "Check egress rule created properly" + ) + ssh_egress_rule = (egress_rule["egressrule"][0]).__dict__ + + # Stop virtual machine + self.debug("Stopping virtual machine: %s" % self.virtual_machine.id) + self.virtual_machine.stop(self.apiclient) + + vms = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VM should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Stopped", + "VM state should be stopped" + ) + self.debug("VM: %s state: %s" % (vm.id, vm.state)) + + # Start virtual machine + self.debug("Starting virtual machine: %s" % self.virtual_machine.id) + self.virtual_machine.start(self.apiclient) + + vms = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VM should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "VM state should be stopped" + ) + self.debug("VM: %s state: %s" % (vm.id, vm.state)) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % self.virtual_machine.ssh_ip) + ssh = self.virtual_machine.get_ssh_client() + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machine.ipaddress, e) + ) + return + + +@unittest.skip("Valid bug- ID: CS-12647") +class TestInvalidParametersForEgress(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = super( + TestInvalidParametersForEgress, + cls + ).getClsTestClient().getApiClient() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_invalid_parameters(self): + """ Test invalid parameters for egress rules + """ + + # Validate the following: + # 1. createUserAccount + # 2. createSecurityGroup (test) + # 3. authorizeEgressRule (negative port) - Should fail + # 4. authorizeEgressRule (invalid CIDR) - Should fail + # 5. authorizeEgressRule (invalid account) - Should fail + # 6. authorizeEgressRule (22, cidr: anywhere) and + # authorizeEgressRule (22, cidr: restricted) - Should pass + # 7. authorizeEgressRule (21, cidr : 10.1.1.0/24) and + # authorizeEgressRule (21, cidr: 10.1.1.0/24) - Should fail + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + + # Authorize Security group to SSH to VM + self.debug( + "Authorizing egress rule for sec group ID: %s with invalid port" + % security_group.id) + with self.assertRaises(Exception): + egress_rule = security_group.authorizeEgress( + self.apiclient, + self.services["sg_invalid_port"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug( + "Authorizing egress rule for sec group ID: %s with invalid cidr" + % security_group.id) + with self.assertRaises(Exception): + egress_rule = security_group.authorizeEgress( + self.apiclient, + self.services["sg_invalid_cidr"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug( + "Authorizing egress rule for sec group ID: %s with invalid account" + % security_group.id) + with self.assertRaises(Exception): + egress_rule = security_group.authorizeEgress( + self.apiclient, + self.services["security_group"], + account=random_gen(), + domainid=self.account.account.domainid + ) + self.debug( + "Authorizing egress rule for sec group ID: %s with cidr: anywhere and port: 22" + % security_group.id) + egress_rule_A = security_group.authorizeEgress( + self.apiclient, + self.services["sg_cidr_anywhere"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + isinstance(egress_rule_A, dict), + True, + "Check egress rule created properly" + ) + + egress_rule_R = security_group.authorizeEgress( + self.apiclient, + self.services["sg_cidr_restricted"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + isinstance(egress_rule_R, dict), + True, + "Check egress rule created properly" + ) + + self.debug( + "Authorizing egress rule for sec group ID: %s with duplicate port" + % security_group.id) + with self.assertRaises(Exception): + security_group.authorizeEgress( + self.apiclient, + self.services["sg_cidr_restricted"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + return + + +class TestEgressAfterHostMaintainance(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = super( + TestEgressAfterHostMaintainance, + cls + ).getClsTestClient().getApiClient() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.pod = get_pod( + cls.api_client, + zoneid=cls.zone.id + ) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_egress_after_host_maintainance(self): + """Test maintenance case for egress + """ + + # Validate the following: + # 1. createaccount of type user + # 2. createsecuritygroup (ssh) for this account + # 3. authorizeSecurityGroupIngress to allow ssh access to the VM + # 4. authorizeSecurityGroupEgress to allow ssh access only out to + # CIDR: 0.0.0.0/0 + # 5. deployVirtualMachine into this security group (ssh) + # 6. deployed VM should be Running, ssh should be allowed into the VM + # 7. Enable maintainance mode for host, cance maintainance mode + # 8. User should be able to SSH into VM after maintainace + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + # Authorize Security group to SSH to VM + self.debug( + "Authorizing ingress rule for sec group ID: %s for ssh access" + % security_group.id) + ingress_rule = security_group.authorize( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + isinstance(ingress_rule, dict), + True, + "Check ingress rule created properly" + ) + + ssh_rule = (ingress_rule["ingressrule"][0]).__dict__ + + # Authorize Security group to SSH to VM + self.debug( + "Authorizing egress rule for sec group ID: %s for ssh access" + % security_group.id) + egress_rule = security_group.authorizeEgress( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + isinstance(egress_rule, dict), + True, + "Check egress rule created properly" + ) + ssh_egress_rule = (egress_rule["egressrule"][0]).__dict__ + + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id] + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % self.virtual_machine.id) + ssh = self.virtual_machine.get_ssh_client() + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machine.ipaddress, e) + ) + vms = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "Check list VMs response for valid host" + ) + vm = vms[0] + + self.debug("Enabling host maintainance for ID: %s" % vm.hostid) + cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() + cmd.id = vm.hostid + self.apiclient.prepareHostForMaintenance(cmd) + + self.debug("Canceling host maintainance for ID: %s" % vm.hostid) + cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() + cmd.id = vm.hostid + self.apiclient.cancelHostMaintenance(cmd) + + self.debug("Waiting for SSVMs to come up") + wait_for_ssvms( + self.apiclient, + zoneid=self.zone.id, + podid=self.pod.id, + ) + self.debug("Starting VM: %s" % self.virtual_machine.id) + + self.virtual_machine.start(self.apiclient) + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % self.virtual_machine.id) + ssh = self.virtual_machine.get_ssh_client(reconnect=True) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machine.ipaddress, e) + ) + return diff --git a/tools/testClient/testcase/P1-tests/test_high_availability.py b/tools/testClient/testcase/P1-tests/test_high_availability.py new file mode 100644 index 00000000000..e4ee99e2216 --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_high_availability.py @@ -0,0 +1,968 @@ +# -*- encoding: utf-8 -*- +# Copyright 2012 Citrix Systems, Inc. Licensed under the +# Apache License, Version 2.0 (the "License"); you may not use this +# file except in compliance with the License. Citrix Systems, Inc. +# reserves all rights not expressly granted by the License. +# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Automatically generated by addcopyright.py at 04/03/2012 + +""" P1 tests for high availability +""" +#Import Local Modules +from cloudstackTestCase import * +from cloudstackAPI import * +from testcase.libs.utils import * +from testcase.libs.base import * +from testcase.libs.common import * +import remoteSSHClient +import datetime + + +class Services: + """Test network offering Services + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "HA", + "lastname": "HA", + "username": "HA", + # 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 + }, + "lbrule": { + "name": "SSH", + "alg": "roundrobin", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "protocol": "TCP" + }, + "fw_rule":{ + "startport": 1, + "endport": 6000, + "cidr": '55.55.0.0/11', + # Any network (For creating FW rule) + }, + "virtual_machine": { + "displayname": "VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostypeid": '9958b10f-9e5d-4ef1-908d-a047372d823b', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 100, + "mode":'advanced' + } + + +class TestHighAvailability(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = super( + TestHighAvailability, + 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.pod = get_pod( + cls.api_client, + zoneid=cls.zone.id, + services=cls.services + ) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"], + offerha=True + ) + cls._cleanup = [ + cls.service_offering, + ] + return + +# @classmethod +# def tearDownClass(cls): +# try: +# #Cleanup resources used +# cleanup_resources(cls.api_client, cls._cleanup) +# except Exception as e: +# raise Exception("Warning: Exception during cleanup : %s" % e) +# return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + +# def tearDown(self): +# try: +# #Clean up, terminate the created accounts, domains etc +# cleanup_resources(self.apiclient, self.cleanup) +# self.testClient.close() +# except Exception as e: +# raise Exception("Warning: Exception during cleanup : %s" % e) +# return + + def test_01_host_maintenance_mode(self): + """Test host maintenance mode + """ + + # Validate the following + # 1. Create Vms. Acquire IP. Create port forwarding & load balancing + # rules for Vms. + # 2. Host 1: put to maintenance mode. All Vms should failover to Host + # 2 in cluster. Vms should be in running state. All port forwarding + # rules and load balancing Rules should work. + # 3. After failover to Host 2 succeeds, deploy Vms. Deploy Vms on host + # 2 should succeed. + # 4. Host 1: cancel maintenance mode. + # 5. Host 2 : put to maintenance mode. All Vms should failover to + # Host 1 in cluster. + # 6. After failover to Host 1 succeeds, deploy VMs. Deploy Vms on + # host 1 should succeed. + + hosts = Host.list( + self.apiclient, + zoneid=self.zone.id, + resourcestate='Enabled', + type='Routing' + ) + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return valid host response" + ) + self.assertEqual( + len(hosts), + 2, + "There must be two hosts present in a cluster" + ) + self.debug("Checking HA with hosts: %s, %s" % ( + hosts[0].name, + hosts[1].name + )) + self.debug("Deploying VM in account: %s" % self.account.account.name) + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + self.debug("Deployed VM on host: %s" % vm.hostid) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in RUnning state" + ) + networks = Network.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return valid list for the account" + ) + network = networks[0] + + self.debug("Associating public IP for account: %s" % + self.account.account.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + network.id + )) + self.debug("Creating PF rule for IP address: %s" % + public_ip.ipaddress.ipaddress) + nat_rule= NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=public_ip.ipaddress.id + ) + + self.debug("Creating LB rule on IP with NAT: %s" % + public_ip.ipaddress.ipaddress) + + # Create Load Balancer rule on IP already having NAT rule + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name + ) + self.debug("Created LB rule with ID: %s" % lb_rule.id) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % virtual_machine.id) + ssh = virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (virtual_machine.ipaddress, e) + ) + + first_host = vm.hostid + self.debug("Enabling maintenance mode for host %s" % vm.hostid) + cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() + cmd.id = first_host + self.apiclient.prepareHostForMaintenance(cmd) + + self.debug("Waiting for SSVMs to come up") + wait_for_ssvms( + self.apiclient, + zoneid=self.zone.id, + podid=self.pod.id, + ) + + timeout = self.services["timeout"] + # Poll and check state of VM while it migrates from one host to another + while True: + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + + self.debug("VM 1 state: %s" % vm.state) + if vm.state in ["Stopping", "Stopped", "Running", "Starting"]: + if vm.state == "Running": + break + else: + time.sleep(self.services["sleep"]) + timeout = timeout - 1 + else: + self.fail( + "VM migration from one-host-to-other failed while enabling maintenance" + ) + second_host = vm.hostid + self.assertEqual( + vm.state, + "Running", + "VM should be in Running state after enabling host maintenance" + ) + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % virtual_machine.id) + ssh = virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (virtual_machine.ipaddress, e) + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + # Spawn an instance on other host + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + self.debug("Deployed VM on host: %s" % vm.hostid) + self.debug("VM 2 state: %s" % vm.state) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in Running state" + ) + + self.debug("Canceling host maintenance for ID: %s" % first_host) + cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() + cmd.id = first_host + self.apiclient.cancelHostMaintenance(cmd) + self.debug("Maintenance mode canceled for host: %s" % first_host) + + self.debug("Enabling maintenance mode for host %s" % second_host) + cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() + cmd.id = second_host + self.apiclient.prepareHostForMaintenance(cmd) + self.debug("Maintenance mode enabled for host: %s" % second_host) + + self.debug("Waiting for SSVMs to come up") + wait_for_ssvms( + self.apiclient, + zoneid=self.zone.id, + podid=self.pod.id, + ) + + # Poll and check the status of VMs + timeout = self.services["timeout"] + while True: + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + self.debug( + "VM state after enabling maintenance on first host: %s" % + vm.state) + if vm.state in ["Stopping", "Stopped", "Running", "Starting"]: + if vm.state == "Running": + break + else: + time.sleep(self.services["sleep"]) + timeout = timeout - 1 + else: + self.fail( + "VM migration from one-host-to-other failed while enabling maintenance" + ) + + for vm in vms: + self.debug( + "VM states after enabling maintenance mode on host: %s - %s" % + (first_host, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in Running state" + ) + # Spawn an instance on other host + virtual_machine_3 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine_3.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + + self.debug("Deployed VM on host: %s" % vm.hostid) + self.debug("VM 3 state: %s" % vm.state) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in Running state" + ) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % virtual_machine.id) + ssh = virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (virtual_machine.ipaddress, e) + ) + + self.debug("Canceling host maintenance for ID: %s" % second_host) + cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() + cmd.id = second_host + self.apiclient.cancelHostMaintenance(cmd) + self.debug("Maintenance mode canceled for host: %s" % second_host) + self.debug("Waiting for SSVMs to come up") + wait_for_ssvms( + self.apiclient, + zoneid=self.zone.id, + podid=self.pod.id, + ) + return + + def test_02_host_maintenance_mode_with_activities(self): + """Test host maintenance mode with activities + """ + + # Validate the following + # 1. Create Vms. Acquire IP. Create port forwarding & load balancing + # rules for Vms. + # 2. While activities are ongoing: Create snapshots, recurring + # snapshots, create templates, download volumes, Host 1: put to + # maintenance mode. All Vms should failover to Host 2 in cluster + # Vms should be in running state. All port forwarding rules and + # load balancing Rules should work. + # 3. After failover to Host 2 succeeds, deploy Vms. Deploy Vms on host + # 2 should succeed. All ongoing activities in step 3 should succeed + # 4. Host 1: cancel maintenance mode. + # 5. While activities are ongoing: Create snapshots, recurring + # snapshots, create templates, download volumes, Host 2: put to + # maintenance mode. All Vms should failover to Host 1 in cluster. + # 6. After failover to Host 1 succeeds, deploy VMs. Deploy Vms on + # host 1 should succeed. All ongoing activities in step 6 should + # succeed. + + hosts = Host.list( + self.apiclient, + zoneid=self.zone.id, + resourcestate='Enabled', + type='Routing' + ) + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return valid host response" + ) + self.assertEqual( + len(hosts), + 2, + "There must be two hosts present in a cluster" + ) + self.debug("Checking HA with hosts: %s, %s" % ( + hosts[0].name, + hosts[1].name + )) + self.debug("Deploying VM in account: %s" % self.account.account.name) + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + self.debug("Deployed VM on host: %s" % vm.hostid) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in RUnning state" + ) + networks = Network.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return valid list for the account" + ) + network = networks[0] + + self.debug("Associating public IP for account: %s" % + self.account.account.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + network.id + )) + self.debug("Creating PF rule for IP address: %s" % + public_ip.ipaddress.ipaddress) + nat_rule= NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=public_ip.ipaddress.id + ) + + self.debug("Creating LB rule on IP with NAT: %s" % + public_ip.ipaddress.ipaddress) + + # Create Load Balancer rule on IP already having NAT rule + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name + ) + self.debug("Created LB rule with ID: %s" % lb_rule.id) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % virtual_machine.id) + ssh = virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (virtual_machine.ipaddress, e) + ) + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + virtualmachineid=virtual_machine.id, + type='ROOT', + listall=True + ) + volume = volumes[0] + self.debug( + "Root volume of VM(%s): %s" % ( + virtual_machine.name, + volume.name + )) + # Create a snapshot from the ROOTDISK + self.debug("Creating snapshot on ROOT volume: %s" % volume.name) + snapshot = Snapshot.create(self.apiclient, volumes[0].id) + self.debug("Snapshot created: ID - %s" % snapshot.id) + + snapshots = list_snapshots( + self.apiclient, + id=snapshot.id, + listall=True + ) + self.assertEqual( + isinstance(snapshots, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + snapshots, + None, + "Check if result exists in list snapshots call" + ) + self.assertEqual( + snapshots[0].id, + snapshot.id, + "Check snapshot id in list resources call" + ) + # Generate template from the snapshot + self.debug("Generating template from snapshot: %s" % snapshot.name) + template = Template.create_from_snapshot( + self.apiclient, + snapshot, + self.services["templates"] + ) + self.cleanup.append(template) + self.debug("Created template from snapshot: %s" % template.id) + + templates = list_templates( + self.apiclient, + templatefilter=\ + self.services["templates"]["templatefilter"], + id=template.id + ) + + self.assertEqual( + isinstance(templates, list), + True, + "List template call should return the newly created template" + ) + + self.assertEqual( + templates[0].isready, + True, + "The newly created template should be in ready state" + ) + + first_host = vm.hostid + self.debug("Enabling maintenance mode for host %s" % vm.hostid) + cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() + cmd.id = first_host + self.apiclient.prepareHostForMaintenance(cmd) + + self.debug("Waiting for SSVMs to come up") + wait_for_ssvms( + self.apiclient, + zoneid=self.zone.id, + podid=self.pod.id, + ) + + timeout = self.services["timeout"] + # Poll and check state of VM while it migrates from one host to another + while True: + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + + self.debug("VM 1 state: %s" % vm.state) + if vm.state in ["Stopping", "Stopped", "Running", "Starting"]: + if vm.state == "Running": + break + else: + time.sleep(self.services["sleep"]) + timeout = timeout - 1 + else: + self.fail( + "VM migration from one-host-to-other failed while enabling maintenance" + ) + second_host = vm.hostid + self.assertEqual( + vm.state, + "Running", + "VM should be in Running state after enabling host maintenance" + ) + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % virtual_machine.id) + ssh = virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (virtual_machine.ipaddress, e) + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + # Spawn an instance on other host + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + self.debug("Deployed VM on host: %s" % vm.hostid) + self.debug("VM 2 state: %s" % vm.state) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in Running state" + ) + + self.debug("Canceling host maintenance for ID: %s" % first_host) + cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() + cmd.id = first_host + self.apiclient.cancelHostMaintenance(cmd) + self.debug("Maintenance mode canceled for host: %s" % first_host) + + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + virtualmachineid=virtual_machine_2.id, + type='ROOT', + listall=True + ) + volume = volumes[0] + self.debug( + "Root volume of VM(%s): %s" % ( + virtual_machine_2.name, + volume.name + )) + # Create a snapshot from the ROOTDISK + self.debug("Creating snapshot on ROOT volume: %s" % volume.name) + snapshot = Snapshot.create(self.apiclient, volumes[0].id) + self.debug("Snapshot created: ID - %s" % snapshot.id) + + snapshots = list_snapshots( + self.apiclient, + id=snapshot.id, + listall=True + ) + self.assertEqual( + isinstance(snapshots, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + snapshots, + None, + "Check if result exists in list snapshots call" + ) + self.assertEqual( + snapshots[0].id, + snapshot.id, + "Check snapshot id in list resources call" + ) + # Generate template from the snapshot + self.debug("Generating template from snapshot: %s" % snapshot.name) + template = Template.create_from_snapshot( + self.apiclient, + snapshot, + self.services["templates"] + ) + self.cleanup.append(template) + self.debug("Created template from snapshot: %s" % template.id) + + templates = list_templates( + self.apiclient, + templatefilter=\ + self.services["templates"]["templatefilter"], + id=template.id + ) + + self.assertEqual( + isinstance(templates, list), + True, + "List template call should return the newly created template" + ) + + self.assertEqual( + templates[0].isready, + True, + "The newly created template should be in ready state" + ) + + self.debug("Enabling maintenance mode for host %s" % second_host) + cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() + cmd.id = second_host + self.apiclient.prepareHostForMaintenance(cmd) + self.debug("Maintenance mode enabled for host: %s" % second_host) + + self.debug("Waiting for SSVMs to come up") + wait_for_ssvms( + self.apiclient, + zoneid=self.zone.id, + podid=self.pod.id, + ) + + # Poll and check the status of VMs + timeout = self.services["timeout"] + while True: + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + self.debug( + "VM state after enabling maintenance on first host: %s" % + vm.state) + if vm.state in ["Stopping", "Stopped", "Running", "Starting"]: + if vm.state == "Running": + break + else: + time.sleep(self.services["sleep"]) + timeout = timeout - 1 + else: + self.fail( + "VM migration from one-host-to-other failed while enabling maintenance" + ) + + for vm in vms: + self.debug( + "VM states after enabling maintenance mode on host: %s - %s" % + (first_host, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in Running state" + ) + # Spawn an instance on other host + virtual_machine_3 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine_3.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + + self.debug("Deployed VM on host: %s" % vm.hostid) + self.debug("VM 3 state: %s" % vm.state) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in Running state" + ) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % virtual_machine.id) + ssh = virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (virtual_machine.ipaddress, e) + ) + + self.debug("Canceling host maintenance for ID: %s" % second_host) + cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() + cmd.id = second_host + self.apiclient.cancelHostMaintenance(cmd) + self.debug("Maintenance mode canceled for host: %s" % second_host) + self.debug("Waiting for SSVMs to come up") + wait_for_ssvms( + self.apiclient, + zoneid=self.zone.id, + podid=self.pod.id, + ) + return diff --git a/tools/testClient/testcase/P1-tests/test_network_offering.py b/tools/testClient/testcase/P1-tests/test_network_offering.py new file mode 100644 index 00000000000..bea2f53f5b9 --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_network_offering.py @@ -0,0 +1,1782 @@ +# -*- encoding: utf-8 -*- +# Copyright 2012 Citrix Systems, Inc. Licensed under the +# Apache License, Version 2.0 (the "License"); you may not use this +# file except in compliance with the License. Citrix Systems, Inc. +# reserves all rights not expressly granted by the License. +# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Automatically generated by addcopyright.py at 04/03/2012 + +""" P1 tests for network offering +""" +#Import Local Modules +from cloudstackTestCase import * +from cloudstackAPI import * +from testcase.libs.utils import * +from testcase.libs.base import * +from testcase.libs.common import * +import remoteSSHClient +import datetime + + +class Services: + """Test network offering Services + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "network_offering": { + "name": 'Network offering-VR services', + "displaytext": 'Network offering-VR services', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList": { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'VirtualRouter', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "network_offering_netscaler": { + "name": 'Network offering-netscaler', + "displaytext": 'Network offering-netscaler', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList": { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + "openfirewall": False, + }, + "lbrule_port_2221": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2221, + "openfirewall": False, + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "protocol": "TCP" + }, + "natrule_port_66": { + "privateport": 22, + "publicport": 66, + "protocol": "TCP" + }, + "fw_rule": { + "startport": 1, + "endport": 6000, + "cidr": '55.55.0.0/11', + # Any network (For creating FW rule) + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostypeid": '9958b10f-9e5d-4ef1-908d-a047372d823b', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode": 'advanced' + } + + +class TestNOVirtualRouter(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNOVirtualRouter, + 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["ostypeid"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [] + return + + def tearDown(self): + try: + self.account.delete(self.apiclient) + interval = list_configurations( + self.apiclient, + name='account.cleanup.interval' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) * 2) + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_network_off_without_conserve_mode(self): + """Test Network offering with Conserve mode off and VR - All services + """ + + # Validate the following + # 1. Create a Network from the above network offering and deploy a VM. + # 2. On source NAT ipaddress, we should NOT be allowed to add a + # LB rules + # 3. On source NAT ipaddress, we should be NOT be allowed to add + # PF rule + # 4. On an ipaddress that has PF rules, we should NOT be allowed to + # add a LB rules. + # 5. On an ipaddress that has Lb rules, we should NOT allow PF rules + # to be programmed. + # 6. We should be allowed to program multiple PF rules on the same Ip + # address on different public ports. + # 7. We should be allowed to program multiple LB rules on the same Ip + # address for different public port ranges. + # 8. On source NAT ipaddress, we should be allowed to Enable VPN. + # 9. On SOurce NAT ipaddress, we will be allowed to add firewall rule + + # Create a network offering with all virtual router services enabled + self.debug( + "Creating n/w offering with all services in VR & conserve mode:off" + ) + self.network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering"], + conservemode=False + ) + self.cleanup.append(self.network_offering) + + self.debug("Created n/w offering with ID: %s" % + self.network_offering.id) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + src_nat_list = PublicIPAddress.list( + self.apiclient, + associatednetworkid=self.network.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True, + issourcenat=True, + ) + self.assertEqual( + isinstance(src_nat_list, list), + True, + "List Public IP should return a valid source NAT" + ) + self.assertNotEqual( + len(src_nat_list), + 0, + "Length of response from listPublicIp should not be 0" + ) + src_nat = src_nat_list[0] + self.debug("Trying to create LB rule on source NAT IP: %s" % + src_nat.ipaddress) + # Create Load Balancer rule with source NAT + with self.assertRaises(Exception): + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=src_nat.id, + accountid=self.account.account.name + ) + self.debug( + "Trying to create a port forwarding rule in source NAT: %s" % + src_nat.ipaddress) + #Create NAT rule + with self.assertRaises(Exception): + NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=src_nat.id + ) + + self.debug("Associating public IP for network: %s" % self.network.id) + ip_with_nat_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + + self.debug("Associated %s with network %s" % ( + ip_with_nat_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug("Creating PF rule for IP address: %s" % + ip_with_nat_rule.ipaddress.ipaddress) + NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=ip_with_nat_rule.ipaddress.id + ) + + self.debug("Trying to create LB rule on IP with NAT: %s" % + ip_with_nat_rule.ipaddress.ipaddress) + + # Create Load Balancer rule on IP already having NAT rule + with self.assertRaises(Exception): + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_nat_rule.ipaddress.id, + accountid=self.account.account.name + ) + self.debug("Creating PF rule with public port: 66") + + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule_port_66"], + ipaddressid=ip_with_nat_rule.ipaddress.id + ) + + # Check if NAT rule created successfully + nat_rules = NATRule.list( + self.apiclient, + id=nat_rule.id + ) + + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT rules should return valid list" + ) + + self.debug("Associating public IP for network: %s" % self.network.id) + ip_with_lb_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug("Creating LB rule for IP address: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + ip_with_nat_rule.ipaddress.ipaddress) + + with self.assertRaises(Exception): + NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id + ) + + self.debug("Creating LB rule with public port: 2221") + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule_port_2221"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name + ) + + # Check if NAT rule created successfully + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id + ) + + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return valid list" + ) + + self.debug("Creating firewall rule on source NAT: %s" % + src_nat.ipaddress) + #Create Firewall rule on source NAT + fw_rule = FireWallRule.create( + self.apiclient, + ipaddressid=src_nat.id, + protocol='TCP', + cidrlist=[self.services["fw_rule"]["cidr"]], + startport=self.services["fw_rule"]["startport"], + endport=self.services["fw_rule"]["endport"] + ) + self.debug("Created firewall rule: %s" % fw_rule.id) + + fw_rules = FireWallRule.list( + self.apiclient, + id=fw_rule.id + ) + self.assertEqual( + isinstance(fw_rules, list), + True, + "List fw rules should return a valid firewall rules" + ) + + self.assertNotEqual( + len(fw_rules), + 0, + "Length of fw rules response should not be zero" + ) + return + + def test_02_network_off_with_conserve_mode(self): + """Test Network offering with Conserve mode ON and VR - All services + """ + + # Validate the following + # 1. Create a Network from the above network offering and deploy a VM. + # 2. On source NAT ipaddress, we should be allowed to add a LB rules + # 3. On source NAT ipaddress, we should be allowed to add a PF rules + # 4. On source NAT ipaddress, we should be allowed to add a Firewall + # rules + # 5. On an ipaddress that has Lb rules, we should be allowed to + # program PF rules. + # 6. We should be allowed to program multiple PF rules on the same Ip + # address on different public ports. + # 7. We should be allowed to program multiple LB rules on the same Ip + # address for different public port ranges. + # 8. On source NAT ipaddress, we should be allowed to Enable VPN + # access. + + # Create a network offering with all virtual router services enabled + self.debug( + "Creating n/w offering with all services in VR & conserve mode:off" + ) + self.network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering"], + conservemode=True + ) + self.cleanup.append(self.network_offering) + + self.debug("Created n/w offering with ID: %s" % + self.network_offering.id) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + src_nat_list = PublicIPAddress.list( + self.apiclient, + associatednetworkid=self.network.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True, + issourcenat=True, + ) + self.assertEqual( + isinstance(src_nat_list, list), + True, + "List Public IP should return a valid source NAT" + ) + self.assertNotEqual( + len(src_nat_list), + 0, + "Length of response from listPublicIp should not be 0" + ) + + src_nat = src_nat_list[0] + + self.debug("Trying to create LB rule on source NAT IP: %s" % + src_nat.ipaddress) + # Create Load Balancer rule with source NAT + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=src_nat.id, + accountid=self.account.account.name + ) + self.debug("Created LB rule on source NAT: %s" % src_nat.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List lb rules should return a valid lb rules" + ) + self.assertNotEqual( + len(lb_rules), + 0, + "Length of response from listLbRules should not be 0" + ) + + self.debug( + "Trying to create a port forwarding rule in source NAT: %s" % + src_nat.ipaddress) + #Create NAT rule + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=src_nat.id + ) + self.debug("Created PF rule on source NAT: %s" % src_nat.ipaddress) + + nat_rules = NATRule.list( + self.apiclient, + id=nat_rule.id + ) + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT should return a valid port forwarding rules" + ) + self.assertNotEqual( + len(nat_rules), + 0, + "Length of response from listLbRules should not be 0" + ) + self.debug("Creating firewall rule on source NAT: %s" % + src_nat.ipaddress) + #Create Firewall rule on source NAT + fw_rule = FireWallRule.create( + self.apiclient, + ipaddressid=src_nat.id, + protocol='TCP', + cidrlist=[self.services["fw_rule"]["cidr"]], + startport=self.services["fw_rule"]["startport"], + endport=self.services["fw_rule"]["endport"] + ) + self.debug("Created firewall rule: %s" % fw_rule.id) + + fw_rules = FireWallRule.list( + self.apiclient, + id=fw_rule.id + ) + self.assertEqual( + isinstance(fw_rules, list), + True, + "List fw rules should return a valid firewall rules" + ) + + self.assertNotEqual( + len(fw_rules), + 0, + "Length of fw rules response should not be zero" + ) + + self.debug("Associating public IP for network: %s" % self.network.id) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + self.network.id + )) + self.debug("Creating PF rule for IP address: %s" % + public_ip.ipaddress.ipaddress) + NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=public_ip.ipaddress.id + ) + + self.debug("Trying to create LB rule on IP with NAT: %s" % + public_ip.ipaddress.ipaddress) + + # Create Load Balancer rule on IP already having NAT rule + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name + ) + self.debug("Creating PF rule with public port: 66") + + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule_port_66"], + ipaddressid=public_ip.ipaddress.id + ) + + # Check if NAT rule created successfully + nat_rules = NATRule.list( + self.apiclient, + id=nat_rule.id + ) + + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT rules should return valid list" + ) + + self.debug("Creating LB rule with public port: 2221") + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule_port_2221"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name + ) + + # Check if NAT rule created successfully + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id + ) + + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return valid list" + ) + + # User should be able to enable VPN on source NAT + self.debug("Created VPN with source NAT IP: %s" % src_nat.ipaddress) + # Assign VPN to source NAT + vpn = Vpn.create( + self.apiclient, + src_nat.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + vpns = Vpn.list( + self.apiclient, + publicipid=src_nat.id, + listall=True, + ) + + self.assertEqual( + isinstance(vpns, list), + True, + "List VPNs should return a valid VPN list" + ) + + self.assertNotEqual( + len(vpns), + 0, + "Length of list VPN response should not be zero" + ) + return + + +class TestNOWithNetscaler(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNOWithNetscaler, + 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["ostypeid"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [] + return + + def tearDown(self): + try: + self.account.delete(self.apiclient) + interval = list_configurations( + self.apiclient, + name='account.cleanup.interval' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) * 2) + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_network_off_without_conserve_mode(self): + """Test Nw off with Conserve mode off, VR-All services, LB-netscaler + """ + + # Validate the following + # 1. Create a Network from the above network offering and deploy a VM. + # 2. On source NAT ipaddress, we should NOT be allowed to add LB rule + # 3. On source NAT ipaddress, we should NOT be allowed to add PF rule + # 4. On an ipaddress that has PF rules, we should NOT be allowed to + # add a LB rules. + # 5. On an ipaddress that has Lb rules , we should NOT allow firewall + # rules to be programmed. + # 6. On an ipaddress that has Lb rules , we should NOT allow PF rules + # to be programmed. + # 7. We should be allowed to program multiple PF rules on the same Ip + # address on different public ports. + # 8. We should be allowed to program multiple LB rules on the same Ip + # address for different public port ranges. + # 9. On source NAT ipaddress, we should NOT be allowed to Enable VPN. + + # Create a network offering with all virtual router services enabled + self.debug( + "Creating n/w offering with all services in VR & conserve mode:ON" + ) + self.network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering_netscaler"], + conservemode=False + ) + self.cleanup.append(self.network_offering) + + self.debug("Created n/w offering with ID: %s" % + self.network_offering.id) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + src_nat_list = PublicIPAddress.list( + self.apiclient, + associatednetworkid=self.network.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True, + issourcenat=True, + ) + self.assertEqual( + isinstance(src_nat_list, list), + True, + "List Public IP should return a valid source NAT" + ) + self.assertNotEqual( + len(src_nat_list), + 0, + "Length of response from listPublicIp should not be 0" + ) + + src_nat = src_nat_list[0] + + self.debug("Trying to create LB rule on source NAT IP: %s" % + src_nat.ipaddress) + # Create Load Balancer rule with source NAT + with self.assertRaises(Exception): + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=src_nat.id, + accountid=self.account.account.name + ) + + self.debug( + "Trying to create a port forwarding rule in source NAT: %s" % + src_nat.ipaddress) + #Create NAT rule + with self.assertRaises(Exception): + NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=src_nat.id + ) + self.debug("Creating firewall rule on source NAT: %s" % + src_nat.ipaddress) + #Create Firewall rule on source NAT + fw_rule = FireWallRule.create( + self.apiclient, + ipaddressid=src_nat.id, + protocol='TCP', + cidrlist=[self.services["fw_rule"]["cidr"]], + startport=self.services["fw_rule"]["startport"], + endport=self.services["fw_rule"]["endport"] + ) + + self.debug("Created firewall rule: %s" % fw_rule.id) + + fw_rules = FireWallRule.list( + self.apiclient, + id=fw_rule.id + ) + self.assertEqual( + isinstance(fw_rules, list), + True, + "List fw rules should return a valid firewall rules" + ) + + self.assertNotEqual( + len(fw_rules), + 0, + "Length of fw rules response should not be zero" + ) + + self.debug("Associating public IP for network: %s" % self.network.id) + ip_with_nat_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + + self.debug("Associated %s with network %s" % ( + ip_with_nat_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug("Creating PF rule for IP address: %s" % + ip_with_nat_rule.ipaddress.ipaddress) + NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=ip_with_nat_rule.ipaddress.id + ) + + self.debug("Trying to create LB rule on IP with NAT: %s" % + ip_with_nat_rule.ipaddress.ipaddress) + + # Create Load Balancer rule on IP already having NAT rule + with self.assertRaises(Exception): + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_nat_rule.ipaddress.id, + accountid=self.account.account.name + ) + self.debug("Creating PF rule with public port: 66") + + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule_port_66"], + ipaddressid=ip_with_nat_rule.ipaddress.id + ) + + # Check if NAT rule created successfully + nat_rules = NATRule.list( + self.apiclient, + id=nat_rule.id + ) + + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT rules should return valid list" + ) + + self.debug("Associating public IP for network: %s" % self.network.id) + ip_with_lb_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug("Creating LB rule for IP address: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + ip_with_nat_rule.ipaddress.ipaddress) + + with self.assertRaises(Exception): + NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id + ) + + self.debug("Trying to create FW rule on IP with LB rule") + with self.assertRaises(Exception): + FireWallRule.create( + self.apiclient, + ipaddressid=src_nat.id, + protocol='TCP', + cidrlist=[self.services["fw_rule"]["cidr"]], + startport=self.services["fw_rule"]["startport"], + endport=self.services["fw_rule"]["endport"] + ) + + self.debug("Creating LB rule with public port: 2221") + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule_port_2221"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + # Check if NAT rule created successfully + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id + ) + + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return valid list" + ) + + # User should be able to enable VPN on source NAT + self.debug("Enabling VPN on source NAT IP: %s" % src_nat.ipaddress) + # Assign VPN to source NAT + with self.assertRaises(Exception): + Vpn.create( + self.apiclient, + src_nat.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + return + + def test_02_network_off_with_conserve_mode_netscaler(self): + """Test NW off with Conserve mode ON, LB-Netscaler and VR-All services + """ + + # Validate the following + # 1. Create a Network from the above network offering and deploy a VM. + # 2. On source NAT ipaddress, we should NOT be allowed to add LB rule + # 3. On source NAT ipaddress, we should be allowed to add PF rule and + # Fierwall rules. + # 4. On an ipaddress that has PF rules, we should NOT be allowed to + # add a LB rules. + # 5. On an ipaddress that has Lb rules , we should NOT allow firewall + # rules to be programmed. + # 6. On an ipaddress that has Lb rules , we should NOT allow PF rules + # to be programmed. + # 7. We should be allowed to program multiple PF rules on the same Ip + # address on different public ports. + # 8. We should be allowed to program multiple LB rules on the same Ip + # address for different public port ranges. + # 9. On source NAT ipaddress, we should be allowed to Enable VPN. + + # Create a network offering with all virtual router services enabled + self.debug( + "Creating n/w offering with all services in VR & conserve mode:ON" + ) + self.network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering_netscaler"], + conservemode=True + ) + self.cleanup.append(self.network_offering) + + self.debug("Created n/w offering with ID: %s" % + self.network_offering.id) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + src_nat_list = PublicIPAddress.list( + self.apiclient, + associatednetworkid=self.network.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True, + issourcenat=True, + ) + self.assertEqual( + isinstance(src_nat_list, list), + True, + "List Public IP should return a valid source NAT" + ) + self.assertNotEqual( + len(src_nat_list), + 0, + "Length of response from listPublicIp should not be 0" + ) + + src_nat = src_nat_list[0] + + self.debug("Trying to create LB rule on source NAT IP: %s" % + src_nat.ipaddress) + # Create Load Balancer rule with source NAT + with self.assertRaises(Exception): + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=src_nat.id, + accountid=self.account.account.name + ) + + self.debug( + "Trying to create a port forwarding rule in source NAT: %s" % + src_nat.ipaddress) + #Create NAT rule + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=src_nat.id + ) + self.debug("Created PF rule on source NAT: %s" % src_nat.ipaddress) + + nat_rules = NATRule.list( + self.apiclient, + id=nat_rule.id + ) + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT should return a valid port forwarding rules" + ) + self.assertNotEqual( + len(nat_rules), + 0, + "Length of response from listLbRules should not be 0" + ) + self.debug("Creating firewall rule on source NAT: %s" % + src_nat.ipaddress) + #Create Firewall rule on source NAT + fw_rule = FireWallRule.create( + self.apiclient, + ipaddressid=src_nat.id, + protocol='TCP', + cidrlist=[self.services["fw_rule"]["cidr"]], + startport=self.services["fw_rule"]["startport"], + endport=self.services["fw_rule"]["endport"] + ) + self.debug("Created firewall rule: %s" % fw_rule.id) + + fw_rules = FireWallRule.list( + self.apiclient, + id=fw_rule.id + ) + self.assertEqual( + isinstance(fw_rules, list), + True, + "List fw rules should return a valid firewall rules" + ) + + self.assertNotEqual( + len(fw_rules), + 0, + "Length of fw rules response should not be zero" + ) + self.debug("Associating public IP for network: %s" % self.network.id) + ip_with_nat_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + + self.debug("Associated %s with network %s" % ( + ip_with_nat_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug("Creating PF rule for IP address: %s" % + ip_with_nat_rule.ipaddress.ipaddress) + NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=ip_with_nat_rule.ipaddress.id + ) + + self.debug("Trying to create LB rule on IP with NAT: %s" % + ip_with_nat_rule.ipaddress.ipaddress) + + # Create Load Balancer rule on IP already having NAT rule + with self.assertRaises(Exception): + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_nat_rule.ipaddress.id, + accountid=self.account.account.name + ) + self.debug("Creating PF rule with public port: 66") + + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule_port_66"], + ipaddressid=ip_with_nat_rule.ipaddress.id + ) + + # Check if NAT rule created successfully + nat_rules = NATRule.list( + self.apiclient, + id=nat_rule.id + ) + + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT rules should return valid list" + ) + + self.debug("Associating public IP for network: %s" % self.network.id) + ip_with_lb_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug("Creating LB rule for IP address: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + ip_with_nat_rule.ipaddress.ipaddress) + + with self.assertRaises(Exception): + NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id + ) + + self.debug("Trying to create FW rule on IP with LB rule") + with self.assertRaises(Exception): + FireWallRule.create( + self.apiclient, + ipaddressid=src_nat.id, + protocol='TCP', + cidrlist=[self.services["fw_rule"]["cidr"]], + startport=self.services["fw_rule"]["startport"], + endport=self.services["fw_rule"]["endport"] + ) + + self.debug("Creating LB rule with public port: 2221") + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule_port_2221"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + # Check if NAT rule created successfully + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id + ) + + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return valid list" + ) + + # User should be able to enable VPN on source NAT + self.debug("Created VPN with source NAT IP: %s" % src_nat.ipaddress) + # Assign VPN to source NAT + vpn = Vpn.create( + self.apiclient, + src_nat.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + vpns = Vpn.list( + self.apiclient, + publicipid=src_nat.id, + listall=True, + ) + + self.assertEqual( + isinstance(vpns, list), + True, + "List VPNs should return a valid VPN list" + ) + + self.assertNotEqual( + len(vpns), + 0, + "Length of list VNP response should not be zero" + ) + return + + +class TestNetworkUpgrade(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNetworkUpgrade, + 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["ostypeid"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + + cls._cleanup = [ + cls.service_offering, + cls.network_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [] + return + + def tearDown(self): + try: + self.account.delete(self.apiclient) + interval = list_configurations( + self.apiclient, + name='account.cleanup.interval' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) * 2) + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_nwupgrade_netscaler_conserve_on(self): + """Test Nw upgrade to netscaler lb service and conserve mode ON + """ + + # Validate the following + # 1. Upgrade a network with VR and conserve mode ON TO + # A network that has Lb provided by "Netscaler" and all other + # services provided by "VR" and Conserve mode ON + # 2. Have PF and LB rules on the same ip address. Upgrade network + # should fail. + # 3. Have SourceNat,PF and VPN on the same IP address. Upgrade of + # network should succeed. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + src_nat_list = PublicIPAddress.list( + self.apiclient, + associatednetworkid=self.network.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True, + issourcenat=True, + ) + self.assertEqual( + isinstance(src_nat_list, list), + True, + "List Public IP should return a valid source NAT" + ) + self.assertNotEqual( + len(src_nat_list), + 0, + "Length of response from listPublicIp should not be 0" + ) + + src_nat = src_nat_list[0] + self.debug("Trying to create LB rule on source NAT IP: %s" % + src_nat.ipaddress) + # Create Load Balancer rule with source NAT + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=src_nat.id, + accountid=self.account.account.name + ) + self.debug("Created LB rule on source NAT: %s" % src_nat.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List lb rules should return a valid lb rules" + ) + self.assertNotEqual( + len(lb_rules), + 0, + "Length of response from listLbRules should not be 0" + ) + + self.debug( + "Trying to create a port forwarding rule in source NAT: %s" % + src_nat.ipaddress) + #Create NAT rule + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=src_nat.id + ) + self.debug("Created PF rule on source NAT: %s" % src_nat.ipaddress) + + nat_rules = NATRule.list( + self.apiclient, + id=nat_rule.id + ) + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT should return a valid port forwarding rules" + ) + self.assertNotEqual( + len(nat_rules), + 0, + "Length of response from listLbRules should not be 0" + ) + # Create a network offering with all virtual router services enabled + self.debug( + "Creating n/w offering with all services in VR & conserve mode:ON LB- Netscaler" + ) + ns_lb_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering_netscaler"], + conservemode=True + ) + self.cleanup.append(ns_lb_offering) + ns_lb_offering.update(self.apiclient, state='Enabled') + #Stop all the VMs associated with network to update cidr + self.debug("Stopping the VM: %s" % virtual_machine.name) + virtual_machine.stop(self.apiclient) + + self.debug("Updating network offering for network: %s" % + self.network.id) + with self.assertRaises(Exception): + self.network.update( + self.apiclient, + networkofferingid=ns_lb_offering.id, + changecidr=True + ) + + self.debug("Network upgrade failed!") + self.debug("Deleting LB Rule: %s" % lb_rule.id) + lb_rule.delete(self.apiclient) + self.debug("LB rule deleted") + + # Assign VPN to source NAT + self.debug("Enabling VPN on source NAT") + vpn = Vpn.create( + self.apiclient, + src_nat.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + vpns = Vpn.list( + self.apiclient, + publicipid=src_nat.id, + listall=True, + ) + + self.assertEqual( + isinstance(vpns, list), + True, + "List VPNs should return a valid VPN list" + ) + + self.assertNotEqual( + len(vpns), + 0, + "Length of list VPN response should not be zero" + ) + self.debug("Upgrading the network: %s" % self.network.id) + self.network.update( + self.apiclient, + networkofferingid=ns_lb_offering.id, + changecidr=True + ) + networks = Network.list( + self.apiclient, + id=self.network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List Networks should return a valid list for given network ID" + ) + self.assertNotEqual( + len(networks), + 0, + "Length of list networks should not be 0" + ) + network = networks[0] + self.assertEqual( + network.networkofferingid, + ns_lb_offering.id, + "Network offering ID should match with new offering ID" + ) + return + + def test_02_nwupgrade_netscaler_conserve_off(self): + """Test Nw upgrade to netscaler lb service and conserve mode OFF + """ + + # Validate the following + # 1. Upgrade a network with VR and conserve mode ON TO + # A network that has Lb provided by "Netscaler" and all other + # services provided by "VR" and Conserve mode OFF + # 2. Have PF and LB rules on the same ip address. Upgrade network + # should fail. + # 3. Have SourceNat,PF and VPN on the same IP address. Upgrade of + # network should fail. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + src_nat_list = PublicIPAddress.list( + self.apiclient, + associatednetworkid=self.network.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True, + issourcenat=True, + ) + self.assertEqual( + isinstance(src_nat_list, list), + True, + "List Public IP should return a valid source NAT" + ) + self.assertNotEqual( + len(src_nat_list), + 0, + "Length of response from listPublicIp should not be 0" + ) + + src_nat = src_nat_list[0] + self.debug("Trying to create LB rule on source NAT IP: %s" % + src_nat.ipaddress) + # Create Load Balancer rule with source NAT + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=src_nat.id, + accountid=self.account.account.name + ) + self.debug("Created LB rule on source NAT: %s" % src_nat.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List lb rules should return a valid lb rules" + ) + self.assertNotEqual( + len(lb_rules), + 0, + "Length of response from listLbRules should not be 0" + ) + + self.debug( + "Trying to create a port forwarding rule in source NAT: %s" % + src_nat.ipaddress) + #Create NAT rule + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=src_nat.id + ) + self.debug("Created PF rule on source NAT: %s" % src_nat.ipaddress) + + nat_rules = NATRule.list( + self.apiclient, + id=nat_rule.id + ) + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT should return a valid port forwarding rules" + ) + self.assertNotEqual( + len(nat_rules), + 0, + "Length of response from listLbRules should not be 0" + ) + # Create a network offering with all virtual router services enabled + self.debug( + "Creating n/w offering with all services in VR & conserve mode:ON LB- Netscaler" + ) + ns_lb_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering_netscaler"], + conservemode=False + ) + self.cleanup.append(ns_lb_offering) + ns_lb_offering.update(self.apiclient, state='Enabled') + #Stop all the VMs associated with network to update cidr + self.debug("Stopping the VM: %s" % virtual_machine.name) + virtual_machine.stop(self.apiclient) + + self.debug("Updating network offering for network: %s" % + self.network.id) + with self.assertRaises(Exception): + self.network.update( + self.apiclient, + networkofferingid=ns_lb_offering.id, + changecidr=True + ) + + self.debug("Network upgrade failed!") + self.debug("Deleting LB Rule: %s" % lb_rule.id) + lb_rule.delete(self.apiclient) + self.debug("LB rule deleted") + + # Assign VPN to source NAT + self.debug("Enabling VPN on source NAT") + vpn = Vpn.create( + self.apiclient, + src_nat.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + vpns = Vpn.list( + self.apiclient, + publicipid=src_nat.id, + listall=True, + ) + + self.assertEqual( + isinstance(vpns, list), + True, + "List VPNs should return a valid VPN list" + ) + + self.assertNotEqual( + len(vpns), + 0, + "Length of list VPN response should not be zero" + ) + self.debug("Upgrading the network: %s" % self.network.id) + with self.assertRaises(Exception): + self.network.update( + self.apiclient, + networkofferingid=ns_lb_offering.id, + changecidr=True + ) + return diff --git a/tools/testClient/testcase/P1-tests/test_project_configs.py b/tools/testClient/testcase/P1-tests/test_project_configs.py index e7abab519bd..eb3a36c4260 100644 --- a/tools/testClient/testcase/P1-tests/test_project_configs.py +++ b/tools/testClient/testcase/P1-tests/test_project_configs.py @@ -9,7 +9,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -# +# # Automatically generated by addcopyright.py at 04/03/2012 """ P1 tests for Project """ @@ -40,7 +40,7 @@ class Services: "ipaddress": '192.168.100.21', "username": 'root', "password": 'fr3sca', - "port": 22, + "port": 22, }, "account": { "email": "administrator@clogeny.com", @@ -52,7 +52,7 @@ class Services: "password": "fr3sca", }, "user": { - "email": "mayur.dhande@clogeny.com", + "email": "administrator@clogeny.com", "firstname": "User", "lastname": "User", "username": "User", @@ -118,7 +118,7 @@ class TestUserProjectCreation(cloudstackTestCase): cls.services = Services().services # Get Zone cls.zone = get_zone(cls.api_client, cls.services) - + # Create domains, account etc. cls.domain = Domain.create( cls.api_client, @@ -131,14 +131,14 @@ class TestUserProjectCreation(cloudstackTestCase): admin=True, domainid=cls.domain.id ) - + cls.user = Account.create( cls.api_client, cls.services["account"], admin=True, domainid=cls.domain.id ) - + cls._cleanup = [cls.account, cls.user, cls.domain] return @@ -174,7 +174,7 @@ class TestUserProjectCreation(cloudstackTestCase): # 1. Check if 'allow.user.create.projects' configuration is true # 2. Create a Project as domain admin # 3. Create a Project as domain user - # 4. In both 2 and 3 project creation should be successful + # 4. In both 2 and 3 project creation should be successful configs = Configurations.list( self.apiclient, diff --git a/tools/testClient/testcase/P1-tests/test_project_limits.py b/tools/testClient/testcase/P1-tests/test_project_limits.py index dbc677b2417..cfb4a247e2e 100644 --- a/tools/testClient/testcase/P1-tests/test_project_limits.py +++ b/tools/testClient/testcase/P1-tests/test_project_limits.py @@ -447,7 +447,7 @@ class TestResourceLimitsProject(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestResourceLimitsDomain, cls).getClsTestClient().getApiClient() + cls.api_client = super(TestResourceLimitsProject, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.zone = get_zone(cls.api_client, cls.services) diff --git a/tools/testClient/testcase/P1-tests/test_projects.py b/tools/testClient/testcase/P1-tests/test_projects.py index 55fa2f95ec0..aee9070e583 100644 --- a/tools/testClient/testcase/P1-tests/test_projects.py +++ b/tools/testClient/testcase/P1-tests/test_projects.py @@ -87,7 +87,7 @@ class Services: "publicport": 22, "protocol": 'TCP', }, - "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', + "ostypeid": '8531d1df-faac-4895-a741-238d3b10e6e6', # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, @@ -164,6 +164,23 @@ class TestMultipleProjectCreation(cloudstackTestCase): # 2. add one account to multiple project. Verify at step 2 an account # is allowed to added to multiple project + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.required' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + (config.value).lower(), + 'false', + "'project.invite.required' should be set to false" + ) + # Create project as a domain admin project_1 = Project.create( self.apiclient, @@ -181,7 +198,6 @@ class TestMultipleProjectCreation(cloudstackTestCase): id=project_1.id, listall=True ) - self.assertEqual( isinstance(list_projects_reponse, list), True, @@ -369,6 +385,23 @@ class TestCrossDomainAccountAdd(cloudstackTestCase): # 2. Add different domain account to the project. Add account should # fail + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.required' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + (config.value).lower(), + 'false', + "'project.invite.required' should be set to false" + ) + # Create project as a domain admin project = Project.create( self.apiclient, @@ -479,6 +512,23 @@ class TestDeleteAccountWithProject(cloudstackTestCase): # 2. Delete account who is owner of the project. Delete account should # fail + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.required' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + (config.value).lower(), + 'false', + "'project.invite.required' should be set to false" + ) + # Create project as a domain admin project = Project.create( self.apiclient, @@ -582,6 +632,23 @@ class TestDeleteDomainWithProject(cloudstackTestCase): # 2. Delete domain forcefully. Verify that project is also deleted as # as part of domain cleanup + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.required' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + (config.value).lower(), + 'false', + "'project.invite.required' should be set to false" + ) + # Create project as a domain admin project = Project.create( self.apiclient, @@ -718,6 +785,23 @@ class TestProjectOwners(cloudstackTestCase): # owner. verify new user is project owner and old account is # regular user of the project. + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.required' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + (config.value).lower(), + 'false', + "'project.invite.required' should be set to false" + ) + # Create project as a domain admin project = Project.create( self.apiclient, @@ -859,6 +943,23 @@ class TestProjectOwners(cloudstackTestCase): # owner. # 3. Update project to add another account as an owner + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.required' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + (config.value).lower(), + 'false', + "'project.invite.required' should be set to false" + ) + # Create project as a domain admin project = Project.create( self.apiclient, @@ -1140,6 +1241,23 @@ class TestProjectResources(cloudstackTestCase): # 3. Delete the account. Verify resources are still there after # account deletion. + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.required' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + (config.value).lower(), + 'false', + "'project.invite.required' should be set to false" + ) + # Create project as a domain admin project = Project.create( self.apiclient, @@ -1256,6 +1374,23 @@ class TestProjectResources(cloudstackTestCase): # account deletion. # 4. Verify all accounts are unassigned from project. + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.required' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + (config.value).lower(), + 'false', + "'project.invite.required' should be set to false" + ) + # Create project as a domain admin project = Project.create( self.apiclient, @@ -1460,6 +1595,23 @@ class TestProjectSuspendActivate(cloudstackTestCase): # 3. Delete the account. Verify resources are still there after # account deletion. + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.required' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + (config.value).lower(), + 'false', + "'project.invite.required' should be set to false" + ) + self.debug("Adding %s user to project: %s" % ( self.user.account.name, self.project.name @@ -1594,6 +1746,23 @@ class TestProjectSuspendActivate(cloudstackTestCase): # 1. Activate the project # 2. Verify project is activated and we are able to add resources + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.required' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + (config.value).lower(), + 'false', + "'project.invite.required' should be set to false" + ) + # Activating the project self.debug("Activating project: %s" % self.project.name) self.project.activate(self.apiclient) diff --git a/tools/testClient/testcase/libs/base.py b/tools/testClient/testcase/libs/base.py index 854f06c2ce6..638ff8cd577 100644 --- a/tools/testClient/testcase/libs/base.py +++ b/tools/testClient/testcase/libs/base.py @@ -878,7 +878,7 @@ class ServiceOffering: self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, domainid=None): + def create(cls, apiclient, services, domainid=None, **kwargs): """Create Service offering""" cmd = createServiceOffering.createServiceOfferingCmd() cmd.cpunumber = services["cpunumber"] @@ -891,6 +891,7 @@ class ServiceOffering: if domainid: cmd.domainid = domainid + [setattr(cmd, k, v) for k, v in kwargs.items()] return ServiceOffering(apiclient.createServiceOffering(cmd).__dict__) def delete(self, apiclient): @@ -953,12 +954,12 @@ class NetworkOffering: self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, serviceProviderList=None, **kwargs): + def create(cls, apiclient, services, **kwargs): """Create network offering""" cmd = createNetworkOffering.createNetworkOfferingCmd() - cmd.displaytext = services["displaytext"] - cmd.name = services["name"] + cmd.displaytext = "-".join([services["displaytext"], random_gen()]) + cmd.name = "-".join([services["name"], random_gen()]) cmd.guestiptype = services["guestiptype"] cmd.supportedservices = services["supportedservices"] cmd.traffictype = services["traffictype"] @@ -1039,7 +1040,7 @@ class LoadBalancerRule: @classmethod def create(cls, apiclient, services, ipaddressid, accountid=None, - projectid=None): + networkid=None, projectid=None): """Create Load balancing Rule""" cmd = createLoadBalancerRule.createLoadBalancerRuleCmd() @@ -1055,9 +1056,14 @@ class LoadBalancerRule: cmd.privateport = services["privateport"] cmd.publicport = services["publicport"] + if "openfirewall" in services: + cmd.openfirewall = services["openfirewall"] + if projectid: cmd.projectid = projectid - + + if networkid: + cmd.networkid = networkid return LoadBalancerRule(apiclient.createLoadBalancerRule(cmd).__dict__) def delete(self, apiclient): @@ -1322,6 +1328,14 @@ class Network: cmd.id = self.id apiclient.deleteNetwork(cmd) + def update(self, apiclient, **kwargs): + """Updates network with parameters passed""" + + cmd = updateNetwork.updateNetworkCmd() + cmd.id = self.id + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.updateNetwork(cmd)) + @classmethod def list(cls, apiclient, **kwargs): """List all Networks matching criteria""" @@ -1358,6 +1372,14 @@ class Vpn: cmd.publicipid = self.publicipid apiclient.deleteRemoteAccessVpn(cmd) + @classmethod + def list(cls, apiclient, **kwargs): + """List all VPN matching criteria""" + + cmd = listRemoteAccessVpns.listRemoteAccessVpnsCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listRemoteAccessVpns(cmd)) + class VpnUser: """Manage VPN user""" @@ -1390,6 +1412,14 @@ class VpnUser: cmd.domainid = self.domainid apiclient.removeVpnUser(cmd) + @classmethod + def list(cls, apiclient, **kwargs): + """List all VPN Users matching criteria""" + + cmd = listVpnUsers.listVpnUsersCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listVpnUsers(cmd)) + class Zone: """Manage Zone""" @@ -1640,7 +1670,48 @@ class SecurityGroup: cmd=revokeSecurityGroupIngress.revokeSecurityGroupIngressCmd() cmd.id=id return apiclient.revokeSecurityGroupIngress(cmd) + + def authorizeEgress(self, apiclient, services, account=None, domainid=None, + projectid=None, user_secgrp_list = {}): + """Authorize Egress Rule""" + + cmd=authorizeSecurityGroupEgress.authorizeSecurityGroupEgressCmd() + + if domainid: + cmd.domainid = domainid + if account: + cmd.account = account + + if projectid: + cmd.projectid = projectid + cmd.securitygroupid=self.id + cmd.protocol=services["protocol"] + + if services["protocol"] == 'ICMP': + cmd.icmptype = -1 + cmd.icmpcode = -1 + else: + cmd.startport = services["startport"] + cmd.endport = services["endport"] + + cmd.cidrlist = services["cidrlist"] + + cmd.usersecuritygrouplist = [] + for account, group in user_secgrp_list.items(): + cmd.usersecuritygrouplist.append({ + 'account' : account, + 'group': group + }) + + return (apiclient.authorizeSecurityGroupEgress(cmd).__dict__) + def revokeEgress(self, apiclient, id): + """Revoke Egress rule""" + + cmd=revokeSecurityGroupEgress.revokeSecurityGroupEgressCmd() + cmd.id=id + return apiclient.revokeSecurityGroupEgress(cmd) + @classmethod def list(cls, apiclient, **kwargs): """Lists all security groups.""" @@ -1787,4 +1858,4 @@ class Configurations: cmd = listConfigurations.listConfigurationsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] - return(apiclient.listConfigurations(cmd)) \ No newline at end of file + return(apiclient.listConfigurations(cmd)) From 3a0455daebc13b10bb5b2cd426a10bfc1c6d3d58 Mon Sep 17 00:00:00 2001 From: Murali reddy Date: Wed, 2 May 2012 17:20:10 +0530 Subject: [PATCH 15/16] bug cs-14285 NetScaler SDX: can not create VPX instances when XVA image is not NSVPX-XEN-9.3-52.4_nc.xva status cs-14285: resolved fixed This fix enables to use the first available VPX image and device profile on the SDX while creating VPX --- .../network/resource/NetscalerResource.java | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/core/src/com/cloud/network/resource/NetscalerResource.java b/core/src/com/cloud/network/resource/NetscalerResource.java index 160c90ec1e7..c7b31f31464 100644 --- a/core/src/com/cloud/network/resource/NetscalerResource.java +++ b/core/src/com/cloud/network/resource/NetscalerResource.java @@ -61,8 +61,11 @@ import com.citrix.netscaler.nitro.resource.config.network.*; import com.citrix.netscaler.nitro.resource.config.ns.*; import com.citrix.netscaler.nitro.resource.config.basic.server_service_binding; import com.citrix.netscaler.nitro.resource.stat.lb.lbvserver_stats; +import com.citrix.sdx.nitro.resource.config.device_profile; import com.citrix.sdx.nitro.resource.config.ns; import com.citrix.sdx.nitro.resource.config.mps; +import com.citrix.sdx.nitro.resource.config.xen_vpx_image; + import org.apache.log4j.Logger; class NitroError { @@ -179,7 +182,7 @@ public class NetscalerResource implements ServerResource { login(); validateDeviceType(_deviceName); validateInterfaces(_publicInterface, _privateInterface); - + //enable load balancing feature enableLoadBalancingFeature(); @@ -603,9 +606,26 @@ public class NetscalerResource implements ServerResource { ns_obj.set_memory_total(new Double(2048)); ns_obj.set_throughput(new Double(1000)); ns_obj.set_pps(new Double(1000000)); - ns_obj.set_nsroot_profile("NS_nsroot_profile"); ns_obj.set_number_of_ssl_cores(0); - ns_obj.set_image_name("NSVPX-XEN-9.3-52.4_nc.xva"); + + // use the first device profile available on the SDX to create an instance of VPX + device_profile[] profiles = device_profile.get(_netscalerSdxService); + if (!(profiles != null && profiles.length >= 1)) { + new Answer(cmd, new ExecutionException("Failed to create VPX instance on the netscaler SDX device " + _ip + + " as there are no admin profile to use for creating VPX.")); + } + String profileName = profiles[0].get_name(); + ns_obj.set_nsroot_profile(profileName); + + // use the first VPX image of the available VPX images on the SDX to create an instance of VPX + // TODO: should enable the option to choose the template while adding the SDX device in to CloudStack + xen_vpx_image[] vpxImages = xen_vpx_image.get(_netscalerSdxService); + if (!(vpxImages != null && vpxImages.length >= 1)) { + new Answer(cmd, new ExecutionException("Failed to create VPX instance on the netscaler SDX device " + _ip + + " as there are no VPX images on SDX to use for creating VPX.")); + } + String imageName = vpxImages[0].get_file_name(); + ns_obj.set_image_name(imageName); String publicIf = _publicInterface; String privateIf = _privateInterface; From 486d962f09005c04c571ec04b0be250bcfbb9483 Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Wed, 2 May 2012 13:14:47 +0100 Subject: [PATCH 16/16] CS-14724 : Making the default network label configurable, improving exception management Please also see notes added to wiki.cloudstack.org/display/QA/Open+vSwitch+Tunnel+Manager --- .../xen/resource/CitrixResourceBase.java | 15 +++++--- .../src/com/cloud/configuration/Config.java | 3 +- .../network/ovs/OvsTunnelManagerImpl.java | 36 +++++++++++++------ setup/db/db/schema-302to303.sql | 3 +- wscript | 2 +- 5 files changed, 41 insertions(+), 18 deletions(-) diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 0f193340274..b7cce8d6acb 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -4945,22 +4945,23 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe private OvsFetchInterfaceAnswer execute(OvsFetchInterfaceCommand cmd) { String label = cmd.getLabel(); - s_logger.debug("### Will look for network with name-label:" + label + " on host " + _host.ip); + s_logger.debug("Will look for network with name-label:" + label + " on host " + _host.ip); Connection conn = getConnection(); try { XsLocalNetwork nw = this.getNetworkByName(conn, label); - s_logger.debug("### Network object:" + nw.getNetwork().getUuid(conn)); + s_logger.debug("Network object:" + nw.getNetwork().getUuid(conn)); PIF pif = nw.getPif(conn); Record pifRec = pif.getRecord(conn); - s_logger.debug("### PIF object:" + pifRec.uuid + "(" + pifRec.device + ")"); + s_logger.debug("PIF object:" + pifRec.uuid + "(" + pifRec.device + ")"); return new OvsFetchInterfaceAnswer(cmd, true, "Interface " + pifRec.device + " retrieved successfully", pifRec.IP, pifRec.netmask, pifRec.MAC); } catch (Exception e) { e.printStackTrace(); + s_logger.error("An error occurred while fetching the interface for " + + label + " on host " + _host.ip + ":" + e.toString() + + "(" + e.getClass() + ")"); return new OvsFetchInterfaceAnswer(cmd, false, "EXCEPTION:" + e.getMessage()); } - - } @@ -4985,6 +4986,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } catch (Exception e) { e.printStackTrace(); + s_logger.error("An error occurred while creating a GRE tunnel to " + + cmd.getRemoteIp() + " on host " + _host.ip + ":" + e.getMessage() + + "(" + e.getClass() + ")"); + } return new OvsCreateGreTunnelAnswer(cmd, false, "EXCEPTION", _host.ip, bridge); diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 0b4f7dd4238..94b106ac83f 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -88,7 +88,8 @@ public enum Config { NetworkThrottlingRate("Network", ManagementServer.class, Integer.class, "network.throttling.rate", "200", "Default data transfer rate in megabits per second allowed in network.", null), GuestDomainSuffix("Network", AgentManager.class, String.class, "guest.domain.suffix", "cloud.internal", "Default domain name for vms inside virtualized networks fronted by router", null), DirectNetworkNoDefaultRoute("Network", ManagementServer.class, Boolean.class, "direct.network.no.default.route", "false", "Direct Network Dhcp Server should not send a default route", "true/false"), - OvsTunnelNetwork("Network", ManagementServer.class, Boolean.class, "sdn.ovs.controller", "false", "enable/disable open vswitch tunnel network(no vlan)", null), + OvsTunnelNetwork("Network", ManagementServer.class, Boolean.class, "sdn.ovs.controller", "false", "Enable/Disable Open vSwitch SDN controller for L2-in-L3 overlay networks", null), + OvsTunnelNetworkDefaultLabel("Network", ManagementServer.class, String.class, "sdn.ovs.controller.default.label", "cloud-public", "Default network label to be used when fetching interface for GRE endpoints", null), VmNetworkThrottlingRate("Network", ManagementServer.class, Integer.class, "vm.network.throttling.rate", "200", "Default data transfer rate in megabits per second allowed in User vm's default network.", null), NetworkLockTimeout("Network", ManagementServer.class, Integer.class, "network.lock.timeout", "600", "Lock wait timeout (seconds) while implementing network", null), diff --git a/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java b/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java index 75276b590a9..1081b9e9bfb 100644 --- a/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java +++ b/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java @@ -138,10 +138,19 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager { private String handleFetchInterfaceAnswer(Answer[] answers, Long hostId){ OvsFetchInterfaceAnswer ans = (OvsFetchInterfaceAnswer) answers[0]; - OvsTunnelInterfaceVO ti = - createInterfaceRecord(ans.getIp(), ans.getNetmask(), - ans.getMac(), hostId, ans.getLabel()); - return ti.getIp(); + if (ans.getResult()) { + if (ans.getIp() != null && + !("".equals(ans.getIp()))) { + OvsTunnelInterfaceVO ti = + createInterfaceRecord(ans.getIp(), ans.getNetmask(), + ans.getMac(), hostId, ans.getLabel()); + return ti.getIp(); + } + } + // Fetch interface failed! + s_logger.warn("Unable to fetch the IP address for the GRE tunnel endpoint" + + ans.getDetails()); + return null; } private void handleCreateTunnelAnswer(Answer[] answers){ @@ -177,10 +186,8 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager { private String getGreEndpointIP(Host host, Network nw) throws AgentUnavailableException, OperationTimedoutException { String endpointIp = null; - // Fetch physical network and associated tags - // If no tag specified, look for this network - // Default name for network label - String physNetLabel = "cloud-public"; + // Fetch fefault name for network label from configuration + String physNetLabel = _configDao.getValue(Config.OvsTunnelNetworkDefaultLabel.key()); Long physNetId = nw.getPhysicalNetworkId(); PhysicalNetworkTrafficType physNetTT = _physNetTTDao.findBy(physNetId, TrafficType.Guest); @@ -313,13 +320,21 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager { } } } - //FIXME: Why are we cancelling the exception here? + //TODO: Should we propagate the exception here? try { String myIp = getGreEndpointIP(dest.getHost(), nw); + if (myIp == null) + throw new GreTunnelException("Unable to retrieve the source " + + "endpoint for the GRE tunnel." + + "Failure is on host:" + dest.getHost().getId()); boolean noHost = true; for (Long i : toHostIds) { HostVO rHost = _hostDao.findById(i); String otherIp = getGreEndpointIP(rHost, nw); + if (otherIp == null) + throw new GreTunnelException("Unable to retrieve the remote " + + "endpoint for the GRE tunnel." + + "Failure is on host:" + rHost.getId()); Commands cmds = new Commands( new OvsCreateTunnelCommand(otherIp, key, Long.valueOf(hostId), i, nw.getId(), myIp)); @@ -354,7 +369,8 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager { handleSetupBridgeAnswer(answers); } } catch (Exception e) { - s_logger.debug("Ovs Tunnel network created tunnel failed", e); + // I really thing we should do a better handling of these exceptions + s_logger.warn("Ovs Tunnel network created tunnel failed", e); } } diff --git a/setup/db/db/schema-302to303.sql b/setup/db/db/schema-302to303.sql index 2fd4c53159a..ce29b627932 100755 --- a/setup/db/db/schema-302to303.sql +++ b/setup/db/db/schema-302to303.sql @@ -24,7 +24,8 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'manag INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'secstorage.service.offering', NULL, 'Service offering used by secondary storage; if NULL - system offering will be used'); -INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Network', 'DEFAULT', 'management-server', 'sdn.ovs.controller', NULL, 'Enabled Open vSwitch SDN controller for L2-in-L3 overlay networks'); +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Network', 'DEFAULT', 'management-server', 'sdn.ovs.controller', NULL, 'Enable/Disable Open vSwitch SDN controller for L2-in-L3 overlay networks'); +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Network', 'DEFAULT', 'management-server', 'sdn.ovs.controller.default.label', NULL, 'Default network label to be used when fetching interface for GRE endpoints'); ALTER TABLE `cloud`.`user_vm` ADD COLUMN `update_parameters` tinyint(1) NOT NULL DEFAULT 1 COMMENT 'Defines if the parameters need to be set for the vm'; UPDATE `cloud`.`user_vm` SET update_parameters=0 where id>0; diff --git a/wscript b/wscript index edabbdaf1ff..31f29178846 100644 --- a/wscript +++ b/wscript @@ -3,7 +3,7 @@ # the following two variables are used by the target "waf dist" # if you change 'em here, you need to change it also in cloud.spec, add a %changelog entry there, and add an entry in debian/changelog -VERSION = '3.0.3.2012-05-02T00:07:57Z' +VERSION = '3.0.3' APPNAME = 'cloud' import shutil,os