Merge branch 'master' into internallb1

Conflicts:
	server/src/com/cloud/network/NetworkModelImpl.java
	server/src/com/cloud/network/NetworkServiceImpl.java
	server/src/com/cloud/server/ManagementServerImpl.java
	server/test/com/cloud/network/MockNetworkManagerImpl.java
	server/test/com/cloud/vpc/MockNetworkManagerImpl.java
This commit is contained in:
Alena Prokharchyk 2013-05-03 11:23:08 -07:00
commit 1cff609347
84 changed files with 2085 additions and 467 deletions

View File

@ -0,0 +1,26 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.agent.api.storage;
import com.cloud.agent.api.Answer;
public class CreateVolumeOVAAnswer extends Answer {
public CreateVolumeOVAAnswer(CreateVolumeOVACommand cmd, boolean result, String details) {
super(cmd, result, details);
}
}

View File

@ -0,0 +1,60 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.agent.api.storage;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.to.StorageFilerTO;
import com.cloud.storage.StoragePool;
public class CreateVolumeOVACommand extends Command {
String secUrl;
String volPath;
String volName;
StorageFilerTO pool;
public CreateVolumeOVACommand() {
}
public CreateVolumeOVACommand(String secUrl, String volPath, String volName, StoragePool pool, int wait) {
this.secUrl = secUrl;
this.volPath = volPath;
this.volName = volName;
this.pool = new StorageFilerTO(pool);
setWait(wait);
}
@Override
public boolean executeInSequence() {
return true;
}
public String getVolPath() {
return this.volPath;
}
public String getVolName() {
return this.volName;
}
public String getSecondaryStorageUrl() {
return this.secUrl;
}
public StorageFilerTO getPool() {
return pool;
}
}

View File

@ -0,0 +1,26 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.agent.api.storage;
import com.cloud.agent.api.Answer;
public class PrepareOVAPackingAnswer extends Answer {
public PrepareOVAPackingAnswer(PrepareOVAPackingCommand cmd, boolean result, String details) {
super(cmd, result, details);
}
}

View File

@ -0,0 +1,48 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.agent.api.storage;
import com.cloud.agent.api.Command;
public class PrepareOVAPackingCommand extends Command {
private String templatePath;
private String secUrl;
public PrepareOVAPackingCommand() {
}
public PrepareOVAPackingCommand(String secUrl, String templatePath) {
this.secUrl = secUrl;
this.templatePath = templatePath;
}
@Override
public boolean executeInSequence() {
return true;
}
public String getTemplatePath() {
return this.templatePath;
}
public String getSecondaryStorageUrl() {
return this.secUrl;
}
}

View File

@ -138,6 +138,7 @@ public interface NetworkService {
ResourceAllocationException, ResourceUnavailableException, ConcurrentOperationException;
/**
*
* @param networkName
* @param displayText
* @param physicalNetworkId
@ -148,13 +149,14 @@ public interface NetworkService {
* @param netmask
* @param networkOwnerId
* @param vpcId TODO
* @param sourceNat
* @return
* @throws InsufficientCapacityException
* @throws ConcurrentOperationException
* @throws ResourceAllocationException
*/
Network createPrivateNetwork(String networkName, String displayText, long physicalNetworkId, String vlan,
String startIp, String endIP, String gateway, String netmask, long networkOwnerId, Long vpcId)
String startIp, String endIP, String gateway, String netmask, long networkOwnerId, Long vpcId, Boolean sourceNat)
throws ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException;
/* Requests an IP address for the guest nic */

View File

@ -67,7 +67,7 @@ public interface RulesService {
boolean applyPortForwardingRules(long ipAdddressId, Account caller) throws ResourceUnavailableException;
boolean enableStaticNat(long ipAddressId, long vmId, long networkId, boolean isSystemVm, String vmGuestIp) throws NetworkRuleConflictException, ResourceUnavailableException;
boolean enableStaticNat(long ipAddressId, long vmId, long networkId, String vmGuestIp) throws NetworkRuleConflictException, ResourceUnavailableException;
PortForwardingRule getPortForwardigRule(long ruleId);

View File

@ -44,5 +44,6 @@ public interface PrivateIp {
String getMacAddress();
long getNetworkId();
boolean getSourceNat();
}

View File

@ -77,4 +77,8 @@ public interface VpcGateway extends Identity, ControlledEntity, InternalIdentity
* @return
*/
State getState();
/**
* @return
*/
boolean getSourceNat();
}

View File

@ -163,6 +163,7 @@ public interface VpcService {
/**
* Persists VPC private gateway in the Database.
*
*
* @param vpcId TODO
* @param physicalNetworkId
* @param vlan
@ -170,13 +171,14 @@ public interface VpcService {
* @param gateway
* @param netmask
* @param gatewayOwnerId
* @param isSourceNat
* @return
* @throws InsufficientCapacityException
* @throws ConcurrentOperationException
* @throws ResourceAllocationException
*/
public PrivateGateway createVpcPrivateGateway(long vpcId, Long physicalNetworkId, String vlan, String ipAddress,
String gateway, String netmask, long gatewayOwnerId) throws ResourceAllocationException,
String gateway, String netmask, long gatewayOwnerId, Boolean isSourceNat) throws ResourceAllocationException,
ConcurrentOperationException, InsufficientCapacityException;
/**

View File

@ -451,6 +451,6 @@ public interface UserVmService {
UserVm restoreVM(RestoreVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException;
UserVm upgradeVirtualMachine(ScaleVMCmd scaleVMCmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException;
boolean upgradeVirtualMachine(ScaleVMCmd scaleVMCmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException;
}

View File

@ -69,6 +69,11 @@ public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd {
required=true, description="the VPC network belongs to")
private Long vpcId;
@Parameter(name=ApiConstants.SOURCE_NAT_SUPPORTED, type=CommandType.BOOLEAN, required=false,
description="source NAT supported value. Default value false. If 'true' source NAT is enabled on the private gateway" +
" 'false': sourcenat is not supported")
private Boolean isSourceNat;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -97,6 +102,13 @@ public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd {
return vpcId;
}
public Boolean getIsSourceNat () {
if (isSourceNat == null) {
return false;
}
return true;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@ -111,7 +123,7 @@ public class CreatePrivateGatewayCmd extends BaseAsyncCreateCmd {
PrivateGateway result = null;
try {
result = _vpcService.createVpcPrivateGateway(getVpcId(), getPhysicalNetworkId(),
getVlan(), getStartIp(), getGateway(), getNetmask(), getEntityOwnerId());
getVlan(), getStartIp(), getGateway(), getNetmask(), getEntityOwnerId(), getIsSourceNat());
} catch (InsufficientCapacityException ex){
s_logger.info(ex);
s_logger.trace(ex);

View File

@ -120,7 +120,7 @@ public class EnableStaticNatCmd extends BaseCmd{
@Override
public void execute() throws ResourceUnavailableException{
try {
boolean result = _rulesService.enableStaticNat(ipAddressId, virtualMachineId, getNetworkId(), false, getVmSecondaryIp());
boolean result = _rulesService.enableStaticNat(ipAddressId, virtualMachineId, getNetworkId(), getVmSecondaryIp());
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
this.setResponseObject(response);

View File

@ -163,6 +163,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
@Override
public void execute() {
s_logger.info("VOLSS: createSnapshotCmd starts:" + System.currentTimeMillis());
UserContext.current().setEventDetails("Volume Id: "+getVolumeId());
Snapshot snapshot = _snapshotService.createSnapshot(getVolumeId(), getPolicyId(), getEntityId(), _accountService.getAccount(getEntityOwnerId()));
if (snapshot != null) {
@ -172,6 +173,7 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd {
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create snapshot due to an internal error creating snapshot for volume " + volumeId);
}
s_logger.info("VOLSS: backupSnapshotCmd finishes:" + System.currentTimeMillis());
}

View File

@ -22,11 +22,12 @@ import com.cloud.user.UserContext;
import com.cloud.uservm.UserVm;
import org.apache.cloudstack.api.*;
import org.apache.cloudstack.api.response.ServiceOfferingResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.log4j.Logger;
@APICommand(name = "scaleVirtualMachine", description="Scales the virtual machine to a new service offering.", responseObject=UserVmResponse.class)
@APICommand(name = "scaleVirtualMachine", description="Scales the virtual machine to a new service offering.", responseObject=SuccessResponse.class)
public class ScaleVMCmd extends BaseCmd {
public static final Logger s_logger = Logger.getLogger(ScaleVMCmd.class.getName());
private static final String s_name = "scalevirtualmachineresponse";
@ -83,7 +84,7 @@ public class ScaleVMCmd extends BaseCmd {
@Override
public void execute(){
//UserContext.current().setEventDetails("Vm Id: "+getId());
UserVm result = null;
boolean result;
try {
result = _userVmService.upgradeVirtualMachine(this);
} catch (ResourceUnavailableException ex) {
@ -99,9 +100,8 @@ public class ScaleVMCmd extends BaseCmd {
s_logger.warn("Exception: ", ex);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
}
if (result != null){
UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", result).get(0);
response.setResponseName(getCommandName());
if (result){
SuccessResponse response = new SuccessResponse(getCommandName());
this.setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to scale vm");

View File

@ -37,11 +37,11 @@ import com.cloud.user.UserContext;
import com.cloud.uservm.UserVm;
import com.cloud.vm.snapshot.VMSnapshot;
@APICommand(name = "revertToSnapshot",description = "Revert VM from a vmsnapshot.", responseObject = UserVmResponse.class, since="4.2.0")
public class RevertToSnapshotCmd extends BaseAsyncCmd {
@APICommand(name = "revertToVMSnapshot",description = "Revert VM from a vmsnapshot.", responseObject = UserVmResponse.class, since="4.2.0")
public class RevertToVMSnapshotCmd extends BaseAsyncCmd {
public static final Logger s_logger = Logger
.getLogger(RevertToSnapshotCmd.class.getName());
private static final String s_name = "reverttosnapshotresponse";
.getLogger(RevertToVMSnapshotCmd.class.getName());
private static final String s_name = "reverttovmsnapshotresponse";
@Parameter(name = ApiConstants.VM_SNAPSHOT_ID, type = CommandType.UUID, required = true,entityType=VMSnapshotResponse.class,description = "The ID of the vm snapshot")
private Long vmSnapShotId;

View File

@ -76,6 +76,10 @@ public class PrivateGatewayResponse extends BaseResponse implements ControlledEn
private String state;
@SerializedName(ApiConstants.SOURCE_NAT_SUPPORTED) @Param(description = "Souce Nat enable status")
private Boolean sourceNat;
@Override
public String getObjectId() {
return this.id;
@ -145,5 +149,11 @@ public class PrivateGatewayResponse extends BaseResponse implements ControlledEn
public void setState(String state) {
this.state = state;
}
public void setSourceNat(Boolean sourceNat) {
this.sourceNat = sourceNat;
}
}

View File

@ -16,31 +16,20 @@
// under the License.
package org.apache.cloudstack.api.command.test;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
import com.cloud.uservm.UserVm;
import com.cloud.vm.UserVmService;
import junit.framework.Assert;
import junit.framework.TestCase;
import org.apache.cloudstack.api.ResponseGenerator;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.admin.region.AddRegionCmd;
import org.apache.cloudstack.api.command.user.vm.ScaleVMCmd;
import org.apache.cloudstack.api.response.RegionResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.region.Region;
import org.apache.cloudstack.region.RegionService;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public class ScaleVMCmdTest extends TestCase{
private ScaleVMCmd scaleVMCmd;
@ -57,12 +46,11 @@ public class ScaleVMCmdTest extends TestCase{
public Long getId() {
return 2L;
}
@Override
public String getCommandName() {
return "scalevirtualmachineresponse";
}
};
//Account account = new AccountVO("testaccount", 1L, "networkdomain", (short) 0, "uuid");
//UserContext.registerContext(1, account, null, true);
}
@ -71,11 +59,10 @@ public class ScaleVMCmdTest extends TestCase{
UserVmService userVmService = Mockito.mock(UserVmService.class);
UserVm uservm = Mockito.mock(UserVm.class);
try {
Mockito.when(
userVmService.upgradeVirtualMachine(scaleVMCmd))
.thenReturn(uservm);
.thenReturn(true);
}catch (Exception e){
Assert.fail("Received exception when success expected " +e.getMessage());
}
@ -83,13 +70,6 @@ public class ScaleVMCmdTest extends TestCase{
scaleVMCmd._userVmService = userVmService;
responseGenerator = Mockito.mock(ResponseGenerator.class);
UserVmResponse userVmResponse = Mockito.mock(UserVmResponse.class);
List<UserVmResponse> responseList = new ArrayList<UserVmResponse>();
responseList.add(userVmResponse);
Mockito.when(responseGenerator.createUserVmResponse("virtualmachine",uservm))
.thenReturn(responseList);
scaleVMCmd._responseGenerator = responseGenerator;
scaleVMCmd.execute();
@ -101,10 +81,9 @@ public class ScaleVMCmdTest extends TestCase{
UserVmService userVmService = Mockito.mock(UserVmService.class);
try {
UserVm uservm = Mockito.mock(UserVm.class);
Mockito.when(
userVmService.upgradeVirtualMachine(scaleVMCmd))
.thenReturn(null);
.thenReturn(false);
}catch (Exception e){
Assert.fail("Received exception when success expected " +e.getMessage());
}

View File

@ -569,7 +569,7 @@ removeFromGlobalLoadBalancerRule=15
listVMSnapshot=15
createVMSnapshot=15
deleteVMSnapshot=15
revertToSnapshot=15
revertToVMSnapshot=15
#### Baremetal commands
addBaremetalHost=1

View File

@ -863,13 +863,16 @@ public class VirtualRoutingResource implements Manager {
}
public void assignVpcIpToRouter(final String routerIP, final boolean add, final String pubIP,
final String nicname, final String gateway, final String netmask, final String subnet) throws InternalErrorException {
final String nicname, final String gateway, final String netmask, final String subnet, boolean sourceNat) throws InternalErrorException {
String args = "";
String snatArgs = "";
if (add) {
args += " -A ";
snatArgs += " -A ";
} else {
args += " -D ";
snatArgs += " -D ";
}
args += " -l ";
@ -887,6 +890,16 @@ public class VirtualRoutingResource implements Manager {
if (result != null) {
throw new InternalErrorException("KVM plugin \"vpc_ipassoc\" failed:"+result);
}
if (sourceNat) {
snatArgs += " -l " + pubIP;
snatArgs += " -c " + nicname;
result = routerProxy("vpc_privateGateway.sh", routerIP, snatArgs);
if (result != null) {
throw new InternalErrorException("KVM plugin \"vpc_privateGateway\" failed:"+result);
}
}
}
private SetStaticRouteAnswer execute(SetStaticRouteCommand cmd) {

View File

@ -21,6 +21,8 @@ import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.api.storage.CreateAnswer;
import com.cloud.agent.api.storage.CreateCommand;
import com.cloud.agent.api.storage.CreateVolumeOVAAnswer;
import com.cloud.agent.api.storage.CreateVolumeOVACommand;
import com.cloud.agent.api.storage.DestroyCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
@ -34,5 +36,7 @@ public interface StoragePoolResource {
CopyVolumeAnswer execute(CopyVolumeCommand cmd);
CreateVolumeOVAAnswer execute(CreateVolumeOVACommand cmd);
CreateAnswer execute(CreateCommand cmd);
}

View File

@ -21,16 +21,31 @@
<section id="elastic-ip">
<title>About Elastic IP</title>
<para>Elastic IP (EIP) addresses are the IP addresses that are associated with an account, and act
as static IP addresses. The account owner has complete control over the Elastic IP addresses
that belong to the account. You can allocate an Elastic IP to a VM of your choice from the EIP
pool of your account. Later if required you can reassign the IP address to a different VM. This
feature is extremely helpful during VM failure. Instead of replacing the VM which is down, the
IP address can be reassigned to a new VM in your account. Elastic IP service provides Static NAT
(1:1) service in an EIP-enabled basic zone. The default network offering,
as static IP addresses. The account owner has the complete control over the Elastic IP addresses
that belong to the account. As an account owner, you can allocate an Elastic IP to a VM of your
choice from the EIP pool of your account. Later if required you can reassign the IP address to a
different VM. This feature is extremely helpful during VM failure. Instead of replacing the VM
which is down, the IP address can be reassigned to a new VM in your account. </para>
<para>Similar to the public IP address, Elastic IP addresses are mapped to their associated
private IP addresses by using StaticNAT. The EIP service is equipped with StaticNAT (1:1)
service in an EIP-enabled basic zone. The default network offering,
DefaultSharedNetscalerEIPandELBNetworkOffering, provides your network with EIP and ELB network
services if a NetScaler device is deployed in your zone. Similar to the public IP address,
Elastic IP addresses are also mapped to their associated private IP addresses by using Stactic
NAT.</para>
services if a NetScaler device is deployed in your zone. Consider the following illustration for
more details.</para>
<mediaobject>
<imageobject>
<imagedata fileref="./images/eip-ns-basiczone.png"/>
</imageobject>
<textobject>
<phrase>eip-ns-basiczone.png: Elastic IP in a NetScaler-enabled Basic Zone.</phrase>
</textobject>
</mediaobject>
<para>In the illustration, a NetScaler appliance is the default entry or exit point for the
&PRODUCT; instances, and firewall is the default entry or exit point for the rest of the data
center. Netscaler provides LB services and staticNAT service to the guest networks. The guest
traffic in the pods and the Management Server are on different subnets / VLANs. The policy-based
routing in the data center core switch sends the public traffic through the NetScaler, whereas
the rest of the data center goes through the firewall. </para>
<para>The EIP work flow is as follows:</para>
<itemizedlist>
<listitem>
@ -48,7 +63,6 @@
supported by NetScaler, in which the source IP address is replaced in the packets
generated by a VM in the private network with the public IP address.</para>
</note>
<para/>
</listitem>
<listitem>
<para>This default public IP will be released in two cases:</para>
@ -68,12 +82,12 @@
</itemizedlist>
</listitem>
</itemizedlist>
<para>However, for the deployments where public IPs are limited resources, you have the
flexibility to choose not to allocate a public IP by default. You can use the Associate Public
IP option to turn on or off the automatic public IP assignment in the EIP-enabled Basic zones.
If you turn off the automatic public IP assignment while creating a network offering, only a
private IP is assigned to a VM when the VM is deployed with that network offering. Later, the
user can acquire an IP for the VM and enable static NAT.</para>
<para>For the deployments where public IPs are limited resources, you have the flexibility to
choose not to allocate a public IP by default. You can use the Associate Public IP option to
turn on or off the automatic public IP assignment in the EIP-enabled Basic zones. If you turn
off the automatic public IP assignment while creating a network offering, only a private IP is
assigned to a VM when the VM is deployed with that network offering. Later, the user can acquire
an IP for the VM and enable static NAT.</para>
<para condition="admin">For more information on the Associate Public IP option, see <xref
linkend="creating-network-offerings"/>.</para>
<para condition="install">For more information on the Associate Public IP option, see the
@ -83,7 +97,6 @@
continue to get both public IP and private by default, irrespective of the network offering
configuration.</para>
</note>
<para/>
<para>New deployments which use the default shared network offering with EIP and ELB services to
create a shared network in the Basic zone will continue allocating public IPs to each user
VM.</para>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -442,6 +442,9 @@ setup_dnsmasq() {
[ -z $DHCP_RANGE ] && [ $ETH0_IP ] && DHCP_RANGE=$ETH0_IP
[ $ETH0_IP6 ] && DHCP_RANGE_IP6=$ETH0_IP6
[ -z $DOMAIN ] && DOMAIN="cloudnine.internal"
#get the template
cp /etc/dnsmasq.conf.tmpl /etc/dnsmasq.conf
if [ -n "$DOMAIN" ]
then

View File

@ -91,7 +91,7 @@ fi
if [ "$Dflag" == "1" ]
then
remove_sat $publicIp
remove_snat $publicIp
unlock_exit $? $lock $locked
fi

View File

@ -113,7 +113,8 @@ if [ $ipv6 ]
then
sed -i /$ipv6,/d $DHCP_HOSTS
fi
sed -i /$host,/d $DHCP_HOSTS
# don't want to do this in the future, we can have same VM with multiple nics/entries
#sed -i /$host,/d $DHCP_HOSTS
#put in the new entry

View File

@ -1756,7 +1756,7 @@ ServerResource {
String netmask = Long.toString(NetUtils.getCidrSize(ip.getVlanNetmask()));
String subnet = NetUtils.getSubNet(ip.getPublicIp(), ip.getVlanNetmask());
_virtRouterResource.assignVpcIpToRouter(routerIP, ip.isAdd(), ip.getPublicIp(),
nicName, ip.getVlanGateway(), netmask, subnet);
nicName, ip.getVlanGateway(), netmask, subnet, ip.isSourceNat());
results[i++] = ip.getPublicIp() + " - success";
}

View File

@ -38,6 +38,8 @@ import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
import com.cloud.agent.api.UnregisterVMCommand;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.api.storage.CreateVolumeOVACommand;
import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.agent.api.to.NicTO;
import com.cloud.agent.api.to.VirtualMachineTO;
@ -282,10 +284,18 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
cmd instanceof CreatePrivateTemplateFromVolumeCommand ||
cmd instanceof CreatePrivateTemplateFromSnapshotCommand ||
cmd instanceof CopyVolumeCommand ||
cmd instanceof CreateVolumeOVACommand ||
cmd instanceof PrepareOVAPackingCommand ||
cmd instanceof CreateVolumeFromSnapshotCommand) {
needDelegation = true;
}
/* Fang: remove this before checking in */
// needDelegation = false;
if (cmd instanceof PrepareOVAPackingCommand ||
cmd instanceof CreateVolumeOVACommand ) {
cmd.setContextParam("hypervisor", HypervisorType.VMware.toString());
}
if(needDelegation) {
HostVO host = _hostDao.findById(hostId);
assert(host != null);
@ -311,6 +321,8 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru {
cmd instanceof CreatePrivateTemplateFromVolumeCommand ||
cmd instanceof CreatePrivateTemplateFromSnapshotCommand ||
cmd instanceof CopyVolumeCommand ||
cmd instanceof CreateVolumeOVACommand ||
cmd instanceof PrepareOVAPackingCommand ||
cmd instanceof CreateVolumeFromSnapshotCommand) {
String workerName = _vmwareMgr.composeWorkerName();

View File

@ -25,6 +25,8 @@ import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
import com.cloud.agent.api.DeleteVMSnapshotCommand;
import com.cloud.agent.api.RevertToVMSnapshotCommand;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
import com.cloud.agent.api.storage.CreateVolumeOVACommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
public interface VmwareStorageManager {
@ -33,6 +35,8 @@ public interface VmwareStorageManager {
Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromVolumeCommand cmd);
Answer execute(VmwareHostService hostService, CreatePrivateTemplateFromSnapshotCommand cmd);
Answer execute(VmwareHostService hostService, CopyVolumeCommand cmd);
Answer execute(VmwareHostService hostService, CreateVolumeOVACommand cmd);
Answer execute(VmwareHostService hostService, PrepareOVAPackingCommand cmd);
Answer execute(VmwareHostService hostService, CreateVolumeFromSnapshotCommand cmd);
Answer execute(VmwareHostService hostService, CreateVMSnapshotCommand cmd);
Answer execute(VmwareHostService hostService, DeleteVMSnapshotCommand cmd);

View File

@ -18,12 +18,14 @@ package com.cloud.hypervisor.vmware.manager;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.Map;
import java.util.UUID;
@ -44,6 +46,10 @@ import com.cloud.agent.api.RevertToVMSnapshotAnswer;
import com.cloud.agent.api.RevertToVMSnapshotCommand;
import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.api.storage.PrepareOVAPackingAnswer;
import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
import com.cloud.agent.api.storage.CreateVolumeOVAAnswer;
import com.cloud.agent.api.storage.CreateVolumeOVACommand;
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
@ -102,6 +108,109 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
_timeout = NumbersUtil.parseInt(value, 1440) * 1000;
}
//Fang note: use Answer here instead of the PrepareOVAPackingAnswer
@Override
public Answer execute(VmwareHostService hostService, PrepareOVAPackingCommand cmd) {
String secStorageUrl = ((PrepareOVAPackingCommand) cmd).getSecondaryStorageUrl();
assert (secStorageUrl != null);
String installPath = cmd.getTemplatePath();
String details = null;
boolean success = false;
String ovafileName = "";
s_logger.info("Fang: execute OVAPacking cmd at vmwareMngImpl. ");
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
// String installPath = getTemplateRelativeDirInSecStorage(accountId, templateId);
String installFullPath = secondaryMountPoint + "/" + installPath;
String templateName = installFullPath; // should be a file ending .ova;
s_logger.info("Fang: execute vmwareMgrImpl: templateNAme " + templateName);
// Fang: Dir list, if there is ova file, done; Fang: add answer cmd;
// if not, from ova.meta, create a new OVA file;
// change the install path to *.ova , not ova.meta;
// VmwareContext context = hostService.getServiceContext(cmd); //Fang: we may not have the CTX here
try {
if (templateName.endsWith(".ova")) {
if(new File(templateName).exists()) {
details = "OVA files exists. succeed. ";
return new Answer(cmd, true, details);
} else {
if (new File(templateName + ".meta").exists()) { //Fang parse the meta file
//execute the tar command;
s_logger.info("Fang: execute vmwareMgrImpl: getfromMeta " + templateName);
ovafileName = getOVAFromMetafile(templateName + ".meta");
details = "OVA file in meta file is " + ovafileName;
return new Answer(cmd, true, details);
} else {
String msg = "Unable to find ova meta or ova file to prepare template (vmware)";
s_logger.error(msg);
throw new Exception(msg);
}
}
}
} catch (Throwable e) {
if (e instanceof RemoteException) {
//hostService.invalidateServiceContext(context); do not need context
s_logger.error("Unable to connect to remote service ");
details = "Unable to connect to remote service ";
return new Answer(cmd, false, details);
}
String msg = "Unable to execute PrepareOVAPackingCommand due to exception";
s_logger.error(msg, e);
return new Answer(cmd, false, details);
}
return new Answer(cmd, true, details);
}
//Fang: new command added;
// Important! we need to sync file system before we can safely use tar to work around a linux kernal bug(or feature)
@Override
public Answer execute(VmwareHostService hostService, CreateVolumeOVACommand cmd) {
String secStorageUrl = ((CreateVolumeOVACommand) cmd).getSecondaryStorageUrl();
assert (secStorageUrl != null);
String installPath = cmd.getVolPath();
String details = null;
boolean success = false;
s_logger.info("volss: execute CreateVolumeOVA cmd at vmwareMngImpl. ");
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
// String installPath = getTemplateRelativeDirInSecStorage(accountId, templateId);
s_logger.info("volss: mountPoint: " + secondaryMountPoint + "installPath:" + installPath);
String installFullPath = secondaryMountPoint + "/" + installPath;
String volName = cmd.getVolName(); // should be a UUID, without ova ovf, etc;
s_logger.info("volss: execute vmwareMgrImpl: VolName " + volName);
// Fang: Dir list, if there is ova file, done; Note: add answer cmd;
try {
if(new File(volName + ".ova").exists()) {
details = "OVA files exists. succeed. ";
return new CreateVolumeOVAAnswer(cmd, true, details);
} else {
File ovaFile = new File(installFullPath);
String exportDir = ovaFile.getParent();
s_logger.info("Fang: exportDir is (for VolumeOVA): " + exportDir);
s_logger.info("Sync file system before we package OVA...");
Script commandSync = new Script(true, "sync", 0, s_logger);
commandSync.execute();
Script command = new Script(false, "tar", 0, s_logger);
command.setWorkDir(exportDir);
command.add("-cf", volName + ".ova");
command.add(volName + ".ovf"); // OVF file should be the first file in OVA archive
command.add(volName + "-disk0.vmdk");
s_logger.info("Package Volume OVA with commmand: " + command.toString());
command.execute();
return new CreateVolumeOVAAnswer(cmd, true, details);
}
} catch (Throwable e) {
s_logger.info("Exception for createVolumeOVA");
}
return new CreateVolumeOVAAnswer(cmd, true, "fail to pack OVA for volume");
}
@Override
public Answer execute(VmwareHostService hostService, PrimaryStorageDownloadCommand cmd) {
String secondaryStorageUrl = cmd.getSecondaryStorageUrl();
@ -570,11 +679,14 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
String installPath = getTemplateRelativeDirInSecStorage(accountId, templateId);
String installFullPath = secondaryMountPoint + "/" + installPath;
String installFullName = installFullPath + "/" + templateUniqueName + ".ova";
String snapshotFullName = secondaryMountPoint + "/" + getSnapshotRelativeDirInSecStorage(accountId, volumeId)
+ "/" + backedUpSnapshotUuid + ".ova";
String installFullOVAName = installFullPath + "/" + templateUniqueName + ".ova"; //Note: volss for tmpl
String snapshotRoot = secondaryMountPoint + "/" + getSnapshotRelativeDirInSecStorage(accountId, volumeId);
String snapshotFullOVAName = snapshotRoot + "/" + backedUpSnapshotUuid + ".ova";
String snapshotFullOvfName = snapshotRoot + "/" + backedUpSnapshotUuid + ".ovf";
String result;
Script command;
String templateVMDKName = "";
String snapshotFullVMDKName = snapshotRoot + "/";
synchronized(installPath.intern()) {
command = new Script(false, "mkdir", _timeout, s_logger);
@ -591,40 +703,85 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
}
try {
command = new Script(false, "cp", _timeout, s_logger);
command.add(snapshotFullName);
command.add(installFullName);
result = command.execute();
if(result != null) {
String msg = "unable to copy snapshot " + snapshotFullName + " to " + installFullPath;
if(new File(snapshotFullOVAName).exists()) {
command = new Script(false, "cp", _timeout, s_logger);
command.add(snapshotFullOVAName);
command.add(installFullOVAName);
result = command.execute();
if(result != null) {
String msg = "unable to copy snapshot " + snapshotFullOVAName + " to " + installFullPath;
s_logger.error(msg);
throw new Exception(msg);
}
// untar OVA file at template directory
command = new Script("tar", 0, s_logger);
command.add("--no-same-owner");
command.add("-xf", installFullOVAName);
command.setWorkDir(installFullPath);
s_logger.info("Executing command: " + command.toString());
result = command.execute();
if(result != null) {
String msg = "unable to untar snapshot " + snapshotFullOVAName + " to "
+ installFullPath;
s_logger.error(msg);
throw new Exception(msg);
}
} else { // there is no ova file, only ovf originally;
if(new File(snapshotFullOvfName).exists()) {
command = new Script(false, "cp", _timeout, s_logger);
command.add(snapshotFullOvfName);
//command.add(installFullOvfName);
command.add(installFullPath);
result = command.execute();
if(result != null) {
String msg = "unable to copy snapshot " + snapshotFullOvfName + " to " + installFullPath;
s_logger.error(msg);
throw new Exception(msg);
}
File snapshotdir = new File(snapshotRoot);
File[] ssfiles = snapshotdir.listFiles();
// List<String> filenames = new ArrayList<String>();
for (int i = 0; i < ssfiles.length; i++) {
String vmdkfile = ssfiles[i].getName();
if(vmdkfile.toLowerCase().startsWith(backedUpSnapshotUuid) && vmdkfile.toLowerCase().endsWith(".vmdk")) {
snapshotFullVMDKName += vmdkfile;
templateVMDKName += vmdkfile;
break;
}
}
if (snapshotFullVMDKName != null) {
command = new Script(false, "cp", _timeout, s_logger);
command.add(snapshotFullVMDKName);
command.add(installFullPath);
result = command.execute();
s_logger.info("Copy VMDK file: " + snapshotFullVMDKName);
if(result != null) {
String msg = "unable to copy snapshot vmdk file " + snapshotFullVMDKName + " to " + installFullPath;
s_logger.error(msg);
throw new Exception(msg);
}
}
} else {
String msg = "unable to find any snapshot ova/ovf files" + snapshotFullOVAName + " to " + installFullPath;
s_logger.error(msg);
throw new Exception(msg);
}
}
// untar OVA file at template directory
command = new Script("tar", 0, s_logger);
command.add("--no-same-owner");
command.add("-xf", installFullName);
command.setWorkDir(installFullPath);
s_logger.info("Executing command: " + command.toString());
result = command.execute();
if(result != null) {
String msg = "unable to untar snapshot " + snapshotFullName + " to "
+ installFullPath;
s_logger.error(msg);
throw new Exception(msg);
}
long physicalSize = new File(installFullPath + "/" + templateUniqueName + ".ova").length();
long physicalSize = new File(installFullPath + "/" + templateVMDKName).length();
VmdkProcessor processor = new VmdkProcessor();
// long physicalSize = new File(installFullPath + "/" + templateUniqueName + ".ova").length();
Map<String, Object> params = new HashMap<String, Object>();
params.put(StorageLayer.InstanceConfigKey, _storage);
processor.configure("VMDK Processor", params);
long virtualSize = processor.getTemplateVirtualSize(installFullPath, templateUniqueName);
postCreatePrivateTemplate(installFullPath, templateId, templateUniqueName, physicalSize, virtualSize);
writeMetaOvaForTemplate(installFullPath, backedUpSnapshotUuid + ".ovf", templateVMDKName, templateUniqueName, physicalSize);
return new Ternary<String, Long, Long>(installPath + "/" + templateUniqueName + ".ova", physicalSize, virtualSize);
} catch(Exception e) {
// TODO, clean up left over files
throw e;
@ -648,7 +805,8 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
out.newLine();
out.write("size=" + size);
out.newLine();
out.write("ova=true");
//out.write("ova=true");
out.write("ova=false"); //volss: the real ova file is not created
out.newLine();
out.write("id=" + templateId);
out.newLine();
@ -670,6 +828,31 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
}
}
private void writeMetaOvaForTemplate(String installFullPath, String ovfFilename, String vmdkFilename,
String templateName, long diskSize) throws Exception {
// TODO a bit ugly here
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(installFullPath + "/" + templateName +".ova.meta")));
out.write("ova.filename=" + templateName + ".ova");
out.newLine();
out.write("version=1.0");
out.newLine();
out.write("ovf=" + ovfFilename);
out.newLine();
out.write("numDisks=1");
out.newLine();
out.write("disk1.name=" + vmdkFilename);
out.newLine();
out.write("disk1.size=" + diskSize);
out.newLine();
} finally {
if(out != null)
out.close();
}
}
private String createVolumeFromSnapshot(VmwareHypervisorHost hyperHost, DatastoreMO primaryDsMo, String newVolumeName,
long accountId, long volumeId, String secStorageUrl, String snapshotBackupUuid) throws Exception {
@ -688,23 +871,35 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
if (backupName.contains("/")){
snapshotDir = backupName.split("/")[0];
}
String srcFileName = getOVFFilePath(srcOVAFileName);
if(srcFileName == null) {
Script command = new Script("tar", 0, s_logger);
command.add("--no-same-owner");
command.add("-xf", srcOVAFileName);
command.setWorkDir(secondaryMountPoint + "/" + secStorageDir + "/" + snapshotDir);
s_logger.info("Executing command: " + command.toString());
String result = command.execute();
if(result != null) {
String msg = "Unable to unpack snapshot OVA file at: " + srcOVAFileName;
s_logger.error(msg);
throw new Exception(msg);
}
}
srcFileName = getOVFFilePath(srcOVAFileName);
if(srcFileName == null) {
File ovafile = new File(srcOVAFileName);
String srcOVFFileName = secondaryMountPoint + "/" + secStorageDir + "/"
+ backupName + ".ovf";
File ovfFile = new File(srcOVFFileName);
// String srcFileName = getOVFFilePath(srcOVAFileName);
if (!ovfFile.exists()) {
srcOVFFileName = getOVFFilePath(srcOVAFileName);
if(srcOVFFileName == null && ovafile.exists() ) { // volss: ova file exists; o/w can't do tar
Script command = new Script("tar", 0, s_logger);
command.add("--no-same-owner");
command.add("-xf", srcOVAFileName);
command.setWorkDir(secondaryMountPoint + "/" + secStorageDir + "/" + snapshotDir);
s_logger.info("Executing command: " + command.toString());
String result = command.execute();
if(result != null) {
String msg = "Unable to unpack snapshot OVA file at: " + srcOVAFileName;
s_logger.error(msg);
throw new Exception(msg);
}
} else {
String msg = "Unable to find snapshot OVA file at: " + srcOVAFileName;
s_logger.error(msg);
throw new Exception(msg);
}
srcOVFFileName = getOVFFilePath(srcOVAFileName);
}
if(srcOVFFileName == null) {
String msg = "Unable to locate OVF file in template package directory: " + srcOVAFileName;
s_logger.error(msg);
throw new Exception(msg);
@ -712,7 +907,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
VirtualMachineMO clonedVm = null;
try {
hyperHost.importVmFromOVF(srcFileName, newVolumeName, primaryDsMo, "thin");
hyperHost.importVmFromOVF(srcOVFFileName, newVolumeName, primaryDsMo, "thin");
clonedVm = hyperHost.findVmOnHyperHost(newVolumeName);
if(clonedVm == null)
throw new Exception("Unable to create container VM for volume creation");
@ -774,7 +969,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
throw new Exception(msg);
}
clonedVm.exportVm(exportPath, exportName, true, true);
clonedVm.exportVm(exportPath, exportName, false, false); //Note: volss: not to create ova.
} finally {
if(clonedVm != null) {
clonedVm.detachAllDisks();
@ -787,17 +982,31 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl);
String snapshotMountRoot = secondaryMountPoint + "/" + getSnapshotRelativeDirInSecStorage(accountId, volumeId);
File file = new File(snapshotMountRoot + "/" + backupUuid + ".ova");
File file = new File(snapshotMountRoot + "/" + backupUuid + ".ovf");
if(file.exists()) {
if(file.delete())
return null;
} else {
return "Backup file does not exist. backupUuid: " + backupUuid;
}
return "Failed to delete snapshot backup file, backupUuid: " + backupUuid;
}
File snapshotdir = new File(snapshotMountRoot);
File[] ssfiles = snapshotdir.listFiles();
// List<String> filenames = new ArrayList<String>();
for (int i = 0; i < ssfiles.length; i++) {
String vmdkfile = ssfiles[i].getName();
if(vmdkfile.toLowerCase().startsWith(backupUuid) && vmdkfile.toLowerCase().endsWith(".vmdk")) {
// filenames.add(vmdkfile);
new File(vmdkfile).delete();
}
}
if(file.delete())
return null;
} else {
File file1 = new File(snapshotMountRoot + "/" + backupUuid + ".ova");
if(file1.exists()) {
if(file1.delete())
return null;
} else {
return "Backup file does not exist. backupUuid: " + backupUuid;
}
}
return "Failed to delete snapshot backup file, backupUuid: " + backupUuid;
}
private Pair<String, String> copyVolumeToSecStorage(VmwareHostService hostService, VmwareHypervisorHost hyperHost, CopyVolumeCommand cmd,
String vmName, long volumeId, String poolId, String volumePath,
@ -881,6 +1090,92 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager {
return new Pair<String, String>(volumeFolder, newVolume);
}
//Fang: here I use a method to return the ovf and vmdk file names; Another way to do it:
// create a new class, and like TemplateLocation.java and create templateOvfInfo.java to handle it;
private String getOVAFromMetafile(String metafileName) throws Exception {
File ova_metafile = new File(metafileName);
Properties props = null;
FileInputStream strm = null;
String ovaFileName = "";
s_logger.info("Fang: getOVAfromMetaFile: metafileName " + metafileName);
try {
strm = new FileInputStream(ova_metafile);
if (null == strm) {
String msg = "Cannot read ova meat file. Error";
s_logger.error(msg);
throw new Exception(msg);
}
s_logger.info("Fang: getOVAfromMetaFile: load strm " );
if (null != ova_metafile) {
props = new Properties();
props.load(strm);
if (props == null) {
s_logger.info("Fang: getOVAfromMetaFile: props is null. " );
}
}
if (null != props) {
ovaFileName = props.getProperty("ova.filename");
s_logger.info("Fang: ovafilename" + ovaFileName);
String ovfFileName = props.getProperty("ovf");
s_logger.info("Fang: ovffilename" + ovfFileName);
int diskNum = Integer.parseInt(props.getProperty("numDisks"));
if (diskNum <= 0) {
String msg = "VMDK disk file number is 0. Error";
s_logger.error(msg);
throw new Exception(msg);
}
String[] disks = new String[diskNum];
for (int i = 0; i < diskNum; i++) {
//String diskNameKey = "disk" + Integer.toString(i+1) + ".name"; // Fang use this
String diskNameKey = "disk1.name";
disks[i] = props.getProperty(diskNameKey);
s_logger.info("Fang: diskname " + disks[i]);
}
String exportDir = ova_metafile.getParent();
s_logger.info("Fang: exportDir: " + exportDir);
// Important! we need to sync file system before we can safely use tar to work around a linux kernal bug(or feature)
s_logger.info("Fang: Sync file system before we package OVA..., before tar ");
s_logger.info("Fang: ova: " + ovaFileName+ ", ovf:" + ovfFileName + ", vmdk:" + disks[0] + ".");
Script commandSync = new Script(true, "sync", 0, s_logger);
commandSync.execute();
Script command = new Script(false, "tar", 0, s_logger);
command.setWorkDir(exportDir); //Fang: pass this in to the method?
command.add("-cf", ovaFileName);
command.add(ovfFileName); // OVF file should be the first file in OVA archive
for(String diskName: disks) {
command.add(diskName);
}
command.execute();
s_logger.info("Fang: Package OVA for template in dir: " + exportDir + "cmd: " + command.toString());
// to be safe, physically test existence of the target OVA file
if((new File(exportDir + ovaFileName)).exists()) {
s_logger.info("Fang: ova file is created and ready to extract ");
return (ovaFileName);
} else {
String msg = exportDir + File.separator + ovaFileName + ".ova is not created as expected";
s_logger.error(msg);
throw new Exception(msg);
}
} else {
String msg = "Error reading the ova meta file: " + metafileName;
s_logger.error(msg);
throw new Exception(msg);
}
} catch (Exception e) {
return null;
//Do something, re-throw the exception
} finally {
if (strm != null) {
try {
strm.close();
} catch (Exception e) {
}
}
}
}
private String getOVFFilePath(String srcOVAFileName) {
File file = new File(srcOVAFileName);
assert(_storage != null);

View File

@ -155,6 +155,10 @@ import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.agent.api.routing.VpnUsersCfgCommand;
import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.api.storage.CreateVolumeOVACommand;
import com.cloud.agent.api.storage.CreateVolumeOVAAnswer;
import com.cloud.agent.api.storage.PrepareOVAPackingAnswer;
import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
import com.cloud.agent.api.storage.CreateAnswer;
import com.cloud.agent.api.storage.CreateCommand;
import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
@ -392,6 +396,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
answer = execute((DeleteStoragePoolCommand) cmd);
} else if (clz == CopyVolumeCommand.class) {
answer = execute((CopyVolumeCommand) cmd);
} else if (clz == CreateVolumeOVACommand.class) {
answer = execute((CreateVolumeOVACommand) cmd);
} else if (clz == PrepareOVAPackingCommand.class) {
answer = execute((PrepareOVAPackingCommand) cmd);
} else if (clz == AttachVolumeCommand.class) {
answer = execute((AttachVolumeCommand) cmd);
} else if (clz == AttachIsoCommand.class) {
@ -1433,10 +1441,14 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
String args = "";
String snatArgs = "";
if (ip.isAdd()) {
args += " -A ";
snatArgs += " -A ";
} else {
args += " -D ";
snatArgs += " -D ";
}
args += " -l ";
@ -1460,6 +1472,21 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
if (!result.first()) {
throw new InternalErrorException("Unable to assign public IP address");
}
if (ip.isSourceNat()) {
snatArgs += " -l ";
snatArgs += ip.getPublicIp();
snatArgs += " -c ";
snatArgs += "eth" + ethDeviceNum;
Pair<Boolean, String> result_gateway = SshHelper.sshExecute(routerIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null,
"/opt/cloud/bin/vpc_privateGateway.sh " + args);
if (!result_gateway.first()) {
throw new InternalErrorException("Unable to configure source NAT for public IP address.");
}
}
}
protected void assignPublicIpAddress(VirtualMachineMO vmMo, final String vmName, final String privateIpAddress, final String publicIpAddress, final boolean add, final boolean firstIP,
@ -3905,8 +3932,48 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
}
}
public CreateVolumeOVAAnswer execute(CreateVolumeOVACommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource CreateVolumeOVACommand: " + _gson.toJson(cmd));
}
try {
VmwareContext context = getServiceContext();
VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
return (CreateVolumeOVAAnswer) mgr.getStorageManager().execute(this, cmd);
} catch (Throwable e) {
if (e instanceof RemoteException) {
s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
invalidateServiceContext();
}
String msg = "CreateVolumeOVACommand failed due to " + VmwareHelper.getExceptionMessage(e);
s_logger.error(msg, e);
return new CreateVolumeOVAAnswer(cmd, false, msg);
}
}
protected Answer execute(PrepareOVAPackingCommand cmd) {
if (s_logger.isInfoEnabled()) {
s_logger.info("Executing resource PrepareOVAPackingCommand: " + _gson.toJson(cmd));
}
try {
VmwareContext context = getServiceContext();
VmwareManager mgr = context.getStockObject(VmwareManager.CONTEXT_STOCK_NAME);
return mgr.getStorageManager().execute(this, cmd);
} catch (Throwable e) {
if (e instanceof RemoteException) {
s_logger.warn("Encounter remote exception to vCenter, invalidate VMware session context");
invalidateServiceContext();
}
String details = "PrepareOVAPacking for template failed due to " + VmwareHelper.getExceptionMessage(e);
s_logger.error(details, e);
return new PrepareOVAPackingAnswer(cmd, false, details);
}
}
private boolean createVMFullClone(VirtualMachineMO vmTemplate, DatacenterMO dcMo, DatastoreMO dsMo,
String vmdkName, ManagedObjectReference morDatastore, ManagedObjectReference morPool) throws Exception {

View File

@ -28,6 +28,9 @@ import com.cloud.agent.api.CreatePrivateTemplateFromSnapshotCommand;
import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
import com.cloud.agent.api.CreateVolumeFromSnapshotCommand;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.api.storage.CreateVolumeOVAAnswer;
import com.cloud.agent.api.storage.CreateVolumeOVACommand;
import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
import com.cloud.hypervisor.vmware.manager.VmwareHostService;
import com.cloud.hypervisor.vmware.manager.VmwareStorageManager;
@ -76,6 +79,10 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
answer = execute((CreatePrivateTemplateFromSnapshotCommand)cmd);
} else if(cmd instanceof CopyVolumeCommand) {
answer = execute((CopyVolumeCommand)cmd);
} else if(cmd instanceof CreateVolumeOVACommand) {
answer = execute((CreateVolumeOVACommand)cmd);
} else if (cmd instanceof PrepareOVAPackingCommand) {
answer = execute((PrepareOVAPackingCommand)cmd);
} else if(cmd instanceof CreateVolumeFromSnapshotCommand) {
answer = execute((CreateVolumeFromSnapshotCommand)cmd);
} else {
@ -138,6 +145,23 @@ public class VmwareSecondaryStorageResourceHandler implements SecondaryStorageRe
return _storageMgr.execute(this, cmd);
}
private Answer execute(PrepareOVAPackingCommand cmd) {
s_logger.info("Fang: VmwareSecStorageResourceHandler: exec cmd. cmd is " + cmd.toString());
if (s_logger.isDebugEnabled()) {
s_logger.debug("Executing resource PrepareOVAPackingCommand: " + _gson.toJson(cmd));
}
return _storageMgr.execute(this, cmd);
}
private CreateVolumeOVAAnswer execute(CreateVolumeOVACommand cmd) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Executing resource CreateVolumeOVACommand: " + _gson.toJson(cmd));
}
return (CreateVolumeOVAAnswer) _storageMgr.execute(this, cmd);
}
private Answer execute(CreateVolumeFromSnapshotCommand cmd) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Executing resource CreateVolumeFromSnapshotCommand: " + _gson.toJson(cmd));

View File

@ -2217,11 +2217,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
}
String args = "vpc_ipassoc.sh " + routerIp;
String snatArgs = "vpc_privateGateway.sh " + routerIp;
if (ip.isAdd()) {
args += " -A ";
snatArgs += " -A ";
} else {
args += " -D ";
snatArgs+= " -D ";
}
args += " -l ";
@ -2244,6 +2247,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
if (result == null || result.isEmpty()) {
throw new InternalErrorException("Xen plugin \"vpc_ipassoc\" failed.");
}
if (ip.isSourceNat()) {
snatArgs += " -l " + ip.getPublicIp();
snatArgs += " -c " + "eth" + correctVif.getDevice(conn);
result = callHostPlugin(conn, "vmops", "routerProxy", "args", snatArgs);
if (result == null || result.isEmpty()) {
throw new InternalErrorException("Xen plugin \"vcp_privateGateway\" failed.");
}
}
} catch (Exception e) {
String msg = "Unable to assign public IP address due to " + e.toString();
s_logger.warn(msg, e);

View File

@ -35,6 +35,8 @@ import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.routing.GlobalLoadBalancerConfigCommand;
import com.cloud.agent.api.routing.HealthCheckLBConfigAnswer;
import com.cloud.agent.api.routing.HealthCheckLBConfigCommand;
import com.cloud.agent.api.routing.LoadBalancerConfigCommand;
import com.cloud.agent.api.routing.SetStaticNatRulesAnswer;
import com.cloud.agent.api.routing.SetStaticNatRulesCommand;
@ -714,7 +716,7 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl
List<LbDestination> destinations = rule.getDestinations();
if ((destinations != null && !destinations.isEmpty()) || rule.isAutoScaleConfig()) {
LoadBalancerTO loadBalancer = new LoadBalancerTO(lbUuid, srcIp, srcPort, protocol, algorithm, revoked, false, false, destinations, rule.getStickinessPolicies());
LoadBalancerTO loadBalancer = new LoadBalancerTO(lbUuid, srcIp, srcPort, protocol, algorithm, revoked, false, false, destinations, rule.getStickinessPolicies(), rule.getHealthCheckPolicies());
if (rule.isAutoScaleConfig()) {
loadBalancer.setAutoScaleVmGroup(rule.getAutoScaleVmGroup());
}
@ -840,11 +842,75 @@ public class NetscalerElement extends ExternalLoadBalancerDeviceManagerImpl impl
return null;
}
public List<LoadBalancerTO> getElasticLBRulesHealthCheck(Network network, List<? extends FirewallRule> rules)
throws ResourceUnavailableException {
HealthCheckLBConfigAnswer answer = null;
List<LoadBalancingRule> loadBalancingRules = new ArrayList<LoadBalancingRule>();
for (FirewallRule rule : rules) {
if (rule.getPurpose().equals(Purpose.LoadBalancing)) {
loadBalancingRules.add((LoadBalancingRule) rule);
}
}
if (loadBalancingRules == null || loadBalancingRules.isEmpty()) {
return null;
}
String errMsg = null;
ExternalLoadBalancerDeviceVO lbDeviceVO = getExternalLoadBalancerForNetwork(network);
if (lbDeviceVO == null) {
s_logger.warn("There is no external load balancer device assigned to this network either network is not implement are already shutdown so just returning");
return null;
}
if (!isNetscalerDevice(lbDeviceVO.getDeviceName())) {
errMsg = "There are no NetScaler load balancer assigned for this network. So NetScaler element can not be handle elastic load balancer rules.";
s_logger.error(errMsg);
throw new ResourceUnavailableException(errMsg, this.getClass(), 0);
}
List<LoadBalancerTO> loadBalancersToApply = new ArrayList<LoadBalancerTO>();
for (int i = 0; i < loadBalancingRules.size(); i++) {
LoadBalancingRule rule = loadBalancingRules.get(i);
boolean revoked = (rule.getState().equals(FirewallRule.State.Revoke));
String protocol = rule.getProtocol();
String algorithm = rule.getAlgorithm();
String lbUuid = rule.getUuid();
String srcIp = _networkMgr.getIp(rule.getSourceIpAddressId()).getAddress().addr();
int srcPort = rule.getSourcePortStart();
List<LbDestination> destinations = rule.getDestinations();
if ((destinations != null && !destinations.isEmpty()) || rule.isAutoScaleConfig()) {
LoadBalancerTO loadBalancer = new LoadBalancerTO(lbUuid, srcIp, srcPort, protocol, algorithm, revoked,
false, false, destinations, null, rule.getHealthCheckPolicies());
loadBalancersToApply.add(loadBalancer);
}
}
if (loadBalancersToApply.size() > 0) {
int numLoadBalancersForCommand = loadBalancersToApply.size();
LoadBalancerTO[] loadBalancersForCommand = loadBalancersToApply
.toArray(new LoadBalancerTO[numLoadBalancersForCommand]);
HealthCheckLBConfigCommand cmd = new HealthCheckLBConfigCommand(loadBalancersForCommand);
HostVO externalLoadBalancer = _hostDao.findById(lbDeviceVO.getHostId());
answer = (HealthCheckLBConfigAnswer) _agentMgr.easySend(externalLoadBalancer.getId(), cmd);
return answer.getLoadBalancers();
}
return null;
}
public List<LoadBalancerTO> updateHealthChecks(Network network, List<LoadBalancingRule> lbrules) {
if (canHandle(network, Service.Lb) && canHandleLbRules(lbrules)) {
try {
return getLBHealthChecks(network, lbrules);
if (isBasicZoneNetwok(network)) {
return getElasticLBRulesHealthCheck(network, lbrules);
} else {
return getLBHealthChecks(network, lbrules);
}
} catch (ResourceUnavailableException e) {
s_logger.error("Error in getting the LB Rules from NetScaler " + e);
}

View File

@ -1618,7 +1618,9 @@ public class NetscalerResource implements ServerResource {
String srcIp = rule.getSrcIp();
String dstIP = rule.getDstIp();
String iNatRuleName = generateInatRuleName(srcIp, dstIP);
String rNatRuleName = generateRnatRuleName(srcIp, dstIP);
inat iNatRule = null;
rnat rnatRule = null;
if (!rule.revoked()) {
try {
@ -1645,9 +1647,47 @@ public class NetscalerResource implements ServerResource {
}
s_logger.debug("Created Inat rule on the Netscaler device " + _ip + " to enable static NAT from " + srcIp + " to " + dstIP);
}
try {
rnat[] rnatRules = rnat.get(_netscalerService);
if (rnatRules != null) {
for (rnat rantrule : rnatRules) {
if (rantrule.get_network().equalsIgnoreCase(rNatRuleName)) {
rnatRule = rantrule;
break;
}
}
}
} catch (nitro_exception e) {
throw e;
}
if (rnatRule == null) {
rnatRule = new rnat();
rnatRule.set_natip(srcIp);
rnatRule.set_network(dstIP);
rnatRule.set_netmask("255.255.255.255");
try {
apiCallResult = rnat.update(_netscalerService, rnatRule);
} catch (nitro_exception e) {
if (e.getErrorCode() != NitroError.NS_RESOURCE_EXISTS) {
throw e;
}
}
s_logger.debug("Created Rnat rule on the Netscaler device " + _ip + " to enable revese static NAT from " + dstIP + " to " + srcIp);
}
} else {
try {
inat.delete(_netscalerService, iNatRuleName);
rnat[] rnatRules = rnat.get(_netscalerService);
if (rnatRules != null) {
for (rnat rantrule : rnatRules) {
if (rantrule.get_network().equalsIgnoreCase(dstIP)) {
rnatRule = rantrule;
rnat.clear(_netscalerService, rnatRule);
break;
}
}
}
} catch (nitro_exception e) {
if (e.getErrorCode() != NitroError.NS_RESOURCE_NOT_EXISTS) {
throw e;
@ -2257,6 +2297,7 @@ public class NetscalerResource implements ServerResource {
}
csMon.set_interval(hcp.getHealthcheckInterval());
csMon.set_retries(Math.max(hcp.getHealthcheckThresshold(), hcp.getUnhealthThresshold()) + 1);
csMon.set_resptimeout(hcp.getResponseTime());
csMon.set_failureretries(hcp.getUnhealthThresshold());
csMon.set_successretries(hcp.getHealthcheckThresshold());
@ -3090,6 +3131,10 @@ public class NetscalerResource implements ServerResource {
return genObjectName("Cloud-Inat", srcIp);
}
private String generateRnatRuleName(String srcIp, String dstIP) {
return genObjectName("Cloud-Rnat", srcIp);
}
private String generateNSVirtualServerName(String srcIp, long srcPort) {
return genObjectName("Cloud-VirtualServer", srcIp, srcPort);
}

View File

@ -399,7 +399,7 @@
<exclude>patches/systemvm/debian/config/etc/apache2/sites-available/default</exclude>
<exclude>patches/systemvm/debian/config/etc/apache2/sites-available/default-ssl</exclude>
<exclude>patches/systemvm/debian/config/etc/apache2/vhostexample.conf</exclude>
<exclude>patches/systemvm/debian/config/etc/dnsmasq.conf</exclude>
<exclude>patches/systemvm/debian/config/etc/dnsmasq.conf.tmpl</exclude>
<exclude>patches/systemvm/debian/config/etc/vpcdnsmasq.conf</exclude>
<exclude>patches/systemvm/debian/config/etc/ssh/sshd_config</exclude>
<exclude>patches/systemvm/debian/config/etc/rsyslog.conf</exclude>

View File

@ -3145,6 +3145,7 @@ public class ApiResponseHelper implements ResponseGenerator {
populateAccount(response, result.getAccountId());
populateDomain(response, result.getDomainId());
response.setState(result.getState().toString());
response.setSourceNat(result.getSourceNat());
response.setObjectName("privategateway");

View File

@ -270,7 +270,7 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase
lbDeviceVO = new ExternalLoadBalancerDeviceVO(host.getId(), pNetwork.getId(), ntwkDevice.getNetworkServiceProvder(),
deviceName, capacity, dedicatedUse, gslbProvider);
if (gslbProvider) {
lbDeviceVO.setGslbSitePrivateIP(gslbSitePublicIp);
lbDeviceVO.setGslbSitePublicIP(gslbSitePublicIp);
lbDeviceVO.setGslbSitePrivateIP(gslbSitePrivateIp);
}
_externalLoadBalancerDeviceDao.persist(lbDeviceVO);

View File

@ -930,9 +930,9 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel {
}
}
if (isUserVmsDefaultNetwork || isDomRGuestOrPublicNetwork) {
return _configMgr.getServiceOfferingNetworkRate(vm.getServiceOfferingId(), vm.getDataCenterId());
return _configMgr.getServiceOfferingNetworkRate(vm.getServiceOfferingId(), network.getDataCenterId());
} else {
return _configMgr.getNetworkOfferingNetworkRate(ntwkOff.getId(), vm.getDataCenterId());
return _configMgr.getNetworkOfferingNetworkRate(ntwkOff.getId(), network.getDataCenterId());
}
}
@ -1669,20 +1669,17 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel {
String[] cidr = network.getCidr().split("/");
List<String> ips = getUsedIpsInNetwork(network);
Set<Long> usedIps = new TreeSet<Long>();
for (String ip : ips) {
if (requestedIp != null && requestedIp.equals(ip)) {
s_logger.warn("Requested ip address " + requestedIp + " is already in use in network" + network);
return null;
}
usedIps.add(NetUtils.ip2Long(ip));
}
Set<Long> allPossibleIps = NetUtils.getAllIpsFromCidr(cidr[0], Integer.parseInt(cidr[1]));
if (usedIps.size() != 0) {
allPossibleIps.removeAll(usedIps);
}
Set<Long> allPossibleIps = NetUtils.getAllIpsFromCidr(cidr[0], Integer.parseInt(cidr[1]), usedIps);
String gateway = network.getGateway();
if ((gateway != null) && (allPossibleIps.contains(NetUtils.ip2Long(gateway))))

View File

@ -30,6 +30,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import javax.ejb.Local;
@ -490,17 +491,19 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
}
// if shared network in the advanced zone, then check the caller against the network for 'AccessType.UseNetwork'
if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId()) && zone.getNetworkType() == NetworkType.Advanced) {
Account caller = UserContext.current().getCaller();
long callerUserId = UserContext.current().getCallerUserId();
_accountMgr.checkAccess(caller, AccessType.UseNetwork, false, network);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId());
if (zone.getNetworkType() == NetworkType.Advanced) {
if (isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) {
Account caller = UserContext.current().getCaller();
long callerUserId = UserContext.current().getCallerUserId();
_accountMgr.checkAccess(caller, AccessType.UseNetwork, false, network);
if (s_logger.isDebugEnabled()) {
s_logger.debug("Associate IP address called by the user " + callerUserId + " account " + ipOwner.getId());
}
return _networkMgr.allocateIp(ipOwner, false, caller, callerUserId, zone);
} else {
throw new InvalidParameterValueException("Associate IP address can only be called on the shared networks in the advanced zone" +
" with Firewall/Source Nat/Static Nat/Port Forwarding/Load balancing services enabled");
}
return _networkMgr.allocateIp(ipOwner, false, caller, callerUserId, zone);
} else {
throw new InvalidParameterValueException("Associate IP address can only be called on the shared networks in the advanced zone" +
" with Firewall/Source Nat/Static Nat/Port Forwarding/Load balancing services enabled");
}
}
}
@ -2128,6 +2131,29 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
return getNetwork(network.getId());
}
protected Set<Long> getAvailableIps(Network network, String requestedIp) {
String[] cidr = network.getCidr().split("/");
List<String> ips = _nicDao.listIpAddressInNetwork(network.getId());
Set<Long> usedIps = new TreeSet<Long>();
for (String ip : ips) {
if (requestedIp != null && requestedIp.equals(ip)) {
s_logger.warn("Requested ip address " + requestedIp + " is already in use in network" + network);
return null;
}
usedIps.add(NetUtils.ip2Long(ip));
}
Set<Long> allPossibleIps = NetUtils.getAllIpsFromCidr(cidr[0], Integer.parseInt(cidr[1]), usedIps);
String gateway = network.getGateway();
if ((gateway != null) && (allPossibleIps.contains(NetUtils.ip2Long(gateway))))
allPossibleIps.remove(NetUtils.ip2Long(gateway));
return allPossibleIps;
}
protected boolean canUpgrade(Network network, long oldNetworkOfferingId, long newNetworkOfferingId) {
NetworkOffering oldNetworkOffering = _networkOfferingDao.findByIdIncludingRemoved(oldNetworkOfferingId);
@ -3379,8 +3405,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
@Override @DB
public Network createPrivateNetwork(String networkName, String displayText, long physicalNetworkId,
String vlan, String startIp, String endIp, String gateway, String netmask, long networkOwnerId, Long vpcId)
public Network createPrivateNetwork(String networkName, String displayText, long physicalNetworkId,
String vlan, String startIp, String endIp, String gateway, String netmask, long networkOwnerId, Long vpcId, Boolean sourceNat)
throws ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException {
Account owner = _accountMgr.getAccount(networkOwnerId);
@ -3448,7 +3474,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
Long nextMac = mac + 1;
dc.setMacAddress(nextMac);
privateIp = new PrivateIpVO(startIp, privateNetwork.getId(), nextMac, vpcId);
privateIp = new PrivateIpVO(startIp, privateNetwork.getId(), nextMac, vpcId, sourceNat);
_privateIpDao.persist(privateIp);
_dcDao.update(dc.getId(), dc);

View File

@ -1178,8 +1178,8 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian
for (final PrivateIpAddress ipAddr : ipAddrList) {
Network network = _networkModel.getNetwork(ipAddr.getNetworkId());
IpAddressTO ip = new IpAddressTO(Account.ACCOUNT_ID_SYSTEM, ipAddr.getIpAddress(), add, false,
false, ipAddr.getVlanTag(), ipAddr.getGateway(), ipAddr.getNetmask(), ipAddr.getMacAddress(),
IpAddressTO ip = new IpAddressTO(Account.ACCOUNT_ID_SYSTEM, ipAddr.getIpAddress(), add, false,
ipAddr.getSourceNat(), ipAddr.getVlanTag(), ipAddr.getGateway(), ipAddr.getNetmask(), ipAddr.getMacAddress(),
null, false);
ip.setTrafficType(network.getTrafficType());

View File

@ -80,12 +80,14 @@ import com.cloud.utils.net.Ip;
import com.cloud.vm.Nic;
import com.cloud.vm.NicSecondaryIp;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.NicSecondaryIpDao;
import com.cloud.vm.dao.NicSecondaryIpVO;
import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.VMInstanceDao;
@Component
@Local(value = { RulesManager.class, RulesService.class })
@ -103,6 +105,8 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
@Inject
UserVmDao _vmDao;
@Inject
VMInstanceDao _vmInstanceDao;
@Inject
AccountManager _accountMgr;
@Inject
NetworkManager _networkMgr;
@ -416,7 +420,12 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
@Override
@ActionEvent(eventType = EventTypes.EVENT_ENABLE_STATIC_NAT, eventDescription = "enabling static nat")
public boolean enableStaticNat(long ipId, long vmId, long networkId, boolean isSystemVm, String vmGuestIp)
public boolean enableStaticNat(long ipId, long vmId, long networkId, String vmGuestIp)
throws NetworkRuleConflictException, ResourceUnavailableException {
return enableStaticNat(ipId, vmId, networkId, false, vmGuestIp);
}
private boolean enableStaticNat(long ipId, long vmId, long networkId, boolean isSystemVm, String vmGuestIp)
throws NetworkRuleConflictException, ResourceUnavailableException {
UserContext ctx = UserContext.current();
Account caller = ctx.getCaller();
@ -1370,7 +1379,7 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules
throw new CloudRuntimeException("Ip address is not associated with any network");
}
UserVmVO vm = _vmDao.findById(sourceIp.getAssociatedWithVmId());
VMInstanceVO vm = _vmInstanceDao.findById(sourceIp.getAssociatedWithVmId());
Network network = _networkModel.getNetwork(networkId);
if (network == null) {
CloudRuntimeException ex = new CloudRuntimeException("Unable to find an ip address to map to specified vm id");

View File

@ -100,4 +100,9 @@ public class PrivateGatewayProfile implements PrivateGateway {
public State getState() {
return vpcGateway.getState();
}
@Override
public boolean getSourceNat() {
return vpcGateway.getSourceNat();
}
}

View File

@ -25,6 +25,7 @@ public class PrivateIpAddress implements PrivateIp{
String ipAddress;
String macAddress;
long networkId;
boolean sourceNat;
/**
* @param privateIp
@ -42,6 +43,7 @@ public class PrivateIpAddress implements PrivateIp{
this.netmask = netmask;
this.macAddress = macAddress;
this.networkId = privateIp.getNetworkId();
this.sourceNat = privateIp.getSourceNat();
}
@Override
@ -73,4 +75,9 @@ public class PrivateIpAddress implements PrivateIp{
public long getNetworkId() {
return networkId;
}
@Override
public boolean getSourceNat() {
return sourceNat;
}
}

View File

@ -54,15 +54,19 @@ public class PrivateIpVO implements InternalIdentity {
@Column(name="vpc_id")
private Long vpcId;
@Column(name="source_nat")
private boolean sourceNat;
public PrivateIpVO() {
}
}
public PrivateIpVO(String ipAddress, long networkId, long macAddress, long vpcId) {
public PrivateIpVO(String ipAddress, long networkId, long macAddress, long vpcId, boolean sourceNat) {
this.ipAddress = ipAddress;
this.networkId = networkId;
this.macAddress = macAddress;
this.vpcId = vpcId;
this.sourceNat = sourceNat;
}
public void setTakenAt(Date takenDate) {
@ -92,4 +96,8 @@ public class PrivateIpVO implements InternalIdentity {
public Long getVpcId() {
return vpcId;
}
public boolean getSourceNat() {
return sourceNat;
}
}

View File

@ -29,7 +29,6 @@ import javax.persistence.Id;
import javax.persistence.Table;
import com.cloud.utils.db.GenericDao;
import org.apache.cloudstack.api.InternalIdentity;
@Entity
@ -84,7 +83,10 @@ public class VpcGatewayVO implements VpcGateway {
@Column(name="state")
@Enumerated(value=EnumType.STRING)
State state;
@Column(name="source_nat")
boolean sourceNat;
protected VpcGatewayVO(){
this.uuid = UUID.randomUUID().toString();
}
@ -101,9 +103,10 @@ public class VpcGatewayVO implements VpcGateway {
* @param accountId TODO
* @param domainId TODO
* @param account_id
* @param sourceNat
*/
public VpcGatewayVO(String ip4Address, Type type, Long vpcId, long zoneId, Long networkId, String vlanTag,
String gateway, String netmask, long accountId, long domainId) {
String gateway, String netmask, long accountId, long domainId, boolean sourceNat) {
this.ip4Address = ip4Address;
this.type = type;
this.vpcId = vpcId;
@ -116,6 +119,7 @@ public class VpcGatewayVO implements VpcGateway {
this.accountId = accountId;
this.domainId = domainId;
this.state = State.Creating;
this.sourceNat = sourceNat;
}
@Override
@ -193,4 +197,10 @@ public class VpcGatewayVO implements VpcGateway {
public void setState(State state) {
this.state = state;
}
@Override
public boolean getSourceNat() {
return this.sourceNat;
}
}

View File

@ -1288,8 +1288,8 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
@Override
@DB
@ActionEvent(eventType = EventTypes.EVENT_PRIVATE_GATEWAY_CREATE, eventDescription = "creating vpc private gateway", create=true)
public PrivateGateway createVpcPrivateGateway(long vpcId, Long physicalNetworkId, String vlan, String ipAddress,
String gateway, String netmask, long gatewayOwnerId) throws ResourceAllocationException,
public PrivateGateway createVpcPrivateGateway(long vpcId, Long physicalNetworkId, String vlan, String ipAddress,
String gateway, String netmask, long gatewayOwnerId, Boolean isSourceNat) throws ResourceAllocationException,
ConcurrentOperationException, InsufficientCapacityException {
//Validate parameters
@ -1315,11 +1315,11 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
//1) create private network
String networkName = "vpc-" + vpc.getName() + "-privateNetwork";
Network privateNtwk = _ntwkSvc.createPrivateNetwork(networkName, networkName, physicalNetworkId,
vlan, ipAddress, null, gateway, netmask, gatewayOwnerId, vpcId);
vlan, ipAddress, null, gateway, netmask, gatewayOwnerId, vpcId, isSourceNat);
//2) create gateway entry
VpcGatewayVO gatewayVO = new VpcGatewayVO(ipAddress, VpcGateway.Type.Private, vpcId, privateNtwk.getDataCenterId(),
privateNtwk.getId(), vlan, gateway, netmask, vpc.getAccountId(), vpc.getDomainId());
privateNtwk.getId(), vlan, gateway, netmask, vpc.getAccountId(), vpc.getDomainId(), isSourceNat);
_vpcGatewayDao.persist(gatewayVO);
s_logger.debug("Created vpc gateway entry " + gatewayVO);

View File

@ -582,7 +582,7 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
}
//Convert max storage size from GiB to bytes
if (resourceType == ResourceType.primary_storage || resourceType == ResourceType.secondary_storage) {
if ((resourceType == ResourceType.primary_storage || resourceType == ResourceType.secondary_storage) && max >= 0) {
max = max * ResourceType.bytesToGiB;
}

View File

@ -358,7 +358,6 @@ import org.apache.cloudstack.api.command.user.vmgroup.UpdateVMGroupCmd;
import org.apache.cloudstack.api.command.user.vmsnapshot.CreateVMSnapshotCmd;
import org.apache.cloudstack.api.command.user.vmsnapshot.DeleteVMSnapshotCmd;
import org.apache.cloudstack.api.command.user.vmsnapshot.ListVMSnapshotCmd;
import org.apache.cloudstack.api.command.user.vmsnapshot.RevertToSnapshotCmd;
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
import org.apache.cloudstack.api.command.user.volume.DeleteVolumeCmd;
@ -409,6 +408,8 @@ import com.cloud.agent.api.GetVncPortAnswer;
import com.cloud.agent.api.GetVncPortCommand;
import com.cloud.agent.api.storage.CopyVolumeAnswer;
import com.cloud.agent.api.storage.CopyVolumeCommand;
import com.cloud.agent.api.storage.CreateVolumeOVAAnswer;
import com.cloud.agent.api.storage.CreateVolumeOVACommand;
import com.cloud.agent.manager.allocator.HostAllocator;
import com.cloud.alert.Alert;
import com.cloud.alert.AlertManager;
@ -575,6 +576,81 @@ import com.cloud.vm.dao.VMInstanceDao;
import edu.emory.mathcs.backport.java.util.Arrays;
import edu.emory.mathcs.backport.java.util.Collections;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.api.command.admin.autoscale.CreateCounterCmd;
import org.apache.cloudstack.api.command.admin.autoscale.DeleteCounterCmd;
import org.apache.cloudstack.api.command.admin.cluster.AddClusterCmd;
import org.apache.cloudstack.api.command.admin.cluster.DeleteClusterCmd;
import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd;
import org.apache.cloudstack.api.command.admin.cluster.UpdateClusterCmd;
import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd;
import org.apache.cloudstack.api.command.admin.config.ListHypervisorCapabilitiesCmd;
import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd;
import org.apache.cloudstack.api.command.admin.config.UpdateHypervisorCapabilitiesCmd;
import org.apache.cloudstack.api.command.admin.ldap.LDAPConfigCmd;
import org.apache.cloudstack.api.command.admin.ldap.LDAPRemoveCmd;
import org.apache.cloudstack.api.command.admin.pod.CreatePodCmd;
import org.apache.cloudstack.api.command.admin.pod.DeletePodCmd;
import org.apache.cloudstack.api.command.admin.pod.ListPodsByCmd;
import org.apache.cloudstack.api.command.admin.pod.UpdatePodCmd;
import org.apache.cloudstack.api.command.admin.region.AddRegionCmd;
import org.apache.cloudstack.api.command.admin.region.RemoveRegionCmd;
import org.apache.cloudstack.api.command.admin.region.UpdateRegionCmd;
import org.apache.cloudstack.api.command.admin.swift.AddSwiftCmd;
import org.apache.cloudstack.api.command.admin.swift.ListSwiftsCmd;
import org.apache.cloudstack.api.command.admin.template.PrepareTemplateCmd;
import org.apache.cloudstack.api.command.admin.vlan.CreateVlanIpRangeCmd;
import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd;
import org.apache.cloudstack.api.command.admin.vlan.ListVlanIpRangesCmd;
import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd;
import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd;
import org.apache.cloudstack.api.command.admin.vm.MigrateVirtualMachineWithVolumeCmd;
import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd;
import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd;
import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd;
import org.apache.cloudstack.api.command.admin.zone.MarkDefaultZoneForAccountCmd;
import org.apache.cloudstack.api.command.admin.zone.UpdateZoneCmd;
import org.apache.cloudstack.api.command.user.account.AddAccountToProjectCmd;
import org.apache.cloudstack.api.command.user.account.DeleteAccountFromProjectCmd;
import org.apache.cloudstack.api.command.user.account.ListAccountsCmd;
import org.apache.cloudstack.api.command.user.account.ListProjectAccountsCmd;
import org.apache.cloudstack.api.command.user.address.AssociateIPAddrCmd;
import org.apache.cloudstack.api.command.user.address.DisassociateIPAddrCmd;
import org.apache.cloudstack.api.command.user.address.ListPublicIpAddressesCmd;
import org.apache.cloudstack.api.command.user.config.ListCapabilitiesCmd;
import org.apache.cloudstack.api.command.user.event.ArchiveEventsCmd;
import org.apache.cloudstack.api.command.user.event.DeleteEventsCmd;
import org.apache.cloudstack.api.command.user.event.ListEventTypesCmd;
import org.apache.cloudstack.api.command.user.event.ListEventsCmd;
import org.apache.cloudstack.api.command.user.guest.ListGuestOsCategoriesCmd;
import org.apache.cloudstack.api.command.user.guest.ListGuestOsCmd;
import org.apache.cloudstack.api.command.user.job.ListAsyncJobsCmd;
import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd;
import org.apache.cloudstack.api.command.user.offering.ListDiskOfferingsCmd;
import org.apache.cloudstack.api.command.user.offering.ListServiceOfferingsCmd;
import org.apache.cloudstack.api.command.user.region.ListRegionsCmd;
import org.apache.cloudstack.api.command.user.region.ha.gslb.*;
import org.apache.cloudstack.api.command.user.ssh.CreateSSHKeyPairCmd;
import org.apache.cloudstack.api.command.user.ssh.DeleteSSHKeyPairCmd;
import org.apache.cloudstack.api.command.user.ssh.ListSSHKeyPairsCmd;
import org.apache.cloudstack.api.command.user.ssh.RegisterSSHKeyPairCmd;
import org.apache.cloudstack.api.command.user.tag.CreateTagsCmd;
import org.apache.cloudstack.api.command.user.tag.DeleteTagsCmd;
import org.apache.cloudstack.api.command.user.tag.ListTagsCmd;
import org.apache.cloudstack.api.command.user.vmgroup.CreateVMGroupCmd;
import org.apache.cloudstack.api.command.user.vmgroup.DeleteVMGroupCmd;
import org.apache.cloudstack.api.command.user.vmgroup.ListVMGroupsCmd;
import org.apache.cloudstack.api.command.user.vmgroup.UpdateVMGroupCmd;
import org.apache.cloudstack.api.command.user.vmsnapshot.CreateVMSnapshotCmd;
import org.apache.cloudstack.api.command.user.vmsnapshot.DeleteVMSnapshotCmd;
import org.apache.cloudstack.api.command.user.vmsnapshot.ListVMSnapshotCmd;
import org.apache.cloudstack.api.command.user.vmsnapshot.RevertToVMSnapshotCmd;
import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
public class ManagementServerImpl extends ManagerBase implements ManagementServer {
public static final Logger s_logger = Logger.getLogger(ManagementServerImpl.class.getName());
@ -2837,7 +2913,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
cmdList.add(ListZonesByCmd.class);
cmdList.add(ListVMSnapshotCmd.class);
cmdList.add(CreateVMSnapshotCmd.class);
cmdList.add(RevertToSnapshotCmd.class);
cmdList.add(RevertToVMSnapshotCmd.class);
cmdList.add(DeleteVMSnapshotCmd.class);
cmdList.add(AddIpToVmNicCmd.class);
cmdList.add(RemoveIpFromVmNicCmd.class);
@ -3404,7 +3480,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
List<UploadVO> extractURLList = _uploadDao.listByTypeUploadStatus(volumeId, Upload.Type.VOLUME, UploadVO.Status.DOWNLOAD_URL_CREATED);
if (extractMode == Upload.Mode.HTTP_DOWNLOAD && extractURLList.size() > 0) {
return extractURLList.get(0).getId(); // If download url already
return extractURLList.get(0).getId(); // If download url already Note: volss
// exists then return
} else {
UploadVO uploadJob = _uploadMonitor.createNewUploadEntry(sserver.getId(), volumeId, UploadVO.Status.COPY_IN_PROGRESS, Upload.Type.VOLUME,
@ -3456,6 +3532,19 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
}
String volumeLocalPath = "volumes/" + volume.getId() + "/" + cvAnswer.getVolumePath() + "." + getFormatForPool(srcPool);
//Fang: volss, handle the ova special case;
if (getFormatForPool(srcPool) == "ova") {
CreateVolumeOVACommand cvOVACmd = new CreateVolumeOVACommand(secondaryStorageURL, volumeLocalPath, cvAnswer.getVolumePath(), srcPool, copyvolumewait);
CreateVolumeOVAAnswer OVAanswer = null;
try {
cvOVACmd.setContextParam("hypervisor", HypervisorType.VMware.toString());
OVAanswer = (CreateVolumeOVAAnswer) _storageMgr.sendToPool(srcPool, cvOVACmd); //Fang: for extract volume, create the ova file here;
} catch (StorageUnavailableException e) {
s_logger.debug("Storage unavailable");
}
}
// Update the DB that volume is copied and volumePath
uploadJob.setUploadState(UploadVO.Status.COPY_COMPLETE);
uploadJob.setLastUpdated(new Date());

View File

@ -562,10 +562,15 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
sql = SELECT_TEMPLATE_HOST_REF;
groupByClause = " GROUP BY t.id, h.data_center_id ";
}
if (((templateFilter == TemplateFilter.featured) || (templateFilter == TemplateFilter.community)) ||(zoneType != null && zoneId != null)) {
if ((templateFilter == TemplateFilter.featured) || (templateFilter == TemplateFilter.community)) {
dataCenterJoin = " INNER JOIN data_center dc on (h.data_center_id = dc.id)";
}
if (zoneType != null) {
dataCenterJoin = " INNER JOIN template_host_ref thr on (t.id = thr.template_id) INNER JOIN host h on (thr.host_id = h.id)";
dataCenterJoin += " INNER JOIN data_center dc on (h.data_center_id = dc.id)";
}
if (templateFilter == TemplateFilter.sharedexecutable || templateFilter == TemplateFilter.shared ){
lpjoin = " INNER JOIN launch_permission lp ON t.id = lp.template_id ";
}
@ -783,13 +788,15 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
sql += " AND h.data_center_id = " +zoneId;
}
}else if (zoneId != null){
sql += " AND tzr.zone_id = " +zoneId+ " AND tzr.removed is null" ;
if (zoneType != null){
sql += " AND dc.networktype = " + zoneType;
}
sql += " AND tzr.zone_id = " +zoneId+ " AND tzr.removed is null" ;
}else{
sql += " AND tzr.removed is null ";
}
if (zoneType != null){
sql += " AND dc.networktype = '" + zoneType + "'";
}
if (!showDomr){
sql += " AND t.type != '" +Storage.TemplateType.SYSTEM.toString() + "'";
}

View File

@ -30,6 +30,9 @@ import javax.inject.Inject;
import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd;
import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd;
import com.cloud.agent.api.storage.PrepareOVAPackingCommand;
import com.cloud.agent.api.storage.PrepareOVAPackingAnswer;
import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
@ -64,6 +67,10 @@ import com.cloud.utils.UriUtils;
import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.UserVmVO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.OperationTimedoutException;
@Local(value=TemplateAdapter.class)
public class HypervisorTemplateAdapter extends TemplateAdapterBase implements TemplateAdapter {
@ -188,6 +195,77 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase implements Te
return template;
}
@Override
public TemplateProfile prepareExtractTemplate(ExtractTemplateCmd extractcmd) {
TemplateProfile profile = super.prepareExtractTemplate(extractcmd);
VMTemplateVO template = (VMTemplateVO)profile.getTemplate();
Long zoneId = profile.getZoneId();
Long templateId = template.getId();
if (template.getHypervisorType() == HypervisorType.VMware) {
PrepareOVAPackingCommand cmd = null;
String zoneName="";
List<HostVO> secondaryStorageHosts;
if (!template.isCrossZones() && zoneId != null) {
DataCenterVO zone = _dcDao.findById(zoneId);
zoneName = zone.getName();
secondaryStorageHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(zoneId);
s_logger.debug("Attempting to mark template host refs for template: " + template.getName() + " as destroyed in zone: " + zoneName);
// Make sure the template is downloaded to all the necessary secondary storage hosts
for (HostVO secondaryStorageHost : secondaryStorageHosts) {
long hostId = secondaryStorageHost.getId();
List<VMTemplateHostVO> templateHostVOs = _tmpltHostDao.listByHostTemplate(hostId, templateId);
for (VMTemplateHostVO templateHostVO : templateHostVOs) {
if (templateHostVO.getDownloadState() == Status.DOWNLOAD_IN_PROGRESS) {
String errorMsg = "Please specify a template that is not currently being downloaded.";
s_logger.debug("Template: " + template.getName() + " is currently being downloaded to secondary storage host: " + secondaryStorageHost.getName() + ".");
throw new CloudRuntimeException(errorMsg);
}
String installPath = templateHostVO.getInstallPath();
if (installPath != null) {
HostVO ssvmhost = _ssvmMgr.pickSsvmHost(secondaryStorageHost);
if( ssvmhost == null ) {
s_logger.warn("prepareOVAPacking (hyervisorTemplateAdapter): There is no secondary storage VM for secondary storage host " + secondaryStorageHost.getName());
throw new CloudRuntimeException("PrepareExtractTemplate: can't locate ssvm for SecStorage Host.");
}
//Answer answer = _agentMgr.sendToSecStorage(secondaryStorageHost, new PrepareOVAPackingCommand(secondaryStorageHost.getStorageUrl(), installPath));
cmd = new PrepareOVAPackingCommand(secondaryStorageHost.getStorageUrl(), installPath);
if (cmd == null) {
s_logger.debug("Fang: PrepareOVAPacking cmd can't created. cmd is null .");
throw new CloudRuntimeException("PrepareExtractTemplate: can't create a new cmd to packing ova.");
} else {
cmd.setContextParam("hypervisor", HypervisorType.VMware.toString());
}
Answer answer = null;
s_logger.debug("Fang: PrepareOVAPAcking cmd, before send out. cmd: " + cmd.toString());
try {
answer = _agentMgr.send(ssvmhost.getId(), cmd);
} catch (AgentUnavailableException e) {
s_logger.warn("Unable to packOVA for template: id: " + templateId + ", name " + ssvmhost.getName(), e);
} catch (OperationTimedoutException e) {
s_logger.warn("Unable to packOVA for template timeout. template id: " + templateId);
e.printStackTrace();
}
if (answer == null || !answer.getResult()) {
s_logger.debug("Failed to create OVA for template " + templateHostVO + " due to " + ((answer == null) ? "answer is null" : answer.getDetails()));
throw new CloudRuntimeException("PrepareExtractTemplate: Failed to create OVA for template extraction. ");
}
}
}
}
} else {
s_logger.debug("Failed to create OVA for template " + template + " due to zone non-existing.");
throw new CloudRuntimeException("PrepareExtractTemplate: Failed to create OVA for template extraction. ");
}
}
return profile;
}
@Override @DB
public boolean delete(TemplateProfile profile) {
boolean success = true;

View File

@ -22,6 +22,7 @@ import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd;
import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
@ -56,6 +57,8 @@ public interface TemplateAdapter extends Adapter {
public TemplateProfile prepareDelete(DeleteIsoCmd cmd);
public TemplateProfile prepareExtractTemplate(ExtractTemplateCmd cmd);
public boolean delete(TemplateProfile profile);
public TemplateProfile prepare(boolean isIso, Long userId, String name, String displayText, Integer bits,

View File

@ -26,6 +26,7 @@ import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
import org.apache.cloudstack.api.command.user.iso.RegisterIsoCmd;
import org.apache.cloudstack.api.command.user.template.DeleteTemplateCmd;
import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
@ -340,6 +341,18 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
return new TemplateProfile(userId, template, zoneId);
}
public TemplateProfile prepareExtractTemplate(ExtractTemplateCmd cmd) {
Long templateId = cmd.getId();
Long userId = UserContext.current().getCallerUserId();
Long zoneId = cmd.getZoneId();
VMTemplateVO template = _tmpltDao.findById(templateId.longValue());
if (template == null) {
throw new InvalidParameterValueException("unable to find template with id " + templateId);
}
return new TemplateProfile(userId, template, zoneId);
}
public TemplateProfile prepareDelete(DeleteIsoCmd cmd) {
Long templateId = cmd.getId();
Long userId = UserContext.current().getCallerUserId();

View File

@ -367,6 +367,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
String mode = cmd.getMode();
Long eventId = cmd.getStartEventId();
VirtualMachineTemplate template = getTemplate(templateId);
if (template == null) {
throw new InvalidParameterValueException("unable to find template with id " + templateId);
}
TemplateAdapter adapter = getAdapter(template.getHypervisorType());
TemplateProfile profile = adapter.prepareExtractTemplate(cmd);
// FIXME: async job needs fixing
Long uploadId = extract(caller, templateId, url, zoneId, mode, eventId, false, null, _asyncMgr);
if (uploadId != null){

24
server/src/com/cloud/upgrade/dao/Upgrade2214to30.java Executable file → Normal file
View File

@ -629,8 +629,8 @@ public class Upgrade2214to30 extends Upgrade30xBase implements DbUpgrade {
s_logger.debug("Updating XenSever System Vms");
//XenServer
try {
//Get 3.0.0 xenserer system Vm template Id
pstmt = conn.prepareStatement("select id from `cloud`.`vm_template` where name = 'systemvm-xenserver-3.0.0' and removed is null");
//Get 3.0.0 or later xenserer system Vm template Id
pstmt = conn.prepareStatement("select max(id) from `cloud`.`vm_template` where name like 'systemvm-xenserver-%' and removed is null");
rs = pstmt.executeQuery();
if(rs.next()){
long templateId = rs.getLong(1);
@ -648,9 +648,9 @@ public class Upgrade2214to30 extends Upgrade30xBase implements DbUpgrade {
pstmt.close();
} else {
if (xenserver){
throw new CloudRuntimeException("3.0.0 XenServer SystemVm template not found. Cannot upgrade system Vms");
throw new CloudRuntimeException("3.0.0 or later XenServer SystemVm template not found. Cannot upgrade system Vms");
} else {
s_logger.warn("3.0.0 XenServer SystemVm template not found. XenServer hypervisor is not used, so not failing upgrade");
s_logger.warn("3.0.0 or later XenServer SystemVm template not found. XenServer hypervisor is not used, so not failing upgrade");
}
}
} catch (SQLException e) {
@ -660,8 +660,8 @@ public class Upgrade2214to30 extends Upgrade30xBase implements DbUpgrade {
//KVM
s_logger.debug("Updating KVM System Vms");
try {
//Get 3.0.0 KVM system Vm template Id
pstmt = conn.prepareStatement("select id from `cloud`.`vm_template` where name = 'systemvm-kvm-3.0.0' and removed is null");
//Get 3.0.0 or later KVM system Vm template Id
pstmt = conn.prepareStatement("select max(id) from `cloud`.`vm_template` where name like 'systemvm-kvm-%' and removed is null");
rs = pstmt.executeQuery();
if(rs.next()){
long templateId = rs.getLong(1);
@ -679,9 +679,9 @@ public class Upgrade2214to30 extends Upgrade30xBase implements DbUpgrade {
pstmt.close();
} else {
if (kvm){
throw new CloudRuntimeException("3.0.0 KVM SystemVm template not found. Cannot upgrade system Vms");
throw new CloudRuntimeException("3.0.0 or later KVM SystemVm template not found. Cannot upgrade system Vms");
} else {
s_logger.warn("3.0.0 KVM SystemVm template not found. KVM hypervisor is not used, so not failing upgrade");
s_logger.warn("3.0.0 or later KVM SystemVm template not found. KVM hypervisor is not used, so not failing upgrade");
}
}
} catch (SQLException e) {
@ -691,8 +691,8 @@ public class Upgrade2214to30 extends Upgrade30xBase implements DbUpgrade {
//VMware
s_logger.debug("Updating VMware System Vms");
try {
//Get 3.0.0 VMware system Vm template Id
pstmt = conn.prepareStatement("select id from `cloud`.`vm_template` where name = 'systemvm-vmware-3.0.0' and removed is null");
//Get 3.0.0 or later VMware system Vm template Id
pstmt = conn.prepareStatement("select max(id) from `cloud`.`vm_template` where name like 'systemvm-vmware-%' and removed is null");
rs = pstmt.executeQuery();
if(rs.next()){
long templateId = rs.getLong(1);
@ -710,9 +710,9 @@ public class Upgrade2214to30 extends Upgrade30xBase implements DbUpgrade {
pstmt.close();
} else {
if (VMware){
throw new CloudRuntimeException("3.0.0 VMware SystemVm template not found. Cannot upgrade system Vms");
throw new CloudRuntimeException("3.0.0 or later VMware SystemVm template not found. Cannot upgrade system Vms");
} else {
s_logger.warn("3.0.0 VMware SystemVm template not found. VMware hypervisor is not used, so not failing upgrade");
s_logger.warn("3.0.0 or later VMware SystemVm template not found. VMware hypervisor is not used, so not failing upgrade");
}
}
} catch (SQLException e) {

View File

@ -1050,7 +1050,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
@Override
@ActionEvent(eventType = EventTypes.EVENT_VM_SCALE, eventDescription = "scaling Vm")
public UserVm
public boolean
upgradeVirtualMachine(ScaleVMCmd cmd) throws InvalidParameterValueException {
Long vmId = cmd.getId();
Long newServiceOfferingId = cmd.getServiceOfferingId();
@ -1076,8 +1076,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
}
// Dynamically upgrade the running vms
boolean success = false;
if(vmInstance.getState().equals(State.Running)){
boolean success = false;
int retry = _scaleRetry;
while (retry-- != 0) { // It's != so that it can match -1.
try{
@ -1095,7 +1095,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
vmInstance = _vmInstanceDao.findById(vmId);
vmInstance = _itMgr.reConfigureVm(vmInstance, oldServiceOffering, existingHostHasCapacity);
success = true;
return _vmDao.findById(vmInstance.getId());
return success;
}catch(InsufficientCapacityException e ){
s_logger.warn("Received exception while scaling ",e);
} catch (ResourceUnavailableException e) {
@ -1112,11 +1112,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
}
}
}
if (!success)
return null;
}
return _vmDao.findById(vmInstance.getId());
return success;
}

View File

@ -64,6 +64,7 @@ import com.cloud.alert.AlertManager;
import com.cloud.cluster.ClusterManager;
import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.DataCenter;
@ -131,6 +132,7 @@ import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.User;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserDao;
@ -231,6 +233,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
protected VMSnapshotDao _vmSnapshotDao;
@Inject
protected VolumeDataFactory volFactory;
@Inject
protected ResourceLimitService _resourceLimitMgr;
protected List<DeploymentPlanner> _planners;
public List<DeploymentPlanner> getPlanners() {
@ -428,6 +432,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
s_logger.debug("Cleaning up NICS");
_networkMgr.cleanupNics(profile);
// Clean up volumes based on the vm's instance id
List<VolumeVO> rootVol = _volsDao.findByInstanceAndType(vm.getId(), Volume.Type.ROOT);
this.volumeMgr.cleanupVolumes(vm.getId());
VirtualMachineGuru<T> guru = getVmGuru(vm);
@ -462,6 +467,12 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
s_logger.debug("Expunged " + vm);
}
// Update Resource count
if (vm.getAccountId() != Account.ACCOUNT_ID_SYSTEM && !rootVol.isEmpty()) {
_resourceLimitMgr.decrementResourceCount(vm.getAccountId(), ResourceType.volume);
_resourceLimitMgr.decrementResourceCount(vm.getAccountId(), ResourceType.primary_storage,
new Long(rootVol.get(0).getSize()));
}
return true;
}

View File

@ -64,15 +64,23 @@ import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ManagerBase;
import com.cloud.vm.Nic;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicSecondaryIp;
import com.cloud.vm.NicVO;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.*;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VirtualMachineProfile;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
import org.springframework.stereotype.Component;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Component
@Local(value = { NetworkManager.class, NetworkService.class })
@ -611,7 +619,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage
*/
@Override
public Network createPrivateNetwork(String networkName, String displayText, long physicalNetworkId, String vlan,
String startIp, String endIP, String gateway, String netmask, long networkOwnerId, Long vpcId)
String startIp, String endIP, String gateway, String netmask, long networkOwnerId, Long vpcId, Boolean sourceNat)
throws ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException {
// TODO Auto-generated method stub
return null;

View File

@ -76,8 +76,7 @@ public class MockRulesManagerImpl extends ManagerBase implements RulesManager, R
@Override
public boolean enableStaticNat(long ipAddressId, long vmId, long networkId,
boolean isSystemVm, String ipAddr) throws NetworkRuleConflictException,
ResourceUnavailableException {
String ipAddr) throws NetworkRuleConflictException, ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
}

View File

@ -407,8 +407,8 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager,
}
@Override
public UserVm upgradeVirtualMachine(ScaleVMCmd scaleVMCmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException {
return null; //To change body of implemented methods use File | Settings | File Templates.
public boolean upgradeVirtualMachine(ScaleVMCmd scaleVMCmd) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException {
return false; //To change body of implemented methods use File | Settings | File Templates.
}

View File

@ -79,15 +79,25 @@ import com.cloud.user.Account;
import com.cloud.user.User;
import com.cloud.utils.Pair;
import com.cloud.utils.component.ManagerBase;
import com.cloud.vm.Nic;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicSecondaryIp;
import com.cloud.vm.NicVO;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.*;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.vm.VirtualMachineProfile;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
import org.apache.cloudstack.api.command.user.network.ListNetworksCmd;
import org.apache.cloudstack.api.command.user.network.RestartNetworkCmd;
import org.apache.cloudstack.api.command.user.vm.ListNicsCmd;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
@Local(value = { NetworkManager.class, NetworkService.class })
@ -625,7 +635,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage
*/
@Override
public Network createPrivateNetwork(String networkName, String displayText, long physicalNetworkId, String vlan,
String startIp, String endIP, String gateway, String netmask, long networkOwnerId, Long vpcId)
String startIp, String endIP, String gateway, String netmask, long networkOwnerId, Long vpcId, Boolean sourceNat)
throws ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException {
// TODO Auto-generated method stub
return null;

View File

@ -164,7 +164,7 @@ public class MockVpcManagerImpl extends ManagerBase implements VpcManager {
* @see com.cloud.network.vpc.VpcService#createVpcPrivateGateway(long, java.lang.Long, java.lang.String, java.lang.String, java.lang.String, java.lang.String, long)
*/
@Override
public PrivateGateway createVpcPrivateGateway(long vpcId, Long physicalNetworkId, String vlan, String ipAddress, String gateway, String netmask, long gatewayOwnerId) throws ResourceAllocationException,
public PrivateGateway createVpcPrivateGateway(long vpcId, Long physicalNetworkId, String vlan, String ipAddress, String gateway, String netmask, long gatewayOwnerId, Boolean isSourceNat) throws ResourceAllocationException,
ConcurrentOperationException, InsufficientCapacityException {
// TODO Auto-generated method stub
return null;

View File

@ -1158,3 +1158,6 @@ ALTER TABLE `cloud`.`account_details` MODIFY value varchar(255);
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Network', 'DEFAULT', 'management-server', 'midonet.apiserver.address', 'http://localhost:8081', 'Specify the address at which the Midonet API server can be contacted (if using Midonet)');
INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Network', 'DEFAULT', 'management-server', 'midonet.providerrouter.id', 'd7c5e6a3-e2f4-426b-b728-b7ce6a0448e5', 'Specifies the UUID of the Midonet provider router (if using Midonet)');
alter table cloud.vpc_gateways add column source_nat boolean default false;
alter table cloud.private_ip_address add column source_nat boolean default false;

View File

@ -0,0 +1,308 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Import Local Modules
import marvin
from nose.plugins.attrib import attr
from marvin.cloudstackTestCase import *
from marvin.cloudstackAPI import *
from marvin.integration.lib.utils import *
from marvin.integration.lib.base import *
from marvin.integration.lib.common import *
from marvin.remoteSSHClient import remoteSSHClient
class Services:
"""Test Snapshots Services
"""
def __init__(self):
self.services = {
"account": {
"email": "test@test.com",
"firstname": "Test",
"lastname": "User",
"username": "test",
# Random characters are appended for unique
# username
"password": "password",
},
"service_offering": {
"name": "Tiny Instance",
"displaytext": "Tiny Instance",
"cpunumber": 1,
"cpuspeed": 200, # in MHz
"memory": 256, # In MBs
},
"server": {
"displayname": "TestVM",
"username": "root",
"password": "password",
"ssh_port": 22,
"hypervisor": 'XenServer',
"privateport": 22,
"publicport": 22,
"protocol": 'TCP',
},
"mgmt_server": {
"ipaddress": '1.2.2.152',
"username": "root",
"password": "password",
"port": 22,
},
"templates": {
"displaytext": 'Template',
"name": 'Template',
"ostype": "CentOS 5.3 (64-bit)",
"templatefilter": 'self',
},
"test_dir": "/tmp",
"random_data": "random.data",
"snapshot_name":"TestSnapshot",
"snapshot_displaytext":"Test",
"ostype": "CentOS 5.3 (64-bit)",
"sleep": 60,
"timeout": 10,
"mode": 'advanced', # Networking mode: Advanced, Basic
}
class TestVmSnapshot(cloudstackTestCase):
@classmethod
def setUpClass(cls):
cls.api_client = super(TestVmSnapshot, 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)
template = get_template(
cls.api_client,
cls.zone.id,
cls.services["ostype"]
)
cls.services["domainid"] = cls.domain.id
cls.services["server"]["zoneid"] = cls.zone.id
cls.services["templates"]["ostypeid"] = template.ostypeid
cls.services["zoneid"] = cls.zone.id
# Create VMs, NAT Rules etc
cls.account = Account.create(
cls.api_client,
cls.services["account"],
domainid=cls.domain.id
)
cls.services["account"] = cls.account.name
cls.service_offering = ServiceOffering.create(
cls.api_client,
cls.services["service_offering"]
)
cls.virtual_machine = VirtualMachine.create(
cls.api_client,
cls.services["server"],
templateid=template.id,
accountid=cls.account.name,
domainid=cls.account.domainid,
serviceofferingid=cls.service_offering.id,
mode=cls.services["mode"]
)
cls.random_data_0 = random_gen(100)
cls._cleanup = [
cls.service_offering,
cls.account,
]
return
@classmethod
def tearDownClass(cls):
try:
# Cleanup resources used
cleanup_resources(cls.api_client, cls._cleanup)
except Exception as e:
raise Exception("Warning: Exception during cleanup : %s" % e)
return
def setUp(self):
self.apiclient = self.testClient.getApiClient()
self.dbclient = self.testClient.getDbConnection()
self.cleanup = []
return
def tearDown(self):
try:
# Clean up, terminate the created instance, volumes and snapshots
cleanup_resources(self.apiclient, self.cleanup)
except Exception as e:
raise Exception("Warning: Exception during cleanup : %s" % e)
return
@attr(tags=["advanced", "advancedns", "smoke"])
def test_01_create_vm_snapshots(self):
try:
# Login to VM and write data to file system
ssh_client = self.virtual_machine.get_ssh_client()
cmds = [
"echo %s > %s/%s" % (self.random_data_0, self.services["test_dir"], self.services["random_data"]),
"cat %s/%s" % (self.services["test_dir"], self.services["random_data"])
]
for c in cmds:
self.debug(c)
result = ssh_client.execute(c)
self.debug(result)
except Exception:
self.fail("SSH failed for Virtual machine: %s" %
self.virtual_machine.ipaddress)
self.assertEqual(
self.random_data_0,
result[0],
"Check the random data has be write into temp file!"
)
time.sleep(self.services["sleep"])
vm_snapshot = VmSnapshot.create(
self.apiclient,
self.virtual_machine.id,
"false",
self.services["snapshot_name"],
self.services["snapshot_displaytext"]
)
self.assertEqual(
vm_snapshot.state,
"Ready",
"Check the snapshot of vm is ready!"
)
return
@attr(tags=["advanced", "advancedns", "smoke"])
def test_02_revert_vm_snapshots(self):
try:
ssh_client = self.virtual_machine.get_ssh_client()
cmds = [
"rm -rf %s/%s" % (self.services["test_dir"], self.services["random_data"]),
"ls %s/%s" % (self.services["test_dir"], self.services["random_data"])
]
for c in cmds:
self.debug(c)
result = ssh_client.execute(c)
self.debug(result)
except Exception:
self.fail("SSH failed for Virtual machine: %s" %
self.virtual_machine.ipaddress)
if str(result[0]).index("No such file or directory") == -1:
self.fail("Check the random data has be delete from temp file!")
time.sleep(self.services["sleep"])
list_snapshot_response = VmSnapshot.list(self.apiclient,vmid=self.virtual_machine.id,listall=True)
self.assertEqual(
isinstance(list_snapshot_response, list),
True,
"Check list response returns a valid list"
)
self.assertNotEqual(
list_snapshot_response,
None,
"Check if snapshot exists in ListSnapshot"
)
self.assertEqual(
list_snapshot_response[0].state,
"Ready",
"Check the snapshot of vm is ready!"
)
VmSnapshot.revertToSnapshot(self.apiclient,list_snapshot_response[0].id)
list_vm_response = list_virtual_machines(
self.apiclient,
id=self.virtual_machine.id
)
self.assertEqual(
list_vm_response[0].state,
"Stopped",
"Check the state of vm is Stopped!"
)
cmd = startVirtualMachine.startVirtualMachineCmd()
cmd.id = list_vm_response[0].id
self.apiclient.startVirtualMachine(cmd)
time.sleep(self.services["sleep"])
try:
ssh_client = self.virtual_machine.get_ssh_client(reconnect=True)
cmds = [
"cat %s/%s" % (self.services["test_dir"], self.services["random_data"])
]
for c in cmds:
self.debug(c)
result = ssh_client.execute(c)
self.debug(result)
except Exception:
self.fail("SSH failed for Virtual machine: %s" %
self.virtual_machine.ipaddress)
self.assertEqual(
self.random_data_0,
result[0],
"Check the random data is equal with the ramdom file!"
)
@attr(tags=["advanced", "advancedns", "smoke"])
def test_03_delete_vm_snapshots(self):
list_snapshot_response = VmSnapshot.list(self.apiclient,vmid=self.virtual_machine.id,listall=True)
self.assertEqual(
isinstance(list_snapshot_response, list),
True,
"Check list response returns a valid list"
)
self.assertNotEqual(
list_snapshot_response,
None,
"Check if snapshot exists in ListSnapshot"
)
"""
cmd = deleteVMSnapshot.deleteVMSnapshotCmd()
cmd.vmsnapshotid = list_snapshot_response[0].id
self.apiclient.deleteVMSnapshot(cmd)
"""
VmSnapshot.deleteVMSnapshot(self.apiclient,list_snapshot_response[0].id)
time.sleep(self.services["sleep"]*3)
list_snapshot_response = VmSnapshot.list(self.apiclient,vmid=self.virtual_machine.id,listall=True)
self.assertEqual(
list_snapshot_response,
None,
"Check list vm snapshot has be deleted"
)

View File

@ -1,31 +1,41 @@
##############################################
Questions? Post'em @ dev@cloudstack.apache.org
##############################################
This files contains following:
1) Installation requirements
2) Test Pre requisites
3) Running the Test and Generating the report
2) Testing pre-requisites
3) Running the Tests and Generating the report
##############################################
##########################################################################################################################################
1) Installtion Requirements
1) Installation Requirements
---------------------------
1)Firefox depending on your OS (Good to have Firebug and Selenium IDE for troubleshooting and dev work)
1) Firefox depending on your OS (Good to have Firebug and Selenium IDE for troubleshooting and dev work)
2)Install Python 2.7. Recommend to use Active State Python
2) Install Python 2.7.
3) Now Open CMD/Terminal and type all of following
- pypm install pycrypto (Installs Pycrypto)
- pypm install paramiko (Install paramiko)
- pip install pycrypto (Installs Pycrypto)
- pip install paramiko (Install paramiko)
- pip install unittest-xml-reporting (Install XML Test Runner)
- pip install -U selenium (Installs Selenium)
4) Get PhoantomJS for your OS from http://phantomjs.org/
- PhantomJS will run selenium test in headless mode. Follow the instruction on PhantomJS.org.
- Make sure the executable is in PATH. (TIP: Drop it in Python27 folder :-))
5) Now get the HTMLTestRunner for nice looking report generation.
- http://tungwaiyip.info/software/HTMLTestRunner.html
@ -35,18 +45,22 @@ This files contains following:
##########################################################################################################################################
2) Test Prerequisites
---------------------
- Download and install CS. /cwiki.apache.org has links to Installation Guide and API reference.
- Log into the management server and Add a Zone. (Must be Advance Zone and Hypervisor type must be Xen)
- Download and install CS
- Log into the management server nad Add a Zone. (Must be Advance Zone and Hypervisor type must be Xen)
##########################################################################################################################################
3) Running the Test and Generating the report
---------------------------------------------
- Folder smoke contains main.py
- main.py is the file where all the tests are serialized.
- main.py supports HTML and XML reporting. Please refer to end of file to choose either.
- Typical usage is: python main.py for XML Reporting
- And python main.py >> results.html for HTML Reporting.
- Typical usage is: python main.py 10.1.1.10 >> result.xml for XML Reporting
- And python main.py 10.1.1.10 >> result.html for HTML Reporting.
- 10.1.1.10 (your management server IP) is an argument required for main.
##########################################################################################################################################

View File

@ -21,11 +21,26 @@ This will help pass webdriver (Browser instance) across our test cases.
from selenium import webdriver
import sys
DRIVER = None
MS_ip = None
def getOrCreateWebdriver():
global DRIVER
DRIVER = DRIVER or webdriver.Firefox()
DRIVER = DRIVER or webdriver.PhantomJS('phantomjs') # phantomjs executable must be in PATH.
return DRIVER
def getMSip():
global MS_ip
if len(sys.argv) >= 3:
sys.exit("Only One argument is required .. Enter your Management Server IP")
if len(sys.argv) == 1:
sys.exit("Atleast One argument is required .. Enter your Management Server IP")
for arg in sys.argv[1:]:
MS_ip = arg
return MS_ip

View File

@ -34,11 +34,12 @@ class login(unittest.TestCase):
def setUp(self):
MS_URL = initialize.getMSip()
self.driver = initialize.getOrCreateWebdriver()
self.base_url = "http://10.223.49.206:8080/" # Your management Server IP goes here
self.base_url = "http://"+ MS_URL +":8080/" # Your management Server IP goes here
self.verificationErrors = []
def test_login(self):
# Here we will clear the test box for Username and Password and fill them with actual login data.

View File

@ -21,7 +21,7 @@ import xmlrunner
global DRIVER
global MS_ip
# Import test cases

View File

@ -3045,3 +3045,40 @@ class ASA1000V:
cmd = listCiscoAsa1000vResources.listCiscoAsa1000vResourcesCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listCiscoAsa1000vResources(cmd))
class VmSnapshot:
"""Manage VM Snapshot life cycle"""
def __init__(self, items):
self.__dict__.update(items)
@classmethod
def create(cls,apiclient,vmid,snapshotmemory="false",name=None,description=None):
cmd = createVMSnapshot.createVMSnapshotCmd()
cmd.virtualmachineid = vmid
if snapshotmemory:
cmd.snapshotmemory = snapshotmemory
if name:
cmd.name = name
if description:
cmd.description = description
return VmSnapshot(apiclient.createVMSnapshot(cmd).__dict__)
@classmethod
def list(cls, apiclient, **kwargs):
cmd = listVMSnapshot.listVMSnapshotCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listVMSnapshot(cmd))
@classmethod
def revertToSnapshot(cls, apiclient,vmsnapshotid):
cmd = revertToVMSnapshot.revertToVMSnapshotCmd()
cmd.vmsnapshotid = vmsnapshotid
return apiclient.revertToVMSnapshot(cmd)
@classmethod
def deleteVMSnapshot(cls,apiclient,vmsnapshotid):
cmd = deleteVMSnapshot.deleteVMSnapshotCmd()
cmd.vmsnapshotid = vmsnapshotid
return apiclient.deleteVMSnapshot(cmd)

View File

@ -1662,6 +1662,7 @@ under the License.
<script type="text/javascript" src="scripts/ui-custom/autoscaler.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui-custom/healthCheck.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/autoscaler.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui-custom/granularSettings.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui-custom/zoneChart.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/ui-custom/dashboard.js?t=<%=now%>"></script>
<script type="text/javascript" src="scripts/installWizard.js?t=<%=now%>"></script>

View File

@ -277,6 +277,7 @@
detailView: {
name: 'Account details',
isMaximized: true,
viewAll: { path: 'accounts.users', label: 'label.users' },
actions: {
@ -895,6 +896,56 @@
}
});
}
},
// Granular settings for account
settings: {
title: 'Settings',
custom: cloudStack.uiCustom.granularSettings({
dataProvider: function(args) {
$.ajax({
url:createURL('listConfigurations&accountid=' + args.context.accounts[0].id),
data: { page: args.page, pageSize: pageSize, listAll: true },
success:function(json){
args.response.success({
data:json.listconfigurationsresponse.configuration
});
},
error:function(json){
args.response.error(parseXMLHttpResponse(json));
}
});
},
actions: {
edit: function(args) {
// call updateAccountLevelParameters
var data = {
name: args.data.jsonObj.name,
value: args.data.value
};
$.ajax({
url:createURL('updateConfiguration&accountid=' + args.context.accounts[0].id),
data:data,
success:function(json){
var item = json.updateconfigurationresponse.configuration;
args.response.success({data:item});
},
error: function(json) {
args.response.error(parseXMLHttpResponse(json));
}
});
}
}
})
}
}
}

View File

@ -317,7 +317,15 @@
url: createURL('listAffinityGroups'),
success: function(json) {
var items = json.listaffinitygroupsresponse.affinitygroup;
args.response.success({data: {affinityGroups: items}});
var data = {
affinityGroups: items
};
if('affinityGroups' in args.context) {
$.extend(data, {
selectedObj: args.context.affinityGroups[0]
});
}
args.response.success({data: data});
}
});
},

View File

@ -204,13 +204,7 @@
affinitygroupid: args.context.affinityGroups[0].id
});
}
if(args.context.zoneType != null && args.context.zoneType.length > 0) { //Basic type or Advanced type
$.extend(data, {
zonetype: args.context.zoneType
});
}
$.ajax({
url: createURL('listVirtualMachines'),
data: data,

View File

@ -89,20 +89,7 @@
dataType: "json",
async: true,
success: function(json) {
var zoneObjs;
if(args.context.zoneType == null || args.context.zoneType == '') { //all types
zoneObjs = json.listzonesresponse.zone;
}
else { //Basic type or Advanced type
zoneObjs = [];
var items = json.listzonesresponse.zone;
if(items != null) {
for(var i = 0; i < items.length; i++) {
if(items[i].networktype == args.context.zoneType)
zoneObjs.push(items[i]);
}
}
}
var zoneObjs = json.listzonesresponse.zone;
args.response.success({descriptionField: 'name', data: zoneObjs});
}
});
@ -227,20 +214,7 @@
dataType: "json",
async: true,
success: function(json) {
var zoneObjs;
if(args.context.zoneType == null || args.context.zoneType == '') { //all types
zoneObjs = json.listzonesresponse.zone;
}
else { //Basic type or Advanced type
zoneObjs = [];
var items = json.listzonesresponse.zone;
if(items != null) {
for(var i = 0; i < items.length; i++) {
if(items[i].networktype == args.context.zoneType)
zoneObjs.push(items[i]);
}
}
}
var zoneObjs = json.listzonesresponse.zone;
args.response.success({descriptionField: 'name', data: zoneObjs});
}
});
@ -398,18 +372,12 @@
if(args.context != null) {
if("instances" in args.context) {
$.extend(data, {
virtualMachineId: args.context.instances[0].id
});
$.extend(data, {
virtualMachineId: args.context.instances[0].id
});
}
}
if(args.context.zoneType != null && args.context.zoneType.length > 0) { //Basic type or Advanced type
$.extend(data, {
zonetype: args.context.zoneType
});
}
$.ajax({
url: createURL('listVolumes'),
data: data,

View File

@ -184,16 +184,9 @@
dashboard: {
dataProvider: function(args) {
var dataFns = {
zoneCount: function(data) {
var data = {};
if(cloudStack.context.zoneType != null && cloudStack.context.zoneType.length > 0) { //Basic type or Advanced type
$.extend(data, {
networktype: cloudStack.context.zoneType
});
}
zoneCount: function(data) {
$.ajax({
url: createURL('listZones'),
data: data,
url: createURL('listZones'),
success: function(json) {
dataFns.podCount($.extend(data, {
zoneCount: json.listzonesresponse.count ?
@ -250,12 +243,7 @@
type: 'routing',
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: data2,
@ -272,12 +260,7 @@
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: data2,
@ -294,12 +277,7 @@
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: data2,
@ -333,12 +311,7 @@
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: data2,
@ -349,12 +322,7 @@
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: data3,
@ -2332,12 +2300,7 @@
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("")),
@ -2817,12 +2780,7 @@
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("")),
@ -4708,12 +4666,7 @@
break;
}
}
}
if(args.context.zoneType != null && args.context.zoneType.length > 0) { //Basic type or Advanced type
array1.push("&networktype=" + args.context.zoneType);
}
}
$.ajax({
url: createURL("listZones&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
dataType: "json",
@ -5566,6 +5519,55 @@
}
}
}
},
// Granular settings for zone
settings: {
title: 'Settings',
custom: cloudStack.uiCustom.granularSettings({
dataProvider: function(args) {
$.ajax({
url:createURL('listConfigurations&zoneid=' + args.context.physicalResources[0].id),
data: { page: args.page, pageSize: pageSize, listAll: true },
success:function(json){
args.response.success({
data:json.listconfigurationsresponse.configuration
});
},
error:function(json){
args.response.error(parseXMLHttpResponse(json));
}
});
},
actions: {
edit: function(args) {
// call updateZoneLevelParamter
var data = {
name: args.data.jsonObj.name,
value: args.data.value
};
$.ajax({
url:createURL('updateConfiguration&zoneid=' + args.context.physicalResources[0].id),
data:data,
success:function(json){
var item = json.updateconfigurationresponse.configuration;
args.response.success({data:item});
},
error: function(json) {
args.response.error(parseXMLHttpResponse(json));
}
});
}
}
})
}
}
}
@ -5660,12 +5662,12 @@
var searchByArgs = args.filterBy.search.value.length ?
'&name=' + args.filterBy.search.value : '';
var data = { page: args.page, pageSize: pageSize, type: 'routing', listAll: true };
if(args.context.zoneType != null && args.context.zoneType.length > 0) { //Basic type or Advanced type
$.extend(data, {
zonetype: args.context.zoneType
});
}
var data = {
page: args.page,
pageSize: pageSize,
type: 'routing',
listAll: true
};
$.ajax({
url: createURL('listHosts' + searchByArgs),
@ -5714,11 +5716,7 @@
pageSize: pageSize,
listAll: true
};
if(args.context.zoneType != null && args.context.zoneType.length > 0) { //Basic type or Advanced type
$.extend(data, {
zonetype: args.context.zoneType
});
}
$.ajax({
url: createURL('listStoragePools' + searchByArgs),
data: data,
@ -5761,12 +5759,12 @@
var searchByArgs = args.filterBy.search.value.length ?
'&name=' + args.filterBy.search.value : '';
var data = { type: 'SecondaryStorage', page: args.page, pageSize: pageSize, listAll: true };
if(args.context.zoneType != null && args.context.zoneType.length > 0) { //Basic type or Advanced type
$.extend(data, {
zonetype: args.context.zoneType
});
}
var data = {
type: 'SecondaryStorage',
page: args.page,
pageSize: pageSize,
listAll: true
};
$.ajax({
url: createURL('listHosts' + searchByArgs),
@ -5850,18 +5848,11 @@
var listView = $.extend(true, {}, cloudStack.sections.system.subsections.virtualRouters.listView, {
dataProvider: function (args) {
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
});
}
'&name=' + args.filterBy.search.value : '';
var routers = [];
$.ajax({
url: createURL("listRouters&listAll=true&page=" + args.page + "&pagesize=" + pageSize + searchByArgs),
data: data2,
url: createURL("listRouters&listAll=true&page=" + args.page + "&pagesize=" + pageSize + searchByArgs),
async: true,
success: function(json) {
var items = json.listroutersresponse.router ?
@ -5873,8 +5864,7 @@
// Get project routers
$.ajax({
url: createURL("listRouters&listAll=true&page=" + args.page + "&pagesize=" + pageSize + "&projectid=-1"),
data: data2,
url: createURL("listRouters&listAll=true&page=" + args.page + "&pagesize=" + pageSize + "&projectid=-1"),
async: true,
success: function(json) {
var items = json.listroutersresponse.router ?
@ -5961,11 +5951,7 @@
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("")),
@ -6278,6 +6264,80 @@
}
},
scaleUp:{
label:'scaleUp Router VM',
createForm: {
title: 'label.change.service.offering',
desc: '',
fields: {
serviceOfferingId: {
label: 'label.compute.offering',
select: function(args) {
$.ajax({
url: createURL('listServiceOfferings'),
data: {
issystem: true,
systemvmtype: 'domainrouter'
},
success: function(json) {
var serviceofferings = json.listserviceofferingsresponse.serviceoffering;
var items = [];
$(serviceofferings).each(function() {
// if(this.id != args.context.routers[0].serviceofferingid) {
items.push({id: this.id, description: this.name}); //default one (i.e. "System Offering For Software Router") doesn't have displaytext property. So, got to use name property instead.
});
args.response.success({data: items});
}
});
}
}
}
},
action: function(args) {
$.ajax({
url: createURL("scaleVirtualMachine&id=" + args.context.routers[0].id + "&serviceofferingid=" + args.data.serviceOfferingId),
dataType: "json",
async: true,
success: function(json) {
var jid = json.scalevirtualmachineresponse.jobid;
args.response.success(
{_custom:
{jobId: jid,
getUpdatedItem: function(json) {
return json.queryasyncjobresultresponse.jobresult.virtualmachine;
},
getActionFilter: function() {
return vmActionfilter;
}
}
}
);
},
error:function(json){
args.response.error(parseXMLHttpResponse(json));
}
});
},
messages: {
confirm: function(args) {
return 'Do you really want to scale up the Router VM ?';
},
notification: function(args) {
return 'Router VM Scaled Up';
}
},
notification: {
poll: pollAsyncJobResult
}
},
viewConsole: {
label: 'label.view.console',
action: {
@ -9085,6 +9145,57 @@
});
}
}
},
// Granular settings for cluster
settings: {
title: 'Settings',
custom: cloudStack.uiCustom.granularSettings({
dataProvider: function(args) {
$.ajax({
url:createURL('listConfigurations&clusterid=' + args.context.clusters[0].id),
data: { page: args.page, pageSize: pageSize, listAll: true },
success:function(json){
args.response.success({
data:json.listconfigurationsresponse.configuration
});
},
error:function(json){
args.response.error(parseXMLHttpResponse(json));
}
});
},
actions: {
edit: function(args) {
// call updateClusterLevelParameters
var data = {
name: args.data.jsonObj.name,
value: args.data.value
};
$.ajax({
url:createURL('updateConfiguration&clusterid=' + args.context.clusters[0].id),
data:data,
success:function(json){
var item = json.updateconfigurationresponse.configuration;
args.response.success({data:item});
},
error: function(json) {
args.response.error(parseXMLHttpResponse(json));
}
});
}
}
})
}
}
}
@ -9135,11 +9246,7 @@
} else {
array1.push("&hostid=" + args.context.instances[0].hostid);
}
if(args.context.zoneType != null && args.context.zoneType.length > 0) { //Basic type or Advanced type
array1.push("&zonetype=" + args.context.zoneType);
}
$.ajax({
url: createURL("listHosts&type=Routing" + array1.join("") + "&page=" + args.page + "&pagesize=" + pageSize),
dataType: "json",
@ -10524,6 +10631,7 @@
detailView: {
name: "Primary storage details",
isMaximized: true,
actions: {
edit: {
label: 'label.edit',
@ -10708,6 +10816,57 @@
}
});
}
},
// Granular settings for storage pool
settings: {
title: 'Settings',
custom: cloudStack.uiCustom.granularSettings({
dataProvider: function(args) {
$.ajax({
url:createURL('listConfigurations&storageid=' + args.context.primarystorages[0].id),
data: { page: args.page, pageSize: pageSize, listAll: true },
success:function(json){
args.response.success({
data:json.listconfigurationsresponse.configuration
});
},
error:function(json){
args.response.error(parseXMLHttpResponse(json));
}
});
},
actions: {
edit: function(args) {
// call updateStorageLevelParameters
var data = {
name: args.data.jsonObj.name,
value: args.data.value
};
$.ajax({
url:createURL('updateConfiguration&storageid=' + args.context.primarystorages[0].id),
data:data,
success:function(json){
var item = json.updateconfigurationresponse.configuration;
args.response.success({data:item});
},
error: function(json) {
args.response.error(parseXMLHttpResponse(json));
}
});
}
}
})
}
}
}
@ -10747,10 +10906,6 @@
}
array1.push("&zoneid=" + args.context.zones[0].id);
if(args.context.zoneType != null && args.context.zoneType.length > 0) { //Basic type or Advanced type
array1.push("&zonetype=" + args.context.zoneType);
}
$.ajax({
url: createURL("listHosts&type=SecondaryStorage&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
dataType: "json",
@ -10851,6 +11006,7 @@
detailView: {
name: 'Secondary storage details',
isMaximized: true,
actions: {
remove: {
label: 'label.action.delete.secondary.storage' ,
@ -10907,6 +11063,27 @@
});
}
}
// Granular settings for storage pool for secondary storage is not required
/* settings: {
title: 'label.menu.global.settings',
custom: cloudStack.uiCustom.granularSettings({
dataProvider: function(args) {
args.response.success({
data: [
{ name: 'config.param.1', value: 1 },
{ name: 'config.param.2', value: 2 }
]
});
},
actions: {
edit: function(args) {
// call updateStorageLevelParameters
args.response.success();
}
}
})
} */
}
}
}
@ -11816,9 +11993,9 @@
if (jsonObj.state == 'Running') {
allowedActions.push("stop");
allowedActions.push("scaleUp");
// if(jsonObj.vpcid != null)
allowedActions.push("restart");
allowedActions.push("restart");
allowedActions.push("viewConsole");
if (isAdmin())
@ -11826,7 +12003,8 @@
}
else if (jsonObj.state == 'Stopped') {
allowedActions.push("start");
allowedActions.push("remove");
allowedActions.push("scaleUp");
allowedActions.push("remove");
if(jsonObj.vpcid != null)
allowedActions.push("changeService");

View File

@ -116,27 +116,13 @@
dataType: "json",
async: true,
success: function(json) {
var zoneObjs;
if(args.context.zoneType == null || args.context.zoneType == '') { //all types
zoneObjs = [];
var items = json.listzonesresponse.zone;
if(items != null) {
for(var i = 0; i < items.length; i++) {
zoneObjs.push({id: items[i].id, description: items[i].name});
}
var zoneObjs= [];
var items = json.listzonesresponse.zone;
if(items != null) {
for(var i = 0; i < items.length; i++) {
zoneObjs.push({id: items[i].id, description: items[i].name});
}
}
else { //Basic type or Advanced type
zoneObjs = [];
var items = json.listzonesresponse.zone;
if(items != null) {
for(var i = 0; i < items.length; i++) {
if(items[i].networktype == args.context.zoneType) {
zoneObjs.push({id: items[i].id, description: items[i].name});
}
}
}
}
}
if (isAdmin() && !(cloudStack.context.projects && cloudStack.context.projects[0])){
zoneObjs.unshift({id: -1, description: "All Zones"});
}
@ -548,27 +534,14 @@
async: true,
success: function(json) {
var zoneObjs = [];
var items = json.listzonesresponse.zone;
if(args.context.zoneType == null || args.context.zoneType == '') { //all types
if(items != null) {
for(var i = 0; i < items.length; i++) {
if(items[i].id != args.context.templates[0].zoneid) { //destination zone must be different from source zone
zoneObjs.push({id: items[i].id, description: items[i].name});
}
}
var items = json.listzonesresponse.zone;
if(items != null) {
for(var i = 0; i < items.length; i++) {
if(items[i].id != args.context.templates[0].zoneid) { //destination zone must be different from source zone
zoneObjs.push({id: items[i].id, description: items[i].name});
}
}
}
else { //Basic type or Advanced type
if(items != null) {
for(var i = 0; i < items.length; i++) {
if(items[i].networktype == args.context.zoneType) { //type must be matched
if(items[i].id != args.context.templates[0].zoneid) { //destination zone must be different from source zone
zoneObjs.push({id: items[i].id, description: items[i].name});
}
}
}
}
}
}
args.response.success({data: zoneObjs});
}
});
@ -894,27 +867,13 @@
dataType: "json",
async: true,
success: function(json) {
var zoneObjs;
if(args.context.zoneType == null || args.context.zoneType == '') { //all types
zoneObjs = [];
var items = json.listzonesresponse.zone;
if(items != null) {
for(var i = 0; i < items.length; i++) {
zoneObjs.push({id: items[i].id, description: items[i].name});
}
var zoneObjs = [];
var items = json.listzonesresponse.zone;
if(items != null) {
for(var i = 0; i < items.length; i++) {
zoneObjs.push({id: items[i].id, description: items[i].name});
}
}
else { //Basic type or Advanced type
zoneObjs = [];
var items = json.listzonesresponse.zone;
if(items != null) {
for(var i = 0; i < items.length; i++) {
if(items[i].networktype == args.context.zoneType) {
zoneObjs.push({id: items[i].id, description: items[i].name});
}
}
}
}
}
if (isAdmin() && !(cloudStack.context.projects && cloudStack.context.projects[0])){
zoneObjs.unshift({id: -1, description: "All Zones"});
}
@ -1224,27 +1183,14 @@
async: true,
success: function(json) {
var zoneObjs = [];
var items = json.listzonesresponse.zone;
if(args.context.zoneType == null || args.context.zoneType == '') { //all types
if(items != null) {
for(var i = 0; i < items.length; i++) {
if(items[i].id != args.context.isos[0].zoneid) { //destination zone must be different from source zone
zoneObjs.push({id: items[i].id, description: items[i].name});
}
}
var items = json.listzonesresponse.zone;
if(items != null) {
for(var i = 0; i < items.length; i++) {
if(items[i].id != args.context.isos[0].zoneid) { //destination zone must be different from source zone
zoneObjs.push({id: items[i].id, description: items[i].name});
}
}
}
else { //Basic type or Advanced type
if(items != null) {
for(var i = 0; i < items.length; i++) {
if(items[i].networktype == args.context.zoneType) { //type must be matched
if(items[i].id != args.context.isos[0].zoneid) { //destination zone must be different from source zone
zoneObjs.push({id: items[i].id, description: items[i].name});
}
}
}
}
}
}
args.response.success({data: zoneObjs});
}
});

View File

@ -0,0 +1,46 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
(function($, cloudStack) {
cloudStack.uiCustom.granularSettings = function(args) {
var dataProvider = args.dataProvider;
var actions = args.actions;
return function(args) {
var context = args.context;
var listView = {
id: 'settings',
fields: {
name: { label: 'label.name' },
value: { label: 'label.value', editable: true }
},
actions: {
edit: {
label: 'label.change.value',
action: actions.edit
}
},
dataProvider: dataProvider
};
var $listView = $('<div>').listView({ context: context, listView: listView });
return $listView;
}
};
}(jQuery, cloudStack));

View File

@ -86,7 +86,7 @@
});
};
var makeSelects = function(name, data, fields, options) {
var makeSelects = function(name, data, fields, options, selectedObj) {
var $selects = $('<div>');
options = options ? options : {};
@ -151,7 +151,11 @@
.append($('<div>').addClass('desc').html(_s(this[fields.desc])))
)
.data('json-obj', this);
if(selectedObj != null && selectedObj.id == item.id) {
$select.find('input[type=checkbox]').attr('checked', 'checked');
}
$selects.append($select);
if (item._singleSelect) {
@ -493,14 +497,20 @@
)
);
$step.find('.select-container').append(
makeSelects('affinity-groups', args.data.affinityGroups, {
name: 'name',
desc: 'description',
id: 'id'
}, {
type: 'checkbox',
'wizard-field': 'affinity-groups'
})
makeSelects(
'affinity-groups',
args.data.affinityGroups,
{
name: 'name',
desc: 'description',
id: 'id'
},
{
type: 'checkbox',
'wizard-field': 'affinity-groups'
},
args.data.selectedObj
)
);
} else {
$step.find('.select-container').append($('<p>').html(_l('message.no.affinity.groups')));

View File

@ -653,6 +653,11 @@
});
});
var itemState=multiRule._itemState ? item[multiRule._itemState] :item.state;
var $itemState = $('<span>').html(_s(itemState));
$tr.append($('<td>').addClass('state').appendTo($tr).append("Application State - ").append($itemState));
if (itemActions) {
var $itemActions = $('<td>').addClass('actions item-actions');

View File

@ -170,7 +170,7 @@
},
action: function(args) {
$.ajax({
url: createURL("revertToSnapshot&vmsnapshotid=" + args.context.vmsnapshots[0].id),
url: createURL("revertToVMSnapshot&vmsnapshotid=" + args.context.vmsnapshots[0].id),
dataType: "json",
async: true,
success: function(json) {

View File

@ -737,6 +737,12 @@
actions:{
add:{
label:'Add Private Gateway',
preFilter: function(args) {
if(isAdmin() || isDomainAdmin() )
return true;
else
return false;
},
createForm:{
title: 'label.add.new.gateway',
desc: 'message.add.new.gateway.to.vpc',

View File

@ -627,7 +627,7 @@ public class NetUtils {
return result;
}
public static Set<Long> getAllIpsFromCidr(String cidr, long size) {
public static Set<Long> getAllIpsFromCidr(String cidr, long size, Set<Long> usedIps) {
assert (size < 32) : "You do know this is not for ipv6 right? Keep it smaller than 32 but you have " + size;
Set<Long> result = new TreeSet<Long>();
long ip = ip2Long(cidr);
@ -639,8 +639,12 @@ public class NetUtils {
end++;
end = (end << (32 - size)) - 2;
while (start <= end) {
result.add(start);
int maxIps = 255; // get 255 ips as maximum
while (start <= end && maxIps > 0) {
if (!usedIps.contains(start)){
result.add(start);
maxIps--;
}
start++;
}

View File

@ -1281,6 +1281,7 @@ public class VirtualMachineMO extends BaseMO {
long totalBytesDownloaded = 0;
List<HttpNfcLeaseDeviceUrl> deviceUrls = leaseInfo.getDeviceUrl();
s_logger.info("volss: copy vmdk and ovf file starts " + System.currentTimeMillis());
if(deviceUrls != null) {
OvfFile[] ovfFiles = new OvfFile[deviceUrls.size()];
for (int i = 0; i < deviceUrls.size(); i++) {
@ -1328,7 +1329,7 @@ public class VirtualMachineMO extends BaseMO {
// tar files into OVA
if(packToOva) {
// Important! we need to sync file system before we can safely use tar to work around a linux kernal bug(or feature)
// Important! we need to sync file system before we can safely use tar to work around a linux kernal bug(or feature)
s_logger.info("Sync file system before we package OVA...");
Script commandSync = new Script(true, "sync", 0, s_logger);
@ -1351,8 +1352,11 @@ public class VirtualMachineMO extends BaseMO {
} else {
s_logger.error(exportDir + File.separator + exportName + ".ova is not created as expected");
}
} else {
success = true;
}
}
s_logger.info("volss: copy vmdk and ovf file finishes " + System.currentTimeMillis());
} catch(Throwable e) {
s_logger.error("Unexpected exception ", e);
} finally {

View File

@ -528,7 +528,7 @@ public class VmwareClient {
PropertySpec pSpec = new PropertySpec();
pSpec.setType(type);
pSpec.setAll(false);
pSpec.getPathSet().add(name);
pSpec.getPathSet().add("name");
ObjectSpec oSpec = new ObjectSpec();
oSpec.setObj(root);