diff --git a/agent/conf/agent.properties b/agent/conf/agent.properties
index e49afbf2aaf..7dc4ba8a18c 100644
--- a/agent/conf/agent.properties
+++ b/agent/conf/agent.properties
@@ -78,7 +78,7 @@ domr.scripts.dir=scripts/network/domr/kvm
# a sensible default will be selected based on the network.bridge.type but can
# be overridden here.
# native = com.cloud.hypervisor.kvm.resource.BridgeVifDriver
-# openvswitch = com.cloud.hypervisor.kvm.resource.OvsBridgeDriver
+# openvswitch = com.cloud.hypervisor.kvm.resource.OvsVifDriver
#libvirt.vif.driver=com.cloud.hypervisor.kvm.resource.BridgeVifDriver
# set the hypervisor type, values are: kvm, lxc
diff --git a/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java b/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java
index d2b26c0ac8f..9fbc9401532 100644
--- a/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/admin/router/ListRoutersCmd.java
@@ -64,6 +64,9 @@ public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd {
description="the Zone ID of the router")
private Long zoneId;
+ @Parameter(name=ApiConstants.ZONE_TYPE, type=CommandType.STRING, description="the network type of the zone that the virtual machine belongs to")
+ private String zoneType;
+
@Parameter(name=ApiConstants.NETWORK_ID, type=CommandType.UUID, entityType=NetworkResponse.class,
description="list by network id")
private Long networkId;
@@ -103,6 +106,10 @@ public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd {
return zoneId;
}
+ public String getZoneType() {
+ return zoneType;
+ }
+
public Long getNetworkId() {
return networkId;
}
diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java
index 17f20aeb0d0..d7e6bc87b7f 100644
--- a/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/ListSnapshotsCmd.java
@@ -58,6 +58,9 @@ public class ListSnapshotsCmd extends BaseListTaggedResourcesCmd {
@Parameter(name=ApiConstants.VOLUME_ID, type=CommandType.UUID, entityType = VolumeResponse.class,
description="the ID of the disk volume")
private Long volumeId;
+
+ @Parameter(name=ApiConstants.ZONE_TYPE, type=CommandType.STRING, description="the network type of the zone that the virtual machine belongs to")
+ private String zoneType;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
@@ -83,6 +86,10 @@ public class ListSnapshotsCmd extends BaseListTaggedResourcesCmd {
return volumeId;
}
+ public String getZoneType() {
+ return zoneType;
+ }
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
diff --git a/client/pom.xml b/client/pom.xml
index 743cd363005..a7c7009ffc2 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -450,16 +450,15 @@
- test
-
-
-
-
-
+
+
+
+
+
diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in
index d2ea380ddab..1f5ab20333a 100644
--- a/client/tomcatconf/applicationContext.xml.in
+++ b/client/tomcatconf/applicationContext.xml.in
@@ -532,10 +532,14 @@
-->
+
+
+
+
diff --git a/core/src/com/cloud/async/AsyncJobVO.java b/core/src/com/cloud/async/AsyncJobVO.java
index ad482b03a9d..c40fc987a4a 100644
--- a/core/src/com/cloud/async/AsyncJobVO.java
+++ b/core/src/com/cloud/async/AsyncJobVO.java
@@ -133,6 +133,7 @@ public class AsyncJobVO implements AsyncJob {
this.callbackType = CALLBACK_POLLING;
this.uuid = UUID.randomUUID().toString();
this.instanceId = instanceId;
+ this.instanceType = instanceType;
}
public AsyncJobVO(long userId, long accountId, String cmd, String cmdInfo,
diff --git a/docs/en-US/added-API-commands-4.2.xml b/docs/en-US/added-API-commands-4.2.xml
index 4bec148ba96..34716240657 100644
--- a/docs/en-US/added-API-commands-4.2.xml
+++ b/docs/en-US/added-API-commands-4.2.xml
@@ -39,5 +39,29 @@
The response parameters are: id, ipaddress, secondaryips, gateway, netmask, macaddr,
broadcasturi, isolationuri, isdefault,
+
+ deleteAlerts
+ Deletes the specified alerts. The request parameters are: ids (allowed to pass one or
+ more IDs separated by comma); type (string); olderthan (yyyy-mm-dd format).
+ The response parameters are: true, false
+
+
+ archiveAlerts
+ Archives the specified alerts. The request parameters are: ids (allowed to pass one or
+ more IDs separated by comma); type (string); olderthan (yyyy-mm-dd format).
+ The response parameters are: true, false
+
+
+ deleteEvents
+ Deletes the specified events. The request parameters are: ids (allowed to pass one or
+ more IDs separated by comma); type (string); olderthan (yyyy-mm-dd format).
+ The response parameters are: true, false
+
+
+ archiveEvents
+ Archives the specified events. The request parameters are: ids (allowed to pass one or
+ more IDs separated by comma); type (string); olderthan (yyyy-mm-dd format).
+ The response parameters are: true, false
+
diff --git a/docs/en-US/delete-event-alerts.xml b/docs/en-US/delete-event-alerts.xml
index 3eebcb727a0..ef39040c102 100644
--- a/docs/en-US/delete-event-alerts.xml
+++ b/docs/en-US/delete-event-alerts.xml
@@ -28,6 +28,18 @@
or by using the Details page. If you want to delete multiple alerts or events at the same time,
you can use the respective context menu. You can delete alerts or events by category for a time
period.
+ In order to support the delete or archive alerts, the following global parameters have been
+ added:
+
+
+ alert.purge.delay: The alerts older than specified
+ number of days are purged. Set the value to 0 to never purge alerts automatically.
+
+
+ alert.purge.interval: The interval in seconds to wait
+ before running the alert purge thread. The default is 86400 seconds (one day).
+
+
Archived alerts or events cannot be viewed in the UI, or by using the API. They are
maintained in the database for auditing or compliance purposes.
diff --git a/docs/en-US/events.xml b/docs/en-US/events.xml
index 4a1445873a4..3b93ee0451e 100644
--- a/docs/en-US/events.xml
+++ b/docs/en-US/events.xml
@@ -25,7 +25,7 @@
physical resources associated with a cloud environment. Events are used by monitoring systems,
usage and billing systems, or any other event-driven workflow systems to discern a pattern and
make the right business decision. In &PRODUCT; an event could be a state change of virtual or
- psychical resources, an action performed by an user (action events), or policy based events
+ physical resources, an action performed by an user (action events), or policy based events
(alerts).
diff --git a/docs/en-US/images/eip-ns-basiczone.png b/docs/en-US/images/eip-ns-basiczone.png
new file mode 100644
index 00000000000..315ff55dab9
Binary files /dev/null and b/docs/en-US/images/eip-ns-basiczone.png differ
diff --git a/packaging/centos63/package.sh b/packaging/centos63/package.sh
index faa089b73fa..c466f588776 100755
--- a/packaging/centos63/package.sh
+++ b/packaging/centos63/package.sh
@@ -44,7 +44,7 @@ if echo $VERSION | grep SNAPSHOT ; then
else
DEFVER="-D_ver $REALVER"
DEFPRE=
- DEFREL=
+ DEFREL="-D_rel 1"
fi
mkdir -p $RPMDIR/SPECS
@@ -78,7 +78,7 @@ else
REALVER=`echo $VERSION`
DEFVER="-D_ver $REALVER"
DEFPRE=
- DEFREL=
+ DEFREL="-D_rel 1"
fi
mkdir -p $RPMDIR/SPECS
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 187ae25c40c..6ffd648faeb 100755
--- a/patches/systemvm/debian/config/etc/init.d/cloud-early-config
+++ b/patches/systemvm/debian/config/etc/init.d/cloud-early-config
@@ -520,6 +520,7 @@ setup_sshd(){
local eth=$2
[ -f /etc/ssh/sshd_config ] && sed -i -e "s/^[#]*ListenAddress.*$/ListenAddress $ip/" /etc/ssh/sshd_config
sed -i "/3922/s/eth./$eth/" /etc/iptables/rules.v4
+ sed -i "/3922/s/eth./$eth/" /etc/iptables/rules
}
@@ -692,6 +693,8 @@ setup_router() {
enable_fwding 1
chkconfig nfs-common off
cp /etc/iptables/iptables-router /etc/iptables/rules.v4
+#for old templates
+ cp /etc/iptables/iptables-router /etc/iptables/rules
setup_sshd $ETH1_IP "eth1"
}
@@ -764,6 +767,7 @@ EOF
disable_rpfilter
enable_fwding 1
cp /etc/iptables/iptables-vpcrouter /etc/iptables/rules.v4
+ cp /etc/iptables/iptables-vpcrouter /etc/iptables/rules
setup_sshd $ETH0_IP "eth0"
cp /etc/vpcdnsmasq.conf /etc/dnsmasq.conf
cp /etc/cloud-nic.rules /etc/udev/rules.d/cloud-nic.rules
@@ -790,6 +794,7 @@ setup_dhcpsrvr() {
enable_fwding 0
chkconfig nfs-common off
cp /etc/iptables/iptables-router /etc/iptables/rules.v4
+ cp /etc/iptables/iptables-router /etc/iptables/rules
if [ "$SSHONGUEST" == "true" ]
then
setup_sshd $ETH0_IP "eth0"
@@ -825,6 +830,7 @@ setup_secstorage() {
echo "$public_ip $NAME" >> /etc/hosts
cp /etc/iptables/iptables-secstorage /etc/iptables/rules.v4
+ cp /etc/iptables/iptables-secstorage /etc/iptables/rules
if [ "$hyp" == "vmware" ]; then
setup_sshd $ETH1_IP "eth1"
else
@@ -849,6 +855,7 @@ setup_console_proxy() {
sed -i /gateway/d /etc/hosts
echo "$public_ip $NAME" >> /etc/hosts
cp /etc/iptables/iptables-consoleproxy /etc/iptables/rules.v4
+ cp /etc/iptables/iptables-consoleproxy /etc/iptables/rules
if [ "$hyp" == "vmware" ]; then
setup_sshd $ETH1_IP "eth1"
else
@@ -874,6 +881,7 @@ setup_elbvm() {
echo "$public_ip $NAME" >> /etc/hosts
cp /etc/iptables/iptables-elbvm /etc/iptables/rules.v4
+ cp /etc/iptables/iptables-elbvm /etc/iptables/rules
if [ "$SSHONGUEST" == "true" ]
then
setup_sshd $ETH0_IP "eth0"
diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java
index 67af7e4b684..2c003d31679 100644
--- a/server/src/com/cloud/api/query/QueryManagerImpl.java
+++ b/server/src/com/cloud/api/query/QueryManagerImpl.java
@@ -994,7 +994,8 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
Long id = cmd.getId();
String name = cmd.getRouterName();
String state = cmd.getState();
- Long zone = cmd.getZoneId();
+ Long zoneId = cmd.getZoneId();
+ String zoneType = cmd.getZoneType();
Long pod = cmd.getPodId();
Long hostId = cmd.getHostId();
String keyword = cmd.getKeyword();
@@ -1027,6 +1028,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.IN);
sb.and("state", sb.entity().getState(), SearchCriteria.Op.EQ);
sb.and("dataCenterId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
+ sb.and("dataCenterType", sb.entity().getDataCenterType(), SearchCriteria.Op.EQ);
sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ);
sb.and("hostId", sb.entity().getHostId(), SearchCriteria.Op.EQ);
sb.and("vpcId", sb.entity().getVpcId(), SearchCriteria.Op.EQ);
@@ -1067,10 +1069,14 @@ public class QueryManagerImpl extends ManagerBase implements QueryService {
sc.setParameters("state", state);
}
- if (zone != null) {
- sc.setParameters("dataCenterId", zone);
+ if (zoneId != null) {
+ sc.setParameters("dataCenterId", zoneId);
}
+ if (zoneType != null) {
+ sc.setParameters("dataCenterType", zoneType);
+ }
+
if (pod != null) {
sc.setParameters("podId", pod);
}
diff --git a/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java
index 796ae54d52f..528bdacffda 100644
--- a/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java
@@ -203,8 +203,10 @@ public class AccountJoinDaoImpl extends GenericDaoBase impl
accountResponse.setObjectName("account");
// set async job
- accountResponse.setJobId(account.getJobUuid());
- accountResponse.setJobStatus(account.getJobStatus());
+ if (account.getJobId() != null) {
+ accountResponse.setJobId(account.getJobUuid());
+ accountResponse.setJobStatus(account.getJobStatus());
+ }
return accountResponse;
}
diff --git a/server/src/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java
index 25cd62faf7b..125db17c760 100644
--- a/server/src/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/DomainRouterJoinDaoImpl.java
@@ -158,8 +158,10 @@ public class DomainRouterJoinDaoImpl extends GenericDaoBase implements
hostResponse.setResourceState(host.getResourceState().toString());
// set async job
- hostResponse.setJobId(host.getJobUuid());
- hostResponse.setJobStatus(host.getJobStatus());
+ if (host.getJobId() != null) {
+ hostResponse.setJobId(host.getJobUuid());
+ hostResponse.setJobStatus(host.getJobStatus());
+ }
hostResponse.setObjectName("host");
diff --git a/server/src/com/cloud/api/query/dao/SecurityGroupJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/SecurityGroupJoinDaoImpl.java
index 3e579c179e2..2a6afca231e 100644
--- a/server/src/com/cloud/api/query/dao/SecurityGroupJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/SecurityGroupJoinDaoImpl.java
@@ -117,8 +117,10 @@ public class SecurityGroupJoinDaoImpl extends GenericDaoBase implem
}
}
userVmResponse.setPassword(userVm.getPassword());
- userVmResponse.setJobId(userVm.getJobUuid());
- userVmResponse.setJobStatus(userVm.getJobStatus());
+ if (userVm.getJobId() != null) {
+ userVmResponse.setJobId(userVm.getJobUuid());
+ userVmResponse.setJobStatus(userVm.getJobStatus());
+ }
//userVmResponse.setForVirtualNetwork(userVm.getForVirtualNetwork());
userVmResponse.setPublicIpId(userVm.getPublicIpUuid());
diff --git a/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java
index a7a0bf0b435..a09c4a0c09b 100644
--- a/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java
+++ b/server/src/com/cloud/api/query/dao/VolumeJoinDaoImpl.java
@@ -197,8 +197,10 @@ public class VolumeJoinDaoImpl extends GenericDaoBase implem
volResponse.setExtractable(isExtractable);
// set async job
- volResponse.setJobId(volume.getJobUuid());
- volResponse.setJobStatus(volume.getJobStatus());
+ if (volume.getJobId() != null) {
+ volResponse.setJobId(volume.getJobUuid());
+ volResponse.setJobStatus(volume.getJobStatus());
+ }
volResponse.setObjectName("volume");
return volResponse;
diff --git a/server/src/com/cloud/api/query/vo/AccountJoinVO.java b/server/src/com/cloud/api/query/vo/AccountJoinVO.java
index 800da7803fd..fbcc9342b22 100644
--- a/server/src/com/cloud/api/query/vo/AccountJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/AccountJoinVO.java
@@ -177,7 +177,7 @@ public class AccountJoinVO extends BaseViewVO implements InternalIdentity, Ident
private Long secondaryStorageTotal;
@Column(name="job_id")
- private long jobId;
+ private Long jobId;
@Column(name="job_uuid")
private String jobUuid;
@@ -645,12 +645,12 @@ public class AccountJoinVO extends BaseViewVO implements InternalIdentity, Ident
}
- public long getJobId() {
+ public Long getJobId() {
return jobId;
}
- public void setJobId(long jobId) {
+ public void setJobId(Long jobId) {
this.jobId = jobId;
}
diff --git a/server/src/com/cloud/api/query/vo/DomainRouterJoinVO.java b/server/src/com/cloud/api/query/vo/DomainRouterJoinVO.java
index 5f2b500fa57..83e15477287 100644
--- a/server/src/com/cloud/api/query/vo/DomainRouterJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/DomainRouterJoinVO.java
@@ -210,7 +210,7 @@ public class DomainRouterJoinVO extends BaseViewVO implements ControlledViewEnti
private String projectName;
@Column(name="job_id")
- private long jobId;
+ private Long jobId;
@Column(name="job_uuid")
private String jobUuid;
@@ -781,14 +781,14 @@ public class DomainRouterJoinVO extends BaseViewVO implements ControlledViewEnti
}
- public long getJobId() {
+ public Long getJobId() {
return jobId;
}
- public void setJobId(long jobId) {
+ public void setJobId(Long jobId) {
this.jobId = jobId;
}
diff --git a/server/src/com/cloud/api/query/vo/HostJoinVO.java b/server/src/com/cloud/api/query/vo/HostJoinVO.java
index 4aa45e5f593..4b70cfcaa10 100644
--- a/server/src/com/cloud/api/query/vo/HostJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/HostJoinVO.java
@@ -168,7 +168,7 @@ public class HostJoinVO extends BaseViewVO implements InternalIdentity, Identity
private long cpuReservedCapacity;
@Column(name="job_id")
- private long jobId;
+ private Long jobId;
@Column(name="job_uuid")
private String jobUuid;
@@ -427,11 +427,11 @@ public class HostJoinVO extends BaseViewVO implements InternalIdentity, Identity
this.osCategoryName = osCategoryName;
}
- public long getJobId() {
+ public Long getJobId() {
return jobId;
}
- public void setJobId(long jobId) {
+ public void setJobId(Long jobId) {
this.jobId = jobId;
}
diff --git a/server/src/com/cloud/api/query/vo/SecurityGroupJoinVO.java b/server/src/com/cloud/api/query/vo/SecurityGroupJoinVO.java
index 922e130ed30..258b6136224 100644
--- a/server/src/com/cloud/api/query/vo/SecurityGroupJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/SecurityGroupJoinVO.java
@@ -77,7 +77,7 @@ public class SecurityGroupJoinVO extends BaseViewVO implements ControlledViewEnt
private String projectName;
@Column(name="job_id")
- private long jobId;
+ private Long jobId;
@Column(name="job_uuid")
private String jobUuid;
@@ -269,11 +269,11 @@ public class SecurityGroupJoinVO extends BaseViewVO implements ControlledViewEnt
this.projectName = projectName;
}
- public long getJobId() {
+ public Long getJobId() {
return jobId;
}
- public void setJobId(long jobId) {
+ public void setJobId(Long jobId) {
this.jobId = jobId;
}
diff --git a/server/src/com/cloud/api/query/vo/StoragePoolJoinVO.java b/server/src/com/cloud/api/query/vo/StoragePoolJoinVO.java
index da06227ea66..d86726c3523 100644
--- a/server/src/com/cloud/api/query/vo/StoragePoolJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/StoragePoolJoinVO.java
@@ -121,7 +121,7 @@ public class StoragePoolJoinVO extends BaseViewVO implements InternalIdentity, I
@Column(name="job_id")
- private long jobId;
+ private Long jobId;
@Column(name="job_uuid")
private String jobUuid;
@@ -342,11 +342,11 @@ public class StoragePoolJoinVO extends BaseViewVO implements InternalIdentity, I
this.reservedCapacity = reservedCapacity;
}
- public long getJobId() {
+ public Long getJobId() {
return jobId;
}
- public void setJobId(long jobId) {
+ public void setJobId(Long jobId) {
this.jobId = jobId;
}
diff --git a/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java b/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java
index d85392fb85a..c44027b8bc0 100644
--- a/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java
@@ -109,7 +109,7 @@ public class UserAccountJoinVO extends BaseViewVO implements InternalIdentity, I
private String domainPath = null;
@Column(name="job_id")
- private long jobId;
+ private Long jobId;
@Column(name="job_uuid")
private String jobUuid;
@@ -324,11 +324,11 @@ public class UserAccountJoinVO extends BaseViewVO implements InternalIdentity, I
this.loginAttempts = loginAttempts;
}
- public long getJobId() {
+ public Long getJobId() {
return jobId;
}
- public void setJobId(long jobId) {
+ public void setJobId(Long jobId) {
this.jobId = jobId;
}
diff --git a/server/src/com/cloud/api/query/vo/UserVmJoinVO.java b/server/src/com/cloud/api/query/vo/UserVmJoinVO.java
index a50906d9e3d..d7b516c312f 100644
--- a/server/src/com/cloud/api/query/vo/UserVmJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/UserVmJoinVO.java
@@ -332,7 +332,7 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity {
private String keypairName;
@Column(name="job_id")
- private long jobId;
+ private Long jobId;
@Column(name="job_uuid")
private String jobUuid;
@@ -1608,14 +1608,14 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity {
- public long getJobId() {
+ public Long getJobId() {
return jobId;
}
- public void setJobId(long jobId) {
+ public void setJobId(Long jobId) {
this.jobId = jobId;
}
diff --git a/server/src/com/cloud/api/query/vo/VolumeJoinVO.java b/server/src/com/cloud/api/query/vo/VolumeJoinVO.java
index 8a4bfe5c0fa..2d7b1d5bb49 100644
--- a/server/src/com/cloud/api/query/vo/VolumeJoinVO.java
+++ b/server/src/com/cloud/api/query/vo/VolumeJoinVO.java
@@ -206,7 +206,7 @@ public class VolumeJoinVO extends BaseViewVO implements ControlledViewEntity {
private Storage.TemplateType templateType;
@Column(name="job_id")
- private long jobId;
+ private Long jobId;
@Column(name="job_uuid")
private String jobUuid;
@@ -817,13 +817,13 @@ public class VolumeJoinVO extends BaseViewVO implements ControlledViewEntity {
- public long getJobId() {
+ public Long getJobId() {
return jobId;
}
- public void setJobId(long jobId) {
+ public void setJobId(Long jobId) {
this.jobId = jobId;
}
diff --git a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java
index 080f7b0edf6..4ad8868b86a 100644
--- a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java
+++ b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java
@@ -27,6 +27,7 @@ import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
+import com.cloud.network.dao.*;
import org.apache.cloudstack.api.command.user.firewall.ListFirewallRulesCmd;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
@@ -56,10 +57,6 @@ import com.cloud.network.Networks.TrafficType;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkModel;
import com.cloud.network.NetworkRuleApplier;
-import com.cloud.network.dao.FirewallRulesCidrsDao;
-import com.cloud.network.dao.FirewallRulesDao;
-import com.cloud.network.dao.IPAddressDao;
-import com.cloud.network.dao.IPAddressVO;
import com.cloud.network.element.FirewallServiceProvider;
import com.cloud.network.element.NetworkACLServiceProvider;
import com.cloud.network.element.PortForwardingServiceProvider;
@@ -127,6 +124,8 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
@Inject
ResourceTagDao _resourceTagDao;
@Inject
+ NetworkDao _networkDao;
+ @Inject
VpcManager _vpcMgr;
@Inject List _firewallElements;
@@ -150,6 +149,11 @@ public class FirewallManagerImpl extends ManagerBase implements FirewallService,
@Override
public FirewallRule createEgressFirewallRule(FirewallRule rule) throws NetworkRuleConflictException {
Account caller = UserContext.current().getCaller();
+
+ Network network = _networkDao.findById(rule.getNetworkId());
+ if (network.getGuestType() == Network.GuestType.Shared) {
+ throw new InvalidParameterValueException("Egress firewall rules are not supported for " + network.getGuestType() + " networks");
+ }
return createFirewallRule(null, caller, rule.getXid(), rule.getSourcePortStart(),
rule.getSourcePortEnd(), rule.getProtocol(), rule.getSourceCidrList(), rule.getIcmpCode(),
diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
index 490948ba5ae..7dafe4ac865 100755
--- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
+++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java
@@ -58,6 +58,7 @@ import com.cloud.configuration.Resource.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenter;
+import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.domain.dao.DomainDao;
@@ -571,6 +572,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
String keyword = cmd.getKeyword();
String snapshotTypeStr = cmd.getSnapshotType();
String intervalTypeStr = cmd.getIntervalType();
+ String zoneType = cmd.getZoneType();
Map tags = cmd.getTags();
Account caller = UserContext.current().getCaller();
@@ -602,17 +604,23 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
sb.and("snapshotTypeNEQ", sb.entity().getsnapshotType(), SearchCriteria.Op.NEQ);
if (tags != null && !tags.isEmpty()) {
- SearchBuilder tagSearch = _resourceTagDao.createSearchBuilder();
- for (int count=0; count < tags.size(); count++) {
- tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ);
- tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ);
- tagSearch.cp();
+ SearchBuilder tagSearch = _resourceTagDao.createSearchBuilder();
+ for (int count=0; count < tags.size(); count++) {
+ tagSearch.or().op("key" + String.valueOf(count), tagSearch.entity().getKey(), SearchCriteria.Op.EQ);
+ tagSearch.and("value" + String.valueOf(count), tagSearch.entity().getValue(), SearchCriteria.Op.EQ);
+ tagSearch.cp();
+ }
+ tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
+ sb.groupBy(sb.entity().getId());
+ sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER);
}
- tagSearch.and("resourceType", tagSearch.entity().getResourceType(), SearchCriteria.Op.EQ);
- sb.groupBy(sb.entity().getId());
- sb.join("tagSearch", tagSearch, sb.entity().getId(), tagSearch.entity().getResourceId(), JoinBuilder.JoinType.INNER);
- }
+ if(zoneType != null) {
+ SearchBuilder zoneSb = _dcDao.createSearchBuilder();
+ zoneSb.and("zoneNetworkType", zoneSb.entity().getNetworkType(), SearchCriteria.Op.EQ);
+ sb.join("zoneSb", zoneSb, sb.entity().getDataCenterId(), zoneSb.entity().getId(), JoinBuilder.JoinType.INNER);
+ }
+
SearchCriteria sc = sb.create();
_accountMgr.buildACLSearchCriteria(sc, domainId, isRecursive, permittedAccounts, listProjectResourcesCriteria);
@@ -630,6 +638,10 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager,
}
}
+ if(zoneType != null) {
+ sc.setJoinParameters("zoneSb", "zoneNetworkType", zoneType);
+ }
+
if (name != null) {
sc.setParameters("name", "%" + name + "%");
}
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java
index ebc5757770e..f58d6be5b2f 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -2902,10 +2902,15 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
}
UserVO user = _userDao.findById(userId);
-
+ boolean status = false;
try {
VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
- vmEntity.stop(new Long(userId).toString());
+ status = vmEntity.stop(new Long(userId).toString());
+ if (status) {
+ return _vmDao.findById(vmId);
+ } else {
+ return null;
+ }
} catch (ResourceUnavailableException e) {
throw new CloudRuntimeException(
"Unable to contact the agent to stop the virtual machine "
@@ -2915,8 +2920,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
"Unable to contact the agent to stop the virtual machine "
+ vm, e);
}
-
- return _vmDao.findById(vmId);
}
@Override
diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
index 252fc99ca0d..b0d6378e9e5 100755
--- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
+++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java
@@ -1136,7 +1136,9 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
vmGuru.finalizeStop(profile, answer);
} catch (AgentUnavailableException e) {
+ s_logger.warn("Unable to stop vm, agent unavailable: " + e.toString());
} catch (OperationTimedoutException e) {
+ s_logger.warn("Unable to stop vm, operation timed out: " + e.toString());
} finally {
if (!stopped) {
if (!forced) {
diff --git a/tools/marvin/marvin/asyncJobMgr.py b/tools/marvin/marvin/asyncJobMgr.py
index 40304fa4141..698462783bd 100644
--- a/tools/marvin/marvin/asyncJobMgr.py
+++ b/tools/marvin/marvin/asyncJobMgr.py
@@ -28,6 +28,8 @@ class job(object):
def __init__(self):
self.id = None
self.cmd = None
+
+
class jobStatus(object):
def __init__(self):
self.result = None
@@ -37,8 +39,11 @@ class jobStatus(object):
self.duration = None
self.jobId = None
self.responsecls = None
+
def __str__(self):
return '{%s}' % str(', '.join('%s : %s' % (k, repr(v)) for (k, v) in self.__dict__.iteritems()))
+
+
class workThread(threading.Thread):
def __init__(self, in_queue, outqueue, apiClient, db=None, lock=None):
threading.Thread.__init__(self)
@@ -47,11 +52,11 @@ class workThread(threading.Thread):
self.connection = apiClient.connection.__copy__()
self.db = None
self.lock = lock
-
+
def queryAsynJob(self, job):
if job.jobId is None:
return job
-
+
try:
self.lock.acquire()
result = self.connection.poll(job.jobId, job.responsecls).jobresult
@@ -59,10 +64,10 @@ class workThread(threading.Thread):
result = str(e)
finally:
self.lock.release()
-
+
job.result = result
return job
-
+
def executeCmd(self, job):
cmd = job.cmd
@@ -70,14 +75,15 @@ class workThread(threading.Thread):
jobId = None
try:
self.lock.acquire()
-
+
if cmd.isAsync == "false":
jobstatus.startTime = datetime.datetime.now()
-
+
result = self.connection.make_request(cmd)
jobstatus.result = result
jobstatus.endTime = datetime.datetime.now()
- jobstatus.duration = time.mktime(jobstatus.endTime.timetuple()) - time.mktime(jobstatus.startTime.timetuple())
+ jobstatus.duration = time.mktime(jobstatus.endTime.timetuple()) - time.mktime(
+ jobstatus.startTime.timetuple())
else:
result = self.connection.make_request(cmd, None, True)
if result is None:
@@ -99,9 +105,9 @@ class workThread(threading.Thread):
jobstatus.result = sys.exc_info()
finally:
self.lock.release()
-
+
return jobstatus
-
+
def run(self):
while self.inqueue.qsize() > 0:
job = self.inqueue.get()
@@ -109,18 +115,20 @@ class workThread(threading.Thread):
jobstatus = self.queryAsynJob(job)
else:
jobstatus = self.executeCmd(job)
-
+
self.output.put(jobstatus)
self.inqueue.task_done()
-
+
'''release the resource'''
self.connection.close()
+
class jobThread(threading.Thread):
def __init__(self, inqueue, interval):
threading.Thread.__init__(self)
self.inqueue = inqueue
self.interval = interval
+
def run(self):
while self.inqueue.qsize() > 0:
job = self.inqueue.get()
@@ -130,23 +138,25 @@ class jobThread(threading.Thread):
job.apiClient.connection.close()
except:
pass
-
+
self.inqueue.task_done()
time.sleep(self.interval)
-
+
+
class outputDict(object):
def __init__(self):
self.lock = threading.Condition()
- self.dict = {}
+ self.dict = {}
+
class asyncJobMgr(object):
def __init__(self, apiClient, db):
self.inqueue = Queue.Queue()
- self.output = outputDict()
+ self.output = outputDict()
self.outqueue = Queue.Queue()
self.apiClient = apiClient
self.db = db
-
+
def submitCmds(self, cmds):
if not self.inqueue.empty():
return False
@@ -160,11 +170,12 @@ class asyncJobMgr(object):
id += 1
ids.append(id)
return ids
-
+
def updateTimeStamp(self, jobstatus):
jobId = jobstatus.jobId
if jobId is not None and self.db is not None:
- result = self.db.execute("select job_status, created, last_updated from async_job where id=%s"%jobId)
+ result = self.db.execute(
+ "select job_status, created, last_updated from async_job where id='%s'" % str(jobId))
if result is not None and len(result) > 0:
if result[0][0] == 1:
jobstatus.status = True
@@ -174,7 +185,7 @@ class asyncJobMgr(object):
jobstatus.endTime = result[0][2]
delta = jobstatus.endTime - jobstatus.startTime
jobstatus.duration = delta.total_seconds()
-
+
def waitForComplete(self, workers=10):
self.inqueue.join()
lock = threading.Lock()
@@ -183,28 +194,30 @@ class asyncJobMgr(object):
for i in range(workers):
worker = workThread(self.outqueue, resultQueue, self.apiClient, self.db, lock)
worker.start()
-
+
self.outqueue.join()
-
+
asyncJobResult = []
while resultQueue.qsize() > 0:
jobstatus = resultQueue.get()
self.updateTimeStamp(jobstatus)
asyncJobResult.append(jobstatus)
-
+
return asyncJobResult
-
+
'''put commands into a queue at first, then start workers numbers threads to execute this commands'''
+
def submitCmdsAndWait(self, cmds, workers=10):
self.submitCmds(cmds)
lock = threading.Lock()
for i in range(workers):
worker = workThread(self.inqueue, self.outqueue, self.apiClient, self.db, lock)
worker.start()
-
+
return self.waitForComplete(workers)
'''submit one job and execute the same job ntimes, with nums_threads of threads'''
+
def submitJobExecuteNtimes(self, job, ntimes=1, nums_threads=1, interval=1):
inqueue1 = Queue.Queue()
lock = threading.Condition()
@@ -213,22 +226,23 @@ class asyncJobMgr(object):
setattr(newjob, "apiClient", copy.copy(self.apiClient))
setattr(newjob, "lock", lock)
inqueue1.put(newjob)
-
+
for i in range(nums_threads):
work = jobThread(inqueue1, interval)
work.start()
inqueue1.join()
-
+
'''submit n jobs, execute them with nums_threads of threads'''
+
def submitJobs(self, jobs, nums_threads=1, interval=1):
inqueue1 = Queue.Queue()
lock = threading.Condition()
-
+
for job in jobs:
setattr(job, "apiClient", copy.copy(self.apiClient))
setattr(job, "lock", lock)
inqueue1.put(job)
-
+
for i in range(nums_threads):
work = jobThread(inqueue1, interval)
work.start()
diff --git a/tools/marvin/marvin/cloudstackConnection.py b/tools/marvin/marvin/cloudstackConnection.py
index 5d30803d930..9a4c387a87a 100644
--- a/tools/marvin/marvin/cloudstackConnection.py
+++ b/tools/marvin/marvin/cloudstackConnection.py
@@ -33,13 +33,18 @@ from requests import RequestException
class cloudConnection(object):
""" Connections to make API calls to the cloudstack management server
"""
- def __init__(self, mgtSvr, port=8096, apiKey=None, securityKey=None,
+ def __init__(self, mgtSvr, port=8096, user=None, passwd=None,
+ apiKey=None, securityKey=None,
asyncTimeout=3600, logging=None, scheme='http',
path='client/api'):
self.apiKey = apiKey
self.securityKey = securityKey
self.mgtSvr = mgtSvr
self.port = port
+ if user:
+ self.user = user
+ if passwd:
+ self.passwd = passwd
self.logging = logging
self.path = path
self.retries = 5
@@ -55,9 +60,10 @@ class cloudConnection(object):
% (self.protocol, self.mgtSvr, self.port, self.path)
def __copy__(self):
- return cloudConnection(self.mgtSvr, self.port, self.apiKey,
- self.securityKey, self.asyncTimeout,
- self.logging, self.protocol, self.path)
+ return cloudConnection(self.mgtSvr, self.port, self.user, self.passwd,
+ self.apiKey, self.securityKey,
+ self.asyncTimeout, self.logging, self.protocol,
+ self.path)
def poll(self, jobid, response):
"""
@@ -200,7 +206,8 @@ class cloudConnection(object):
@return:
"""
cmdname, isAsync, payload = self.sanitize_command(cmd)
- self.logging.debug("sending %s request: %s %s" % (method, cmdname, str(payload)))
+ self.logging.debug("sending %s request: %s %s" % (method, cmdname,
+ str(payload)))
response = self.request(
cmdname, self.auth, payload=payload, method=method)
self.logging.debug("Request: %s Response: %s" %
diff --git a/tools/marvin/marvin/cloudstackTestClient.py b/tools/marvin/marvin/cloudstackTestClient.py
index 85552ed5523..d85a61c4872 100644
--- a/tools/marvin/marvin/cloudstackTestClient.py
+++ b/tools/marvin/marvin/cloudstackTestClient.py
@@ -18,24 +18,29 @@
import cloudstackConnection
import asyncJobMgr
import dbConnection
-from cloudstackAPI import *
+from cloudstackAPI import *
import random
import string
import hashlib
class cloudstackTestClient(object):
- def __init__(self, mgtSvr=None, port=8096, apiKey = None, securityKey = None, asyncTimeout=3600,
+ def __init__(self, mgtSvr=None, port=8096, user=None, passwd=None,
+ apiKey=None, securityKey=None, asyncTimeout=3600,
defaultWorkerThreads=10, logging=None):
- self.connection = cloudstackConnection.cloudConnection(mgtSvr, port, apiKey, securityKey, asyncTimeout, logging)
+ self.connection = \
+ cloudstackConnection.cloudConnection(
+ mgtSvr, port, user,
+ passwd, apiKey, securityKey,
+ asyncTimeout, logging)
self.apiClient = cloudstackAPIClient.CloudStackAPIClient(self.connection)
self.dbConnection = None
self.asyncJobMgr = None
self.ssh = None
self.defaultWorkerThreads = defaultWorkerThreads
-
+
def dbConfigure(self, host="localhost", port=3306, user='cloud', passwd='cloud', db='cloud'):
self.dbConnection = dbConnection.dbConnection(host, port, user, passwd, db)
-
+
def isAdminContext(self):
"""
A user is a regular user if he fails to listDomains;
@@ -53,7 +58,7 @@ class cloudstackTestClient(object):
return 2 #domain-admin
except:
return 0 #user
-
+
def random_gen(self, size=6, chars=string.ascii_uppercase + string.digits):
"""Generate Random Strings of variable length"""
return ''.join(random.choice(chars) for x in range(size))
@@ -61,7 +66,7 @@ class cloudstackTestClient(object):
def createUserApiClient(self, UserName, DomainName, acctType=0):
if not self.isAdminContext():
return self.apiClient
-
+
listDomain = listDomains.listDomainsCmd()
listDomain.listall = True
listDomain.name = DomainName
@@ -73,11 +78,11 @@ class cloudstackTestClient(object):
cdomain.name = DomainName
domain = self.apiClient.createDomain(cdomain)
domId = domain.id
-
+
mdf = hashlib.md5()
mdf.update("password")
mdf_pass = mdf.hexdigest()
-
+
cmd = listAccounts.listAccountsCmd()
cmd.name = UserName
cmd.domainid = domId
@@ -95,46 +100,47 @@ class cloudstackTestClient(object):
createAcctCmd.username = UserName
acct = self.apiClient.createAccount(createAcctCmd)
acctId = acct.id
-
- listuser = listUsers.listUsersCmd()
+
+ listuser = listUsers.listUsersCmd()
listuser.username = UserName
-
+
listuserRes = self.apiClient.listUsers(listuser)
userId = listuserRes[0].id
apiKey = listuserRes[0].apikey
securityKey = listuserRes[0].secretkey
-
+
if apiKey is None:
registerUser = registerUserKeys.registerUserKeysCmd()
registerUser.id = userId
registerUserRes = self.apiClient.registerUserKeys(registerUser)
apiKey = registerUserRes.apikey
securityKey = registerUserRes.secretkey
-
+
newUserConnection = cloudstackConnection.cloudConnection(self.connection.mgtSvr, self.connection.port,
+ self.connection.user, self.connection.passwd,
apiKey, securityKey, self.connection.asyncTimeout, self.connection.logging)
self.userApiClient = cloudstackAPIClient.CloudStackAPIClient(newUserConnection)
self.userApiClient.connection = newUserConnection
return self.userApiClient
-
+
def close(self):
if self.connection is not None:
self.connection.close()
-
+
def getDbConnection(self):
return self.dbConnection
def executeSql(self, sql=None):
if sql is None or self.dbConnection is None:
return None
-
+
return self.dbConnection.execute()
-
+
def executeSqlFromFile(self, sqlFile=None):
if sqlFile is None or self.dbConnection is None:
return None
return self.dbConnection.executeSqlFromFile(sqlFile)
-
+
def getApiClient(self):
return self.apiClient
@@ -151,18 +157,21 @@ class cloudstackTestClient(object):
'''FixME, httplib has issue if more than one thread submitted'''
+
def submitCmdsAndWait(self, cmds, workers=1):
if self.asyncJobMgr is None:
self.asyncJobMgr = asyncJobMgr.asyncJobMgr(self.apiClient, self.dbConnection)
return self.asyncJobMgr.submitCmdsAndWait(cmds, workers)
-
+
'''submit one job and execute the same job ntimes, with nums_threads of threads'''
+
def submitJob(self, job, ntimes=1, nums_threads=10, interval=1):
if self.asyncJobMgr is None:
self.asyncJobMgr = asyncJobMgr.asyncJobMgr(self.apiClient, self.dbConnection)
self.asyncJobMgr.submitJobExecuteNtimes(job, ntimes, nums_threads, interval)
-
- '''submit n jobs, execute them with nums_threads of threads'''
+
+ '''submit n jobs, execute them with nums_threads of threads'''
+
def submitJobs(self, jobs, nums_threads=10, interval=1):
if self.asyncJobMgr is None:
self.asyncJobMgr = asyncJobMgr.asyncJobMgr(self.apiClient, self.dbConnection)
diff --git a/tools/marvin/marvin/dbConnection.py b/tools/marvin/marvin/dbConnection.py
index 8fa86438ab0..958299aff2a 100644
--- a/tools/marvin/marvin/dbConnection.py
+++ b/tools/marvin/marvin/dbConnection.py
@@ -37,7 +37,11 @@ class dbConnection(object):
return None
resultRow = []
- with contextlib.closing(mysql.connector.connect(host=self.host, port=self.port, user=self.user, password=self.passwd, db=self.database)) as conn:
+ with contextlib.closing(mysql.connector.connect(host=str(self.host),
+ port=int(self.port),
+ user=str(self.user),
+ password=str(self.passwd),
+ db=str(self.database))) as conn:
conn.autocommit = True
with contextlib.closing(conn.cursor(buffered=True)) as cursor:
cursor.execute(sql, params)
diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py
index d358789d8da..5ca1ebfb4f8 100644
--- a/tools/marvin/marvin/deployDataCenter.py
+++ b/tools/marvin/marvin/deployDataCenter.py
@@ -402,6 +402,7 @@ class deployDataCenters():
self.testClient = \
cloudstackTestClient.cloudstackTestClient(mgt.mgtSvrIp, mgt.port, \
+ mgt.user, mgt.passwd, \
mgt.apiKey, \
mgt.securityKey, \
logging=self.testClientLogger)
@@ -409,6 +410,7 @@ class deployDataCenters():
apiKey, securityKey = self.registerApiKey()
self.testClient = \
cloudstackTestClient.cloudstackTestClient(mgt.mgtSvrIp, 8080, \
+ mgt.user, mgt.passwd, \
apiKey, securityKey, \
logging=self.testClientLogger)
@@ -419,6 +421,11 @@ class deployDataCenters():
dbSvr.passwd, dbSvr.db)
self.apiClient = self.testClient.getApiClient()
+ """set hypervisor"""
+ if mgt.hypervisor:
+ self.apiClient.hypervisor = mgt.hypervisor
+ else:
+ self.apiClient.hypervisor = "XenServer" #Defaults to Xenserver
def updateConfiguration(self, globalCfg):
if globalCfg is None:
diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py
index 6c285233a82..1d86c6c1599 100755
--- a/tools/marvin/marvin/integration/lib/base.py
+++ b/tools/marvin/marvin/integration/lib/base.py
@@ -5,9 +5,9 @@
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
-#
+#
# http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -22,7 +22,7 @@
import marvin
from utils import is_server_ssh_ready, random_gen
from marvin.cloudstackAPI import *
-#Import System modules
+# Import System modules
import time
import hashlib
import base64
@@ -54,8 +54,12 @@ class Domain:
cmd.parentdomainid = parentdomainid
elif "parentdomainid" in services:
cmd.parentdomainid = services["parentdomainid"]
-
- return Domain(apiclient.createDomain(cmd).__dict__)
+ try:
+ domain = apiclient.createDomain(cmd)
+ if domain is not None:
+ return Domain(domain.__dict__)
+ except Exception as e:
+ raise e
def delete(self, apiclient, cleanup=None):
"""Delete an domain"""
@@ -83,7 +87,7 @@ class Account:
"""Creates an account"""
cmd = createAccount.createAccountCmd()
- #0 - User, 1 - Root Admin, 2 - Domain Admin
+ # 0 - User, 1 - Root Admin, 2 - Domain Admin
cmd.accounttype = 2 if (admin and domainid) else int(admin)
cmd.email = services["email"]
@@ -213,14 +217,15 @@ class VirtualMachine:
else:
self.ssh_port = 22
self.ssh_client = None
- #extract out the ipaddress
+ # extract out the ipaddress
self.ipaddress = self.nic[0].ipaddress
@classmethod
def create(cls, apiclient, services, templateid=None, accountid=None,
domainid=None, zoneid=None, networkids=None, serviceofferingid=None,
securitygroupids=None, projectid=None, startvm=None,
- diskofferingid=None, affinitygroupnames=None, hostid=None, mode='basic', method='GET'):
+ diskofferingid=None, affinitygroupnames=None, group=None,
+ hostid=None, keypair=None, mode='basic', method='GET'):
"""Create the instance"""
cmd = deployVirtualMachine.deployVirtualMachineCmd()
@@ -234,7 +239,13 @@ class VirtualMachine:
cmd.zoneid = zoneid
elif "zoneid" in services:
cmd.zoneid = services["zoneid"]
- cmd.hypervisor = services["hypervisor"]
+ cmd.hypervisor = apiclient.hypervisor
+
+ if "displayname" in services:
+ cmd.displayname = services["displayname"]
+
+ if "name" in services:
+ cmd.name = services["name"]
if accountid:
cmd.account = accountid
@@ -256,9 +267,16 @@ class VirtualMachine:
elif "template" in services:
cmd.templateid = services["template"]
- if "diskoffering" in services:
+ if diskofferingid:
+ cmd.diskofferingid = diskofferingid
+ elif "diskoffering" in services:
cmd.diskofferingid = services["diskoffering"]
+ if keypair:
+ cmd.keypair = keypair
+ elif "keypair" in services:
+ cmd.keypair = services["keypair"]
+
if securitygroupids:
cmd.securitygroupids = [str(sg_id) for sg_id in securitygroupids]
@@ -282,6 +300,15 @@ class VirtualMachine:
virtual_machine = apiclient.deployVirtualMachine(cmd, method=method)
+ if group:
+ cmd.group = group
+ virtual_machine = apiclient.deployVirtualMachine(cmd)
+
+ if startvm == False:
+ virtual_machine.ssh_ip = virtual_machine.nic[0].ipaddress
+ virtual_machine.public_ip = virtual_machine.nic[0].ipaddress
+ return VirtualMachine(virtual_machine.__dict__, services)
+
# VM should be in Running state after deploy
timeout = 10
while True:
@@ -308,14 +335,14 @@ class VirtualMachine:
virtual_machine.domainid,
services
)
- fw_rule = FireWallRule.create(
+ FireWallRule.create(
apiclient,
ipaddressid=public_ip.ipaddress.id,
protocol='TCP',
cidrlist=['0.0.0.0/0'],
startport=22,
endport=22
- )
+ )
nat_rule = NATRule.create(
apiclient,
virtual_machine,
@@ -348,7 +375,13 @@ class VirtualMachine:
cmd.id = self.id
apiclient.rebootVirtualMachine(cmd)
- def get_ssh_client(self, ipaddress=None, reconnect=False, port=None):
+ def recover(self, apiclient):
+ """Recover the instance"""
+ cmd = recoverVirtualMachine.recoverVirtualMachineCmd()
+ cmd.id = self.id
+ apiclient.recoverVirtualMachine(cmd)
+
+ def get_ssh_client(self, ipaddress=None, reconnect=False, port=None, keyPairFileLocation=None):
"""Get SSH object of VM"""
# If NAT Rules are not created while VM deployment in Advanced mode
@@ -358,27 +391,56 @@ class VirtualMachine:
if port:
self.ssh_port = port
+ if keyPairFileLocation is not None:
+ self.password = None
+
if reconnect:
self.ssh_client = is_server_ssh_ready(
self.ssh_ip,
self.ssh_port,
self.username,
- self.password
+ self.password,
+ keyPairFileLocation=keyPairFileLocation
)
self.ssh_client = self.ssh_client or is_server_ssh_ready(
self.ssh_ip,
self.ssh_port,
self.username,
- self.password
+ self.password,
+ keyPairFileLocation=keyPairFileLocation
)
return self.ssh_client
+ def resetSshKey(self, apiclient, **kwargs):
+ """Resets SSH key"""
+
+ cmd = resetSSHKeyForVirtualMachine.resetSSHKeyForVirtualMachineCmd()
+ cmd.id = self.id
+ [setattr(cmd, k, v) for k, v in kwargs.items()]
+ return(apiclient.resetSSHKeyForVirtualMachine(cmd))
+
+ def update(self, apiclient, **kwargs):
+ """Updates the VM data"""
+
+ cmd = updateVirtualMachine.updateVirtualMachineCmd()
+ cmd.id = self.id
+ [setattr(cmd, k, v) for k, v in kwargs.items()]
+ return(apiclient.updateVirtualMachine(cmd))
+
def delete(self, apiclient):
"""Destroy an Instance"""
cmd = destroyVirtualMachine.destroyVirtualMachineCmd()
cmd.id = self.id
apiclient.destroyVirtualMachine(cmd)
+ def migrate(self, apiclient, hostid=None):
+ """migrate an Instance"""
+ cmd = migrateVirtualMachine.migrateVirtualMachineCmd()
+ cmd.virtualmachineid = self.id
+ if hostid:
+ cmd.hostid = hostid
+ apiclient.migrateVirtualMachine(cmd)
+
def attach_volume(self, apiclient, volume):
"""Attach volume to instance"""
cmd = attachVolume.attachVolumeCmd()
@@ -394,7 +456,7 @@ class VirtualMachine:
def add_nic(self, apiclient, networkId):
"""Add a NIC to a VM"""
- cmd = addNicToVirtualMachine.addNicToVirtualMachineCmd();
+ cmd = addNicToVirtualMachine.addNicToVirtualMachineCmd()
cmd.virtualmachineid = self.id
cmd.networkid = networkId
return apiclient.addNicToVirtualMachine(cmd)
@@ -413,6 +475,26 @@ class VirtualMachine:
cmd.virtualmachineid = self.id
return apiclient.updateDefaultNicForVirtualMachine(cmd)
+ def attach_iso(self, apiclient, iso):
+ """Attach ISO to instance"""
+ cmd = attachIso.attachIsoCmd()
+ cmd.id = iso.id
+ cmd.virtualmachineid = self.id
+ return apiclient.attachIso(cmd)
+
+ def detach_iso(self, apiclient):
+ """Detach ISO to instance"""
+ cmd = detachIso.detachIsoCmd()
+ cmd.id = self.id
+ return apiclient.detachIso(cmd)
+
+ def change_service_offering(self, apiclient, serviceOfferingId):
+ """Change service offering of the instance"""
+ cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd()
+ cmd.id = self.id
+ cmd.serviceofferingid = serviceOfferingId
+ return apiclient.changeServiceForVirtualMachine(cmd)
+
@classmethod
def list(cls, apiclient, **kwargs):
"""List all VMs matching criteria"""
@@ -428,16 +510,14 @@ class VirtualMachine:
cmd.id = self.id
try:
response = apiclient.resetPasswordForVirtualMachine(cmd)
- print response
except Exception as e:
raise Exception("Reset Password failed! - %s" % e)
- print type(response)
if isinstance(response, list):
return response[0].password
class Volume:
- """Manage Volume Lifecycle
+ """Manage Volume Life cycle
"""
def __init__(self, items):
self.__dict__.update(items)
@@ -533,7 +613,7 @@ class Volume:
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listVolumes(cmd))
- def resize(cls, apiclient, **kwargs):
+ def resize(self, apiclient, **kwargs):
"""Resize a volume"""
cmd = resizeVolume.resizeVolumeCmd()
cmd.id = self.id
@@ -541,6 +621,58 @@ class Volume:
return(apiclient.resizeVolume(cmd))
@classmethod
+ def upload(cls, apiclient, services, zoneid=None, account=None, domainid=None, url=None):
+ """Uploads the volume to specified account"""
+
+ cmd = uploadVolume.uploadVolumeCmd()
+ if zoneid:
+ cmd.zoneid = zoneid
+ if account:
+ cmd.account = account
+ if domainid:
+ cmd.domainid = domainid
+ cmd.format = services["format"]
+ cmd.name = services["diskname"]
+ if url:
+ cmd.url = url
+ else:
+ cmd.url = services["url"]
+ return Volume(apiclient.uploadVolume(cmd).__dict__)
+
+ def wait_for_upload(self, apiclient, timeout=5, interval=60):
+ """Wait for upload"""
+ # Sleep to ensure template is in proper state before download
+ time.sleep(interval)
+
+ while True:
+ volume_response = Volume.list(
+ apiclient,
+ id=self.id,
+ zoneid=self.zoneid,
+ )
+ if isinstance(volume_response, list):
+
+ volume = volume_response[0]
+ # If volume is ready,
+ # volume.state = Allocated
+ if volume.state == 'Uploaded':
+ break
+
+ elif 'Uploading' in volume.state:
+ time.sleep(interval)
+
+ elif 'Installing' not in volume.state:
+ raise Exception(
+ "Error in uploading volume: status - %s" %
+ volume.state)
+ elif timeout == 0:
+ break
+
+ else:
+ time.sleep(interval)
+ timeout = timeout - 1
+ return
+
def migrate(cls, apiclient, **kwargs):
"""Migrate a volume"""
cmd = migrateVolume.migrateVolumeCmd()
@@ -592,7 +724,7 @@ class Template:
def create(cls, apiclient, services, volumeid=None,
account=None, domainid=None, projectid=None):
"""Create template from Volume"""
- #Create template from Virtual machine and Volume ID
+ # Create template from Virtual machine and Volume ID
cmd = createTemplate.createTemplateCmd()
cmd.displaytext = services["displaytext"]
cmd.name = "-".join([services["name"], random_gen()])
@@ -617,7 +749,6 @@ class Template:
cmd.ispublic = services["ispublic"] if "ispublic" in services else False
cmd.isextractable = services["isextractable"] if "isextractable" in services else False
cmd.passwordenabled = services["passwordenabled"] if "passwordenabled" in services else False
- cmd.passwordenabled = services["passwordenabled"] if "passwordenabled" in services else False
if volumeid:
cmd.volumeid = volumeid
@@ -637,12 +768,12 @@ class Template:
account=None, domainid=None):
"""Create template from URL"""
- #Create template from Virtual machine and Volume ID
+ # Create template from Virtual machine and Volume ID
cmd = registerTemplate.registerTemplateCmd()
cmd.displaytext = services["displaytext"]
cmd.name = "-".join([services["name"], random_gen()])
cmd.format = services["format"]
- cmd.hypervisor = services["hypervisor"]
+ cmd.hypervisor = apiclient.hypervisor
if "ostypeid" in services:
cmd.ostypeid = services["ostypeid"]
@@ -689,7 +820,7 @@ class Template:
def create_from_snapshot(cls, apiclient, snapshot, services,
random_name=True):
"""Create Template from snapshot"""
- #Create template from Virtual machine and Snapshot ID
+ # Create template from Virtual machine and Snapshot ID
cmd = createTemplate.createTemplateCmd()
cmd.displaytext = services["displaytext"]
cmd.name = "-".join([
@@ -726,7 +857,7 @@ class Template:
def download(self, apiclient, timeout=5, interval=60):
"""Download Template"""
- #Sleep to ensure template is in proper state before download
+ # Sleep to ensure template is in proper state before download
time.sleep(interval)
while True:
@@ -789,7 +920,7 @@ class Iso:
def create(cls, apiclient, services, account=None, domainid=None,
projectid=None):
"""Create an ISO"""
- #Create ISO from URL
+ # Create ISO from URL
cmd = registerIso.registerIsoCmd()
cmd.displaytext = services["displaytext"]
cmd.name = services["name"]
@@ -841,7 +972,7 @@ class Iso:
def download(self, apiclient, timeout=5, interval=60):
"""Download an ISO"""
- #Ensuring ISO is successfully downloaded
+ # Ensuring ISO is successfully downloaded
while True:
time.sleep(interval)
@@ -853,7 +984,6 @@ class Iso:
response = iso_response[0]
# Again initialize timeout to avoid listISO failure
timeout = 5
- print response.status
# Check whether download is in progress(for Ex:10% Downloaded)
# or ISO is 'Successfully Installed'
if response.status == 'Successfully Installed':
@@ -940,7 +1070,7 @@ class NATRule:
@classmethod
def create(cls, apiclient, virtual_machine, services, ipaddressid=None,
- projectid=None, networkid=None):
+ projectid=None, openfirewall=False, networkid=None, vpcid=None):
"""Create Port forwarding rule"""
cmd = createPortForwardingRule.createPortForwardingRuleCmd()
@@ -951,15 +1081,24 @@ class NATRule:
cmd.privateport = services["privateport"]
cmd.publicport = services["publicport"]
+ if "privateendport" in services:
+ cmd.privateendport = services["privateendport"]
+ if "publicendport" in services:
+ cmd.publicendport = services["publicendport"]
cmd.protocol = services["protocol"]
cmd.virtualmachineid = virtual_machine.id
if projectid:
cmd.projectid = projectid
+ if openfirewall:
+ cmd.openfirewall = True
+
if networkid:
cmd.networkid = networkid
+ if vpcid:
+ cmd.vpcid = vpcid
return NATRule(apiclient.createPortForwardingRule(cmd).__dict__)
def delete(self, apiclient):
@@ -985,10 +1124,10 @@ class StaticNATRule:
self.__dict__.update(items)
@classmethod
- def create(cls, apiclient, services, ipaddressid=None, vpcid=None):
+ def create(cls, apiclient, services, ipaddressid=None, networkid=None, vpcid=None):
"""Creates static ip forwarding rule"""
- cmd = createIpForwardingRule.createIpForwardingRuleCmd()
+ cmd = createFirewallRule.createFirewallRuleCmd()
cmd.protocol = services["protocol"]
cmd.startport = services["startport"]
@@ -1003,10 +1142,12 @@ class StaticNATRule:
elif "ipaddressid" in services:
cmd.ipaddressid = services["ipaddressid"]
+ if networkid:
+ cmd.networkid = networkid
+
if vpcid:
cmd.vpcid = vpcid
-
- return StaticNATRule(apiclient.createIpForwardingRule(cmd).__dict__)
+ return StaticNATRule(apiclient.createFirewallRule(cmd).__dict__)
def delete(self, apiclient):
"""Delete IP forwarding rule"""
@@ -1024,12 +1165,14 @@ class StaticNATRule:
return(apiclient.listIpForwardingRules(cmd))
@classmethod
- def enable(cls, apiclient, ipaddressid, virtualmachineid):
+ def enable(cls, apiclient, ipaddressid, virtualmachineid, networkid=None):
"""Enables Static NAT rule"""
cmd = enableStaticNat.enableStaticNatCmd()
cmd.ipaddressid = ipaddressid
cmd.virtualmachineid = virtualmachineid
+ if networkid:
+ cmd.networkid = networkid
apiclient.enableStaticNat(cmd)
return
@@ -1105,6 +1248,14 @@ class ServiceOffering:
if "storagetype" in services:
cmd.storagetype = services["storagetype"]
+ if "systemvmtype" in services:
+ cmd.systemvmtype = services['systemvmtype']
+
+ if "issystem" in services:
+ cmd.issystem = services['issystem']
+
+ if "tags" in services:
+ cmd.tags = services["tags"]
# Service Offering private to that domain
if domainid:
cmd.domainid = domainid
@@ -1183,20 +1334,25 @@ class NetworkOffering:
cmd.displaytext = "-".join([services["displaytext"], random_gen()])
cmd.name = "-".join([services["name"], random_gen()])
cmd.guestiptype = services["guestiptype"]
- cmd.supportedservices = services["supportedservices"]
+ cmd.supportedservices = ''
+ if "supportedservices" in services:
+ cmd.supportedservices = services["supportedservices"]
cmd.traffictype = services["traffictype"]
+ if "useVpc" in services:
+ cmd.useVpc = services["useVpc"]
cmd.serviceProviderList = []
- for service, provider in services["serviceProviderList"].items():
- cmd.serviceProviderList.append({
+ if "serviceProviderList" in services:
+ for service, provider in services["serviceProviderList"].items():
+ cmd.serviceProviderList.append({
'service': service,
'provider': provider
})
if "servicecapabilitylist" in services:
- cmd.servicecapabilitylist = []
+ cmd.serviceCapabilityList = []
for service, capability in services["servicecapabilitylist"].items():
for ctype, value in capability.items():
- cmd.servicecapabilitylist.append({
+ cmd.serviceCapabilityList.append({
'service': service,
'capabilitytype': ctype,
'capabilityvalue': value
@@ -1205,6 +1361,7 @@ class NetworkOffering:
cmd.specifyVlan = services["specifyVlan"]
if "specifyIpRanges" in services:
cmd.specifyIpRanges = services["specifyIpRanges"]
+ cmd.availability = 'Optional'
[setattr(cmd, k, v) for k, v in kwargs.items()]
@@ -1275,7 +1432,7 @@ class LoadBalancerRule:
@classmethod
def create(cls, apiclient, services, ipaddressid=None, accountid=None,
- networkid=None, projectid=None, domainid=None):
+ networkid=None, vpcid=None, projectid=None, domainid=None):
"""Create Load balancing Rule"""
cmd = createLoadBalancerRule.createLoadBalancerRuleCmd()
@@ -1293,6 +1450,8 @@ class LoadBalancerRule:
if domainid:
cmd.domainid = domainid
+ if vpcid:
+ cmd.vpcid = vpcid
cmd.name = services["name"]
cmd.algorithm = services["alg"]
cmd.privateport = services["privateport"]
@@ -1359,19 +1518,19 @@ class LoadBalancerRule:
for name, value in param.items():
cmd.param.append({'name': name, 'value': value})
return apiclient.createLBStickinessPolicy(cmd)
-
+
def deleteSticky(self, apiclient, id):
"""Deletes stickyness policy"""
-
+
cmd = deleteLBStickinessPolicy.deleteLBStickinessPolicyCmd()
cmd.id = id
return apiclient.deleteLBStickinessPolicy(cmd)
-
+
@classmethod
def listStickyPolicies(cls, apiclient, lbruleid, **kwargs):
"""Lists stickiness policies for load balancing rule"""
-
- cmd= listLBStickinessPolicies.listLBStickinessPoliciesCmd()
+
+ cmd = listLBStickinessPolicies.listLBStickinessPoliciesCmd()
cmd.lbruleid = lbruleid
[setattr(cmd, k, v) for k, v in kwargs.items()]
return apiclient.listLBStickinessPolicies(cmd)
@@ -1396,7 +1555,7 @@ class Cluster:
"""Create Cluster"""
cmd = addCluster.addClusterCmd()
cmd.clustertype = services["clustertype"]
- cmd.hypervisor = services["hypervisor"]
+ cmd.hypervisor = apiclient.hypervisor
if zoneid:
cmd.zoneid = zoneid
@@ -1446,7 +1605,7 @@ class Host:
"""Create Host in cluster"""
cmd = addHost.addHostCmd()
- cmd.hypervisor = services["hypervisor"]
+ cmd.hypervisor = apiclient.hypervisor
cmd.url = services["url"]
cmd.clusterid = cluster.id
@@ -1493,6 +1652,29 @@ class Host:
cmd.id = self.id
return apiclient.prepareHostForMaintenance(cmd)
+ @classmethod
+ def enableMaintenance(cls, apiclient, id):
+ """enables maintainance mode Host"""
+
+ cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
+ cmd.id = id
+ return apiclient.prepareHostForMaintenance(cmd)
+
+ def cancelMaintenance(self, apiclient):
+ """Cancels maintainance mode Host"""
+
+ cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
+ cmd.id = self.id
+ return apiclient.cancelHostMaintenance(cmd)
+
+ @classmethod
+ def cancelMaintenance(cls, apiclient, id):
+ """Cancels maintainance mode Host"""
+
+ cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
+ cmd.id = id
+ return apiclient.cancelHostMaintenance(cmd)
+
@classmethod
def list(cls, apiclient, **kwargs):
"""List all Hosts matching criteria"""
@@ -1586,7 +1768,8 @@ class Network:
@classmethod
def create(cls, apiclient, services, accountid=None, domainid=None,
- networkofferingid=None, projectid=None, zoneid=None,
+ networkofferingid=None, projectid=None,
+ subdomainaccess=None, zoneid=None,
gateway=None, netmask=None, vpcid=None, guestcidr=None):
"""Create Network for account"""
cmd = createNetwork.createNetworkCmd()
@@ -1603,6 +1786,9 @@ class Network:
elif "zoneid" in services:
cmd.zoneid = services["zoneid"]
+ if subdomainaccess is not None:
+ cmd.subdomainaccess = subdomainaccess
+
if gateway:
cmd.gateway = gateway
elif "gateway" in services:
@@ -1717,7 +1903,7 @@ class Vpn:
@classmethod
def create(cls, apiclient, publicipid, account=None, domainid=None,
- projectid=None, vpcid=None):
+ projectid=None, networkid=None, vpcid=None):
"""Create VPN for Public IP address"""
cmd = createRemoteAccessVpn.createRemoteAccessVpnCmd()
cmd.publicipid = publicipid
@@ -1727,6 +1913,8 @@ class Vpn:
cmd.domainid = domainid
if projectid:
cmd.projectid = projectid
+ if networkid:
+ cmd.networkid = networkid
if vpcid:
cmd.vpcid = vpcid
return Vpn(apiclient.createRemoteAccessVpn(cmd).__dict__)
@@ -1755,10 +1943,11 @@ class VpnUser:
@classmethod
def create(cls, apiclient, username, password, account=None, domainid=None,
- projectid=None):
+ projectid=None, rand_name=True):
"""Create VPN user"""
cmd = addVpnUser.addVpnUserCmd()
- cmd.username = username
+ cmd.username = "-".join([username,
+ random_gen()]) if rand_name else username
cmd.password = password
if account:
@@ -1997,6 +2186,7 @@ class PhysicalNetwork:
[setattr(cmd, k, v) for k, v in kwargs.items()]
return map(lambda pn : PhysicalNetwork(pn.__dict__), apiclient.listPhysicalNetworks(cmd))
+
class SecurityGroup:
"""Manage Security Groups"""
@@ -2364,6 +2554,104 @@ class NetworkServiceProvider:
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listNetworkServiceProviders(cmd))
+
+class Router:
+ """Manage router life cycle"""
+
+ def __init__(self, items):
+ self.__dict__.update(items)
+
+ @classmethod
+ def start(cls, apiclient, id):
+ """Starts the router"""
+ cmd = startRouter.startRouterCmd()
+ cmd.id = id
+ return apiclient.startRouter(cmd)
+
+ @classmethod
+ def stop(cls, apiclient, id, forced=None):
+ """Stops the router"""
+ cmd = stopRouter.stopRouterCmd()
+ cmd.id = id
+ if forced:
+ cmd.forced = forced
+ return apiclient.stopRouter(cmd)
+
+ @classmethod
+ def reboot(cls, apiclient, id):
+ """Reboots the router"""
+ cmd = rebootRouter.rebootRouterCmd()
+ cmd.id = id
+ return apiclient.rebootRouter(cmd)
+
+ @classmethod
+ def destroy(cls, apiclient, id):
+ """Destroy the router"""
+ cmd = destroyRouter.destroyRouterCmd()
+ cmd.id = id
+ return apiclient.destroyRouter(cmd)
+
+ @classmethod
+ def change_service_offering(cls, apiclient, id, serviceofferingid):
+ """Change service offering of the router"""
+ cmd = changeServiceForRouter.changeServiceForRouterCmd()
+ cmd.id = id
+ cmd.serviceofferingid = serviceofferingid
+ return apiclient.changeServiceForRouter(cmd)
+
+ @classmethod
+ def list(cls, apiclient, **kwargs):
+ """List routers"""
+
+ cmd = listRouters.listRoutersCmd()
+ [setattr(cmd, k, v) for k, v in kwargs.items()]
+ return(apiclient.listRouters(cmd))
+
+
+class Tag:
+ """Manage tags"""
+
+ def __init__(self, items):
+ self.__dict__.update(items)
+
+ @classmethod
+ def create(cls, apiclient, resourceIds, resourceType, tags):
+ """Create tags"""
+
+ cmd = createTags.createTagsCmd()
+ cmd.resourceIds = resourceIds
+ cmd.resourcetype = resourceType
+ cmd.tags = []
+ for key, value in tags.items():
+ cmd.tags.append({
+ 'key': key,
+ 'value': value
+ })
+ return Tag(apiclient.createTags(cmd).__dict__)
+
+ def delete(self, apiclient, resourceIds, resourceType, tags):
+ """Delete tags"""
+
+ cmd = deleteTags.deleteTagsCmd()
+ cmd.resourceIds = resourceIds
+ cmd.resourcetype = resourceType
+ cmd.tags = []
+ for key, value in tags.items():
+ cmd.tags.append({
+ 'key': key,
+ 'value': value
+ })
+ apiclient.deleteTags(cmd)
+
+ @classmethod
+ def list(cls, apiclient, **kwargs):
+ """List all tags matching the criteria"""
+
+ cmd = listTags.listTagsCmd()
+ [setattr(cmd, k, v) for k, v in kwargs.items()]
+ return(apiclient.listTags(cmd))
+
+
class VpcOffering:
"""Manage VPC offerings"""
@@ -2417,7 +2705,7 @@ class VPC:
@classmethod
def create(cls, apiclient, services, vpcofferingid,
- zoneid, networkDomain=None, account=None, domainid=None):
+ zoneid, networkDomain=None, account=None, domainid=None):
"""Creates the virtual private connection (VPC)"""
cmd = createVPC.createVPCCmd()
@@ -2467,6 +2755,40 @@ class VPC:
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listVPCs(cmd))
+
+class PrivateGateway:
+ """Manage private gateway lifecycle"""
+ def create(cls, apiclient, gateway, ipaddress, netmask, vlan, vpcid,
+ physicalnetworkid=None):
+ """Create private gateway"""
+
+ cmd = createPrivateGateway.createPrivateGatewayCmd()
+ cmd.gateway = gateway
+ cmd.ipaddress = ipaddress
+ cmd.netmask = netmask
+ cmd.vlan = vlan
+ cmd.vpcid = vpcid
+ if physicalnetworkid:
+ cmd.physicalnetworkid = physicalnetworkid
+
+ return PrivateGateway(apiclient.createPrivateGateway(cmd).__dict__)
+
+ def delete(self, apiclient):
+ """Delete private gateway"""
+
+ cmd = deletePrivateGateway.deletePrivateGatewayCmd()
+ cmd.id = self.id
+ return apiclient.deletePrivateGateway(cmd)
+
+ @classmethod
+ def list(cls, apiclient, **kwargs):
+ """List private gateways"""
+
+ cmd = listPrivateGateways.listPrivateGatewaysCmd()
+ [setattr(cmd, k, v) for k, v in kwargs.items()]
+ return(apiclient.listPrivateGateways(cmd))
+
+
class AffinityGroup:
def __init__(self, items):
self.__dict__.update(items)
@@ -2495,9 +2817,35 @@ class AffinityGroup:
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listVPCs(cmd))
+class StaticRoute:
+ """Manage static route lifecycle"""
+ @classmethod
+ def create(cls, apiclient, cidr, gatewayid):
+ """Create static route"""
+
+ cmd = createStaticRoute.createStaticRouteCmd()
+ cmd.cidr = cidr
+ cmd.gatewayid = gatewayid
+ return StaticRoute(apiclient.createStaticRoute(cmd).__dict__)
+
+ def delete(self, apiclient):
+ """Delete static route"""
+
+ cmd = deleteStaticRoute.deleteStaticRouteCmd()
+ cmd.id = self.id
+ return apiclient.deleteStaticRoute(cmd)
+
+ @classmethod
+ def list(cls, apiclient, **kwargs):
+ """List static route"""
+
+ cmd = listStaticRoutes.listStaticRoutesCmd()
+ [setattr(cmd, k, v) for k, v in kwargs.items()]
+ return(apiclient.listStaticRoutes(cmd))
+
+
class VNMC:
"""Manage VNMC lifecycle"""
-
def __init__(self, items):
self.__dict__.update(items)
@@ -2526,13 +2874,153 @@ class VNMC:
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listCiscoVnmcResources(cmd))
-class ASA1000V:
- """Manage ASA 1000v lifecycle"""
+
+class SSHKeyPair:
+ """Manage SSH Key pairs"""
+
+ def __init__(self, items, services):
+ self.__dict__.update(items)
+
+ @classmethod
+ def create(cls, apiclient, name=None, account=None,
+ domainid=None, projectid=None):
+ """Creates SSH keypair"""
+ cmd = createSSHKeyPair.createSSHKeyPairCmd()
+ cmd.name = name
+ if account is not None:
+ cmd.account = account
+ if domainid is not None:
+ cmd.domainid = domainid
+ if projectid is not None:
+ cmd.projectid = projectid
+ return (apiclient.createSSHKeyPair(cmd))
+
+ def delete(self, apiclient):
+ """Delete SSH key pair"""
+ cmd = deleteSSHKeyPair.deleteSSHKeyPairCmd()
+ cmd.name = self.name
+ apiclient.deleteSSHKeyPair(cmd)
+
+ @classmethod
+ def list(cls, apiclient, **kwargs):
+ """List all SSH key pairs"""
+ cmd = listSSHKeyPairs.listSSHKeyPairsCmd()
+ [setattr(cmd, k, v) for k, v in kwargs.items()]
+ return(apiclient.listSSHKeyPairs(cmd))
+
+
+class Capacities:
+ """Manage Capacities"""
+
+ @classmethod
+ def list(cls, apiclient, **kwargs):
+ """Lists capacities"""
+
+ cmd = listCapacity.listCapacityCmd()
+ [setattr(cmd, k, v) for k, v in kwargs.items()]
+ return(apiclient.listCapacity(cmd))
+
+
+class Alert:
+ """Manage alerts"""
+
+ @classmethod
+ def list(cls, apiclient, **kwargs):
+ """Lists alerts"""
+
+ cmd = listAlerts.listAlertsCmd()
+ [setattr(cmd, k, v) for k, v in kwargs.items()]
+ return(apiclient.listAlerts(cmd))
+
+
+class InstanceGroup:
+ """Manage VM instance groups"""
def __init__(self, items):
self.__dict__.update(items)
@classmethod
+ def create(cls, apiclient, name=None, account=None, domainid=None,
+ projectid=None, networkid=None, rand_name=True):
+ """Creates instance groups"""
+
+ cmd = createInstanceGroup.createInstanceGroupCmd()
+ cmd.name = "-".join([name, random_gen()]) if rand_name else name
+ if account is not None:
+ cmd.account = account
+ if domainid is not None:
+ cmd.domainid = domainid
+ if projectid is not None:
+ cmd.projectid = projectid
+ if networkid is not None:
+ cmd.networkid = networkid
+ return InstanceGroup(apiclient.createInstanceGroup(cmd).__dict__)
+
+ def delete(self, apiclient):
+ """Delete instance group"""
+ cmd = deleteInstanceGroup.deleteInstanceGroupCmd()
+ cmd.id = self.id
+ apiclient.deleteInstanceGroup(cmd)
+
+ def update(self, apiclient, **kwargs):
+ """Updates the instance groups"""
+ cmd = updateInstanceGroup.updateInstanceGroupCmd()
+ cmd.id = self.id
+ [setattr(cmd, k, v) for k, v in kwargs.items()]
+ return (apiclient.updateInstanceGroup(cmd))
+
+ @classmethod
+ def list(cls, apiclient, **kwargs):
+ """List all instance groups"""
+ cmd = listInstanceGroups.listInstanceGroupsCmd()
+ [setattr(cmd, k, v) for k, v in kwargs.items()]
+ return (apiclient.listInstanceGroups(cmd))
+
+ def startInstances(self, apiclient):
+ """Starts all instances in a VM tier"""
+
+ cmd = startVirtualMachine.startVirtualMachineCmd()
+ cmd.group = self.id
+ return apiclient.startVirtualMachine(cmd)
+
+ def stopInstances(self, apiclient):
+ """Stops all instances in a VM tier"""
+
+ cmd = stopVirtualMachine.stopVirtualMachineCmd()
+ cmd.group = self.id
+ return apiclient.stopVirtualMachine(cmd)
+
+ def rebootInstances(self, apiclient):
+ """Reboot all instances in a VM tier"""
+
+ cmd = rebootVirtualMachine.rebootVirtualMachineCmd()
+ cmd.group = self.id
+ return apiclient.rebootVirtualMachine(cmd)
+
+ def deleteInstances(self, apiclient):
+ """Stops all instances in a VM tier"""
+
+ cmd = destroyVirtualMachine.destroyVirtualMachineCmd()
+ cmd.group = self.id
+ return apiclient.destroyVirtualMachine(cmd)
+
+ def changeServiceOffering(self, apiclient, serviceOfferingId):
+ """Change service offering of the vm tier"""
+
+ cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd()
+ cmd.group = self.id
+ cmd.serviceofferingid = serviceOfferingId
+ return apiclient.changeServiceForVirtualMachine(cmd)
+
+ def recoverInstances(self, apiclient):
+ """Recover the instances from vm tier"""
+ cmd = recoverVirtualMachine.recoverVirtualMachineCmd()
+ cmd.group = self.id
+ apiclient.recoverVirtualMachine(cmd)
+
+
+class ASA1000V:
+ """Manage ASA 1000v lifecycle"""
def create(cls, apiclient, hostname, insideportprofile, clusterid, physicalnetworkid):
"""Registers ASA 1000v appliance"""
diff --git a/tools/marvin/marvin/integration/lib/utils.py b/tools/marvin/marvin/integration/lib/utils.py
index cff24a1b2d5..6892c41d1ec 100644
--- a/tools/marvin/marvin/integration/lib/utils.py
+++ b/tools/marvin/marvin/integration/lib/utils.py
@@ -106,12 +106,17 @@ def cleanup_resources(api_client, resources):
obj.delete(api_client)
-def is_server_ssh_ready(ipaddress, port, username, password, retries=50):
+def is_server_ssh_ready(ipaddress, port, username, password, retries=50, keyPairFileLocation=None):
"""Return ssh handle else wait till sshd is running"""
loop_cnt = retries
while True:
try:
- ssh = remoteSSHClient(ipaddress, port, username, password)
+ ssh = remoteSSHClient(
+ host=ipaddress,
+ port=port,
+ user=username,
+ passwd=password,
+ keyPairFileLocation=keyPairFileLocation)
except Exception as e:
if loop_cnt == 0:
raise e
@@ -149,12 +154,16 @@ def fetch_api_client(config_file='datacenterCfg'):
)
-def get_process_status(hostip, port, username, password, linklocalip, process):
+def get_process_status(hostip, port, username, password, linklocalip, process, hypervisor=None):
"""Double hop and returns a process status"""
#SSH to the machine
ssh = remoteSSHClient(hostip, port, username, password)
- ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no "
+ if str(hypervisor).lower() == 'vmware':
+ ssh_command = "ssh -i /var/lib/cloud/management/.ssh/id_rsa -ostricthostkeychecking=no "
+ else:
+ ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no "
+
ssh_command = ssh_command + \
"-oUserKnownHostsFile=/dev/null -p 3922 %s %s" % (
linklocalip,
diff --git a/tools/marvin/marvin/remoteSSHClient.py b/tools/marvin/marvin/remoteSSHClient.py
index 4fb2f0de8f0..04450fdf0e2 100644
--- a/tools/marvin/marvin/remoteSSHClient.py
+++ b/tools/marvin/marvin/remoteSSHClient.py
@@ -23,11 +23,12 @@ import logging
from contextlib import closing
class remoteSSHClient(object):
- def __init__(self, host, port, user, passwd, retries = 10, log_lvl=logging.INFO):
+ def __init__(self, host, port, user, passwd, retries = 10, log_lvl=logging.INFO, keyPairFileLocation=None):
self.host = host
self.port = port
self.user = user
self.passwd = passwd
+ self.keyPairFile = keyPairFileLocation
self.ssh = paramiko.SSHClient()
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.logger = logging.getLogger('sshClient')
@@ -38,8 +39,19 @@ class remoteSSHClient(object):
retry_count = retries
while True:
try:
- self.ssh.connect(str(host),int(port), user, passwd)
- self.logger.debug("SSH connect: %s@%s with passwd %s"%(user, str(host), passwd))
+ if keyPairFileLocation == None:
+ self.ssh.connect(str(host),int(port), user, passwd)
+ self.logger.debug("SSH connect: %s@%s with passwd %s"%(user, str(host), passwd))
+ else:
+ self.ssh.connect(
+ hostname=str(host),
+ port=int(port),
+ username=str(user),
+ key_filename=str(keyPairFileLocation),
+ look_for_keys=False
+ )
+ self.logger.debug("connecting to server %s with user %s key %s"%(str(host), user, keyPairFileLocation))
+ self.logger.debug("SSH connect: %s@%s with passwd %s"%(user, str(host), passwd))
except paramiko.SSHException, sshex:
if retry_count == 0:
raise cloudstackException.InvalidParameterException(repr(sshex))
diff --git a/ui/images/icons.png b/ui/images/icons.png
index f07ca838ee4..e2083da1969 100644
Binary files a/ui/images/icons.png and b/ui/images/icons.png differ
diff --git a/ui/scripts/domains.js b/ui/scripts/domains.js
index 8ee0ee6816a..e82f8ff44e8 100644
--- a/ui/scripts/domains.js
+++ b/ui/scripts/domains.js
@@ -530,7 +530,7 @@
case "10":
domainObj["primaryStorageLimit"] = limit.max;
break;
- case "7":
+ case "11":
domainObj["secondaryStorageLimit"] = limit.max;
break;
}
diff --git a/ui/scripts/regions.js b/ui/scripts/regions.js
index 334eb267bd8..2bbbbeea672 100644
--- a/ui/scripts/regions.js
+++ b/ui/scripts/regions.js
@@ -461,18 +461,27 @@
id: 'lbUnderGSLB',
label: 'assigned load balancing',
fields: {
- 'name': { label: 'label.name' },
+ name: { label: 'label.name' },
publicport: { label: 'label.public.port' },
- privateport: { label: 'label.private.port' },
- algorithm: { label: 'label.algorithm' }
+ privateport: { label: 'label.private.port' },
+ algorithm: { label: 'label.algorithm' }
},
- dataProvider: function(args) {
- var items = args.context.GSLB[0].loadbalancerrule;
- args.response.success({
- data: items
- });
+ dataProvider: function(args) {
+ var data = {
+ id: args.context.GSLB[0].id
+ };
+ $.ajax({
+ url: createURL('listGlobalLoadBalancerRules'),
+ data: data,
+ success: function(json) {
+ var items = json.listgloballoadbalancerrulesresponse.globalloadbalancerrule[0].loadbalancerrule;
+ args.response.success({
+ data: items
+ });
+ }
+ });
},
- actions: {
+ actions: {
add: {
label: 'assign more load balancing',
messages: {
diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js
index 74675314040..a01840637e3 100644
--- a/ui/scripts/sharedFunctions.js
+++ b/ui/scripts/sharedFunctions.js
@@ -114,6 +114,10 @@ function createURL(apiName, options) {
if (cloudStack.context && cloudStack.context.projects && !options.ignoreProject) {
urlString = urlString + '&projectid=' + cloudStack.context.projects[0].id;
}
+
+ if(cloudStack.context != null && cloudStack.context.zoneType != null && cloudStack.context.zoneType.length > 0) { //Basic type or Advanced type
+ urlString = urlString + '&zonetype=' + cloudStack.context.zoneType;
+ }
return urlString;
}
diff --git a/ui/scripts/system.js b/ui/scripts/system.js
index 312d5f4906e..8c962fc2b7b 100644
--- a/ui/scripts/system.js
+++ b/ui/scripts/system.js
@@ -269,29 +269,40 @@
},
primaryStorageCount: function(data) {
+ var data2 = {
+ page: 1,
+ pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property.
+ };
+ if(cloudStack.context.zoneType != null && cloudStack.context.zoneType.length > 0) { //Basic type or Advanced type
+ $.extend(data2, {
+ zonetype: cloudStack.context.zoneType
+ });
+ }
$.ajax({
url: createURL('listStoragePools'),
- data: {
- page: 1,
- pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property.
- },
+ data: data2,
success: function(json) {
- dataFns.secondaryStorageCount($.extend(data, {
- primaryStorageCount: json.liststoragepoolsresponse.count ?
- json.liststoragepoolsresponse.count : 0
+ dataFns.secondaryStorageCount($.extend(data, {
+ primaryStorageCount: json.liststoragepoolsresponse.count ? json.liststoragepoolsresponse.count : 0
}));
}
});
},
secondaryStorageCount: function(data) {
+ var data2 = {
+ type: 'SecondaryStorage',
+ page: 1,
+ pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property.
+ };
+ if(cloudStack.context.zoneType != null && cloudStack.context.zoneType.length > 0) { //Basic type or Advanced type
+ $.extend(data2, {
+ zonetype: cloudStack.context.zoneType
+ });
+ }
$.ajax({
url: createURL('listHosts'),
- data: {
- type: 'SecondaryStorage',
- page: 1,
- pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property.
- },
+ data: data2,
success: function(json) {
dataFns.systemVmCount($.extend(data, {
secondaryStorageCount: json.listhostsresponse.count ?
@@ -318,22 +329,35 @@
},
virtualRouterCount: function(data) {
+ var data2 = {
+ projectid: -1,
+ page: 1,
+ pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property.
+ };
+ if(cloudStack.context.zoneType != null && cloudStack.context.zoneType.length > 0) { //Basic type or Advanced type
+ $.extend(data2, {
+ zonetype: cloudStack.context.zoneType
+ });
+ }
$.ajax({
url: createURL('listRouters'),
- data: {
- projectid: -1,
- page: 1,
- pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property.
- },
+ data: data2,
success: function(json) {
- var total1 = json.listroutersresponse.count ? json.listroutersresponse.count : 0;
+ var total1 = json.listroutersresponse.count ? json.listroutersresponse.count : 0;
+
+ var data3 = {
+ listAll: true,
+ page: 1,
+ pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property.
+ };
+ if(cloudStack.context.zoneType != null && cloudStack.context.zoneType.length > 0) { //Basic type or Advanced type
+ $.extend(data3, {
+ zonetype: cloudStack.context.zoneType
+ });
+ }
$.ajax({
url: createURL('listRouters'),
- data: {
- listAll: true,
- page: 1,
- pagesize: 1 //specifying pagesize as 1 because we don't need any embedded objects to be returned here. The only thing we need from API response is "count" property.
- },
+ data: data3,
success: function(json) {
var total2 = json.listroutersresponse.count ? json.listroutersresponse.count : 0;
dataFns.capacity($.extend(data, {
@@ -2306,12 +2330,18 @@
}
}
+ var data2 = {
+ forvpc: false
+ };
+ if(cloudStack.context.zoneType != null && cloudStack.context.zoneType.length > 0) { //Basic type or Advanced type
+ $.extend(data2, {
+ zonetype: cloudStack.context.zoneType
+ });
+ }
var routers = [];
$.ajax({
url: createURL("listRouters&zoneid=" + selectedZoneObj.id + "&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
- data: {
- forvpc: false
- },
+ data: data2,
success: function(json) {
var items = json.listroutersresponse.router ?
json.listroutersresponse.router : [];
@@ -2323,9 +2353,7 @@
// Get project routers
$.ajax({
url: createURL("listRouters&zoneid=" + selectedZoneObj.id + "&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("") + "&projectid=-1"),
- data: {
- forvpc: false
- },
+ data: data2,
success: function(json) {
var items = json.listroutersresponse.router ?
json.listroutersresponse.router : [];
@@ -2787,13 +2815,19 @@
}
}
+ var data2 = {
+ forvpc: true
+ };
+ if(cloudStack.context.zoneType != null && cloudStack.context.zoneType.length > 0) { //Basic type or Advanced type
+ $.extend(data2, {
+ zonetype: cloudStack.context.zoneType
+ });
+ }
var routers = [];
$.ajax({
url: createURL("listRouters&zoneid=" + selectedZoneObj.id + "&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
dataType: 'json',
- data: {
- forvpc: true
- },
+ data: data2,
async: true,
success: function(json) {
var items = json.listroutersresponse.router;
@@ -2805,9 +2839,7 @@
$.ajax({
url: createURL("listRouters&zoneid=" + selectedZoneObj.id + "&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("") + "&projectid=-1"),
dataType: 'json',
- data: {
- forvpc: true
- },
+ data: data2,
async: true,
success: function(json) {
var items = json.listroutersresponse.router;
@@ -5743,10 +5775,16 @@
var searchByArgs = args.filterBy.search.value.length ?
'&name=' + args.filterBy.search.value : '';
+ var data2 = {};
+ if(cloudStack.context.zoneType != null && cloudStack.context.zoneType.length > 0) { //Basic type or Advanced type
+ $.extend(data2, {
+ zonetype: cloudStack.context.zoneType
+ });
+ }
var routers = [];
$.ajax({
url: createURL("listRouters&listAll=true&page=" + args.page + "&pagesize=" + pageSize + searchByArgs),
- dataType: 'json',
+ data: data2,
async: true,
success: function(json) {
var items = json.listroutersresponse.router ?
@@ -5759,7 +5797,7 @@
// Get project routers
$.ajax({
url: createURL("listRouters&listAll=true&page=" + args.page + "&pagesize=" + pageSize + "&projectid=-1"),
- dataType: 'json',
+ data: data2,
async: true,
success: function(json) {
var items = json.listroutersresponse.router ?
@@ -5843,12 +5881,18 @@
}
}
+ var data2 = {
+ forvpc: false
+ };
+ if(cloudStack.context.zoneType != null && cloudStack.context.zoneType.length > 0) { //Basic type or Advanced type
+ $.extend(data2, {
+ zonetype: cloudStack.context.zoneType
+ });
+ }
var routers = [];
$.ajax({
url: createURL("listRouters&zoneid=" + selectedZoneObj.id + "&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
- data: {
- forvpc: false
- },
+ data: data2,
success: function(json) {
var items = json.listroutersresponse.router ?
json.listroutersresponse.router : [];
@@ -5859,9 +5903,7 @@
// Get project routers
$.ajax({
url: createURL("listRouters&zoneid=" + selectedZoneObj.id + "&listAll=true&page=" + args.page + "&pagesize=" + pageSize + array1.join("") + "&projectid=-1"),
- data: {
- forvpc: false
- },
+ data: data2,
success: function(json) {
var items = json.listroutersresponse.router ?
json.listroutersresponse.router : [];