diff --git a/agent/src/com/cloud/agent/AgentShell.java b/agent/src/com/cloud/agent/AgentShell.java index 2af08e9bf21..73b3950e7e4 100644 --- a/agent/src/com/cloud/agent/AgentShell.java +++ b/agent/src/com/cloud/agent/AgentShell.java @@ -38,12 +38,10 @@ import java.util.UUID; import javax.naming.ConfigurationException; -import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; import org.apache.log4j.xml.DOMConfigurator; import com.cloud.agent.Agent.ExitStatus; @@ -373,6 +371,7 @@ public class AgentShell implements IAgentShell { throw new ConfigurationException("Unable to find the guid"); } _guid = UUID.randomUUID().toString(); + _properties.setProperty("guid", _guid); } return true; diff --git a/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java b/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java index 516430b2fed..991764c53f8 100644 --- a/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java +++ b/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java @@ -235,14 +235,14 @@ public class ConsoleProxyResource extends ServerResourceBase implements if (_eth1ip != null) { params.put("private.network.device", "eth1"); } else { - s_logger.warn("WARNING: eth1ip parameter is not found!"); + s_logger.info("eth1ip parameter has not been configured, assuming that we are not inside a system vm"); } String eth2ip = (String) params.get("eth2ip"); if (eth2ip != null) { params.put("public.network.device", "eth2"); } else { - s_logger.warn("WARNING: eth2ip parameter is not found!"); + s_logger.info("eth2ip parameter is not found, assuming that we are not inside a system vm"); } super.configure(name, params); diff --git a/api/src/com/cloud/agent/api/to/FirewallRuleTO.java b/api/src/com/cloud/agent/api/to/FirewallRuleTO.java index 7f779365c9e..f296aa4d1f9 100644 --- a/api/src/com/cloud/agent/api/to/FirewallRuleTO.java +++ b/api/src/com/cloud/agent/api/to/FirewallRuleTO.java @@ -23,6 +23,7 @@ import org.apache.cloudstack.api.InternalIdentity; import com.cloud.network.rules.FirewallRule; import com.cloud.network.rules.FirewallRule.State; +import com.cloud.network.rules.FirewallRule.TrafficType; import com.cloud.utils.net.NetUtils; /** @@ -109,6 +110,11 @@ public class FirewallRuleTO implements InternalIdentity { this(rule.getId(),srcVlanTag, srcIp, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), revokeState, alreadyAdded, purpose,rule.getSourceCidrList(),rule.getIcmpType(),rule.getIcmpCode()); } + public FirewallRuleTO(FirewallRule rule, String guestVlanTag, FirewallRule.TrafficType trafficType) { + this(rule.getId(), guestVlanTag, null, rule.getProtocol(), rule.getSourcePortStart(), rule.getSourcePortEnd(), rule.getState()==State.Revoke, rule.getState()==State.Active, rule.getPurpose(), rule.getSourceCidrList(), rule.getIcmpType(), rule.getIcmpCode()); + this.trafficType = trafficType; + } + public FirewallRule.TrafficType getTrafficType(){ return trafficType; } diff --git a/api/src/com/cloud/api/commands/CreatePrivateNetworkCmd.java b/api/src/com/cloud/api/commands/CreatePrivateNetworkCmd.java deleted file mode 100644 index 2b63c64425d..00000000000 --- a/api/src/com/cloud/api/commands/CreatePrivateNetworkCmd.java +++ /dev/null @@ -1,197 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package com.cloud.api.commands; - -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseAsyncCreateCmd; -import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.response.DomainResponse; -import org.apache.cloudstack.api.response.NetworkResponse; -import org.apache.cloudstack.api.response.PhysicalNetworkResponse; -import org.apache.cloudstack.api.response.ProjectResponse; -import org.apache.log4j.Logger; - -import com.cloud.event.EventTypes; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.ResourceAllocationException; -import com.cloud.network.Network; -import com.cloud.user.UserContext; - -//@APICommand(description="Creates a private network", responseObject=NetworkResponse.class) -public class CreatePrivateNetworkCmd extends BaseAsyncCreateCmd { - public static final Logger s_logger = Logger.getLogger(CreatePrivateNetworkCmd.class.getName()); - - private static final String s_name = "createnetworkresponse"; - - ///////////////////////////////////////////////////// - //////////////// API parameters ///////////////////// - ///////////////////////////////////////////////////// - - @Parameter(name=ApiConstants.NAME, type=CommandType.STRING, required=true, description="the name of the network") - private String name; - - @Parameter(name=ApiConstants.DISPLAY_TEXT, type=CommandType.STRING, required=true, description="the display text of the network") - private String displayText; - - @Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.UUID, entityType = PhysicalNetworkResponse.class, - required=true, description="the Physical Network ID the network belongs to") - private Long physicalNetworkId; - - @Parameter(name=ApiConstants.GATEWAY, type=CommandType.STRING, required=true, description="the gateway of the network") - private String gateway; - - @Parameter(name=ApiConstants.NETMASK, type=CommandType.STRING, required=true, description="the netmask of the network") - private String netmask; - - @Parameter(name=ApiConstants.START_IP, type=CommandType.STRING, required=true, description="the beginning IP address in the network IP range") - private String startIp; - - @Parameter(name=ApiConstants.END_IP, type=CommandType.STRING, description="the ending IP address in the network IP" + - " range. If not specified, will be defaulted to startIP") - private String endIp; - - @Parameter(name=ApiConstants.VLAN, type=CommandType.STRING, required=true, description="the ID or VID of the network") - private String vlan; - - @Parameter(name=ApiConstants.ACCOUNT, type=CommandType.STRING, description="account who will own the network") - private String accountName; - - @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, entityType = ProjectResponse.class, - description="an optional project for the ssh key") - private Long projectId; - - @Parameter(name=ApiConstants.DOMAIN_ID, type=CommandType.UUID, entityType = DomainResponse.class, - description="domain ID of the account owning a network") - private Long domainId; - - - ///////////////////////////////////////////////////// - /////////////////// Accessors /////////////////////// - ///////////////////////////////////////////////////// - - public String getGateway() { - return gateway; - } - - public String getVlan() { - return vlan; - } - - public String getAccountName() { - return accountName; - } - - public Long getDomainId() { - return domainId; - } - - public String getNetmask() { - return netmask; - } - - public String getStartIp() { - return startIp; - } - - public String getNetworkName() { - return name; - } - - public String getDisplayText() { - return displayText; - } - - public Long getProjectId() { - return projectId; - } - - public long getPhysicalNetworkId() { - return physicalNetworkId; - } - - public String getEndIp() { - return endIp; - } - - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// - @Override - public String getCommandName() { - return s_name; - } - - - @Override - public void create() throws ResourceAllocationException { - Network result = null; - try { - result = _networkService.createPrivateNetwork(getNetworkName(), getDisplayText(), getPhysicalNetworkId(), getVlan(), - getStartIp(), getEndIp(), getGateway(), getNetmask(), getEntityOwnerId(), null); - } catch (InsufficientCapacityException ex){ - s_logger.info(ex); - s_logger.trace(ex); - throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage()); - } catch (ConcurrentOperationException ex) { - s_logger.warn("Exception: ", ex); - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage()); - } - - if (result != null) { - this.setEntityId(result.getId()); - this.setEntityUuid(result.getUuid()); - } else { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create a Private network"); - } - } - - @Override - public void execute() throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException{ - Network result = _networkService.getNetwork(getEntityId()); - if (result != null) { - NetworkResponse response = _responseGenerator.createNetworkResponse(result); - response.setResponseName(getCommandName()); - this.setResponseObject(response); - } else { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create private network"); - } - } - - @Override - public long getEntityOwnerId() { - Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); - if (accountId == null) { - return UserContext.current().getCaller().getId(); - } - return accountId; - } - - @Override - public String getEventType() { - return EventTypes.EVENT_NETWORK_CREATE; - } - - @Override - public String getEventDescription() { - return "creating private network"; - - } - -} diff --git a/api/src/com/cloud/api/commands/DestroyConsoleProxyCmd.java b/api/src/com/cloud/api/commands/DestroyConsoleProxyCmd.java deleted file mode 100644 index 829283e8b9f..00000000000 --- a/api/src/com/cloud/api/commands/DestroyConsoleProxyCmd.java +++ /dev/null @@ -1,93 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package com.cloud.api.commands; - -import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.ApiErrorCode; -import org.apache.cloudstack.api.BaseAsyncCmd; -import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.response.SuccessResponse; -import org.apache.log4j.Logger; - -import com.cloud.event.EventTypes; -import com.cloud.user.Account; -import com.cloud.user.UserContext; - -//@APICommand(description="Destroys console proxy", responseObject=SuccessResponse.class) -public class DestroyConsoleProxyCmd extends BaseAsyncCmd { - public static final Logger s_logger = Logger.getLogger(DestroyConsoleProxyCmd.class.getName()); - - private static final String s_name = "destroyconsoleproxyresponse"; - - ///////////////////////////////////////////////////// - //////////////// API parameters ///////////////////// - ///////////////////////////////////////////////////// - - @Parameter(name=ApiConstants.ID, type=CommandType.LONG, required=true, description="console proxy ID") - private Long id; - - - ///////////////////////////////////////////////////// - /////////////////// Accessors /////////////////////// - ///////////////////////////////////////////////////// - - public Long getId() { - return id; - } - - - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// - - @Override - public String getCommandName() { - return s_name; - } - - @Override - public long getEntityOwnerId() { - Account account = (Account)UserContext.current().getCaller(); - if (account != null) { - return account.getId(); - } - - return Account.ACCOUNT_ID_SYSTEM; // no account info given, parent this command to SYSTEM so ERROR events are tracked - } - - @Override - public String getEventType() { - return EventTypes.EVENT_PROXY_DESTROY; - } - - @Override - public String getEventDescription() { - return "destroying console proxy: " + getId(); - } - - @Override - public void execute(){ - boolean result = _consoleProxyService.destroyConsoleProxy(this); - if (result) { - SuccessResponse response = new SuccessResponse(getCommandName()); - this.setResponseObject(response); - } else { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to destroy console proxy"); - } - } -} diff --git a/api/src/com/cloud/offering/NetworkOffering.java b/api/src/com/cloud/offering/NetworkOffering.java index 8cb82996036..bd14acd4718 100644 --- a/api/src/com/cloud/offering/NetworkOffering.java +++ b/api/src/com/cloud/offering/NetworkOffering.java @@ -46,6 +46,7 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity, public final static String SystemPrivateGatewayNetworkOffering = "System-Private-Gateway-Network-Offering"; public final static String DefaultSharedNetworkOfferingWithSGService = "DefaultSharedNetworkOfferingWithSGService"; + public final static String QuickCloudNoServices = "QuickCloudNoServices"; public final static String DefaultIsolatedNetworkOfferingWithSourceNatService = "DefaultIsolatedNetworkOfferingWithSourceNatService"; public final static String OvsIsolatedNetworkOfferingWithSourceNatService = "OvsIsolatedNetworkOfferingWithSourceNatService"; public final static String DefaultSharedNetworkOffering = "DefaultSharedNetworkOffering"; diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java index 78a2af36aa2..8fef422b915 100644 --- a/api/src/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseCmd.java @@ -32,7 +32,6 @@ import org.apache.cloudstack.usage.UsageService; import org.apache.log4j.Logger; import com.cloud.configuration.ConfigurationService; -import com.cloud.consoleproxy.ConsoleProxyService; import com.cloud.dao.EntityManager; import com.cloud.domain.Domain; import com.cloud.exception.ConcurrentOperationException; @@ -109,7 +108,6 @@ public abstract class BaseCmd { @Inject public TemplateService _templateService; @Inject public SecurityGroupService _securityGroupService; @Inject public SnapshotService _snapshotService; - @Inject public ConsoleProxyService _consoleProxyService; @Inject public VpcVirtualNetworkApplianceService _routerService; @Inject public ResponseGenerator _responseGenerator; @Inject public EntityManager _entityMgr; diff --git a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java index f0dbf16b250..aa9feb8e2a3 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/CreateVMSnapshotCmd.java @@ -34,7 +34,7 @@ import com.cloud.user.UserContext; import com.cloud.uservm.UserVm; import com.cloud.vm.snapshot.VMSnapshot; -@APICommand(name = "createVMSnapshot", description = "Creates snapshot for a vm.", responseObject = VMSnapshotResponse.class) +@APICommand(name = "createVMSnapshot", description = "Creates snapshot for a vm.", responseObject = VMSnapshotResponse.class, since="4.2.0") public class CreateVMSnapshotCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger diff --git a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java index a2b2c08b381..bda84c893a5 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/DeleteVMSnapshotCmd.java @@ -32,7 +32,7 @@ import com.cloud.user.Account; import com.cloud.user.UserContext; import com.cloud.vm.snapshot.VMSnapshot; -@APICommand(name="deleteVMSnapshot", description = "Deletes a vmsnapshot.", responseObject = SuccessResponse.class) +@APICommand(name="deleteVMSnapshot", description = "Deletes a vmsnapshot.", responseObject = SuccessResponse.class, since="4.2.0") public class DeleteVMSnapshotCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger .getLogger(DeleteVMSnapshotCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/ListVMSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/ListVMSnapshotCmd.java index 936d348950d..82fb9e57877 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/ListVMSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/ListVMSnapshotCmd.java @@ -30,7 +30,7 @@ import org.apache.cloudstack.api.response.VMSnapshotResponse; import com.cloud.vm.snapshot.VMSnapshot; -@APICommand(name="listVMSnapshot", description = "List virtual machine snapshot by conditions", responseObject = VMSnapshotResponse.class) +@APICommand(name="listVMSnapshot", description = "List virtual machine snapshot by conditions", responseObject = VMSnapshotResponse.class, since="4.2.0") public class ListVMSnapshotCmd extends BaseListTaggedResourcesCmd { private static final String s_name = "listvmsnapshotresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/RevertToSnapshotCmd.java b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/RevertToSnapshotCmd.java index d7b4599d6c4..ea7bf60d6a3 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/RevertToSnapshotCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vmsnapshot/RevertToSnapshotCmd.java @@ -37,7 +37,7 @@ 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) +@APICommand(name = "revertToSnapshot",description = "Revert VM from a vmsnapshot.", responseObject = UserVmResponse.class, since="4.2.0") public class RevertToSnapshotCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger .getLogger(RevertToSnapshotCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/response/FirewallRuleResponse.java b/api/src/org/apache/cloudstack/api/response/FirewallRuleResponse.java index 08722ae2c6b..787410a24c5 100644 --- a/api/src/org/apache/cloudstack/api/response/FirewallRuleResponse.java +++ b/api/src/org/apache/cloudstack/api/response/FirewallRuleResponse.java @@ -71,6 +71,18 @@ public class FirewallRuleResponse extends BaseResponse { @SerializedName(ApiConstants.TAGS) @Param(description="the list of resource tags associated with the rule", responseObject = ResourceTagResponse.class) private List tags; + @SerializedName(ApiConstants.VM_GUEST_IP) @Param(description="the vm ip address for the port forwarding rule") + private String destNatVmIp; + + + public String getDestNatVmIp() { + return destNatVmIp; + } + + public void setDestNatVmIp(String destNatVmIp) { + this.destNatVmIp = destNatVmIp; + } + @Override public String getObjectId() { diff --git a/client/pom.xml b/client/pom.xml index 9323d0fb20f..b3d7acb08a8 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -453,6 +453,22 @@ + + process-quickcloud-spring-context + process-resources + + run + + + + quickcloud + + + + diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in index 3b51a83e6ad..67b1286eaed 100644 --- a/client/tomcatconf/applicationContext.xml.in +++ b/client/tomcatconf/applicationContext.xml.in @@ -503,7 +503,7 @@ - + diff --git a/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java b/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java index b525a2d05d5..fafc0a33af0 100644 --- a/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java +++ b/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java @@ -62,6 +62,9 @@ public class HypervisorCapabilitiesVO implements HypervisorCapabilities { @Column(name="max_hosts_per_cluster") private Integer maxHostsPerCluster; + @Column(name="vm_snapshot_enabled") + private Boolean vmSnapshotEnabled; + protected HypervisorCapabilitiesVO() { this.uuid = UUID.randomUUID().toString(); } @@ -169,7 +172,15 @@ public class HypervisorCapabilitiesVO implements HypervisorCapabilities { this.maxHostsPerCluster = maxHostsPerCluster; } - @Override + public Boolean getVmSnapshotEnabled() { + return vmSnapshotEnabled; + } + + public void setVmSnapshotEnabled(Boolean vmSnapshotEnabled) { + this.vmSnapshotEnabled = vmSnapshotEnabled; + } + + @Override public boolean equals(Object obj) { if (obj instanceof HypervisorCapabilitiesVO) { return ((HypervisorCapabilitiesVO)obj).getId() == this.getId(); diff --git a/core/src/com/cloud/resource/ServerResourceBase.java b/core/src/com/cloud/resource/ServerResourceBase.java index 9449b058556..e381fcbec86 100755 --- a/core/src/com/cloud/resource/ServerResourceBase.java +++ b/core/src/com/cloud/resource/ServerResourceBase.java @@ -80,7 +80,7 @@ public abstract class ServerResourceBase implements ServerResource { _storageNic2 = getNetworkInterface(storageNic2); if (_privateNic == null) { - s_logger.error("Nics are not configured!"); + s_logger.warn("Nics are not specified in properties file/db, will try to autodiscover"); Enumeration nics = null; try { diff --git a/deps/install-non-oss.sh b/deps/install-non-oss.sh index 74575a8dbd1..0bf8e48d70c 100755 --- a/deps/install-non-oss.sh +++ b/deps/install-non-oss.sh @@ -17,7 +17,6 @@ # under the License. mvn install:install-file -Dfile=cloud-iControl.jar -DgroupId=com.cloud.com.f5 -DartifactId=icontrol -Dversion=1.0 -Dpackaging=jar -mvn install:install-file -Dfile=cloud-netscaler.jar -DgroupId=com.cloud.com.citrix -DartifactId=netscaler -Dversion=1.0 -Dpackaging=jar mvn install:install-file -Dfile=cloud-netscaler-sdx.jar -DgroupId=com.cloud.com.citrix -DartifactId=netscaler-sdx -Dversion=1.0 -Dpackaging=jar # From http://support.netapp.com/ (not available online, contact your support representative) @@ -25,18 +24,6 @@ mvn install:install-file -Dfile=cloud-netscaler-sdx.jar -DgroupId=com.cloud.com. if [ -e cloud-manageontap.jar ]; then mv cloud-manageontap.jar manageontap.jar; fi mvn install:install-file -Dfile=manageontap.jar -DgroupId=com.cloud.com.netapp -DartifactId=manageontap -Dversion=4.0 -Dpackaging=jar -# From https://my.vmware.com/group/vmware/get-download?downloadGroup=VSDK41 -# Version: 4.1, Release-date: 2010-07-13, Build: 257238 -if [ -e vmware-apputils.jar ]; then mv vmware-apputils.jar apputils.jar; fi -if [ -e vmware-vim.jar ]; then mv vmware-vim.jar vim.jar; fi -if [ -e vmware-vim25.jar ]; then mv vmware-vim25.jar vim25.jar; fi -mvn install:install-file -Dfile=vim25.jar -DgroupId=com.cloud.com.vmware -DartifactId=vmware-vim25 -Dversion=4.1 -Dpackaging=jar -mvn install:install-file -Dfile=apputils.jar -DgroupId=com.cloud.com.vmware -DartifactId=vmware-apputils -Dversion=4.1 -Dpackaging=jar -mvn install:install-file -Dfile=vim.jar -DgroupId=com.cloud.com.vmware -DartifactId=vmware-vim -Dversion=4.1 -Dpackaging=jar - -# # From https://my.vmware.com/group/vmware/get-download?downloadGroup=VSP510-WEBSDK-510 # Version: 5.1, Release-date: 2012-09-10, Build: 774886 mvn install:install-file -Dfile=vim25_51.jar -DgroupId=com.cloud.com.vmware -DartifactId=vmware-vim25 -Dversion=5.1 -Dpackaging=jar - - diff --git a/docs/en-US/Book_Info.xml b/docs/en-US/Book_Info.xml index c125ab8de2b..0ab84c40d9b 100644 --- a/docs/en-US/Book_Info.xml +++ b/docs/en-US/Book_Info.xml @@ -27,7 +27,7 @@ &PRODUCT; Guide Revised August 9, 2012 10:48 pm Pacific Apache CloudStack - 4.0.0-incubating + 4.0.0 1 diff --git a/docs/en-US/Release_Notes.xml b/docs/en-US/Release_Notes.xml index 00cbc49c881..b8c5c01fb0b 100644 --- a/docs/en-US/Release_Notes.xml +++ b/docs/en-US/Release_Notes.xml @@ -33,7 +33,7 @@ under the License. If you run into any issues during upgrades, please feel free to ask questions on users@apache.cloudstack.org or dev@apache.cloudstack.org.
Upgrade from 4.0.x to 4.1.0 - This section will guide you from Apache CloudStack 4.0.x versions (4.0.0-incubating, 4.0.1-incubating, and 4.0.2) to &PRODUCT; 4.1.0. + This section will guide you from Apache CloudStack 4.0.x versions to &PRODUCT; 4.1.0. Any steps that are hypervisor-specific will be called out with a note. Package Structure Changes The package structure for &PRODUCT; has changed significantly since the 4.0.x releases. If you've compiled your own packages, you'll notice that the package names and the number of packages has changed. This is not a bug. @@ -48,32 +48,23 @@ under the License. Stop your management server or servers. Run this on all management server hosts: - # service cloud-management stop + # service cloud-management stop + + + If you are running a usage server or usage servers, stop those as well: + # service cloud-usage stop Make a backup of your MySQL database. If you run into any issues or need to roll back the upgrade, this will assist in debugging or restoring your existing environment. You'll be prompted for your password. - # mysqldump -u root -p cloud > cloudstack-backup.sql + # mysqldump -u root -p cloud > cloudstack-backup.sql Whether you're upgrading a Red Hat/CentOS based system or Ubuntu based system, you're going to need to stop the CloudStack management server before proceeding. - # service cloud-management stop + # service cloud-management stop If you have made changes to /etc/cloud/management/components.xml, you'll need to carry these over manually to the new file, /etc/cloudstack/management/componentContext.xml. This is not done automatically. (If you're unsure, we recommend making a backup of the original components.xml to be on the safe side. - - For AWS API Users Only - This step is only necessary if you're using the AWS APIs with &PRODUCT;. If not, you can skip this step. - - The file /etc/cloud/management/db.properties will be carried over to etc/cloudstack/management/db.properties, but the parameters for the AWS API are not carried over. You'll need to add these parameters to the new file manually: - -db.awsapi.username= -db.awsapi.password= -db.awsapi.host= -db.awsapi.port= - - For the AWS API queries to work, you'll need to copy those over to /etc/cloudstack/management/db.properties (with the values you have currently). - If you are using Ubuntu, follow this procedure to upgrade your packages. If not, skip to step . Community Packages @@ -110,12 +101,51 @@ db.awsapi.port= Restart the agent: + +service cloud-agent stop +killall jsvc +service cloudstack-agent start + + + During the upgrade, log4j-cloud.xml was simply copied over, so the logs will continue to be added to /var/log/cloud/agent/agent.log. There's nothing wrong with this, but if you prefer to be consistent, you can change this by copying over the sample configuration file: + +cd /etc/cloudstack/agent +mv log4j-cloud.xml.dpkg-dist log4j-cloud.xml +service cloudstack-agent restart + + + + Once the agent is running, you can uninstall the old cloud-* packages from your system: + sudo dpkg --purge cloud-agent + - ### + The package names have changed between 4.0 and 4.1, so upgrading the packages won't happen automatically with a yum update + + Once you've upgraded the packages on your management servers, you'll need to restart the system VMs. Make sure port 8096 is open to do this. + There is a script that will do this for you, all you need to do is run the script and supply the IP address for your MySQL instance and your MySQL credentials: + # nohup cloudstack-sysvmadm -d IP address -u cloud -p -a > sysvm.log 2>&1 & + You can monitor the log for progress. The process of restarting the system VMs can take an hour or more. + # tail -f sysvm.log + The output to sysvm.log will look something like this: + +Stopping and starting 1 secondary storage vm(s)... +Done stopping and starting secondary storage vm(s) +Stopping and starting 1 console proxy vm(s)... +Done stopping and starting console proxy vm(s). +Stopping and starting 4 running routing vm(s)... +Done restarting router(s). + + + + For Xen Hosts: Copy vhd-utils + This step is only for CloudStack installs that are using Xen hosts. + + Copy the file vhd-utils to /usr/share/cloudstack-common/scripts/vm/hypervisor/xenserver. +
@@ -220,11 +250,11 @@ db.awsapi.port= Stop all Usage Servers if running. Run this on all Usage Server hosts. - # service cloud-usage stop + # service cloud-usage stop Stop the Management Servers. Run this on all Management Server hosts. - # service cloud-management stop + # service cloud-management stop On the MySQL master, take a backup of the MySQL databases. We recommend performing @@ -288,7 +318,7 @@ db.awsapi.port= Start the first Management Server. Do not start any other Management Server nodes yet. - # service cloud-management start + # service cloud-management start Wait until the databases are upgraded. Ensure that the database upgrade is complete. After confirmation, start the other Management Servers one at a time by running the same command on each node. @@ -669,7 +699,7 @@ db.awsapi.port= Stop the Management Servers. Run this on all Management Server hosts. - # service cloud-management stop + # service cloud-management stop On the MySQL master, take a backup of the MySQL databases. We recommend performing @@ -780,7 +810,7 @@ db.awsapi.port= Start the first Management Server. Do not start any other Management Server nodes yet. - # service cloud-management start + # service cloud-management start Wait until the databases are upgraded. Ensure that the database upgrade is complete. You should see a message like "Complete! Done." After confirmation, start the other Management Servers one at a time by running the same command on each node. @@ -788,7 +818,7 @@ db.awsapi.port= Start all Usage Servers (if they were running on your previous version). Perform this on each Usage Server host. - # service cloud-usage start + # service cloud-usage start (KVM only) Additional steps are required for each KVM host. These steps will not @@ -856,12 +886,12 @@ db.awsapi.port= # tail -f sysvm.log The content should be like the following: - Stopping and starting 1 secondary storage vm(s)... - Done stopping and starting secondary storage vm(s) - Stopping and starting 1 console proxy vm(s)... - Done stopping and starting console proxy vm(s). - Stopping and starting 4 running routing vm(s)... - Done restarting router(s). +Stopping and starting 1 secondary storage vm(s)... +Done stopping and starting secondary storage vm(s) +Stopping and starting 1 console proxy vm(s)... +Done stopping and starting console proxy vm(s). +Stopping and starting 4 running routing vm(s)... +Done restarting router(s). diff --git a/docs/en-US/add-clusters-vsphere.xml b/docs/en-US/add-clusters-vsphere.xml index 6b2dff2a595..c3a0902be8f 100644 --- a/docs/en-US/add-clusters-vsphere.xml +++ b/docs/en-US/add-clusters-vsphere.xml @@ -71,38 +71,106 @@ In Hypervisor, choose VMware. - Provide the following information in the dialog. The fields below make reference to + Provide the following information in the dialog. The fields below make reference to the values from vCenter. + + + + + + addcluster.png: add a cluster + + - Cluster Name. Enter the name of the cluster you created in vCenter. For example, - "cloud.cluster.2.2.1" + Cluster Name: Enter the name of the cluster you + created in vCenter. For example, "cloud.cluster.2.2.1" - vCenter Host. Enter the hostname or IP address of the vCenter server. + vCenter Username: Enter the username that &PRODUCT; + should use to connect to vCenter. This user must have all the administrative + privileges. - vCenter Username. Enter the username that &PRODUCT; should use to connect to - vCenter. This user must have all administrative privileges. + CPU overcommit ratio: Enter the CPU overcommit + ratio for the cluster. The value you enter determines the CPU consumption of each VM in + the selected cluster. By increasing the over-provisioning ratio, more resource capacity + will be used. If no value is specified, the value is defaulted to 1, which implies no + over-provisioning is done. - vCenter Password. Enter the password for the user named above + RAM overcommit ratio: Enter the RAM overcommit + ratio for the cluster. The value you enter determines the memory consumption of each VM + in the selected cluster. By increasing the over-provisioning ratio, more resource + capacity will be used. If no value is specified, the value is defaulted to 1, which + implies no over-provisioning is done. - vCenter Datacenter. Enter the vCenter datacenter that the cluster is in. For - example, "cloud.dc.VM". + vCenter Host: Enter the hostname or IP address of + the vCenter server. + + + vCenter Password: Enter the password for the user + named above. + + + vCenter Datacenter: Enter the vCenter datacenter + that the cluster is in. For example, "cloud.dc.VM". + + + Override Public Traffic: Enable this option to + override the zone-wide public traffic for the cluster you are creating. + + + Public Traffic vSwitch Type: This option is + displayed only if you enable the Override Public Traffic option. Select a desirable + switch. If the vmware.use.dvswitch global parameter is true, the default option will be + VMware vNetwork Distributed Virtual Switch. + If you have enabled Nexus dvSwitch in the environment, the following parameters for + dvSwitch configuration are displayed: + + + Nexus dvSwitch IP Address: The IP address of the Nexus VSM appliance. + + + Nexus dvSwitch Username: The username required to access the Nexus VSM + appliance. + + + Nexus dvSwitch Password: The password associated with the username specified + above. + + + + + Override Guest Traffic: Enable this option to + override the zone-wide guest traffic for the cluster you are creating. + + + Guest Traffic vSwitch Type: This option is + displayed only if you enable the Override Guest Traffic option. Select a desirable + switch. + If the vmware.use.dvswitch global parameter is true, the default option will be + VMware vNetwork Distributed Virtual Switch. + If you have enabled Nexus dvSwitch in the environment, the following parameters for + dvSwitch configuration are displayed: + + + Nexus dvSwitch IP Address: The IP address of the Nexus VSM appliance. + + + Nexus dvSwitch Username: The username required to access the Nexus VSM + appliance. + + + Nexus dvSwitch Password: The password associated with the username specified + above. + + - - - - - - addcluster.png: add cluster - - There might be a slight delay while the cluster is provisioned. It will - automatically display in the UI + automatically display in the UI. diff --git a/docs/en-US/added-API-commands-4.2.xml b/docs/en-US/added-API-commands-4.2.xml new file mode 100644 index 00000000000..4bec148ba96 --- /dev/null +++ b/docs/en-US/added-API-commands-4.2.xml @@ -0,0 +1,43 @@ + + +%BOOK_ENTITIES; +]> + +
+ Added API Commands in 4.2 + + + addIpToNic + Adds an IP address to the NIC from the guest subnet. The request parameters are: nicid, + ipaddress. + The response parameters are: nicid, ipaddress, networkid + + + removeIpFromNic + Removes the reserved IP for the NIC. The request parameters is: id. + The response parameters are: true, false + + + listNics + Lists the NIC details of the user VM; the API response also contains the Secondary IP + addresses of the NIC. The request parameters are: nicid, virtualmachineid. + The response parameters are: id, ipaddress, secondaryips, gateway, netmask, macaddr, + broadcasturi, isolationuri, isdefault, + + +
diff --git a/docs/en-US/added-API-commands.xml b/docs/en-US/added-API-commands.xml index 208aac29dc2..99635de4697 100644 --- a/docs/en-US/added-API-commands.xml +++ b/docs/en-US/added-API-commands.xml @@ -87,7 +87,7 @@ suspendProject (Suspends a project) listProjects (Lists projects and provides detailed information for listed projects) - addAccountToProject (Adds acoount to a project) + addAccountToProject (Adds account to a project) deleteAccountFromProject (Deletes account from the project) diff --git a/docs/en-US/aws-ec2-introduction.xml b/docs/en-US/aws-ec2-introduction.xml index 538c09d5ad1..4cf071bcbb2 100644 --- a/docs/en-US/aws-ec2-introduction.xml +++ b/docs/en-US/aws-ec2-introduction.xml @@ -45,7 +45,7 @@ Available in fresh installations of &PRODUCT;. Not available through upgrade of previous versions.
- Features such as Elastic IP (EIP) and Elastic Load Balacing (ELB) are only available in an infrastructure + Features such as Elastic IP (EIP) and Elastic Load Balancing (ELB) are only available in an infrastructure with a Citrix NetScaler device. Users accessing a Zone with a NetScaler device will need to use a NetScaler-enabled network offering (DefaultSharedNetscalerEIP and ELBNetworkOffering). diff --git a/docs/en-US/building-documentation.xml b/docs/en-US/building-documentation.xml index 484826604fa..8ee63b06ec0 100644 --- a/docs/en-US/building-documentation.xml +++ b/docs/en-US/building-documentation.xml @@ -25,7 +25,7 @@
Building &PRODUCT; Documentation To build a specific guide, go to the source tree of the documentation in /docs and identify the guide you want to build. - Currenlty there are four guides plus the release notes, all defined in publican configuration files: + Currently there are four guides plus the release notes, all defined in publican configuration files: publican-adminguide.cfg publican-devguide.cfg diff --git a/docs/en-US/building-marvin.xml b/docs/en-US/building-marvin.xml index 3332b16d9b1..e33c4cb2248 100644 --- a/docs/en-US/building-marvin.xml +++ b/docs/en-US/building-marvin.xml @@ -27,7 +27,7 @@ Marvin is built with Maven and is dependent on APIdoc. To build it do the following in the root tree of &PRODUCT;: mvn -P developer -pl :cloud-apidoc mvn -P developer -pl :cloud-marvin - If successfull the build will have created the cloudstackAPI Python package under tools/marvin/marvin/cloudstackAPI as well as a gziped Marvin package under tools/marvin dist. To install the Python Marvin module do the following in tools/marvin: + If successful the build will have created the cloudstackAPI Python package under tools/marvin/marvin/cloudstackAPI as well as a gziped Marvin package under tools/marvin dist. To install the Python Marvin module do the following in tools/marvin: sudo python ./setup.py install The dependencies will be downloaded the Python module installed and you should be able to use Marvin in Python. Check that you can import the module before starting to use it. $ python diff --git a/docs/en-US/building-translation.xml b/docs/en-US/building-translation.xml index 659c55ffc5e..dd66365cd9d 100644 --- a/docs/en-US/building-translation.xml +++ b/docs/en-US/building-translation.xml @@ -52,7 +52,7 @@ how to prepare a document for translation. The basic command to execute to build the pot files for the developer guide is: publican update_pot --config=publican-devguide.cfg - This will create a pot directory with pot files in it, one for each corresponding xml files needed to build the guide. Once genereated, all pots files need to be configured for translation using transifex this is best done by using the transifex client that you can install with the following command (For RHEL and its derivatives): + This will create a pot directory with pot files in it, one for each corresponding xml files needed to build the guide. Once generated, all pots files need to be configured for translation using transifex this is best done by using the transifex client that you can install with the following command (For RHEL and its derivatives): yum install transifex-client The transifex client is also available via PyPi and you can install it like this: easy_install transifex-client diff --git a/docs/en-US/change-console-proxy-ssl-certificate-domain.xml b/docs/en-US/change-console-proxy-ssl-certificate-domain.xml index 89796a22c23..3fd05018e99 100644 --- a/docs/en-US/change-console-proxy-ssl-certificate-domain.xml +++ b/docs/en-US/change-console-proxy-ssl-certificate-domain.xml @@ -32,7 +32,7 @@ Generate a new 2048-bit private keyopenssl genrsa -des3 -out yourprivate.key 2048 Generate a new certificate CSRopenssl req -new -key yourprivate.key -out yourcertificate.csr Head to the website of your favorite trusted Certificate Authority, purchase an SSL certificate, and submit the CSR. You should receive a valid certificate in return - Convert your private key format into PKCS#8 encrypted format.openssl pkcs8 -topk8 -in yourprivate.key -out yourprivate.pkcs8.encryped.key + Convert your private key format into PKCS#8 encrypted format.openssl pkcs8 -topk8 -in yourprivate.key -out yourprivate.pkcs8.encrypted.key Convert your PKCS#8 encrypted private key into the PKCS#8 format that is compliant with &PRODUCT;openssl pkcs8 -in yourprivate.pkcs8.encrypted.key -out yourprivate.pkcs8.key diff --git a/docs/en-US/citrix-xenserver-installation.xml b/docs/en-US/citrix-xenserver-installation.xml index 40538658078..2cd39a41368 100644 --- a/docs/en-US/citrix-xenserver-installation.xml +++ b/docs/en-US/citrix-xenserver-installation.xml @@ -62,7 +62,7 @@ support any system that is not up to date with patches. - All hosts within a cluster must be homogenous. The CPUs must be of the same type, + All hosts within a cluster must be homogeneous. The CPUs must be of the same type, count, and feature flags. diff --git a/docs/en-US/configure-package-repository.xml b/docs/en-US/configure-package-repository.xml index 3d102c697ad..c8ba48f2717 100644 --- a/docs/en-US/configure-package-repository.xml +++ b/docs/en-US/configure-package-repository.xml @@ -33,7 +33,7 @@ If you didn't follow the steps to build your own packages from source in the sections for or you may find pre-built - DEB and RPM packages for your convience linked from the + DEB and RPM packages for your convenience linked from the downloads page. diff --git a/docs/en-US/configure-vpn.xml b/docs/en-US/configure-vpn.xml index 87b4e65b56f..5d25620b3eb 100644 --- a/docs/en-US/configure-vpn.xml +++ b/docs/en-US/configure-vpn.xml @@ -29,7 +29,7 @@ In the left navigation, click Global Settings. Set the following global configuration parameters. - remote.access.vpn.client.ip.range – The range of IP addressess to be allocated to remote access VPN clients. The first IP in the range is used by the VPN server. + remote.access.vpn.client.ip.range – The range of IP addresses to be allocated to remote access VPN clients. The first IP in the range is used by the VPN server. remote.access.vpn.psk.length – Length of the IPSec key. remote.access.vpn.user.limit – Maximum number of VPN users per account. diff --git a/docs/en-US/console-proxy.xml b/docs/en-US/console-proxy.xml index 64183b4bfc0..5f9a82027d2 100644 --- a/docs/en-US/console-proxy.xml +++ b/docs/en-US/console-proxy.xml @@ -95,7 +95,7 @@ Convert your private key format into PKCS#8 encrypted format. - openssl pkcs8 -topk8 -in yourprivate.key -out yourprivate.pkcs8.encryped.key + openssl pkcs8 -topk8 -in yourprivate.key -out yourprivate.pkcs8.encrypted.key Convert your PKCS#8 encrypted private key into the PKCS#8 format that is compliant diff --git a/docs/en-US/hypervisor-host-install-libvirt.xml b/docs/en-US/hypervisor-host-install-libvirt.xml index d7dc47f8dbd..f3ff090463c 100644 --- a/docs/en-US/hypervisor-host-install-libvirt.xml +++ b/docs/en-US/hypervisor-host-install-libvirt.xml @@ -28,7 +28,7 @@ In order to have live migration working libvirt has to listen for unsecured TCP connections. We also need to turn off libvirts attempt to use Multicast DNS advertising. Both of these settings are in /etc/libvirt/libvirtd.conf - Set the following paramaters: + Set the following parameters: listen_tls = 0 listen_tcp = 1 tcp_port = "16509" diff --git a/docs/en-US/hypervisor-host-install-network-openvswitch.xml b/docs/en-US/hypervisor-host-install-network-openvswitch.xml index e9bf47a0d20..a16dc8e0e8d 100644 --- a/docs/en-US/hypervisor-host-install-network-openvswitch.xml +++ b/docs/en-US/hypervisor-host-install-network-openvswitch.xml @@ -69,7 +69,7 @@ we can proceed to configuring the network. First we configure eth0 vi /etc/sysconfig/network-scripts/ifcfg-eth0 - Make sure it looks similair to: + Make sure it looks similar to: The required packages were installed when libvirt was installed, we can proceed to configuring the network. First we configure eth0 vi /etc/sysconfig/network-scripts/ifcfg-eth0 - Make sure it looks similair to: + Make sure it looks similar to: Now we have the VLAN interfaces configured we can add the bridges on top of them. vi /etc/sysconfig/network-scripts/ifcfg-cloudbr0 - Now we just configure it is a plain bridge without an IP-Adress + Now we just configure it is a plain bridge without an IP-Address Check for a fully qualified hostname. hostname --fqdn - This should return a fully qualified hostname such as "managament1.lab.example.org". If it does not, edit /etc/hosts so that it does. + This should return a fully qualified hostname such as "management1.lab.example.org". If it does not, edit /etc/hosts so that it does. Make sure that the machine can reach the Internet. diff --git a/docs/en-US/management-server-lb.xml b/docs/en-US/management-server-lb.xml index 9aee1548026..13f87560e10 100644 --- a/docs/en-US/management-server-lb.xml +++ b/docs/en-US/management-server-lb.xml @@ -58,7 +58,7 @@ - In addition to above settings, the adminstrator is responsible for setting the 'host' global + In addition to above settings, the administrator is responsible for setting the 'host' global config value from the management server IP to load balancer virtual IP address. If the 'host' value is not set to the VIP for Port 8250 and one of your management servers crashes, the UI is still available but the system VMs will not be able to contact the management server. diff --git a/docs/en-US/minimum-system-requirements.xml b/docs/en-US/minimum-system-requirements.xml index de1bc222023..870ef68eae4 100644 --- a/docs/en-US/minimum-system-requirements.xml +++ b/docs/en-US/minimum-system-requirements.xml @@ -57,7 +57,7 @@ If DHCP is used for hosts, ensure that no conflict occurs between DHCP server used for these hosts and the DHCP router created by &PRODUCT;. Latest hotfixes applied to hypervisor software When you deploy &PRODUCT;, the hypervisor host must not have any VMs already running - All hosts within a cluster must be homogenous. The CPUs must be of the same type, count, and feature flags. + All hosts within a cluster must be homogeneous. The CPUs must be of the same type, count, and feature flags. Hosts have additional requirements depending on the hypervisor. See the requirements listed at the top of the Installation section for your chosen hypervisor: diff --git a/docs/en-US/multiple-ip-nic.xml b/docs/en-US/multiple-ip-nic.xml new file mode 100644 index 00000000000..561ba0757b5 --- /dev/null +++ b/docs/en-US/multiple-ip-nic.xml @@ -0,0 +1,91 @@ + + +%BOOK_ENTITIES; +]> + + +
+ Configuring Multiple IP Addresses on a Single NIC + &PRODUCT; now provides you the ability to associate multiple private IP addresses per guest + VM NIC. This feature is supported on all the network configurations—Basic, Advanced, and + VPC. Security Groups, Static NAT and Port forwarding services are supported on these additional + IPs. In addition to the primary IP, you can assign additional IPs to the guest VM NIC. Up to 256 + IP addresses are allowed per NIC. + As always, you can specify an IP from the guest subnet; if not specified, an IP is + automatically picked up from the guest VM subnet. You can view the IPs associated with for each + guest VM NICs on the UI. You can apply NAT on these additional guest IPs by using firewall + configuration in the &PRODUCT; UI. You must specify the NIC to which the IP should be + associated. + This feature is supported on XenServer, KVM, and VMware hypervisors. + + You need to configure the secondary IP address on the guest VM. &PRODUCT; will + not configure the acquired IP address on the VM. Ensure that you assign IPs to NIC each + time the VM reboots. + + Some of the use cases are described below: + + + Building network appliances: Network appliances, such as firewalls and load balancers, + generally work best when they have access to multiple IP addresses on the network + interface. + + + Moving private IP addresses between interfaces or instances. Applications that are bound + to specific IP addresses can be moved between instances. + + + Hosting multiple SSL Websites on a single instance. You can install multiple SSL + certificates on a single instance, each associated with a distinct IP address. + + +
+ Assigning Additional IPs to a VM + + + Log in to the &PRODUCT; UI. + + + In the left navigation bar, click Instances. + + + Click the name of the instance you want to work with. + + + In the Details tab, click NICs. + + + Click View All. + + + Click Acquire New IP, and click Yes in the confirmation dialog. + You are prompted for confirmation because, typically, IP addresses are a limited + resource. Within a few moments, the new IP address should appear with the state Allocated. + You can now use the IP address in Port Forwarding or StaticNAT rules. + + +
+
+ Port Forwarding and StaticNAT Services Changes + Because multiple IPs can be associated per NIC, you are allowed to select a desired IP for + the Port Forwarding and StaticNAT services. The default is the primary IP. To enable this + functionality, an extra optional parameter 'vmguestip' is added to the Port forwarding and + StaticNAT APIs (enableStaticNat, createIpForwardingRule) to indicate on what IP address NAT + need to be configured. If vmguestip is passed, NAT is configured on the specified private IP + of the VM. if not passed, NAT is configured on the primary IP of the VM. +
+
diff --git a/docs/en-US/networks.xml b/docs/en-US/networks.xml index f877aa55584..cb7493cc945 100644 --- a/docs/en-US/networks.xml +++ b/docs/en-US/networks.xml @@ -32,6 +32,7 @@ xmlns:xi="http://www.w3.org/2001/XInclude"/> + diff --git a/docs/en-US/translating-documentation.xml b/docs/en-US/translating-documentation.xml index afe27658f1a..4d5e3d21b43 100644 --- a/docs/en-US/translating-documentation.xml +++ b/docs/en-US/translating-documentation.xml @@ -32,7 +32,7 @@ Using the Transifex client and pushing your translated strings to the website.
- Once a translation is complete, a site admin will pull the translated strings within the &PRODUCT; repository, build the documenation and publish it. + Once a translation is complete, a site admin will pull the translated strings within the &PRODUCT; repository, build the documentation and publish it. For instructions on how to use the Transifex website see http://sebgoa.blogspot.ch/2012/11/translating-apache-cloudstack-docs-with.html For instructions on how to use the Transifex client to translate from the command line see http://sebgoa.blogspot.ch/2012/12/using-transifex-client-to-translate.html
diff --git a/docs/en-US/using-sshkeys.xml b/docs/en-US/using-sshkeys.xml index cd10d68470a..f34dfa0c15b 100644 --- a/docs/en-US/using-sshkeys.xml +++ b/docs/en-US/using-sshkeys.xml @@ -92,7 +92,7 @@ KfEEuzcCUIxtJYTahJ1pvlFkQ8anpuxjSEDp8x/18bq3 After you save the SSH keypair file, you must create an instance by using the template that you created at . Ensure that you use the same SSH key name that you created at . You cannot create the instance by using the GUI at this time and associate the instance with the newly created SSH keypair. A sample curl command to create a new instance is: - curl --globoff http://localhost:<port numbet>/?command=deployVirtualMachine\&zoneId=1\&serviceOfferingId=18727021-7556-4110-9322-d625b52e0813\&templateId=e899c18a-ce13-4bbf-98a9-625c5026e0b5\&securitygroupids=ff03f02f-9e3b-48f8-834d-91b822da40c5\&account=admin\&domainid=1\&keypair=keypair-doc + curl --globoff http://localhost:<port number>/?command=deployVirtualMachine\&zoneId=1\&serviceOfferingId=18727021-7556-4110-9322-d625b52e0813\&templateId=e899c18a-ce13-4bbf-98a9-625c5026e0b5\&securitygroupids=ff03f02f-9e3b-48f8-834d-91b822da40c5\&account=admin\&domainid=1\&keypair=keypair-doc Substitute the template, service offering and security group IDs (if you are using the security group feature) that are in your cloud environment.
diff --git a/docs/en-US/vmware-cluster-config-dvswitch.xml b/docs/en-US/vmware-cluster-config-dvswitch.xml new file mode 100644 index 00000000000..3468c1bea4e --- /dev/null +++ b/docs/en-US/vmware-cluster-config-dvswitch.xml @@ -0,0 +1,193 @@ + + +%BOOK_ENTITIES; +]> + + +
+ Configuring a vSphere Cluster with VMware Distributed Virtual Switch + &PRODUCT;supports VMware vNetwork Distributed Switch (VDS) for virtual network configuration + in a VMware vSphere environment. This section helps you configure VMware VDS in a &PRODUCT; + deployment. Each vCenter server instance can support up to 128 VDS instances and each VDS + instance can manage up to 500 VMware hosts. +
+ About VMware Distributed Virtual Switch + VMware VDS is an aggregation of host-level virtual switches on a VMware vCenter server. + VDS abstracts the configuration of individual virtual switches that span across a large number + of hosts, and enables centralized provisioning, administration, and monitoring for your entire + datacenter from a centralized interface. In effect, a VDS acts as a single virtual switch at + the datacenter level and manages networking for a number of hosts in a datacenter from a + centralized VMware vCenter server. Each VDS maintains network runtime state for VMs as they + move across multiple hosts, enabling inline monitoring and centralized firewall services. A + VDS can be deployed with or without Virtual Standard Switch and a Nexus 1000V virtual + switch. +
+
+ Prerequisites and Guidelines + + + Do not attempt to configure VDS by altering VMware traffic label when configuring + physical networks. This will only work for Standard Virtual Switch and should not be + distributed. + + + VMware VDS does not support multiple VDS per traffic type. If a user has many VDS + switches, only one can be used for Guest traffic and another one for Public + traffic. + + + Management and Storage network does not support VDS. Therefore, use Standard Switch + for these networks. + + +
+
+ Enabling Virtual Distributed Switch in &PRODUCT; + To make a &PRODUCT; deployment VDS enabled, set the vmware.use.dvswitch parameter to true + by using the Global Settings page in the &PRODUCT; UI and restart the Management Server. + Unless you enable the vmware.use.dvswitch parameter, you cannot see any UI options specific to + VDS, and &PRODUCT; ignores the VDS-specific parameters given in the AddClusterCmd API call. + Additionally, &PRODUCT; uses VDS for virtual network infrastructure if the value of + vmware.use.dvswitch parameter is true and the value of vmware.use.nexus.dvswitch parameter is + false. + &PRODUCT; supports orchestration of virtual networks in a deployment with a mix of Virtual + Distributed Switch, Standard Virtual Switch and Nexus 1000v Virtual Switch. +
+
+ Configuring Distributed Virtual Switch in &PRODUCT; + You can configure VDS by adding the necessary resources while a zone is created. + + + + + + dvSwitchConfig.png: Configuring dvSwitch + + + Alternatively, you can create an additional cluster with VDS enabled in the existing zone. + Use the Add Cluster option. For information as given in . + In both these cases, you must specify the following parameters to configure VDS: + + + + + + + Parameters + Description + + + + + Cluster Name + Enter the name of the cluster you created in vCenter. For example, + "cloud.cluster". + + + vCenter Host + Enter the name or the IP address of the vCenter host where you have deployed the VMware + VDS. + + + vCenter User name + Enter the username that &PRODUCT; should use to connect to vCenter. This + user must have all administrative privileges. + + + vCenter Password + Enter the password for the user named above. + + + vCenter Datacenter + Enter the vCenter datacenter that the cluster is in. For example, + "cloud.dc.VM". + + + Override Public Traffic + Enable this option to override the zone-wide public traffic for the cluster + you are creating. + + + Public Traffic vSwitch Type + This option is displayed only if you enable the Override Public Traffic + option. Select VMware vNetwork Distributed Virtual Switch. + If the vmware.use.dvswitch global parameter is true, the default option will be + VMware vNetwork Distributed Virtual Switch. + + + Public Traffic vSwitch Name + Name of virtual switch to be used for the public traffic. + + + Override Guest Traffic + Enable the option to override the zone-wide guest traffic for the cluster + you are creating. + + + Guest Traffic vSwitch Type + This option is displayed only if you enable the Override Guest Traffic + option. Select VMware vNetwork Distributed Virtual Switch. + If the vmware.use.dvswitch global parameter is true, the default option will be + VMware vNetwork Distributed Virtual Switch. + + + Guest Traffic vSwitch Name + Name of virtual switch to be used for guest traffic. + + + + +
+
+ Removing VMware Virtual Switch + + + In the vCenter datacenter that is served by the VDS, ensure that you delete all the + hosts in the corresponding cluster. + + + Log in with Admin permissions to the &PRODUCT; administrator UI. + + + In the left navigation bar, select Infrastructure. + + + In the Infrastructure page, click View all under Clusters. + + + Select the cluster where you want to remove the virtual switch. + + + In the VMware dvSwitch tab, click the name of the virtual switch. + + + In the Details page, click Delete VMware dvSwitch icon. + + + + + DeleteButton.png: button to delete dvSwitch + + + + Click Yes in the confirmation dialog box. + + +
+
diff --git a/docs/en-US/vmware-install.xml b/docs/en-US/vmware-install.xml index 467e1358638..fd88fc7c0cb 100644 --- a/docs/en-US/vmware-install.xml +++ b/docs/en-US/vmware-install.xml @@ -327,282 +327,439 @@ esxcfg-firewall -o 59000-60000,tcp,out,vncextras guide.
- + + Log in with Admin permissions to the &PRODUCT; administrator UI. + + + In the left navigation bar, select Infrastructure. + + + In the Infrastructure page, click View all under Clusters. + + + Select the cluster where you want to remove the virtual switch. + + + In the dvSwitch tab, click the name of the virtual switch. + + + In the Details page, click Delete Nexus dvSwitch icon. + + + + + DeleteButton.png: button to delete dvSwitch + + + + Click Yes in the confirmation dialog box. + + + + +
Storage Preparation for vSphere (iSCSI only) Use of iSCSI requires preparatory work in vCenter. You must add an iSCSI target and create diff --git a/docs/en-US/vmware-requirements.xml b/docs/en-US/vmware-requirements.xml index 207a4566de8..d7a6d70e6a4 100644 --- a/docs/en-US/vmware-requirements.xml +++ b/docs/en-US/vmware-requirements.xml @@ -68,7 +68,7 @@ vCenter must be configured to use the standard port 443 so that it can communicate with the &PRODUCT; Management Server. You must re-install VMware ESXi if you are going to re-use a host from a previous install. &PRODUCT; requires VMware vSphere 4.1 or 5.0. VMware vSphere 4.0 is not supported. - All hosts must be 64-bit and must support HVM (Intel-VT or AMD-V enabled). All hosts within a cluster must be homogenous. That means the CPUs must be of the same type, count, and feature flags. + All hosts must be 64-bit and must support HVM (Intel-VT or AMD-V enabled). All hosts within a cluster must be homogeneous. That means the CPUs must be of the same type, count, and feature flags. The &PRODUCT; management network must not be configured as a separate virtual network. The &PRODUCT; management network is the same as the vCenter management network, and will inherit its configuration. See . &PRODUCT; requires ESXi. ESX is not supported. All resources used for &PRODUCT; must be used for &PRODUCT; only. &PRODUCT; cannot share instance of ESXi or storage with other management consoles. Do not share the same storage volumes that will be used by &PRODUCT; with a different set of ESXi servers that are not managed by &PRODUCT;. diff --git a/docs/en-US/whats-new.xml b/docs/en-US/whats-new.xml index 252f87d0543..295b53220e1 100644 --- a/docs/en-US/whats-new.xml +++ b/docs/en-US/whats-new.xml @@ -21,7 +21,11 @@ What's New in the API? The following describes any new major features of each &PRODUCT; version as it applies to - API usage. + API usage. +
+ What's New in the API for 4.2 + +
What's New in the API for 4.1 diff --git a/docs/en-US/writing-new-documentation.xml b/docs/en-US/writing-new-documentation.xml index 340900e3c60..7557359fd09 100644 --- a/docs/en-US/writing-new-documentation.xml +++ b/docs/en-US/writing-new-documentation.xml @@ -82,7 +82,7 @@
Building &PRODUCT; Documentation To build a specific guide, go to the source tree of the documentation in /docs and identify the guide you want to build. - Currenlty there are four guides plus the release notes, all defined in publican configuration files: + Currently there are four guides plus the release notes, all defined in publican configuration files: publican-adminguide.cfg publican-devguide.cfg @@ -96,5 +96,5 @@
]]> - Happy Publicaning and DocBooking. + Happy Publicating and DocBooking.
diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java index 8b9b100c243..0359db95a96 100755 --- a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java @@ -207,7 +207,7 @@ public class VMEntityManagerImpl implements VMEntityManager { } DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), vmReservation.getPodId(), vmReservation.getClusterId(), - vmReservation.getHostId(), poolId , null); + vmReservation.getHostId(), null , null); VMInstanceVO vmDeployed = _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), plan); diff --git a/patches/systemvm/debian/config/etc/init.d/cloud-early-config b/patches/systemvm/debian/config/etc/init.d/cloud-early-config index 2b99c5b6cf3..3faa1bd0f2e 100755 --- a/patches/systemvm/debian/config/etc/init.d/cloud-early-config +++ b/patches/systemvm/debian/config/etc/init.d/cloud-early-config @@ -386,33 +386,39 @@ setup_common() { ip route delete default if [ "$RROUTER" != "1" ] then - if [ -z "$3" ] + gwdev=$3 + if [ -z "$gwdev" ] + then + gwdev="eth0" + fi + + timer=0 + #default route add fails if we run before interface configured with ip + log_it "checking that $gwdev has IP before setting default route to $GW" + echo "checking that $gwdev has IP before setting default route to $GW" + while true + do + ip=$(ifconfig $gwdev | grep "inet addr:" | awk '{print $2}' | awk -F: '{print $2}') + if [ -z $ip ] then - ip route add default via $GW dev eth0 + sleep 1; + #waiting for the interface to setup with ip + log_it "waiting for $gwdev interface setup with ip" + echo "waiting for $gwdev interface setup with ip" else - timer=0 - #default route add fails if we run before interface configured with ip - while true - do - ip=$(ifconfig $3 | grep "inet addr:" | awk '{print $2}' | awk -F: '{print $2}') - if [ -z $ip ] - then - sleep 1; - #waiting for the interface to setup with ip - echo "waiting for $3 interface setup with ip" - else - ip route add default via $GW dev $3 - break - fi - - if [ $timer -gt 5 ] - then - echo "interface $3 is not set up with ip... configuring default route failed" - break - fi - timer=`expr $timer + 1` - done + ip route add default via $GW dev $gwdev + break fi + + if [ $timer -gt 15 ] + then + log_it "interface $gwdev is not set up with ip... configuring default route failed"; + echo "interface $gwdev is not set up with ip... configuring default route failed" + break + fi + timer=`expr $timer + 1` + done + fi # a hacking way to activate vSwitch under VMware @@ -704,7 +710,7 @@ setup_vpcrouter() { fi cat > /etc/network/interfaces << EOF -auto lo $1 +auto lo eth0 iface lo inet loopback EOF setup_interface "0" $ETH0_IP $ETH0_MASK $GW diff --git a/plugins/hypervisors/simulator/pom.xml b/plugins/hypervisors/simulator/pom.xml index ff1664ad85f..e4ca9272853 100644 --- a/plugins/hypervisors/simulator/pom.xml +++ b/plugins/hypervisors/simulator/pom.xml @@ -40,5 +40,10 @@ cloud-utils ${project.version} + + org.apache.cloudstack + cloud-secondary-storage + ${project.version} + diff --git a/plugins/hypervisors/simulator/src/com/cloud/resource/AgentStorageResource.java b/plugins/hypervisors/simulator/src/com/cloud/resource/AgentStorageResource.java index 2d81c2ab705..a012340d088 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/resource/AgentStorageResource.java +++ b/plugins/hypervisors/simulator/src/com/cloud/resource/AgentStorageResource.java @@ -20,6 +20,7 @@ import java.util.Map; import javax.naming.ConfigurationException; +import org.apache.cloudstack.storage.resource.SecondaryStorageResource; import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; @@ -35,7 +36,6 @@ import com.cloud.agent.manager.SimulatorManager; import com.cloud.agent.manager.SimulatorManager.AgentType; import com.cloud.host.Host; import com.cloud.host.Host.Type; -import com.cloud.storage.resource.SecondaryStorageResource; import com.cloud.vm.SecondaryStorageVm; diff --git a/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java b/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java index 3a8cf17e24b..c121fbac5d9 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java +++ b/plugins/hypervisors/simulator/src/com/cloud/resource/SimulatorSecondaryDiscoverer.java @@ -24,6 +24,7 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.storage.resource.SecondaryStorageDiscoverer; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -40,9 +41,7 @@ import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.storage.SnapshotVO; import com.cloud.storage.dao.SnapshotDao; -import com.cloud.storage.secondary.SecondaryStorageDiscoverer; import com.cloud.utils.exception.CloudRuntimeException; -import org.springframework.stereotype.Component; @Local(value=Discoverer.class) diff --git a/plugins/hypervisors/vmware/pom.xml b/plugins/hypervisors/vmware/pom.xml index 468e0a50599..d65ef640655 100644 --- a/plugins/hypervisors/vmware/pom.xml +++ b/plugins/hypervisors/vmware/pom.xml @@ -32,6 +32,11 @@ cloud-vmware-base ${project.version} + + org.apache.cloudstack + cloud-secondary-storage + ${project.version} + com.cloud.com.vmware vmware-vim25 diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java index bb7c29745d9..20146970daa 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java @@ -135,10 +135,9 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru { if (!(vm.getVirtualMachine() instanceof DomainRouterVO || vm.getVirtualMachine() instanceof ConsoleProxyVO || vm.getVirtualMachine() instanceof SecondaryStorageVmVO)){ // user vm - if (diskDeviceType != null){ - details.remove(VmDetailConstants.ROOK_DISK_CONTROLLER); + if (diskDeviceType == null){ + details.put(VmDetailConstants.ROOK_DISK_CONTROLLER, _vmwareMgr.getRootDiskController()); } - details.put(VmDetailConstants.ROOK_DISK_CONTROLLER, _vmwareMgr.getRootDiskController()); } to.setDetails(details); diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/PremiumSecondaryStorageResource.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/PremiumSecondaryStorageResource.java index 856982a8e0e..3966e0242d9 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/PremiumSecondaryStorageResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/PremiumSecondaryStorageResource.java @@ -21,6 +21,8 @@ import java.util.Map; import javax.naming.ConfigurationException; +import org.apache.cloudstack.storage.resource.NfsSecondaryStorageResource; +import org.apache.cloudstack.storage.resource.SecondaryStorageResourceHandler; import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; diff --git a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java index 566e750c3fe..ce42f67bf1d 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java +++ b/plugins/hypervisors/vmware/src/com/cloud/storage/resource/VmwareSecondaryStorageResourceHandler.java @@ -18,6 +18,7 @@ package com.cloud.storage.resource; import java.util.List; +import org.apache.cloudstack.storage.resource.SecondaryStorageResourceHandler; import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index c50f13ce7e5..4ef583a5463 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -6380,7 +6380,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String guestOSType = cmd.getGuestOSType(); boolean snapshotMemory = cmd.getTarget().getType() == VMSnapshot.Type.DiskAndMemory; - long timeout = 600; + long timeout = cmd.getWait(); Connection conn = getConnection(); VM vm = null; diff --git a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java index af0912ad9f5..64b0f5aa37d 100644 --- a/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java +++ b/plugins/network-elements/juniper-srx/src/com/cloud/network/element/JuniperSRXExternalFirewallElement.java @@ -274,7 +274,7 @@ PortForwardingServiceProvider, RemoteAccessVPNServiceProvider, IpDeployer, Junip firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp"); firewallCapabilities.put(Capability.MultipleIps, "true"); firewallCapabilities.put(Capability.TrafficStatistics, "per public ip"); - firewallCapabilities.put(Capability.SupportedTrafficDirection, "ingress"); + firewallCapabilities.put(Capability.SupportedTrafficDirection, "ingress, egress"); capabilities.put(Service.Firewall, firewallCapabilities); // Disabling VPN for Juniper in Acton as it 1) Was never tested 2) probably just doesn't work diff --git a/plugins/network-elements/juniper-srx/src/com/cloud/network/resource/JuniperSrxResource.java b/plugins/network-elements/juniper-srx/src/com/cloud/network/resource/JuniperSrxResource.java index 84821680198..a0068c3784c 100644 --- a/plugins/network-elements/juniper-srx/src/com/cloud/network/resource/JuniperSrxResource.java +++ b/plugins/network-elements/juniper-srx/src/com/cloud/network/resource/JuniperSrxResource.java @@ -303,7 +303,7 @@ public class JuniperSrxResource implements ServerResource { } private enum Protocol { - tcp, udp, icmp, any; + tcp, udp, icmp, all, any; } private enum RuleMatchCondition { @@ -320,7 +320,8 @@ public class JuniperSrxResource implements ServerResource { private enum SecurityPolicyType { STATIC_NAT("staticnat"), DESTINATION_NAT("destnat"), - VPN("vpn"); + VPN("vpn"), + SECURITYPOLICY_EGRESS("egress"); private String identifier; @@ -776,6 +777,43 @@ public class JuniperSrxResource implements ServerResource { s_logger.debug(msg); } + private Map> getActiveFirewallEgressRules(FirewallRuleTO[] allRules) { + Map> activeRules = new HashMap>(); + + for (FirewallRuleTO rule : allRules) { + String guestVlan; + guestVlan = rule.getSrcVlanTag(); + + ArrayList activeRulesForNetwork = activeRules.get(guestVlan); + + if (activeRulesForNetwork == null) { + activeRulesForNetwork = new ArrayList(); + } + + if (!rule.revoked() || rule.isAlreadyAdded()) { + activeRulesForNetwork.add(rule); + } + + activeRules.put(guestVlan, activeRulesForNetwork); + } + + return activeRules; + } + + private List extractCidrs(List rules) throws ExecutionException { + List allCidrs = new ArrayList(); + List cidrs = new ArrayList(); + + for (FirewallRuleTO rule : rules) { + cidrs = (rule.getSourceCidrList()); + for (String cidr: cidrs) { + if (!allCidrs.contains(cidr)) { + allCidrs.add(cidr); + } + } + } + return allCidrs; + } /* security policies */ private synchronized Answer execute(SetFirewallRulesCommand cmd) { @@ -787,24 +825,39 @@ public class JuniperSrxResource implements ServerResource { FirewallRuleTO[] rules = cmd.getRules(); try { openConfiguration(); + if (rules[0].getTrafficType() == FirewallRule.TrafficType.Egress) { + Map> activeRules = getActiveFirewallEgressRules(rules); + Set guestVlans = activeRules.keySet(); + List cidrs = new ArrayList(); - for (FirewallRuleTO rule : rules) { - int startPort = 0, endPort = 0; - if (rule.getSrcPortRange() != null) { - startPort = rule.getSrcPortRange()[0]; - endPort = rule.getSrcPortRange()[1]; + for (String guestVlan : guestVlans) { + List activeRulesForGuestNw = activeRules.get(guestVlan); + + removeEgressSecurityPolicyAndApplications(SecurityPolicyType.SECURITYPOLICY_EGRESS, guestVlan, extractCidrs(activeRulesForGuestNw)); + if (activeRulesForGuestNw.size() > 0) { + addEgressSecurityPolicyAndApplications(SecurityPolicyType.SECURITYPOLICY_EGRESS, guestVlan, extractApplications(activeRulesForGuestNw), extractCidrs(activeRulesForGuestNw)); + } } - FirewallFilterTerm term = new FirewallFilterTerm(genIpIdentifier(rule.getSrcIp()) + "-" + String.valueOf(rule.getId()), rule.getSourceCidrList(), - rule.getSrcIp(), rule.getProtocol(), startPort, endPort, - rule.getIcmpType(), rule.getIcmpCode(), genIpIdentifier(rule.getSrcIp()) + _usageFilterIPInput.getCounterIdentifier()); - if (!rule.revoked()) { - manageFirewallFilter(SrxCommand.ADD, term, _publicZoneInputFilterName); - } else { - manageFirewallFilter(SrxCommand.DELETE, term, _publicZoneInputFilterName); + commitConfiguration(); + } else { + for (FirewallRuleTO rule : rules) { + int startPort = 0, endPort = 0; + if (rule.getSrcPortRange() != null) { + startPort = rule.getSrcPortRange()[0]; + endPort = rule.getSrcPortRange()[1]; + FirewallFilterTerm term = new FirewallFilterTerm(genIpIdentifier(rule.getSrcIp()) + "-" + String.valueOf(rule.getId()), rule.getSourceCidrList(), + rule.getSrcIp(), rule.getProtocol(), startPort, endPort, + rule.getIcmpType(), rule.getIcmpCode(), genIpIdentifier(rule.getSrcIp()) + _usageFilterIPInput.getCounterIdentifier()); + if (!rule.revoked()) { + manageFirewallFilter(SrxCommand.ADD, term, _publicZoneInputFilterName); + } else { + manageFirewallFilter(SrxCommand.DELETE, term, _publicZoneInputFilterName); + } + } + commitConfiguration(); } } - commitConfiguration(); return new Answer(cmd); } catch (ExecutionException e) { s_logger.error(e); @@ -992,7 +1045,7 @@ public class JuniperSrxResource implements ServerResource { // Delete all security policies for (String securityPolicyName : getVpnObjectNames(SrxXml.SECURITY_POLICY_GETALL, accountId)) { - manageSecurityPolicy(SecurityPolicyType.VPN, SrxCommand.DELETE, accountId, null, null, null, securityPolicyName); + manageSecurityPolicy(SecurityPolicyType.VPN, SrxCommand.DELETE, accountId, null, null, null, null, securityPolicyName); } // Delete all address book entries @@ -1064,7 +1117,7 @@ public class JuniperSrxResource implements ServerResource { manageAddressBookEntry(srxCmd, _privateZone , guestNetworkCidr, ipsecVpnName); // Security policy - manageSecurityPolicy(SecurityPolicyType.VPN, srxCmd, null, null, guestNetworkCidr, null, ipsecVpnName); + manageSecurityPolicy(SecurityPolicyType.VPN, srxCmd, null, null, guestNetworkCidr, null, null, ipsecVpnName); } commitConfiguration(); @@ -2455,38 +2508,44 @@ public class JuniperSrxResource implements ServerResource { * Applications */ - private String genApplicationName(Protocol protocol, int startPort, int endPort) { + private String genApplicationName(SecurityPolicyType type, Protocol protocol, int startPort, int endPort) { if (protocol.equals(Protocol.any)) { return Protocol.any.toString(); } else { - return genObjectName(protocol.toString(), String.valueOf(startPort), String.valueOf(endPort)); + if (type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS)) { + return genObjectName(type.getIdentifier(), protocol.toString(), String.valueOf(startPort), String.valueOf(endPort)); + } else { + return genObjectName(protocol.toString(), String.valueOf(startPort), String.valueOf(endPort)); + } } } - private Object[] parseApplicationName(String applicationName) throws ExecutionException { + private Object[] parseApplicationName(SecurityPolicyType type, String applicationName) throws ExecutionException { String errorMsg = "Invalid application: " + applicationName; String[] applicationComponents = applicationName.split("-"); Protocol protocol; Integer startPort; Integer endPort; + int offset = 0; try { - protocol = getProtocol(applicationComponents[0]); - startPort = Integer.parseInt(applicationComponents[1]); - endPort = Integer.parseInt(applicationComponents[2]); - } catch (Exception e) { + offset = type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS) ? 1 : 0; + protocol = getProtocol(applicationComponents[offset + 0]); + startPort = Integer.parseInt(applicationComponents[offset + 1]); + endPort = Integer.parseInt(applicationComponents[offset + 2]); + } catch (Exception e) { throw new ExecutionException(errorMsg); } return new Object[]{protocol, startPort, endPort}; } - private boolean manageApplication(SrxCommand command, Protocol protocol, int startPort, int endPort) throws ExecutionException { + private boolean manageApplication(SecurityPolicyType type, SrxCommand command, Protocol protocol, int startPort, int endPort) throws ExecutionException { if (protocol.equals(Protocol.any)) { return true; } - String applicationName = genApplicationName(protocol, startPort, endPort); + String applicationName = genApplicationName(type, protocol, startPort, endPort); String xml; switch (command) { @@ -2498,23 +2557,28 @@ public class JuniperSrxResource implements ServerResource { return sendRequestAndCheckResponse(command, xml, "name", applicationName); case ADD: - if (manageApplication(SrxCommand.CHECK_IF_EXISTS, protocol, startPort, endPort)) { + if (manageApplication(type, SrxCommand.CHECK_IF_EXISTS, protocol, startPort, endPort)) { return true; } - + String icmpOrDestPort; xml = SrxXml.APPLICATION_ADD.getXml(); xml = replaceXmlValue(xml, "name", applicationName); xml = replaceXmlValue(xml, "protocol", protocol.toString()); - - String destPort; - if (startPort == endPort) { - destPort = String.valueOf(startPort); + if (protocol.toString() == Protocol.icmp.toString()) { + icmpOrDestPort = "" + startPort + ""; + icmpOrDestPort += "" + endPort + ""; } else { - destPort = startPort + "-" + endPort; + String destPort; + + if (startPort == endPort) { + destPort = String.valueOf(startPort); + } else { + destPort = startPort + "-" + endPort; + } + icmpOrDestPort = "" + destPort + ""; } - xml = replaceXmlValue(xml, "dest-port", destPort); - + xml = replaceXmlValue(xml, "dest-port-icmp", icmpOrDestPort); if (!sendRequestAndCheckResponse(command, xml)) { throw new ExecutionException("Failed to add application " + applicationName); } else { @@ -2522,7 +2586,7 @@ public class JuniperSrxResource implements ServerResource { } case DELETE: - if (!manageApplication(SrxCommand.CHECK_IF_EXISTS, protocol, startPort, endPort)) { + if (!manageApplication(type, SrxCommand.CHECK_IF_EXISTS, protocol, startPort, endPort)) { return true; } @@ -2543,13 +2607,13 @@ public class JuniperSrxResource implements ServerResource { } - private List getUnusedApplications(List applications) throws ExecutionException { + private List getUnusedApplications(List applications, String fromZone, String toZone) throws ExecutionException { List unusedApplications = new ArrayList(); // Check if any of the applications are unused by existing security policies String xml = SrxXml.SECURITY_POLICY_GETALL.getXml(); - xml = replaceXmlValue(xml, "from-zone", _publicZone); - xml = replaceXmlValue(xml, "to-zone", _privateZone); + xml = replaceXmlValue(xml, "from-zone", fromZone); + xml = replaceXmlValue(xml, "to-zone", toZone); String allPolicies = sendRequest(xml); for (String application : applications) { @@ -2560,10 +2624,7 @@ public class JuniperSrxResource implements ServerResource { return unusedApplications; } - - private List getApplicationsForSecurityPolicy(SecurityPolicyType type, String privateIp) throws ExecutionException { - String fromZone = _publicZone; - String toZone = _privateZone; + private List getApplicationsForSecurityPolicy(SecurityPolicyType type, String privateIp, String fromZone, String toZone) throws ExecutionException { String policyName = genSecurityPolicyName(type, null, null, fromZone, toZone, privateIp); String xml = SrxXml.SECURITY_POLICY_GETONE.getXml(); xml = setDelete(xml, false); @@ -2591,8 +2652,31 @@ public class JuniperSrxResource implements ServerResource { for (FirewallRuleTO rule : rules) { Object[] application = new Object[3]; application[0] = getProtocol(rule.getProtocol()); - application[1] = rule.getSrcPortRange()[0]; - application[2] = rule.getSrcPortRange()[1]; + if (application[0] == Protocol.icmp) { + if (rule.getIcmpType() == -1) { + application[1] = 255; + } else { + application[1] = rule.getIcmpType(); + } + + if (rule.getIcmpCode() == -1) { + application[2] = 255; + } else { + application[2] = rule.getIcmpCode(); + } + } else if (application[0] == Protocol.tcp || application[0] == Protocol.udp) { + if (rule.getSrcPortRange() != null) { + application[1] = rule.getSrcPortRange()[0]; + application[2] = rule.getSrcPortRange()[1]; + } else { + application[1] = 0; + application[2] = 65535; + } + } else if (application[0] == Protocol.all) { + application[1] = 0; + application[2] = 65535; + } + applications.add(application); } @@ -2611,16 +2695,20 @@ public class JuniperSrxResource implements ServerResource { } } - private boolean manageSecurityPolicy(SecurityPolicyType type, SrxCommand command, Long accountId, String username, String privateIp, List applicationNames, String ipsecVpnName) throws ExecutionException { + private boolean manageSecurityPolicy(SecurityPolicyType type, SrxCommand command, Long accountId, String username, String privateIp, List applicationNames, List cidrs, String ipsecVpnName) throws ExecutionException { String fromZone = _publicZone; String toZone = _privateZone; String securityPolicyName; - String addressBookEntryName; - + String addressBookEntryName = null; + if (type.equals(SecurityPolicyType.VPN) && ipsecVpnName != null) { - securityPolicyName = ipsecVpnName; - addressBookEntryName = ipsecVpnName; + securityPolicyName = ipsecVpnName; + addressBookEntryName = ipsecVpnName; + } else if (type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS)) { + fromZone = _privateZone; + toZone = _publicZone; + securityPolicyName = genSecurityPolicyName(type, accountId, username, fromZone, toZone, privateIp); } else { securityPolicyName = genSecurityPolicyName(type, accountId, username, fromZone, toZone, privateIp); addressBookEntryName = genAddressBookEntryName(privateIp); @@ -2661,17 +2749,38 @@ public class JuniperSrxResource implements ServerResource { return false; case ADD: - if (!manageAddressBookEntry(SrxCommand.CHECK_IF_EXISTS, toZone, privateIp, ipsecVpnName)) { - throw new ExecutionException("No address book entry for policy: " + securityPolicyName); + if (!type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS)) { + if (!manageAddressBookEntry(SrxCommand.CHECK_IF_EXISTS, toZone, privateIp, addressBookEntryName)) { + throw new ExecutionException("No address book entry for policy: " + securityPolicyName); + } + } + + String srcAddrs = ""; + String dstAddrs = ""; + xml = SrxXml.SECURITY_POLICY_ADD.getXml(); + xml = replaceXmlValue(xml, "policy-name", securityPolicyName); + if (type.equals(SecurityPolicyType.SECURITYPOLICY_EGRESS)) { + xml = replaceXmlValue(xml, "from-zone", _privateZone); + xml = replaceXmlValue(xml, "to-zone", _publicZone); + if (cidrs == null) { + srcAddrs = "any"; + } else { + for (String cidr : cidrs) { + srcAddrs += "" + genAddressBookEntryName(cidr) + ""; + } + } + xml = replaceXmlValue(xml, "src-address", srcAddrs); + dstAddrs = "any"; + xml = replaceXmlValue(xml, "dst-address", dstAddrs); + } else { + xml = replaceXmlValue(xml, "from-zone", fromZone); + xml = replaceXmlValue(xml, "to-zone", toZone); + srcAddrs = "any"; + xml = replaceXmlValue(xml, "src-address", srcAddrs); + dstAddrs = "" + addressBookEntryName + ""; + xml = replaceXmlValue(xml, "dst-address", dstAddrs); } - xml = SrxXml.SECURITY_POLICY_ADD.getXml(); - xml = replaceXmlValue(xml, "from-zone", fromZone); - xml = replaceXmlValue(xml, "to-zone", toZone); - xml = replaceXmlValue(xml, "policy-name", securityPolicyName); - xml = replaceXmlValue(xml, "src-address", "any"); - xml = replaceXmlValue(xml, "dest-address", addressBookEntryName); - if (type.equals(SecurityPolicyType.VPN) && ipsecVpnName != null) { xml = replaceXmlValue(xml, "tunnel", "" + ipsecVpnName + ""); } else { @@ -2679,7 +2788,7 @@ public class JuniperSrxResource implements ServerResource { } String applications; - if (applicationNames == null) { + if (applicationNames == null || applicationNames.size() == 0) { applications = "any"; } else { applications = ""; @@ -2697,11 +2806,11 @@ public class JuniperSrxResource implements ServerResource { } case DELETE: - if (!manageSecurityPolicy(type, SrxCommand.CHECK_IF_EXISTS, null, null, privateIp, applicationNames, ipsecVpnName)) { + if (!manageSecurityPolicy(type, SrxCommand.CHECK_IF_EXISTS, null, null, privateIp, applicationNames, cidrs, ipsecVpnName)) { return true; } - if (manageSecurityPolicy(type, SrxCommand.CHECK_IF_IN_USE, null, null, privateIp, applicationNames, ipsecVpnName)) { + if (manageSecurityPolicy(type, SrxCommand.CHECK_IF_IN_USE, null, null, privateIp, applicationNames, cidrs, ipsecVpnName)) { return true; } @@ -2757,42 +2866,42 @@ public class JuniperSrxResource implements ServerResource { int startPort = application[1] != null ? ((Integer) application[1]) : -1; int endPort = application[2] != null ? ((Integer) application[2]) : -1; - String applicationName = genApplicationName(protocol, startPort, endPort); + String applicationName = genApplicationName(type, protocol, startPort, endPort); if (!applicationNames.contains(applicationName)) { applicationNames.add(applicationName); } - manageApplication(SrxCommand.ADD, protocol, startPort, endPort); + manageApplication(type, SrxCommand.ADD, protocol, startPort, endPort); } // Add a new security policy - manageSecurityPolicy(type, SrxCommand.ADD, null, null, privateIp, applicationNames, null); + manageSecurityPolicy(type, SrxCommand.ADD, null, null, privateIp, applicationNames, null, null); return true; } private boolean removeSecurityPolicyAndApplications(SecurityPolicyType type, String privateIp) throws ExecutionException { - if (!manageSecurityPolicy(type, SrxCommand.CHECK_IF_EXISTS, null, null, privateIp, null, null)) { + if (!manageSecurityPolicy(type, SrxCommand.CHECK_IF_EXISTS, null, null, privateIp, null,null, null)) { return true; } - if (manageSecurityPolicy(type, SrxCommand.CHECK_IF_IN_USE, null, null, privateIp, null, null)) { + if (manageSecurityPolicy(type, SrxCommand.CHECK_IF_IN_USE, null, null, privateIp, null, null, null)) { return true; } // Get a list of applications for this security policy - List applications = getApplicationsForSecurityPolicy(type, privateIp); + List applications = getApplicationsForSecurityPolicy(type, privateIp, _publicZone, _privateZone); - // Remove the security policy - manageSecurityPolicy(type, SrxCommand.DELETE, null, null, privateIp, null, null); + // Remove the security policy + manageSecurityPolicy(type, SrxCommand.DELETE, null, null, privateIp, null, null, null); // Remove any applications for the removed security policy that are no longer in use - List unusedApplications = getUnusedApplications(applications); + List unusedApplications = getUnusedApplications(applications, _publicZone, _privateZone); for (String application : unusedApplications) { Object[] applicationComponents; try { - applicationComponents = parseApplicationName(application); + applicationComponents = parseApplicationName(type, application); } catch (ExecutionException e) { s_logger.error("Found an invalid application: " + application + ". Not attempting to clean up."); continue; @@ -2800,13 +2909,78 @@ public class JuniperSrxResource implements ServerResource { Protocol protocol = (Protocol) applicationComponents[0]; Integer startPort = (Integer) applicationComponents[1]; - Integer endPort = (Integer) applicationComponents[2]; - manageApplication(SrxCommand.DELETE, protocol, startPort, endPort); + Integer endPort = (Integer) applicationComponents[2]; + manageApplication(type, SrxCommand.DELETE, protocol, startPort, endPort); } return true; } + + private boolean removeEgressSecurityPolicyAndApplications(SecurityPolicyType type, String guestVlan, List cidrs) throws ExecutionException { + if (!manageSecurityPolicy(type, SrxCommand.CHECK_IF_EXISTS, null, null, guestVlan, null, cidrs, null)) { + return true; + } + // Get a list of applications for this security policy + List applications; + applications = getApplicationsForSecurityPolicy(type, guestVlan, _privateZone, _publicZone); + + // Remove the security policy even if it is in use + manageSecurityPolicy(type, SrxCommand.DELETE, null, null, guestVlan, null, cidrs, null); + + // Remove any applications for the removed security policy that are no longer in use + List unusedApplications; + unusedApplications = getUnusedApplications(applications, _privateZone, _publicZone); + + for (String application : unusedApplications) { + Object[] applicationComponents; + + try { + applicationComponents = parseApplicationName(type, application); + } catch (ExecutionException e) { + s_logger.error("Found an invalid application: " + application + ". Not attempting to clean up."); + continue; + } + + Protocol protocol = (Protocol) applicationComponents[0]; + Integer startPort = (Integer) applicationComponents[1]; + Integer endPort = (Integer) applicationComponents[2]; + manageApplication(type, SrxCommand.DELETE, protocol, startPort, endPort); + } + for (String cidr: cidrs) { + manageAddressBookEntry(SrxCommand.DELETE, _publicZone, cidr, null); + } + + return true; + } + + private boolean addEgressSecurityPolicyAndApplications(SecurityPolicyType type, String guestVlan, List applications, List cidrs) throws ExecutionException { + // Add all necessary applications + List applicationNames = new ArrayList(); + for (Object[] application : applications) { + Protocol protocol = (Protocol) application[0]; + if (!protocol.equals(Protocol.all)) { + int startPort = application[1] != null ? ((Integer) application[1]) : 0; + int endPort = application[2] != null ? ((Integer) application[2]) : 65535; + + String applicationName = genApplicationName(type, protocol, startPort, endPort); + if (!applicationNames.contains(applicationName)) { + applicationNames.add(applicationName); + } + manageApplication(type, SrxCommand.ADD, protocol, startPort, endPort); + } + } + + for (String cidr: cidrs) { + manageAddressBookEntry(SrxCommand.ADD, _privateZone, cidr, null); + } + + // Add a new security policy + manageSecurityPolicy(type, SrxCommand.ADD, null, null, guestVlan, applicationNames, cidrs, null); + s_logger.debug("Added Egress firewall rule for guest network " + guestVlan); + return true; + } + /* * Filter terms */ diff --git a/pom.xml b/pom.xml index 62081241445..dbc39076f2d 100644 --- a/pom.xml +++ b/pom.xml @@ -317,6 +317,10 @@ deps/XenServerJava/Makefile dist/console-proxy/js/jquery.js scripts/vm/systemvm/id_rsa.cloud + services/console-proxy/server/conf/agent.properties + services/console-proxy/server/conf/environment.properties + services/secondary-storage/conf/agent.properties + services/secondary-storage/conf/environment.properties tools/devcloud/basebuild/puppet-devcloudinitial/files/network.conf tools/appliance/definitions/devcloud/* tools/appliance/definitions/systemvmtemplate/* diff --git a/scripts/network/juniper/application-add.xml b/scripts/network/juniper/application-add.xml index 66038507c44..177329a0359 100644 --- a/scripts/network/juniper/application-add.xml +++ b/scripts/network/juniper/application-add.xml @@ -23,7 +23,7 @@ under the License. %name% %protocol% -%dest-port% +%dest-port-icmp% diff --git a/scripts/network/juniper/security-policy-add.xml b/scripts/network/juniper/security-policy-add.xml index 632a17d6651..595e02680b8 100644 --- a/scripts/network/juniper/security-policy-add.xml +++ b/scripts/network/juniper/security-policy-add.xml @@ -27,8 +27,8 @@ under the License. %policy-name% -%src-address% -%dest-address% +%src-address% +%dst-address% %applications% diff --git a/scripts/vm/hypervisor/kvm/patchviasocket.pl b/scripts/vm/hypervisor/kvm/patchviasocket.pl index 443d6e4277b..7bcd245bc38 100644 --- a/scripts/vm/hypervisor/kvm/patchviasocket.pl +++ b/scripts/vm/hypervisor/kvm/patchviasocket.pl @@ -53,6 +53,6 @@ my $msg = "pubkey:" . $key . "\ncmdline:" . $cmdline; my $socket = IO::Socket::UNIX->new(Peer=>$sockfile,Type=>SOCK_STREAM) or die "ERROR: unable to connect to $sockfile - $^E\n"; -print $socket "$msg\r\n"; +print $socket "$msg\n"; close $socket; diff --git a/scripts/vm/systemvm/injectkeys.sh b/scripts/vm/systemvm/injectkeys.sh index e56eb85b356..c17a3c61935 100755 --- a/scripts/vm/systemvm/injectkeys.sh +++ b/scripts/vm/systemvm/injectkeys.sh @@ -22,6 +22,7 @@ # $2 = new private key #set -x +set -e TMP=/tmp MOUNTPATH=${HOME}/systemvm_mnt @@ -29,7 +30,7 @@ TMPDIR=${TMP}/cloud/systemvm clean_up() { - sudo umount $MOUNTPATH + $SUDO umount $MOUNTPATH } inject_into_iso() { @@ -39,23 +40,23 @@ inject_into_iso() { local tmpiso=${TMP}/$1 mkdir -p $MOUNTPATH [ ! -f $isofile ] && echo "$(basename $0): Could not find systemvm iso patch file $isofile" && return 1 - sudo mount -o loop $isofile $MOUNTPATH + $SUDO mount -o loop $isofile $MOUNTPATH [ $? -ne 0 ] && echo "$(basename $0): Failed to mount original iso $isofile" && clean_up && return 1 diff -q $MOUNTPATH/authorized_keys $newpubkey &> /dev/null && clean_up && return 0 - sudo cp -b $isofile $backup + $SUDO cp -b $isofile $backup [ $? -ne 0 ] && echo "$(basename $0): Failed to backup original iso $isofile" && clean_up && return 1 rm -rf $TMPDIR mkdir -p $TMPDIR [ ! -d $TMPDIR ] && echo "$(basename $0): Could not find/create temporary dir $TMPDIR" && clean_up && return 1 - sudo cp -fr $MOUNTPATH/* $TMPDIR/ + $SUDO cp -fr $MOUNTPATH/* $TMPDIR/ [ $? -ne 0 ] && echo "$(basename $0): Failed to copy from original iso $isofile" && clean_up && return 1 - sudo cp $newpubkey $TMPDIR/authorized_keys + $SUDO cp $newpubkey $TMPDIR/authorized_keys [ $? -ne 0 ] && echo "$(basename $0): Failed to copy key $newpubkey from original iso to new iso " && clean_up && return 1 mkisofs -quiet -r -o $tmpiso $TMPDIR [ $? -ne 0 ] && echo "$(basename $0): Failed to create new iso $tmpiso from $TMPDIR" && clean_up && return 1 - sudo umount $MOUNTPATH + $SUDO umount $MOUNTPATH [ $? -ne 0 ] && echo "$(basename $0): Failed to unmount old iso from $MOUNTPATH" && return 1 - sudo cp -f $tmpiso $isofile + $SUDO cp -f $tmpiso $isofile [ $? -ne 0 ] && echo "$(basename $0): Failed to overwrite old iso $isofile with $tmpiso" && return 1 rm -rf $TMPDIR } @@ -63,12 +64,17 @@ inject_into_iso() { copy_priv_key() { local newprivkey=$1 diff -q $newprivkey $(dirname $0)/id_rsa.cloud && return 0 - sudo cp -fb $newprivkey $(dirname $0)/id_rsa.cloud - sudo chmod 644 $(dirname $0)/id_rsa.cloud + $SUDO cp -fb $newprivkey $(dirname $0)/id_rsa.cloud + $SUDO chmod 644 $(dirname $0)/id_rsa.cloud return $? } -sudo mkdir -p $MOUNTPATH +if [[ "$EUID" -ne 0 ]] +then + SUDO="sudo " +fi + +$SUDO mkdir -p $MOUNTPATH [ $# -ne 3 ] && echo "Usage: $(basename $0) " && exit 3 newpubkey=$1 diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 64be7f8758a..93b755a665a 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -965,6 +965,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setPublicIpAddress(ip.getAddress().addr()); if (ip != null && fwRule.getDestinationIpAddress() != null) { + response.setDestNatVmIp(fwRule.getDestinationIpAddress().toString()); UserVm vm = ApiDBUtils.findUserVmById(fwRule.getVirtualMachineId()); if (vm != null) { response.setVirtualMachineId(vm.getUuid()); diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index 200943b35e6..2137c003912 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -397,9 +397,7 @@ public enum Config { // VMSnapshots VMSnapshotMax("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.max", "10", "Maximum vm snapshots for a vm", null), - VMSnapshotCreateWait("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.create.wait", "600", "In second, timeout for create vm snapshot", null), - VMSnapshotExpungeInterval("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.expunge.interval", "60", "The interval (in seconds) to wait before running the expunge thread.", null), - VMSnapshotExpungeWorkers("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.expunge.workers", "1", "Number of workers performing expunge ", null), + VMSnapshotCreateWait("Advanced", VMSnapshotManager.class, Integer.class, "vmsnapshot.create.wait", "1800", "In second, timeout for create vm snapshot", null), CloudDnsName("Advanced", ManagementServer.class, String.class, "cloud.dns.name", "default", " DNS name of the cloud", null); diff --git a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java index 6f8575d751c..ff6e64eca94 100755 --- a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java +++ b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java @@ -23,48 +23,28 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; -import org.springframework.stereotype.Component; import com.cloud.agent.AgentManager; -import com.cloud.agent.api.AgentControlAnswer; -import com.cloud.agent.api.ConsoleAccessAuthenticationAnswer; -import com.cloud.agent.api.ConsoleAccessAuthenticationCommand; -import com.cloud.agent.api.ConsoleProxyLoadReportCommand; import com.cloud.agent.api.GetVncPortAnswer; import com.cloud.agent.api.GetVncPortCommand; -import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupProxyCommand; -import com.cloud.agent.api.StopAnswer; -import com.cloud.agent.api.to.NicTO; -import com.cloud.agent.api.to.VirtualMachineTO; -import com.cloud.agent.manager.Commands; import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.deploy.DeployDestination; -import com.cloud.exception.ConcurrentOperationException; -import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.ResourceUnavailableException; import com.cloud.host.HostVO; -import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.info.ConsoleProxyInfo; -import com.cloud.network.Network; +import com.cloud.keystore.KeystoreManager; import com.cloud.utils.NumbersUtil; import com.cloud.utils.component.ManagerBase; import com.cloud.vm.ConsoleProxyVO; -import com.cloud.vm.ReservationContext; import com.cloud.vm.UserVmVO; import com.cloud.vm.VMInstanceVO; -import com.cloud.vm.VirtualMachine; -import com.cloud.vm.VirtualMachineGuru; import com.cloud.vm.VirtualMachineManager; -import com.cloud.vm.VirtualMachineName; -import com.cloud.vm.VirtualMachineProfile; import com.cloud.vm.dao.ConsoleProxyDao; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; @Local(value = { ConsoleProxyManager.class }) -public class AgentBasedConsoleProxyManager extends ManagerBase implements ConsoleProxyManager, VirtualMachineGuru, AgentHook { +public class AgentBasedConsoleProxyManager extends ManagerBase implements ConsoleProxyManager { private static final Logger s_logger = Logger.getLogger(AgentBasedConsoleProxyManager.class); @Inject @@ -85,9 +65,25 @@ public class AgentBasedConsoleProxyManager extends ManagerBase implements Consol VirtualMachineManager _itMgr; @Inject protected ConsoleProxyDao _cpDao; + @Inject + protected KeystoreManager _ksMgr; @Inject ConfigurationDao _configDao; + public class AgentBasedAgentHook extends AgentHookBase { + + public AgentBasedAgentHook(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, + KeystoreManager ksMgr, AgentManager agentMgr) { + super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr); + } + + @Override + protected HostVO findConsoleProxyHost(StartupProxyCommand cmd) { + return _hostDao.findByGuid(cmd.getGuid()); + } + + } + public int getVncPort(VMInstanceVO vm) { if (vm.getHostId() == null) { return -1; @@ -123,11 +119,10 @@ public class AgentBasedConsoleProxyManager extends ManagerBase implements Consol _consoleProxyUrlDomain = configs.get("consoleproxy.url.domain"); - _listener = new ConsoleProxyListener(this); + _listener = + new ConsoleProxyListener(new AgentBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr, _agentMgr)); _agentMgr.registerForHostEvents(_listener, true, true, false); - _itMgr.registerGuru(VirtualMachine.Type.ConsoleProxy, this); - if (s_logger.isInfoEnabled()) { s_logger.info("AgentBasedConsoleProxyManager has been configured. SSL enabled: " + _sslEnabled); } @@ -177,64 +172,8 @@ public class AgentBasedConsoleProxyManager extends ManagerBase implements Consol return null; } - @Override - public void onLoadReport(ConsoleProxyLoadReportCommand cmd) { - } - @Override - public AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd) { - long vmId = 0; - if (cmd.getVmId() != null && cmd.getVmId().isEmpty()) { - if (s_logger.isTraceEnabled()) { - s_logger.trace("Invalid vm id sent from proxy(happens when proxy session has terminated)"); - } - return new ConsoleAccessAuthenticationAnswer(cmd, false); - } - - try { - vmId = Long.parseLong(cmd.getVmId()); - } catch (NumberFormatException e) { - s_logger.error("Invalid vm id " + cmd.getVmId() + " sent from console access authentication", e); - return new ConsoleAccessAuthenticationAnswer(cmd, false); - } - - // TODO authentication channel between console proxy VM and management - // server needs to be secured, - // the data is now being sent through private network, but this is - // apparently not enough - VMInstanceVO vm = _instanceDao.findById(vmId); - if (vm == null) { - return new ConsoleAccessAuthenticationAnswer(cmd, false); - } - - if (vm.getHostId() == null) { - s_logger.warn("VM " + vmId + " lost host info, failed authentication request"); - return new ConsoleAccessAuthenticationAnswer(cmd, false); - } - - HostVO host = _hostDao.findById(vm.getHostId()); - if (host == null) { - s_logger.warn("VM " + vmId + "'s host does not exist, fail authentication request"); - return new ConsoleAccessAuthenticationAnswer(cmd, false); - } - - String sid = cmd.getSid(); - if (sid == null || !sid.equals(vm.getVncPassword())) { - s_logger.warn("sid " + sid + " in url does not match stored sid " + vm.getVncPassword()); - return new ConsoleAccessAuthenticationAnswer(cmd, false); - } - - return new ConsoleAccessAuthenticationAnswer(cmd, true); - } - - @Override - public void onAgentConnect(HostVO host, StartupCommand cmd) { - } - - @Override - public void onAgentDisconnect(long agentId, Status state) { - } @Override public ConsoleProxyVO startProxy(long proxyVmId) { @@ -269,91 +208,8 @@ public class AgentBasedConsoleProxyManager extends ManagerBase implements Consol public void resumeLastManagementState() { } - @Override - public void startAgentHttpHandlerInVM(StartupProxyCommand startupCmd) { - } - @Override public String getName() { return _name; } - - @Override - public Long convertToId(String vmName) { - if (!VirtualMachineName.isValidConsoleProxyName(vmName, _instance)) { - return null; - } - return VirtualMachineName.getConsoleProxyId(vmName); - } - - @Override - public ConsoleProxyVO findByName(String name) { - // TODO Auto-generated method stub - return null; - } - - @Override - public ConsoleProxyVO findById(long id) { - // TODO Auto-generated method stub - return null; - } - - @Override - public ConsoleProxyVO persist(ConsoleProxyVO vm) { - // TODO Auto-generated method stub - return null; - } - - @Override - public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { - // TODO Auto-generated method stub - } - - @Override - public void finalizeExpunge(ConsoleProxyVO proxy) { - } - - @Override - public boolean plugNic(Network network, NicTO nic, VirtualMachineTO vm, - ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException, - InsufficientCapacityException { - //not supported - throw new UnsupportedOperationException("Plug nic is not supported for vm of type " + vm.getType()); - } - - - @Override - public boolean unplugNic(Network network, NicTO nic, VirtualMachineTO vm, - ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException { - //not supported - throw new UnsupportedOperationException("Unplug nic is not supported for vm of type " + vm.getType()); - } - - @Override - public void prepareStop(VirtualMachineProfile profile) { - } } diff --git a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java.orig b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java.orig new file mode 100755 index 00000000000..134d59d0065 --- /dev/null +++ b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java.orig @@ -0,0 +1,298 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.consoleproxy; + +import java.util.Map; + +import javax.ejb.Local; +import javax.inject.Inject; +import javax.naming.ConfigurationException; + +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.GetVncPortAnswer; +import com.cloud.agent.api.GetVncPortCommand; +import com.cloud.agent.api.StartupProxyCommand; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.info.ConsoleProxyInfo; +import com.cloud.keystore.KeystoreManager; +import com.cloud.utils.NumbersUtil; +import com.cloud.utils.component.ManagerBase; +import com.cloud.vm.ConsoleProxyVO; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.VirtualMachineManager; +import com.cloud.vm.dao.ConsoleProxyDao; +import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.dao.VMInstanceDao; + +@Local(value = { ConsoleProxyManager.class }) +public class AgentBasedConsoleProxyManager extends ManagerBase implements ConsoleProxyManager { + private static final Logger s_logger = Logger.getLogger(AgentBasedConsoleProxyManager.class); + + @Inject + protected HostDao _hostDao; + @Inject + protected UserVmDao _userVmDao; + private String _instance; + protected String _consoleProxyUrlDomain; + @Inject + private VMInstanceDao _instanceDao; + private ConsoleProxyListener _listener; + protected int _consoleProxyUrlPort = ConsoleProxyManager.DEFAULT_PROXY_URL_PORT; + protected int _consoleProxyPort = ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT; + protected boolean _sslEnabled = false; + @Inject + AgentManager _agentMgr; + @Inject + VirtualMachineManager _itMgr; + @Inject + protected ConsoleProxyDao _cpDao; + @Inject + protected KeystoreManager _ksMgr; + + @Inject ConfigurationDao _configDao; + + public class AgentBasedAgentHook extends AgentHookBase { + + public AgentBasedAgentHook(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, + KeystoreManager ksMgr, AgentManager agentMgr) { + super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr); + } + + @Override + protected HostVO findConsoleProxyHost(StartupProxyCommand cmd) { + return _hostDao.findByGuid(cmd.getGuid()); + } + + } + + public int getVncPort(VMInstanceVO vm) { + if (vm.getHostId() == null) { + return -1; + } + GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new GetVncPortCommand(vm.getId(), vm.getHostName())); + return (answer == null || !answer.getResult()) ? -1 : answer.getPort(); + } + + @Override + public boolean configure(String name, Map params) throws ConfigurationException { + + if (s_logger.isInfoEnabled()) { + s_logger.info("Start configuring AgentBasedConsoleProxyManager"); + } + + Map configs = _configDao.getConfiguration("management-server", params); + String value = configs.get("consoleproxy.url.port"); + if (value != null) { + _consoleProxyUrlPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_URL_PORT); + } + + value = configs.get("consoleproxy.port"); + if (value != null) { + _consoleProxyPort = NumbersUtil.parseInt(value, ConsoleProxyManager.DEFAULT_PROXY_VNC_PORT); + } + + value = configs.get("consoleproxy.sslEnabled"); + if (value != null && value.equalsIgnoreCase("true")) { + _sslEnabled = true; + } + + _instance = configs.get("instance.name"); + + _consoleProxyUrlDomain = configs.get("consoleproxy.url.domain"); + + _listener = + new ConsoleProxyListener(new AgentBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr, _agentMgr)); + _agentMgr.registerForHostEvents(_listener, true, true, false); + + if (s_logger.isInfoEnabled()) { + s_logger.info("AgentBasedConsoleProxyManager has been configured. SSL enabled: " + _sslEnabled); + } + return true; + } + + HostVO findHost(VMInstanceVO vm) { + return _hostDao.findById(vm.getHostId()); + } + + @Override + public ConsoleProxyInfo assignProxy(long dataCenterId, long userVmId) { + UserVmVO userVm = _userVmDao.findById(userVmId); + if (userVm == null) { + s_logger.warn("User VM " + userVmId + " no longer exists, return a null proxy for user vm:" + userVmId); + return null; + } + + HostVO host = findHost(userVm); + if (host != null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Assign embedded console proxy running at " + host.getName() + " to user vm " + userVmId + " with public IP " + + host.getPublicIpAddress()); + } + + // only private IP, public IP, host id have meaningful values, rest + // of all are place-holder values + String publicIp = host.getPublicIpAddress(); + if (publicIp == null) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Host " + host.getName() + "/" + host.getPrivateIpAddress() + + " does not have public interface, we will return its private IP for cosole proxy."); + } + publicIp = host.getPrivateIpAddress(); + } + + int urlPort = _consoleProxyUrlPort; + + if (host.getProxyPort() != null && host.getProxyPort().intValue() > 0) { + urlPort = host.getProxyPort().intValue(); + } + + return new ConsoleProxyInfo(_sslEnabled, publicIp, _consoleProxyPort, urlPort, _consoleProxyUrlDomain); + } else { + s_logger.warn("Host that VM is running is no longer available, console access to VM " + userVmId + " will be temporarily unavailable."); + } + return null; + } + + + + + @Override + public ConsoleProxyVO startProxy(long proxyVmId) { + return null; + } + + @Override + public boolean destroyProxy(long proxyVmId) { + return false; + } + + @Override + public boolean rebootProxy(long proxyVmId) { + return false; + } + + @Override + public boolean stopProxy(long proxyVmId) { + return false; + } + + @Override + public void setManagementState(ConsoleProxyManagementState state) { + } + + @Override + public ConsoleProxyManagementState getManagementState() { + return null; + } + + @Override + public void resumeLastManagementState() { + } + + @Override + public String getName() { + return _name; + } +<<<<<<< HEAD + + @Override + public Long convertToId(String vmName) { + if (!VirtualMachineName.isValidConsoleProxyName(vmName, _instance)) { + return null; + } + return VirtualMachineName.getConsoleProxyId(vmName); + } + + @Override + public ConsoleProxyVO findByName(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public ConsoleProxyVO findById(long id) { + // TODO Auto-generated method stub + return null; + } + + @Override + public ConsoleProxyVO persist(ConsoleProxyVO vm) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile profile, DeployDestination dest, ReservationContext context) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean finalizeCommandsOnStart(Commands cmds, VirtualMachineProfile profile) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean finalizeStart(VirtualMachineProfile profile, long hostId, Commands cmds, ReservationContext context) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void finalizeStop(VirtualMachineProfile profile, StopAnswer answer) { + // TODO Auto-generated method stub + } + + @Override + public void finalizeExpunge(ConsoleProxyVO proxy) { + } + + @Override + public boolean plugNic(Network network, NicTO nic, VirtualMachineTO vm, + ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException, + InsufficientCapacityException { + //not supported + throw new UnsupportedOperationException("Plug nic is not supported for vm of type " + vm.getType()); + } + + + @Override + public boolean unplugNic(Network network, NicTO nic, VirtualMachineTO vm, + ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException { + //not supported + throw new UnsupportedOperationException("Unplug nic is not supported for vm of type " + vm.getType()); + } + + @Override + public void prepareStop(VirtualMachineProfile profile) { + } +} +======= +} +>>>>>>> QuickCloud: refactor to avoid copy paste of authentication and startup code diff --git a/server/src/com/cloud/consoleproxy/AgentHookBase.java b/server/src/com/cloud/consoleproxy/AgentHookBase.java new file mode 100644 index 00000000000..b969f6da2ce --- /dev/null +++ b/server/src/com/cloud/consoleproxy/AgentHookBase.java @@ -0,0 +1,266 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package com.cloud.consoleproxy; + +import java.util.Date; +import java.util.Random; +import java.util.UUID; + +import org.apache.log4j.Logger; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.AgentControlAnswer; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.ConsoleAccessAuthenticationAnswer; +import com.cloud.agent.api.ConsoleAccessAuthenticationCommand; +import com.cloud.agent.api.ConsoleProxyLoadReportCommand; +import com.cloud.agent.api.GetVncPortAnswer; +import com.cloud.agent.api.GetVncPortCommand; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupProxyCommand; +import com.cloud.agent.api.proxy.StartConsoleProxyAgentHttpHandlerCommand; +import com.cloud.configuration.Config; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.host.HostVO; +import com.cloud.host.Status; +import com.cloud.host.dao.HostDao; +import com.cloud.keystore.KeystoreManager; +import com.cloud.servlet.ConsoleProxyServlet; +import com.cloud.utils.Ternary; +import com.cloud.vm.VirtualMachine; +import com.cloud.vm.dao.VMInstanceDao; + +/** + * Utility class to manage interactions with agent-based console access + * Extracted from ConsoleProxyManagerImpl so that other console proxy managers + * can reuse + */ +public abstract class AgentHookBase implements AgentHook { + private static final Logger s_logger = Logger.getLogger(AgentHookBase.class); + + VMInstanceDao _instanceDao; + HostDao _hostDao; + ConfigurationDao _configDao; + AgentManager _agentMgr; + KeystoreManager _ksMgr; + final Random _random = new Random(System.currentTimeMillis()); + private String _hashKey; + + + public AgentHookBase(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, KeystoreManager ksMgr, + AgentManager agentMgr) { + this._instanceDao = instanceDao; + this._hostDao = hostDao; + this._agentMgr = agentMgr; + this._configDao = cfgDao; + this._ksMgr = ksMgr; + } + + public String getHashKey() { + // although we may have race condition here, database transaction + // serialization should give us the same key + if (_hashKey == null) { + _hashKey = + _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), Config.HashKey.getCategory(), UUID + .randomUUID().toString()); + } + return _hashKey; + } + + public AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd) { + Long vmId = null; + + String ticketInUrl = cmd.getTicket(); + if (ticketInUrl == null) { + s_logger.error("Access ticket could not be found, you could be running an old version of console proxy. vmId: " + + cmd.getVmId()); + return new ConsoleAccessAuthenticationAnswer(cmd, false); + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Console authentication. Ticket in url for " + cmd.getHost() + ":" + cmd.getPort() + "-" + + cmd.getVmId() + " is " + ticketInUrl); + } + + if (!cmd.isReauthenticating()) { + String ticket = + ConsoleProxyServlet.genAccessTicket(cmd.getHost(), cmd.getPort(), cmd.getSid(), cmd.getVmId()); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Console authentication. Ticket in 1 minute boundary for " + cmd.getHost() + ":" + + cmd.getPort() + "-" + cmd.getVmId() + " is " + ticket); + } + + if (!ticket.equals(ticketInUrl)) { + Date now = new Date(); + // considering of minute round-up + String minuteEarlyTicket = + ConsoleProxyServlet.genAccessTicket(cmd.getHost(), cmd.getPort(), cmd.getSid(), cmd.getVmId(), + new Date(now.getTime() - 60 * 1000)); + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Console authentication. Ticket in 2-minute boundary for " + cmd.getHost() + ":" + + cmd.getPort() + "-" + cmd.getVmId() + " is " + minuteEarlyTicket); + } + + if (!minuteEarlyTicket.equals(ticketInUrl)) { + s_logger.error("Access ticket expired or has been modified. vmId: " + cmd.getVmId() + + "ticket in URL: " + ticketInUrl + ", tickets to check against: " + ticket + "," + + minuteEarlyTicket); + return new ConsoleAccessAuthenticationAnswer(cmd, false); + } + } + } + + if (cmd.getVmId() != null && cmd.getVmId().isEmpty()) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Invalid vm id sent from proxy(happens when proxy session has terminated)"); + } + return new ConsoleAccessAuthenticationAnswer(cmd, false); + } + + VirtualMachine vm = _instanceDao.findByUuid(cmd.getVmId()); + if (vm == null) { + vm = _instanceDao.findById(Long.parseLong(cmd.getVmId())); + } + if (vm == null) { + s_logger.error("Invalid vm id " + cmd.getVmId() + " sent from console access authentication"); + return new ConsoleAccessAuthenticationAnswer(cmd, false); + } + + if (vm.getHostId() == null) { + s_logger.warn("VM " + vmId + " lost host info, failed authentication request"); + return new ConsoleAccessAuthenticationAnswer(cmd, false); + } + + HostVO host = _hostDao.findById(vm.getHostId()); + if (host == null) { + s_logger.warn("VM " + vmId + "'s host does not exist, fail authentication request"); + return new ConsoleAccessAuthenticationAnswer(cmd, false); + } + + String sid = cmd.getSid(); + if (sid == null || !sid.equals(vm.getVncPassword())) { + s_logger.warn("sid " + sid + " in url does not match stored sid " + vm.getVncPassword()); + return new ConsoleAccessAuthenticationAnswer(cmd, false); + } + + if (cmd.isReauthenticating()) { + ConsoleAccessAuthenticationAnswer authenticationAnswer = new ConsoleAccessAuthenticationAnswer(cmd, true); + authenticationAnswer.setReauthenticating(true); + + s_logger.info("Re-authentication request, ask host " + vm.getHostId() + " for new console info"); + GetVncPortAnswer answer = + (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), + new GetVncPortCommand(vm.getId(), vm.getInstanceName())); + + if (answer != null && answer.getResult()) { + Ternary parsedHostInfo = ConsoleProxyServlet.parseHostInfo(answer.getAddress()); + + if (parsedHostInfo.second() != null && parsedHostInfo.third() != null) { + + s_logger.info("Re-authentication result. vm: " + vm.getId() + ", tunnel url: " + + parsedHostInfo.second() + ", tunnel session: " + parsedHostInfo.third()); + + authenticationAnswer.setTunnelUrl(parsedHostInfo.second()); + authenticationAnswer.setTunnelSession(parsedHostInfo.third()); + } else { + s_logger.info("Re-authentication result. vm: " + vm.getId() + ", host address: " + + parsedHostInfo.first() + ", port: " + answer.getPort()); + + authenticationAnswer.setHost(parsedHostInfo.first()); + authenticationAnswer.setPort(answer.getPort()); + } + } else { + s_logger.warn("Re-authentication request failed"); + + authenticationAnswer.setSuccess(false); + } + + return authenticationAnswer; + } + + return new ConsoleAccessAuthenticationAnswer(cmd, true); + } + + public void startAgentHttpHandlerInVM(StartupProxyCommand startupCmd) { + StartConsoleProxyAgentHttpHandlerCommand cmd = null; + if (_configDao.isPremium()) { + String storePassword = String.valueOf(_random.nextLong()); + byte[] ksBits = + _ksMgr.getKeystoreBits(ConsoleProxyManager.CERTIFICATE_NAME, ConsoleProxyManager.CERTIFICATE_NAME, + storePassword); + + assert (ksBits != null); + if (ksBits == null) { + s_logger.error("Could not find and construct a valid SSL certificate"); + } + cmd = new StartConsoleProxyAgentHttpHandlerCommand(ksBits, storePassword); + cmd.setEncryptorPassword(getHashKey()); + } else { + cmd = new StartConsoleProxyAgentHttpHandlerCommand(); + cmd.setEncryptorPassword(getHashKey()); + } + + try { + + HostVO consoleProxyHost = findConsoleProxyHost(startupCmd); + + assert (consoleProxyHost != null); + + Answer answer = _agentMgr.send(consoleProxyHost.getId(), cmd); + if (answer == null || !answer.getResult()) { + s_logger.error("Console proxy agent reported that it failed to execute http handling startup command"); + } else { + s_logger.info("Successfully sent out command to start HTTP handling in console proxy agent"); + } + } catch (AgentUnavailableException e) { + s_logger.error("Unable to send http handling startup command to the console proxy resource for proxy:" + + startupCmd.getProxyVmId(), e); + } catch (OperationTimedoutException e) { + s_logger.error( + "Unable to send http handling startup command(time out) to the console proxy resource for proxy:" + + startupCmd.getProxyVmId(), e); + } catch (OutOfMemoryError e) { + s_logger.error("Unrecoverable OutOfMemory Error, exit and let it be re-launched"); + System.exit(1); + } catch (Exception e) { + s_logger.error( + "Unexpected exception when sending http handling startup command(time out) to the console proxy resource for proxy:" + + startupCmd.getProxyVmId(), e); + } + } + + protected abstract HostVO findConsoleProxyHost(StartupProxyCommand cmd); + + @Override + public void onLoadReport(ConsoleProxyLoadReportCommand cmd) { + // no-op since we do not auto-scale + } + + @Override + public void onAgentConnect(HostVO host, StartupCommand cmd) { + // no-op + } + + @Override + public void onAgentDisconnect(long agentId, Status state) { + // no-op since we do not autoscale + } +} diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManager.java index 6ebf3bc61f4..faec51307b5 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManager.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManager.java @@ -16,17 +16,9 @@ // under the License. package com.cloud.consoleproxy; -import com.cloud.agent.api.AgentControlAnswer; -import com.cloud.agent.api.ConsoleAccessAuthenticationCommand; -import com.cloud.agent.api.ConsoleProxyLoadReportCommand; -import com.cloud.agent.api.StartupCommand; -import com.cloud.host.HostVO; -import com.cloud.host.Status; -import com.cloud.host.Host.Type; -import com.cloud.info.ConsoleProxyInfo; import com.cloud.utils.component.Manager; import com.cloud.vm.ConsoleProxyVO; -public interface ConsoleProxyManager extends Manager { +public interface ConsoleProxyManager extends Manager, ConsoleProxyService { public static final int DEFAULT_PROXY_CAPACITY = 50; public static final int DEFAULT_STANDBY_CAPACITY = 10; @@ -45,16 +37,9 @@ public interface ConsoleProxyManager extends Manager { public ConsoleProxyManagementState getManagementState(); public void resumeLastManagementState(); - public ConsoleProxyInfo assignProxy(long dataCenterId, long userVmId); - public ConsoleProxyVO startProxy(long proxyVmId); public boolean stopProxy(long proxyVmId); public boolean rebootProxy(long proxyVmId); public boolean destroyProxy(long proxyVmId); - - public void onLoadReport(ConsoleProxyLoadReportCommand cmd); - public AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd); - public void onAgentConnect(HostVO host, StartupCommand cmd); - public void onAgentDisconnect(long agentId, Status state); } diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 1edd8692ec7..9740d28a94f 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -23,26 +23,19 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Random; import java.util.UUID; import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; -import com.cloud.agent.api.AgentControlAnswer; import com.cloud.agent.api.Answer; -import com.cloud.agent.api.ConsoleAccessAuthenticationAnswer; -import com.cloud.agent.api.ConsoleAccessAuthenticationCommand; import com.cloud.agent.api.ConsoleProxyLoadReportCommand; -import com.cloud.agent.api.GetVncPortAnswer; -import com.cloud.agent.api.GetVncPortCommand; import com.cloud.agent.api.RebootCommand; import com.cloud.agent.api.StartupCommand; import com.cloud.agent.api.StartupProxyCommand; @@ -50,11 +43,9 @@ import com.cloud.agent.api.StopAnswer; import com.cloud.agent.api.check.CheckSshAnswer; import com.cloud.agent.api.check.CheckSshCommand; import com.cloud.agent.api.proxy.ConsoleProxyLoadAnswer; -import com.cloud.agent.api.proxy.StartConsoleProxyAgentHttpHandlerCommand; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.manager.Commands; -import com.cloud.api.commands.DestroyConsoleProxyCmd; import com.cloud.certificate.dao.CertificateDao; import com.cloud.cluster.ClusterManager; import com.cloud.configuration.Config; @@ -68,11 +59,8 @@ import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.HostPodDao; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; -import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; -import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.exception.StorageUnavailableException; import com.cloud.host.Host; @@ -109,12 +97,11 @@ import com.cloud.resource.ServerResource; import com.cloud.resource.UnableDeleteHostException; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; -import com.cloud.servlet.ConsoleProxyServlet; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.VMTemplateHostVO; -import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplateHostDao; @@ -126,8 +113,6 @@ import com.cloud.user.UserContext; import com.cloud.utils.DateUtil; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; -import com.cloud.utils.Ternary; -import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.DB; import com.cloud.utils.db.GlobalLock; @@ -170,7 +155,8 @@ import com.google.gson.GsonBuilder; // because sooner or later, it will be driven into Running state // @Local(value = { ConsoleProxyManager.class, ConsoleProxyService.class }) -public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxyManager, ConsoleProxyService, AgentHook, VirtualMachineGuru, SystemVmLoadScanHandler, ResourceStateAdapter { +public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxyManager, + VirtualMachineGuru, SystemVmLoadScanHandler, ResourceStateAdapter { private static final Logger s_logger = Logger.getLogger(ConsoleProxyManagerImpl.class); private static final int DEFAULT_CAPACITY_SCAN_INTERVAL = 30000; // 30 seconds @@ -458,7 +444,131 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy private KeystoreDao _ksDao; @Inject private KeystoreManager _ksMgr; - private final Random _random = new Random(System.currentTimeMillis()); + + public class VmBasedAgentHook extends AgentHookBase { + + public VmBasedAgentHook(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, + KeystoreManager ksMgr, AgentManager agentMgr) { + super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr); + } + + @Override + public void onLoadReport(ConsoleProxyLoadReportCommand cmd) { + if (cmd.getLoadInfo() == null) { + return; + } + + ConsoleProxyStatus status = null; + try { + GsonBuilder gb = new GsonBuilder(); + gb.setVersion(1.3); + Gson gson = gb.create(); + status = gson.fromJson(cmd.getLoadInfo(), ConsoleProxyStatus.class); + } catch (Throwable e) { + s_logger.warn("Unable to parse load info from proxy, proxy vm id : " + cmd.getProxyVmId() + ", info : " + cmd.getLoadInfo()); + } + + if (status != null) { + int count = 0; + if (status.getConnections() != null) { + count = status.getConnections().length; + } + + byte[] details = null; + if (cmd.getLoadInfo() != null) { + details = cmd.getLoadInfo().getBytes(Charset.forName("US-ASCII")); + } + _consoleProxyDao.update(cmd.getProxyVmId(), count, DateUtil.currentGMTTime(), details); + } else { + if (s_logger.isTraceEnabled()) { + s_logger.trace("Unable to get console proxy load info, id : " + cmd.getProxyVmId()); + } + + _consoleProxyDao.update(cmd.getProxyVmId(), 0, DateUtil.currentGMTTime(), null); + } + } + + @Override + public void onAgentConnect(HostVO host, StartupCommand cmd) { + // no-op + } + + @Override + public void onAgentDisconnect(long agentId, com.cloud.host.Status state) { + + if (state == com.cloud.host.Status.Alert || state == com.cloud.host.Status.Disconnected) { + // be it either in alert or in disconnected state, the agent + // process + // may be gone in the VM, + // we will be reacting to stop the corresponding VM and let the + // scan + // process to + HostVO host = _hostDao.findById(agentId); + if (host.getType() == Type.ConsoleProxy) { + String name = host.getName(); + if (s_logger.isInfoEnabled()) { + s_logger.info("Console proxy agent disconnected, proxy: " + name); + } + if (name != null && name.startsWith("v-")) { + String[] tokens = name.split("-"); + long proxyVmId = 0; + try { + proxyVmId = Long.parseLong(tokens[1]); + } catch (NumberFormatException e) { + s_logger.error("Unexpected exception " + e.getMessage(), e); + return; + } + + final ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyVmId); + if (proxy != null) { + + // Disable this feature for now, as it conflicts + // with + // the case of allowing user to reboot console proxy + // when rebooting happens, we will receive + // disconnect + // here and we can't enter into stopping process, + // as when the rebooted one comes up, it will kick + // off a + // newly started one and trigger the process + // continue on forever + + /* + * _capacityScanScheduler.execute(new Runnable() { + * public void run() { if(s_logger.isInfoEnabled()) + * s_logger.info("Stop console proxy " + + * proxy.getName() + + * " VM because of that the agent running inside it has disconnected" + * ); stopProxy(proxy.getId()); } }); + */ + } else { + if (s_logger.isInfoEnabled()) { + s_logger.info("Console proxy agent disconnected but corresponding console proxy VM no longer exists in DB, proxy: " + + name); + } + } + } else { + assert (false) : "Invalid console proxy name: " + name; + } + } + } + + } + + @Override + protected HostVO findConsoleProxyHost(StartupProxyCommand startupCmd) { + long proxyVmId = startupCmd.getProxyVmId(); + ConsoleProxyVO consoleProxy = _consoleProxyDao.findById(proxyVmId); + if (consoleProxy == null) { + s_logger.info("Proxy " + proxyVmId + " is no longer in DB, skip sending startup command"); + return null; + } + + assert (consoleProxy != null); + return findConsoleProxyHostByName(consoleProxy.getHostName()); + } + + } @Override public ConsoleProxyInfo assignProxy(final long dataCenterId, final long vmId) { @@ -850,181 +960,9 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy } } - @Override - public void onLoadReport(ConsoleProxyLoadReportCommand cmd) { - if (cmd.getLoadInfo() == null) { - return; - } - ConsoleProxyStatus status = null; - try { - GsonBuilder gb = new GsonBuilder(); - gb.setVersion(1.3); - Gson gson = gb.create(); - status = gson.fromJson(cmd.getLoadInfo(), ConsoleProxyStatus.class); - } catch (Throwable e) { - s_logger.warn("Unable to parse load info from proxy, proxy vm id : " + cmd.getProxyVmId() + ", info : " + cmd.getLoadInfo()); - } - if (status != null) { - int count = 0; - if (status.getConnections() != null) { - count = status.getConnections().length; - } - - byte[] details = null; - if (cmd.getLoadInfo() != null) { - details = cmd.getLoadInfo().getBytes(Charset.forName("US-ASCII")); - } - _consoleProxyDao.update(cmd.getProxyVmId(), count, DateUtil.currentGMTTime(), details); - } else { - if (s_logger.isTraceEnabled()) { - s_logger.trace("Unable to get console proxy load info, id : " + cmd.getProxyVmId()); - } - - _consoleProxyDao.update(cmd.getProxyVmId(), 0, DateUtil.currentGMTTime(), null); - } - } - - @Override - public AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd) { - Long vmId = null; - - String ticketInUrl = cmd.getTicket(); - if (ticketInUrl == null) { - s_logger.error("Access ticket could not be found, you could be running an old version of console proxy. vmId: " + cmd.getVmId()); - return new ConsoleAccessAuthenticationAnswer(cmd, false); - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Console authentication. Ticket in url for " + cmd.getHost() + ":" + cmd.getPort() + "-" + cmd.getVmId() + " is " + ticketInUrl); - } - - if(!cmd.isReauthenticating()) { - String ticket = ConsoleProxyServlet.genAccessTicket(cmd.getHost(), cmd.getPort(), cmd.getSid(), cmd.getVmId()); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Console authentication. Ticket in 1 minute boundary for " + cmd.getHost() + ":" + cmd.getPort() + "-" + cmd.getVmId() + " is " + ticket); - } - - if (!ticket.equals(ticketInUrl)) { - Date now = new Date(); - // considering of minute round-up - String minuteEarlyTicket = ConsoleProxyServlet.genAccessTicket(cmd.getHost(), cmd.getPort(), cmd.getSid(), cmd.getVmId(), new Date(now.getTime() - 60 * 1000)); - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Console authentication. Ticket in 2-minute boundary for " + cmd.getHost() + ":" + cmd.getPort() + "-" + cmd.getVmId() + " is " + minuteEarlyTicket); - } - - if (!minuteEarlyTicket.equals(ticketInUrl)) { - s_logger.error("Access ticket expired or has been modified. vmId: " + cmd.getVmId() + "ticket in URL: " + ticketInUrl + ", tickets to check against: " + ticket + "," - + minuteEarlyTicket); - return new ConsoleAccessAuthenticationAnswer(cmd, false); - } - } - } - - if (cmd.getVmId() != null && cmd.getVmId().isEmpty()) { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Invalid vm id sent from proxy(happens when proxy session has terminated)"); - } - return new ConsoleAccessAuthenticationAnswer(cmd, false); - } - - VirtualMachine vm = _instanceDao.findByUuid(cmd.getVmId()); - if (vm == null) { - vm = _instanceDao.findById(Long.parseLong(cmd.getVmId())); - } - if (vm == null) { - s_logger.error("Invalid vm id " + cmd.getVmId() + " sent from console access authentication"); - return new ConsoleAccessAuthenticationAnswer(cmd, false); - } - - if (vm.getHostId() == null) { - s_logger.warn("VM " + vmId + " lost host info, failed authentication request"); - return new ConsoleAccessAuthenticationAnswer(cmd, false); - } - - HostVO host = _hostDao.findById(vm.getHostId()); - if (host == null) { - s_logger.warn("VM " + vmId + "'s host does not exist, fail authentication request"); - return new ConsoleAccessAuthenticationAnswer(cmd, false); - } - - String sid = cmd.getSid(); - if (sid == null || !sid.equals(vm.getVncPassword())) { - s_logger.warn("sid " + sid + " in url does not match stored sid " + vm.getVncPassword()); - return new ConsoleAccessAuthenticationAnswer(cmd, false); - } - - if(cmd.isReauthenticating()) { - ConsoleAccessAuthenticationAnswer authenticationAnswer = new ConsoleAccessAuthenticationAnswer(cmd, true); - authenticationAnswer.setReauthenticating(true); - - s_logger.info("Re-authentication request, ask host " + vm.getHostId() + " for new console info"); - GetVncPortAnswer answer = (GetVncPortAnswer) _agentMgr.easySend(vm.getHostId(), new - GetVncPortCommand(vm.getId(), vm.getInstanceName())); - - if (answer != null && answer.getResult()) { - Ternary parsedHostInfo = ConsoleProxyServlet.parseHostInfo(answer.getAddress()); - - if(parsedHostInfo.second() != null && parsedHostInfo.third() != null) { - - s_logger.info("Re-authentication result. vm: " + vm.getId() + ", tunnel url: " + parsedHostInfo.second() - + ", tunnel session: " + parsedHostInfo.third()); - - authenticationAnswer.setTunnelUrl(parsedHostInfo.second()); - authenticationAnswer.setTunnelSession(parsedHostInfo.third()); - } else { - s_logger.info("Re-authentication result. vm: " + vm.getId() + ", host address: " + parsedHostInfo.first() - + ", port: " + answer.getPort()); - - authenticationAnswer.setHost(parsedHostInfo.first()); - authenticationAnswer.setPort(answer.getPort()); - } - } else { - s_logger.warn("Re-authentication request failed"); - - authenticationAnswer.setSuccess(false); - } - - return authenticationAnswer; - } - - return new ConsoleAccessAuthenticationAnswer(cmd, true); - } - - @Override - public void onAgentConnect(HostVO host, StartupCommand cmd) { - // if (host.getType() == Type.ConsoleProxy) { - // // TODO we can use this event to mark the proxy is up and - // // functioning instead of - // // pinging the console proxy VM command port - // // - // // for now, just log a message - // if (s_logger.isInfoEnabled()) { - // s_logger.info("Console proxy agent is connected. proxy: " + host.getName()); - // } - // - // /* update public/private ip address */ - // if (_IpAllocator != null && _IpAllocator.exteralIpAddressAllocatorEnabled()) { - // try { - // ConsoleProxyVO console = findConsoleProxyByHost(host); - // if (console == null) { - // s_logger.debug("Can't find console proxy "); - // return; - // } - // console.setPrivateIpAddress(cmd.getPrivateIpAddress()); - // console.setPublicIpAddress(cmd.getPublicIpAddress()); - // console.setPublicNetmask(cmd.getPublicNetmask()); - // _consoleProxyDao.persist(console); - // } catch (NumberFormatException e) { - // } - // } - // } - } - - @Override - public void onAgentDisconnect(long agentId, com.cloud.host.Status state) { + public void handleAgentDisconnect(long agentId, com.cloud.host.Status state) { if (state == com.cloud.host.Status.Alert || state == com.cloud.host.Status.Disconnected) { // be it either in alert or in disconnected state, the agent process // may be gone in the VM, @@ -1499,7 +1437,9 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy value = agentMgrConfigs.get("port"); _mgmt_port = NumbersUtil.parseInt(value, 8250); - _listener = new ConsoleProxyListener(this); + _listener = + new ConsoleProxyListener(new VmBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr, + _agentMgr)); _agentMgr.registerForHostEvents(_listener, true, true, false); _itMgr.registerGuru(VirtualMachine.Type.ConsoleProxy, this); @@ -1549,18 +1489,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy return true; } - @Override - public boolean destroyConsoleProxy(DestroyConsoleProxyCmd cmd) throws ServerApiException { - Long proxyId = cmd.getId(); - // verify parameters - ConsoleProxyVO proxy = _consoleProxyDao.findById(proxyId); - if (proxy == null) { - throw new InvalidParameterValueException("unable to find a console proxy with id " + proxyId); - } - - return destroyProxy(proxyId); - } protected ConsoleProxyManagerImpl() { } @@ -1733,52 +1662,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy _consoleProxyDao.update(proxy.getId(), proxy); } - @Override - public void startAgentHttpHandlerInVM(StartupProxyCommand startupCmd) { - StartConsoleProxyAgentHttpHandlerCommand cmd = null; - if (_configDao.isPremium()) { - String storePassword = String.valueOf(_random.nextLong()); - byte[] ksBits = _ksMgr.getKeystoreBits(ConsoleProxyManager.CERTIFICATE_NAME, ConsoleProxyManager.CERTIFICATE_NAME, storePassword); - assert (ksBits != null); - if (ksBits == null) { - s_logger.error("Could not find and construct a valid SSL certificate"); - } - cmd = new StartConsoleProxyAgentHttpHandlerCommand(ksBits, storePassword); - cmd.setEncryptorPassword(getHashKey()); - } else { - cmd = new StartConsoleProxyAgentHttpHandlerCommand(); - cmd.setEncryptorPassword(getHashKey()); - } - - try { - long proxyVmId = startupCmd.getProxyVmId(); - ConsoleProxyVO consoleProxy = _consoleProxyDao.findById(proxyVmId); - if (consoleProxy == null) { - s_logger.info("Proxy " + proxyVmId + " is no longer in DB, skip sending startup command"); - return; - } - - assert (consoleProxy != null); - HostVO consoleProxyHost = findConsoleProxyHostByName(consoleProxy.getHostName()); - - Answer answer = _agentMgr.send(consoleProxyHost.getId(), cmd); - if (answer == null || !answer.getResult()) { - s_logger.error("Console proxy agent reported that it failed to execute http handling startup command"); - } else { - s_logger.info("Successfully sent out command to start HTTP handling in console proxy agent"); - } - } catch (AgentUnavailableException e) { - s_logger.error("Unable to send http handling startup command to the console proxy resource for proxy:" + startupCmd.getProxyVmId(), e); - } catch (OperationTimedoutException e) { - s_logger.error("Unable to send http handling startup command(time out) to the console proxy resource for proxy:" + startupCmd.getProxyVmId(), e); - } catch (OutOfMemoryError e) { - s_logger.error("Unrecoverable OutOfMemory Error, exit and let it be re-launched"); - System.exit(1); - } catch (Exception e) { - s_logger.error("Unexpected exception when sending http handling startup command(time out) to the console proxy resource for proxy:" + startupCmd.getProxyVmId(), e); - } - } @Override public ConsoleProxyVO persist(ConsoleProxyVO proxy) { diff --git a/api/src/com/cloud/consoleproxy/ConsoleProxyService.java b/server/src/com/cloud/consoleproxy/ConsoleProxyService.java similarity index 87% rename from api/src/com/cloud/consoleproxy/ConsoleProxyService.java rename to server/src/com/cloud/consoleproxy/ConsoleProxyService.java index c347e0bf9fc..fd00f56333a 100644 --- a/api/src/com/cloud/consoleproxy/ConsoleProxyService.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyService.java @@ -16,8 +16,10 @@ // under the License. package com.cloud.consoleproxy; -import com.cloud.api.commands.DestroyConsoleProxyCmd; +import com.cloud.info.ConsoleProxyInfo; public interface ConsoleProxyService { - boolean destroyConsoleProxy(DestroyConsoleProxyCmd cmd); -} + + public abstract ConsoleProxyInfo assignProxy(long dataCenterId, long userVmId); + +} \ No newline at end of file diff --git a/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java index 3ba98a94362..7b59a6bf45e 100755 --- a/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java +++ b/server/src/com/cloud/consoleproxy/StaticConsoleProxyManager.java @@ -16,29 +16,59 @@ // under the License. package com.cloud.consoleproxy; + import java.util.List; import java.util.Map; +import java.util.Random; import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; -import org.springframework.stereotype.Component; +import org.apache.log4j.Logger; +import com.cloud.agent.api.StartupCommand; +import com.cloud.agent.api.StartupProxyCommand; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.host.Host.Type; import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; import com.cloud.info.ConsoleProxyInfo; +import com.cloud.keystore.KeystoreDao; +import com.cloud.keystore.KeystoreManager; import com.cloud.resource.ResourceManager; +import com.cloud.resource.ResourceStateAdapter; +import com.cloud.resource.ServerResource; +import com.cloud.resource.UnableDeleteHostException; +import com.cloud.utils.NumbersUtil; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.dao.ConsoleProxyDao; +import com.cloud.vm.dao.VMInstanceDao; @Local(value={ConsoleProxyManager.class}) -public class StaticConsoleProxyManager extends AgentBasedConsoleProxyManager implements ConsoleProxyManager { - String _ip = null; - @Inject ConsoleProxyDao _proxyDao; - @Inject ResourceManager _resourceMgr; - @Inject ConfigurationDao _configDao; +public class StaticConsoleProxyManager extends AgentBasedConsoleProxyManager implements ConsoleProxyManager, + ResourceStateAdapter { + private static final Logger s_logger = Logger.getLogger(StaticConsoleProxyManager.class); + + @Inject + ConsoleProxyDao _proxyDao; + @Inject + ResourceManager _resourceMgr; + @Inject + ConfigurationDao _configDao; + @Inject + private VMInstanceDao _instanceDao; + @Inject + KeystoreDao _ksDao; + @Inject + private KeystoreManager _ksMgr; + @Inject + private HostDao _hostDao; + private final Random _random = new Random(System.currentTimeMillis()); + private String _hashKey; + private String _ip = null; + + @Override protected HostVO findHost(VMInstanceVO vm) { @@ -50,20 +80,52 @@ public class StaticConsoleProxyManager extends AgentBasedConsoleProxyManager imp @Override public ConsoleProxyInfo assignProxy(long dataCenterId, long userVmId) { - return new ConsoleProxyInfo(false, _ip, _consoleProxyPort, _consoleProxyUrlPort, _consoleProxyUrlDomain); + return new ConsoleProxyInfo(_sslEnabled, _ip, _consoleProxyPort, _consoleProxyUrlPort, _consoleProxyUrlDomain); } @Override public boolean configure(String name, Map params) throws ConfigurationException { super.configure(name, params); - - Map dbParams = _configDao.getConfiguration("ManagementServer", params); - - _ip = dbParams.get("public.ip"); + _ip = _configDao.getValue("consoleproxy.static.publicIp"); if (_ip == null) { _ip = "127.0.0.1"; } + + String value = (String) params.get("consoleproxy.sslEnabled"); + if (value != null && value.equalsIgnoreCase("true")) { + _sslEnabled = true; + } + int defaultPort = 8088; + if (_sslEnabled) + defaultPort = 8443; + _consoleProxyUrlPort = NumbersUtil.parseInt(_configDao.getValue("consoleproxy.static.port"), defaultPort); + + _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this); + return true; } + + @Override + public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) { + if (!(cmd[0] instanceof StartupProxyCommand)) { + return null; + } + + host.setType(com.cloud.host.Host.Type.ConsoleProxy); + return host; + } + + @Override + public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, + Map details, List hostTags) { + return null; + } + + @Override + public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) + throws UnableDeleteHostException { + return null; + } + } diff --git a/server/src/com/cloud/deploy/FirstFitPlanner.java b/server/src/com/cloud/deploy/FirstFitPlanner.java index 012d160d3ef..2dffe70fb46 100755 --- a/server/src/com/cloud/deploy/FirstFitPlanner.java +++ b/server/src/com/cloud/deploy/FirstFitPlanner.java @@ -102,7 +102,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { @Inject protected StorageManager _storageMgr; @Inject DataStoreManager dataStoreMgr; @Inject protected ClusterDetailsDao _clusterDetailsDao; - + protected List _storagePoolAllocators; public List getStoragePoolAllocators() { return _storagePoolAllocators; @@ -157,7 +157,8 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { if(plan.getHostId() != null && haVmTag == null){ Long hostIdSpecified = plan.getHostId(); if (s_logger.isDebugEnabled()){ - s_logger.debug("DeploymentPlan has host_id specified, making no checks on this host, looks like admin test: "+hostIdSpecified); + s_logger.debug("DeploymentPlan has host_id specified, choosing this host and making no checks on this host: " + + hostIdSpecified); } HostVO host = _hostDao.findById(hostIdSpecified); if (s_logger.isDebugEnabled()) { @@ -407,9 +408,9 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { } /** - * This method should reorder the given list of Cluster Ids by applying any necessary heuristic + * This method should reorder the given list of Cluster Ids by applying any necessary heuristic * for this planner - * For FirstFitPlanner there is no specific heuristic to be applied + * For FirstFitPlanner there is no specific heuristic to be applied * other than the capacity based ordering which is done by default. * @return List ordered list of Cluster Ids */ @@ -419,9 +420,9 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { } /** - * This method should reorder the given list of Pod Ids by applying any necessary heuristic + * This method should reorder the given list of Pod Ids by applying any necessary heuristic * for this planner - * For FirstFitPlanner there is no specific heuristic to be applied + * For FirstFitPlanner there is no specific heuristic to be applied * other than the capacity based ordering which is done by default. * @return List ordered list of Pod Ids */ @@ -443,7 +444,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { private List listDisabledPods(long zoneId){ List disabledPods = _podDao.listDisabledPods(zoneId); return disabledPods; - } + } private Map getCapacityThresholdMap(){ // Lets build this real time so that the admin wont have to restart MS if he changes these values @@ -461,9 +462,9 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { } private List getCapacitiesForCheckingThreshold(){ - List capacityList = new ArrayList(); + List capacityList = new ArrayList(); capacityList.add(Capacity.CAPACITY_TYPE_CPU); - capacityList.add(Capacity.CAPACITY_TYPE_MEMORY); + capacityList.add(Capacity.CAPACITY_TYPE_MEMORY); return capacityList; } @@ -479,7 +480,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { // For each capacity get the cluster list crossing the threshold and remove it from the clusterList that will be used for vm allocation. for(short capacity : capacityList){ - + if (clusterListForVmAllocation == null || clusterListForVmAllocation.size() == 0){ return; } @@ -492,17 +493,17 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { capacityThresholdMap.get(capacity), ram_requested ); } - + if (clustersCrossingThreshold != null && clustersCrossingThreshold.size() != 0){ // addToAvoid Set avoid.addClusterList(clustersCrossingThreshold); // Remove clusters crossing disabled threshold clusterListForVmAllocation.removeAll(clustersCrossingThreshold); - + s_logger.debug("Cannot allocate cluster list " + clustersCrossingThreshold.toString() + " for vm creation since their allocated percentage" + " crosses the disable capacity threshold: " + capacityThresholdMap.get(capacity) + " for capacity Type : " + capacity + ", skipping these clusters"); } - + } } @@ -652,7 +653,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { public int compare(Volume v1, Volume v2) { if(v1.getSize() < v2.getSize()) return 1; - else + else return -1; } }); @@ -749,7 +750,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { }else{ pool = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(plan.getPoolId()); } - + if(!pool.isInMaintenance()){ if(!avoid.shouldAvoid(pool)){ long exstPoolDcId = pool.getDataCenterId(); @@ -781,13 +782,13 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { if(!isRootAdmin(plan.getReservationContext())){ if(!isEnabledForAllocation(plan.getDataCenterId(), plan.getPodId(), plan.getClusterId())){ if(s_logger.isDebugEnabled()){ - s_logger.debug("Cannot allocate new storagepool for this volume in this cluster, allocation state is disabled"); + s_logger.debug("Cannot allocate new storagepool for this volume in this cluster, allocation state is disabled"); s_logger.debug("Cannot deploy to this specified plan, allocation state is disabled, returning."); } - //Cannot find suitable storage pools under this cluster for this volume since allocation_state is disabled. + //Cannot find suitable storage pools under this cluster for this volume since allocation_state is disabled. //- remove any suitable pools found for other volumes. //All volumes should get suitable pools under this cluster; else we cant use this cluster. - suitableVolumeStoragePools.clear(); + suitableVolumeStoragePools.clear(); break; } } @@ -877,7 +878,7 @@ public class FirstFitPlanner extends PlannerBase implements DeploymentPlanner { super.configure(name, params); _allocationAlgorithm = _configDao.getValue(Config.VmAllocationAlgorithm.key()); return true; - } + } private boolean isEnabledForAllocation(long zoneId, Long podId, Long clusterId){ // Check if the zone exists in the system diff --git a/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java b/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java index 0fe0b535f78..1fdc03a74fe 100644 --- a/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java +++ b/server/src/com/cloud/hypervisor/dao/HypervisorCapabilitiesDao.java @@ -33,4 +33,6 @@ public interface HypervisorCapabilitiesDao extends GenericDao>(), true, + Network.GuestType.Shared, false, null, true, null, true, false); + offering.setState(NetworkOffering.State.Enabled); + _networkOfferingDao.update(offering.getId(), offering); + } if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultSharedNetworkOfferingWithSGService) == null) { - offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultSharedNetworkOfferingWithSGService, "Offering for Shared Security group enabled networks", TrafficType.Guest, null, - true, Availability.Optional, null, defaultSharedNetworkOfferingProviders, true, Network.GuestType.Shared, false, null, true, null, true, false); + offering = + _configMgr.createNetworkOffering(NetworkOffering.DefaultSharedNetworkOfferingWithSGService, + "Offering for Shared Security group enabled networks", TrafficType.Guest, null, true, + Availability.Optional, null, defaultSharedNetworkOfferingProviders, true, + Network.GuestType.Shared, false, null, true, null, true, false); offering.setState(NetworkOffering.State.Enabled); _networkOfferingDao.update(offering.getId(), offering); } diff --git a/server/src/com/cloud/secstorage/PremiumSecondaryStorageManagerImpl.java b/server/src/com/cloud/secstorage/PremiumSecondaryStorageManagerImpl.java index 73015c11464..8658113d0f6 100755 --- a/server/src/com/cloud/secstorage/PremiumSecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/secstorage/PremiumSecondaryStorageManagerImpl.java @@ -25,8 +25,6 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Component; import com.cloud.agent.api.Command; import com.cloud.configuration.Config; @@ -90,6 +88,10 @@ public class PremiumSecondaryStorageManagerImpl extends SecondaryStorageManagerI @Override public Pair scanPool(Long pool) { long dataCenterId = pool.longValue(); + if (!isSecondaryStorageVmRequired(dataCenterId)) { + return new Pair(AfterScanAction.nop, null); + } + Date cutTime = new Date(DateUtil.currentGMTTime().getTime() - _maxExecutionTimeMs); _cmdExecLogDao.expungeExpiredRecords(cutTime); diff --git a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java index cfb92d5ccde..5d7a2106e6a 100755 --- a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java +++ b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java @@ -851,7 +851,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor TemplateInfo tmpltInfo = templateInfos.remove(uniqueName); toBeDownloaded.remove(tmplt); if (tmpltHost != null) { - s_logger.info("Template Sync found " + uniqueName + " already in the template host table"); + s_logger.info("Template Sync found " + tmplt.getName() + " already in the template host table"); if (tmpltHost.getDownloadState() != Status.DOWNLOADED) { tmpltHost.setErrorString(""); } @@ -911,10 +911,12 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor continue; } if (tmpltHost != null && tmpltHost.getDownloadState() != Status.DOWNLOADED) { - s_logger.info("Template Sync did not find " + uniqueName + " ready on server " + sserverId + ", will request download to start/resume shortly"); + s_logger.info("Template Sync did not find " + tmplt.getName() + " ready on server " + sserverId + + ", will request download to start/resume shortly"); } else if (tmpltHost == null) { - s_logger.info("Template Sync did not find " + uniqueName + " on the server " + sserverId + ", will request download shortly"); + s_logger.info("Template Sync did not find " + tmplt.getName() + " on the server " + sserverId + + ", will request download shortly"); VMTemplateHostVO templtHost = new VMTemplateHostVO(sserverId, tmplt.getId(), new Date(), 0, Status.NOT_DOWNLOADED, null, null, null, null, tmplt.getUrl()); _vmTemplateHostDao.persist(templtHost); VMTemplateZoneVO tmpltZoneVO = _vmTemplateZoneDao.findByZoneTemplate(zoneId, tmplt.getId()); @@ -964,6 +966,9 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor } s_logger.debug("Template " + tmplt.getName() + " needs to be downloaded to " + ssHost.getName()); downloadTemplateToStorage(tmplt, ssHost); + } else { + s_logger.info("Skipping download of template " + tmplt.getName() + " since we don't have any " + + tmplt.getHypervisorType() + " hypervisors"); } } } diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index c94224b264c..3cf9a7ef5a3 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -30,8 +30,6 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Component; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; @@ -98,8 +96,8 @@ import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.SnapshotVO; import com.cloud.storage.Storage; import com.cloud.storage.VMTemplateHostVO; -import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.storage.VMTemplateVO; import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.VMTemplateDao; @@ -474,7 +472,7 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar } - private boolean isSecondaryStorageVmRequired(long dcId) { + protected boolean isSecondaryStorageVmRequired(long dcId) { DataCenterVO dc = _dcDao.findById(dcId); _dcDao.loadDetails(dc); String ssvmReq = dc.getDetail(ZoneConfig.EnableSecStorageVm.key()); @@ -1066,10 +1064,10 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar buf.append(" resource=com.cloud.storage.resource.PremiumSecondaryStorageResource"); } else { s_logger.debug("Telling the ssvm to load the NfsSecondaryStorageResource"); - buf.append(" resource=com.cloud.storage.resource.NfsSecondaryStorageResource"); + buf.append(" resource=org.apache.cloudstack.storage.resource.NfsSecondaryStorageResource"); } } else { - buf.append(" resource=com.cloud.storage.resource.NfsSecondaryStorageResource"); + buf.append(" resource=org.apache.cloudstack.storage.resource.NfsSecondaryStorageResource"); } buf.append(" instance=SecStorage"); buf.append(" sslcopy=").append(Boolean.toString(_useSSlCopy)); diff --git a/server/src/com/cloud/upgrade/dao/Upgrade410to420.java b/server/src/com/cloud/upgrade/dao/Upgrade410to420.java index f39038fea8a..b43e494893b 100644 --- a/server/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/server/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -65,6 +65,7 @@ public class Upgrade410to420 implements DbUpgrade { updateSystemVmTemplates(conn); updateCluster_details(conn); updatePrimaryStore(conn); + addEgressFwRulesForSRXGuestNw(conn); } private void updateSystemVmTemplates(Connection conn) { @@ -305,4 +306,63 @@ public class Upgrade410to420 implements DbUpgrade { } } } + private void addEgressFwRulesForSRXGuestNw(Connection conn) { + PreparedStatement pstmt = null; + ResultSet rs = null; + ResultSet rsId = null; + ResultSet rsNw = null; + try { + pstmt = conn.prepareStatement("select network_id FROM `cloud`.`ntwk_service_map` where service='Firewall' and provider='JuniperSRX' "); + rs = pstmt.executeQuery(); + while (rs.next()) { + long netId = rs.getLong(1); + //checking for Isolated OR Virtual + pstmt = conn.prepareStatement("select account_id, domain_id FROM `cloud`.`networks` where (guest_type='Isolated' OR guest_type='Virtual') and traffic_type='Guest' and vpc_id is NULL and (state='implemented' OR state='Shutdown') and id=? "); + pstmt.setLong(1, netId); + s_logger.debug("Getting account_id, domain_id from networks table: " + pstmt); + rsNw = pstmt.executeQuery(); + + if(rsNw.next()) { + long accountId = rsNw.getLong(1); + long domainId = rsNw.getLong(2); + + //Add new rule for the existing networks + s_logger.debug("Adding default egress firewall rule for network " + netId); + pstmt = conn.prepareStatement("INSERT INTO firewall_rules (uuid, state, protocol, purpose, account_id, domain_id, network_id, xid, created, traffic_type) VALUES (?, 'Active', 'all', 'Firewall', ?, ?, ?, ?, now(), 'Egress')"); + pstmt.setString(1, UUID.randomUUID().toString()); + pstmt.setLong(2, accountId); + pstmt.setLong(3, domainId); + pstmt.setLong(4, netId); + pstmt.setString(5, UUID.randomUUID().toString()); + s_logger.debug("Inserting default egress firewall rule " + pstmt); + pstmt.executeUpdate(); + + pstmt = conn.prepareStatement("select id from firewall_rules where protocol='all' and network_id=?"); + pstmt.setLong(1, netId); + rsId = pstmt.executeQuery(); + + long firewallRuleId; + if(rsId.next()) { + firewallRuleId = rsId.getLong(1); + pstmt = conn.prepareStatement("insert into firewall_rules_cidrs (firewall_rule_id,source_cidr) values (?, '0.0.0.0/0')"); + pstmt.setLong(1, firewallRuleId); + s_logger.debug("Inserting rule for cidr 0.0.0.0/0 for the new Firewall rule id=" + firewallRuleId + " with statement " + pstmt); + pstmt.executeUpdate(); + } + } + } + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to set egress firewall rules ", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + } } diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index 9736aa122e6..bc93df8e756 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -2138,7 +2138,6 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M permittedAccounts, Ternary domainIdRecursiveListProject, boolean listAll, boolean forProjectInvitation) { Long domainId = domainIdRecursiveListProject.first(); - if (domainId != null) { Domain domain = _domainDao.findById(domainId); if (domain == null) { @@ -2154,10 +2153,13 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M } Account userAccount = null; + Domain domain = null; if (domainId != null) { userAccount = _accountDao.findActiveAccount(accountName, domainId); + domain = _domainDao.findById(domainId); } else { userAccount = _accountDao.findActiveAccount(accountName, caller.getDomainId()); + domain = _domainDao.findById(caller.getDomainId()); } if (userAccount != null) { @@ -2165,7 +2167,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M //check permissions permittedAccounts.add(userAccount.getId()); } else { - throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domainId); + throw new InvalidParameterValueException("could not find account " + accountName + " in domain " + domain.getUuid()); } } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 646cf9285e3..1c3764a8391 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -2485,6 +2485,21 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use _vmCloneSettingDao.persist(vmCloneSettingVO); } + long guestOSId = template.getGuestOSId(); + GuestOSVO guestOS = _guestOSDao.findById(guestOSId); + long guestOSCategoryId = guestOS.getCategoryId(); + GuestOSCategoryVO guestOSCategory = _guestOSCategoryDao.findById(guestOSCategoryId); + + + // If hypervisor is vSphere and OS is OS X, set special settings. + if (hypervisorType.equals(HypervisorType.VMware)) { + if (guestOS.getDisplayName().toLowerCase().contains("apple mac os")){ + vm.setDetail("smc.present", "TRUE"); + vm.setDetail(VmDetailConstants.ROOK_DISK_CONTROLLER, "scsi"); + vm.setDetail("firmware", "efi"); + s_logger.info("guestOS is OSX : overwrite root disk controller to scsi, use smc and efi"); + } + } _vmDao.persist(vm); _vmDao.saveDetails(vm); @@ -2492,12 +2507,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use s_logger.debug("Allocating in the DB for vm"); DataCenterDeployment plan = new DataCenterDeployment(zone.getId()); - - long guestOSId = template.getGuestOSId(); - GuestOSVO guestOS = _guestOSDao.findById(guestOSId); - long guestOSCategoryId = guestOS.getCategoryId(); - GuestOSCategoryVO guestOSCategory = _guestOSCategoryDao.findById(guestOSCategoryId); - List computeTags = new ArrayList(); computeTags.add(offering.getHostTag()); diff --git a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java index 638be6c0c9b..86871635b02 100644 --- a/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java +++ b/server/src/com/cloud/vm/snapshot/VMSnapshotManagerImpl.java @@ -59,6 +59,7 @@ import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; import com.cloud.hypervisor.HypervisorGuruManager; import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.storage.GuestOSVO; @@ -119,7 +120,9 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana @Inject VirtualMachineManager _itMgr; @Inject DataStoreManager dataStoreMgr; @Inject ConfigurationDao _configDao; + @Inject HypervisorCapabilitiesDao _hypervisorCapabilitiesDao; int _vmSnapshotMax; + int _wait; StateMachine2 _vmSnapshottateMachine ; @Override @@ -131,6 +134,9 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana } _vmSnapshotMax = NumbersUtil.parseInt(_configDao.getValue("vmsnapshot.max"), VMSNAPSHOTMAX); + + String value = _configDao.getValue("vmsnapshot.create.wait"); + _wait = NumbersUtil.parseInt(value, 1800); _vmSnapshottateMachine = VMSnapshot.State.getStateMachine(); return true; @@ -240,7 +246,11 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana if (userVmVo == null) { throw new InvalidParameterValueException("Creating VM snapshot failed due to VM:" + vmId + " is a system VM or does not exist"); } - + + // check hypervisor capabilities + if(!_hypervisorCapabilitiesDao.isVmSnapshotEnabled(userVmVo.getHypervisorType(), "default")) + throw new InvalidParameterValueException("VM snapshot is not enabled for hypervisor type: " + userVmVo.getHypervisorType()); + // parameter length check if(vsDisplayName != null && vsDisplayName.length()>255) throw new InvalidParameterValueException("Creating VM snapshot failed due to length of VM snapshot vsDisplayName should not exceed 255"); @@ -361,6 +371,7 @@ public class VMSnapshotManagerImpl extends ManagerBase implements VMSnapshotMana vmSnapshot.setParent(current.getId()); CreateVMSnapshotCommand ccmd = new CreateVMSnapshotCommand(userVm.getInstanceName(),target ,volumeTOs, guestOS.getDisplayName(),userVm.getState()); + ccmd.setWait(_wait); answer = (CreateVMSnapshotAnswer) sendToPool(hostId, ccmd); if (answer != null && answer.getResult()) { diff --git a/server/test/com/cloud/vm/snapshot/VMSnapshotManagerTest.java b/server/test/com/cloud/vm/snapshot/VMSnapshotManagerTest.java index 576c95b3788..41c9d120539 100644 --- a/server/test/com/cloud/vm/snapshot/VMSnapshotManagerTest.java +++ b/server/test/com/cloud/vm/snapshot/VMSnapshotManagerTest.java @@ -27,6 +27,8 @@ import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.List; +import javax.inject.Inject; + import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; @@ -36,6 +38,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import com.amazonaws.services.ec2.model.HypervisorType; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.CreateVMSnapshotAnswer; @@ -47,7 +50,9 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.ResourceAllocationException; import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor; import com.cloud.hypervisor.HypervisorGuruManager; +import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; import com.cloud.storage.GuestOSVO; import com.cloud.storage.Snapshot; import com.cloud.storage.SnapshotVO; @@ -88,6 +93,7 @@ public class VMSnapshotManagerTest { @Mock SnapshotDao _snapshotDao; @Mock VirtualMachineManager _itMgr; @Mock ConfigurationDao _configDao; + @Mock HypervisorCapabilitiesDao _hypervisorCapabilitiesDao; int _vmSnapshotMax = 10; private static long TEST_VM_ID = 3L; @@ -105,6 +111,7 @@ public class VMSnapshotManagerTest { _vmSnapshotMgr._accountMgr = _accountMgr; _vmSnapshotMgr._snapshotDao = _snapshotDao; _vmSnapshotMgr._guestOSDao = _guestOSDao; + _vmSnapshotMgr._hypervisorCapabilitiesDao = _hypervisorCapabilitiesDao; doNothing().when(_accountMgr).checkAccess(any(Account.class), any(AccessType.class), any(Boolean.class), any(ControlledEntity.class)); @@ -114,7 +121,8 @@ public class VMSnapshotManagerTest { when(_userVMDao.findById(anyLong())).thenReturn(vmMock); when(_vmSnapshotDao.findByName(anyLong(), anyString())).thenReturn(null); when(_vmSnapshotDao.findByVm(anyLong())).thenReturn(new ArrayList()); - + when(_hypervisorCapabilitiesDao.isVmSnapshotEnabled(Hypervisor.HypervisorType.XenServer, "default")).thenReturn(true); + List mockVolumeList = new ArrayList(); mockVolumeList.add(volumeMock); when(volumeMock.getInstanceId()).thenReturn(TEST_VM_ID); @@ -122,7 +130,7 @@ public class VMSnapshotManagerTest { when(vmMock.getInstanceName()).thenReturn("i-3-VM-TEST"); when(vmMock.getState()).thenReturn(State.Running); - + when(vmMock.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.XenServer); when(_guestOSDao.findById(anyLong())).thenReturn(mock(GuestOSVO.class)); } @@ -133,6 +141,14 @@ public class VMSnapshotManagerTest { _vmSnapshotMgr.allocVMSnapshot(TEST_VM_ID,"","",true); } + // hypervisorCapabilities not expected case + @Test(expected=InvalidParameterValueException.class) + public void testAllocVMSnapshotF6() throws ResourceAllocationException{ + when(vmMock.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.Ovm); + when(_hypervisorCapabilitiesDao.isVmSnapshotEnabled(Hypervisor.HypervisorType.Ovm, "default")).thenReturn(false); + _vmSnapshotMgr.allocVMSnapshot(TEST_VM_ID,"","",true); + } + // vm state not in [running, stopped] case @Test(expected=InvalidParameterValueException.class) public void testAllocVMSnapshotF2() throws ResourceAllocationException{ diff --git a/services/console-proxy/server/conf/agent.properties b/services/console-proxy/server/conf/agent.properties index 4e217f21100..246cb1c3d08 100644 --- a/services/console-proxy/server/conf/agent.properties +++ b/services/console-proxy/server/conf/agent.properties @@ -1,19 +1,2 @@ -# 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. - instance=ConsoleProxy resource=com.cloud.agent.resource.consoleproxy.ConsoleProxyResource diff --git a/services/console-proxy/server/conf/environment.properties b/services/console-proxy/server/conf/environment.properties new file mode 100644 index 00000000000..269acad9152 --- /dev/null +++ b/services/console-proxy/server/conf/environment.properties @@ -0,0 +1,2 @@ +paths.script=../../scripts/storage/secondary/ +paths.pid=. diff --git a/services/console-proxy/server/conf/log4j-cloud.xml b/services/console-proxy/server/conf/log4j-cloud.xml index 5b31c9db967..2d1d361c939 100644 --- a/services/console-proxy/server/conf/log4j-cloud.xml +++ b/services/console-proxy/server/conf/log4j-cloud.xml @@ -27,7 +27,7 @@ under the License. - + diff --git a/services/console-proxy/server/pom.xml b/services/console-proxy/server/pom.xml index f57b4caddd6..3ac5d5957f7 100644 --- a/services/console-proxy/server/pom.xml +++ b/services/console-proxy/server/pom.xml @@ -57,6 +57,11 @@ ${project.version} pom + + org.apache.cloudstack + cloud-secondary-storage + ${project.version} + install @@ -254,6 +259,42 @@ + + quickcloud + + + + org.codehaus.mojo + exec-maven-plugin + 1.2.1 + + + + java + + + + + com.cloud.agent.AgentShell + + zone=1 + pod=1 + host=192.168.56.1 + guid=ConsoleProxy.1 + + + + javax.net.ssl.trustStore + certs/realhostip.keystore + log.home + ${PWD}/ + + + + + + + diff --git a/services/console-proxy/server/scripts/_run.sh b/services/console-proxy/server/scripts/_run.sh index e408378afbc..bd063468cfb 100755 --- a/services/console-proxy/server/scripts/_run.sh +++ b/services/console-proxy/server/scripts/_run.sh @@ -35,6 +35,7 @@ do CP=${CP}:$file done keyvalues= +LOGHOME=/var/log/cloud/ CMDLINE=$(cat /var/cache/cloud/cmdline) @@ -60,4 +61,4 @@ then maxmem=$eightypcnt fi -java -Djavax.net.ssl.trustStore=./certs/realhostip.keystore -mx${maxmem}m -cp $CP com.cloud.agent.AgentShell $keyvalues $@ +java -Djavax.net.ssl.trustStore=./certs/realhostip.keystore -Dlog.home=$LOGHOME -mx${maxmem}m -cp $CP com.cloud.agent.AgentShell $keyvalues $@ diff --git a/services/console-proxy/server/scripts/consoleproxy.sh b/services/console-proxy/server/scripts/consoleproxy.sh new file mode 100755 index 00000000000..294d5974bb5 --- /dev/null +++ b/services/console-proxy/server/scripts/consoleproxy.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + + + +#runs the console proxy as a standalone server +#i.e., not in the system vm + +CP=./:./conf +for file in *.jar +do + CP=${CP}:$file +done +keyvalues= +#LOGHOME=/var/log/cloud/ +LOGHOME=$PWD/ + +java -Djavax.net.ssl.trustStore=./certs/realhostip.keystore -Dlog.home=$LOGHOME -cp $CP com.cloud.agent.AgentShell $keyvalues $@ diff --git a/services/console-proxy/server/scripts/secstorage.sh b/services/console-proxy/server/scripts/secstorage.sh new file mode 100755 index 00000000000..b45afc2e8ca --- /dev/null +++ b/services/console-proxy/server/scripts/secstorage.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + + + +#runs the secondary storage service as a standalone server +#i.e., not in the system vm + +CP=./:./conf +for file in *.jar +do + CP=${CP}:$file +done +keyvalues= +#LOGHOME=/var/log/cloud/ +LOGHOME=$PWD/ + +java -Djavax.net.ssl.trustStore=./certs/realhostip.keystore -Dlog.home=$LOGHOME -cp $CP com.cloud.agent.AgentShell $keyvalues $@ diff --git a/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxy.java b/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxy.java index b5c29892a7b..2abce565856 100644 --- a/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxy.java +++ b/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxy.java @@ -17,6 +17,8 @@ package com.cloud.consoleproxy; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -34,6 +36,7 @@ import org.apache.commons.codec.binary.Base64; import org.apache.log4j.xml.DOMConfigurator; import com.cloud.consoleproxy.util.Logger; +import com.cloud.utils.PropertiesUtil; import com.google.gson.Gson; import com.sun.net.httpserver.HttpServer; @@ -282,8 +285,17 @@ public class ConsoleProxy { InputStream confs = ConsoleProxy.class.getResourceAsStream("/conf/consoleproxy.properties"); Properties props = new Properties(); if (confs == null) { - s_logger.info("Can't load consoleproxy.properties from classpath, will use default configuration"); - } else { + final File file = PropertiesUtil.findConfigFile("consoleproxy.properties"); + if (file == null) + s_logger.info("Can't load consoleproxy.properties from classpath, will use default configuration"); + else + try { + confs = new FileInputStream(file); + } catch (FileNotFoundException e) { + s_logger.info("Ignoring file not found exception and using defaults"); + } + } + if (confs != null) { try { props.load(confs); diff --git a/services/pom.xml b/services/pom.xml index 35ec2e186ba..54b22bbbf62 100644 --- a/services/pom.xml +++ b/services/pom.xml @@ -32,5 +32,6 @@ console-proxy + secondary-storage diff --git a/services/secondary-storage/conf/agent.properties b/services/secondary-storage/conf/agent.properties new file mode 100644 index 00000000000..aab82b63374 --- /dev/null +++ b/services/secondary-storage/conf/agent.properties @@ -0,0 +1,2 @@ +#mount.path=~/secondary-storage/ +resource=org.apache.cloudstack.storage.resource.NfsSecondaryStorageResource diff --git a/services/secondary-storage/conf/environment.properties b/services/secondary-storage/conf/environment.properties new file mode 100644 index 00000000000..269acad9152 --- /dev/null +++ b/services/secondary-storage/conf/environment.properties @@ -0,0 +1,2 @@ +paths.script=../../scripts/storage/secondary/ +paths.pid=. diff --git a/services/secondary-storage/conf/log4j-cloud.xml b/services/secondary-storage/conf/log4j-cloud.xml new file mode 100644 index 00000000000..7d9d22cfa99 --- /dev/null +++ b/services/secondary-storage/conf/log4j-cloud.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/services/secondary-storage/pom.xml b/services/secondary-storage/pom.xml new file mode 100644 index 00000000000..2c8a1d0b9b8 --- /dev/null +++ b/services/secondary-storage/pom.xml @@ -0,0 +1,103 @@ + + + 4.0.0 + cloud-secondary-storage + Apache CloudStack Secondary Storage Service + + org.apache.cloudstack + cloud-services + 4.2.0-SNAPSHOT + ../pom.xml + + + + log4j + log4j + ${cs.log4j.version} + + + com.google.code.gson + gson + ${cs.gson.version} + + + commons-codec + commons-codec + ${cs.codec.version} + + + + org.apache.cloudstack + cloud-agent + ${project.version} + + + org.apache.cloudstack + cloud-patches + ${project.version} + pom + + + org.apache.cloudstack + cloud-server + ${project.version} + + + + install + src + + + org.codehaus.mojo + exec-maven-plugin + 1.2.1 + + + + java + + + + + com.cloud.agent.AgentShell + + zone=1 + pod=1 + host=192.168.56.1 + name=192.168.56.10 + eth1ip=192.168.56.10 + eth2ip=192.168.56.10 + guid=SecondaryStorage.1 + secondary.storage.vm=false + instance=Secondary + + + + javax.net.ssl.trustStore + certs/realhostip.keystore + log.home + ${PWD}/ + + + + + + + diff --git a/services/secondary-storage/scripts/_run.sh b/services/secondary-storage/scripts/_run.sh new file mode 100755 index 00000000000..cb9624c58e6 --- /dev/null +++ b/services/secondary-storage/scripts/_run.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + + + + + +#run.sh runs the console proxy. + +# make sure we delete the old files from the original template +rm console-proxy.jar +rm console-common.jar +rm conf/cloud.properties + +set -x + +CP=./:./conf +for file in *.jar +do + CP=${CP}:$file +done +keyvalues= + +LOGHOME=/var/log/cloud/ +CMDLINE=$(cat /var/cache/cloud/cmdline) + +#CMDLINE="graphical utf8 eth0ip=0.0.0.0 eth0mask=255.255.255.0 eth1ip=192.168.140.40 eth1mask=255.255.255.0 eth2ip=172.24.0.50 eth2mask=255.255.0.0 gateway=172.24.0.1 dns1=72.52.126.11 template=domP dns2=72.52.126.12 host=192.168.1.142 port=8250 mgmtcidr=192.168.1.0/24 localgw=192.168.140.1 zone=5 pod=5" +for i in $CMDLINE + do + KEY=$(echo $i | cut -s -d= -f1) + VALUE=$(echo $i | cut -s -d= -f2) + [ "$KEY" == "" ] && continue + case $KEY in + *) + keyvalues="${keyvalues} $KEY=$VALUE" + esac + done + +tot_mem_k=$(cat /proc/meminfo | grep MemTotal | awk '{print $2}') +let "tot_mem_m=tot_mem_k>>10" +let "eightypcnt=$tot_mem_m*8/10" +let "maxmem=$tot_mem_m-80" + +if [ $maxmem -gt $eightypcnt ] +then + maxmem=$eightypcnt +fi + +java -Djavax.net.ssl.trustStore=./certs/realhostip.keystore -Dlog.home=$LOGHOME -mx${maxmem}m -cp $CP com.cloud.agent.AgentShell $keyvalues $@ diff --git a/services/secondary-storage/scripts/config_auth.sh b/services/secondary-storage/scripts/config_auth.sh new file mode 100755 index 00000000000..4b74f8eb995 --- /dev/null +++ b/services/secondary-storage/scripts/config_auth.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + + + + + + +BASE_DIR="/var/www/html/copy/template/" +HTACCESS="$BASE_DIR/.htaccess" + +PASSWDFILE="/etc/httpd/.htpasswd" +if [ -d /etc/apache2 ] +then + PASSWDFILE="/etc/apache2/.htpasswd" +fi + +config_htaccess() { + mkdir -p $BASE_DIR + result=$? + echo "Options -Indexes" > $HTACCESS + let "result=$result+$?" + echo "AuthType Basic" >> $HTACCESS + let "result=$result+$?" + echo "AuthName \"Authentication Required\"" >> $HTACCESS + let "result=$result+$?" + echo "AuthUserFile \"$PASSWDFILE\"" >> $HTACCESS + let "result=$result+$?" + echo "Require valid-user" >> $HTACCESS + let "result=$result+$?" + return $result +} + +write_passwd() { + local user=$1 + local passwd=$2 + htpasswd -bc $PASSWDFILE $user $passwd + return $? +} + +if [ $# -ne 2 ] ; then + echo $"Usage: `basename $0` username password " + exit 0 +fi + +write_passwd $1 $2 +if [ $? -ne 0 ] +then + echo "Failed to update password" + exit 2 +fi + +config_htaccess +exit $? diff --git a/services/secondary-storage/scripts/config_ssl.sh b/services/secondary-storage/scripts/config_ssl.sh new file mode 100755 index 00000000000..8d80c4731ad --- /dev/null +++ b/services/secondary-storage/scripts/config_ssl.sh @@ -0,0 +1,174 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + + + + +help() { + printf " -c use customized key/cert\n" + printf " -k path of private key\n" + printf " -p path of certificate of public key\n" + printf " -t path of certificate chain\n" +} + + +config_httpd_conf() { + local ip=$1 + local srvr=$2 + cp -f /etc/httpd/conf/httpd.conf.orig /etc/httpd/conf/httpd.conf + sed -i -e "s/Listen.*:80$/Listen $ip:80/" /etc/httpd/conf/httpd.conf + echo " " >> /etc/httpd/conf/httpd.conf + echo " DocumentRoot /var/www/html/" >> /etc/httpd/conf/httpd.conf + echo " ServerName $srvr" >> /etc/httpd/conf/httpd.conf + echo " SSLEngine on" >> /etc/httpd/conf/httpd.conf + echo " SSLCertificateFile /etc/httpd/ssl/certs/realhostip.crt" >> /etc/httpd/conf/httpd.conf + echo " SSLCertificateKeyFile /etc/httpd/ssl/keys/realhostip.key" >> /etc/httpd/conf/httpd.conf + echo "" >> /etc/httpd/conf/httpd.conf +} + +config_apache2_conf() { + local ip=$1 + local srvr=$2 + cp -f /etc/apache2/sites-available/default.orig /etc/apache2/sites-available/default + cp -f /etc/apache2/sites-available/default-ssl.orig /etc/apache2/sites-available/default-ssl + sed -i -e "s///" /etc/apache2/sites-available/default + sed -i -e "s///" /etc/apache2/sites-available/default-ssl + sed -i -e "s/Listen .*:80/Listen $ip:80/g" /etc/apache2/ports.conf + sed -i -e "s/Listen .*:443/Listen $ip:443/g" /etc/apache2/ports.conf + sed -i -e "s/NameVirtualHost .*:80/NameVirtualHost $ip:80/g" /etc/apache2/ports.conf + sed -i 's/ssl-cert-snakeoil.key/cert_apache.key/' /etc/apache2/sites-available/default-ssl + sed -i 's/ssl-cert-snakeoil.pem/cert_apache.crt/' /etc/apache2/sites-available/default-ssl +} + +copy_certs() { + local certdir=$(dirname $0)/certs + local mydir=$(dirname $0) + if [ -d $certdir ] && [ -f $customPrivKey ] && [ -f $customPrivCert ] ; then + mkdir -p /etc/httpd/ssl/keys && mkdir -p /etc/httpd/ssl/certs && cp $customprivKey /etc/httpd/ssl/keys && cp $customPrivCert /etc/httpd/ssl/certs + return $? + fi + if [ ! -z customCertChain ] && [ -f $customCertChain ] ; then + cp $customCertChain /etc/httpd/ssl/certs + fi + return 1 +} + +copy_certs_apache2() { + local certdir=$(dirname $0)/certs + local mydir=$(dirname $0) + if [ -f $customPrivKey ] && [ -f $customPrivCert ] ; then + cp $customPrivKey /etc/ssl/private/cert_apache.key && cp $customPrivCert /etc/ssl/certs/cert_apache.crt + fi + if [ ! -z "$customCertChain" ] && [ -f "$customCertChain" ] ; then + cp $customCertChain /etc/ssl/certs/cert_apache_chain.crt + fi + return 0 +} + + +cflag= +cpkflag= +cpcflag= +cccflag= +customPrivKey=$(dirname $0)/certs/realhostip.key +customPrivCert=$(dirname $0)/certs/realhostip.crt +customCertChain= +publicIp= +hostName= +while getopts 'i:h:k:p:t:c' OPTION +do + case $OPTION in + c) cflag=1 + ;; + k) cpkflag=1 + customPrivKey="$OPTARG" + ;; + p) cpcflag=1 + customPrivCert="$OPTARG" + ;; + t) cccflag=1 + customCertChain="$OPTARG" + ;; + i) publicIp="$OPTARG" + ;; + h) hostName="$OPTARG" + ;; + ?) help + ;; + esac +done + + +if [ -z "$publicIp" ] || [ -z "$hostName" ] +then + help + exit 1 +fi + +if [ "$cflag" == "1" ] +then + if [ "$cpkflag$cpcflag" != "11" ] + then + help + exit 1 + fi + if [ ! -f "$customPrivKey" ] + then + printf "priviate key file is not exist\n" + exit 2 + fi + + if [ ! -f "$customPrivCert" ] + then + printf "public certificate is not exist\n" + exit 3 + fi + + if [ "$cccflag" == "1" ] + then + if [ ! -f "$customCertChain" ] + then + printf "certificate chain is not exist\n" + exit 4 + fi + fi +fi + +if [ -d /etc/apache2 ] +then + copy_certs_apache2 +else + copy_certs +fi + +if [ $? -ne 0 ] +then + echo "Failed to copy certificates" + exit 2 +fi + +if [ -d /etc/apache2 ] +then + config_apache2_conf $publicIp $hostName + /etc/init.d/apache2 stop + /etc/init.d/apache2 start +else + config_httpd_conf $publicIp $hostName +fi + + diff --git a/services/secondary-storage/scripts/ipfirewall.sh b/services/secondary-storage/scripts/ipfirewall.sh new file mode 100755 index 00000000000..4711b8ac6db --- /dev/null +++ b/services/secondary-storage/scripts/ipfirewall.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +BASE_DIR="/var/www/html/copy/" +HTACCESS="$BASE_DIR/.htaccess" + +config_htaccess() { + mkdir -p $BASE_DIR + result=$? + echo "Options -Indexes" > $HTACCESS + let "result=$result+$?" + echo "order deny,allow" >> $HTACCESS + let "result=$result+$?" + echo "deny from all" >> $HTACCESS + let "result=$result+$?" + return $result +} + +ips(){ + echo "allow from $1" >> $HTACCESS + result=$? + return $result +} + +is_append="$1" +shift +if [ $is_append != "true" ]; then + config_htaccess +fi +for i in $@ +do + ips "$i" +done +exit $? + diff --git a/services/secondary-storage/scripts/run-proxy.sh b/services/secondary-storage/scripts/run-proxy.sh new file mode 100644 index 00000000000..d6ccf7c0091 --- /dev/null +++ b/services/secondary-storage/scripts/run-proxy.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + + + + + +#run.sh runs the console proxy. + +# make sure we delete the old files from the original template +rm console-proxy.jar +rm console-common.jar +rm conf/cloud.properties + +CP=./:./conf +for file in *.jar +do + CP=${CP}:$file +done + +#CMDLINE=$(cat /proc/cmdline) +#for i in $CMDLINE +# do +# KEY=$(echo $i | cut -d= -f1) +# VALUE=$(echo $i | cut -d= -f2) +# case $KEY in +# mgmt_host) +# MGMT_HOST=$VALUE +# ;; +# esac +# done + +java -mx700m -cp $CP:./conf com.cloud.consoleproxy.ConsoleProxy $@ diff --git a/services/secondary-storage/scripts/run.bat b/services/secondary-storage/scripts/run.bat new file mode 100644 index 00000000000..ce6dc404574 --- /dev/null +++ b/services/secondary-storage/scripts/run.bat @@ -0,0 +1,18 @@ +rem Licensed to the Apache Software Foundation (ASF) under one +rem or more contributor license agreements. See the NOTICE file +rem distributed with this work for additional information +rem regarding copyright ownership. The ASF licenses this file +rem to you under the Apache License, Version 2.0 (the +rem "License"); you may not use this file except in compliance +rem with the License. You may obtain a copy of the License at +rem +rem http://www.apache.org/licenses/LICENSE-2.0 +rem +rem Unless required by applicable law or agreed to in writing, +rem software distributed under the License is distributed on an +rem "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +rem KIND, either express or implied. See the License for the +rem specific language governing permissions and limitations +rem under the License. + +java -mx700m -cp cloud-console-proxy.jar;;cloud-console-common.jar;log4j-1.2.15.jar;apache-log4j-extras-1.0.jar;gson-1.3.jar;commons-logging-1.1.1.jar;.;.\conf; com.cloud.consoleproxy.ConsoleProxy %* diff --git a/services/secondary-storage/scripts/run.sh b/services/secondary-storage/scripts/run.sh new file mode 100755 index 00000000000..146d96f0287 --- /dev/null +++ b/services/secondary-storage/scripts/run.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + + + + + +#_run.sh runs the agent client. + +# set -x + +while true +do + ./_run.sh "$@" & + wait + ex=$? + if [ $ex -eq 0 ] || [ $ex -eq 1 ] || [ $ex -eq 66 ] || [ $ex -gt 128 ]; then + # permanent errors + sleep 5 + fi + + # user stop agent by service cloud stop + grep 'stop' /usr/local/cloud/systemvm/user_request &>/dev/null + if [ $? -eq 0 ]; then + timestamp=$(date) + echo "$timestamp User stops cloud.com service" >> /var/log/cloud.log + exit 0 + fi + sleep 5 +done diff --git a/services/secondary-storage/scripts/ssvm-check.sh b/services/secondary-storage/scripts/ssvm-check.sh new file mode 100644 index 00000000000..a4011647f07 --- /dev/null +++ b/services/secondary-storage/scripts/ssvm-check.sh @@ -0,0 +1,136 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + + +# Health check script for the Secondary Storage VM + +# DNS server is specified. + + +CMDLINE=/var/cache/cloud/cmdline +for i in `cat $CMDLINE` +do + key=`echo $i | cut -d= -f1` + value=`echo $i | cut -d= -f2` + case $key in + host) + MGMTSERVER=$value + ;; + esac +done + + +# ping dns server +echo ================================================ +DNSSERVER=`egrep '^nameserver' /etc/resolv.conf | awk '{print $2}'| head -1` +echo "First DNS server is " $DNSSERVER +ping -c 2 $DNSSERVER +if [ $? -eq 0 ] +then + echo "Good: Can ping DNS server" +else + echo "WARNING: cannot ping DNS server" + echo "route follows" + route -n +fi + + +# check dns resolve +echo ================================================ +nslookup download.cloud.com 1> /tmp/dns 2>&1 +grep 'no servers could' /tmp/dns 1> /dev/null 2>&1 +if [ $? -eq 0 ] +then + echo "ERROR: DNS not resolving download.cloud.com" + echo resolv.conf follows + cat /etc/resolv.conf + exit 2 +else + echo "Good: DNS resolves download.cloud.com" +fi + + +# check to see if we have the NFS volume mounted +echo ================================================ +mount|grep -v sunrpc|grep nfs 1> /dev/null 2>&1 +if [ $? -eq 0 ] +then + echo "NFS is currently mounted" + # check for write access + for MOUNTPT in `mount|grep -v sunrpc|grep nfs| awk '{print $3}'` + do + if [ $MOUNTPT != "/proc/xen" ] # mounted by xen + then + echo Mount point is $MOUNTPT + touch $MOUNTPT/foo + if [ $? -eq 0 ] + then + echo "Good: Can write to mount point" + rm $MOUNTPT/foo + else + echo "ERROR: Cannot write to mount point" + echo "You need to export with norootsquash" + fi + fi + done +else + echo "ERROR: NFS is not currently mounted" + echo "Try manually mounting from inside the VM" + NFSSERVER=`awk '{print $17}' $CMDLINE|awk -F= '{print $2}'|awk -F: '{print $1}'` + echo "NFS server is " $NFSSERVER + ping -c 2 $NFSSERVER + if [ $? -eq 0 ] + then + echo "Good: Can ping NFS server" + else + echo "WARNING: cannot ping NFS server" + echo routing table follows + route -n + fi +fi + + +# check for connectivity to the management server +echo ================================================ +echo Management server is $MGMTSERVER. Checking connectivity. +socatout=$(echo | socat - TCP:$MGMTSERVER:8250,connect-timeout=3 2>&1) +if [ $? -eq 0 ] +then + echo "Good: Can connect to management server port 8250" +else + echo "ERROR: Cannot connect to $MGMTSERVER port 8250" + echo $socatout + exit 4 +fi + + +# check for the java process running +echo ================================================ +ps -eaf|grep -v grep|grep java 1> /dev/null 2>&1 +if [ $? -eq 0 ] +then + echo "Good: Java process is running" +else + echo "ERROR: Java process not running. Try restarting the SSVM." + exit 3 +fi + +echo ================================================ +echo Tests Complete. Look for ERROR or WARNING above. + +exit 0 diff --git a/core/src/com/cloud/storage/resource/CifsSecondaryStorageResource.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/CifsSecondaryStorageResource.java similarity index 98% rename from core/src/com/cloud/storage/resource/CifsSecondaryStorageResource.java rename to services/secondary-storage/src/org/apache/cloudstack/storage/resource/CifsSecondaryStorageResource.java index 285005a1c3a..de4cfe0c97f 100755 --- a/core/src/com/cloud/storage/resource/CifsSecondaryStorageResource.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/CifsSecondaryStorageResource.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.storage.resource; +package org.apache.cloudstack.storage.resource; import java.io.File; import java.net.InetAddress; @@ -27,6 +27,10 @@ import java.util.Random; import javax.naming.ConfigurationException; +import org.apache.cloudstack.storage.template.DownloadManager; +import org.apache.cloudstack.storage.template.DownloadManagerImpl; +import org.apache.cloudstack.storage.template.UploadManager; +import org.apache.cloudstack.storage.template.UploadManagerImpl; import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; @@ -58,11 +62,7 @@ import com.cloud.resource.ServerResourceBase; import com.cloud.storage.Storage; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StorageLayer; -import com.cloud.storage.template.DownloadManager; -import com.cloud.storage.template.DownloadManagerImpl; import com.cloud.storage.template.TemplateInfo; -import com.cloud.storage.template.UploadManager; -import com.cloud.storage.template.UploadManagerImpl; import com.cloud.utils.NumbersUtil; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.exception.CloudRuntimeException; diff --git a/core/src/com/cloud/storage/resource/LocalSecondaryStorageResource.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/LocalSecondaryStorageResource.java similarity index 97% rename from core/src/com/cloud/storage/resource/LocalSecondaryStorageResource.java rename to services/secondary-storage/src/org/apache/cloudstack/storage/resource/LocalSecondaryStorageResource.java index c638c5d874e..b904254b944 100644 --- a/core/src/com/cloud/storage/resource/LocalSecondaryStorageResource.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/LocalSecondaryStorageResource.java @@ -14,13 +14,15 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.storage.resource; +package org.apache.cloudstack.storage.resource; import java.util.HashMap; import java.util.Map; import javax.naming.ConfigurationException; +import org.apache.cloudstack.storage.template.DownloadManager; +import org.apache.cloudstack.storage.template.DownloadManagerImpl; import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; @@ -46,8 +48,6 @@ import com.cloud.resource.ServerResourceBase; import com.cloud.storage.Storage; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StorageLayer; -import com.cloud.storage.template.DownloadManager; -import com.cloud.storage.template.DownloadManagerImpl; import com.cloud.storage.template.TemplateInfo; import com.cloud.utils.component.ComponentContext; diff --git a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java similarity index 95% rename from core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java rename to services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java index e65cbe1312e..1176d762f95 100755 --- a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.storage.resource; +package org.apache.cloudstack.storage.resource; import static com.cloud.utils.S3Utils.deleteDirectory; import static com.cloud.utils.S3Utils.getDirectory; @@ -46,6 +46,11 @@ import java.util.concurrent.Callable; import javax.naming.ConfigurationException; +import org.apache.cloudstack.storage.template.DownloadManager; +import org.apache.cloudstack.storage.template.DownloadManagerImpl; +import org.apache.cloudstack.storage.template.DownloadManagerImpl.ZfsPathParser; +import org.apache.cloudstack.storage.template.UploadManager; +import org.apache.cloudstack.storage.template.UploadManagerImpl; import org.apache.log4j.Logger; import com.cloud.agent.api.Answer; @@ -97,18 +102,12 @@ import com.cloud.host.Host; import com.cloud.host.Host.Type; import com.cloud.resource.ServerResourceBase; import com.cloud.storage.StorageLayer; -import com.cloud.storage.template.DownloadManager; -import com.cloud.storage.template.DownloadManagerImpl; -import com.cloud.storage.template.DownloadManagerImpl.ZfsPathParser; import com.cloud.storage.template.TemplateInfo; import com.cloud.storage.template.TemplateLocation; -import com.cloud.storage.template.UploadManager; -import com.cloud.storage.template.UploadManagerImpl; import com.cloud.utils.NumbersUtil; import com.cloud.utils.S3Utils; import com.cloud.utils.S3Utils.FileNamingStrategy; import com.cloud.utils.S3Utils.ObjectNamingStrategy; -import com.cloud.utils.component.ComponentContext; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.utils.script.OutputInterpreter; @@ -133,7 +132,7 @@ SecondaryStorageResource { String _role; Map _params; StorageLayer _storage; - boolean _inSystemVM = false; + protected boolean _inSystemVM = false; boolean _sslCopy = false; DownloadManager _dlMgr; @@ -150,7 +149,7 @@ SecondaryStorageResource { private String _storageNetmask; private String _storageGateway; private final List nfsIps = new ArrayList(); - final private String _parent = "/mnt/SecStorage"; + private String _parent = "/mnt/SecStorage"; final private String _tmpltDir = "/var/cloudstack/template"; final private String _tmpltpp = "template.properties"; @Override @@ -397,8 +396,8 @@ SecondaryStorageResource { @Override public boolean accept(final File directory, final String fileName) { - File fileToUpload = new File(directory.getAbsolutePath() + "/" + fileName); - return !fileName.startsWith(".") && !fileToUpload.isDirectory(); + File fileToUpload = new File(directory.getAbsolutePath() + "/" + fileName); + return !fileName.startsWith(".") && !fileToUpload.isDirectory(); } }, new ObjectNamingStrategy() { @Override @@ -1107,9 +1106,7 @@ SecondaryStorageResource { } private Answer execute(ListTemplateCommand cmd) { - if (!_inSystemVM){ - return new Answer(cmd, true, null); - } + if (cmd.getSwift() != null) { Map templateInfos = swiftListTemplate(cmd.getSwift()); return new ListTemplateAnswer(cmd.getSwift().toString(), templateInfos); @@ -1121,9 +1118,6 @@ SecondaryStorageResource { } private Answer execute(ListVolumeCommand cmd) { - if (!_inSystemVM){ - return new Answer(cmd, true, null); - } String root = getRootDir(cmd.getSecUrl()); Map templateInfos = _dlMgr.gatherVolumeInfo(root); @@ -1217,7 +1211,9 @@ SecondaryStorageResource { } public String allowOutgoingOnPrivate(String destCidr) { - + if (!_inSystemVM) { + return null; + } Script command = new Script("/bin/bash", s_logger); String intf = "eth1"; command.add("-c"); @@ -1392,6 +1388,9 @@ SecondaryStorageResource { synchronized public String getRootDir(String secUrl) { + if (!_inSystemVM) { + return _parent; + } try { URI uri = new URI(secUrl); String nfsHost = uri.getHost(); @@ -1465,7 +1464,7 @@ SecondaryStorageResource { if (_eth1ip != null) { //can only happen inside service vm params.put("private.network.device", "eth1"); } else { - s_logger.warn("Wait, what's going on? eth1ip is null!!"); + s_logger.warn("eth1ip parameter has not been configured, assuming that we are not inside a system vm"); } String eth2ip = (String) params.get("eth2ip"); if (eth2ip != null) { @@ -1474,9 +1473,14 @@ SecondaryStorageResource { _publicIp = (String) params.get("eth2ip"); _hostname = (String) params.get("name"); + String inSystemVM = (String) params.get("secondary.storage.vm"); + if (inSystemVM == null || "true".equalsIgnoreCase(inSystemVM)) { + _inSystemVM = true; + } + _storageIp = (String) params.get("storageip"); - if (_storageIp == null) { - s_logger.warn("Wait, there is no storageip in /proc/cmdline, something wrong!"); + if (_storageIp == null && _inSystemVM) { + s_logger.warn("There is no storageip in /proc/cmdline, something wrong!"); } _storageNetmask = (String) params.get("storagenetmask"); _storageGateway = (String) params.get("storagegateway"); @@ -1505,7 +1509,10 @@ SecondaryStorageResource { throw new ConfigurationException("Unable to find class " + value); } } - _storage.mkdirs(_parent); + + if (_inSystemVM) + _storage.mkdirs(_parent); + _configSslScr = Script.findScript(getDefaultScriptsDir(), "config_ssl.sh"); if (_configSslScr != null) { s_logger.info("config_ssl.sh found in " + _configSslScr); @@ -1539,10 +1546,12 @@ SecondaryStorageResource { _instance = (String)params.get("instance"); + if (!_inSystemVM) { + _parent = (String) params.get("mount.path"); + } - String inSystemVM = (String)params.get("secondary.storage.vm"); - if (inSystemVM == null || "true".equalsIgnoreCase(inSystemVM)) { - _inSystemVM = true; + + if (_inSystemVM) { _localgw = (String)params.get("localgw"); if (_localgw != null) { // can only happen inside service vm String mgmtHost = (String) params.get("host"); @@ -1581,6 +1590,9 @@ SecondaryStorageResource { } private void startAdditionalServices() { + if (!_inSystemVM) { + return; + } Script command = new Script("/bin/bash", s_logger); command.add("-c"); command.add("if [ -f /etc/init.d/ssh ]; then service ssh restart; else service sshd restart; fi "); @@ -1598,6 +1610,9 @@ SecondaryStorageResource { } private void addRouteToInternalIpOrCidr(String localgw, String eth1ip, String eth1mask, String destIpOrCidr) { + if (!_inSystemVM) { + return; + } s_logger.debug("addRouteToInternalIp: localgw=" + localgw + ", eth1ip=" + eth1ip + ", eth1mask=" + eth1mask + ",destIp=" + destIpOrCidr); if (destIpOrCidr == null) { s_logger.debug("addRouteToInternalIp: destIp is null"); @@ -1637,6 +1652,9 @@ SecondaryStorageResource { } private void configureSSL() { + if (!_inSystemVM) { + return; + } Script command = new Script(_configSslScr); command.add("-i", _publicIp); command.add("-h", _hostname); @@ -1647,6 +1665,9 @@ SecondaryStorageResource { } private void configureSSL(String prvkeyPath, String prvCertPath, String certChainPath) { + if (!_inSystemVM) { + return; + } Script command = new Script(_configSslScr); command.add("-i", _publicIp); command.add("-h", _hostname); @@ -1758,13 +1779,15 @@ SecondaryStorageResource { if(_publicIp != null) cmd.setPublicIpAddress(_publicIp); - Script command = new Script("/bin/bash", s_logger); - command.add("-c"); - command.add("ln -sf " + _parent + " /var/www/html/copy"); - String result = command.execute(); - if (result != null) { - s_logger.warn("Error in linking err=" + result); - return null; + if (_inSystemVM) { + Script command = new Script("/bin/bash", s_logger); + command.add("-c"); + command.add("ln -sf " + _parent + " /var/www/html/copy"); + String result = command.execute(); + if (result != null) { + s_logger.warn("Error in linking err=" + result); + return null; + } } return new StartupCommand[] {cmd}; } @@ -1810,33 +1833,50 @@ SecondaryStorageResource { return "./scripts/storage/secondary"; } - @Override - public void setName(String name) { - // TODO Auto-generated method stub - - } + @Override + public void setName(String name) { + // TODO Auto-generated method stub - @Override - public void setConfigParams(Map params) { - // TODO Auto-generated method stub - - } + } - @Override - public Map getConfigParams() { - // TODO Auto-generated method stub - return null; - } + @Override + public void setConfigParams(Map params) { + // TODO Auto-generated method stub - @Override - public int getRunLevel() { - // TODO Auto-generated method stub - return 0; - } + } - @Override - public void setRunLevel(int level) { - // TODO Auto-generated method stub - - } + @Override + public Map getConfigParams() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getRunLevel() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void setRunLevel(int level) { + // TODO Auto-generated method stub + + } + + @Override + public void fillNetworkInformation(final StartupCommand cmd) { + final String dummyMac = "00:06:0A:0B:0C:0D"; + final String dummyNetmask = "255.255.255.0"; + if (!_inSystemVM) { + cmd.setPrivateIpAddress(_eth1ip); + cmd.setPrivateMacAddress(dummyMac); + cmd.setPrivateNetmask(dummyNetmask); + cmd.setPublicIpAddress(_publicIp); + cmd.setPublicMacAddress(dummyMac); + cmd.setPublicNetmask(dummyNetmask); + cmd.setName(_hostname); + } else { + super.fillNetworkInformation(cmd); + } + } } diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageDiscoverer.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageDiscoverer.java similarity index 98% rename from server/src/com/cloud/storage/secondary/SecondaryStorageDiscoverer.java rename to services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageDiscoverer.java index 3ca74a351e8..d3af792faa5 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageDiscoverer.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageDiscoverer.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.storage.secondary; +package org.apache.cloudstack.storage.resource; import java.io.File; import java.lang.reflect.Constructor; @@ -47,8 +47,6 @@ import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplateHostDao; import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.resource.DummySecondaryStorageResource; -import com.cloud.storage.resource.LocalSecondaryStorageResource; -import com.cloud.storage.resource.NfsSecondaryStorageResource; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.net.NfsUtils; import com.cloud.utils.script.Script; diff --git a/core/src/com/cloud/storage/resource/SecondaryStorageResource.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageResource.java similarity index 95% rename from core/src/com/cloud/storage/resource/SecondaryStorageResource.java rename to services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageResource.java index 37c6686afd8..5c87b0dcc92 100755 --- a/core/src/com/cloud/storage/resource/SecondaryStorageResource.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageResource.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.storage.resource; +package org.apache.cloudstack.storage.resource; import com.cloud.agent.api.storage.ssCommand; import com.cloud.resource.ServerResource; /** diff --git a/core/src/com/cloud/storage/resource/SecondaryStorageResourceHandler.java b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageResourceHandler.java similarity index 95% rename from core/src/com/cloud/storage/resource/SecondaryStorageResourceHandler.java rename to services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageResourceHandler.java index 28b96b621ed..d03d983dcd8 100644 --- a/core/src/com/cloud/storage/resource/SecondaryStorageResourceHandler.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/resource/SecondaryStorageResourceHandler.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.storage.resource; +package org.apache.cloudstack.storage.resource; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; diff --git a/core/src/com/cloud/storage/template/DownloadManager.java b/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManager.java similarity index 94% rename from core/src/com/cloud/storage/template/DownloadManager.java rename to services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManager.java index f4f8a0f17fa..3e5072abfa3 100644 --- a/core/src/com/cloud/storage/template/DownloadManager.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManager.java @@ -14,18 +14,20 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.storage.template; +package org.apache.cloudstack.storage.template; -import java.util.List; import java.util.Map; +import org.apache.cloudstack.storage.resource.SecondaryStorageResource; + import com.cloud.agent.api.storage.DownloadAnswer; import com.cloud.agent.api.storage.DownloadCommand; import com.cloud.agent.api.storage.DownloadCommand.Proxy; import com.cloud.agent.api.storage.DownloadCommand.ResourceType; -import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.Storage.ImageFormat; -import com.cloud.storage.resource.SecondaryStorageResource; +import com.cloud.storage.VMTemplateHostVO; +import com.cloud.storage.template.TemplateDownloader; +import com.cloud.storage.template.TemplateInfo; import com.cloud.utils.component.Manager; public interface DownloadManager extends Manager { diff --git a/core/src/com/cloud/storage/template/DownloadManagerImpl.java b/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java similarity index 95% rename from core/src/com/cloud/storage/template/DownloadManagerImpl.java rename to services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java index 22e78a081c1..a9d23cb7779 100755 --- a/core/src/com/cloud/storage/template/DownloadManagerImpl.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/template/DownloadManagerImpl.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.storage.template; +package org.apache.cloudstack.storage.template; import java.io.BufferedReader; import java.io.File; @@ -41,6 +41,7 @@ import java.util.concurrent.Executors; import javax.ejb.Local; import javax.naming.ConfigurationException; +import org.apache.cloudstack.storage.resource.SecondaryStorageResource; import org.apache.log4j.Logger; import com.cloud.agent.api.storage.DownloadAnswer; @@ -54,10 +55,22 @@ import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageLayer; import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.VMTemplateStorageResourceAssoc; -import com.cloud.storage.resource.SecondaryStorageResource; +import com.cloud.storage.template.HttpTemplateDownloader; +import com.cloud.storage.template.IsoProcessor; +import com.cloud.storage.template.LocalTemplateDownloader; +import com.cloud.storage.template.Processor; import com.cloud.storage.template.Processor.FormatInfo; +import com.cloud.storage.template.QCOW2Processor; +import com.cloud.storage.template.RawImageProcessor; +import com.cloud.storage.template.ScpTemplateDownloader; +import com.cloud.storage.template.TemplateConstants; +import com.cloud.storage.template.TemplateDownloader; import com.cloud.storage.template.TemplateDownloader.DownloadCompleteCallback; import com.cloud.storage.template.TemplateDownloader.Status; +import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateLocation; +import com.cloud.storage.template.VhdProcessor; +import com.cloud.storage.template.VmdkProcessor; import com.cloud.utils.NumbersUtil; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.exception.CloudRuntimeException; @@ -743,21 +756,27 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager TemplateInfo tInfo = loc.getTemplateInfo(); - if ((tInfo.size == tInfo.physicalSize) && (tInfo.installPath.endsWith(ImageFormat.OVA.getFileExtension()))) { + if ((tInfo.getSize() == tInfo.getPhysicalSize()) + && (tInfo.getInstallPath().endsWith(ImageFormat.OVA.getFileExtension()))) { try { Processor processor = _processors.get("VMDK Processor"); VmdkProcessor vmdkProcessor = (VmdkProcessor)processor; - long vSize = vmdkProcessor.getTemplateVirtualSize(path, tInfo.installPath.substring(tInfo.installPath.lastIndexOf(File.separator) + 1)); - tInfo.size = vSize; + long vSize = + vmdkProcessor.getTemplateVirtualSize( + path, + tInfo.getInstallPath().substring( + tInfo.getInstallPath().lastIndexOf(File.separator) + 1)); + tInfo.setSize(vSize); loc.updateVirtualSize(vSize); loc.save(); } catch (Exception e) { - s_logger.error("Unable to get the virtual size of the template: " + tInfo.installPath + " due to " + e.getMessage()); + s_logger.error("Unable to get the virtual size of the template: " + tInfo.getInstallPath() + + " due to " + e.getMessage()); } } - result.put(tInfo.templateName, tInfo); - s_logger.debug("Added template name: " + tInfo.templateName + ", path: " + tmplt); + result.put(tInfo.getTemplateName(), tInfo); + s_logger.debug("Added template name: " + tInfo.getTemplateName() + ", path: " + tmplt); } /* for (String tmplt : isoTmplts) { @@ -800,21 +819,27 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager TemplateInfo vInfo = loc.getTemplateInfo(); - if ((vInfo.size == vInfo.physicalSize) && (vInfo.installPath.endsWith(ImageFormat.OVA.getFileExtension()))) { + if ((vInfo.getSize() == vInfo.getPhysicalSize()) + && (vInfo.getInstallPath().endsWith(ImageFormat.OVA.getFileExtension()))) { try { Processor processor = _processors.get("VMDK Processor"); VmdkProcessor vmdkProcessor = (VmdkProcessor)processor; - long vSize = vmdkProcessor.getTemplateVirtualSize(path, vInfo.installPath.substring(vInfo.installPath.lastIndexOf(File.separator) + 1)); - vInfo.size = vSize; + long vSize = + vmdkProcessor.getTemplateVirtualSize( + path, + vInfo.getInstallPath().substring( + vInfo.getInstallPath().lastIndexOf(File.separator) + 1)); + vInfo.setSize(vSize); loc.updateVirtualSize(vSize); loc.save(); } catch (Exception e) { - s_logger.error("Unable to get the virtual size of the volume: " + vInfo.installPath + " due to " + e.getMessage()); + s_logger.error("Unable to get the virtual size of the volume: " + vInfo.getInstallPath() + + " due to " + e.getMessage()); } } result.put(vInfo.getId(), vInfo); - s_logger.debug("Added volume name: " + vInfo.templateName + ", path: " + vol); + s_logger.debug("Added volume name: " + vInfo.getTemplateName() + ", path: " + vol); } return result; } diff --git a/core/src/com/cloud/storage/template/UploadManager.java b/services/secondary-storage/src/org/apache/cloudstack/storage/template/UploadManager.java similarity index 94% rename from core/src/com/cloud/storage/template/UploadManager.java rename to services/secondary-storage/src/org/apache/cloudstack/storage/template/UploadManager.java index fa40b8c9ac6..14de1500104 100755 --- a/core/src/com/cloud/storage/template/UploadManager.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/template/UploadManager.java @@ -14,7 +14,9 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.storage.template; +package org.apache.cloudstack.storage.template; + +import org.apache.cloudstack.storage.resource.SecondaryStorageResource; import com.cloud.agent.api.storage.CreateEntityDownloadURLAnswer; import com.cloud.agent.api.storage.CreateEntityDownloadURLCommand; @@ -24,7 +26,7 @@ import com.cloud.agent.api.storage.UploadAnswer; import com.cloud.agent.api.storage.UploadCommand; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Upload.Status; -import com.cloud.storage.resource.SecondaryStorageResource; +import com.cloud.storage.template.TemplateUploader; import com.cloud.utils.component.Manager; public interface UploadManager extends Manager { diff --git a/core/src/com/cloud/storage/template/UploadManagerImpl.java b/services/secondary-storage/src/org/apache/cloudstack/storage/template/UploadManagerImpl.java similarity index 98% rename from core/src/com/cloud/storage/template/UploadManagerImpl.java rename to services/secondary-storage/src/org/apache/cloudstack/storage/template/UploadManagerImpl.java index 2492a1be2b2..88623a9e0fb 100755 --- a/core/src/com/cloud/storage/template/UploadManagerImpl.java +++ b/services/secondary-storage/src/org/apache/cloudstack/storage/template/UploadManagerImpl.java @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -package com.cloud.storage.template; +package org.apache.cloudstack.storage.template; import java.io.File; import java.net.URI; @@ -30,6 +30,7 @@ import java.util.concurrent.Executors; import javax.naming.ConfigurationException; +import org.apache.cloudstack.storage.resource.SecondaryStorageResource; import org.apache.log4j.Logger; import com.cloud.agent.api.storage.CreateEntityDownloadURLAnswer; @@ -43,7 +44,9 @@ import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageLayer; import com.cloud.storage.Upload; import com.cloud.storage.UploadVO; -import com.cloud.storage.resource.SecondaryStorageResource; +import com.cloud.storage.template.FtpTemplateUploader; +import com.cloud.storage.template.Processor; +import com.cloud.storage.template.TemplateUploader; import com.cloud.storage.template.TemplateUploader.Status; import com.cloud.storage.template.TemplateUploader.UploadCompleteCallback; import com.cloud.utils.NumbersUtil; diff --git a/setup/db/db/schema-40to410.sql b/setup/db/db/schema-40to410.sql index fc15b94493e..e2949d93e61 100644 --- a/setup/db/db/schema-40to410.sql +++ b/setup/db/db/schema-40to410.sql @@ -404,35 +404,6 @@ INSERT INTO `cloud`.`counter` (id, uuid, source, name, value,created) VALUES (1, INSERT INTO `cloud`.`counter` (id, uuid, source, name, value,created) VALUES (2, UUID(), 'snmp','Linux System CPU - percentage', '1.3.6.1.4.1.2021.11.10.0', now()); INSERT INTO `cloud`.`counter` (id, uuid, source, name, value,created) VALUES (3, UUID(), 'snmp','Linux CPU Idle - percentage', '1.3.6.1.4.1.2021.11.11.0', now()); INSERT INTO `cloud`.`counter` (id, uuid, source, name, value,created) VALUES (100, UUID(), 'netscaler','Response Time - microseconds', 'RESPTIME', now()); -CREATE TABLE `cloud`.`vm_snapshots` ( - `id` bigint(20) unsigned NOT NULL auto_increment COMMENT 'Primary Key', - `uuid` varchar(40) NOT NULL, - `name` varchar(255) NOT NULL, - `display_name` varchar(255) default NULL, - `description` varchar(255) default NULL, - `vm_id` bigint(20) unsigned NOT NULL, - `account_id` bigint(20) unsigned NOT NULL, - `domain_id` bigint(20) unsigned NOT NULL, - `vm_snapshot_type` varchar(32) default NULL, - `state` varchar(32) NOT NULL, - `parent` bigint unsigned default NULL, - `current` int(1) unsigned default NULL, - `update_count` bigint unsigned NOT NULL DEFAULT 0, - `updated` datetime default NULL, - `created` datetime default NULL, - `removed` datetime default NULL, - PRIMARY KEY (`id`), - CONSTRAINT UNIQUE KEY `uc_vm_snapshots_uuid` (`uuid`), - INDEX `vm_snapshots_name` (`name`), - INDEX `vm_snapshots_vm_id` (`vm_id`), - INDEX `vm_snapshots_account_id` (`account_id`), - INDEX `vm_snapshots_display_name` (`display_name`), - INDEX `vm_snapshots_removed` (`removed`), - INDEX `vm_snapshots_parent` (`parent`), - CONSTRAINT `fk_vm_snapshots_vm_id__vm_instance_id` FOREIGN KEY `fk_vm_snapshots_vm_id__vm_instance_id` (`vm_id`) REFERENCES `vm_instance` (`id`), - CONSTRAINT `fk_vm_snapshots_account_id__account_id` FOREIGN KEY `fk_vm_snapshots_account_id__account_id` (`account_id`) REFERENCES `account` (`id`), - CONSTRAINT `fk_vm_snapshots_domain_id__domain_id` FOREIGN KEY `fk_vm_snapshots_domain_id__domain_id` (`domain_id`) REFERENCES `domain` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `cloud`.`user_ipv6_address` ( `id` bigint unsigned NOT NULL UNIQUE auto_increment, diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index ab9df05103b..c7c8b5b49ca 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -124,6 +124,15 @@ INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Windows 8 (64 bit)', 209); INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Windows 8 Server (64 bit)', 210); +INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (211, UUID(), 7, 'Apple Mac OS X 10.6 (32 bits)'); +INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (212, UUID(), 7, 'Apple Mac OS X 10.6 (64 bits)'); +INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (213, UUID(), 7, 'Apple Mac OS X 10.7 (32 bits)'); +INSERT INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (214, UUID(), 7, 'Apple Mac OS X 10.7 (64 bits)'); +INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Apple Mac OS X 10.6 (32 bits)', 211); +INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Apple Mac OS X 10.6 (64 bits)', 212); +INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Apple Mac OS X 10.7 (32 bits)', 213); +INSERT INTO `cloud`.`guest_os_hypervisor` (hypervisor_type, guest_os_name, guest_os_id) VALUES ("VmWare", 'Apple Mac OS X 10.7 (64 bits)', 214); + CREATE TABLE `cloud`.`user_vm_clone_setting` ( `vm_id` bigint unsigned NOT NULL COMMENT 'guest VM id', `clone_type` varchar(10) NOT NULL COMMENT 'Full or Linked Clone (applicable to VMs on ESX)', @@ -405,3 +414,37 @@ INSERT INTO `cloud`.`vm_template` (id, unique_name, name, public, created, type, VALUES (10, 'routing-10', 'SystemVM Template (LXC)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2', '2755de1f9ef2ce4d6f2bee2efbb4da92', 0, 'SystemVM Template (LXC)', 'QCOW2', 15, 0, 1, 'LXC'); -- END: support for LXC + +CREATE TABLE `cloud`.`vm_snapshots` ( + `id` bigint(20) unsigned NOT NULL auto_increment COMMENT 'Primary Key', + `uuid` varchar(40) NOT NULL, + `name` varchar(255) NOT NULL, + `display_name` varchar(255) default NULL, + `description` varchar(255) default NULL, + `vm_id` bigint(20) unsigned NOT NULL, + `account_id` bigint(20) unsigned NOT NULL, + `domain_id` bigint(20) unsigned NOT NULL, + `vm_snapshot_type` varchar(32) default NULL, + `state` varchar(32) NOT NULL, + `parent` bigint unsigned default NULL, + `current` int(1) unsigned default NULL, + `update_count` bigint unsigned NOT NULL DEFAULT 0, + `updated` datetime default NULL, + `created` datetime default NULL, + `removed` datetime default NULL, + PRIMARY KEY (`id`), + CONSTRAINT UNIQUE KEY `uc_vm_snapshots_uuid` (`uuid`), + INDEX `vm_snapshots_name` (`name`), + INDEX `vm_snapshots_vm_id` (`vm_id`), + INDEX `vm_snapshots_account_id` (`account_id`), + INDEX `vm_snapshots_display_name` (`display_name`), + INDEX `vm_snapshots_removed` (`removed`), + INDEX `vm_snapshots_parent` (`parent`), + CONSTRAINT `fk_vm_snapshots_vm_id__vm_instance_id` FOREIGN KEY `fk_vm_snapshots_vm_id__vm_instance_id` (`vm_id`) REFERENCES `vm_instance` (`id`), + CONSTRAINT `fk_vm_snapshots_account_id__account_id` FOREIGN KEY `fk_vm_snapshots_account_id__account_id` (`account_id`) REFERENCES `account` (`id`), + CONSTRAINT `fk_vm_snapshots_domain_id__domain_id` FOREIGN KEY `fk_vm_snapshots_domain_id__domain_id` (`domain_id`) REFERENCES `domain` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +ALTER TABLE `cloud`.`hypervisor_capabilities` ADD COLUMN `vm_snapshot_enabled` tinyint(1) DEFAULT 0 NOT NULL COMMENT 'Whether VM snapshot is supported by hypervisor'; +UPDATE `cloud`.`hypervisor_capabilities` SET `vm_snapshot_enabled`=1 WHERE `hypervisor_type` in ('VMware', 'XenServer'); + diff --git a/setup/dev/basic.cfg b/setup/dev/basic.cfg index fb99b8b5498..3f56a3ce980 100644 --- a/setup/dev/basic.cfg +++ b/setup/dev/basic.cfg @@ -57,7 +57,7 @@ "startip": "60.147.41.2", "endip": "60.147.41.254", "netmask": "255.255.255.0", - "gateway": "60.147.40.1" + "gateway": "60.147.41.1" } ], "netmask": "255.255.255.0", @@ -102,11 +102,11 @@ "logger": [ { "name": "TestClient", - "file": "/var/log/testclient.log" + "file": "/tmp/testclient.log" }, { "name": "TestCase", - "file": "/var/log/testcase.log" + "file": "/tmp/testcase.log" } ], "globalConfig": [ diff --git a/setup/dev/local.cfg b/setup/dev/local.cfg new file mode 100644 index 00000000000..ce956a54e63 --- /dev/null +++ b/setup/dev/local.cfg @@ -0,0 +1,44 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +{ + "dbSvr": { + "dbSvr": "localhost", + "passwd": "cloud", + "db": "cloud", + "port": 3306, + "user": "cloud" + }, + "logger": [ + { + "name": "TestClient", + "file": "/tmp/testclient.log" + }, + { + "name": "TestCase", + "file": "/tmp/testcase.log" + } + ], + "mgtSvr": [ + { + "mgtSvrIp": "localhost", + "passwd": "password", + "user": "root", + "port": 8096 + } + ] +} diff --git a/tools/appliance/build.sh b/tools/appliance/build.sh index f1ee4a64b40..c39d38a4e76 100644 --- a/tools/appliance/build.sh +++ b/tools/appliance/build.sh @@ -81,7 +81,10 @@ rm raw.img bzip2 $appliance-$build_date-$branch-kvm.qcow2 echo "$appliance exported for KVM: dist/$appliance-$build_date-$branch-kvm.qcow2.bz2" -# Export for VMWare vSphere +# Export both ova and vmdk for VMWare +vboxmanage clonehd $hdd_uuid $appliance-$build_date-$branch-vmware.vmdk --format VMDK +bzip2 $appliance-$build_date-$branch-vmware.vmdk +echo "$appliance exported for VMWare: dist/$appliance-$build_date-$branch-vmware.vmdk.bz2" vboxmanage export $machine_uuid --output $appliance-$build_date-$branch-vmware.ova echo "$appliance exported for VMWare: dist/$appliance-$build_date-$branch-vmware.ova" diff --git a/tools/appliance/definitions/systemvmtemplate/postinstall.sh b/tools/appliance/definitions/systemvmtemplate/postinstall.sh index 5d529de038a..ae8f1adfb9c 100644 --- a/tools/appliance/definitions/systemvmtemplate/postinstall.sh +++ b/tools/appliance/definitions/systemvmtemplate/postinstall.sh @@ -50,8 +50,6 @@ install_packages() { echo "openswan openswan/install_x509_certificate seen true" | debconf-set-selections apt-get --no-install-recommends -q -y --force-yes install openswan - # vmware tools - apt-get --no-install-recommends -q -y --force-yes install open-vm-tools # xenstore utils apt-get --no-install-recommends -q -y --force-yes install xenstore-utils libxenstore3.0 # keepalived and conntrackd for redundant router @@ -64,6 +62,22 @@ install_packages() { echo "iptables-persistent iptables-persistent/autosave_v4 boolean true" | debconf-set-selections echo "iptables-persistent iptables-persistent/autosave_v6 boolean true" | debconf-set-selections apt-get --no-install-recommends -q -y --force-yes install iptables-persistent + + # vmware tools + apt-get --no-install-recommends -q -y --force-yes install open-vm-tools + # commented installaion of vmware-tools as we are using the opensource open-vm-tools: + # apt-get --no-install-recommends -q -y --force-yes install build-essential linux-headers-`uname -r` + # df -h + # PREVDIR=$PWD + # cd /opt + # wget http://people.apache.org/~bhaisaab/cloudstack/VMwareTools-9.2.1-818201.tar.gz + # tar xzf VMwareTools-9.2.1-818201.tar.gz + # rm VMwareTools-*.tar.gz + # cd vmware-tools-distrib + # ./vmware-install.pl -d + # cd $PREV + # rm -fr /opt/vmware-tools-distrib + # apt-get -q -y --force-yes purge build-essential } setup_accounts() { @@ -171,7 +185,7 @@ configure_services() { snapshot_url="https://git-wip-us.apache.org/repos/asf?p=cloudstack.git;a=snapshot;h=HEAD;sf=tgz" snapshot_dir="/opt/cloudstack*" cd /opt - wget $snapshot_url -O cloudstack.tar.gz + wget --no-check-certificate $snapshot_url -O cloudstack.tar.gz tar -zxvf cloudstack.tar.gz cp -rv $snapshot_dir/patches/systemvm/debian/config/* / cp -rv $snapshot_dir/patches/systemvm/debian/vpn/* / diff --git a/tools/appliance/definitions/systemvmtemplate/preseed.cfg b/tools/appliance/definitions/systemvmtemplate/preseed.cfg index ac9edd31213..6996565aaae 100644 --- a/tools/appliance/definitions/systemvmtemplate/preseed.cfg +++ b/tools/appliance/definitions/systemvmtemplate/preseed.cfg @@ -130,23 +130,23 @@ d-i partman-auto/choose_recipe select atomic d-i partman-auto/expert_recipe string \ boot-root :: \ - 40 50 100 ext4 \ + 30 50 100 ext4 \ $primary{ } $bootable{ } \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /boot } \ . \ - 400 40 500 ext4 \ + 300 40 400 ext4 \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ / } \ . \ - 60 100 200 ext4 \ + 50 100 200 ext4 \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /home } \ . \ - 500 30 1000 ext4 \ + 650 20 1100 ext4 \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /usr } \ @@ -156,17 +156,17 @@ d-i partman-auto/expert_recipe string \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /opt } \ . \ - 500 60 1000 ext4 \ + 450 60 1000 ext4 \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /var } \ . \ - 100 70 400 ext4 \ + 50 70 400 ext4 \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /tmp } \ . \ - 64 512 300% linux-swap \ + 70 512 300% linux-swap \ method{ swap } format{ } \ . diff --git a/tools/appliance/definitions/systemvmtemplate64/postinstall.sh b/tools/appliance/definitions/systemvmtemplate64/postinstall.sh index 5d529de038a..ae8f1adfb9c 100644 --- a/tools/appliance/definitions/systemvmtemplate64/postinstall.sh +++ b/tools/appliance/definitions/systemvmtemplate64/postinstall.sh @@ -50,8 +50,6 @@ install_packages() { echo "openswan openswan/install_x509_certificate seen true" | debconf-set-selections apt-get --no-install-recommends -q -y --force-yes install openswan - # vmware tools - apt-get --no-install-recommends -q -y --force-yes install open-vm-tools # xenstore utils apt-get --no-install-recommends -q -y --force-yes install xenstore-utils libxenstore3.0 # keepalived and conntrackd for redundant router @@ -64,6 +62,22 @@ install_packages() { echo "iptables-persistent iptables-persistent/autosave_v4 boolean true" | debconf-set-selections echo "iptables-persistent iptables-persistent/autosave_v6 boolean true" | debconf-set-selections apt-get --no-install-recommends -q -y --force-yes install iptables-persistent + + # vmware tools + apt-get --no-install-recommends -q -y --force-yes install open-vm-tools + # commented installaion of vmware-tools as we are using the opensource open-vm-tools: + # apt-get --no-install-recommends -q -y --force-yes install build-essential linux-headers-`uname -r` + # df -h + # PREVDIR=$PWD + # cd /opt + # wget http://people.apache.org/~bhaisaab/cloudstack/VMwareTools-9.2.1-818201.tar.gz + # tar xzf VMwareTools-9.2.1-818201.tar.gz + # rm VMwareTools-*.tar.gz + # cd vmware-tools-distrib + # ./vmware-install.pl -d + # cd $PREV + # rm -fr /opt/vmware-tools-distrib + # apt-get -q -y --force-yes purge build-essential } setup_accounts() { @@ -171,7 +185,7 @@ configure_services() { snapshot_url="https://git-wip-us.apache.org/repos/asf?p=cloudstack.git;a=snapshot;h=HEAD;sf=tgz" snapshot_dir="/opt/cloudstack*" cd /opt - wget $snapshot_url -O cloudstack.tar.gz + wget --no-check-certificate $snapshot_url -O cloudstack.tar.gz tar -zxvf cloudstack.tar.gz cp -rv $snapshot_dir/patches/systemvm/debian/config/* / cp -rv $snapshot_dir/patches/systemvm/debian/vpn/* / diff --git a/tools/appliance/definitions/systemvmtemplate64/preseed.cfg b/tools/appliance/definitions/systemvmtemplate64/preseed.cfg index ac9edd31213..6996565aaae 100644 --- a/tools/appliance/definitions/systemvmtemplate64/preseed.cfg +++ b/tools/appliance/definitions/systemvmtemplate64/preseed.cfg @@ -130,23 +130,23 @@ d-i partman-auto/choose_recipe select atomic d-i partman-auto/expert_recipe string \ boot-root :: \ - 40 50 100 ext4 \ + 30 50 100 ext4 \ $primary{ } $bootable{ } \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /boot } \ . \ - 400 40 500 ext4 \ + 300 40 400 ext4 \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ / } \ . \ - 60 100 200 ext4 \ + 50 100 200 ext4 \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /home } \ . \ - 500 30 1000 ext4 \ + 650 20 1100 ext4 \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /usr } \ @@ -156,17 +156,17 @@ d-i partman-auto/expert_recipe string \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /opt } \ . \ - 500 60 1000 ext4 \ + 450 60 1000 ext4 \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /var } \ . \ - 100 70 400 ext4 \ + 50 70 400 ext4 \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /tmp } \ . \ - 64 512 300% linux-swap \ + 70 512 300% linux-swap \ method{ swap } format{ } \ . diff --git a/tools/devcloud/devcloud.cfg b/tools/devcloud/devcloud.cfg index c41f8bcef58..e6ab71b5ebf 100644 --- a/tools/devcloud/devcloud.cfg +++ b/tools/devcloud/devcloud.cfg @@ -20,6 +20,7 @@ "zones": [ { "name": "DevCloud0", + "enabled" : "True", "physical_networks": [ { "broadcastdomainrange": "Zone", diff --git a/tools/devcloud/pom.xml b/tools/devcloud/pom.xml index d7b82c9d7fe..ba4cc464ccc 100644 --- a/tools/devcloud/pom.xml +++ b/tools/devcloud/pom.xml @@ -142,5 +142,38 @@ + + quickcloud + + + deployquick + + + + + + org.codehaus.mojo + exec-maven-plugin + 1.2.1 + + + integration-test + + exec + + + + + python + + ../marvin/marvin/deployDataCenter.py + -i + quickcloud.cfg + + + + + + diff --git a/tools/devcloud/quickcloud.cfg b/tools/devcloud/quickcloud.cfg new file mode 100644 index 00000000000..a2613d22bdb --- /dev/null +++ b/tools/devcloud/quickcloud.cfg @@ -0,0 +1,121 @@ +# 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. +# + +{ + "zones": [ + { + "name": "QuickCloud00", + "enabled" : "True", + "details" : [ + {"key" : "enable.secstorage.vm", "value": "False"}, + {"key" : "enable.consoleproxy.vm", "value": "False"} + ], + "physical_networks": [ + { + "broadcastdomainrange": "Zone", + "name": "test-network", + "traffictypes": [ + { + "typ": "Guest" + }, + { + "typ": "Management" + } + ], + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "VirtualRouter" + }, + { + "broadcastdomainrange": "Pod", + "name": "SecurityGroupProvider" + } + ] + } + ], + "dns2": "4.4.4.4", + "dns1": "8.8.8.8", + "securitygroupenabled": "true", + "localstorageenabled": "true", + "networktype": "Basic", + "networkofferingname": "QuickCloudNoServices", + "pods": [ + { + "endip": "192.168.56.220", + "name": "test00", + "startip": "192.168.56.200", + "guestIpRanges": [ + { + "startip": "192.168.56.100", + "endip": "192.168.56.199", + "netmask": "255.255.255.0", + "gateway": "192.168.56.1" + } + ], + "netmask": "255.255.255.0", + "clusters": [ + { + "clustername": "test000", + "hypervisor": "XenServer", + "hosts": [ + { + "username": "root", + "url": "http://192.168.56.10/", + "password": "password" + } + ], + "clustertype": "CloudManaged" + } + ], + "gateway": "192.168.56.1" + } + ], + "internaldns1": "192.168.56.1", + "secondaryStorages": [ + { + "url": "nfs://192.168.56.10:/opt/storage/secondary" + } + ] + } + ], + "logger": [ + { + "name": "TestClient", + "file": "testclient.log" + }, + { + "name": "TestCase", + "file": "testcase.log" + } + ], + "mgtSvr": [ + { + "mgtSvrIp": "127.0.0.1", + "port": 8096 + } + ], + "dbSvr": + { + "dbSvr": "127.0.0.1", + "port": 3306, + "user": "cloud", + "passwd": "cloud", + "db": "cloud" + } +} diff --git a/tools/marvin/marvin/cloudstackConnection.py b/tools/marvin/marvin/cloudstackConnection.py index e8b861eedb2..1caeef35ff2 100644 --- a/tools/marvin/marvin/cloudstackConnection.py +++ b/tools/marvin/marvin/cloudstackConnection.py @@ -162,9 +162,9 @@ class cloudConnection(object): else: requests.pop(param) i = 0 - for v in value: - for key, val in v.iteritems(): - requests["%s[%d].%s"%(param,i,key)] = val + for val in value: + for k,v in val.iteritems(): + requests["%s[%d].%s"%(param,i,k)] = v i = i + 1 if self.logging is not None: diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py index cec920c5ff0..2e270a7cd58 100644 --- a/tools/marvin/marvin/deployDataCenter.py +++ b/tools/marvin/marvin/deployDataCenter.py @@ -270,6 +270,12 @@ class deployDataCenters(): zoneCmd.allocationstate = allocation_state return self.apiClient.updateZone(zoneCmd) + def updateZoneDetails(self, zoneid, details): + zoneCmd = updateZone.updateZoneCmd() + zoneCmd.id = zoneid + zoneCmd.details = details + return self.apiClient.updateZone(zoneCmd) + def createZones(self, zones): for zone in zones: createzone = createZone.createZoneCmd() @@ -293,10 +299,11 @@ class deployDataCenters(): if zone.networktype == "Basic": listnetworkoffering = listNetworkOfferings.listNetworkOfferingsCmd() - listnetworkoffering.name = "DefaultSharedNetscalerEIPandELBNetworkOffering" \ if len(filter(lambda x : x.typ == 'Public', zone.physical_networks[0].traffictypes)) > 0 \ else "DefaultSharedNetworkOfferingWithSGService" + if zone.networkofferingname is not None: + listnetworkoffering.name = zone.networkofferingname listnetworkofferingresponse = \ self.apiClient.listNetworkOfferings(listnetworkoffering) @@ -320,7 +327,15 @@ class deployDataCenters(): zoneId) self.createSecondaryStorages(zone.secondaryStorages, zoneId) - self.enableZone(zoneId, "Enabled") + + enabled = getattr(zone, 'enabled', 'True') + if enabled == 'True' or enabled is None: + self.enableZone(zoneId, "Enabled") + details = getattr(zone, 'details') + if details is not None: + det = [d.__dict__ for d in details] + self.updateZoneDetails(zoneId, det) + return def isEipElbZone(self, zone): diff --git a/tools/marvin/pom.xml b/tools/marvin/pom.xml index ce6ce388125..c0505664486 100644 --- a/tools/marvin/pom.xml +++ b/tools/marvin/pom.xml @@ -157,12 +157,7 @@ marvin.setup ${user.dir}/setup/dev/advanced.cfg - - - - marvin.config - - + @@ -182,7 +177,7 @@ deployAndRun.py -c - ${marvin.config} + ${user.dir}/${marvin.config} -t /tmp/t.log -r @@ -200,15 +195,10 @@ marvin.test - ${user.dir}/setup/dev/advanced.cfg simulator test/integration/smoke + ${user.dir}/setup/dev/advanced.cfg - - - marvin.config - - @@ -228,7 +218,7 @@ --with-marvin --marvin-config - ${marvin.config} + ${user.dir}/${marvin.config} --load -a tags=${tag} diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js index 80c1634199a..1c4c38c75fd 100644 --- a/ui/scripts/instances.js +++ b/ui/scripts/instances.js @@ -1084,7 +1084,7 @@ label:'scaleUp VM', action: function(args) { $.ajax({ - url: createURL("scaleVirtualMachine&id=" + args.context.instances[0].id), + url: createURL("scaleVirtualMachine&id=" + args.context.instances[0].id + "&serviceofferingid=" + args.context.instances[0].serviceofferingid), dataType: "json", async: true, success: function(json) { @@ -1101,7 +1101,11 @@ } } ); + }, + error:function(json){ + args.response.error(parseXMLHttpResponse(json)); } + }); }, messages: { diff --git a/ui/scripts/network.js b/ui/scripts/network.js index 6f6a073812f..6c311923faf 100755 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -924,7 +924,7 @@ } if (isVPC || isAdvancedSGZone || hasSRXFirewall) { - hiddenTabs.push('egressRules'); + hiddenTabs.push('egressRules'); } return hiddenTabs; @@ -1108,6 +1108,401 @@ } }); } + }, + + egressRules: { + title: 'label.egress.rules', + custom: function(args) { + var context = args.context; + + return $('
').multiEdit({ + context: context, + noSelect: true, + noHeaderActionsColumn: true, + fields: { + 'cidrlist': { edit: true, label: 'label.cidr.list', isOptional: true }, + 'protocol': { + label: 'label.protocol', + select: function(args) { + args.$select.change(function() { + var $inputs = args.$form.find('th, td'); + var $icmpFields = $inputs.filter(function() { + var name = $(this).attr('rel'); + + return $.inArray(name, [ + 'icmptype', + 'icmpcode' + ]) > -1; + }); + var $otherFields = $inputs.filter(function() { + var name = $(this).attr('rel'); + + return name != 'cidrlist' && + name != 'icmptype' && + name != 'icmpcode' && + name != 'protocol' && + name != 'add-rule'; + }); + + if ($(this).val() == 'icmp') { + $icmpFields.show(); + $otherFields.hide(); + } else if ($(this).val() == 'all') { + $icmpFields.hide(); + $otherFields.hide(); + } else { + $icmpFields.hide(); + $otherFields.show(); + } + }); + + args.response.success({ + data: [ + { name: 'tcp', description: 'TCP' }, + { name: 'udp', description: 'UDP' }, + { name: 'icmp', description: 'ICMP' }, + { name: 'all', description: 'All' } + ] + }); + } + }, + 'startport': { edit: true, label: 'label.start.port', isOptional: true }, + 'endport': { edit: true, label: 'label.end.port', isOptional: true }, + 'icmptype': { edit: true, label: 'ICMP.type', isHidden: true, isOptional: true }, + 'icmpcode': { edit: true, label: 'ICMP.code', isHidden: true, isOptional: true }, + 'add-rule': { + label: 'label.add', + addButton: true + } + }, + add: { + label: 'label.add', + action: function(args) { + var data = { + protocol: args.data.protocol, + cidrlist: args.data.cidrlist, + networkid: args.context.networks[0].id + }; + + if (args.data.icmptype && args.data.icmpcode) { // ICMP + $.extend(data, { + icmptype: args.data.icmptype, + icmpcode: args.data.icmpcode + }); + } else { // TCP/UDP + $.extend(data, { + startport: args.data.startport, + endport: args.data.endport + }); + } + + $.ajax({ + url: createURL('createEgressFirewallRule'), + data: data, + dataType: 'json', + async: true, + success: function(json) { + var jobId = json.createegressfirewallruleresponse.jobid; + + args.response.success({ + _custom: { + jobId: jobId + }, + notification: { + label: 'label.add.egress.rule', + poll: pollAsyncJobResult + } + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + } + }, + actions: { + destroy: { + label: 'label.remove.rule', + action: function(args) { + $.ajax({ + url: createURL('deleteEgressFirewallRule'), + data: { + id: args.context.multiRule[0].id + }, + dataType: 'json', + async: true, + success: function(data) { + var jobID = data.deleteegressfirewallruleresponse.jobid; + + args.response.success({ + _custom: { + jobId: jobID + }, + notification: { + label: 'label.remove.egress.rule', + poll: pollAsyncJobResult + } + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + } + } + }, + ignoreEmptyFields: true, + dataProvider: function(args) { + $.ajax({ + url: createURL('listEgressFirewallRules'), + data: { + listAll: true, + networkid: args.context.networks[0].id + }, + dataType: 'json', + async: true, + success: function(json) { + var response = json.listegressfirewallrulesresponse.firewallrule ? + json.listegressfirewallrulesresponse.firewallrule : []; + + args.response.success({ + data: $.map(response, function(rule) { + if (rule.protocol == 'all') { + $.extend(rule, { + startport: 'All', + endport: 'All' + }); + } else if (rule.protocol == 'tcp' || rule.protocol == 'udp') { + if (!rule.startport) { + rule.startport = ' '; + } + + if (!rule.endport) { + rule.endport = ' '; + } + } + + return rule; + }) + }); + } + }); + } + }); + } + }, + + addloadBalancer: { // EIP/ELB Basic zone: Add Load Balancer tab in network detailView + title: 'label.add.load.balancer', + custom: function(args) { + var context = args.context; + + return $('
').addClass('loadBalancer').multiEdit( + { + context: context, + listView: $.extend(true, {}, cloudStack.sections.instances, { + listView: { + filters: false, + + dataProvider: function(args) { + var data = { + page: args.page, + pageSize: pageSize, + domainid: g_domainid, + account: g_account, + networkid: args.context.networks[0].id, + listAll: true + }; + + $.ajax({ + url: createURL('listVirtualMachines'), + data: data, + dataType: 'json', + async: true, + success: function(data) { + args.response.success({ + data: $.grep( + data.listvirtualmachinesresponse.virtualmachine ? + data.listvirtualmachinesresponse.virtualmachine : [], + function(instance) { + var nonAutoScale=0; + if(instance.displayname == null) + nonAutoScale = 1; + else{ + if( instance.displayname.match(/AutoScale-LB-/)==null) + nonAutoScale =1; + else { + if(instance.displayname.match(/AutoScale-LB-/).length) + nonAutoScale =0; + } + } + var isActiveState= $.inArray(instance.state, ['Destroyed','Expunging']) == -1; + return nonAutoScale && isActiveState; + } + ) + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + } + } + }), + multipleAdd: true, + fields: { + 'name': { edit: true, label: 'label.name' }, + 'publicport': { edit: true, label: 'label.public.port' }, + 'privateport': { edit: true, label: 'label.private.port' }, + 'algorithm': { + label: 'label.algorithm', + select: function(args) { + args.response.success({ + data: [ + { name: 'roundrobin', description: _l('label.round.robin') }, + { name: 'leastconn', description: _l('label.least.connections') }, + { name: 'source', description: _l('label.source') } + ] + }); + } + }, + 'sticky': { + label: 'label.stickiness', + custom: { + buttonLabel: 'label.configure', + action: cloudStack.lbStickyPolicy.dialog() + } + }, + 'autoScale': { + label: 'AutoScale', + custom: { + requireValidation: true, + buttonLabel: 'label.configure', + action: cloudStack.uiCustom.autoscaler(cloudStack.autoscaler) + } + }, + 'add-vm': { + label: 'label.add.vms', + addButton: true + } + }, + + add: { //basic zone - elastic IP - Add Load Balancer tab - Add VMs button + label: 'label.add.vms', + action: function(args) { + var data = { + algorithm: args.data.algorithm, + name: args.data.name, + privateport: args.data.privateport, + publicport: args.data.publicport, + openfirewall: false, + domainid: g_domainid, + account: g_account + }; + + if('vpc' in args.context) { //from VPC section + if(args.data.tier == null) { + args.response.error('Tier is required'); + return; + } + $.extend(data, { + networkid: args.data.tier + }); + } + else { //from Guest Network section + $.extend(data, { + networkid: args.context.networks[0].id + }); + } + + var stickyData = $.extend(true, {}, args.data.sticky); + + $.ajax({ + url: createURL('createLoadBalancerRule'), + data: data, + dataType: 'json', + async: true, + success: function(data) { + var itemData = args.itemData; + //var jobID = data.createloadbalancerruleresponse.jobid; //CS-16964: use jobid from assignToLoadBalancerRule instead of createLoadBalancerRule + + $.ajax({ + url: createURL('assignToLoadBalancerRule'), + data: { + id: data.createloadbalancerruleresponse.id, + virtualmachineids: $.map(itemData, function(elem) { + return elem.id; + }).join(',') + }, + dataType: 'json', + async: true, + success: function(data) { + var jobID = data.assigntoloadbalancerruleresponse.jobid; //CS-16964: use jobid from assignToLoadBalancerRule instead of createLoadBalancerRule + var lbCreationComplete = false; + + args.response.success({ + _custom: { + jobId: jobID + }, + notification: { + label: 'label.add.load.balancer', + poll: function(args) { + var complete = args.complete; + var error = args.error; + + pollAsyncJobResult({ + _custom: args._custom, + complete: function(args) { + if (lbCreationComplete) { + return; + } + + lbCreationComplete = true; + cloudStack.dialog.notice({ + message: _l('message.add.load.balancer.under.ip') + + args.data.loadbalancer.publicip + }); + + if (stickyData && + stickyData.methodname && + stickyData.methodname != 'None') { + cloudStack.lbStickyPolicy.actions.add( + args.data.loadbalancer.id, + stickyData, + complete, // Complete + complete // Error + ); + } else { + complete(); + } + }, + error: error + }); + } + } + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + } + }, + + + dataProvider: function(args) { + args.response.success({ //no LB listing in AddLoadBalancer tab + data: [] + }); + } + } + ); + } } } } @@ -2783,6 +3178,7 @@ } } }, + itemActions: { add: { label: 'label.add.vms.to.lb', diff --git a/ui/scripts/system.js b/ui/scripts/system.js index d89f6b69dcd..f74711d273d 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -565,6 +565,14 @@ }); } }, + actionPreFilter: function(args) { + var actionsToShow = ['destroy']; + if(args.context.multiRule[0].domain == 'ROOT' && args.context.multiRule[0].account.account == 'system') + actionsToShow.push('addAccount'); + else + actionsToShow.push('releaseFromAccount'); + return actionsToShow; + }, actions: { destroy: { label: 'label.remove.ip.range', @@ -588,7 +596,7 @@ } }); } - }, + }, /* releaseFromAccount: { label: 'Release from Account', @@ -643,7 +651,10 @@ }, action: function(args) { var data = { - id: args.context.multiRule[0].id + id: args.context.multiRule[0].id, + zoneid: args.context.multiRule[0].zoneid, + domainid: args.data.domainid, + account: args.data.account }; $.ajax({ url: createURL('dedicatePublicIpRange'), @@ -663,8 +674,8 @@ } }); } - } - */ + } + */ }, dataProvider: function(args) { $.ajax({ diff --git a/utils/src/com/cloud/utils/nio/NioClient.java b/utils/src/com/cloud/utils/nio/NioClient.java index 1e2aa52fc77..8d12f931dc6 100755 --- a/utils/src/com/cloud/utils/nio/NioClient.java +++ b/utils/src/com/cloud/utils/nio/NioClient.java @@ -22,8 +22,8 @@ import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; -import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; import org.apache.log4j.Logger; @@ -78,6 +78,7 @@ public class NioClient extends NioConnection { Link.doHandshake(sch, sslEngine, true); s_logger.info("SSL: Handshake done"); + s_logger.info("Connected to " + _host + ":" + _port); } catch (Exception e) { _selector.close(); throw new IOException("SSL: Fail to init SSL! " + e); diff --git a/utils/src/com/cloud/utils/nio/NioConnection.java b/utils/src/com/cloud/utils/nio/NioConnection.java index 50e6a88e3e4..07c2beaf517 100755 --- a/utils/src/com/cloud/utils/nio/NioConnection.java +++ b/utils/src/com/cloud/utils/nio/NioConnection.java @@ -107,7 +107,7 @@ public abstract class NioConnection implements Runnable { try { init(); } catch (ConnectException e) { - s_logger.error("Unable to connect to remote"); + s_logger.warn("Unable to connect to remote: is there a server running on port " + _port); return; } catch (IOException e) { s_logger.error("Unable to initialize the threads.", e); diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java index 04b4d8edcce..c76ce84bc3d 100755 --- a/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/util/VmwareGuestOsMapper.java @@ -62,6 +62,11 @@ public class VmwareGuestOsMapper { s_mapper.put("Windows 8 (64 bit)", VirtualMachineGuestOsIdentifier.WINDOWS_8_64_GUEST); s_mapper.put("Windows 8 Server (64 bit)", VirtualMachineGuestOsIdentifier.WINDOWS_8_SERVER_64_GUEST); + s_mapper.put("Apple Mac OS X 10.6 (32 bits)", VirtualMachineGuestOsIdentifier.DARWIN_10_GUEST); + s_mapper.put("Apple Mac OS X 10.6 (64 bits)", VirtualMachineGuestOsIdentifier.DARWIN_10_64_GUEST); + s_mapper.put("Apple Mac OS X 10.7 (32 bits)", VirtualMachineGuestOsIdentifier.DARWIN_11_GUEST); + s_mapper.put("Apple Mac OS X 10.7 (64 bits)", VirtualMachineGuestOsIdentifier.DARWIN_11_64_GUEST); + s_mapper.put("Open Enterprise Server", VirtualMachineGuestOsIdentifier.OES_GUEST); s_mapper.put("Asianux 3(32-bit)", VirtualMachineGuestOsIdentifier.ASIANUX_3_GUEST);