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/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index b995e481286..6a26212ecc7 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -142,6 +142,9 @@ public class EventTypes { //registering SSH keypair events public static final String EVENT_REGISTER_SSH_KEYPAIR = "REGISTER.SSH.KEYPAIR"; + //register for user API and secret keys + public static final String EVENT_REGISTER_FOR_SECRET_API_KEY = "REGISTER.USER.KEY"; + // Template Events public static final String EVENT_TEMPLATE_CREATE = "TEMPLATE.CREATE"; public static final String EVENT_TEMPLATE_DELETE = "TEMPLATE.DELETE"; 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 179dc655fbf..77d419e540b 100644 --- a/api/src/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseCmd.java @@ -33,7 +33,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; @@ -110,7 +109,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/region/ha/gslb/ListGlobalLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/ListGlobalLoadBalancerRuleCmd.java index dae861a35b1..d75de57f7d1 100644 --- a/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/ListGlobalLoadBalancerRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/region/ha/gslb/ListGlobalLoadBalancerRuleCmd.java @@ -45,7 +45,7 @@ public class ListGlobalLoadBalancerRuleCmd extends BaseListTaggedResourcesCmd { @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = GlobalLoadBalancerResponse.class, description = "the ID of the global load balancer rule") private Long id; - @Parameter(name = ApiConstants.REGION_ID, type = CommandType.UUID, entityType = RegionResponse.class, description = "region ID") + @Parameter(name = ApiConstants.REGION_ID, type = CommandType.INTEGER, entityType = RegionResponse.class, description = "region ID") private Integer regionId; // /////////////////////////////////////////////////// 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 4de80afa629..72b412898c7 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -458,6 +458,22 @@ + + process-quickcloud-spring-context + process-resources + + run + + + + quickcloud + + + + diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in index ed881acb23c..ca930da3067 100644 --- a/client/tomcatconf/applicationContext.xml.in +++ b/client/tomcatconf/applicationContext.xml.in @@ -506,7 +506,7 @@ - + @@ -737,7 +737,6 @@ - diff --git a/client/tomcatconf/nonossComponentContext.xml.in b/client/tomcatconf/nonossComponentContext.xml.in index 187446c44f3..fc8a9cd5409 100644 --- a/client/tomcatconf/nonossComponentContext.xml.in +++ b/client/tomcatconf/nonossComponentContext.xml.in @@ -43,7 +43,12 @@ --> - + + + + + + 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/debian/cloudstack-agent.install b/debian/cloudstack-agent.install index 02501855354..a3cc86964dd 100644 --- a/debian/cloudstack-agent.install +++ b/debian/cloudstack-agent.install @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,7 +20,7 @@ /etc/cloudstack/agent/log4j-cloud.xml /etc/init.d/cloudstack-agent /usr/bin/cloudstack-setup-agent -/usr/bin/cloud-ssh +/usr/bin/cloudstack-ssh /var/log/cloudstack/agent /usr/share/cloudstack-agent/lib/* /usr/share/cloudstack-agent/plugins diff --git a/debian/cloudstack-common.install b/debian/cloudstack-common.install index 021474e1b65..7e01adadedf 100644 --- a/debian/cloudstack-common.install +++ b/debian/cloudstack-common.install @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -27,6 +27,6 @@ /usr/share/cloudstack-common/scripts/vm/hypervisor/versions.sh /usr/share/cloudstack-common/scripts/vm/hypervisor/xenserver/* /usr/share/cloudstack-common/lib/* -/usr/bin/cloud-set-guest-password -/usr/bin/cloud-set-guest-sshkey +/usr/bin/cloudstack-set-guest-password +/usr/bin/cloudstack-set-guest-sshkey /usr/lib/python2.?/*-packages/* diff --git a/debian/cloudstack-management.install b/debian/cloudstack-management.install index 6d87748c757..5a682d45862 100644 --- a/debian/cloudstack-management.install +++ b/debian/cloudstack-management.install @@ -25,8 +25,10 @@ /var/log/cloudstack/management /var/lib/cloudstack/mnt /var/lib/cloudstack/management -/usr/bin/cloud-update-xenserver-licenses -/usr/bin/cloud-setup-management -/usr/bin/cloud-setup-databases -/usr/bin/cloud-migrate-databases +/usr/bin/cloudstack-update-xenserver-licenses +/usr/bin/cloudstack-setup-management +/usr/bin/cloudstack-setup-databases +/usr/bin/cloudstack-migrate-databases +/usr/bin/cloudstack-setup-encryption +/usr/bin/cloudstack-sysvmadm /usr/share/cloudstack-management/* diff --git a/debian/rules b/debian/rules index f05277ed5d1..4e55c71048c 100755 --- a/debian/rules +++ b/debian/rules @@ -69,7 +69,7 @@ install: install -D plugins/hypervisors/kvm/target/dependencies/* $(DESTDIR)/usr/share/$(PACKAGE)-agent/lib/ install -D packaging/debian/init/cloud-agent $(DESTDIR)/$(SYSCONFDIR)/init.d/$(PACKAGE)-agent install -D agent/bindir/cloud-setup-agent.in $(DESTDIR)/usr/bin/cloudstack-setup-agent - install -D agent/bindir/cloud-ssh.in $(DESTDIR)/usr/bin/cloud-ssh + install -D agent/bindir/cloud-ssh.in $(DESTDIR)/usr/bin/cloudstack-ssh install -D agent/target/transformed/* $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/agent # cloudstack-management @@ -100,7 +100,7 @@ install: ln -s tomcat6-nonssl.conf $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/management/tomcat6.conf ln -s server-nonssl.xml $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/management/server.xml install -D packaging/debian/init/cloud-management $(DESTDIR)/$(SYSCONFDIR)/init.d/$(PACKAGE)-management - install -D client/bindir/cloud-update-xenserver-licenses.in $(DESTDIR)/usr/bin/cloud-update-xenserver-licenses + install -D client/bindir/cloud-update-xenserver-licenses.in $(DESTDIR)/usr/bin/cloudstack-update-xenserver-licenses ln -s /usr/share/tomcat6/bin $(DESTDIR)/usr/share/$(PACKAGE)-management/bin # Remove configuration in /ur/share/cloudstack-management/webapps/client/WEB-INF # This should all be in /etc/cloudstack/management @@ -121,11 +121,13 @@ install: cp -r scripts/storage $(DESTDIR)/usr/share/$(PACKAGE)-common/scripts cp -r scripts/util $(DESTDIR)/usr/share/$(PACKAGE)-common/scripts cp -r scripts/vm $(DESTDIR)/usr/share/$(PACKAGE)-common/scripts - install -D client/target/utilities/bin/cloud-migrate-databases $(DESTDIR)/usr/bin - install -D client/target/utilities/bin/cloud-set-guest-password $(DESTDIR)/usr/bin - install -D client/target/utilities/bin/cloud-set-guest-sshkey $(DESTDIR)/usr/bin - install -D client/target/utilities/bin/cloud-setup-databases $(DESTDIR)/usr/bin - install -D client/target/utilities/bin/cloud-setup-management $(DESTDIR)/usr/bin + install -D client/target/utilities/bin/cloud-migrate-databases $(DESTDIR)/usr/bin/cloudstack-migrate-databases + install -D client/target/utilities/bin/cloud-set-guest-password $(DESTDIR)/usr/bin/cloudstack-set-guest-password + install -D client/target/utilities/bin/cloud-set-guest-sshkey $(DESTDIR)/usr/bin/cloudstack-set-guest-sshkey + install -D client/target/utilities/bin/cloud-setup-databases $(DESTDIR)/usr/bin/cloudstack-setup-databases + install -D client/target/utilities/bin/cloud-setup-management $(DESTDIR)/usr/bin/cloudstack-setup-management + install -D client/target/utilities/bin/cloud-setup-encryption $(DESTDIR)/usr/bin/cloudstack-setup-encryption + install -D client/target/utilities/bin/cloud-sysvmadm $(DESTDIR)/usr/bin/cloudstack-sysvmadm install -D services/console-proxy/server/dist/systemvm.iso $(DESTDIR)/usr/share/$(PACKAGE)-common/vms/systemvm.iso # We need jasypt for cloud-install-sys-tmplt, so this is a nasty hack to get it into the right place install -D agent/target/dependencies/jasypt-1.9.0.jar $(DESTDIR)/usr/share/$(PACKAGE)-common/lib 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 be8bcdd7544..0ab84c40d9b 100644 --- a/docs/en-US/Book_Info.xml +++ b/docs/en-US/Book_Info.xml @@ -22,23 +22,26 @@ specific language governing permissions and limitations under the License. --> + - &PRODUCT; Guide - Revised August 9, 2012 10:48 pm Pacific - Apache CloudStack - 4.0.0 - 1 - - - Complete technical documentation of &PRODUCT;. - - - - - - - - - - + &PRODUCT; Guide + Revised August 9, 2012 10:48 pm Pacific + Apache CloudStack + 4.0.0 + 1 + + + + Complete technical documentation of &PRODUCT;. + + + + + + + + + + + diff --git a/docs/en-US/Installation_Guide.xml b/docs/en-US/Installation_Guide.xml index 28df071d42f..6ce5527e86c 100644 --- a/docs/en-US/Installation_Guide.xml +++ b/docs/en-US/Installation_Guide.xml @@ -11,7 +11,9 @@ to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/docs/en-US/Release_Notes.xml b/docs/en-US/Release_Notes.xml index be0267dd4b3..b8c5c01fb0b 100644 --- a/docs/en-US/Release_Notes.xml +++ b/docs/en-US/Release_Notes.xml @@ -4,1064 +4,1290 @@ %BOOK_ENTITIES; ]> - - Welcome to &PRODUCT; 4.1 - Welcome to the 4.1.0 release of &PRODUCT;, the first major release from the Apache CloudStack project since its graduation from the Apache Incubator. - This document contains information specific to this release of &PRODUCT;, including upgrade instructions from prior releases, new features added to &PRODUCT;, API changes, and issues fixed in the release. For installation instructions, please see the Installation Guide. For usage and administration instructions, please see the &PRODUCT; Administrator's Guide. Developers and users who wish to work with the API will find instruction in the &PRODUCT; API Developer's Guide - If you find any errors or problems in this guide, please see . We hope you enjoy working with &PRODUCT;! - - - Upgrade Instructions - This section contains upgrade instructions from prior versions of CloudStack to Apache CloudStack 4.1.0. We include instructions on upgrading to Apache CloudStack from pre-Apache versions of Citrix CloudStack (last version prior to Apache is 3.0.2) and from the releases made while CloudStack was in the Apache Incubator. - 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. - Any steps that are hypervisor-specific will be called out with a note. - - - Create RPM or Debian packages (as appropriate) and a repository from the 4.1.0 source, or check the Apache CloudStack downloads page at http://cloudstack.apache.org/downloads.html for package repositories supplied by community members. Instructions for creating packages from the &PRODUCT; source are in the Installation Guide. - - - Stop your management server or servers. Run this on all management server hosts: - # service cloud-management 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 - - -
-
- Upgrade from 3.0.2 to 4.0.0-incubating - Perform the following to upgrade from version 3.0.2 to version 4.0.0-incubating. Note - that some of the steps here are only required if you're using a specific hypervisor. The - steps that are hypervisor-specific are called out with a note. - - - Ensure that you query your IP address usage records and process them or make a - backup. During the upgrade you will lose the old IP address usage records. - Starting in 3.0.2, the usage record format for IP addresses is the same as the rest - of the usage types. Instead of a single record with the assignment and release dates, - separate records are generated per aggregation period with start and end dates. After - upgrading, any existing IP address usage records in the old format will no longer be - available. - - - - The following upgrade instructions apply only if you're using VMware hosts. If - you're not using VMware hosts, skip this step and move on to step 3: stopping all - usage servers. - - In each zone that includes VMware hosts, you need to add a new system VM template. - - - While running the existing 3.0.2 system, log in to the UI as root - administrator. - - - In the left navigation bar, click Templates. - - - In Select view, click Templates. - - - Click Register template. - The Register template dialog box is displayed. - - - In the Register template dialog box, specify the following values (do not change - these): - - - - - - - Field - Value - - - - - Name - systemvm-vmware-4.0 - - - Description - systemvm-vmware-4.0 - - - URL - http://download.cloud.com/templates/burbank/burbank-systemvm-08012012.ova - - - Zone - Choose the zone where this hypervisor is used - - - Hypervisor - VMware - - - Format - OVA - - - OS Type - Debian GNU/Linux 5.0 (32-bit) - - - Extractable - no - - - Password Enabled - no - - - Public - no - - - Featured - no - - - - - - - Watch the screen to be sure that the template downloads successfully and enters - the READY state. Do not proceed until this is successful. - - - - - Stop all Usage Servers if running. Run this on all Usage Server hosts. - # service cloud-usage stop - - - Stop the Management Servers. Run this on all Management Server hosts. - # service cloud-management stop - - - On the MySQL master, take a backup of the MySQL databases. We recommend performing - this step even in test upgrades. If there is an issue, this will assist with - debugging. - In the following commands, it is assumed that you have set the root password on the - database, which is a CloudStack recommended best practice. Substitute your own MySQL - root password. - # mysqldump -u root -pmysql_password cloud > cloud-backup.dmp -# mysqldump -u root -pmysql_password cloud_usage > cloud-usage-backup.dmp - - - Either build RPM/DEB packages as detailed in the Installation Guide, or use one of - the community provided yum/apt repositories to gain access to the &PRODUCT; - binaries. - - - After you have configured an appropriate yum or apt repository, you may execute the - one of the following commands as appropriate for your environment in order to upgrade - &PRODUCT;: # yum update cloud-* - # apt-get update -# apt-get upgrade cloud-* - - You will, of course, have to agree to the changes suggested by Yum or APT. - - If the upgrade output includes a message similar to the following, then some - custom content was found in your old components.xml, and you need to merge the two - files: - warning: /etc/cloud/management/components.xml created as /etc/cloud/management/components.xml.rpmnew - Instructions follow in the next step. - - - - If you have made changes to your copy of - /etc/cloud/management/components.xml the changes will be - preserved in the upgrade. However, you need to do the following steps to place these - changes in a new version of the file which is compatible with version - 4.0.0-incubating. - - - Make a backup copy of /etc/cloud/management/components.xml. - For example: - # mv /etc/cloud/management/components.xml /etc/cloud/management/components.xml-backup - - - Copy /etc/cloud/management/components.xml.rpmnew to create - a new /etc/cloud/management/components.xml: - # cp -ap /etc/cloud/management/components.xml.rpmnew /etc/cloud/management/components.xml - - - Merge your changes from the backup file into the new - components.xml. - # vi /etc/cloud/management/components.xml - - - - If you have more than one management server node, repeat the upgrade steps on each - node. - - - - Start the first Management Server. Do not start any other Management Server nodes - yet. - # 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. - - Failing to restart the Management Server indicates a problem in the upgrade. - Having the Management Server restarted without any issues indicates that the upgrade - is successfully completed. - - - - Start all Usage Servers (if they were running on your previous version). Perform - this on each Usage Server host. - # service cloud-usage start - - - - Additional steps are required for each KVM host. These steps will not affect - running guests in the cloud. These steps are required only for clouds using KVM as - hosts and only on the KVM hosts. - - - - Configure a yum or apt respository containing the &PRODUCT; packages as outlined - in the Installation Guide. - - - Stop the running agent. - # service cloud-agent stop - - - Update the agent software with one of the following command sets as appropriate - for your environment. - # yum update cloud-* - # apt-get update - # apt-get upgrade cloud-* - - - Start the agent. - # service cloud-agent start - - - Edit /etc/cloud/agent/agent.properties to change the - resource parameter from - "com.cloud.agent.resource.computing.LibvirtComputingResource" to - "com.cloud.hypervisor.kvm.resource.LibvirtComputingResource". - - - Start the cloud agent and cloud management services. - - - When the Management Server is up and running, log in to the CloudStack UI and - restart the virtual router for proper functioning of all the features. - - - - - Log in to the CloudStack UI as administrator, and check the status of the hosts. All - hosts should come to Up state (except those that you know to be offline). You may need - to wait 20 or 30 minutes, depending on the number of hosts. - - Troubleshooting: If login fails, clear your browser cache and reload the - page. - - - Do not proceed to the next step until the hosts show in Up state. - - - If you are upgrading from 3.0.2, perform the following: - - - Ensure that the admin port is set to 8096 by using the "integration.api.port" - global parameter. - This port is used by the cloud-sysvmadm script at the end of the upgrade - procedure. For information about how to set this parameter, see "Setting Global - Configuration Parameters" in the Installation Guide. - - - Restart the Management Server. - - If you don't want the admin port to remain open, you can set it to null after - the upgrade is done and restart the management server. - - - - - - Run the cloud-sysvmadm script to stop, then start, all Secondary - Storage VMs, Console Proxy VMs, and virtual routers. Run the script once on each - management server. Substitute your own IP address of the MySQL instance, the MySQL user - to connect as, and the password to use for that user. In addition to those parameters, - provide the -c and -r arguments. For - example: - # nohup cloud-sysvmadm -d 192.168.1.5 -u cloud -p password -c -r > - sysvm.log 2>&1 & - # tail -f sysvm.log - This might take up to an hour or more to run, depending on the number of accounts in - the system. - - - If needed, upgrade all Citrix XenServer hypervisor hosts in your cloud to a version - supported by CloudStack 4.0.0-incubating. The supported versions are XenServer 5.6 SP2 - and 6.0.2. Instructions for upgrade can be found in the CloudStack 4.0.0-incubating - Installation Guide. - - - Now apply the XenServer hotfix XS602E003 (and any other needed hotfixes) to - XenServer v6.0.2 hypervisor hosts. - - - Disconnect the XenServer cluster from CloudStack. - In the left navigation bar of the CloudStack UI, select Infrastructure. Under - Clusters, click View All. Select the XenServer cluster and click Actions - - Unmanage. - This may fail if there are hosts not in one of the states Up, Down, - Disconnected, or Alert. You may need to fix that before unmanaging this - cluster. - Wait until the status of the cluster has reached Unmanaged. Use the CloudStack - UI to check on the status. When the cluster is in the unmanaged state, there is no - connection to the hosts in the cluster. - - - To clean up the VLAN, log in to one XenServer host and run: - /opt/xensource/bin/cloud-clean-vlan.sh - - - Now prepare the upgrade by running the following on one XenServer host: - /opt/xensource/bin/cloud-prepare-upgrade.sh - If you see a message like "can't eject CD", log in to the VM and unmount the CD, - then run this script again. - - - Upload the hotfix to the XenServer hosts. Always start with the Xen pool master, - then the slaves. Using your favorite file copy utility (e.g. WinSCP), copy the - hotfixes to the host. Place them in a temporary folder such as /tmp. - On the Xen pool master, upload the hotfix with this command: - xe patch-upload file-name=XS602E003.xsupdate - Make a note of the output from this command, which is a UUID for the hotfix - file. You'll need it in another step later. - - (Optional) If you are applying other hotfixes as well, you can repeat the - commands in this section with the appropriate hotfix number. For example, - XS602E004.xsupdate. - - - - Manually live migrate all VMs on this host to another host. First, get a list of - the VMs on this host: - # xe vm-list - Then use this command to migrate each VM. Replace the example host name and VM - name with your own: - # xe vm-migrate live=true host=host-name - vm=VM-name - - Troubleshooting - If you see a message like "You attempted an operation on a VM which requires - PV drivers to be installed but the drivers were not detected," run: - /opt/xensource/bin/make_migratable.sh - b6cf79c8-02ee-050b-922f-49583d9f1a14. - - - - Apply the hotfix. First, get the UUID of this host: - # xe host-list - Then use the following command to apply the hotfix. Replace the example host - UUID with the current host ID, and replace the hotfix UUID with the output from the - patch-upload command you ran on this machine earlier. You can also get the hotfix - UUID by running xe patch-list. - xe patch-apply host-uuid=host-uuid uuid=hotfix-uuid - - - Copy the following files from the CloudStack Management Server to the - host. - - - - - - - Copy from here... - ...to here - - - - - /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/xenserver60/NFSSR.py - /opt/xensource/sm/NFSSR.py - - - /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/setupxenserver.sh - /opt/xensource/bin/setupxenserver.sh - - - /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/make_migratable.sh - /opt/xensource/bin/make_migratable.sh - - - - - - - (Only for hotfixes XS602E005 and XS602E007) You need to apply a new Cloud - Support Pack. - + + Welcome to &PRODUCT; 4.1 + Welcome to the 4.1.0 release of &PRODUCT;, the first major release from the Apache CloudStack project since its graduation from the Apache Incubator. + This document contains information specific to this release of &PRODUCT;, including upgrade instructions from prior releases, new features added to &PRODUCT;, API changes, and issues fixed in the release. For installation instructions, please see the Installation Guide. For usage and administration instructions, please see the &PRODUCT; Administrator's Guide. Developers and users who wish to work with the API will find instruction in the &PRODUCT; API Developer's Guide + If you find any errors or problems in this guide, please see . We hope you enjoy working with &PRODUCT;! + + + Upgrade Instructions + This section contains upgrade instructions from prior versions of CloudStack to Apache CloudStack 4.1.0. We include instructions on upgrading to Apache CloudStack from pre-Apache versions of Citrix CloudStack (last version prior to Apache is 3.0.2) and from the releases made while CloudStack was in the Apache Incubator. + 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 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. + However, this does mean that the procedure is not as simple as an apt-get upgrade or yum update, so please follow this section carefully. + + We recommend reading through this section once or twice before beginning your upgrade procedure, and working through it on a test system before working on a production system. + - Download the CSP software onto the XenServer host from one of the following - links: - For hotfix XS602E005: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E005/56710/xe-phase-2/xenserver-cloud-supp.tgz - For hotfix XS602E007: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E007/57824/xe-phase-2/xenserver-cloud-supp.tgz + Most users of &PRODUCT; manage the installation and upgrades of &PRODUCT; with one of Linux's predominant package systems, RPM or APT. This guide assumes you'll be using RPM and Yum (for Red Hat Enterprise Linux or CentOS), or APT and Debian packages (for Ubuntu). + Create RPM or Debian packages (as appropriate) and a repository from the 4.1.0 source, or check the Apache CloudStack downloads page at http://cloudstack.apache.org/downloads.html for package repositories supplied by community members. You will need them for step or step . + Instructions for creating packages from the &PRODUCT; source are in the Installation Guide. - Extract the file: - # tar xf xenserver-cloud-supp.tgz + Stop your management server or servers. Run this on all management server hosts: + # service cloud-management stop - Run the following script: - # xe-install-supplemental-pack xenserver-cloud-supp.iso + If you are running a usage server or usage servers, stop those as well: + # service cloud-usage stop - If the XenServer host is part of a zone that uses basic networking, disable - Open vSwitch (OVS): - # xe-switch-network-backend bridge + 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 - - - - Reboot this XenServer host. - - - Run the following: - /opt/xensource/bin/setupxenserver.sh - - If the message "mv: cannot stat `/etc/cron.daily/logrotate': No such file or - directory" appears, you can safely ignore it. - - - - Run the following: - for pbd in `xe pbd-list currently-attached=false| grep ^uuid | awk '{print $NF}'`; do xe pbd-plug uuid=$pbd ; - - - On each slave host in the Xen pool, repeat these steps, starting from "manually - live migrate VMs." - - - - - - Troubleshooting Tip - If passwords which you know to be valid appear not to work after upgrade, or other UI - issues are seen, try clearing your browser cache and reloading the UI page. - -
-
- Upgrade from 2.2.14 to 4.0.0-incubating - - - Ensure that you query your IPaddress usage records and process them; for example, - issue invoices for any usage that you have not yet billed users for. - Starting in 3.0.2, the usage record format for IP addresses is the same as the rest - of the usage types. Instead of a single record with the assignment and release dates, - separate records are generated per aggregation period with start and end dates. After - upgrading to 4.0.0-incubating, any existing IP address usage records in the old format - will no longer be available. - - - If you are using version 2.2.0 - 2.2.13, first upgrade to 2.2.14 by using the - instructions in the 2.2.14 Release Notes. - - KVM Hosts - If KVM hypervisor is used in your cloud, be sure you completed the step to insert - a valid username and password into the host_details table on each KVM node as - described in the 2.2.14 Release Notes. This step is critical, as the database will be - encrypted after the upgrade to 4.0.0-incubating. - - - - While running the 2.2.14 system, log in to the UI as root administrator. - - - Using the UI, add a new System VM template for each hypervisor type that is used in - your cloud. In each zone, add a system VM template for each hypervisor used in that - zone - - - In the left navigation bar, click Templates. - - - In Select view, click Templates. - - - Click Register template. - The Register template dialog box is displayed. - - - In the Register template dialog box, specify the following values depending on - the hypervisor type (do not change these): - - - - - - - Hypervisor - Description - - - - - XenServer - Name: systemvm-xenserver-3.0.0 - Description: systemvm-xenserver-3.0.0 - URL: - http://download.cloud.com/templates/acton/acton-systemvm-02062012.vhd.bz2 - Zone: Choose the zone where this hypervisor is used - Hypervisor: XenServer - Format: VHD - OS Type: Debian GNU/Linux 5.0 (32-bit) - Extractable: no - Password Enabled: no - Public: no - Featured: no - - - - KVM - Name: systemvm-kvm-4.1.0 - Description: systemvm-kvm-4.1.0 - URL: - http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2 - Zone: Choose the zone where this hypervisor is used - Hypervisor: KVM - Format: QCOW2 - OS Type: Debian GNU/Linux 5.0 (32-bit) - Extractable: no - Password Enabled: no - Public: no - Featured: no - - - - VMware - Name: systemvm-vmware-4.1.0 - Description: systemvm-vmware-4.1.0 - URL: - http://download.cloud.com/templates/burbank/burbank-systemvm-08012012.ova - Zone: Choose the zone where this hypervisor is used - Hypervisor: VMware - Format: OVA - OS Type: Debian GNU/Linux 5.0 (32-bit) - Extractable: no - Password Enabled: no - Public: no - Featured: no - - - - - - - - - - Watch the screen to be sure that the template downloads successfully and enters the - READY state. Do not proceed until this is successful - - - WARNING: If you use more than one type of - hypervisor in your cloud, be sure you have repeated these steps to download the system - VM template for each hypervisor type. Otherwise, the upgrade will fail. - - - Stop all Usage Servers if running. Run this on all Usage Server hosts. - # service cloud-usage stop - - - Stop the Management Servers. Run this on all Management Server hosts. - # service cloud-management stop - - - On the MySQL master, take a backup of the MySQL databases. We recommend performing - this step even in test upgrades. If there is an issue, this will assist with - debugging. - In the following commands, it is assumed that you have set the root password on the - database, which is a CloudStack recommended best practice. Substitute your own MySQL - root password. - # mysqldump -u root -pmysql_password cloud > cloud-backup.dmp -# mysqldump -u root -pmysql_password cloud_usage > cloud-usage-backup.dmp - - - - Either build RPM/DEB packages as detailed in the Installation Guide, or use one of - the community provided yum/apt repositories to gain access to the &PRODUCT; binaries. - - - - After you have configured an appropriate yum or apt repository, you may execute the - one of the following commands as appropriate for your environment in order to upgrade - &PRODUCT;: # yum update cloud-* - # apt-get update -# apt-get upgrade cloud-* - - You will, of course, have to agree to the changes suggested by Yum or APT. - - - If you have made changes to your existing copy of the file components.xml in your - previous-version CloudStack installation, the changes will be preserved in the upgrade. - However, you need to do the following steps to place these changes in a new version of - the file which is compatible with version 4.0.0-incubating. - - How will you know whether you need to do this? If the upgrade output in the - previous step included a message like the following, then some custom content was - found in your old components.xml, and you need to merge the two files: - - warning: /etc/cloud/management/components.xml created as /etc/cloud/management/components.xml.rpmnew - - - Make a backup copy of your - /etc/cloud/management/components.xml file. For - example: - # mv /etc/cloud/management/components.xml /etc/cloud/management/components.xml-backup - - - Copy /etc/cloud/management/components.xml.rpmnew to create - a new /etc/cloud/management/components.xml: - # cp -ap /etc/cloud/management/components.xml.rpmnew /etc/cloud/management/components.xml - - - Merge your changes from the backup file into the new components.xml file. - # vi /etc/cloud/management/components.xml - - - - - - If you have made changes to your existing copy of the - /etc/cloud/management/db.properties file in your previous-version - CloudStack installation, the changes will be preserved in the upgrade. However, you need - to do the following steps to place these changes in a new version of the file which is - compatible with version 4.0.0-incubating. - - - Make a backup copy of your file - /etc/cloud/management/db.properties. For example: - # mv /etc/cloud/management/db.properties /etc/cloud/management/db.properties-backup - - - Copy /etc/cloud/management/db.properties.rpmnew to create a - new /etc/cloud/management/db.properties: - # cp -ap /etc/cloud/management/db.properties.rpmnew etc/cloud/management/db.properties - - - Merge your changes from the backup file into the new db.properties file. - # vi /etc/cloud/management/db.properties - - - - - On the management server node, run the following command. It is recommended that you - use the command-line flags to provide your own encryption keys. See Password and Key - Encryption in the Installation Guide. - # cloud-setup-encryption -e encryption_type -m management_server_key -k database_key - When used without arguments, as in the following example, the default encryption - type and keys will be used: - - - (Optional) For encryption_type, use file or web to indicate the technique used - to pass in the database encryption password. Default: file. - - - (Optional) For management_server_key, substitute the default key that is used to - encrypt confidential parameters in the properties file. Default: password. It is - highly recommended that you replace this with a more secure value - - - (Optional) For database_key, substitute the default key that is used to encrypt - confidential parameters in the CloudStack database. Default: password. It is highly - recommended that you replace this with a more secure value. - - - - - Repeat steps 10 - 14 on every management server node. If you provided your own - encryption key in step 14, use the same key on all other management servers. - - - Start the first Management Server. Do not start any other Management Server nodes - yet. - # 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. - - - Start all Usage Servers (if they were running on your previous version). Perform - this on each Usage Server host. - # service cloud-usage start - - - (KVM only) Additional steps are required for each KVM host. These steps will not - affect running guests in the cloud. These steps are required only for clouds using KVM - as hosts and only on the KVM hosts. - - - Configure your CloudStack package repositories as outlined in the Installation - Guide - - - Stop the running agent. - # service cloud-agent stop - - - Update the agent software with one of the following command sets as - appropriate. - # yum update cloud-* - - # apt-get update -# apt-get upgrade cloud-* - - - - Start the agent. - # service cloud-agent start - - - Copy the contents of the agent.properties file to the new - agent.properties file by using the following command - sed -i 's/com.cloud.agent.resource.computing.LibvirtComputingResource/com.cloud.hypervisor.kvm.resource.LibvirtComputingResource/g' /etc/cloud/agent/agent.properties - - - Start the cloud agent and cloud management services. - - - When the Management Server is up and running, log in to the CloudStack UI and - restart the virtual router for proper functioning of all the features. - - - - - Log in to the CloudStack UI as admin, and check the status of the hosts. All hosts - should come to Up state (except those that you know to be offline). You may need to wait - 20 or 30 minutes, depending on the number of hosts. - Do not proceed to the next step until the hosts show in the Up state. If the hosts - do not come to the Up state, contact support. - - - Run the following script to stop, then start, all Secondary Storage VMs, Console - Proxy VMs, and virtual routers. - - - Run the command once on one management server. Substitute your own IP address of - the MySQL instance, the MySQL user to connect as, and the password to use for that - user. In addition to those parameters, provide the "-c" and "-r" arguments. For - example: - # nohup cloud-sysvmadm -d 192.168.1.5 -u cloud -p password -c -r > sysvm.log 2>&1 & -# tail -f sysvm.log - This might take up to an hour or more to run, depending on the number of - accounts in the system. - - - After the script terminates, check the log to verify correct execution: - # tail -f sysvm.log - The content should be like the following: - + + 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 + + + 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. + + + If you are using Ubuntu, follow this procedure to upgrade your packages. If not, skip to step . + Community Packages + This section assumes you're using the community supplied packages for &PRODUCT;. If you've created your own packages and APT repository, substitute your own URL for the ones used in these examples. + + + + The first order of business will be to change the sources list for each system with &PRODUCT; packages. This means all management servers, and any hosts that have the KVM agent. (No changes should be necessary for hosts that are running VMware or Xen.) + Start by opening /etc/apt/sources.list.d/cloudstack.list on any systems that have &PRODUCT; packages installed. + This file should have one line, which contains: + deb http://cloudstack.apt-get.eu/ubuntu precise 4.0 + We'll change it to point to the new package repository: + deb http://cloudstack.apt-get.eu/ubuntu precise 4.1 + If you're using your own package repository, change this line to read as appropriate for your 4.1.0 repository. + + + Now update your apt package list: + $ sudo apt-get update + + + Now that you have the repository configured, it's time to install the cloudstack-management package. This will pull in any other dependencies you need. + $ sudo apt-get install cloudstack-management + + + You will need to manually install the cloudstack-agent package: + $ sudo apt-get install cloudstack-agent + During the installation of cloudstack-agent, APT will copy your agent.properties, log4j-cloud.xml, and environment.properties from /etc/cloud/agent to /etc/cloudstack/agent. + When prompted whether you wish to keep your configuration, say Yes. + + + Verify that the file /etc/cloudstack/agent/environment.properties has a line that reads: + paths.script=/usr/share/cloudstack-common + If not, add the line. + + + 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). - - - - - - If you would like additional confirmation that the new system VM templates were - correctly applied when these system VMs were rebooted, SSH into the System VM and check - the version. - Use one of the following techniques, depending on the hypervisor. - - XenServer or KVM: - SSH in by using the link local IP address of the system VM. For example, in the - command below, substitute your own path to the private key used to log in to the - system VM and your own link local IP. - - Run the following commands on the XenServer or KVM host on which the system VM is - present: - # ssh -i private-key-path link-local-ip -p 3922 -# cat /etc/cloudstack-release - The output should be like the following: - Cloudstack Release 4.0.0-incubating Mon Oct 9 15:10:04 PST 2012 - - ESXi - SSH in using the private IP address of the system VM. For example, in the command - below, substitute your own path to the private key used to log in to the system VM and - your own private IP. - - Run the following commands on the Management Server: - # ssh -i private-key-path private-ip -p 3922 -# cat /etc/cloudstack-release - - The output should be like the following: - Cloudstack Release 4.0.0-incubating Mon Oct 9 15:10:04 PST 2012 - - - If needed, upgrade all Citrix XenServer hypervisor hosts in your cloud to a version - supported by CloudStack 4.0.0-incubating. The supported versions are XenServer 5.6 SP2 - and 6.0.2. Instructions for upgrade can be found in the CloudStack 4.0.0-incubating - Installation Guide. - - - Apply the XenServer hotfix XS602E003 (and any other needed hotfixes) to XenServer - v6.0.2 hypervisor hosts. - - - Disconnect the XenServer cluster from CloudStack. - In the left navigation bar of the CloudStack UI, select Infrastructure. Under - Clusters, click View All. Select the XenServer cluster and click Actions - - Unmanage. - This may fail if there are hosts not in one of the states Up, Down, - Disconnected, or Alert. You may need to fix that before unmanaging this - cluster. - Wait until the status of the cluster has reached Unmanaged. Use the CloudStack - UI to check on the status. When the cluster is in the unmanaged state, there is no - connection to the hosts in the cluster. - - - To clean up the VLAN, log in to one XenServer host and run: - /opt/xensource/bin/cloud-clean-vlan.sh - - - Prepare the upgrade by running the following on one XenServer host: - /opt/xensource/bin/cloud-prepare-upgrade.sh - If you see a message like "can't eject CD", log in to the VM and umount the CD, - then run this script again. - - - Upload the hotfix to the XenServer hosts. Always start with the Xen pool master, - then the slaves. Using your favorite file copy utility (e.g. WinSCP), copy the - hotfixes to the host. Place them in a temporary folder such as /root or /tmp. - On the Xen pool master, upload the hotfix with this command: - xe patch-upload file-name=XS602E003.xsupdate - Make a note of the output from this command, which is a UUID for the hotfix - file. You'll need it in another step later. - - (Optional) If you are applying other hotfixes as well, you can repeat the - commands in this section with the appropriate hotfix number. For example, - XS602E004.xsupdate. - - - - Manually live migrate all VMs on this host to another host. First, get a list of - the VMs on this host: - # xe vm-list - Then use this command to migrate each VM. Replace the example host name and VM - name with your own: - # xe vm-migrate live=true host=host-name vm=VM-name - - Troubleshooting - If you see a message like "You attempted an operation on a VM which requires - PV drivers to be installed but the drivers were not detected," run: - /opt/xensource/bin/make_migratable.sh - b6cf79c8-02ee-050b-922f-49583d9f1a14. - - - - Apply the hotfix. First, get the UUID of this host: - # xe host-list - Then use the following command to apply the hotfix. Replace the example host - UUID with the current host ID, and replace the hotfix UUID with the output from the - patch-upload command you ran on this machine earlier. You can also get the hotfix - UUID by running xe patch-list. - xe patch-apply host-uuid=host-uuid - uuid=hotfix-uuid - - - Copy the following files from the CloudStack Management Server to the - host. - + + + + 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. + + +
+
+ Upgrade from 3.0.2 to 4.1.0 + This section will guide you from Citrix CloudStack 3.0.2 to Apache CloudStack 4.1.0. Sections that are hypervisor-specific will be called out with a note. + + + Ensure that you query your IP address usage records and process them or make a + backup. During the upgrade you will lose the old IP address usage records. + Starting in 3.0.2, the usage record format for IP addresses is the same as the rest + of the usage types. Instead of a single record with the assignment and release dates, + separate records are generated per aggregation period with start and end dates. After + upgrading, any existing IP address usage records in the old format will no longer be + available. + + + + The following upgrade instructions apply only if you're using VMware hosts. If + you're not using VMware hosts, skip this step and move on to . + + In each zone that includes VMware hosts, you need to add a new system VM template. + + + While running the existing 3.0.2 system, log in to the UI as root administrator. + + + In the left navigation bar, click Templates. + + + In Select view, click Templates. + + + Click Register template. + The Register template dialog box is displayed. + + + In the Register template dialog box, specify the following values (do not change these): + + + + + + + Field + Value + + + + + Name + systemvm-vmware-4.0 + + + Description + systemvm-vmware-4.0 + + + URL + http://download.cloud.com/templates/burbank/burbank-systemvm-08012012.ova + + + Zone + Choose the zone where this hypervisor is used + + + Hypervisor + VMware + + + Format + OVA + + + OS Type + Debian GNU/Linux 5.0 (32-bit) + + + Extractable + no + + + Password Enabled + no + + + Public + no + + + Featured + no + + + + + + + Watch the screen to be sure that the template downloads successfully and enters + the READY state. Do not proceed until this is successful. + + + + + Stop all Usage Servers if running. Run this on all Usage Server hosts. + # service cloud-usage stop + + + Stop the Management Servers. Run this on all Management Server hosts. + # service cloud-management stop + + + On the MySQL master, take a backup of the MySQL databases. We recommend performing + this step even in test upgrades. If there is an issue, this will assist with + debugging. + In the following commands, it is assumed that you have set the root password on the + database, which is a CloudStack recommended best practice. Substitute your own MySQL + root password. + # mysqldump -u root -pmysql_password cloud > cloud-backup.dmp + # mysqldump -u root -pmysql_password cloud_usage > cloud-usage-backup.dmp + + + Either build RPM/DEB packages as detailed in the Installation Guide, or use one of + the community provided yum/apt repositories to gain access to the &PRODUCT; + binaries. + + + After you have configured an appropriate yum or apt repository, you may execute the + one of the following commands as appropriate for your environment in order to upgrade + &PRODUCT;: # yum update cloud-* + # apt-get update + # apt-get upgrade cloud-* + + You will, of course, have to agree to the changes suggested by Yum or APT. + + If the upgrade output includes a message similar to the following, then some + custom content was found in your old components.xml, and you need to merge the two + files: + warning: /etc/cloud/management/components.xml created as /etc/cloud/management/components.xml.rpmnew + Instructions follow in the next step. + + + + If you have made changes to your copy of + /etc/cloud/management/components.xml the changes will be + preserved in the upgrade. However, you need to do the following steps to place these + changes in a new version of the file which is compatible with version + 4.1.0. + + + Make a backup copy of /etc/cloud/management/components.xml. + For example: + # mv /etc/cloud/management/components.xml /etc/cloud/management/components.xml-backup + + + Copy /etc/cloud/management/components.xml.rpmnew to create + a new /etc/cloud/management/components.xml: + # cp -ap /etc/cloud/management/components.xml.rpmnew /etc/cloud/management/components.xml + + + Merge your changes from the backup file into the new + components.xml. + # vi /etc/cloud/management/components.xml + + + + If you have more than one management server node, repeat the upgrade steps on each + node. + + + + Start the first Management Server. Do not start any other Management Server nodes + yet. + # 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. + + Failing to restart the Management Server indicates a problem in the upgrade. + Having the Management Server restarted without any issues indicates that the upgrade + is successfully completed. + + + + Start all Usage Servers (if they were running on your previous version). Perform + this on each Usage Server host. + # service cloud-usage start + + + + Additional steps are required for each KVM host. These steps will not affect + running guests in the cloud. These steps are required only for clouds using KVM as + hosts and only on the KVM hosts. + + + + Configure a yum or apt respository containing the &PRODUCT; packages as outlined + in the Installation Guide. + + + Stop the running agent. + # service cloud-agent stop + + + Update the agent software with one of the following command sets as appropriate + for your environment. + # yum update cloud-* + # apt-get update + # apt-get upgrade cloud-* + + + Start the agent. + # service cloud-agent start + + + Edit /etc/cloud/agent/agent.properties to change the + resource parameter from + "com.cloud.agent.resource.computing.LibvirtComputingResource" to + "com.cloud.hypervisor.kvm.resource.LibvirtComputingResource". + + + Start the cloud agent and cloud management services. + + + When the Management Server is up and running, log in to the CloudStack UI and + restart the virtual router for proper functioning of all the features. + + + + + Log in to the CloudStack UI as administrator, and check the status of the hosts. All + hosts should come to Up state (except those that you know to be offline). You may need + to wait 20 or 30 minutes, depending on the number of hosts. + + Troubleshooting: If login fails, clear your browser cache and reload the + page. + + + Do not proceed to the next step until the hosts show in Up state. + + + If you are upgrading from 3.0.2, perform the following: + + + Ensure that the admin port is set to 8096 by using the "integration.api.port" + global parameter. + This port is used by the cloud-sysvmadm script at the end of the upgrade + procedure. For information about how to set this parameter, see "Setting Global + Configuration Parameters" in the Installation Guide. + + + Restart the Management Server. + + If you don't want the admin port to remain open, you can set it to null after + the upgrade is done and restart the management server. + + + + + + Run the cloud-sysvmadm script to stop, then start, all Secondary + Storage VMs, Console Proxy VMs, and virtual routers. Run the script once on each + management server. Substitute your own IP address of the MySQL instance, the MySQL user + to connect as, and the password to use for that user. In addition to those parameters, + provide the -c and -r arguments. For + example: + # nohup cloud-sysvmadm -d 192.168.1.5 -u cloud -p password -c -r > + sysvm.log 2>&1 & + # tail -f sysvm.log + This might take up to an hour or more to run, depending on the number of accounts in + the system. + + + If needed, upgrade all Citrix XenServer hypervisor hosts in your cloud to a version + supported by CloudStack 4.1.0. The supported versions are XenServer 5.6 SP2 + and 6.0.2. Instructions for upgrade can be found in the CloudStack 4.1.0 + Installation Guide under "Upgrading XenServer Versions." + + + Now apply the XenServer hotfix XS602E003 (and any other needed hotfixes) to + XenServer v6.0.2 hypervisor hosts. + + + Disconnect the XenServer cluster from CloudStack. + In the left navigation bar of the CloudStack UI, select Infrastructure. Under + Clusters, click View All. Select the XenServer cluster and click Actions - + Unmanage. + This may fail if there are hosts not in one of the states Up, Down, + Disconnected, or Alert. You may need to fix that before unmanaging this + cluster. + Wait until the status of the cluster has reached Unmanaged. Use the CloudStack + UI to check on the status. When the cluster is in the unmanaged state, there is no + connection to the hosts in the cluster. + + + To clean up the VLAN, log in to one XenServer host and run: + /opt/xensource/bin/cloud-clean-vlan.sh + + + Now prepare the upgrade by running the following on one XenServer host: + /opt/xensource/bin/cloud-prepare-upgrade.sh + If you see a message like "can't eject CD", log in to the VM and unmount the CD, + then run this script again. + + + Upload the hotfix to the XenServer hosts. Always start with the Xen pool master, + then the slaves. Using your favorite file copy utility (e.g. WinSCP), copy the + hotfixes to the host. Place them in a temporary folder such as /tmp. + On the Xen pool master, upload the hotfix with this command: + xe patch-upload file-name=XS602E003.xsupdate + Make a note of the output from this command, which is a UUID for the hotfix + file. You'll need it in another step later. + + (Optional) If you are applying other hotfixes as well, you can repeat the + commands in this section with the appropriate hotfix number. For example, + XS602E004.xsupdate. + + + + Manually live migrate all VMs on this host to another host. First, get a list of + the VMs on this host: + # xe vm-list + Then use this command to migrate each VM. Replace the example host name and VM + name with your own: + # xe vm-migrate live=true host=host-name + vm=VM-name + + Troubleshooting + If you see a message like "You attempted an operation on a VM which requires + PV drivers to be installed but the drivers were not detected," run: + /opt/xensource/bin/make_migratable.sh + b6cf79c8-02ee-050b-922f-49583d9f1a14. + + + + Apply the hotfix. First, get the UUID of this host: + # xe host-list + Then use the following command to apply the hotfix. Replace the example host + UUID with the current host ID, and replace the hotfix UUID with the output from the + patch-upload command you ran on this machine earlier. You can also get the hotfix + UUID by running xe patch-list. + xe patch-apply host-uuid=host-uuid uuid=hotfix-uuid + + + Copy the following files from the CloudStack Management Server to the + host. + + + + + + + Copy from here... + ...to here + + + + + /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/xenserver60/NFSSR.py + /opt/xensource/sm/NFSSR.py + + + /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/setupxenserver.sh + /opt/xensource/bin/setupxenserver.sh + + + /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/make_migratable.sh + /opt/xensource/bin/make_migratable.sh + + + + + + + (Only for hotfixes XS602E005 and XS602E007) You need to apply a new Cloud + Support Pack. + + + Download the CSP software onto the XenServer host from one of the following + links: + For hotfix XS602E005: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E005/56710/xe-phase-2/xenserver-cloud-supp.tgz + For hotfix XS602E007: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E007/57824/xe-phase-2/xenserver-cloud-supp.tgz + + + Extract the file: + # tar xf xenserver-cloud-supp.tgz + + + Run the following script: + # xe-install-supplemental-pack xenserver-cloud-supp.iso + + + If the XenServer host is part of a zone that uses basic networking, disable + Open vSwitch (OVS): + # xe-switch-network-backend bridge + + + + + Reboot this XenServer host. + + + Run the following: + /opt/xensource/bin/setupxenserver.sh + + If the message "mv: cannot stat `/etc/cron.daily/logrotate': No such file or + directory" appears, you can safely ignore it. + + + + Run the following: + for pbd in `xe pbd-list currently-attached=false| grep ^uuid | awk '{print $NF}'`; do xe pbd-plug uuid=$pbd ; + + + On each slave host in the Xen pool, repeat these steps, starting from "manually + live migrate VMs." + + + + + + Troubleshooting Tip + If passwords which you know to be valid appear not to work after upgrade, or other UI + issues are seen, try clearing your browser cache and reloading the UI page. + +
+
+ Upgrade from 2.2.14 to 4.1.0 + + + Ensure that you query your IPaddress usage records and process them; for example, + issue invoices for any usage that you have not yet billed users for. + Starting in 3.0.2, the usage record format for IP addresses is the same as the rest + of the usage types. Instead of a single record with the assignment and release dates, + separate records are generated per aggregation period with start and end dates. After + upgrading to 4.1.0, any existing IP address usage records in the old format + will no longer be available. + + + If you are using version 2.2.0 - 2.2.13, first upgrade to 2.2.14 by using the + instructions in the 2.2.14 Release Notes. + + KVM Hosts + If KVM hypervisor is used in your cloud, be sure you completed the step to insert + a valid username and password into the host_details table on each KVM node as + described in the 2.2.14 Release Notes. This step is critical, as the database will be + encrypted after the upgrade to 4.1.0. + + + + While running the 2.2.14 system, log in to the UI as root administrator. + + + Using the UI, add a new System VM template for each hypervisor type that is used in + your cloud. In each zone, add a system VM template for each hypervisor used in that + zone + + + In the left navigation bar, click Templates. + + + In Select view, click Templates. + + + Click Register template. + The Register template dialog box is displayed. + + + In the Register template dialog box, specify the following values depending on + the hypervisor type (do not change these): + + + + + + + Hypervisor + Description + + + + + XenServer + Name: systemvm-xenserver-4.1.0 + Description: systemvm-xenserver-4.1.0 + URL: + http://download.cloud.com/templates/acton/acton-systemvm-02062012.vhd.bz2 + Zone: Choose the zone where this hypervisor is used + Hypervisor: XenServer + Format: VHD + OS Type: Debian GNU/Linux 5.0 (32-bit) + Extractable: no + Password Enabled: no + Public: no + Featured: no + + + + KVM + Name: systemvm-kvm-4.1.0 + Description: systemvm-kvm-4.1.0 + URL: + http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2 + Zone: Choose the zone where this hypervisor is used + Hypervisor: KVM + Format: QCOW2 + OS Type: Debian GNU/Linux 5.0 (32-bit) + Extractable: no + Password Enabled: no + Public: no + Featured: no + + + + VMware + Name: systemvm-vmware-4.1.0 + Description: systemvm-vmware-4.1.0 + URL: + http://download.cloud.com/templates/burbank/burbank-systemvm-08012012.ova + Zone: Choose the zone where this hypervisor is used + Hypervisor: VMware + Format: OVA + OS Type: Debian GNU/Linux 5.0 (32-bit) + Extractable: no + Password Enabled: no + Public: no + Featured: no + + + + + + + + + + Watch the screen to be sure that the template downloads successfully and enters the + READY state. Do not proceed until this is successful + + + WARNING: If you use more than one type of + hypervisor in your cloud, be sure you have repeated these steps to download the system + VM template for each hypervisor type. Otherwise, the upgrade will fail. + + + Stop all Usage Servers if running. Run this on all Usage Server hosts. + # service cloud-usage stop + + + Stop the Management Servers. Run this on all Management Server hosts. + # service cloud-management stop + + + On the MySQL master, take a backup of the MySQL databases. We recommend performing + this step even in test upgrades. If there is an issue, this will assist with + debugging. + In the following commands, it is assumed that you have set the root password on the + database, which is a CloudStack recommended best practice. Substitute your own MySQL + root password. + # mysqldump -u root -pmysql_password cloud > cloud-backup.dmp + # mysqldump -u root -pmysql_password cloud_usage > cloud-usage-backup.dmp + + + + Either build RPM/DEB packages as detailed in the Installation Guide, or use one of + the community provided yum/apt repositories to gain access to the &PRODUCT; binaries. + + + + After you have configured an appropriate yum or apt repository, you may execute the + one of the following commands as appropriate for your environment in order to upgrade + &PRODUCT;: # yum update cloud-* + # apt-get update + # apt-get upgrade cloud-* + + You will, of course, have to agree to the changes suggested by Yum or APT. + + + If you have made changes to your existing copy of the file components.xml in your + previous-version CloudStack installation, the changes will be preserved in the upgrade. + However, you need to do the following steps to place these changes in a new version of + the file which is compatible with version 4.0.0-incubating. + + How will you know whether you need to do this? If the upgrade output in the + previous step included a message like the following, then some custom content was + found in your old components.xml, and you need to merge the two files: + + warning: /etc/cloud/management/components.xml created as /etc/cloud/management/components.xml.rpmnew + + + Make a backup copy of your + /etc/cloud/management/components.xml file. For + example: + # mv /etc/cloud/management/components.xml /etc/cloud/management/components.xml-backup + + + Copy /etc/cloud/management/components.xml.rpmnew to create + a new /etc/cloud/management/components.xml: + # cp -ap /etc/cloud/management/components.xml.rpmnew /etc/cloud/management/components.xml + + + Merge your changes from the backup file into the new components.xml file. + # vi /etc/cloud/management/components.xml + + + + + + If you have made changes to your existing copy of the + /etc/cloud/management/db.properties file in your previous-version + CloudStack installation, the changes will be preserved in the upgrade. However, you need + to do the following steps to place these changes in a new version of the file which is + compatible with version 4.0.0-incubating. + + + Make a backup copy of your file + /etc/cloud/management/db.properties. For example: + # mv /etc/cloud/management/db.properties /etc/cloud/management/db.properties-backup + + + Copy /etc/cloud/management/db.properties.rpmnew to create a + new /etc/cloud/management/db.properties: + # cp -ap /etc/cloud/management/db.properties.rpmnew etc/cloud/management/db.properties + + + Merge your changes from the backup file into the new db.properties file. + # vi /etc/cloud/management/db.properties + + + + + On the management server node, run the following command. It is recommended that you + use the command-line flags to provide your own encryption keys. See Password and Key + Encryption in the Installation Guide. + # cloud-setup-encryption -e encryption_type -m management_server_key -k database_key + When used without arguments, as in the following example, the default encryption + type and keys will be used: + + + (Optional) For encryption_type, use file or web to indicate the technique used + to pass in the database encryption password. Default: file. + + + (Optional) For management_server_key, substitute the default key that is used to + encrypt confidential parameters in the properties file. Default: password. It is + highly recommended that you replace this with a more secure value + + + (Optional) For database_key, substitute the default key that is used to encrypt + confidential parameters in the CloudStack database. Default: password. It is highly + recommended that you replace this with a more secure value. + + + + + Repeat steps 10 - 14 on every management server node. If you provided your own + encryption key in step 14, use the same key on all other management servers. + + + Start the first Management Server. Do not start any other Management Server nodes + yet. + # 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. + + + Start all Usage Servers (if they were running on your previous version). Perform + this on each Usage Server host. + # service cloud-usage start + + + (KVM only) Additional steps are required for each KVM host. These steps will not + affect running guests in the cloud. These steps are required only for clouds using KVM + as hosts and only on the KVM hosts. + + + Configure your CloudStack package repositories as outlined in the Installation + Guide + + + Stop the running agent. + # service cloud-agent stop + + + Update the agent software with one of the following command sets as + appropriate. + # yum update cloud-* + + # apt-get update + # apt-get upgrade cloud-* + + + + Start the agent. + # service cloud-agent start + + + Copy the contents of the agent.properties file to the new + agent.properties file by using the following command + sed -i 's/com.cloud.agent.resource.computing.LibvirtComputingResource/com.cloud.hypervisor.kvm.resource.LibvirtComputingResource/g' /etc/cloud/agent/agent.properties + + + Start the cloud agent and cloud management services. + + + When the Management Server is up and running, log in to the CloudStack UI and + restart the virtual router for proper functioning of all the features. + + + + + Log in to the CloudStack UI as admin, and check the status of the hosts. All hosts + should come to Up state (except those that you know to be offline). You may need to wait + 20 or 30 minutes, depending on the number of hosts. + Do not proceed to the next step until the hosts show in the Up state. If the hosts + do not come to the Up state, contact support. + + + Run the following script to stop, then start, all Secondary Storage VMs, Console + Proxy VMs, and virtual routers. + + + Run the command once on one management server. Substitute your own IP address of + the MySQL instance, the MySQL user to connect as, and the password to use for that + user. In addition to those parameters, provide the "-c" and "-r" arguments. For + example: + # nohup cloud-sysvmadm -d 192.168.1.5 -u cloud -p password -c -r > sysvm.log 2>&1 & + # tail -f sysvm.log + This might take up to an hour or more to run, depending on the number of + accounts in the system. + + + After the script terminates, check the log to verify correct execution: + # 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). + + + + + + If you would like additional confirmation that the new system VM templates were + correctly applied when these system VMs were rebooted, SSH into the System VM and check + the version. + Use one of the following techniques, depending on the hypervisor. + + XenServer or KVM: + SSH in by using the link local IP address of the system VM. For example, in the + command below, substitute your own path to the private key used to log in to the + system VM and your own link local IP. + + Run the following commands on the XenServer or KVM host on which the system VM is + present: + # ssh -i private-key-path link-local-ip -p 3922 + # cat /etc/cloudstack-release + The output should be like the following: + Cloudstack Release 4.0.0-incubating Mon Oct 9 15:10:04 PST 2012 + + ESXi + SSH in using the private IP address of the system VM. For example, in the command + below, substitute your own path to the private key used to log in to the system VM and + your own private IP. + + Run the following commands on the Management Server: + # ssh -i private-key-path private-ip -p 3922 + # cat /etc/cloudstack-release + + The output should be like the following: + Cloudstack Release 4.0.0-incubating Mon Oct 9 15:10:04 PST 2012 + + + If needed, upgrade all Citrix XenServer hypervisor hosts in your cloud to a version + supported by CloudStack 4.0.0-incubating. The supported versions are XenServer 5.6 SP2 + and 6.0.2. Instructions for upgrade can be found in the CloudStack 4.0.0-incubating + Installation Guide. + + + Apply the XenServer hotfix XS602E003 (and any other needed hotfixes) to XenServer + v6.0.2 hypervisor hosts. + + + Disconnect the XenServer cluster from CloudStack. + In the left navigation bar of the CloudStack UI, select Infrastructure. Under + Clusters, click View All. Select the XenServer cluster and click Actions - + Unmanage. + This may fail if there are hosts not in one of the states Up, Down, + Disconnected, or Alert. You may need to fix that before unmanaging this + cluster. + Wait until the status of the cluster has reached Unmanaged. Use the CloudStack + UI to check on the status. When the cluster is in the unmanaged state, there is no + connection to the hosts in the cluster. + + + To clean up the VLAN, log in to one XenServer host and run: + /opt/xensource/bin/cloud-clean-vlan.sh + + + Prepare the upgrade by running the following on one XenServer host: + /opt/xensource/bin/cloud-prepare-upgrade.sh + If you see a message like "can't eject CD", log in to the VM and umount the CD, + then run this script again. + + + Upload the hotfix to the XenServer hosts. Always start with the Xen pool master, + then the slaves. Using your favorite file copy utility (e.g. WinSCP), copy the + hotfixes to the host. Place them in a temporary folder such as /root or /tmp. + On the Xen pool master, upload the hotfix with this command: + xe patch-upload file-name=XS602E003.xsupdate + Make a note of the output from this command, which is a UUID for the hotfix + file. You'll need it in another step later. + + (Optional) If you are applying other hotfixes as well, you can repeat the + commands in this section with the appropriate hotfix number. For example, + XS602E004.xsupdate. + + + + Manually live migrate all VMs on this host to another host. First, get a list of + the VMs on this host: + # xe vm-list + Then use this command to migrate each VM. Replace the example host name and VM + name with your own: + # xe vm-migrate live=true host=host-name vm=VM-name + + Troubleshooting + If you see a message like "You attempted an operation on a VM which requires + PV drivers to be installed but the drivers were not detected," run: + /opt/xensource/bin/make_migratable.sh + b6cf79c8-02ee-050b-922f-49583d9f1a14. + + + + Apply the hotfix. First, get the UUID of this host: + # xe host-list + Then use the following command to apply the hotfix. Replace the example host + UUID with the current host ID, and replace the hotfix UUID with the output from the + patch-upload command you ran on this machine earlier. You can also get the hotfix + UUID by running xe patch-list. + xe patch-apply host-uuid=host-uuid + uuid=hotfix-uuid + + + Copy the following files from the CloudStack Management Server to the + host. + + + + + + + Copy from here... + ...to here + + + + + /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/xenserver60/NFSSR.py + /opt/xensource/sm/NFSSR.py + + + /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/setupxenserver.sh + /opt/xensource/bin/setupxenserver.sh + + + /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/make_migratable.sh + /opt/xensource/bin/make_migratable.sh + + + + + + + (Only for hotfixes XS602E005 and XS602E007) You need to apply a new Cloud + Support Pack. + + + Download the CSP software onto the XenServer host from one of the following + links: + For hotfix XS602E005: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E005/56710/xe-phase-2/xenserver-cloud-supp.tgz + For hotfix XS602E007: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E007/57824/xe-phase-2/xenserver-cloud-supp.tgz + + + Extract the file: + # tar xf xenserver-cloud-supp.tgz + + + Run the following script: + # xe-install-supplemental-pack + xenserver-cloud-supp.iso + + + If the XenServer host is part of a zone that uses basic networking, disable + Open vSwitch (OVS): + # xe-switch-network-backend bridge + + + + + Reboot this XenServer host. + + + Run the following: + /opt/xensource/bin/setupxenserver.sh + + If the message "mv: cannot stat `/etc/cron.daily/logrotate': No such file or + directory" appears, you can safely ignore it. + + + + Run the following: + for pbd in `xe pbd-list currently-attached=false| grep ^uuid | awk + '{print $NF}'`; do xe pbd-plug uuid=$pbd ; + + + + On each slave host in the Xen pool, repeat these steps, starting from "manually + live migrate VMs." + + + + +
+
+ + Version 4.1.0 +
+ What’s New in 4.1 + Apache CloudStack 4.1.0 includes many new features. This section covers the most prominent new features and changes. +
+
+ Issues Fixed in 4.1.0 + Apache CloudStack uses Jira + to track its issues. All new features and bugs for 4.1.0 have been tracked in Jira, and have + a standard naming convention of "CLOUDSTACK-NNNN" where "NNNN" is the issue number. + This section includes a summary of known issues against 4.0.0 that were fixed in 4.1.0. + - - - - - Copy from here... - ...to here - - - - - /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/xenserver60/NFSSR.py - /opt/xensource/sm/NFSSR.py - - - /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/setupxenserver.sh - /opt/xensource/bin/setupxenserver.sh - - - /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/make_migratable.sh - /opt/xensource/bin/make_migratable.sh - - + + + + + + Defect + + + Description + + + + + + CS-16135 + Creating volumes after upgrading from snapshot taken in 2.2.14 no longer + deletes the snapshot physically from the secondary storage. + + - - - - (Only for hotfixes XS602E005 and XS602E007) You need to apply a new Cloud - Support Pack. - - - Download the CSP software onto the XenServer host from one of the following - links: - For hotfix XS602E005: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E005/56710/xe-phase-2/xenserver-cloud-supp.tgz - For hotfix XS602E007: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E007/57824/xe-phase-2/xenserver-cloud-supp.tgz - - - Extract the file: - # tar xf xenserver-cloud-supp.tgz - - - Run the following script: - # xe-install-supplemental-pack - xenserver-cloud-supp.iso - - - If the XenServer host is part of a zone that uses basic networking, disable - Open vSwitch (OVS): - # xe-switch-network-backend bridge - - - - - Reboot this XenServer host. - - - Run the following: - /opt/xensource/bin/setupxenserver.sh - - If the message "mv: cannot stat `/etc/cron.daily/logrotate': No such file or - directory" appears, you can safely ignore it. - - - - Run the following: - for pbd in `xe pbd-list currently-attached=false| grep ^uuid | awk - '{print $NF}'`; do xe pbd-plug uuid=$pbd ; - - - - On each slave host in the Xen pool, repeat these steps, starting from "manually - live migrate VMs." - - - - -
-
- - Version 4.1.0 -
- What’s New in 4.1 - Apache CloudStack 4.1.0 includes many new features. This section covers the most prominent new features and changes. -
-
- Issues Fixed in 4.1.0 - Apache CloudStack uses Jira - to track its issues. All new features and bugs for 4.1.0 have been tracked in Jira, and have - a standard naming convention of "CLOUDSTACK-NNNN" where "NNNN" is the issue number. - This section includes a summary of known issues against 4.0.0 that were fixed in 4.1.0. - - - - - - - - Defect - - - Description - - - - - - CS-16135 - Creating volumes after upgrading from snapshot taken in 2.2.14 no longer - deletes the snapshot physically from the secondary storage. - - - - -
-
- Known Issues in 4.1.0 - - - - - - - - Issue ID - - - Description - - - - - - CLOUDSTACK-1747 - mvn deploydb only creates 4.0 DB, not 4.1 - Due to tooling changes between 4.1 and 4.2, CloudStack's database is created using the 4.0 schema and updated to the 4.1 schema when the management server starts for the first time. It's OK to see the same schema if the management server has not started yet. - - - - CLOUDSTACK-301 - Nexus 1000v DVS integration is not functional - This source code release includes some partial functionality to support the - Cisco Nexus 1000v Distributed Virtual Switch within a VMware hypervisor - environment. The functionality is not complete at this time. - - - - - -
-
- + +
+
+ Known Issues in 4.1.0 + + + + + + + + Issue ID + + + Description + + + + + + CLOUDSTACK-1747 + mvn deploydb only creates 4.0 DB, not 4.1 + Due to tooling changes between 4.1 and 4.2, CloudStack's database is created using the 4.0 schema and updated to the 4.1 schema when the management server starts for the first time. It's OK to see the same schema if the management server has not started yet. + + + + CLOUDSTACK-1824 + Service CloudStack-Management is being displayed as cloud-management service + Many scripts and text entries have references to cloud-management rather than cloudstack-management due to the changeover between 4.0 and 4.1 to rename services. This is a minor issue and should be corrected by 4.2. + + + + + CLOUDSTACK-1824 + Service CloudStack-Management is being displayed as cloud-management service + + + + + CLOUDSTACK-1510 + + + NPE when primary storage is added with wrong path + + + + + CLOUDSTACK-1428 + + + [UI] Instance which are created without display name are not visible when added to LB + + + + + CLOUDSTACK-1306 + + + Better Error message when trying to deploy Vm by passing static Ipv4 addresses that are assigned to another VM/IP4 address is outside the iprange. + + + + + CLOUDSTACK-1236 + + + Warning while adding Xen 6.1 host [Unable to create local link network] + + + + + CLOUDSTACK-969 + + + api: zone response lists vlan in it as "vlan range of zone" but the vlan belongs to physical network + + + + + CLOUDSTACK-963 + + + [cloud.utils.AnnotationHelper] class java.lang.Stringdoes not have a Table annotation + + + + + CLOUDSTACK-458 + + + xen:snapshots:Storage gc fail to clean the failed snapshot images from secondarystorage + + + + + CLOUDSTACK-315 + + + Infrastructure view does not show capacity values + + + + + CLOUDSTACK-300 + + + Creation of compute offering allow combination of local storage + HA + + + + + CLOUDSTACK-282 + + + Virtual Routers do not properly resolve DNS SRV Records + + + + + CLOUDSTACK-276 + + + SSVM ID is exposed in the Error Message thrown by AddTrafficType API + + + + + CLOUDSTACK-270 + + + Ui should not ask for a vlan range if the physical network isolation type is not VLAN + + + + + CLOUDSTACK-245 + + + VPC ACLs are not stored and programmed consistently + + + + + CLOUDSTACK-231 + + + Tag creation using special charecters + + + + + CLOUDSTACK-124 + + + NetworkGarbageCollector not cleaning up networks + + + + + CLOUDSTACK-62 + + + console proxy does not support any keymaps besides us, jp + + + + + +
+
+
diff --git a/docs/en-US/add-clusters-vsphere.xml b/docs/en-US/add-clusters-vsphere.xml index ca36ee108c4..c3a0902be8f 100644 --- a/docs/en-US/add-clusters-vsphere.xml +++ b/docs/en-US/add-clusters-vsphere.xml @@ -71,7 +71,7 @@ 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. @@ -81,8 +81,6 @@ addcluster.png: add a cluster - There might be a slight delay while the cluster is provisioned. It will automatically - display in the UI. Cluster Name: Enter the name of the cluster you @@ -136,7 +134,7 @@ Nexus dvSwitch Username: The username required to access the Nexus VSM - applicance. + appliance. Nexus dvSwitch Password: The password associated with the username specified @@ -151,7 +149,8 @@ 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 + 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: @@ -161,7 +160,7 @@ Nexus dvSwitch Username: The username required to access the Nexus VSM - applicance. + appliance. Nexus dvSwitch Password: The password associated with the username specified 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/global-config.xml b/docs/en-US/global-config.xml index 2f6ad105c0d..11952c382ac 100644 --- a/docs/en-US/global-config.xml +++ b/docs/en-US/global-config.xml @@ -19,6 +19,8 @@ under the License. --> + Global Configuration Parameters +
Setting Global Configuration Parameters &PRODUCT; provides parameters that you can set to control many aspects of the cloud. When &PRODUCT; is first installed, and periodically thereafter, you might need to modify these @@ -51,4 +53,81 @@ must click the name of the hypervisor first to display the editing screen. +
+
+ About Global Configuration Parameters + &PRODUCT; provides a variety of settings you can use to set limits, configure features, + and enable or disable features in the cloud. Once your Management Server is running, you might + need to set some of these global configuration parameters, depending on what optional features + you are setting up. + To modify global configuration parameters, use the steps in "Setting Global Configuration + Parameters." + The documentation for each &PRODUCT; feature should direct you to the names of the applicable + parameters. Many of them are discussed in the &PRODUCT; Administration Guide. The following table + shows a few of the more useful parameters. + + + + + + + Field + Value + + + + + management.network.cidr + A CIDR that describes the network that the management CIDRs reside on. This + variable must be set for deployments that use vSphere. It is recommended to be set for + other deployments as well. Example: 192.168.3.0/24. + + + xen.setup.multipath + For XenServer nodes, this is a true/false variable that instructs CloudStack to + enable iSCSI multipath on the XenServer Hosts when they are added. This defaults to false. + Set it to true if you would like CloudStack to enable multipath. + If this is true for a NFS-based deployment multipath will still be enabled on the + XenServer host. However, this does not impact NFS operation and is harmless. + + + secstorage.allowed.internal.sites + This is used to protect your internal network from rogue attempts to download + arbitrary files using the template download feature. This is a comma-separated list of CIDRs. + If a requested URL matches any of these CIDRs the Secondary Storage VM will use the private + network interface to fetch the URL. Other URLs will go through the public interface. + We suggest you set this to 1 or 2 hardened internal machines where you keep your templates. + For example, set it to 192.168.1.66/32. + + + use.local.storage + Determines whether CloudStack will use storage that is local to the Host for data + disks, templates, and snapshots. By default CloudStack will not use this storage. You should + change this to true if you want to use local storage and you understand the reliability and + feature drawbacks to choosing local storage. + + + host + This is the IP address of the Management Server. If you are using multiple + Management Servers you should enter a load balanced IP address that is reachable via + the private network. + + + default.page.size + Maximum number of items per page that can be returned by a CloudStack API command. + The limit applies at the cloud level and can vary from cloud to cloud. You can override this + with a lower value on a particular API call by using the page and pagesize API command parameters. + For more information, see the Developer's Guide. Default: 500. + + + ha.tag + The label you want to use throughout the cloud to designate certain hosts as dedicated + HA hosts. These hosts will be used only for HA-enabled VMs that are restarting due to the failure + of another host. For example, you could set this to ha_host. Specify the ha.tag value as a host tag + when you add a new host to the cloud. + + + + +
diff --git a/docs/en-US/hypervisor-host-install-firewall.xml b/docs/en-US/hypervisor-host-install-firewall.xml index ae82fc47afa..c6658731819 100644 --- a/docs/en-US/hypervisor-host-install-firewall.xml +++ b/docs/en-US/hypervisor-host-install-firewall.xml @@ -34,7 +34,7 @@ 49152 - 49216 (libvirt live migration) It depends on the firewall you are using how to open these ports. Below you'll find examples how to open these ports in RHEL/CentOS and Ubuntu. -
+
Open ports in RHEL/CentOS RHEL and CentOS use iptables for firewalling the system, you can open extra ports by executing the following iptable commands: $ iptables -I INPUT -p tcp -m tcp --dport 22 -j ACCEPT @@ -45,7 +45,7 @@ These iptable settings are not persistent accross reboots, we have to save them first. $ iptables-save > /etc/sysconfig/iptables
-
+
Open ports in Ubuntu The default firewall under Ubuntu is UFW (Uncomplicated FireWall), which is a Python wrapper around iptables. To open the required ports, execute the following commands: 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: In order to forward traffic to your instances you will need at least two bridges: public and private. By default these bridges are called cloudbr0 and cloudbr1, but you do have to make sure they are available on each hypervisor. The most important factor is that you keep the configuration consistent on all your hypervisors. -
+
Network example There are many ways to configure your network. In the Basic networking mode you should have two (V)LAN's, one for your private network and one for the public network. We assume that the hypervisor has one NIC (eth0) with three tagged VLAN's: @@ -41,16 +41,16 @@ On VLAN 100 we give the Hypervisor the IP-Address 192.168.42.11/24 with the gateway 192.168.42.1 The Hypervisor and Management server don't have to be in the same subnet!
-
+
Configuring the network bridges It depends on the distribution you are using how to configure these, below you'll find examples for RHEL/CentOS and Ubuntu. The goal is to have two bridges called 'cloudbr0' and 'cloudbr1' after this section. This should be used as a guideline only. The exact configuration will depend on your network layout. -
+
Configure in RHEL or CentOS 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 With this configuration you should be able to restart the network, although a reboot is recommended to see if everything works properly. Make sure you have an alternative way like IPMI or ILO to reach the machine in case you made a configuration error and the network stops functioning!
-
+
Configure in Ubuntu All the required packages were installed when you installed libvirt, so we only have to configure the network. vi /etc/network/interfaces diff --git a/docs/en-US/hypervisor-installation.xml b/docs/en-US/hypervisor-installation.xml index b0fc9f46ddb..5ee7dea696a 100644 --- a/docs/en-US/hypervisor-installation.xml +++ b/docs/en-US/hypervisor-installation.xml @@ -28,4 +28,5 @@ + diff --git a/docs/en-US/lxc-install.xml b/docs/en-US/lxc-install.xml new file mode 100644 index 00000000000..a80c18afdd6 --- /dev/null +++ b/docs/en-US/lxc-install.xml @@ -0,0 +1,110 @@ + + + %BOOK_ENTITIES; + ]> + + + +
+ LXC Installation and Configuration +
+ System Requirements for LXC Hosts + LXC requires the Linux kernel cgroups functionality which is available starting 2.6.24. Although you are not required to run these distributions, the following are recommended: + + CentOS / RHEL: 6.3 + Ubuntu: 12.04(.1) + + The main requirement for LXC hypervisors is the libvirt and Qemu version. No matter what + Linux distribution you are using, make sure the following requirements are met: + + libvirt: 1.0.0 or higher + Qemu/KVM: 1.0 or higher + + The default bridge in &PRODUCT; is the Linux native bridge implementation (bridge module). &PRODUCT; includes an option to work with OpenVswitch, the requirements are listed below + + libvirt: 1.0.0 or higher + openvswitch: 1.7.1 or higher + + In addition, the following hardware requirements apply: + + Within a single cluster, the hosts must be of the same distribution version. + All hosts within a cluster must be homogenous. The CPUs must be of the same type, count, and feature flags. + Must support HVM (Intel-VT or AMD-V enabled) + 64-bit x86 CPU (more cores results in better performance) + 4 GB of memory + At least 1 NIC + When you deploy &PRODUCT;, the hypervisor host must not have any VMs already running + +
+
+ LXC Installation Overview + LXC does not have any native system VMs, instead KVM will be used to run system VMs. This means that your host will need to support both LXC and KVM, thus most of the installation and configuration will be identical to the KVM installation. The material in this section doesn't duplicate KVM installation docs. It provides the &PRODUCT;-specific steps that are needed to prepare a KVM host to work with &PRODUCT;. + Before continuing, make sure that you have applied the latest updates to your host. + It is NOT recommended to run services on this host not controlled by &PRODUCT;. + The procedure for installing an LXC Host is: + + Prepare the Operating System + Install and configure libvirt + Configure Security Policies (AppArmor and SELinux) + Install and configure the Agent + +
+
+ +
+
+ Install and configure the Agent + To manage LXC instances on the host &PRODUCT; uses a Agent. This Agent communicates with the Management server and controls all the instances on the host. + First we start by installing the agent: + In RHEL or CentOS: + $ yum install cloud-agent + In Ubuntu: + $ apt-get install cloud-agent + Next step is to update the Agent configuration setttings. The settings are in /etc/cloudstack/agent/agent.properties + + + Set the Agent to run in LXC mode: + hypervisor.type=lxc + + + Optional: If you would like to use direct networking (instead of the default bridge networking), configure these lines: + libvirt.vif.driver=com.cloud.hypervisor.kvm.resource.DirectVifDriver + network.direct.source.mode=private + network.direct.device=eth0 + + + The host is now ready to be added to a cluster. This is covered in a later section, see . It is recommended that you continue to read the documentation before adding the host! +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
diff --git a/docs/en-US/lxc-topology-req.xml b/docs/en-US/lxc-topology-req.xml new file mode 100644 index 00000000000..315863dd34c --- /dev/null +++ b/docs/en-US/lxc-topology-req.xml @@ -0,0 +1,24 @@ + + +%BOOK_ENTITIES; +]> + +
+ LXC Topology Requirements + The Management Servers communicate with LXC hosts on port 22 (ssh). +
diff --git a/docs/en-US/management-server-install-prepare-os.xml b/docs/en-US/management-server-install-prepare-os.xml index ef78731e81a..02453a0b207 100644 --- a/docs/en-US/management-server-install-prepare-os.xml +++ b/docs/en-US/management-server-install-prepare-os.xml @@ -30,7 +30,7 @@ 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-install-systemvm.xml b/docs/en-US/management-server-install-systemvm.xml index 8dc73deb992..928b95618fa 100644 --- a/docs/en-US/management-server-install-systemvm.xml +++ b/docs/en-US/management-server-install-systemvm.xml @@ -53,6 +53,10 @@ For KVM: # /usr/lib64/cloud/common/scripts/storage/secondary/cloud-install-sys-tmplt -m /mnt/secondary -u http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2 -h kvm -s <optional-management-server-secret-key> -F + + For LXC: + # /usr/lib64/cloud/common/scripts/storage/secondary/cloud-install-sys-tmplt -m /mnt/secondary -u http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2 -h lxc -s <optional-management-server-secret-key> -F + On Ubuntu, use the following path instead: # /usr/lib/cloud/common/scripts/storage/secondary/cloud-install-sys-tmplt 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 0e497dd33f1..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: @@ -68,6 +68,7 @@ +
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/prepare-system-vm-template.xml b/docs/en-US/prepare-system-vm-template.xml index b53a509b4a1..35cc7e979bc 100644 --- a/docs/en-US/prepare-system-vm-template.xml +++ b/docs/en-US/prepare-system-vm-template.xml @@ -60,6 +60,10 @@ For KVM: # /usr/lib64/cloud/common/scripts/storage/secondary/cloud-install-sys-tmplt -m /mnt/secondary -u http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2 -h kvm -s <optional-management-server-secret-key> -F + + For LXC: + # /usr/lib64/cloud/common/scripts/storage/secondary/cloud-install-sys-tmplt -m /mnt/secondary -u http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2 -h lxc -s <optional-management-server-secret-key> -F + diff --git a/docs/en-US/topology-req.xml b/docs/en-US/topology-req.xml index 65c9c2ea5c6..75fe69b41a4 100644 --- a/docs/en-US/topology-req.xml +++ b/docs/en-US/topology-req.xml @@ -28,4 +28,5 @@ -
+ +
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 index 3e1e37c0941..3468c1bea4e 100644 --- a/docs/en-US/vmware-cluster-config-dvswitch.xml +++ b/docs/en-US/vmware-cluster-config-dvswitch.xml @@ -47,11 +47,12 @@ 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 one for Public traffic. + switches, only one can be used for Guest traffic and another one for Public + traffic. - Management and Storage network does not support VDS and use Standard Switch for these - networks. + Management and Storage network does not support VDS. Therefore, use Standard Switch + for these networks.
@@ -64,7 +65,7 @@ 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 configuring virtual networks in a deployment with a mix of Virtual + &PRODUCT; supports orchestration of virtual networks in a deployment with a mix of Virtual Distributed Switch, Standard Virtual Switch and Nexus 1000v Virtual Switch.
@@ -100,8 +101,8 @@ vCenter Host - Enter the host name or the IP address of the vCenter host where you have - deployed the Nexus virtual switch. + Enter the name or the IP address of the vCenter host where you have deployed the VMware + VDS. vCenter User name @@ -125,13 +126,13 @@ 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. + 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 - Specify a name to identify the switch. + Name of virtual switch to be used for the public traffic. Override Guest Traffic @@ -141,24 +142,24 @@ 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. + 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 - Specify a name to identify the switch. + Name of virtual switch to be used for guest traffic.
- Removing Nexus Virtual Switch + Removing VMware Virtual Switch - In the vCenter datacenter that is served by the VMware dvSwitch, ensure that you - delete all the hosts in the corresponding cluster. + 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. diff --git a/docs/en-US/vmware-install.xml b/docs/en-US/vmware-install.xml index 81c9a49b038..fd88fc7c0cb 100644 --- a/docs/en-US/vmware-install.xml +++ b/docs/en-US/vmware-install.xml @@ -1,5 +1,5 @@ - %BOOK_ENTITIES; ]> @@ -11,7 +11,9 @@ to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 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/docs/publican-cloudstack/defaults.cfg b/docs/publican-cloudstack/defaults.cfg index 9e27bdd309d..b288b33af47 100644 --- a/docs/publican-cloudstack/defaults.cfg +++ b/docs/publican-cloudstack/defaults.cfg @@ -16,6 +16,6 @@ # specific language governing permissions and limitations # under the License. -doc_url: "http://incubator.apache.org/cloudstack/docs" -prod_url: "http://cloudstack.org" +doc_url: "http://cloudstack.apache.org/docs" +prod_url: "http://cloudstack.apache.org" 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 ed91526fe85..ec813b2e998 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 @@ -212,7 +212,7 @@ public class VMEntityManagerImpl implements VMEntityManager { } DataCenterDeployment reservedPlan = new DataCenterDeployment(vm.getDataCenterId(), vmReservation.getPodId(), vmReservation.getClusterId(), - vmReservation.getHostId(), poolId , null); + vmReservation.getHostId(), null , null); try{ VMInstanceVO vmDeployed = _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), reservedPlan); }catch(Exception ex){ 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..514c0b012cf 100755 --- a/patches/systemvm/debian/config/etc/init.d/cloud-early-config +++ b/patches/systemvm/debian/config/etc/init.d/cloud-early-config @@ -704,7 +704,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/patches/systemvm/debian/config/root/edithosts.sh b/patches/systemvm/debian/config/root/edithosts.sh index 9f21f206172..1f98fbf96ae 100755 --- a/patches/systemvm/debian/config/root/edithosts.sh +++ b/patches/systemvm/debian/config/root/edithosts.sh @@ -200,7 +200,8 @@ fi pid=$(pidof dnsmasq) if [ "$pid" != "" ] then - service dnsmasq restart + #service dnsmasq restart + kill -HUP $pid else if [ $no_redundant -eq 1 ] then 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/plugins/network-elements/netscaler/pom.xml b/plugins/network-elements/netscaler/pom.xml index 1eb73a236dc..d5c7cdc5bcc 100644 --- a/plugins/network-elements/netscaler/pom.xml +++ b/plugins/network-elements/netscaler/pom.xml @@ -28,9 +28,9 @@ - com.cloud.com.citrix - netscaler - 1.0 + com.citrix.netscaler.nitro + nitro + 10.0.e com.cloud.com.citrix 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/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 45d89541379..651a8bed110 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -995,6 +995,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 0f018ddb83f..1647cf7dba9 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 (host == null) { 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/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index 3948f2ecf73..dbd36ae0cf7 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -179,6 +179,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis private final ScheduledExecutorService _executor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("VpcChecker")); private List vpcElements = null; private final List nonSupportedServices = Arrays.asList(Service.SecurityGroup, Service.Firewall); + private final List supportedProviders = Arrays.asList(Provider.VPCVirtualRouter, Provider.NiciraNvp); int _cleanupInterval; int _maxNetworks; @@ -1054,9 +1055,9 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis //1) in current release, only vpc provider is supported by Vpc offering List providers = _ntwkModel.getNtwkOffDistinctProviders(guestNtwkOff.getId()); for (Provider provider : providers) { - if (provider != Provider.VPCVirtualRouter) { - throw new InvalidParameterValueException("Only provider of type " + Provider.VPCVirtualRouter.getName() - + " is supported for network offering that can be used in VPC"); + if (!supportedProviders.contains(provider) ) { + throw new InvalidParameterValueException("Provider of type " + provider.getName() + + " is not supported for network offerings that can be used in VPC"); } } 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 7ed6f3f27d6..5d7a2106e6a 100755 --- a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java +++ b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java @@ -37,21 +37,17 @@ import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; - import com.cloud.agent.api.storage.DeleteTemplateCommand; import com.cloud.agent.api.storage.DeleteVolumeCommand; 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.agent.api.storage.DownloadProgressCommand.RequestType; - import com.cloud.agent.api.storage.DownloadProgressCommand; +import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType; import com.cloud.agent.api.storage.ListTemplateAnswer; import com.cloud.agent.api.storage.ListTemplateCommand; import com.cloud.agent.api.storage.ListVolumeAnswer; import com.cloud.agent.api.storage.ListVolumeCommand; - import com.cloud.agent.manager.Commands; import com.cloud.alert.AlertManager; import com.cloud.configuration.Config; @@ -72,13 +68,12 @@ import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.resource.ResourceManager; import com.cloud.storage.Storage.ImageFormat; - import com.cloud.storage.StorageManager; import com.cloud.storage.SwiftVO; import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.VMTemplateStorageResourceAssoc; -import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateZoneVO; import com.cloud.storage.VolumeHostVO; import com.cloud.storage.VolumeVO; @@ -91,7 +86,6 @@ import com.cloud.storage.dao.VMTemplateSwiftDao; import com.cloud.storage.dao.VMTemplateZoneDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.storage.dao.VolumeHostDao; - import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.storage.swift.SwiftManager; import com.cloud.storage.template.TemplateConstants; @@ -284,10 +278,10 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor String sourceChecksum = this.templateMgr.getChecksum(srcTmpltHost.getHostId(), srcTmpltHost.getInstallPath()); DownloadCommand dcmd = new DownloadCommand(destServer.getStorageUrl(), url, template, TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd, maxTemplateSizeInBytes); - dcmd.setProxy(getHttpProxy()); if (downloadJobExists) { dcmd = new DownloadProgressCommand(dcmd, destTmpltHost.getJobId(), RequestType.GET_OR_RESTART); } + dcmd.setProxy(getHttpProxy()); dcmd.setChecksum(sourceChecksum); // We need to set the checksum as the source template might be a compressed url and have cksum for compressed image. Bug #10775 HostVO ssAhost = _ssvmMgr.pickSsvmHost(destServer); if( ssAhost == null ) { @@ -369,10 +363,10 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor start(); DownloadCommand dcmd = new DownloadCommand(secUrl, template, maxTemplateSizeInBytes); - dcmd.setProxy(getHttpProxy()); if (downloadJobExists) { dcmd = new DownloadProgressCommand(dcmd, vmTemplateHost.getJobId(), RequestType.GET_OR_RESTART); } + dcmd.setProxy(getHttpProxy()); if (vmTemplateHost.isCopy()) { dcmd.setCreds(TemplateConstants.DEFAULT_HTTP_AUTH_USER, _copyAuthPasswd); } @@ -458,12 +452,11 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor if(volumeHost != null) { start(); DownloadCommand dcmd = new DownloadCommand(secUrl, volume, maxVolumeSizeInBytes, checkSum, url, format); - dcmd.setProxy(getHttpProxy()); if (downloadJobExists) { dcmd = new DownloadProgressCommand(dcmd, volumeHost.getJobId(), RequestType.GET_OR_RESTART); dcmd.setResourceType(ResourceType.VOLUME); } - + dcmd.setProxy(getHttpProxy()); HostVO ssvm = _ssvmMgr.pickSsvmHost(sserver); if( ssvm == null ) { s_logger.warn("There is no secondary storage VM for secondary storage host " + sserver.getName()); @@ -858,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(""); } @@ -918,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()); @@ -971,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 12ada667c21..fe714c530b9 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -1991,6 +1991,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M } @Override @DB + @ActionEvent(eventType = EventTypes.EVENT_REGISTER_FOR_SECRET_API_KEY, eventDescription = "register for the developer API keys") public String[] createApiKeyAndSecretKey(RegisterCmd cmd) { Long userId = cmd.getId(); @@ -2144,7 +2145,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) { @@ -2160,10 +2160,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) { @@ -2171,7 +2174,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 7d290f2c911..d281e5b4dc8 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -225,7 +225,9 @@ import com.cloud.vm.dao.UserVmCloneSettingDao; import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.UserVmDetailsDao; import com.cloud.vm.dao.VMInstanceDao; +import com.cloud.vm.snapshot.VMSnapshot; import com.cloud.vm.snapshot.VMSnapshotManager; +import com.cloud.vm.snapshot.VMSnapshotVO; import com.cloud.vm.snapshot.dao.VMSnapshotDao; @Local(value = { UserVmManager.class, UserVmService.class }) @@ -707,22 +709,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } } - - - - private void checkVMSnapshots(UserVmVO vm, Long volumeId, boolean attach) { - // Check that if vm has any VM snapshot - /*Long vmId = vm.getId(); - List listSnapshot = _vmSnapshotDao.listByInstanceId(vmId, - VMSnapshot.State.Ready, VMSnapshot.State.Creating, VMSnapshot.State.Reverting, VMSnapshot.State.Expunging); - if (listSnapshot != null && listSnapshot.size() != 0) { - throw new InvalidParameterValueException( - "The VM has VM snapshots, do not allowed to attach volume. Please delete the VM snapshots first."); - }*/ - } - - - private UserVm rebootVirtualMachine(long userId, long vmId) throws InsufficientCapacityException, ResourceUnavailableException { UserVmVO vm = _vmDao.findById(vmId); @@ -785,7 +771,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use _itMgr.checkIfCanUpgrade(vmInstance, svcOffId); // remove diskAndMemory VM snapshots - /* List vmSnapshots = _vmSnapshotDao.findByVm(vmId); + List vmSnapshots = _vmSnapshotDao.findByVm(vmId); for (VMSnapshotVO vmSnapshotVO : vmSnapshots) { if(vmSnapshotVO.getType() == VMSnapshot.Type.DiskAndMemory){ if(!_vmSnapshotMgr.deleteAllVMSnapshots(vmId, VMSnapshot.Type.DiskAndMemory)){ @@ -795,7 +781,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } } - }*/ + } _itMgr.upgradeVmDb(vmId, svcOffId); @@ -2534,6 +2520,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); @@ -2541,12 +2542,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/src/com/cloud/vm/snapshot/VMSnapshotVO.java b/server/src/com/cloud/vm/snapshot/VMSnapshotVO.java deleted file mode 100644 index 03d4945fda0..00000000000 --- a/server/src/com/cloud/vm/snapshot/VMSnapshotVO.java +++ /dev/null @@ -1,224 +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.vm.snapshot; - -import java.util.Date; -import java.util.UUID; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.Table; -import javax.persistence.TableGenerator; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; - -import com.cloud.utils.db.GenericDao; - -@Entity -@Table(name = "vm_snapshots") -public class VMSnapshotVO implements VMSnapshot { - @Id - @TableGenerator(name = "vm_snapshots_sq", table = "sequence", pkColumnName = "name", valueColumnName = "value", pkColumnValue = "vm_snapshots_seq", allocationSize = 1) - @GeneratedValue(strategy = GenerationType.TABLE) - @Column(name = "id") - long id; - - @Column(name = "uuid") - String uuid = UUID.randomUUID().toString(); - - @Column(name = "name") - String name; - - @Column(name = "display_name") - String displayName; - - @Column(name = "description") - String description; - - @Column(name = "vm_id") - long vmId; - - @Column(name = "account_id") - long accountId; - - @Column(name = "domain_id") - long domainId; - - @Column(name = "vm_snapshot_type") - @Enumerated(EnumType.STRING) - VMSnapshot.Type type; - - @Column(name = "state", updatable = true, nullable = false) - @Enumerated(value = EnumType.STRING) - private State state; - - @Column(name = GenericDao.CREATED_COLUMN) - Date created; - - @Column(name = GenericDao.REMOVED_COLUMN) - Date removed; - - @Column(name = "current") - Boolean current; - - @Column(name = "parent") - Long parent; - - @Column(name = "updated") - @Temporal(value = TemporalType.TIMESTAMP) - Date updated; - - @Column(name="update_count", updatable = true, nullable=false) - protected long updatedCount; - - public Long getParent() { - return parent; - } - - public void setParent(Long parent) { - this.parent = parent; - } - - public VMSnapshotVO() { - - } - - public Date getRemoved() { - return removed; - } - - public VMSnapshotVO(Long accountId, Long domainId, Long vmId, - String description, String vmSnapshotName, String vsDisplayName, - Long serviceOfferingId, Type type, Boolean current) { - this.accountId = accountId; - this.domainId = domainId; - this.vmId = vmId; - this.state = State.Allocated; - this.description = description; - this.name = vmSnapshotName; - this.displayName = vsDisplayName; - this.type = type; - this.current = current; - } - - public String getDescription() { - return description; - } - - @Override - public Date getCreated() { - return created; - } - - public void setCreated(Date created) { - this.created = created; - } - - @Override - public long getId() { - return id; - } - - @Override - public Long getVmId() { - return vmId; - } - - public void setVmId(Long vmId) { - this.vmId = vmId; - } - - @Override - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public State getState() { - return state; - } - - public void setState(State state) { - this.state = state; - } - - @Override - public String getUuid() { - return uuid; - } - - @Override - public long getAccountId() { - return accountId; - } - - @Override - public long getDomainId() { - return domainId; - } - - @Override - public String getDisplayName() { - return displayName; - } - - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - - public Boolean getCurrent() { - return current; - } - - public void setCurrent(Boolean current) { - this.current = current; - } - - @Override - public long getUpdatedCount() { - return updatedCount; - } - - @Override - public void incrUpdatedCount() { - this.updatedCount++; - } - - @Override - public Date getUpdated() { - return updated; - } - - @Override - public Type getType() { - return type; - } - - public void setRemoved(Date removed) { - this.removed = removed; - } -} diff --git a/server/test/com/cloud/network/security/SecurityGroupQueueTest.java b/server/test/com/cloud/network/security/SecurityGroupQueueTest.java index b9e417675e4..e6237850825 100644 --- a/server/test/com/cloud/network/security/SecurityGroupQueueTest.java +++ b/server/test/com/cloud/network/security/SecurityGroupQueueTest.java @@ -139,7 +139,7 @@ public class SecurityGroupQueueTest extends TestCase { testNumJobsEqToNumVms2(400,5000); testNumJobsEqToNumVms2(1,1); testNumJobsEqToNumVms2(1,1000000); - testNumJobsEqToNumVms2(1000,1); + testNumJobsEqToNumVms2(750,1); } 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 494ca1b0a58..b3bc7ddf995 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)', @@ -641,5 +650,38 @@ INSERT INTO `cloud`.`vm_template` (id, unique_name, name, public, created, type, -- 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'); + -- Re-enable foreign key checking, at the end of the upgrade path -SET foreign_key_checks = 1; +SET foreign_key_checks = 1; 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/apidoc/build-apidoc.sh b/tools/apidoc/build-apidoc.sh index 14d6459d0c6..d048a1b2d2a 100755 --- a/tools/apidoc/build-apidoc.sh +++ b/tools/apidoc/build-apidoc.sh @@ -19,7 +19,7 @@ # cloud-build-api-doc.sh -- builds api documentation. #set -x -set -u +#set -u TARGETJARDIR="$1" shift DEPSDIR="$1" diff --git a/tools/apidoc/pom.xml b/tools/apidoc/pom.xml index b324ad4b567..f7570ba13ed 100644 --- a/tools/apidoc/pom.xml +++ b/tools/apidoc/pom.xml @@ -43,7 +43,6 @@ bash - -x ./build-apidoc.sh ${client.config.jars} ${client.config.jars} @@ -63,7 +62,7 @@ target tar - -cvjf + -cjf apidoc.tar.bz2 xmldoc 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..79349f6d62c 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 \ + 700 20 1100 ext4 \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /usr } \ @@ -161,12 +161,12 @@ d-i partman-auto/expert_recipe string \ 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 \ + 50 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..79349f6d62c 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 \ + 700 20 1100 ext4 \ method{ format } format{ } \ use_filesystem{ } filesystem{ ext4 } \ mountpoint{ /usr } \ @@ -161,12 +161,12 @@ d-i partman-auto/expert_recipe string \ 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 \ + 50 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/cloud.core.callbacks.js b/ui/scripts/cloud.core.callbacks.js index 1a9e0456d0b..7fd1b4d1244 100644 --- a/ui/scripts/cloud.core.callbacks.js +++ b/ui/scripts/cloud.core.callbacks.js @@ -52,25 +52,31 @@ Below is a sample login attempt var clientApiUrl = "/client/api"; var clientConsoleUrl = "/client/console"; -$(document).ready(function() { - /* - condition 1: If window.location.href contains parameter 'loginUrl', save the parameter's value to a cookie, then reload the page without any URL parameter. - (After the page is reloaded without any URL parameter, it will fall in condition 2.) - */ - if ($.urlParam('loginUrl') != 0) { - $.cookie('loginUrl', $.urlParam('loginUrl'), { expires: 1}); - document.location.href = window.location.href.substring(0, window.location.href.indexOf('?')); - } +$(document).ready(function() { - /* - condition 2: If window.location.href does not contain parameter 'loginUrl' but cookie 'loginUrl' exists, - save the cookie's value to g_regionUrlParam (a global variable for switching regions), - then call login API to set g_loginResponse (a global variable for single-sign-on). - */ - else if($.cookie('loginUrl') != null) { - g_regionUrlParam = '?loginUrl=' + $.cookie('loginUrl'); + var url = $.urlParam("loginUrl"); + if (url != undefined && url != null && url.length > 0) { + url = unescape(clientApiUrl+"?"+url); $.ajax({ - url: unescape(clientApiUrl + "?" + $.cookie('loginUrl')), + url: url, + dataType: "json", + async: false, + success: function(json) { + g_loginResponse = json.loginresponse; + }, + error: function() { + onLogoutCallback(); + // This means the login failed. You should redirect to your login page. + }, + beforeSend: function(XMLHttpRequest) { + return true; + } + }); + } + else if(window.name != null && window.name.indexOf("&domain=") != -1) { //from region switching + g_loginCmdText = window.name; + $.ajax({ + url: clientApiUrl + "?command=login" + window.name + "&response=json", dataType: "json", async: false, success: function(json) { @@ -85,7 +91,6 @@ $(document).ready(function() { } }); } - }); diff --git a/ui/scripts/cloudStack.js b/ui/scripts/cloudStack.js index 985627b824e..0cf80b02066 100644 --- a/ui/scripts/cloudStack.js +++ b/ui/scripts/cloudStack.js @@ -115,6 +115,11 @@ // Use this for checking the session, to bypass login screen bypassLoginCheck: function(args) { //determine to show or bypass login screen if (g_loginResponse == null) { //show login screen + /* + but if this is a 2nd browser window (of the same domain), login screen still won't show because $.cookie('sessionKey') is valid for 2nd browser window (of the same domain) as well. + i.e. calling listCapabilities API with g_sessionKey from $.cookie('sessionKey') will succeed, + then userValid will be set to true, then an user object (instead of "false") will be returned, then login screen will be bypassed. + */ g_mySession = $.cookie('JSESSIONID'); g_sessionKey = $.cookie('sessionKey'); g_role = $.cookie('role'); @@ -176,8 +181,7 @@ userValid = true; }, - error: function(xmlHTTP) { - logout(false); + error: function(xmlHTTP) { //override default error handling, do nothing instead of showing error "unable to verify user credentials" on login screen }, beforeSend : function(XMLHttpResponse) { return true; @@ -250,13 +254,12 @@ else { array1.push("&domain=" + encodeURIComponent("/")); } - - g_regionUrlParam = '?loginUrl=' + escape("command=login" + array1.join("") + "&response=json"); - $.cookie('loginUrl', escape("command=login" + array1.join("") + "&response=json"), { expires: 1}); + + g_loginCmdText = array1.join(""); $.ajax({ type: "POST", - data: "command=login" + array1.join("") + "&response=json", + data: "command=login" + g_loginCmdText + "&response=json", dataType: "json", async: false, success: function(json) { @@ -386,7 +389,8 @@ g_timezoneoffset = null; g_timezone = null; g_supportELB = null; - g_regionUrlParam = null; + g_loginCmdText = null; + window.name = ''; $.cookie('JSESSIONID', null); $.cookie('sessionKey', null); @@ -398,8 +402,7 @@ $.cookie('timezoneoffset', null); $.cookie('timezone', null); $.cookie('supportELB', null); - $.cookie('loginUrl', null); - + if(onLogoutCallback()) { //onLogoutCallback() will set g_loginResponse(single-sign-on variable) to null, then bypassLoginCheck() will show login screen. document.location.reload(); //when onLogoutCallback() returns true, reload the current document. } @@ -466,7 +469,8 @@ document.title = 'CloudStack'; - if ($.cookie('loginUrl') != null || $.urlParam('loginUrl') != 0) { + if ($.urlParam('loginUrl') != 0 + ||(window.name != null && window.name.indexOf("&domain=") != -1)) { // SSO loginArgs.hideLoginScreen = true; } 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 65be302c0c9..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: [] + }); + } + } + ); + } } } } @@ -1186,7 +1581,7 @@ virtualmachineid: args.context.instances[0].id }, success: function(json) { - var ips = json.listnics.nic ? json.listnics.nic[0].secondaryip : []; + var ips = json.listnicsresponse.nic ? json.listnicsresponse.nic[0].secondaryip : []; args.response.success({ data: $(ips).map(function(index, ip) { @@ -1252,7 +1647,7 @@ virtualmachineid: args.context.instances[0].id }, success: function(json) { - var ips = json.listnics.nic[0].secondaryip + var ips = json.listnicsresponse.nic[0].secondaryip args.response.success({ data: $.grep($(ips).map(function(index, ip) { @@ -2783,6 +3178,7 @@ } } }, + itemActions: { add: { label: 'label.add.vms.to.lb', @@ -2943,7 +3339,7 @@ }); $.extend(item, { - _itemName: 'displayname', + _itemName: 'name', _itemData: lbInstances, _maxLength: { name: 7 diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index dbcb781a6fa..86fe7f6416c 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -20,7 +20,7 @@ var g_role = null; // roles - root, domain-admin, ro-admin, user var g_username = null; var g_account = null; var g_domainid = null; -var g_regionUrlParam = null; +var g_loginCmdText = null; var g_enableLogging = false; var g_timezoneoffset = null; var g_timezone = null; diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 8d08584dc60..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,86 @@ } }); } - } + }, + /* + releaseFromAccount: { + label: 'Release from Account', + action: function(args) { + $.ajax({ + url: createURL('releasePublicIpRange'), + data: { + id: args.context.multiRule[0].id + }, + success: function(json) { + args.response.success({ + notification: { + label: 'release from account', + poll: function(args) { + args.complete(); + } + } + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + } + }, + addAccount: { + label: 'Add Account', + createForm: { + title: 'Add Account', + fields: { + account: { label: 'Account' }, + domainid: { + label: 'Domain', + select: function(args) { + $.ajax({ + url: createURL('listDomains'), + data: { listAll: true }, + success: function(json) { + args.response.success({ + data: $.map(json.listdomainsresponse.domain, function(domain) { + return { + id: domain.id, + description: domain.path + }; + }) + }); + } + }); + } + } + } + }, + action: function(args) { + var data = { + id: args.context.multiRule[0].id, + zoneid: args.context.multiRule[0].zoneid, + domainid: args.data.domainid, + account: args.data.account + }; + $.ajax({ + url: createURL('dedicatePublicIpRange'), + data: data, + success: function(json) { + args.response.success({ + notification: { + label: 'Add Account', + poll: function(args) { + args.complete(); + } + } + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + } + } + */ }, dataProvider: function(args) { $.ajax({ diff --git a/ui/scripts/ui-custom/healthCheck.js b/ui/scripts/ui-custom/healthCheck.js index ebb7e5a8903..4b42fa7724c 100644 --- a/ui/scripts/ui-custom/healthCheck.js +++ b/ui/scripts/ui-custom/healthCheck.js @@ -164,7 +164,15 @@ } }); }, g_queryAsyncJobResultInterval); - } + }, + + error:function(json){ + + cloudStack.dialog.notice({message: _s(json.responseText)}); //Error message in the API needs to be improved + $healthCheckDialog.dialog('close'); + $('.overlay').remove(); + } + }); } } diff --git a/ui/scripts/ui-custom/regions.js b/ui/scripts/ui-custom/regions.js index 17bc86cb5ad..2f61dfddeaf 100644 --- a/ui/scripts/ui-custom/regions.js +++ b/ui/scripts/ui-custom/regions.js @@ -89,8 +89,8 @@ closeRegionSelector({ complete: function() { $('#container').prepend($('
').addClass('loading-overlay')); - - document.location.href = url + g_regionUrlParam; + window.name = g_loginCmdText; + document.location.href = url; } }); }; diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js index 4b88647e6f1..1c74056c75b 100644 --- a/ui/scripts/ui/widgets/listView.js +++ b/ui/scripts/ui/widgets/listView.js @@ -863,7 +863,7 @@ var uiCustom = listViewArgs.uiCustom; var subselect = uiCustom ? listViewArgs.listView.subselect : null; - if (!data || ($.isArray(data) && !data.length)) { + if (!data || !data.length) { if (!$tbody.find('tr').size()) { return [ $('').addClass('empty').append( diff --git a/ui/scripts/ui/widgets/multiEdit.js b/ui/scripts/ui/widgets/multiEdit.js index 0a055916649..27b14d16e61 100755 --- a/ui/scripts/ui/widgets/multiEdit.js +++ b/ui/scripts/ui/widgets/multiEdit.js @@ -240,6 +240,7 @@ // Action filter var allowedActions = options.preFilter ? options.preFilter({ + actions: $.map(actions, function(value, key) { return key; }), context: $.extend(true, {}, options.context, { multiRule: [data], actions: $.map(actions, function(value, key) { return key; }) @@ -323,6 +324,7 @@ var $expandable = $dataItem.find('.expandable-listing'); var isDestroy = $target.hasClass('destroy'); var isEdit = $target.hasClass('edit'); + var createForm = action.createForm; if (isDestroy) { var $loading = _medit.loadingItem($multi, _l('label.removing') + '...'); @@ -340,7 +342,19 @@ } if (!isEdit) { - performAction(); + if (createForm) { + cloudStack.dialog.createForm({ + form: createForm, + after: function(args) { + var $loading = $('
').addClass('loading-overlay').prependTo($dataItem); + performAction({ data: args.data, complete: function() { + $multi.trigger('refresh'); + } }); + } + }); + } else { + performAction(); + } } else { // Get editable fields var editableFields = {}; 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);