diff --git a/.gitignore b/.gitignore index 016554a5f75..929227d8604 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,4 @@ debian/*.debhelper replace.properties.tmp build-indep-stamp configure-stamp +*_flymake.js \ No newline at end of file diff --git a/INSTALL.md b/INSTALL.md index 4f93900ddfe..b0e1a7617b0 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,5 +1,5 @@ -This document describes how to develop, build, package and install Apache CloudStack -(Incubating). For more information please refer to the project's website: +This document describes how to develop, build, package and install Apache +CloudStack. For more information please refer to: http://cloudstack.apache.org @@ -10,7 +10,7 @@ Refer to the [wiki](http://cwiki.apache.org/confluence/display/CLOUDSTACK/Index) for the latest information, especially: - [Setting up development environment](https://cwiki.apache.org/confluence/display/CLOUDSTACK/Setting+up+CloudStack+Development+Environment) for Apache CloudStack. - - [Building](https://cwiki.apache.org/confluence/display/CLOUDSTACK/Building) Apache CloudStack. + - [Building](https://cwiki.apache.org/confluence/display/CLOUDSTACK/How+to+build+on+master+branch) Apache CloudStack. ## Setting up Development Environment @@ -21,12 +21,12 @@ Install tools and dependencies used for development: $ yum install git ant ant-devel java-1.6.0-openjdk java-1.6.0-openjdk-devel mysql mysql-server tomcat6 mkisofs gcc python MySQL-python openssh-clients wget -Set up Maven (3.0.4): +Set up Maven (3.0.5): - $ wget http://www.us.apache.org/dist/maven/maven-3/3.0.4/binaries/apache-maven-3.0.4-bin.tar.gz + $ wget http://www.us.apache.org/dist/maven/maven-3/3.0.5/binaries/apache-maven-3.0.5-bin.tar.gz $ cd /usr/local/ # or any path - $ tar -zxvf apache-maven-3.0.4-bin.tar.gz - $ echo export M2_HOME=/usr/local/apache-maven-3.0.4 >> ~/.bashrc # or .zshrc or .profile + $ tar -zxvf apache-maven-3.0.5-bin.tar.gz + $ echo export M2_HOME=/usr/local/apache-maven-3.0.5 >> ~/.bashrc # or .zshrc or .profile $ echo export PATH=${M2_HOME}/bin:${PATH} >> ~/.bashrc # or .zshrc or .profile Note: Tomcat 6.0.35 has some known issue with Apache CloudStack, please use Tomcat @@ -77,10 +77,10 @@ Start the MySQL service: You may get the source code from the repository hosted on Apache: - $ git clone https://git-wip-us.apache.org/repos/asf/cloudstack.git + $ git clone git://git.apache.org/cloudstack.git Or, you may fork a repository from the official Apache CloudStack mirror by -Apache on [Github](https://github.com/apache/incubator-cloudstack) +Apache on [Github](https://github.com/apache/cloudstack) To keep yourself updated on a branch, do: @@ -92,7 +92,6 @@ For example, for master: ## Building - Clean and build: $ mvn clean install -P systemvm,developer diff --git a/agent/bindir/cloud-setup-agent.in b/agent/bindir/cloud-setup-agent.in index 5e2ba09406d..6932672b962 100755 --- a/agent/bindir/cloud-setup-agent.in +++ b/agent/bindir/cloud-setup-agent.in @@ -95,6 +95,11 @@ if __name__ == '__main__': parser.add_option("--prvNic", dest="prvNic", help="Private traffic interface") parser.add_option("--guestNic", dest="guestNic", help="Guest traffic interface") + old_config = configFileOps("@AGENTSYSCONFDIR@/agent.properties") + bridgeType = old_config.getEntry("network.bridge.type").lower() + if bridgeType: + glbEnv.bridgeType = bridgeType + (options, args) = parser.parse_args() if options.auto is None: userInputs = getUserInputs() @@ -104,7 +109,7 @@ if __name__ == '__main__': glbEnv.pod = userInputs[3] glbEnv.cluster = userInputs[4] #generate UUID - glbEnv.uuid = configFileOps("@AGENTSYSCONFDIR@/agent.properties").getEntry("guid") + glbEnv.uuid = old_config.getEntry("guid") if glbEnv.uuid == "": glbEnv.uuid = bash("uuidgen").getStdout() else: diff --git a/agent/conf/agent.properties b/agent/conf/agent.properties index 7dc4ba8a18c..60030ae4f11 100644 --- a/agent/conf/agent.properties +++ b/agent/conf/agent.properties @@ -84,6 +84,11 @@ domr.scripts.dir=scripts/network/domr/kvm # set the hypervisor type, values are: kvm, lxc # hypervisor.type=kvm +# set the hypervisor URI. Usually there is no need for changing this +# For KVM: qemu:///system +# For LXC: lxc:/// +# hypervisor.uri=qemu:///system + # settings to enable direct networking in libvirt, should not be used # on hosts that run system vms, values for mode are: private, bridge, vepa # libvirt.vif.driver=com.cloud.hypervisor.kvm.resource.DirectVifDriver diff --git a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java index b84d20a9239..46ee01bc8a3 100644 --- a/api/src/com/cloud/agent/api/to/VirtualMachineTO.java +++ b/api/src/com/cloud/agent/api/to/VirtualMachineTO.java @@ -52,6 +52,7 @@ public class VirtualMachineTO { boolean rebootOnCrash; boolean enableHA; boolean limitCpuUse; + boolean enableDynamicallyScaleVm; String vncPassword; String vncAddr; Map params; @@ -102,6 +103,14 @@ public class VirtualMachineTO { this.id = id; } + public boolean isEnableDynamicallyScaleVm() { + return enableDynamicallyScaleVm; + } + + public void setEnableDynamicallyScaleVm(boolean enableDynamicallyScaleVm) { + this.enableDynamicallyScaleVm = enableDynamicallyScaleVm; + } + public String getName() { return name; } diff --git a/api/src/com/cloud/event/EventTypes.java b/api/src/com/cloud/event/EventTypes.java index fcac8e8e65d..6dfb1ab57b6 100755 --- a/api/src/com/cloud/event/EventTypes.java +++ b/api/src/com/cloud/event/EventTypes.java @@ -103,7 +103,7 @@ public class EventTypes { public static final String EVENT_NET_IP_ASSIGN = "NET.IPASSIGN"; public static final String EVENT_NET_IP_RELEASE = "NET.IPRELEASE"; public static final String EVENT_PORTABLE_IP_ASSIGN = "PORTABLE.IPASSIGN"; - public static final String EVENT_PORTABLE_IP_RELEASE = "PORTABLEIPRELEASE"; + public static final String EVENT_PORTABLE_IP_RELEASE = "PORTABLE.IPRELEASE"; public static final String EVENT_NET_RULE_ADD = "NET.RULEADD"; public static final String EVENT_NET_RULE_DELETE = "NET.RULEDELETE"; public static final String EVENT_NET_RULE_MODIFY = "NET.RULEMODIFY"; @@ -436,6 +436,7 @@ public class EventTypes { public static final String EVENT_PORTABLE_IP_RANGE_CREATE = "PORTABLE.IP.RANGE.CREATE"; public static final String EVENT_PORTABLE_IP_RANGE_DELETE = "PORTABLE.IP.RANGE.DELETE"; + public static final String EVENT_PORTABLE_IP_TRANSFER = "PORTABLE.IP.TRANSFER"; static { diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java index 02122381426..4fe7ad033cc 100755 --- a/api/src/com/cloud/network/NetworkService.java +++ b/api/src/com/cloud/network/NetworkService.java @@ -56,7 +56,7 @@ public interface NetworkService { IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId, Long vpcId) throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException; - boolean releasePortableIpAddress(long ipAddressId) throws InsufficientAddressCapacityException; + boolean releasePortableIpAddress(long ipAddressId); Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException; diff --git a/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java b/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java index d637da638ac..b554719f188 100644 --- a/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java +++ b/api/src/com/cloud/network/vpn/RemoteAccessVpnService.java @@ -32,7 +32,7 @@ public interface RemoteAccessVpnService { RemoteAccessVpn createRemoteAccessVpn(long vpnServerAddressId, String ipRange, boolean openFirewall, long networkId) throws NetworkRuleConflictException; - void destroyRemoteAccessVpn(long vpnServerAddressId, Account caller) throws ResourceUnavailableException; + void destroyRemoteAccessVpnForIp(long vpnServerAddressId, Account caller) throws ResourceUnavailableException; RemoteAccessVpn startRemoteAccessVpn(long vpnServerAddressId, boolean openFirewall) throws ResourceUnavailableException; VpnUser addVpnUser(long vpnOwnerId, String userName, String password); diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java index de76b7ab6d6..1450e5d0b70 100644 --- a/api/src/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseCmd.java @@ -522,7 +522,7 @@ public abstract class BaseCmd { return project.getProjectAccountId(); } else { PermissionDeniedException ex = new PermissionDeniedException("Can't add resources to the project with specified projectId in state=" + project.getState() + " as it's no longer active"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(project.getUuid(), "projectId"); throw ex; } } else { diff --git a/api/src/org/apache/cloudstack/api/ServerApiException.java b/api/src/org/apache/cloudstack/api/ServerApiException.java index 4b0fae58548..1a740d56c90 100644 --- a/api/src/org/apache/cloudstack/api/ServerApiException.java +++ b/api/src/org/apache/cloudstack/api/ServerApiException.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import com.cloud.exception.CloudException; import com.cloud.utils.exception.CSExceptionErrorCode; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.exception.ExceptionProxyObject; @SuppressWarnings("serial") public class ServerApiException extends CloudRuntimeException { @@ -45,7 +46,7 @@ public class ServerApiException extends CloudRuntimeException { _description = description; if (cause instanceof CloudRuntimeException) { CloudRuntimeException rt = (CloudRuntimeException) cause; - ArrayList idList = rt.getIdProxyList(); + ArrayList idList = rt.getIdProxyList(); if (idList != null) { for (int i = 0; i < idList.size(); i++) { addProxyObject(idList.get(i)); diff --git a/api/src/org/apache/cloudstack/api/command/admin/config/UpdateHypervisorCapabilitiesCmd.java b/api/src/org/apache/cloudstack/api/command/admin/config/UpdateHypervisorCapabilitiesCmd.java index 7aacf45f2f5..4b61bc8ff8b 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/config/UpdateHypervisorCapabilitiesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/config/UpdateHypervisorCapabilitiesCmd.java @@ -25,12 +25,11 @@ import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.HypervisorCapabilitiesResponse; -import org.apache.cloudstack.api.response.ServiceOfferingResponse; import com.cloud.hypervisor.HypervisorCapabilities; import com.cloud.user.Account; -@APICommand(name = "updateHypervisorCapabilities", description="Updates a hypervisor capabilities.", responseObject=ServiceOfferingResponse.class, since="3.0.0") +@APICommand(name = "updateHypervisorCapabilities", description="Updates a hypervisor capabilities.", responseObject=HypervisorCapabilitiesResponse.class, since="3.0.0") public class UpdateHypervisorCapabilitiesCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(UpdateHypervisorCapabilitiesCmd.class.getName()); private static final String s_name = "updatehypervisorcapabilitiesresponse"; @@ -86,7 +85,7 @@ public class UpdateHypervisorCapabilitiesCmd extends BaseCmd { if (result != null){ HypervisorCapabilitiesResponse response = _responseGenerator.createHypervisorCapabilitiesResponse(result); response.setResponseName(getCommandName()); - this.setResponseObject(response); + setResponseObject(response); } else { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update hypervisor capabilities"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/account/AddAccountToProjectCmd.java b/api/src/org/apache/cloudstack/api/command/user/account/AddAccountToProjectCmd.java index 21493612fda..50aebcc44ba 100644 --- a/api/src/org/apache/cloudstack/api/command/user/account/AddAccountToProjectCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/account/AddAccountToProjectCmd.java @@ -102,7 +102,7 @@ public class AddAccountToProjectCmd extends BaseAsyncCmd { //verify input parameters if (project == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find project with specified id"); - ex.addProxyObject(project, getProjectId(), "projectId"); + ex.addProxyObject(getProjectId().toString(), "projectId"); throw ex; } diff --git a/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java index 3fc30610034..21f8177e55e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/address/AssociateIPAddrCmd.java @@ -211,8 +211,12 @@ public class AssociateIPAddrCmd extends BaseAsyncCreateCmd { @Override public String getEventType() { + if (isPortable()) { + return EventTypes.EVENT_PORTABLE_IP_ASSIGN; + } else { return EventTypes.EVENT_NET_IP_ASSIGN; } + } @Override public String getEventDescription() { diff --git a/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java b/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java index dbb8f061c7c..e5707bcdf93 100644 --- a/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/address/DisassociateIPAddrCmd.java @@ -77,9 +77,9 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { UserContext.current().setEventDetails("Ip Id: " + getIpAddressId()); boolean result = false; if (!isPortable(id)) { - _networkService.releaseIpAddress(getIpAddressId()); + result = _networkService.releaseIpAddress(getIpAddressId()); } else { - _networkService.releaseIpAddress(getIpAddressId()); + result = _networkService.releasePortableIpAddress(getIpAddressId()); } if (result) { SuccessResponse response = new SuccessResponse(getCommandName()); @@ -91,7 +91,11 @@ public class DisassociateIPAddrCmd extends BaseAsyncCmd { @Override public String getEventType() { + if (!isPortable(id)) { return EventTypes.EVENT_NET_IP_RELEASE; + } else { + return EventTypes.EVENT_PORTABLE_IP_RELEASE; + } } @Override diff --git a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListConditionsCmd.java b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListConditionsCmd.java index 9ad7b8edd05..f323ffcd2d7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/autoscale/ListConditionsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/autoscale/ListConditionsCmd.java @@ -33,7 +33,7 @@ import org.apache.cloudstack.api.response.ListResponse; import com.cloud.network.as.Condition; -@APICommand(name = "listConditions", description = "List Conditions for the specific user", responseObject = CounterResponse.class) +@APICommand(name = "listConditions", description = "List Conditions for the specific user", responseObject = ConditionResponse.class) public class ListConditionsCmd extends BaseListAccountResourcesCmd { public static final Logger s_logger = Logger.getLogger(ListConditionsCmd.class.getName()); private static final String s_name = "listconditionsresponse"; @@ -70,7 +70,7 @@ public class ListConditionsCmd extends BaseListAccountResourcesCmd { response.setResponses(cndnResponses); response.setResponseName(getCommandName()); - this.setResponseObject(response); + setResponseObject(response); } // ///////////////////////////////////////////////// diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java index 815af7d3042..43d7b8cf540 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java @@ -199,7 +199,11 @@ public class CreatePortForwardingRuleCmd extends BaseAsyncCreateCmd implements P _firewallService.revokeRelatedFirewallRule(getEntityId(), true); } + try { _rulesService.revokePortForwardingRule(getEntityId(), true); + } catch (Exception ex){ + //Ignore e.g. failed to apply rules to device error + } throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to apply port forwarding rule"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRulesCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRulesCmd.java index 3f9f93df90b..1a206bae3a4 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRulesCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/ListLoadBalancerRulesCmd.java @@ -29,6 +29,7 @@ import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.IPAddressResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.LoadBalancerResponse; +import org.apache.cloudstack.api.response.NetworkResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.ZoneResponse; @@ -64,6 +65,10 @@ public class ListLoadBalancerRulesCmd extends BaseListTaggedResourcesCmd { description = "the availability zone ID") private Long zoneId; + @Parameter(name = ApiConstants.NETWORK_ID, type = CommandType.UUID, entityType = NetworkResponse.class, + description = "list by network id the rule belongs to") + private Long networkId; + // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// @@ -88,6 +93,10 @@ public class ListLoadBalancerRulesCmd extends BaseListTaggedResourcesCmd { return zoneId; } + public Long getNetworkId() { + return networkId; + } + // /////////////////////////////////////////////////// // ///////////// API Implementation/////////////////// // /////////////////////////////////////////////////// diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java index 18e6743099f..113e89cb465 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.api.command.user.network; import java.util.ArrayList; import java.util.List; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.cloudstack.api.APICommand; @@ -93,7 +94,15 @@ public class CreateNetworkACLCmd extends BaseAsyncCreateCmd { // /////////////////////////////////////////////////// public String getProtocol() { - return protocol.trim(); + String p = protocol.trim(); + // Deal with ICMP(protocol number 1) specially because it need to be paired with icmp type and code + if(StringUtils.isNumeric(p)){ + int protoNumber = Integer.parseInt(p); + if (protoNumber == 1) { + p = "icmp"; + } + } + return p; } public List getSourceCidrList() { diff --git a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java index 510cfa1fe5c..589f4198e14 100644 --- a/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotPolicyCmd.java @@ -113,7 +113,7 @@ public class CreateSnapshotPolicyCmd extends BaseCmd { Project project = _projectService.findByProjectAccountId(volume.getAccountId()); if (project.getState() != Project.State.Active) { PermissionDeniedException ex = new PermissionDeniedException("Can't add resources to the specified project id in state=" + project.getState() + " as it's no longer active"); - ex.addProxyObject(project, project.getId(), "projectId"); + ex.addProxyObject(project.getUuid(), "projectId"); throw ex; } } else if (account.getState() == Account.State.disabled) { diff --git a/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java b/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java index cb837050173..b9834d50d87 100644 --- a/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java @@ -31,7 +31,6 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.GuestOSResponse; import org.apache.cloudstack.api.response.SnapshotResponse; -import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.TemplateResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.VolumeResponse; @@ -47,7 +46,7 @@ import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.Account; import com.cloud.user.UserContext; -@APICommand(name = "createTemplate", responseObject = StoragePoolResponse.class, description = "Creates a template of a virtual machine. " + "The virtual machine must be in a STOPPED state. " +@APICommand(name = "createTemplate", responseObject = TemplateResponse.class, description = "Creates a template of a virtual machine. " + "The virtual machine must be in a STOPPED state. " + "A template created from this command is automatically designated as a private template visible to the account that created it.") public class CreateTemplateCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateTemplateCmd.class.getName()); @@ -210,7 +209,7 @@ import com.cloud.user.UserContext; Project project = _projectService.findByProjectAccountId(accountId); if (project.getState() != Project.State.Active) { PermissionDeniedException ex = new PermissionDeniedException("Can't add resources to the specified project id in state=" + project.getState() + " as it's no longer active"); - ex.addProxyObject(project, project.getId(), "projectId"); + ex.addProxyObject(project.getUuid(), "projectId"); } } else if (account.getState() == Account.State.disabled) { throw new PermissionDeniedException("The owner of template is disabled: " + account); @@ -235,16 +234,16 @@ import com.cloud.user.UserContext; } private boolean isBareMetal() { - return (this.getVmId() != null && this.getUrl() != null); + return (getVmId() != null && getUrl() != null); } @Override public void create() throws ResourceAllocationException { VirtualMachineTemplate template = null; - template = this._templateService.createPrivateTemplateRecord(this, _accountService.getAccount(getEntityOwnerId())); + template = _templateService.createPrivateTemplateRecord(this, _accountService.getAccount(getEntityOwnerId())); if (template != null) { - this.setEntityId(template.getId()); - this.setEntityUuid(template.getUuid()); + setEntityId(template.getId()); + setEntityUuid(template.getUuid()); } else { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create a template"); @@ -256,7 +255,7 @@ import com.cloud.user.UserContext; public void execute() { UserContext.current().setEventDetails("Template Id: "+getEntityId()+((getSnapshotId() == null) ? " from volume Id: " + getVolumeId() : " from snapshot Id: " + getSnapshotId())); VirtualMachineTemplate template = null; - template = this._templateService.createPrivateTemplate(this); + template = _templateService.createPrivateTemplate(this); if (template != null){ List templateResponses; @@ -270,7 +269,7 @@ import com.cloud.user.UserContext; response = templateResponses.get(0); } response.setResponseName(getCommandName()); - this.setResponseObject(response); + setResponseObject(response); } else { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create private template"); } diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java index 13d08df9b87..024567ffdc3 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java @@ -36,7 +36,7 @@ import com.cloud.user.Account; import com.cloud.user.UserContext; import com.cloud.uservm.UserVm; -@APICommand(name = "restoreVirtualMachine", description="Restore a VM to original template or new template", responseObject=UserVmResponse.class, since="3.0.0") +@APICommand(name = "restoreVirtualMachine", description="Restore a VM to original template/ISO or new template/ISO", responseObject=UserVmResponse.class, since="3.0.0") public class RestoreVMCmd extends BaseAsyncCmd { public static final Logger s_logger = Logger.getLogger(RestoreVMCmd.class); private static final String s_name = "restorevmresponse"; @@ -45,9 +45,10 @@ public class RestoreVMCmd extends BaseAsyncCmd { required=true, description="Virtual Machine ID") private Long vmId; - @Parameter(name=ApiConstants.TEMPLATE_ID, type=CommandType.UUID, entityType = TemplateResponse.class, description="an optional template Id to restore vm from the new template") + @Parameter(name=ApiConstants.TEMPLATE_ID, type=CommandType.UUID, entityType = TemplateResponse.class, description="an optional template Id to restore vm from the new template. This can be an ISO id in case of restore vm deployed using ISO") private Long templateId; + @Override public String getEventType() { return EventTypes.EVENT_VM_RESTORE; diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java index bd64c1c0c1f..a74763c198a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/UploadVolumeCmd.java @@ -24,7 +24,9 @@ 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.BaseCmd.CommandType; import org.apache.cloudstack.api.response.DomainResponse; +import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.VolumeResponse; import org.apache.cloudstack.api.response.ZoneResponse; @@ -73,6 +75,10 @@ public class UploadVolumeCmd extends BaseAsyncCmd { description="Image store uuid") private String imageStoreUuid; + @Parameter(name=ApiConstants.PROJECT_ID, type=CommandType.UUID, entityType = ProjectResponse.class, + description="Upload volume for the project") + private Long projectId; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -136,7 +142,7 @@ public class UploadVolumeCmd extends BaseAsyncCmd { @Override public long getEntityOwnerId() { - Long accountId = finalyzeAccountId(accountName, domainId, null, true); + Long accountId = finalyzeAccountId(accountName, domainId, projectId, true); if (accountId == null) { return UserContext.current().getCaller().getId(); } diff --git a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java index 38fea371ce1..fa1fd7deda5 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpn/DeleteRemoteAccessVpnCmd.java @@ -85,7 +85,7 @@ public class DeleteRemoteAccessVpnCmd extends BaseAsyncCmd { @Override public void execute() throws ResourceUnavailableException { - _ravService.destroyRemoteAccessVpn(publicIpId, UserContext.current().getCaller()); + _ravService.destroyRemoteAccessVpnForIp(publicIpId, UserContext.current().getCaller()); } @Override diff --git a/api/src/org/apache/cloudstack/api/response/ExceptionResponse.java b/api/src/org/apache/cloudstack/api/response/ExceptionResponse.java index e0bde45a26f..80fc9233761 100644 --- a/api/src/org/apache/cloudstack/api/response/ExceptionResponse.java +++ b/api/src/org/apache/cloudstack/api/response/ExceptionResponse.java @@ -17,17 +17,19 @@ package org.apache.cloudstack.api.response; import java.util.ArrayList; +import java.util.List; import com.google.gson.annotations.SerializedName; import org.apache.cloudstack.api.BaseResponse; import com.cloud.serializer.Param; +import com.cloud.utils.exception.ExceptionProxyObject; public class ExceptionResponse extends BaseResponse { @SerializedName("uuidList") @Param(description="List of uuids associated with this error") - private ArrayList idList; + private final List idList; @SerializedName("errorcode") @Param(description="numeric code associated with this error") private Integer errorCode; @@ -38,6 +40,10 @@ public class ExceptionResponse extends BaseResponse { @SerializedName("errortext") @Param(description="the text associated with this error") private String errorText = "Command failed due to Internal Server Error"; + public ExceptionResponse(){ + idList = new ArrayList(); + } + public Integer getErrorCode() { return errorCode; } @@ -54,17 +60,17 @@ public class ExceptionResponse extends BaseResponse { this.errorText = errorText; } - public void addProxyObject(String id) { + public void addProxyObject(ExceptionProxyObject id) { idList.add(id); return; } - public ArrayList getIdProxyList() { + public List getIdProxyList() { return idList; } public void setCSErrorCode(int cserrcode) { - this.csErrorCode = cserrcode; + csErrorCode = cserrcode; } @Override diff --git a/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java b/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java index d15fc043a13..acc1ef3d498 100644 --- a/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java +++ b/api/src/org/apache/cloudstack/api/response/LoadBalancerResponse.java @@ -59,6 +59,10 @@ public class LoadBalancerResponse extends BaseResponse implements ControlledEnti @Param(description = "the load balancer algorithm (source, roundrobin, leastconn)") private String algorithm; + @SerializedName(ApiConstants.NETWORK_ID) + @Param(description = "the id of the guest network the lb rule belongs to") + private String networkId; + @SerializedName(ApiConstants.CIDR_LIST) @Param(description="the cidr list to forward traffic from") private String cidrList; @@ -91,6 +95,7 @@ public class LoadBalancerResponse extends BaseResponse implements ControlledEnti @SerializedName(ApiConstants.TAGS) @Param(description="the list of resource tags associated with load balancer", responseObject = ResourceTagResponse.class) private List tags; + public void setId(String id) { this.id = id; } @@ -162,4 +167,8 @@ public class LoadBalancerResponse extends BaseResponse implements ControlledEnti this.tags = tags; } + public void setNetworkId(String networkId) { + this.networkId = networkId; + } + } diff --git a/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java b/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java index c686293f18a..2c596a44003 100644 --- a/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java +++ b/api/src/org/apache/cloudstack/api/response/ServiceOfferingResponse.java @@ -59,6 +59,9 @@ public class ServiceOfferingResponse extends BaseResponse { @SerializedName("limitcpuuse") @Param(description="restrict the CPU usage to committed service offering") private Boolean limitCpuUse; + @SerializedName("isvolatile") @Param(description="true if the vm needs to be volatile, i.e., on every reboot of vm from API root disk is discarded and creates a new root disk") + private Boolean isVolatile; + @SerializedName("tags") @Param(description="the tags for the service offering") private String tags; @@ -236,4 +239,12 @@ public class ServiceOfferingResponse extends BaseResponse { public void setDeploymentPlanner(String deploymentPlanner) { this.deploymentPlanner = deploymentPlanner; } + + public boolean getVolatileVm() { + return isVolatile; + } + + public void setVolatileVm(boolean isVolatile) { + this.isVolatile = isVolatile; + } } diff --git a/api/src/org/apache/cloudstack/jobs/Job.java b/api/src/org/apache/cloudstack/jobs/Job.java new file mode 100644 index 00000000000..d238da3400e --- /dev/null +++ b/api/src/org/apache/cloudstack/jobs/Job.java @@ -0,0 +1,67 @@ +// 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 org.apache.cloudstack.jobs; + +import java.util.Date; + +import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + +public interface Job extends Identity, InternalIdentity { + + + + String getType(); + + String getDispatcher(); + + int getPendingSignals(); + + long getUserId(); + + long getAccountId(); + + String getCmd(); + + int getCmdVersion(); + + String getCmdInfo(); + + int getStatus(); + + int getProcessStatus(); + + int getResultCode(); + + String getResult(); + + Long getInitMsid(); + + Long getExecutingMsid(); + + Long getCompleteMsid(); + + Date getCreated(); + + Date getLastUpdated(); + + Date getLastPolled(); + + String getInstanceType(); + + Long getInstanceId(); +} diff --git a/client/WEB-INF/classes/resources/messages_ar.properties b/client/WEB-INF/classes/resources/messages_ar.properties index 4d3011b5a6c..5b3afea929d 100644 --- a/client/WEB-INF/classes/resources/messages_ar.properties +++ b/client/WEB-INF/classes/resources/messages_ar.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=\u062a\u063a\u064a\u0631 \u062e\u0635\u0627\u0626\u0635 \u0627\u0644\u0639\u0646\u0635\u0631 confirm.enable.s3=\u0641\u0636\u0644\u0627 \u0642\u0645 \u0628\u062a\u0639\u0628\u0626\u0629 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0627\u0644\u0642\u0627\u062f\u0645\u0629 \u0644\u062a\u0645\u0643\u064a\u0646 \u0627\u0644\u062a\u062e\u0632\u064a\u0646 S3 \u0644\u0644\u0630\u0627\u0643\u0631\u0629 \u0627\u0644\u062b\u0627\u0646\u0648\u064a\u0629. instances.actions.reboot.label=\u0625\u0639\u0627\u062f\u0629 \u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u0646\u0645\u0648\u0630\u062c @@ -217,6 +216,7 @@ label.zone.step.3.title=\u0627\u0644\u062e\u0637\u0648\u0629 3 \\\: \u0639\u0644 label.zone.step.4.title=\u0627\u0644\u062e\u0637\u0648\u0629 4 \\\: <\u0642\u0648\u064a> \u0625\u0636\u0627\u0641\u0629 \u0645\u062c\u0645\u0648\u0639\u0629 IP <\\\u0642\u0648\u064a> label.zone.wide=\u0645\u0646\u0637\u0642\u0629 \u0648\u0627\u0633\u0639\u0629 label.zoneWizard.trafficType.guest=\u0627\u0644\u0636\u064a\u0641 \\\: \u0627\u0644\u062d\u0631\u0643\u0629 \u0628\u064a\u0646 \u0627\u0644\u0623\u062c\u0647\u0632\u0629 \u0627\u0644\u0625\u0641\u062a\u0631\u0627\u0636\u064a\u0629 \u0644\u0644\u0645\u0633\u062a\u062e\u062f\u0645 \u0627\u0644\u0646\u0647\u0627\u0626\u064a. +label.zoneWizard.trafficType.management=\u0625\u062f\u0627\u0631\u0629\\\: \u0627\u0644\u062d\u0631\u0643\u0629 \u0628\u064a\u0646 \u0627\u0644\u0645\u0648\u0627\u0631\u062f \u0627\u0644\u062f\u0627\u062e\u0644\u064a\u0629 \u0644 \u0643\u0644\u0627\u0648\u062f \u0633\u062a\u0627\u0643 \u060c \u0645\u062a\u0636\u0645\u0646\u0629 \u0623\u064a \u062c\u0632\u0621 \u064a\u062a\u0635\u0644 \u0628\u062e\u0627\u062f\u0645\\\u0633\u064a\u0631\u0641\u0631 \u0627\u0644\u0625\u062f\u0627\u0631\u0629 \u060c \u0645\u062b\u0644 \u0627\u0644\u0645\u0636\u064a\u0641\u0627\u062a \u0648 \u0623\u0646\u0638\u0645\u0629 \u0643\u0644\u0627\u0648\u062f \u0633\u062a\u0627\u0643 \u0627\u0644\u0625\u0641\u062a\u0631\u0627\u0636\u064a\u0629. label.zoneWizard.trafficType.public=\u0627\u0644\u0639\u0627\u0645\u0629 \\\: \u0627\u0644\u0645\u0631\u0648\u0631 \u0628\u064a\u0646 \u0627\u0644\u0625\u0646\u062a\u0631\u0646\u062a \u0648\u0627\u0644\u0623\u062c\u0647\u0632\u0629 \u0627\u0644\u0638\u0627\u0647\u0631\u064a\u0629 \u0641\u064a \u0627\u0644\u0633\u062d\u0627\u0628\u0629. label.zoneWizard.trafficType.storage=\u0627\u0644\u062a\u062e\u0632\u064a\u0646 \\\: \u0627\u0644\u0645\u0631\u0648\u0631 \u0628\u064a\u0646 \u0645\u0644\u0642\u0645\u0627\u062a \u0627\u0644\u062a\u062e\u0632\u064a\u0646 \u0627\u0644\u0627\u0628\u062a\u062f\u0627\u0626\u064a\u0629 \u0648\u0627\u0644\u062b\u0627\u0646\u0648\u064a\u0629\u060c \u0645\u062b\u0644 \u0642\u0648\u0627\u0644\u0628 VM \u0648\u0627\u0644\u0644\u0642\u0637\u0627\u062a message.acquire.new.ip.vpc=\u064a\u0631\u062c\u0649 \u0627\u0644\u062a\u0623\u0643\u064a\u062f \u0628\u0623\u0646\u0643 \u062a\u0631\u063a\u0628 \u0641\u064a \u0627\u0644\u062d\u0635\u0648\u0644 \u0639\u0644\u0649 \u0628\u0648\u0631\u062a\u0648\u0643\u0648\u0644 \u0625\u0646\u062a\u0631\u0646\u062a \u062c\u062f\u064a\u062f \u0644\u0647\u0630\u0627 \u0627\u0644\u062d\u0627\u0633\u0648\u0628 \u0627\u0644\u0625\u0641\u062a\u0631\u0627\u0636\u064a. diff --git a/client/WEB-INF/classes/resources/messages_ca.properties b/client/WEB-INF/classes/resources/messages_ca.properties index 4e66083dbd5..2d8e953419f 100644 --- a/client/WEB-INF/classes/resources/messages_ca.properties +++ b/client/WEB-INF/classes/resources/messages_ca.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - confirm.enable.swift=Si us plau ompliu la seg\u00fcent informaci\u00f3 per habilitar el suport per a Swift error.installWizard.message=Quelcom ha fallat, vost\u00e8 pot tornar enrere i corregir els errors detalls suggerime error.password.not.match=Els camps de contrasenya no coincideixen diff --git a/client/WEB-INF/classes/resources/messages_de_DE.properties b/client/WEB-INF/classes/resources/messages_de_DE.properties index ca87323cc77..3c0c8deaabd 100644 --- a/client/WEB-INF/classes/resources/messages_de_DE.properties +++ b/client/WEB-INF/classes/resources/messages_de_DE.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - error.installWizard.message=Ein Fehler ist aufgetreten; Sie k\u00f6nnen zur\u00fcckgehen und den Fehler korregieren error.login=Ihr Benutzername / Passwort stimmt nicht mit uneren unseren Aufzeichnungen \u00fcberein. error.session.expired=Ihre Sitzung ist abgelaufen. diff --git a/client/WEB-INF/classes/resources/messages_es.properties b/client/WEB-INF/classes/resources/messages_es.properties index 16cfc1cda49..86eb596689c 100644 --- a/client/WEB-INF/classes/resources/messages_es.properties +++ b/client/WEB-INF/classes/resources/messages_es.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - error.installWizard.message=Algo salio mal, debes ir para atr\u00e1s y corregir los error. error.login=Su nombre de usuario / contrase\u00c3\u00b1a no coincide con nuestros registros. error.mgmt.server.inaccessible=El Servidor de Gesti\u00c3\u00b3n es inaccesible. Por favor, int\u00c3\u00a9ntelo de nuevo m\u00c3\u00a1s tarde. diff --git a/client/WEB-INF/classes/resources/messages_fr_FR.properties b/client/WEB-INF/classes/resources/messages_fr_FR.properties index 8be438a11c1..33ffcfc4714 100644 --- a/client/WEB-INF/classes/resources/messages_fr_FR.properties +++ b/client/WEB-INF/classes/resources/messages_fr_FR.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=Propri\u00e9t\u00e9s de l\\'\u00e9l\u00e9ment modifi\u00e9es confirm.enable.s3=Remplir les informations suivantes pour activer le support de stockage secondaire S3 confirm.enable.swift=Remplir les informations suivantes pour activer Swift @@ -93,6 +92,7 @@ label.action.delete.load.balancer=Supprimer la r\u00e8gle de r\u00e9partition de label.action.delete.network.processing=Suppression du r\u00e9seau... label.action.delete.network=Supprimer le r\u00e9seau label.action.delete.nexusVswitch=Supprimer le Nexus 1000v +label.action.delete.nic=Supprimer carte NIC label.action.delete.physical.network=Supprimer le r\u00e9seau physique label.action.delete.pod.processing=Suppression du pod... label.action.delete.pod=Supprimer le Pod @@ -1200,6 +1200,7 @@ message.action.delete.ISO.for.all.zones=L\\'ISO est utilis\u00e9 par toutes les message.action.delete.ISO=\u00cates-vous s\u00fbr que vous souhaitez supprimer cette ISO. message.action.delete.network=\u00cates-vous s\u00fbr que vous voulez supprimer ce r\u00e9seau. message.action.delete.nexusVswitch=Confirmer la suppession de ce Nexus 1000v +message.action.delete.nic=Veuillez confirmer que vous souhaitez supprimer cette carte NIC, ce qui supprimera \u00e9galement le r\u00e9seau associ\u00e9 sur la machine virtuelle. message.action.delete.physical.network=Confirmer la suppression du r\u00e9seau physique message.action.delete.pod=\u00cates-vous s\u00fbr que vous souhaitez supprimer ce pod. message.action.delete.primary.storage=\u00cates-vous s\u00fbr que vous voulez supprimer ce stockage principal. @@ -1412,6 +1413,7 @@ message.migrate.router.confirm=Confirmer la migration du routeur vers \: message.migrate.systemvm.confirm=Confirmer la migration de la VM syst\u00e8me vers \: message.migrate.volume=Confirmer la migration du volume vers un autre stockage principal. message.new.user=Renseigner les informations suivantes pour ajouter un nouveau compte utilisateur +message.no.affinity.groups=Vous n\\'avez pas de groupes d\\'affinit\u00e9. Continuer vers la prochaine \u00e9tape. message.no.network.support.configuration.not.true=Il n\\'y a pas de zone avec la fonction groupe de s\u00e9curit\u00e9 active. D\u00e8s lors, pas de fonction r\u00e9seau suppl\u00e9mentaires disponibles. Continuer \u00e0 l\\'\u00e9tape 5. message.no.network.support=S\u00e9lectionnez l\\'hyperviseur. vSphere, n\\'a pas de fonctionnalit\u00e9s suppl\u00e9mentaires pour le r\u00e9seau. Continuez \u00e0 l\\'\u00e9tape 5. message.no.projects.adminOnly=Vous n\\'avez pas de projet.
Contacter votre administrateur pour ajouter un projet. @@ -1444,6 +1446,7 @@ message.restart.mgmt.usage.server=Red\u00e9marrer le ou les serveur(s) de gestio message.restart.network=Tous les services fournit par ce routeur virtuel vont \u00eatre interrompus. Confirmer le red\u00e9marrage de ce routeur. message.restart.vpc=Confirmer le red\u00e9marrage du VPC message.security.group.usage=(Utilisez Ctrl-clic pour s\u00e9lectionner les groupes de s\u00e9curit\u00e9 vis\u00e9s) +message.select.affinity.groups=S\u00e9lectionner les groupes d\\'affinit\u00e9 qui appartiendront \u00e0 cette machine virtuelle \: message.select.a.zone=Une zone correspond typiquement \u00e0 un seul centre de donn\u00e9es. Des zones multiples peuvent permettre de rendre votre cloud plus fiable en apportant une isolation physique et de la redondance. message.select.instance=S\u00e9lectionner une instance. message.select.iso=S\u00e9lectionner un ISO pour votre nouvelle instance virtuelle. diff --git a/client/WEB-INF/classes/resources/messages_it_IT.properties b/client/WEB-INF/classes/resources/messages_it_IT.properties index 78323b02578..6ae5bd85376 100644 --- a/client/WEB-INF/classes/resources/messages_it_IT.properties +++ b/client/WEB-INF/classes/resources/messages_it_IT.properties @@ -15,32 +15,207 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=Elementi delle propriet\u00e0 modificati confirm.enable.s3=Si prega di inserire i valori richiesti per abilitare il supporto per il Secondary Storage di tipo S3 confirm.enable.swift=Si prega di inserire i valori richiesti per abilitare il supporto per Swift error.could.not.enable.zone=Impossibile abilitare la zona error.installWizard.message=E\\' stato rilevato un errore\: tornare agli step precedenti e correggere gli errori error.invalid.username.password=Username o Password non valida +error.login=Le credenziali fornite per username/password non corrispondono a quelle nei nostri sistemi. +error.menu.select=Impossibile effettuare operazioni senza aver selezionato alcun elemento. +error.mgmt.server.inaccessible=Impossibile accedere al Management Server. Si prega di riprovare pi\u00f9 tardi. error.password.not.match=I campi password non corrispondono error.please.specify.physical.network.tags=Le offerte di rete non sono disponibili se non si specificano tag per questa rete fisica. +error.session.expired=La sessione \u00e8 scaduta. error.something.went.wrong.please.correct.the.following=E\\' stato rilevato un errore; si prega di correggere quanto indicato di seguito error.unable.to.reach.management.server=Impossibile raggiungere il Management Server +error.unresolved.internet.name=Il tuo nome internet non pu\u00f2 essere risolto. +extractable=Estraibile +force.delete.domain.warning=Attenzione\: La scelta di questa opzione provocher\u00e0 la rimozione di tutti i sotto domini e agli account associati e alle loro risorse. +force.remove.host.warning=Attenzione\: La scelta di questa opzione provocher\u00e0 l\\'arresto forzato di tutte le virtual machine da parte di CloudStack prima di rimuovere questo host dal cluster. +force.stop.instance.warning=Attenzione\: Forzare un arresto su questa instanza dovrebbe essere l\\'ultima opzione. C\\'\u00e8 il rischio di perdita di dati e di un comportamento inconsistente dello stato della virtual machine. +ICMP.code=Codice ICMP +ICMP.type=Tipo ICMP +image.directory=Directory Immagine instances.actions.reboot.label=Riavviare una instanza label.accept.project.invitation=Accettare un invito ad un progetto +label.account=Account label.account.and.security.group=Account, Security group +label.account.id=ID dell\\'Account +label.account.name=Nome Account +label.account.specific=Specifico dell\\'Account +label.accounts=Utenti +label.acquire.new.ip=Acquisizione nuovo indirizzo IP +label.action.attach.disk=Collegamento di un Disco +label.action.attach.disk.processing=Collegamento Disco in corso... +label.action.attach.iso=Collegamento di una immagine ISO +label.action.attach.iso.processing=Collegamento immagine ISO in corso... +label.action.cancel.maintenance.mode=Annullamento dello stato di Maintenance Mode +label.action.cancel.maintenance.mode.processing=Cancellazione dello stato Maintenance Mode in corso... +label.action.change.password=Modifica della Password +label.action.change.service=Modificare Servizio +label.action.change.service.processing=Modifica del Servizio in corso... +label.action.copy.ISO=Copia della immagine ISO +label.action.copy.ISO.processing=Copia immagine ISO in corso... +label.action.copy.template=Copia di un Template +label.action.copy.template.processing=Copia Template in corso... +label.action.create.template=Creazione Template +label.action.create.template.from.vm=Creazione Template da una VM +label.action.create.template.from.volume=Creazione Template da un Volume +label.action.create.template.processing=Creazione Template in corso... +label.action.create.vm=Creazione VM +label.action.create.vm.processing=Creazione VM in corso... +label.action.create.volume=Creazione Volume +label.action.create.volume.processing=Creazione Volume in corso... +label.action.delete.account=Cancellazione account +label.action.delete.account.processing=Cancellazione account in corso.... +label.action.delete.cluster=Cancellazione Cluster +label.action.delete.cluster.processing=Cancellazione Cluster in corso.... +label.action.delete.disk.offering=Cancellazione Offerta Disco +label.action.delete.disk.offering.processing=Cancellazione Offerta Disco in corso.... +label.action.delete.domain=Cancellazione Dominio +label.action.delete.domain.processing=Cancellazione Dominio in corso.... +label.action.delete.firewall=Cancellazione regola firewall +label.action.delete.firewall.processing=Cancellazione Firewall in corso.... +label.action.delete.IP.range=Cancellazione intervallo indirizzi IP +label.action.delete.IP.range.processing=Cancellazione intervallo indirizzi IP in corso.... +label.action.delete.ISO=Cancellazione immagine ISO +label.action.delete.ISO.processing=Cancellazione immagine ISO in corso.... +label.action.delete.load.balancer=Cancellazione regola load balancer +label.action.delete.load.balancer.processing=Cancellazione Load Balancer in corso.... +label.action.delete.network=Cancellazione Rete +label.action.delete.network.processing=Cancellazione Rete in corso.... label.action.delete.nexusVswitch=Cancellare Nexus 1000v label.action.delete.physical.network=Cancellazione di una rete fisica +label.action.delete.pod=Cancellazione Pod +label.action.delete.pod.processing=Cancellazione Pod in corso.... +label.action.delete.primary.storage=Cancellazione Storage Primario +label.action.delete.primary.storage.processing=Cancellazione Storage Primario in corso.... +label.action.delete.secondary.storage=Cancellazione Storage Secondario +label.action.delete.secondary.storage.processing=Cancellazione Storage Secondario in corso.... +label.action.delete.security.group=Cancellazione Security Group +label.action.delete.security.group.processing=Cancellazione Security Group in corso.... +label.action.delete.service.offering=Cancellazione Offerta di Servizio +label.action.delete.service.offering.processing=Cancellazione Offerta di Servizio in corso.... +label.action.delete.snapshot=Cancellazione Snapshot +label.action.delete.snapshot.processing=Cancellazione Snapshot in corso.... label.action.delete.system.service.offering=Cancellare Offerta di Servizio di Sistema +label.action.delete.template=Cancellazione Template +label.action.delete.template.processing=Cancellazione Template in corso.... +label.action.delete.user=Cancellazione Utente +label.action.delete.user.processing=Cancellazione Utente in corso.... +label.action.delete.volume=Cancellazione Volume +label.action.delete.volume.processing=Cancellazione Volume in corso.... +label.action.delete.zone=Cancellazione Zona +label.action.delete.zone.processing=Cancellazione Zona in corso.... +label.action.destroy.instance.processing=Rimozione Instanza in corso.... +label.action.destroy.instance=Rimozione instanza +label.action.destroy.systemvm.processing=Rimozione VM di Sistema in corso.... +label.action.destroy.systemvm=Rimozione VM di sistema +label.action.detach.disk.processing=Scollegamento Disco in corso.... +label.action.detach.disk=Scollegamento di un Disco +label.action.detach.iso.processing=Scollegamento immagine ISO in corso.... +label.action.detach.iso=Scollegamento immagine ISO +label.action.disable.account=Disabilitazione account +label.action.disable.account.processing=Disabilitazione account in corso.... +label.action.disable.cluster=Disabilitazione Cluster +label.action.disable.cluster.processing=Disabilitazione Cluster in corso.... label.action.disable.nexusVswitch=Disabilitare Nexus 1000v label.action.disable.physical.network=Disabilitare la rete fisica +label.action.disable.pod=Disabilitazione Pod +label.action.disable.pod.processing=Disabilitazione Pod in corso.... +label.action.disable.static.NAT=Disabilitazione NAT Statico +label.action.disable.static.NAT.processing=Disabilitazione NAT Statico in corso.... +label.action.disable.user=Disabilitazione Utente +label.action.disable.user.processing=Disabilitazione Utente in corso.... +label.action.disable.zone=Disabilitazione Zona +label.action.disable.zone.processing=Disabilitazione Zona in corso.... +label.action.download.ISO=Download immagine ISO +label.action.download.template=Download Template +label.action.download.volume=Download Volume +label.action.download.volume.processing=Download Volume in corso.... +label.action.edit.account=Modifica account +label.action.edit.disk.offering=Modifica Offerta Disco +label.action.edit.domain=Modifica Dominio +label.action.edit.global.setting=Modifica Impostazioni Globali +label.action.edit.host=Modifica Host +label.action.edit.instance=Modifica Instanza +label.action.edit.ISO=Modifica immagine ISO +label.action.edit.network=Modifica Rete +label.action.edit.network.offering=Modifica Offerta di Rete +label.action.edit.network.processing=Modifica Rete in corso.... +label.action.edit.pod=Modifica Pod +label.action.edit.primary.storage=Modifica Storage Primario +label.action.edit.resource.limits=Modifica Limiti delle Risorse +label.action.edit.service.offering=Modifica Offerta di Servizio +label.action.edit.template=Modifica Template +label.action.edit.user=Modifica Utente +label.action.edit.zone=Modifica Zona +label.action.enable.account=Abilitazione account +label.action.enable.account.processing=Abilitazione account in corso.... +label.action.enable.cluster=Abilitazione Cluster +label.action.enable.cluster.processing=Abilitazione Cluster in corso.... +label.action.enable.maintenance.mode=Abilitazione dello stato Maintenance Mode +label.action.enable.maintenance.mode.processing=Abilitazione dello stato Maintenance Mode in corso.... label.action.enable.nexusVswitch=Abilitare Nexus 1000v label.action.enable.physical.network=Abilitare la rete fisica +label.action.enable.pod=Abilitazione Pod +label.action.enable.pod.processing=Abilitazione Pod in corso.... +label.action.enable.static.NAT=Abilitazione NAT Statico +label.action.enable.static.NAT.processing=Abilitazione NAT Statico in corso.... +label.action.enable.user=Abilitazione Utente +label.action.enable.user.processing=Abilitazione Utente in corso.... +label.action.enable.zone=Abilitazione Zona +label.action.enable.zone.processing=Abilitazione Zona in corso.... +label.action.force.reconnect.processing=Riconnessione in corso.... +label.action.generate.keys=Generazione Chiavi +label.action.generate.keys.processing=Generazione Chiavi in corso.... label.action.list.nexusVswitch=Elencare Nexus 1000v +label.action.lock.account=Blocco di un account +label.action.lock.account.processing=Blocco account in corso.... +label.action.manage.cluster=Gestione Cluster +label.action.manage.cluster.processing=Gestione Cluster in corso.... +label.action.migrate.instance=Migrazione Instanza +label.action.migrate.instance.processing=Migrazione Instanza in corso.... +label.action.migrate.router=Migrazione Router label.action.migrate.router.processing=Migrazione Router... +label.action.migrate.systemvm=Migrazione VM di Systema +label.action.migrate.systemvm.processing=Migrazione VM di Sistema in corso.... +label.action.reboot.instance.processing=Riavvio Instanza in corso.... +label.action.reboot.instance=Riavvio Instanza +label.action.reboot.router.processing=Riavvio Router in corso.... +label.action.reboot.router=Riavvio Router +label.action.reboot.systemvm.processing=Riavvio VM di Sistema in corso.... +label.action.reboot.systemvm=Riavvio VM di Sistema label.action.register.iso=Registrare una ISO label.action.register.template=Registrare un template +label.action.release.ip.processing=Rilascio indirizzo IP in corso.... +label.action.release.ip=Rilascio indirizzo IP +label.action.remove.host.processing=Rimozione Host in corso.... +label.action.remove.host=Rimozione Host +label.action.reset.password.processing=Reset della Password in corso.... +label.action.reset.password=Reset Password +label.action.resize.volume.processing=Ridimensionamento Volume in corso.... +label.action.resize.volume=Ridimensionamento Volume +label.action.restore.instance.processing=Restore dell\\'Instanza in corso.... +label.action.restore.instance=Restore Instanza +label.actions=Azioni +label.action.start.instance=Avvio Instanza +label.action.start.instance.processing=Avvio Instanza in corso.... +label.action.start.router=Avvio Router +label.action.start.router.processing=Avvio Router in corso.... +label.action.start.systemvm=Avvio VM di Sistema +label.action.start.systemvm.processing=Avvio VM di Sistema in corso.... +label.action.stop.instance=Arresto Instanza +label.action.stop.instance.processing=Arresto Instanza in corso.... +label.action.stop.router=Arresto Router +label.action.stop.router.processing=Arresto Router in corso.... +label.action.stop.systemvm=Arresto VM di Sistema +label.action.stop.systemvm.processing=Arresto VM di Sistema in corso.... +label.action.update.OS.preference=Aggiornamento Preferenze OS +label.action.update.OS.preference.processing=Aggiornamento preferenze OS in corso.... label.activate.project=Attivare il Progetto +label.active.sessions=Sessioni Attive label.add.accounts=Aggiungere utenti label.add.accounts.to=Aggiungere utenti a label.add.account.to.project=Aggiungere account al progetto @@ -49,6 +224,7 @@ label.add.compute.offering=Aggiungere una offerta computazionale label.add.egress.rule=Aggiungere una regola d\\'uscita label.add.F5.device=Aggiungere device F5 label.add.guest.network=Aggiungere una rete guest +label.additional.networks=Network Aggiuntivi label.add.netScaler.device=Aggiungere device Netscaler label.add.network.ACL=Aggiungere le ACL di rete label.add.network.offering=Aggiungere offerta di rete @@ -76,22 +252,32 @@ label.add.vpn.customer.gateway=Aggiungere Gateway VPN del Cliente label.add.VPN.gateway=Aggiungere un Gateway VPN label.add.vpn.user=Aggiungere utente VPN label.advanced=Avanzato +label.advanced.search=Ricerca Avanzata label.agent.password=Password per l\\'Agent label.agent.username=Username per l\\'Agent label.allocated=Allocato label.apply=Applicare label.associated.network=Rete Associata +label.available.public.ips=Indirizzi IP Pubblici Disponibili label.bandwidth=Capacit\u00e0 della banda (Bandwidth) label.basic=Basic label.broadcast.uri=URI di Broadcast +label.cancel=Annulla +label.certificate=Certificato label.change.service.offering=Modificare offerta di servizio +label.character=Carattere label.checksum=Checksum MD5 +label.cidr=CIDR label.CIDR.list=Lista CIDR label.CIDR.of.destination.network=Valore CIDR della rete di destinazione label.clear.list=Pulizia dell\\'elenco +label.cloud.console=Console di Gestione Cloud label.cluster=Cluster label.cluster.name=Nome del Cluster label.clusters=Cluster +label.cluster.type=Tipo di Cluster +label.clvm=CLVM +label.code=Codice label.community=Community label.compute.and.storage=Computazione e Storage label.compute=Compute @@ -107,6 +293,7 @@ label.console.proxy=Proxy di Console label.continue.basic.install=Proseguire con l\\'installazione di base label.continue=Continuare label.corrections.saved=Salvataggio correzioni effettuato +label.cpu=CPU label.cpu.mhz=CPU (in MHz) label.created.by.system=Creato dal sistema label.create.project=Creare un progetto @@ -234,6 +421,7 @@ label.max.volumes=Numero max di volumi label.max.vpcs=Numero max di VPC label.may.continue=E\\' ora possibile continuare. label.memory.mb=Memoria (in MB) +label.menu.accounts=Utenti label.menu.configuration=Configurazione label.menu.infrastructure=Infrastruttura label.menu.system.service.offerings=Offerte di Sistema @@ -433,6 +621,7 @@ label.zone.name=Nome Zona label.zones=Zone label.zone.type=Tipo di Zona label.zoneWizard.trafficType.guest=Guest\: Traffico di rete tra le virtual machine dell\\'utente finale +label.zoneWizard.trafficType.management=Management\: Traffico di rete tra le risorse interne di CloudStack, incluso qualsiasi componente che comunichi con il Management Server, come ad esempio gli host e le VM di Sistema di CloudStack label.zoneWizard.trafficType.public=Public\: Traffico di rete tra la rete internet e le virtual machine nell\\'infrastruttura cloud. label.zoneWizard.trafficType.storage=Storage\: Traffico di rete tra i server di primary e secondary storage, come ad esempio i template delle VM e le operazioni di snapshot message.acquire.new.ip=Si prega di confermare di voler acquisire un nuovo indirizzo IP per questa rete. diff --git a/client/WEB-INF/classes/resources/messages_ja.properties b/client/WEB-INF/classes/resources/messages_ja.properties index e483a97804b..a6075958d6a 100644 --- a/client/WEB-INF/classes/resources/messages_ja.properties +++ b/client/WEB-INF/classes/resources/messages_ja.properties @@ -23,7 +23,7 @@ error.could.not.enable.zone=\u30be\u30fc\u30f3\u3092\u6709\u52b9\u306b\u3067\u30 error.installWizard.message=\u554f\u984c\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\u623b\u3063\u3066\u30a8\u30e9\u30fc\u3092\u4fee\u6b63\u3067\u304d\u307e\u3059\u3002 error.invalid.username.password=\u7121\u52b9\u306a\u30e6\u30fc\u30b6\u30fc\u540d\u307e\u305f\u306f\u30d1\u30b9\u30ef\u30fc\u30c9 error.login=\u30e6\u30fc\u30b6\u30fc\u540d/\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u8a18\u9332\u3068\u4e00\u81f4\u3057\u307e\u305b\u3093\u3002 -error.menu.select=\u00e3\u0082\u00a2\u00e3\u0082\u00a4\u00e3\u0083\u0086\u00e3\u0083\u00a0\u00e3\u0081\u008c\u00e9\u0081\u00b8\u00e6\u008a\u009e\u00e3\u0081\u0095\u00e3\u0082\u008c\u00e3\u0081\u00a6\u00e3\u0081\u0084\u00e3\u0081\u00aa\u00e3\u0081\u0084\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0082\u00a2\u00e3\u0082\u00af\u00e3\u0082\u00b7\u00e3\u0083\u00a7\u00e3\u0083\u00b3\u00e3\u0082\u0092\u00e5\u00ae\u009f\u00e8\u00a1\u008c\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0081\u0093\u00e3\u0081\u00a8\u00e3\u0081\u008c\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00be\u00e3\u0081\u009b\u00e3\u0082\u0093 +error.menu.select=\u9805\u76ee\u304c\u9078\u629e\u3055\u308c\u3066\u3044\u306a\u3044\u305f\u3081\u64cd\u4f5c\u3092\u5b9f\u884c\u3067\u304d\u307e\u305b\u3093\u3002 error.mgmt.server.inaccessible=\u7ba1\u7406\u30b5\u30fc\u30d0\u30fc\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u305b\u3093\u3002\u5f8c\u3067\u518d\u5b9f\u884c\u3057\u3066\u304f\u3060\u3055\u3044\u3002 error.password.not.match=\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u4e00\u81f4\u3057\u307e\u305b\u3093 error.please.specify.physical.network.tags=\u3053\u306e\u7269\u7406\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306e\u30bf\u30b0\u3092\u6307\u5b9a\u3057\u306a\u3051\u308c\u3070\u3001\u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u306f\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093\u3002 @@ -32,11 +32,11 @@ error.something.went.wrong.please.correct.the.following=\u554f\u984c\u304c\u767a error.unable.to.reach.management.server=\u7ba1\u7406\u30b5\u30fc\u30d0\u30fc\u3068\u901a\u4fe1\u3067\u304d\u307e\u305b\u3093 error.unresolved.internet.name=\u3042\u306a\u305f\u306e\u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u540d\u306f\u89e3\u6c7a\u3055\u308c\u307e\u305b\u3093\u3067\u3057\u305f\u3002 extractable=\u62bd\u51fa\u53ef\u80fd -force.delete.domain.warning=\u8b66\u544a\: \u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3059\u308b\u3068\u3001\u3059\u3079\u3066\u306e\u5b50\u30c9\u30e1\u30a4\u30f3\u304a\u3088\u3073\u95a2\u9023\u3059\u308b\u3059\u3079\u3066\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u3068\u305d\u306e\u30ea\u30bd\u30fc\u30b9\u304c\u524a\u9664\u3055\u308c\u307e\u3059\u3002 +force.delete.domain.warning=\u8b66\u544a: \u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3059\u308b\u3068\u3001\u3059\u3079\u3066\u306e\u5b50\u30c9\u30e1\u30a4\u30f3\u304a\u3088\u3073\u95a2\u9023\u3059\u308b\u3059\u3079\u3066\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u3068\u305d\u306e\u30ea\u30bd\u30fc\u30b9\u304c\u524a\u9664\u3055\u308c\u307e\u3059\u3002 force.delete=\u5f37\u5236\u524a\u9664 -force.remove.host.warning=\u8b66\u544a\: \u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3059\u308b\u3068\u3001\u5b9f\u884c\u4e2d\u306e\u3059\u3079\u3066\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u304c\u5f37\u5236\u7684\u306b\u505c\u6b62\u3055\u308c\u3001\u30af\u30e9\u30b9\u30bf\u30fc\u304b\u3089\u3053\u306e\u30db\u30b9\u30c8\u304c\u5f37\u5236\u7684\u306b\u89e3\u9664\u3055\u308c\u307e\u3059\u3002 +force.remove.host.warning=\u8b66\u544a: \u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3059\u308b\u3068\u3001\u5b9f\u884c\u4e2d\u306e\u3059\u3079\u3066\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u304c\u5f37\u5236\u7684\u306b\u505c\u6b62\u3055\u308c\u3001\u30af\u30e9\u30b9\u30bf\u30fc\u304b\u3089\u3053\u306e\u30db\u30b9\u30c8\u304c\u5f37\u5236\u7684\u306b\u89e3\u9664\u3055\u308c\u307e\u3059\u3002 force.remove=\u5f37\u5236\u89e3\u9664 -force.stop.instance.warning=\u8b66\u544a\: \u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u5f37\u5236\u505c\u6b62\u306f\u3001\u6700\u7d42\u624b\u6bb5\u306b\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30c7\u30fc\u30bf\u3092\u640d\u5931\u3059\u308b\u3060\u3051\u3067\u306a\u304f\u3001\u4eee\u60f3\u30de\u30b7\u30f3\u306e\u52d5\u4f5c\u304c\u4e00\u8cab\u3057\u306a\u304f\u306a\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +force.stop.instance.warning=\u8b66\u544a: \u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u5f37\u5236\u505c\u6b62\u306f\u3001\u6700\u7d42\u624b\u6bb5\u306b\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30c7\u30fc\u30bf\u3092\u640d\u5931\u3059\u308b\u3060\u3051\u3067\u306a\u304f\u3001\u4eee\u60f3\u30de\u30b7\u30f3\u306e\u52d5\u4f5c\u304c\u4e00\u8cab\u3057\u306a\u304f\u306a\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 force.stop=\u5f37\u5236\u505c\u6b62 ICMP.code=ICMP \u30b3\u30fc\u30c9 ICMP.type=ICMP \u306e\u7a2e\u985e @@ -230,7 +230,7 @@ label.action.update.resource.count.processing=\u30ea\u30bd\u30fc\u30b9\u6570\u30 label.action.update.resource.count=\u30ea\u30bd\u30fc\u30b9\u6570\u306e\u66f4\u65b0 label.activate.project=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u30a2\u30af\u30c6\u30a3\u30d6\u5316 label.active.sessions=\u30a2\u30af\u30c6\u30a3\u30d6\u306a\u30bb\u30c3\u30b7\u30e7\u30f3 -label.add.accounts.to=\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u8ffd\u52a0\u5148\: +label.add.accounts.to=\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u8ffd\u52a0\u5148: label.add.accounts=\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u8ffd\u52a0 label.add.account.to.project=\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3078\u306e\u8ffd\u52a0 label.add.account=\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u8ffd\u52a0 @@ -456,7 +456,7 @@ label.domain.admin=\u30c9\u30e1\u30a4\u30f3\u7ba1\u7406\u8005 label.domain.id=\u30c9\u30e1\u30a4\u30f3 ID label.domain.name=\u30c9\u30e1\u30a4\u30f3\u540d label.domain.router=\u30c9\u30e1\u30a4\u30f3 \u30eb\u30fc\u30bf\u30fc -label.domain.suffix=DNS \u30c9\u30e1\u30a4\u30f3 \u30b5\u30d5\u30a3\u30c3\u30af\u30b9 (\u4f8b\: xyz.com) +label.domain.suffix=DNS \u30c9\u30e1\u30a4\u30f3 \u30b5\u30d5\u30a3\u30c3\u30af\u30b9 (\u4f8b: xyz.com) label.domain=\u30c9\u30e1\u30a4\u30f3 label.done=\u5b8c\u4e86 label.double.quotes.are.not.allowed=\u4e8c\u91cd\u5f15\u7528\u7b26\u306f\u4f7f\u7528\u3067\u304d\u307e\u305b\u3093 @@ -534,7 +534,7 @@ label.host.alerts=\u30db\u30b9\u30c8 \u30a2\u30e9\u30fc\u30c8 label.host.MAC=\u30db\u30b9\u30c8\u306e MAC label.host.name=\u30db\u30b9\u30c8\u540d label.hosts=\u30db\u30b9\u30c8 -label.host.tags=\u00e3\u0083\u009b\u00e3\u0082\u00b9\u00e3\u0083\u0088\u00e3\u0082\u00bf\u00e3\u0082\u00b0 +label.host.tags=\u30db\u30b9\u30c8 \u30bf\u30b0 label.host=\u30db\u30b9\u30c8 label.hourly=\u6bce\u6642 label.hypervisor.capabilities=\u30cf\u30a4\u30d1\u30fc\u30d0\u30a4\u30b6\u30fc\u306e\u6a5f\u80fd @@ -563,8 +563,8 @@ label.installWizard.addZoneIntro.subtitle=\u30be\u30fc\u30f3\u306b\u3064\u3044\u label.installWizard.addZoneIntro.title=\u30be\u30fc\u30f3\u3092\u8ffd\u52a0\u3057\u307e\u3057\u3087\u3046 label.installWizard.addZone.title=\u30be\u30fc\u30f3\u306e\u8ffd\u52a0 label.installWizard.click.launch=[\u8d77\u52d5] \u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -label.installWizard.subtitle=\u3053\u306e\u30ac\u30a4\u30c9 \u30c4\u30a2\u30fc\u306f CloudStack&\#8482; \u74b0\u5883\u306e\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u306b\u5f79\u7acb\u3061\u307e\u3059 -label.installWizard.title=CloudStack&\#8482; \u3078\u3088\u3046\u3053\u305d +label.installWizard.subtitle=\u3053\u306e\u30ac\u30a4\u30c9 \u30c4\u30a2\u30fc\u306f CloudStack™ \u74b0\u5883\u306e\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u306b\u5f79\u7acb\u3061\u307e\u3059 +label.installWizard.title=CloudStack™ \u3078\u3088\u3046\u3053\u305d label.instance.limits=\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u5236\u9650 label.instance.name=\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u540d label.instances=\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9 @@ -573,12 +573,12 @@ label.internal.dns.1=\u5185\u90e8 DNS 1 label.internal.dns.2=\u5185\u90e8 DNS 2 label.internal.name=\u5185\u90e8\u540d label.interval.type=\u9593\u9694\u306e\u7a2e\u985e -label.introduction.to.cloudstack=CloudStack&\#8482; \u306e\u7d39\u4ecb +label.introduction.to.cloudstack=CloudStack™ \u306e\u7d39\u4ecb label.invalid.integer=\u7121\u52b9\u306a\u6574\u6570 label.invalid.number=\u7121\u52b9\u306a\u6570 label.invitations=\u62db\u5f85\u72b6 label.invited.accounts=\u62db\u5f85\u6e08\u307f\u30a2\u30ab\u30a6\u30f3\u30c8 -label.invite.to=\u62db\u5f85\u3059\u308b\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\: +label.invite.to=\u62db\u5f85\u3059\u308b\u30d7\u30ed\u30b8\u30a7\u30af\u30c8: label.invite=\u62db\u5f85 label.ip.address=IP \u30a2\u30c9\u30ec\u30b9 label.ipaddress=IP \u30a2\u30c9\u30ec\u30b9 @@ -695,9 +695,9 @@ label.menu.virtual.resources=\u4eee\u60f3\u30ea\u30bd\u30fc\u30b9 label.menu.volumes=\u30dc\u30ea\u30e5\u30fc\u30e0 label.migrate.instance.to.host=\u5225\u306e\u30db\u30b9\u30c8\u3078\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u79fb\u884c label.migrate.instance.to.ps=\u5225\u306e\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3078\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u79fb\u884c -label.migrate.instance.to=\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u79fb\u884c\u5148\: -label.migrate.router.to=\u30eb\u30fc\u30bf\u30fc\u306e\u79fb\u884c\u5148\: -label.migrate.systemvm.to=\u30b7\u30b9\u30c6\u30e0 VM \u306e\u79fb\u884c\u5148\: +label.migrate.instance.to=\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u79fb\u884c\u5148: +label.migrate.router.to=\u30eb\u30fc\u30bf\u30fc\u306e\u79fb\u884c\u5148: +label.migrate.systemvm.to=\u30b7\u30b9\u30c6\u30e0 VM \u306e\u79fb\u884c\u5148: label.migrate.to.host=\u30db\u30b9\u30c8\u3078\u79fb\u884c label.migrate.to.storage=\u30b9\u30c8\u30ec\u30fc\u30b8\u3078\u79fb\u884c label.migrate.volume=\u5225\u306e\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3078\u306e\u30dc\u30ea\u30e5\u30fc\u30e0\u306e\u79fb\u884c @@ -785,7 +785,7 @@ label.os.preference=OS \u57fa\u672c\u8a2d\u5b9a label.os.type=OS \u306e\u7a2e\u985e label.owned.public.ips=\u6240\u6709\u3059\u308b\u30d1\u30d6\u30ea\u30c3\u30af IP \u30a2\u30c9\u30ec\u30b9 label.owner.account=\u6240\u6709\u8005\u30a2\u30ab\u30a6\u30f3\u30c8 -label.owner.domain=\u00e6\u0089\u0080\u00e6\u009c\u0089\u00e8\u0080 +label.owner.domain=\u6240\u6709\u8005\u30c9\u30e1\u30a4\u30f3 label.parent.domain=\u89aa\u30c9\u30e1\u30a4\u30f3 label.password.enabled=\u30d1\u30b9\u30ef\u30fc\u30c9\u7ba1\u7406\u6709\u52b9 label.password=\u30d1\u30b9\u30ef\u30fc\u30c9 @@ -817,7 +817,7 @@ label.private.interface=\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 \u30a4\u30f3\u30bf\ label.private.ip.range=\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2 label.private.ips=\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 IP \u30a2\u30c9\u30ec\u30b9 label.private.ip=\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 IP \u30a2\u30c9\u30ec\u30b9 -label.privatekey=PKC\#8 \u79d8\u5bc6\u30ad\u30fc +label.privatekey=PKC#8 \u79d8\u5bc6\u30ad\u30fc label.private.network=\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 \u30cd\u30c3\u30c8\u30ef\u30fc\u30af label.private.port=\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 \u30dd\u30fc\u30c8 label.private.zone=\u30d7\u30e9\u30a4\u30d9\u30fc\u30c8 \u30be\u30fc\u30f3 @@ -951,7 +951,7 @@ label.start.reserved.system.IP=\u4e88\u7d04\u6e08\u307f\u958b\u59cb\u30b7\u30b9\ label.start.vlan=\u958b\u59cb VLAN label.state=\u72b6\u614b label.static.nat.enabled=\u9759\u7684 NAT \u6709\u52b9 -label.static.nat.to=\u9759\u7684 NAT \u306e\u8a2d\u5b9a\u5148\: +label.static.nat.to=\u9759\u7684 NAT \u306e\u8a2d\u5b9a\u5148: label.static.nat=\u9759\u7684 NAT label.static.nat.vm.details=\u9759\u7684 NAT VM \u306e\u8a73\u7d30 label.statistics=\u7d71\u8a08 @@ -960,7 +960,7 @@ label.step.1.title=\u624b\u9806 1. \u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\ label.step.1=\u624b\u9806 1 label.step.2.title=\u624b\u9806 2. \u30b5\u30fc\u30d3\u30b9 \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0 label.step.2=\u624b\u9806 2 -label.step.3.title=\u624b\u9806 3. \u30c7\u30a3\u30b9\u30af \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u306e\u9078\u629e +label.step.3.title=\u624b\u9806 3. \u30c7\u30a3\u30b9\u30af \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u306e\u9078\u629e label.step.3=\u624b\u9806 3 label.step.4.title=\u624b\u9806 4. \u30cd\u30c3\u30c8\u30ef\u30fc\u30af label.step.4=\u624b\u9806 4 @@ -986,7 +986,7 @@ label.storage.traffic=\u30b9\u30c8\u30ec\u30fc\u30b8 \u30c8\u30e9\u30d5\u30a3\u3 label.storage.type=\u30b9\u30c8\u30ec\u30fc\u30b8\u306e\u7a2e\u985e label.storage=\u30b9\u30c8\u30ec\u30fc\u30b8 label.subdomain.access=\u30b5\u30d6\u30c9\u30e1\u30a4\u30f3 \u30a2\u30af\u30bb\u30b9 -label.submitted.by=[\u9001\u4fe1\u30e6\u30fc\u30b6\u30fc\: ] +label.submitted.by=[\u9001\u4fe1\u30e6\u30fc\u30b6\u30fc: ] label.submit=\u9001\u4fe1 label.succeeded=\u6210\u529f label.sunday=\u65e5\u66dc\u65e5 @@ -1061,7 +1061,7 @@ label.vcipaddress=vCenter IP \u30a2\u30c9\u30ec\u30b9 label.version=\u30d0\u30fc\u30b8\u30e7\u30f3 label.view.all=\u3059\u3079\u3066\u8868\u793a label.view.console=\u30b3\u30f3\u30bd\u30fc\u30eb\u306e\u8868\u793a -label.viewing=\u8868\u793a\u9805\u76ee\: +label.viewing=\u8868\u793a\u9805\u76ee: label.view.more=\u8a73\u7d30\u8868\u793a label.view=\u8868\u793a - label.virtual.appliances=\u4eee\u60f3\u30a2\u30d7\u30e9\u30a4\u30a2\u30f3\u30b9 @@ -1110,7 +1110,7 @@ label.wednesday=\u6c34\u66dc\u65e5 label.weekly=\u6bce\u9031 label.welcome.cloud.console=\u7ba1\u7406\u30b3\u30f3\u30bd\u30fc\u30eb\u3078\u3088\u3046\u3053\u305d label.welcome=\u3088\u3046\u3053\u305d -label.what.is.cloudstack=CloudStack&\#8482; \u306b\u3064\u3044\u3066 +label.what.is.cloudstack=CloudStack™ \u306b\u3064\u3044\u3066 label.xen.traffic.label=XenServer \u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u306e\u30e9\u30d9\u30eb label.yes=\u306f\u3044 label.zone.details=\u30be\u30fc\u30f3\u306e\u8a73\u7d30 @@ -1124,9 +1124,9 @@ label.zones=\u30be\u30fc\u30f3 label.zone.type=\u30be\u30fc\u30f3\u306e\u7a2e\u985e label.zone=\u30be\u30fc\u30f3 label.zone.wide=\u30be\u30fc\u30f3\u5168\u4f53 -label.zoneWizard.trafficType.guest=\u30b2\u30b9\u30c8\: \u30a8\u30f3\u30c9\u30e6\u30fc\u30b6\u30fc\u4eee\u60f3\u30de\u30b7\u30f3\u9593\u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af -label.zoneWizard.trafficType.public=\u30d1\u30d6\u30ea\u30c3\u30af\: \u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u3068\u30af\u30e9\u30a6\u30c9\u5185\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u306e\u9593\u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af -label.zoneWizard.trafficType.storage=\u30b9\u30c8\u30ec\u30fc\u30b8\: VM\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3068\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u306e\u3088\u3046\u306a\u3001\u30d7\u30e9\u30a4\u30de\u30ea\u3068\u30bb\u30ab\u30f3\u30c0\u30ea\u306e\u30b9\u30c8\u30ec\u30fc\u30b8\u30b5\u30fc\u30d0\u30fc\u9593\u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u3002 +label.zoneWizard.trafficType.guest=\u30b2\u30b9\u30c8: \u30a8\u30f3\u30c9\u30e6\u30fc\u30b6\u30fc\u4eee\u60f3\u30de\u30b7\u30f3\u9593\u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af +label.zoneWizard.trafficType.public=\u30d1\u30d6\u30ea\u30c3\u30af: \u30a4\u30f3\u30bf\u30fc\u30cd\u30c3\u30c8\u3068\u30af\u30e9\u30a6\u30c9\u5185\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u306e\u9593\u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af +label.zoneWizard.trafficType.storage=\u30b9\u30c8\u30ec\u30fc\u30b8: VM\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3068\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u306e\u3088\u3046\u306a\u3001\u30d7\u30e9\u30a4\u30de\u30ea\u3068\u30bb\u30ab\u30f3\u30c0\u30ea\u306e\u30b9\u30c8\u30ec\u30fc\u30b8\u30b5\u30fc\u30d0\u30fc\u9593\u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u3002 managed.state=\u7ba1\u7406\u5bfe\u8c61\u72b6\u614b message.acquire.new.ip=\u3053\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306e\u65b0\u3057\u3044 IP \u30a2\u30c9\u30ec\u30b9\u3092\u53d6\u5f97\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.acquire.new.ip.vpc=VPC\u306e\u65b0\u3057\u3044IP\u3092\u53d6\u5f97\u3059\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 @@ -1138,8 +1138,8 @@ message.action.change.service.warning.for.router=\u73fe\u5728\u306e\u30b5\u30fc\ message.action.delete.cluster=\u3053\u306e\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.delete.disk.offering=\u3053\u306e\u30c7\u30a3\u30b9\u30af \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.delete.domain=\u3053\u306e\u30c9\u30e1\u30a4\u30f3\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.action.delete.external.firewall=\u3053\u306e\u5916\u90e8\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? \u8b66\u544a\: \u540c\u3058\u5916\u90e8\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u3092\u518d\u5ea6\u8ffd\u52a0\u3059\u308b\u4e88\u5b9a\u3067\u3042\u308b\u5834\u5408\u306f\u3001\u30c7\u30d0\u30a4\u30b9\u306e\u4f7f\u7528\u72b6\u6cc1\u30c7\u30fc\u30bf\u3092\u30ea\u30bb\u30c3\u30c8\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 -message.action.delete.external.load.balancer=\u3053\u306e\u5916\u90e8\u8ca0\u8377\u5206\u6563\u88c5\u7f6e\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? \u8b66\u544a\: \u540c\u3058\u5916\u90e8\u8ca0\u8377\u5206\u6563\u88c5\u7f6e\u3092\u518d\u5ea6\u8ffd\u52a0\u3059\u308b\u4e88\u5b9a\u3067\u3042\u308b\u5834\u5408\u306f\u3001\u30c7\u30d0\u30a4\u30b9\u306e\u4f7f\u7528\u72b6\u6cc1\u30c7\u30fc\u30bf\u3092\u30ea\u30bb\u30c3\u30c8\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 +message.action.delete.external.firewall=\u3053\u306e\u5916\u90e8\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? \u8b66\u544a: \u540c\u3058\u5916\u90e8\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u3092\u518d\u5ea6\u8ffd\u52a0\u3059\u308b\u4e88\u5b9a\u3067\u3042\u308b\u5834\u5408\u306f\u3001\u30c7\u30d0\u30a4\u30b9\u306e\u4f7f\u7528\u72b6\u6cc1\u30c7\u30fc\u30bf\u3092\u30ea\u30bb\u30c3\u30c8\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 +message.action.delete.external.load.balancer=\u3053\u306e\u5916\u90e8\u8ca0\u8377\u5206\u6563\u88c5\u7f6e\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? \u8b66\u544a: \u540c\u3058\u5916\u90e8\u8ca0\u8377\u5206\u6563\u88c5\u7f6e\u3092\u518d\u5ea6\u8ffd\u52a0\u3059\u308b\u4e88\u5b9a\u3067\u3042\u308b\u5834\u5408\u306f\u3001\u30c7\u30d0\u30a4\u30b9\u306e\u4f7f\u7528\u72b6\u6cc1\u30c7\u30fc\u30bf\u3092\u30ea\u30bb\u30c3\u30c8\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 message.action.delete.ingress.rule=\u3053\u306e\u53d7\u4fe1\u898f\u5247\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.delete.ISO.for.all.zones=\u305d\u306e ISO \u306f\u3059\u3079\u3066\u306e\u30be\u30fc\u30f3\u3067\u4f7f\u7528\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u3059\u3079\u3066\u306e\u30be\u30fc\u30f3\u304b\u3089\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.delete.ISO=\u3053\u306e ISO \u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? @@ -1175,9 +1175,9 @@ message.action.enable.pod=\u3053\u306e\u30dd\u30c3\u30c9\u3092\u6709\u52b9\u306b message.action.enable.zone=\u3053\u306e\u30be\u30fc\u30f3\u3092\u6709\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.force.reconnect=\u30db\u30b9\u30c8\u306f\u5f37\u5236\u7684\u306b\u518d\u63a5\u7d9a\u3057\u307e\u3057\u305f\u3002\u3053\u306e\u51e6\u7406\u306b\u306f\u6570\u5206\u304b\u304b\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 message.action.host.enable.maintenance.mode=\u4fdd\u5b88\u30e2\u30fc\u30c9\u3092\u6709\u52b9\u306b\u3059\u308b\u3068\u3001\u3053\u306e\u30db\u30b9\u30c8\u3067\u5b9f\u884c\u4e2d\u306e\u3059\u3079\u3066\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u304c\u307b\u304b\u306e\u4f7f\u7528\u3067\u304d\u308b\u30db\u30b9\u30c8\u306b\u30e9\u30a4\u30d6 \u30de\u30a4\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u3055\u308c\u307e\u3059\u3002 -message.action.instance.reset.password=\u00e3\u0081\u0093\u00e3\u0081\u00ae\u00e4\u00bb\u00ae\u00e6\u0083\u00b3\u00e3\u0083\u009e\u00e3\u0082\u00b7\u00e3\u0083\u00b3\u00e3\u0081\u00ae\u00e3\u0083\u00ab\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0083\u0091\u00e3\u0082\u00b9\u00e3\u0083\u00af\u00e3\u0083\u00bc\u00e3\u0083\u0089\u00e3\u0082\u0092\u00e5\u00a4\u0089\u00e6\u009b\u00b4\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0082\u0082\u00e3\u0082\u0088\u00e3\u0082\u008d\u00e3\u0081\u0097\u00e3\u0081\u0084\u00e3\u0081\u00a7\u00e3\u0081\u0099\u00e3\u0081\u008b? +message.action.instance.reset.password=\u3053\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u306e\u30eb\u30fc\u30c8 \u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5909\u66f4\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.manage.cluster=\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u7ba1\u7406\u5bfe\u8c61\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.action.primarystorage.enable.maintenance.mode=\u8b66\u544a\: \u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u4fdd\u5b88\u30e2\u30fc\u30c9\u306b\u3059\u308b\u3068\u3001\u305d\u306e\u30b9\u30c8\u30ec\u30fc\u30b8\u4e0a\u306e\u30dc\u30ea\u30e5\u30fc\u30e0\u3092\u4f7f\u7528\u3059\u308b\u3059\u3079\u3066\u306e VM \u304c\u505c\u6b62\u3057\u307e\u3059\u3002\u7d9a\u884c\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? +message.action.primarystorage.enable.maintenance.mode=\u8b66\u544a: \u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u4fdd\u5b88\u30e2\u30fc\u30c9\u306b\u3059\u308b\u3068\u3001\u305d\u306e\u30b9\u30c8\u30ec\u30fc\u30b8\u4e0a\u306e\u30dc\u30ea\u30e5\u30fc\u30e0\u3092\u4f7f\u7528\u3059\u308b\u3059\u3079\u3066\u306e VM \u304c\u505c\u6b62\u3057\u307e\u3059\u3002\u7d9a\u884c\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.reboot.instance=\u3053\u306e\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3092\u518d\u8d77\u52d5\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.reboot.router=\u3053\u306e\u4eee\u60f3\u30eb\u30fc\u30bf\u30fc\u3067\u63d0\u4f9b\u3059\u308b\u3059\u3079\u3066\u306e\u30b5\u30fc\u30d3\u30b9\u304c\u4e2d\u65ad\u3055\u308c\u307e\u3059\u3002\u3053\u306e\u30eb\u30fc\u30bf\u30fc\u3092\u518d\u8d77\u52d5\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.reboot.systemvm=\u3053\u306e\u30b7\u30b9\u30c6\u30e0 VM \u3092\u518d\u8d77\u52d5\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? @@ -1195,8 +1195,8 @@ message.action.stop.systemvm=\u3053\u306e\u30b7\u30b9\u30c6\u30e0 VM \u3092\u505 message.action.take.snapshot=\u3053\u306e\u30dc\u30ea\u30e5\u30fc\u30e0\u306e\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8\u3092\u4f5c\u6210\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.action.unmanage.cluster=\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u975e\u7ba1\u7406\u5bfe\u8c61\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.activate.project=\u3053\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u30a2\u30af\u30c6\u30a3\u30d6\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.add.cluster=\u30be\u30fc\u30f3 \u306e\u30dd\u30c3\u30c9 \u306b\u30cf\u30a4\u30d1\u30fc\u30d0\u30a4\u30b6\u30fc\u3067\u7ba1\u7406\u3055\u308c\u308b\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u8ffd\u52a0\u3057\u307e\u3059 -message.add.cluster.zone=\u30be\u30fc\u30f3 \u306b\u30cf\u30a4\u30d1\u30fc\u30d0\u30a4\u30b6\u30fc\u3067\u7ba1\u7406\u3055\u308c\u308b\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u8ffd\u52a0\u3057\u307e\u3059 +message.add.cluster=\u30be\u30fc\u30f3 \u306e\u30dd\u30c3\u30c9 \u306b\u30cf\u30a4\u30d1\u30fc\u30d0\u30a4\u30b6\u30fc\u3067\u7ba1\u7406\u3055\u308c\u308b\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u8ffd\u52a0\u3057\u307e\u3059 +message.add.cluster.zone=\u30be\u30fc\u30f3 \u306b\u30cf\u30a4\u30d1\u30fc\u30d0\u30a4\u30b6\u30fc\u3067\u7ba1\u7406\u3055\u308c\u308b\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u8ffd\u52a0\u3057\u307e\u3059 message.add.disk.offering=\u65b0\u3057\u3044\u30c7\u30a3\u30b9\u30af \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.add.domain=\u3053\u306e\u30c9\u30e1\u30a4\u30f3\u306b\u4f5c\u6210\u3059\u308b\u30b5\u30d6\u30c9\u30e1\u30a4\u30f3\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.add.firewall=\u30be\u30fc\u30f3\u306b\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u3092\u8ffd\u52a0\u3057\u307e\u3059 @@ -1205,18 +1205,18 @@ message.add.host=\u65b0\u3057\u3044\u30db\u30b9\u30c8\u3092\u8ffd\u52a0\u3059\u3 message.adding.host=\u30db\u30b9\u30c8\u3092\u8ffd\u52a0\u3057\u3066\u3044\u307e\u3059 message.adding.Netscaler.device=Netscaler \u30c7\u30d0\u30a4\u30b9\u3092\u8ffd\u52a0\u3057\u3066\u3044\u307e\u3059 message.adding.Netscaler.provider=Netscaler \u30d7\u30ed\u30d0\u30a4\u30c0\u30fc\u3092\u8ffd\u52a0\u3057\u3066\u3044\u307e\u3059 -message.add.ip.range.direct.network=\u30be\u30fc\u30f3 \u306e\u76f4\u63a5\u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u306b IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3092\u8ffd\u52a0\u3057\u307e\u3059 -message.add.ip.range.to.pod=

\u30dd\u30c3\u30c9 \u306b IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3092\u8ffd\u52a0\u3057\u307e\u3059

+message.add.ip.range.direct.network=\u30be\u30fc\u30f3 \u306e\u76f4\u63a5\u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u306b IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3092\u8ffd\u52a0\u3057\u307e\u3059 +message.add.ip.range.to.pod=

\u30dd\u30c3\u30c9 \u306b IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3092\u8ffd\u52a0\u3057\u307e\u3059

message.add.ip.range=\u30be\u30fc\u30f3\u306e\u30d1\u30d6\u30ea\u30c3\u30af \u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306b IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3092\u8ffd\u52a0\u3057\u307e\u3059 message.additional.networks.desc=\u4eee\u60f3\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u304c\u63a5\u7d9a\u3059\u308b\u8ffd\u52a0\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.add.load.balancer=\u30be\u30fc\u30f3\u306b\u8ca0\u8377\u5206\u6563\u88c5\u7f6e\u3092\u8ffd\u52a0\u3057\u307e\u3059 -message.add.load.balancer.under.ip=\u8ca0\u8377\u5206\u6563\u898f\u5247\u304c\u6b21\u306e IP \u30a2\u30c9\u30ec\u30b9\u306b\u5bfe\u3057\u3066\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f\: -message.add.network=\u30be\u30fc\u30f3 \u306b\u65b0\u3057\u3044\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u8ffd\u52a0\u3057\u307e\u3059 +message.add.load.balancer.under.ip=\u8ca0\u8377\u5206\u6563\u898f\u5247\u304c\u6b21\u306e IP \u30a2\u30c9\u30ec\u30b9\u306b\u5bfe\u3057\u3066\u8ffd\u52a0\u3055\u308c\u307e\u3057\u305f: +message.add.network=\u30be\u30fc\u30f3 \u306b\u65b0\u3057\u3044\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u8ffd\u52a0\u3057\u307e\u3059 message.add.new.gateway.to.vpc=\u3053\u306e VPC \u306b\u65b0\u3057\u3044\u30b2\u30fc\u30c8\u30a6\u30a7\u30a4\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306e\u60c5\u5831\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.add.pod=\u30be\u30fc\u30f3 \u306b\u65b0\u3057\u3044\u30dd\u30c3\u30c9\u3092\u8ffd\u52a0\u3057\u307e\u3059 -message.add.primary.storage=\u30be\u30fc\u30f3 \u306e\u30dd\u30c3\u30c9 \u306b\u65b0\u3057\u3044\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u8ffd\u52a0\u3057\u307e\u3059 +message.add.pod=\u30be\u30fc\u30f3 \u306b\u65b0\u3057\u3044\u30dd\u30c3\u30c9\u3092\u8ffd\u52a0\u3057\u307e\u3059 +message.add.primary.storage=\u30be\u30fc\u30f3 \u306e\u30dd\u30c3\u30c9 \u306b\u65b0\u3057\u3044\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u8ffd\u52a0\u3057\u307e\u3059 message.add.primary=\u65b0\u3057\u3044\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u30d1\u30e9\u30e1\u30fc\u30bf\u30fc\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.add.secondary.storage=\u30be\u30fc\u30f3 \u306b\u65b0\u3057\u3044\u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u8ffd\u52a0\u3057\u307e\u3059 +message.add.secondary.storage=\u30be\u30fc\u30f3 \u306b\u65b0\u3057\u3044\u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u8ffd\u52a0\u3057\u307e\u3059 message.add.service.offering=\u65b0\u3057\u3044\u30b3\u30f3\u30d4\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0 \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u30c7\u30fc\u30bf\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.add.system.service.offering=\u65b0\u3057\u3044\u30b7\u30b9\u30c6\u30e0 \u30b5\u30fc\u30d3\u30b9 \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u30c7\u30fc\u30bf\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.add.template=\u65b0\u3057\u3044\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u4f5c\u6210\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u30c7\u30fc\u30bf\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 @@ -1225,8 +1225,8 @@ message.add.VPN.gateway=VPN \u30b2\u30fc\u30c8\u30a6\u30a7\u30a4\u3092\u8ffd\u52 message.advanced.mode.desc=VLAN \u30b5\u30dd\u30fc\u30c8\u3092\u6709\u52b9\u306b\u3059\u308b\u5834\u5408\u306f\u3001\u3053\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30e2\u30c7\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u3053\u306e\u30e2\u30c7\u30eb\u3067\u306f\u6700\u3082\u67d4\u8edf\u306b\u30ab\u30b9\u30bf\u30e0 \u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30aa\u30d5\u30a1\u30ea\u30f3\u30b0\u3092\u63d0\u4f9b\u3067\u304d\u3001\u30d5\u30a1\u30a4\u30a2\u30a6\u30a9\u30fc\u30eb\u3001VPN\u3001\u8ca0\u8377\u5206\u6563\u88c5\u7f6e\u306e\u30b5\u30dd\u30fc\u30c8\u306e\u307b\u304b\u306b\u3001\u76f4\u63a5\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3068\u4eee\u60f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3082\u6709\u52b9\u306b\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 message.advanced.security.group=\u30b2\u30b9\u30c8 VM \u3092\u5206\u96e2\u3059\u308b\u305f\u3081\u306b\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3 \u30b0\u30eb\u30fc\u30d7\u3092\u4f7f\u7528\u3059\u308b\u5834\u5408\u306f\u3001\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.advanced.virtual=\u30b2\u30b9\u30c8 VM \u3092\u5206\u96e2\u3059\u308b\u305f\u3081\u306b\u30be\u30fc\u30f3\u5168\u4f53\u306e VLAN \u3092\u4f7f\u7528\u3059\u308b\u5834\u5408\u306f\u3001\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.after.enable.s3=S3\u57fa\u76e4\u30bb\u30ab\u30f3\u30c0\u30ea\u30b9\u30c8\u30ec\u30fc\u30b8\u304c\u8a2d\u5b9a\u3055\u308c\u307e\u3057\u305f\u3002 \u30ce\u30fc\u30c8\:\u3053\u306e\u30da\u30fc\u30b8\u3092\u9589\u3058\u308b\u3068S3\u3092\u518d\u8a2d\u5b9a\u3067\u304d\u307e\u305b\u3093\u3002 -message.after.enable.swift=Swift \u304c\u69cb\u6210\u3055\u308c\u307e\u3057\u305f\u3002\u6ce8\: \u3053\u306e\u30da\u30fc\u30b8\u3092\u9589\u3058\u308b\u3068\u3001Swift \u3092\u518d\u69cb\u6210\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 +message.after.enable.s3=S3\u57fa\u76e4\u30bb\u30ab\u30f3\u30c0\u30ea\u30b9\u30c8\u30ec\u30fc\u30b8\u304c\u8a2d\u5b9a\u3055\u308c\u307e\u3057\u305f\u3002 \u30ce\u30fc\u30c8:\u3053\u306e\u30da\u30fc\u30b8\u3092\u9589\u3058\u308b\u3068S3\u3092\u518d\u8a2d\u5b9a\u3067\u304d\u307e\u305b\u3093\u3002 +message.after.enable.swift=Swift \u304c\u69cb\u6210\u3055\u308c\u307e\u3057\u305f\u3002\u6ce8: \u3053\u306e\u30da\u30fc\u30b8\u3092\u9589\u3058\u308b\u3068\u3001Swift \u3092\u518d\u69cb\u6210\u3059\u308b\u3053\u3068\u306f\u3067\u304d\u307e\u305b\u3093\u3002 message.alert.state.detected=\u30a2\u30e9\u30fc\u30c8\u72b6\u614b\u304c\u691c\u51fa\u3055\u308c\u307e\u3057\u305f message.allow.vpn.access=VPN \u30a2\u30af\u30bb\u30b9\u3092\u8a31\u53ef\u3059\u308b\u30e6\u30fc\u30b6\u30fc\u306e\u30e6\u30fc\u30b6\u30fc\u540d\u3068\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.apply.snapshot.policy=\u73fe\u5728\u306e\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8 \u30dd\u30ea\u30b7\u30fc\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002 @@ -1251,10 +1251,10 @@ message.confirm.join.project=\u3053\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3 message.confirm.remove.IP.range=\u3053\u306e IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3092\u524a\u9664\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.confirm.shutdown.provider=\u3053\u306e\u30d7\u30ed\u30d0\u30a4\u30c0\u30fc\u3092\u30b7\u30e3\u30c3\u30c8\u30c0\u30a6\u30f3\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.copy.iso.confirm=ISO \u3092\u6b21\u306e\u5834\u6240\u306b\u30b3\u30d4\u30fc\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.copy.template=\u30be\u30fc\u30f3 \u304b\u3089\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8 XXX \u3092\u6b21\u306e\u5834\u6240\u306b\u30b3\u30d4\u30fc\u3057\u307e\u3059\: +message.copy.template=\u30be\u30fc\u30f3 \u304b\u3089\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8 XXX \u3092\u6b21\u306e\u5834\u6240\u306b\u30b3\u30d4\u30fc\u3057\u307e\u3059: message.create.template=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u4f5c\u6210\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.create.template.vm=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8 \u304b\u3089 VM \u3092\u4f5c\u6210\u3057\u307e\u3059 -message.create.template.volume=\u30c7\u30a3\u30b9\u30af \u30dc\u30ea\u30e5\u30fc\u30e0 \u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u4f5c\u6210\u3059\u308b\u524d\u306b\u3001\u6b21\u306e\u60c5\u5831\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30dc\u30ea\u30e5\u30fc\u30e0 \u30b5\u30a4\u30ba\u306b\u3088\u3063\u3066\u306f\u3001\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306e\u4f5c\u6210\u306b\u306f\u6570\u5206\u4ee5\u4e0a\u304b\u304b\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 +message.create.template.vm=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8 \u304b\u3089 VM \u3092\u4f5c\u6210\u3057\u307e\u3059 +message.create.template.volume=\u30c7\u30a3\u30b9\u30af \u30dc\u30ea\u30e5\u30fc\u30e0 \u306e\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u4f5c\u6210\u3059\u308b\u524d\u306b\u3001\u6b21\u306e\u60c5\u5831\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u30dc\u30ea\u30e5\u30fc\u30e0 \u30b5\u30a4\u30ba\u306b\u3088\u3063\u3066\u306f\u3001\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306e\u4f5c\u6210\u306b\u306f\u6570\u5206\u4ee5\u4e0a\u304b\u304b\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002 message.creating.cluster=\u30af\u30e9\u30b9\u30bf\u30fc\u3092\u4f5c\u6210\u3057\u3066\u3044\u307e\u3059 message.creating.guest.network=\u30b2\u30b9\u30c8 \u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u4f5c\u6210\u3057\u3066\u3044\u307e\u3059 message.creating.physical.networks=\u7269\u7406\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u4f5c\u6210\u3057\u3066\u3044\u307e\u3059 @@ -1278,21 +1278,21 @@ message.desc.secondary.storage=\u5404\u30be\u30fc\u30f3\u306b\u306f\u5c11\u306a\ message.desc.zone=\u30be\u30fc\u30f3\u306f CloudStack \u74b0\u5883\u5185\u306e\u6700\u5927\u306e\u7d44\u7e54\u5358\u4f4d\u3067\u3001\u901a\u5e38\u3001\u5358\u4e00\u306e\u30c7\u30fc\u30bf\u30bb\u30f3\u30bf\u30fc\u306b\u76f8\u5f53\u3057\u307e\u3059\u3002\u30be\u30fc\u30f3\u306b\u3088\u3063\u3066\u7269\u7406\u7684\u306a\u5206\u96e2\u3068\u5197\u9577\u6027\u304c\u63d0\u4f9b\u3055\u308c\u307e\u3059\u3002\u30be\u30fc\u30f3\u306f 1 \u3064\u4ee5\u4e0a\u306e\u30dd\u30c3\u30c9 (\u5404\u30dd\u30c3\u30c9\u306f\u30db\u30b9\u30c8\u3068\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8 \u30b5\u30fc\u30d0\u30fc\u304b\u3089\u69cb\u6210\u3055\u308c\u307e\u3059) \u3068\u3001\u30be\u30fc\u30f3\u5185\u306e\u3059\u3079\u3066\u306e\u30dd\u30c3\u30c9\u3067\u5171\u6709\u3055\u308c\u308b\u30bb\u30ab\u30f3\u30c0\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8 \u30b5\u30fc\u30d0\u30fc\u304b\u3089\u69cb\u6210\u3055\u308c\u307e\u3059\u3002 message.detach.disk=\u3053\u306e\u30c7\u30a3\u30b9\u30af\u3092\u30c7\u30bf\u30c3\u30c1\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.detach.iso.confirm=\u3053\u306e\u4eee\u60f3\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u304b\u3089 ISO \u30d5\u30a1\u30a4\u30eb\u3092\u30c7\u30bf\u30c3\u30c1\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.disable.account=\u00e3\u0081\u0093\u00e3\u0081\u00ae\u00e3\u0082\u00a2\u00e3\u0082\u00ab\u00e3\u0082\u00a6\u00e3\u0083\u00b3\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e7\u0084\u00a1\u00e5\u008a\u00b9\u00e3\u0081\u00ab\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0082\u0082\u00e3\u0082\u0088\u00e3\u0082\u008d\u00e3\u0081\u0097\u00e3\u0081\u0084\u00e3\u0081\u00a7\u00e3\u0081\u0099\u00e3\u0081\u008b? \u00e3\u0082\u00a2\u00e3\u0082\u00ab\u00e3\u0082\u00a6\u00e3\u0083\u00b3\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e7\u0084\u00a1\u00e5\u008a\u00b9\u00e3\u0081\u00ab\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0081\u0093\u00e3\u0081\u00a8\u00e3\u0081\u00ab\u00e3\u0082\u0088\u00e3\u0082\u008a\u00e3\u0080\u0081\u00e3\u0081\u0093\u00e3\u0081\u00ae\u00e3\u0082\u00a2\u00e3\u0082\u00ab\u00e3\u0082\u00a6\u00e3\u0083\u00b3\u00e3\u0083\u0088\u00e3\u0081\u00ae\u00e3\u0081\u0099\u00e3\u0081\u00b9\u00e3\u0081\u00a6\u00e3\u0081\u00ae\u00e3\u0083\u00a6\u00e3\u0083\u00bc\u00e3\u0082\u00b6\u00e3\u0083\u00bc\u00e3\u0081\u00af\u00e3\u0082\u00af\u00e3\u0083\u00a9\u00e3\u0082\u00a6\u00e3\u0083\u0089\u00e3\u0083\u00aa\u00e3\u0082\u00bd\u00e3\u0083\u00bc\u00e3\u0082\u00b9\u00e3\u0081\u00ab\u00e3\u0082\u00a2\u00e3\u0082\u00af\u00e3\u0082\u00bb\u00e3\u0082\u00b9\u00e3\u0081\u00a7\u00e3\u0081\u008d\u00e3\u0081\u00aa\u00e3\u0081\u008f\u00e3\u0081\u00aa\u00e3\u0082\u008a\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082\u00e5\u00ae\u009f\u00e8\u00a1\u008c\u00e4\u00b8\u00ad\u00e3\u0081\u00ae\u00e3\u0081\u0099\u00e3\u0081\u00b9\u00e3\u0081\u00a6\u00e3\u0081\u00ae\u00e4\u00bb\u00ae\u00e6\u0083\u00b3\u00e3\u0083\u009e\u00e3\u0082\u00b7\u00e3\u0083\u00b3\u00e3\u0081\u00af\u00e3\u0081\u0099\u00e3\u0081\u0090\u00e3\u0081\u00ab\u00e3\u0082\u00b7\u00e3\u0083\u00a3\u00e3\u0083\u0083\u00e3\u0083\u0088\u00e3\u0083\u0080\u00e3\u0082\u00a6\u00e3\u0083\u00b3\u00e3\u0081\u0095\u00e3\u0082\u008c\u00e3\u0081\u00be\u00e3\u0081\u0099\u00e3\u0080\u0082 +message.disable.account=\u3053\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u7121\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? \u3053\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u3059\u3079\u3066\u306e\u30e6\u30fc\u30b6\u30fc\u304c\u30af\u30e9\u30a6\u30c9 \u30ea\u30bd\u30fc\u30b9\u306b\u30a2\u30af\u30bb\u30b9\u3067\u304d\u306a\u304f\u306a\u308a\u307e\u3059\u3002\u5b9f\u884c\u4e2d\u306e\u3059\u3079\u3066\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u306f\u4eca\u3059\u3050\u306b\u30b7\u30e3\u30c3\u30c8\u30c0\u30a6\u30f3\u3055\u308c\u307e\u3059\u3002 message.disable.snapshot.policy=\u73fe\u5728\u306e\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8 \u30dd\u30ea\u30b7\u30fc\u3092\u7121\u52b9\u306b\u3057\u307e\u3057\u305f\u3002 message.disable.user=\u3053\u306e\u30e6\u30fc\u30b6\u30fc\u3092\u7121\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.disable.vpn.access=VPN \u30a2\u30af\u30bb\u30b9\u3092\u7121\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.disable.vpn=VPN \u3092\u7121\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.download.ISO=ISO\u00e3\u0082\u0092\u00e3\u0083\u0080\u00e3\u0082\u00a6\u00e3\u0083\u00b3\u00e3\u0083\u00ad\u00e3\u0083\u00bc\u00e3\u0083\u0089\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0081\u00ab00000\u00e3\u0082\u0092\u00e3\u0082\u00af\u00e3\u0083\u00aa\u00e3\u0083\u0083\u00e3\u0082\u00af\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0081\u008f\u00e3\u0081\u00a0\u00e3\u0081\u0095\u00e3\u0081\u0084\u00e3\u0080\u0082 -message.download.template=\u00e3\u0083\u0086\u00e3\u0083\u00b3\u00e3\u0083\u0097\u00e3\u0083\u00ac\u00e3\u0083\u00bc\u00e3\u0083\u0088\u00e3\u0082\u0092\u00e3\u0083\u0080\u00e3\u0082\u00a6\u00e3\u0083\u00b3\u00e3\u0083\u00ad\u00e3\u0083\u00bc\u00e3\u0083\u0089\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0081\u00ab00000\u00e3\u0082\u0092\u00e3\u0082\u00af\u00e3\u0083\u00aa\u00e3\u0083\u0083\u00e3\u0082\u00af\u00e3\u0081\u0097\u00e3\u0081\u00a6\u00e3\u0081\u008f\u00e3\u0081\u00a0\u00e3\u0081\u0095\u00e3\u0081\u0084\u00e3\u0080\u0082 +message.download.ISO=ISO \u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u306b\u306f 00000 \u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059 +message.download.template=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u306b\u306f 00000 \u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059 message.download.volume.confirm=\u3053\u306e\u30dc\u30ea\u30e5\u30fc\u30e0\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.download.volume=\u30dc\u30ea\u30e5\u30fc\u30e0\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u306b\u306f 00000 \u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059 +message.download.volume=\u30dc\u30ea\u30e5\u30fc\u30e0\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u306b\u306f 00000 \u3092\u30af\u30ea\u30c3\u30af\u3057\u307e\u3059 message.edit.account=\u7de8\u96c6 ("-1" \u306f\u3001\u30ea\u30bd\u30fc\u30b9\u4f5c\u6210\u306e\u91cf\u306b\u5236\u9650\u304c\u306a\u3044\u3053\u3068\u3092\u793a\u3057\u307e\u3059) message.edit.confirm=[\u4fdd\u5b58] \u3092\u30af\u30ea\u30c3\u30af\u3059\u308b\u524d\u306b\u5909\u66f4\u5185\u5bb9\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.edit.limits=\u6b21\u306e\u30ea\u30bd\u30fc\u30b9\u306b\u5236\u9650\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u300c-1\u300d\u306f\u3001\u30ea\u30bd\u30fc\u30b9\u4f5c\u6210\u306b\u5236\u9650\u304c\u306a\u3044\u3053\u3068\u3092\u793a\u3057\u307e\u3059\u3002 message.edit.traffic.type=\u3053\u306e\u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u306e\u7a2e\u985e\u306b\u95a2\u9023\u4ed8\u3051\u308b\u30c8\u30e9\u30d5\u30a3\u30c3\u30af \u30e9\u30d9\u30eb\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.enable.account=\u3053\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u6709\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.enabled.vpn.ip.sec=IPSec \u4e8b\u524d\u5171\u6709\u30ad\u30fc\: +message.enabled.vpn.ip.sec=IPSec \u4e8b\u524d\u5171\u6709\u30ad\u30fc: message.enabled.vpn=\u73fe\u5728\u3001VPN \u30a2\u30af\u30bb\u30b9\u304c\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u3059\u3002\u6b21\u306e IP \u30a2\u30c9\u30ec\u30b9\u7d4c\u7531\u3067\u30a2\u30af\u30bb\u30b9\u3067\u304d\u307e\u3059\u3002 message.enable.user=\u3053\u306e\u30e6\u30fc\u30b6\u30fc\u3092\u6709\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.enable.vpn.access=\u73fe\u5728\u3053\u306e IP \u30a2\u30c9\u30ec\u30b9\u306b\u5bfe\u3059\u308b VPN \u306f\u7121\u52b9\u3067\u3059\u3002VPN \u30a2\u30af\u30bb\u30b9\u3092\u6709\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? @@ -1304,8 +1304,8 @@ message.generate.keys=\u3053\u306e\u30e6\u30fc\u30b6\u30fc\u306b\u65b0\u3057\u30 message.guest.traffic.in.advanced.zone=\u30b2\u30b9\u30c8 \u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u306f\u3001\u30a8\u30f3\u30c9 \u30e6\u30fc\u30b6\u30fc\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u9593\u306e\u901a\u4fe1\u3067\u3059\u3002\u5404\u7269\u7406\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u306e\u30b2\u30b9\u30c8 \u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u3092\u901a\u4fe1\u3059\u308b\u305f\u3081\u306e VLAN ID \u306e\u7bc4\u56f2\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.guest.traffic.in.basic.zone=\u30b2\u30b9\u30c8 \u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u306f\u3001\u30a8\u30f3\u30c9 \u30e6\u30fc\u30b6\u30fc\u306e\u4eee\u60f3\u30de\u30b7\u30f3\u9593\u306e\u901a\u4fe1\u3067\u3059\u3002CloudStack \u3067\u30b2\u30b9\u30c8 VM \u306b\u5272\u308a\u5f53\u3066\u3089\u308c\u308b IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u3053\u306e\u7bc4\u56f2\u304c\u4e88\u7d04\u6e08\u307f\u306e\u30b7\u30b9\u30c6\u30e0 IP \u30a2\u30c9\u30ec\u30b9\u306e\u7bc4\u56f2\u3068\u91cd\u8907\u3057\u306a\u3044\u3088\u3046\u306b\u6ce8\u610f\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.installWizard.click.retry=\u8d77\u52d5\u3092\u518d\u8a66\u884c\u3059\u308b\u306b\u306f\u30dc\u30bf\u30f3\u3092\u30af\u30ea\u30c3\u30af\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.installWizard.copy.whatIsAPod=\u901a\u5e38\u30011 \u3064\u306e\u30dd\u30c3\u30c9\u306f\u5358\u4e00\u306e\u30e9\u30c3\u30af\u3092\u8868\u3057\u307e\u3059\u3002\u540c\u3058\u30dd\u30c3\u30c9\u5185\u306e\u30db\u30b9\u30c8\u306f\u540c\u3058\u30b5\u30d6\u30cd\u30c3\u30c8\u306b\u542b\u307e\u308c\u307e\u3059\u3002

\u30dd\u30c3\u30c9\u306f CloudStack&\#8482; \u74b0\u5883\u5185\u306e 2 \u756a\u76ee\u306b\u5927\u304d\u306a\u7d44\u7e54\u5358\u4f4d\u3067\u3059\u3002\u30dd\u30c3\u30c9\u306f\u30be\u30fc\u30f3\u306b\u542b\u307e\u308c\u307e\u3059\u3002\u5404\u30be\u30fc\u30f3\u306f 1 \u3064\u4ee5\u4e0a\u306e\u30dd\u30c3\u30c9\u3092\u542b\u3080\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u57fa\u672c\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3067\u306f\u3001\u30be\u30fc\u30f3\u5185\u306e\u30dd\u30c3\u30c9\u306f 1 \u3064\u3067\u3059\u3002 -message.installWizard.copy.whatIsAZone=\u30be\u30fc\u30f3\u306f CloudStack&\#8482; \u74b0\u5883\u5185\u306e\u6700\u5927\u306e\u7d44\u7e54\u5358\u4f4d\u3067\u3059\u30021 \u3064\u306e\u30c7\u30fc\u30bf\u30bb\u30f3\u30bf\u30fc\u5185\u306b\u8907\u6570\u306e\u30be\u30fc\u30f3\u3092\u8a2d\u5b9a\u3067\u304d\u307e\u3059\u304c\u3001\u901a\u5e38\u3001\u30be\u30fc\u30f3\u306f\u5358\u4e00\u306e\u30c7\u30fc\u30bf\u30bb\u30f3\u30bf\u30fc\u306b\u76f8\u5f53\u3057\u307e\u3059\u3002\u30a4\u30f3\u30d5\u30e9\u30b9\u30c8\u30e9\u30af\u30c1\u30e3\u3092\u30be\u30fc\u30f3\u306b\u7d44\u7e54\u5316\u3059\u308b\u3068\u3001\u30be\u30fc\u30f3\u3092\u7269\u7406\u7684\u306b\u5206\u96e2\u3057\u3066\u5197\u9577\u5316\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u305f\u3068\u3048\u3070\u3001\u5404\u30be\u30fc\u30f3\u306b\u96fb\u6e90\u3068\u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30a2\u30c3\u30d7\u30ea\u30f3\u30af\u3092\u914d\u5099\u3057\u307e\u3059\u3002\u5fc5\u9808\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u304c\u3001\u30be\u30fc\u30f3\u306f\u9060\u9694\u5730\u306b\u5206\u6563\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 +message.installWizard.copy.whatIsAPod=\u901a\u5e38\u30011 \u3064\u306e\u30dd\u30c3\u30c9\u306f\u5358\u4e00\u306e\u30e9\u30c3\u30af\u3092\u8868\u3057\u307e\u3059\u3002\u540c\u3058\u30dd\u30c3\u30c9\u5185\u306e\u30db\u30b9\u30c8\u306f\u540c\u3058\u30b5\u30d6\u30cd\u30c3\u30c8\u306b\u542b\u307e\u308c\u307e\u3059\u3002

\u30dd\u30c3\u30c9\u306f CloudStack™ \u74b0\u5883\u5185\u306e 2 \u756a\u76ee\u306b\u5927\u304d\u306a\u7d44\u7e54\u5358\u4f4d\u3067\u3059\u3002\u30dd\u30c3\u30c9\u306f\u30be\u30fc\u30f3\u306b\u542b\u307e\u308c\u307e\u3059\u3002\u5404\u30be\u30fc\u30f3\u306f 1 \u3064\u4ee5\u4e0a\u306e\u30dd\u30c3\u30c9\u3092\u542b\u3080\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u57fa\u672c\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3067\u306f\u3001\u30be\u30fc\u30f3\u5185\u306e\u30dd\u30c3\u30c9\u306f 1 \u3064\u3067\u3059\u3002 +message.installWizard.copy.whatIsAZone=\u30be\u30fc\u30f3\u306f CloudStack™ \u74b0\u5883\u5185\u306e\u6700\u5927\u306e\u7d44\u7e54\u5358\u4f4d\u3067\u3059\u30021 \u3064\u306e\u30c7\u30fc\u30bf\u30bb\u30f3\u30bf\u30fc\u5185\u306b\u8907\u6570\u306e\u30be\u30fc\u30f3\u3092\u8a2d\u5b9a\u3067\u304d\u307e\u3059\u304c\u3001\u901a\u5e38\u3001\u30be\u30fc\u30f3\u306f\u5358\u4e00\u306e\u30c7\u30fc\u30bf\u30bb\u30f3\u30bf\u30fc\u306b\u76f8\u5f53\u3057\u307e\u3059\u3002\u30a4\u30f3\u30d5\u30e9\u30b9\u30c8\u30e9\u30af\u30c1\u30e3\u3092\u30be\u30fc\u30f3\u306b\u7d44\u7e54\u5316\u3059\u308b\u3068\u3001\u30be\u30fc\u30f3\u3092\u7269\u7406\u7684\u306b\u5206\u96e2\u3057\u3066\u5197\u9577\u5316\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\u305f\u3068\u3048\u3070\u3001\u5404\u30be\u30fc\u30f3\u306b\u96fb\u6e90\u3068\u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30a2\u30c3\u30d7\u30ea\u30f3\u30af\u3092\u914d\u5099\u3057\u307e\u3059\u3002\u5fc5\u9808\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u304c\u3001\u30be\u30fc\u30f3\u306f\u9060\u9694\u5730\u306b\u5206\u6563\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002 message.installWizard.copy.whatIsSecondaryStorage=\u30bb\u30ab\u30f3\u30c0\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u306f\u30be\u30fc\u30f3\u3068\u95a2\u9023\u4ed8\u3051\u3089\u308c\u3001\u6b21\u306e\u9805\u76ee\u3092\u683c\u7d0d\u3057\u307e\u3059\u3002
  • \u30c6\u30f3\u30d7\u30ec\u30fc\u30c8 - VM \u306e\u8d77\u52d5\u306b\u4f7f\u7528\u3067\u304d\u308b OS \u30a4\u30e1\u30fc\u30b8\u3067\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u306a\u3069\u8ffd\u52a0\u306e\u69cb\u6210\u3092\u542b\u3081\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002
  • ISO \u30a4\u30e1\u30fc\u30b8 - \u8d77\u52d5\u53ef\u80fd\u307e\u305f\u306f\u8d77\u52d5\u4e0d\u53ef\u306e OS \u30a4\u30e1\u30fc\u30b8\u3067\u3059\u3002
  • \u30c7\u30a3\u30b9\u30af \u30dc\u30ea\u30e5\u30fc\u30e0\u306e\u30b9\u30ca\u30c3\u30d7\u30b7\u30e7\u30c3\u30c8 - VM \u30c7\u30fc\u30bf\u306e\u4fdd\u5b58\u30b3\u30d4\u30fc\u3067\u3059\u3002\u30c7\u30fc\u30bf\u306e\u5fa9\u5143\u307e\u305f\u306f\u65b0\u3057\u3044\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306e\u4f5c\u6210\u306b\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002
message.installWizard.tooltip.addCluster.name=\u30af\u30e9\u30b9\u30bf\u30fc\u306e\u540d\u524d\u3067\u3059\u3002CloudStack \u3067\u4f7f\u7528\u3055\u308c\u3066\u3044\u306a\u3044\u3001\u4efb\u610f\u306e\u30c6\u30ad\u30b9\u30c8\u3092\u6307\u5b9a\u3067\u304d\u307e\u3059\u3002 message.installWizard.tooltip.addHost.hostname=\u30db\u30b9\u30c8\u306e DNS \u540d\u307e\u305f\u306f IP \u30a2\u30c9\u30ec\u30b9\u3067\u3059\u3002 @@ -1344,7 +1344,7 @@ message.migrate.instance.to.ps=\u5225\u306e\u30d7\u30e9\u30a4\u30de\u30ea \u30b9 message.migrate.router.confirm=\u30eb\u30fc\u30bf\u30fc\u306e\u79fb\u884c\u5148\u306f\u6b21\u306e\u30db\u30b9\u30c8\u3067\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.migrate.systemvm.confirm=\u30b7\u30b9\u30c6\u30e0 VM \u306e\u79fb\u884c\u5148\u306f\u6b21\u306e\u30db\u30b9\u30c8\u3067\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.migrate.volume=\u5225\u306e\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u306b\u30dc\u30ea\u30e5\u30fc\u30e0\u3092\u79fb\u884c\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.new.user=\u00e3\u0082\u00a2\u00e3\u0082\u00ab\u00e3\u0082\u00a6\u00e3\u0083\u00b3\u00e3\u0083\u0088\u00e3\u0081\u00ab\u00e6\u0096\u00b0\u00e3\u0081\u0097\u00e3\u0081\u0084\u00e3\u0083\u00a6\u00e3\u0083\u00bc\u00e3\u0082\u00b6\u00e3\u0083\u00bc\u00e3\u0082\u0092\u00e8\u00bf\u00bd\u00e5\u008a\u00a0\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0081\u00ab\u00e3\u0080\u0081\u00e6\u00ac\u00a1\u00e3\u0081\u00ae\u00e6\u0083 +message.new.user=\u30a2\u30ab\u30a6\u30f3\u30c8\u306b\u65b0\u3057\u3044\u30e6\u30fc\u30b6\u30fc\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u60c5\u5831\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002 message.no.network.support.configuration.not.true=\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3 \u30b0\u30eb\u30fc\u30d7\u304c\u6709\u52b9\u306a\u30be\u30fc\u30f3\u304c\u7121\u3044\u305f\u3081\u3001\u8ffd\u52a0\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u6a5f\u80fd\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u624b\u9806 5. \u306b\u9032\u3093\u3067\u304f\u3060\u3055\u3044\u3002 message.no.network.support=\u30cf\u30a4\u30d1\u30fc\u30d0\u30a4\u30b6\u30fc\u3068\u3057\u3066 vSphere \u3092\u9078\u629e\u3057\u307e\u3057\u305f\u304c\u3001\u3053\u306e\u30cf\u30a4\u30d1\u30fc\u30d0\u30a4\u30b6\u30fc\u306b\u8ffd\u52a0\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u6a5f\u80fd\u306f\u3042\u308a\u307e\u305b\u3093\u3002\u624b\u9806 5. \u306b\u9032\u3093\u3067\u304f\u3060\u3055\u3044\u3002 message.no.projects.adminOnly=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u304c\u3042\u308a\u307e\u305b\u3093\u3002
\u7ba1\u7406\u8005\u306b\u65b0\u3057\u3044\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u4f5c\u6210\u3092\u4f9d\u983c\u3057\u3066\u304f\u3060\u3055\u3044\u3002 @@ -1407,7 +1407,7 @@ message.tooltip.reserved.system.netmask=\u30dd\u30c3\u30c9\u306e\u30b5\u30d6\u30 message.tooltip.zone.name=\u30be\u30fc\u30f3\u306e\u540d\u524d\u3067\u3059\u3002 message.update.os.preference=\u3053\u306e\u30db\u30b9\u30c8\u306e OS \u57fa\u672c\u8a2d\u5b9a\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u540c\u69d8\u306e\u57fa\u672c\u8a2d\u5b9a\u3092\u6301\u3064\u3059\u3079\u3066\u306e\u4eee\u60f3\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306f\u3001\u5225\u306e\u30db\u30b9\u30c8\u3092\u9078\u629e\u3059\u308b\u524d\u306b\u307e\u305a\u3053\u306e\u30db\u30b9\u30c8\u306b\u5272\u308a\u5f53\u3066\u3089\u308c\u307e\u3059\u3002 message.update.resource.count=\u3053\u306e\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u30ea\u30bd\u30fc\u30b9\u6570\u3092\u66f4\u65b0\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? -message.update.ssl=\u5404\u30b3\u30f3\u30bd\u30fc\u30eb \u30d7\u30ed\u30ad\u30b7\u306e\u4eee\u60f3\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3067\u66f4\u65b0\u3059\u308b\u3001X.509 \u6e96\u62e0\u306e\u65b0\u3057\u3044 SSL \u8a3c\u660e\u66f8\u3092\u9001\u4fe1\u3057\u3066\u304f\u3060\u3055\u3044\: +message.update.ssl=\u5404\u30b3\u30f3\u30bd\u30fc\u30eb \u30d7\u30ed\u30ad\u30b7\u306e\u4eee\u60f3\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u3067\u66f4\u65b0\u3059\u308b\u3001X.509 \u6e96\u62e0\u306e\u65b0\u3057\u3044 SSL \u8a3c\u660e\u66f8\u3092\u9001\u4fe1\u3057\u3066\u304f\u3060\u3055\u3044: message.validate.instance.name=\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u540d\u306f 63 \u6587\u5b57\u4ee5\u5185\u3067\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044\u3002ASCII \u6587\u5b57\u306e a\uff5ez\u3001A\uff5eZ\u3001\u6570\u5b57\u306e 0\uff5e9\u3001\u304a\u3088\u3073\u30cf\u30a4\u30d5\u30f3\u306e\u307f\u3092\u4f7f\u7528\u3067\u304d\u307e\u3059\u3002\u6587\u5b57\u3067\u59cb\u307e\u308a\u3001\u6587\u5b57\u307e\u305f\u306f\u6570\u5b57\u3067\u7d42\u308f\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002 message.virtual.network.desc=\u30a2\u30ab\u30a6\u30f3\u30c8\u306e\u5c02\u7528\u4eee\u60f3\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3067\u3059\u3002\u30d6\u30ed\u30fc\u30c9\u30ad\u30e3\u30b9\u30c8 \u30c9\u30e1\u30a4\u30f3\u306f VLAN \u5185\u306b\u914d\u7f6e\u3055\u308c\u3001\u30d1\u30d6\u30ea\u30c3\u30af \u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3078\u306e\u30a2\u30af\u30bb\u30b9\u306f\u3059\u3079\u3066\u4eee\u60f3\u30eb\u30fc\u30bf\u30fc\u306b\u3088\u3063\u3066\u30eb\u30fc\u30c6\u30a3\u30f3\u30b0\u3055\u308c\u307e\u3059\u3002 message.vm.create.template.confirm=\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u3092\u4f5c\u6210\u3059\u308b\u3068 VM \u304c\u81ea\u52d5\u7684\u306b\u518d\u8d77\u52d5\u3055\u308c\u307e\u3059\u3002 @@ -1418,9 +1418,9 @@ message.Zone.creation.complete=\u30be\u30fc\u30f3\u304c\u4f5c\u6210\u3055\u308c\ message.zone.creation.complete.would.you.like.to.enable.this.zone=\u30be\u30fc\u30f3\u304c\u4f5c\u6210\u3055\u308c\u307e\u3057\u305f\u3002\u3053\u306e\u30be\u30fc\u30f3\u3092\u6709\u52b9\u306b\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? message.zone.no.network.selection=\u9078\u629e\u3057\u305f\u30be\u30fc\u30f3\u3067\u306f\u3001\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u3092\u9078\u629e\u3067\u304d\u307e\u305b\u3093\u3002 message.zone.step.1.desc=\u30be\u30fc\u30f3\u306e\u30cd\u30c3\u30c8\u30ef\u30fc\u30af \u30e2\u30c7\u30eb\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002 -message.zone.step.2.desc=\u00e6\u0096\u00b0\u00e3\u0081\u0097\u00e3\u0081\u0084Zone\u00e3\u0082\u0092\u00e8\u00bf\u00bd\u00e5\u008a\u00a0\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0081\u00ab\u00e3\u0080\u0081\u00e6\u00ac\u00a1\u00e3\u0081\u00ae\u00e6\u0083 -message.zone.step.3.desc=\u00e6\u0096\u00b0\u00e3\u0081\u0097\u00e3\u0081\u0084Pod\u00e3\u0082\u0092\u00e8\u00bf\u00bd\u00e5\u008a\u00a0\u00e3\u0081\u0099\u00e3\u0082\u008b\u00e3\u0081\u009f\u00e3\u0082\u0081\u00e3\u0081\u00ab\u00e3\u0080\u0081\u00e6\u00ac\u00a1\u00e3\u0081\u00ae\u00e6\u0083 -message.zoneWizard.enable.local.storage=\u8b66\u544a\: \u3053\u306e\u30be\u30fc\u30f3\u306e\u30ed\u30fc\u30ab\u30eb \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u6709\u52b9\u306b\u3059\u308b\u5834\u5408\u306f\u3001\u30b7\u30b9\u30c6\u30e0 VM \u306e\u8d77\u52d5\u5834\u6240\u306b\u5fdc\u3058\u3066\u6b21\u306e\u64cd\u4f5c\u304c\u5fc5\u8981\u3067\u3059\u3002

1. \u30b7\u30b9\u30c6\u30e0 VM \u3092\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3067\u8d77\u52d5\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u5834\u5408\u306f\u3001\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u4f5c\u6210\u3057\u305f\u5f8c\u3067\u30be\u30fc\u30f3\u306b\u8ffd\u52a0\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\u307e\u305f\u3001\u7121\u52b9\u72b6\u614b\u306e\u30be\u30fc\u30f3\u3092\u8d77\u52d5\u3059\u308b\u5fc5\u8981\u3082\u3042\u308a\u307e\u3059\u3002

2. \u30b7\u30b9\u30c6\u30e0 VM \u3092\u30ed\u30fc\u30ab\u30eb \u30b9\u30c8\u30ec\u30fc\u30b8\u3067\u8d77\u52d5\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u5834\u5408\u306f\u3001system.vm.use.local.storage \u3092 true \u306b\u8a2d\u5b9a\u3057\u3066\u304b\u3089\u30be\u30fc\u30f3\u3092\u6709\u52b9\u306b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002


\u7d9a\u884c\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? +message.zone.step.2.desc=\u65b0\u3057\u3044\u30be\u30fc\u30f3\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u60c5\u5831\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +message.zone.step.3.desc=\u65b0\u3057\u3044\u30dd\u30c3\u30c9\u3092\u8ffd\u52a0\u3059\u308b\u305f\u3081\u306b\u3001\u6b21\u306e\u60c5\u5831\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +message.zoneWizard.enable.local.storage=\u8b66\u544a: \u3053\u306e\u30be\u30fc\u30f3\u306e\u30ed\u30fc\u30ab\u30eb \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u6709\u52b9\u306b\u3059\u308b\u5834\u5408\u306f\u3001\u30b7\u30b9\u30c6\u30e0 VM \u306e\u8d77\u52d5\u5834\u6240\u306b\u5fdc\u3058\u3066\u6b21\u306e\u64cd\u4f5c\u304c\u5fc5\u8981\u3067\u3059\u3002

1. \u30b7\u30b9\u30c6\u30e0 VM \u3092\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3067\u8d77\u52d5\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u5834\u5408\u306f\u3001\u30d7\u30e9\u30a4\u30de\u30ea \u30b9\u30c8\u30ec\u30fc\u30b8\u3092\u4f5c\u6210\u3057\u305f\u5f8c\u3067\u30be\u30fc\u30f3\u306b\u8ffd\u52a0\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002\u307e\u305f\u3001\u7121\u52b9\u72b6\u614b\u306e\u30be\u30fc\u30f3\u3092\u8d77\u52d5\u3059\u308b\u5fc5\u8981\u3082\u3042\u308a\u307e\u3059\u3002

2. \u30b7\u30b9\u30c6\u30e0 VM \u3092\u30ed\u30fc\u30ab\u30eb \u30b9\u30c8\u30ec\u30fc\u30b8\u3067\u8d77\u52d5\u3059\u308b\u5fc5\u8981\u304c\u3042\u308b\u5834\u5408\u306f\u3001system.vm.use.local.storage \u3092 true \u306b\u8a2d\u5b9a\u3057\u3066\u304b\u3089\u30be\u30fc\u30f3\u3092\u6709\u52b9\u306b\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002


\u7d9a\u884c\u3057\u3066\u3082\u3088\u308d\u3057\u3044\u3067\u3059\u304b? mode=\u30e2\u30fc\u30c9 network.rate=\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u901f\u5ea6 notification.reboot.instance=\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u518d\u8d77\u52d5 diff --git a/client/WEB-INF/classes/resources/messages_ko_KR.properties b/client/WEB-INF/classes/resources/messages_ko_KR.properties index 766fc607648..757871acde0 100644 --- a/client/WEB-INF/classes/resources/messages_ko_KR.properties +++ b/client/WEB-INF/classes/resources/messages_ko_KR.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=\ud56d\ubaa9 \uc18d\uc131 \ubcc0\uacbd confirm.enable.swift=Swift \uae30\uc220 \uc9c0\uc6d0\ub97c \uc0ac\uc6a9 \ud558\ub824\uba74 \ub2e4\uc74c \uc815\ubcf4\ub97c \uc785\ub825\ud574 \uc8fc\uc2ed\uc2dc\uc624. error.could.not.enable.zone=Zone\uc744 \uc0ac\uc6a9 \ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. @@ -1194,6 +1193,7 @@ message.add.load.balancer.under.ip=\ub2e4\uc74c IP \uc8fc\uc18c\uc5d0 \ub300\ud5 message.add.load.balancer=Zone\uc5d0 \ub124\ud2b8\uc6cc\ud06c \ub85c\ub4dc \uacf5\uc720 \uc7a5\uce58\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. message.add.network=Zone \uc5d0 \uc0c8\ub85c\uc6b4 \ub124\ud2b8\uc6cc\ud06c\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. message.add.new.gateway.to.vpc=\ud604\uc7ac VPC\uc5d0 \uc0c8\ub85c\uc6b4 \uac8c\uc774\ud2b8\uc6e8\uc774\ub97c \ucd94\uac00\ud558\uae30 \uc704\ud55c \uc815\ubcf4\ub97c \uc9c0\uc815\ud574 \uc8fc\uc2ed\uc2dc\uc624. +message.add.pod.during.zone.creation=\uac01 Zone\uc5d0\ub294 \ud55c \uac1c \uc774\uc0c1 Pod\uac00 \ud544\uc694\ud569\ub2c8\ub2e4. \uc9c0\uae08 \uc5ec\uae30\uc11c \uccab\ubc88\uc9f8 Pod\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. Pod\ub294 \ud638\uc2a4\ud2b8\uc640 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc11c\ubc84\uc5d0\uc11c \uad6c\uc131\ud569\ub2c8\ub2e4\ub9cc \uc774\ub294 \ub2e4\uc74c \uc21c\uc11c\ub85c \ucd94\uac00\ud569\ub2c8\ub2e4. \ub9e8 \ucc98\uc74c CloudStack \ub0b4\ubd80 \uad00\ub9ac \ud2b8\ub798\ud53d\uc744 \uc704\ud574\uc11c IP \uc8fc\uc18c \ubc94\uc704\ub97c \uc608\uc57d\ud569\ub2c8\ub2e4. IP \uc8fc\uc18c \ubc94\uc704\ub294 \ud074\ub77c\uc6b0\ub4dc \ub0b4\ubd80 \uac01 Zone\uc5d0\uc11c \uc911\ubcf5 \ud558\uc9c0 \uc54a\uac8c \uc608\uc57d\ud560 \ud544\uc694\uac00 \uc788\uc2b5\ub2c8\ub2e4. message.add.pod=Zone \uc5d0 \uc0c8\ub85c\uc6b4 Pod\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. message.add.primary.storage=Zone Pod \uc5d0 \uc0c8\ub85c\uc6b4 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. message.add.primary=\uc0c8\ub85c\uc6b4 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0\ub97c \ucd94\uac00\ud558\uae30 \uc704\ud574 \uc544\ub798 \ud30c\ub77c\ubbf8\ud130\ub97c \uc9c0\uc815\ud574 \uc8fc\uc2ed\uc2dc\uc624. @@ -1253,6 +1253,7 @@ message.delete.VPN.gateway=\ud604\uc7ac VPN \uac8c\uc774\ud2b8\uc6e8\uc774\ub97c message.desc.advanced.zone=\ubcf4\ub2e4 \uc138\ub828\ub41c \ub124\ud2b8\uc6cc\ud06c \uae30\uc220\uc744 \uc9c0\uc6d0\ud569\ub2c8\ub2e4. \uc774 \ub124\ud2b8\uc6cc\ud06c \ubaa8\ub378\uc744 \uc120\ud0dd\ud558\uba74, \ubcf4\ub2e4 \uc720\uc5f0\ud558\uac8c \uac8c\uc2a4\ud2b8 \ub124\ud2b8\uc6cc\ud06c\ub97c \uc815\ud558\uace0 \ubc29\ud654\ubcbd(fire wall), VPN, \ub124\ud2b8\uc6cc\ud06c \ub85c\ub4dc \uacf5\uc720 \uc7a5\uce58 \uae30\uc220 \uc9c0\uc6d0\uc640 \uac19\uc740 \uc0ac\uc6a9\uc790 \uc9c0\uc815 \ud55c \ub124\ud2b8\uc6cc\ud06c \uc81c\uacf5\uc744 \uc81c\uacf5\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. message.desc.basic.zone=\uac01 VM \uc778\uc2a4\ud134\uc2a4\uc5d0 IP \uc8fc\uc18c\uac00 \ub124\ud2b8\uc6cc\ud06c\uc5d0\uc11c \uc9c1\uc811 \ud560\ub2f9\ud560 \uc218 \uc788\ub294 \ub2e8\uc77c \ub124\ud2b8\uc6cc\ud06c\ub97c \uc81c\uacf5\ud569\ub2c8\ub2e4. \ubcf4\uc548 \uadf8\ub8f9 (\uc804\uc1a1\uc6d0 IP \uc8fc\uc18c \ud544\ud130)\uacfc \uac19\uc740 \uce35 \uc138 \uac00\uc9c0 \ub808\ubca8 \ubc29\ubc95\uc73c\ub85c \uac8c\uc2a4\ud2b8\ub97c \ubd84\ub9ac\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4. message.desc.cluster=\uac01 Pod\uc5d0\ub294 \ud55c \uac1c \uc774\uc0c1 \ud074\ub7ec\uc2a4\ud130\uac00 \ud544\uc694\ud569\ub2c8\ub2e4. \uc9c0\uae08 \uc5ec\uae30\uc11c \ucd5c\ucd08 \ud074\ub7ec\uc2a4\ud130\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. \ud074\ub7ec\uc2a4\ud130\ub294 \ud638\uc2a4\ud2b8\ub97c \uadf8\ub8f9\ud654 \ud558\ub294 \ubc29\ubc95\uc785\ub2c8\ub2e4. \ud55c \ud074\ub7ec\uc2a4\ud130 \ub0b4\ubd80 \ud638\uc2a4\ud2b8\ub294 \ubaa8\ub450 \ub3d9\uc77c\ud55c \ud558\ub4dc\uc6e8\uc5b4\uc5d0\uc11c \uad6c\uc131\ub418\uc5b4 \uac19\uc740 \ud558\uc774\ud37c \ubc14\uc774\uc800\ub97c \uc2e4\ud589\ud558\uace0 \uac19\uc740 \uc11c\ube0c \ub124\ud2b8\uc6cc\ud06c\uc0c1\uc5d0 \uc788\uc5b4 \uac19\uc740 \uacf5\uc720 \uc2a4\ud1a0\ub9ac\uc9c0\uc5d0 \uc811\uadfc \ud569\ub2c8\ub2e4. \uac01 \ud074\ub7ec\uc2a4\ud130\ub294 \ud55c \uac1c \uc774\uc0c1 \ud638\uc2a4\ud2b8\uc640 \ud55c \uac1c \uc774\uc0c1 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc11c\ubc84\uc5d0\uc11c \uad6c\uc131\ub429\ub2c8\ub2e4. +message.desc.host=\uac01 \ud074\ub7ec\uc2a4\ud130\uc5d0\ub294 \uc801\uc5b4\ub3c4 \ud55c \uac1c \uc774\uc0c1 \uac8c\uc2a4\ud2b8 VM\ub97c \uc2e4\ud589\ud558\uae30 \uc704\ud55c \ud638\uc2a4\ud2b8 (\ucef4\ud4e8\ud130)\uac00 \ud544\uc694\ud569\ub2c8\ub2e4. \uc9c0\uae08 \uc5ec\uae30\uc11c \uccab\ubc88\uc9f8 \ud638\uc2a4\ud2b8\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. CloudStack\uc73c\ub85c \ud638\uc2a4\ud2b8\ub97c \ub3d9\uc791\ud558\ub824\uba74 \ud638\uc2a4\ud2b8\uc5d0\uac8c \ud558\uc774\ud37c \ubc14\uc774\uc800\ub97c \uc124\uce58\ud558\uace0 IP \uc8fc\uc18c\ub97c \ud560\ub2f9\ud574 \ud638\uc2a4\ud2b8\uac00 CloudStack \uad00\ub9ac \uc11c\ubc84\uc5d0 \uc811\uc18d\ud558\ub3c4\ub85d \ud569\ub2c8\ub2e4.

\ud638\uc2a4\ud2b8 DNS \uba85 \ub610\ub294 IP \uc8fc\uc18c, \uc0ac\uc6a9\uc790\uba85(\uc6d0\ub798 root)\uacfc \uc554\ud638 \ubc0f \ud638\uc2a4\ud2b8 \ubd84\ub958\uc5d0 \uc0ac\uc6a9\ud558\ub294 \ub77c\ubca8\uc744 \uc785\ub825\ud574 \uc8fc\uc2ed\uc2dc\uc624. message.desc.primary.storage=\uac01 \ud074\ub7ec\uc2a4\ud130\uc5d0\ub294 \uc801\uc5b4\ub3c4 \ud55c \uac1c \uc774\uc0c1\uc758 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc11c\ubc84\uac00 \ud544\uc694\ud569\ub2c8\ub2e4. \uc9c0\uae08 \uc5ec\uae30\uc11c \uccab\ubc88\uc9f8 \uc11c\ubc84\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0\ub294 \ud074\ub7ec\uc2a4\ud130 \ub0b4 \ubd80 \ud638\uc2a4\ud2b8\uc0c1\uc5d0\uc11c \ub3d9\uc791\ud558\ub294 \ubaa8\ub4e0 VM \ub514\uc2a4\ud06c \ubcfc\ub968\uc744 \ud3ec\ud568\ud569\ub2c8\ub2e4. \uae30\ubcf8\uc801\uc73c\ub85c \ud558\uc774\ud37c \ubc14\uc774\uc800\uc5d0\uc11c \uae30\uc220 \uc9c0\uc6d0\ub418\ub294 \ud45c\uc900\uc5d0 \uc900\uac70\ud55c \ud504\ub85c\ud1a0\ucf5c\uc744 \uc0ac\uc6a9\ud574 \uc8fc\uc2ed\uc2dc\uc624. message.desc.secondary.storage=\uac01 Zone\uc5d0\ub294 \uc801\uc5b4\ub3c4 \ud55c \uac1c \uc774\uc0c1\uc758 NFS \uc989 2\ucc28 \uc2a4\ud1a0\ub9ac\uc9c0 \uc11c\ubc84\uac00 \ud544\uc694\ud569\ub2c8\ub2e4. \uc9c0\uae08 \uc5ec\uae30\uc11c \uccab\ubc88\uc9f8 \uc11c\ubc84\ub97c \ucd94\uac00\ud569\ub2c8\ub2e4. 2\ucc28 \uc2a4\ud1a0\ub9ac\uc9c0\ub294 VM \ud15c\ud50c\ub9bf, ISO \uc774\ubbf8\uc9c0 \ubc0f VM \ub514\uc2a4\ud06c \ubcfc\ub968 \uc2a4\ub0c5\uc0f7\uc744 \ud3ec\ud568\ud569\ub2c8\ub2e4. \uc774 \uc11c\ubc84\ub294 Zone\ub0b4 \ubaa8\ub4e0 \ud638\uc2a4\ud2b8\uc5d0\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc788\uc5b4\uc57c \ud569\ub2c8\ub2e4.

IP \uc8fc\uc18c\uc640 \ub0b4\ubcf4\ub0b4\ub0bc \uacbd\ub85c\ub97c \uc785\ub825\ud574 \uc8fc\uc2ed\uc2dc\uc624. message.desc.zone=Zone\uc740 CloudStack \ud658\uacbd\ub0b4 \ucd5c\ub300 \uc870\uc9c1 \ub2e8\uc704\ub85c \uc6d0\ub798 \ub2e8\uc77c \ub370\uc774\ud130 \uc13c\ud130\uc5d0 \ud574\ub2f9\ud569\ub2c8\ub2e4. Zone\uc5d0 \ud574\uc11c \ubb3c\ub9ac\uc801\uc778 \ubd84\ub9ac\uc640 \uc911\ubcf5\uc131\uc774 \uc81c\uacf5\ub429\ub2c8\ub2e4. Zone\uc740 \ud55c \uac1c \uc774\uc0c1 Pod( \uac01 Pod\ub294 \ud638\uc2a4\ud2b8\uc640 \uae30\ubcf8 \uc2a4\ud1a0\ub9ac\uc9c0 \uc11c\ubc84\uc5d0\uc11c \uad6c\uc131)\uc640 Zone\ub0b4 \ubaa8\ub4e0 Pod\ub85c \uacf5\uc720\ub418\ub294 2\ucc28 \uc2a4\ud1a0\ub9ac\uc9c0 \uc11c\ubc84\ub85c \uad6c\uc131\ub429\ub2c8\ub2e4. @@ -1380,6 +1381,7 @@ message.step.3.continue=\uc2e4\ud589\ud558\ub824\uba74 \ub514\uc2a4\ud06c\uc81c\ message.step.3.desc= message.step.4.continue=\uc2e4\ud589\ud558\ub824\uba74 \ub124\ud2b8\uc6cc\ud06c\ub97c \uc801\uc5b4\ub3c4 \ud55c \uac1c \uc774\uc0c1 \uc120\ud0dd\ud574 \uc8fc\uc2ed\uc2dc\uc624. message.step.4.desc=\uac00\uc0c1 \uc778\uc2a4\ud134\uc2a4\uac00 \uc811\uc18d\ud558\ub294 \uae30\ubcf8 \ub124\ud2b8\uc6cc\ud06c\ub97c \uc120\ud0dd\ud574 \uc8fc\uc2ed\uc2dc\uc624. +message.storage.traffic=\ud638\uc2a4\ud2b8\ub098 CloudStack \uc2dc\uc2a4\ud15c VM \ub4f1 \uad00\ub9ac \uc11c\ubc84\uc640 \ud1b5\uc2e0\ud558\ub294 CloudStack \ub0b4\ubd80 \uc790\uc6d0\uac04 \ud2b8\ub798\ud53d\uc785\ub2c8\ub2e4. \uc5ec\uae30\uc11c \uc2a4\ud1a0\ub9ac\uc9c0 \ud2b8\ub798\ud53d\uc744 \uad6c\uc131\ud574 \uc8fc\uc2ed\uc2dc\uc624. message.suspend.project=\ud604\uc7ac \ud504\ub85c\uc81d\ud2b8\ub97c \uc77c\uc2dc\uc815\uc9c0\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c? message.template.desc=VM\uc758 \uc2dc\uc791\uc5d0 \uc0ac\uc6a9\ud560 \uc218 \uc788\ub294 OS \uc774\ubbf8\uc9c0 message.tooltip.dns.1=Zone\ub0b4 VM \ub85c \uc0ac\uc6a9\ud558\ub294 DNS \uc11c\ubc84 \uc774\ub984\uc785\ub2c8\ub2e4. Zone \uacf5\uac1c IP \uc8fc\uc18c\uc5d0\uc11c \uc774 \uc11c\ubc84\uc5d0 \ud1b5\uc2e0\ud560 \uc218 \uc788\uc5b4\uc57c \ud569\ub2c8\ub2e4. diff --git a/client/WEB-INF/classes/resources/messages_nb_NO.properties b/client/WEB-INF/classes/resources/messages_nb_NO.properties index 8fba48ca9c4..be412449398 100644 --- a/client/WEB-INF/classes/resources/messages_nb_NO.properties +++ b/client/WEB-INF/classes/resources/messages_nb_NO.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=Endrede egenskaper error.could.not.enable.zone=Kunne ikke aktivere sonen error.installWizard.message=Noe gikk galt. G\u00e5 tilbake og korriger feilene. diff --git a/client/WEB-INF/classes/resources/messages_pt_BR.properties b/client/WEB-INF/classes/resources/messages_pt_BR.properties index 23123c16764..fd24f542e8d 100644 --- a/client/WEB-INF/classes/resources/messages_pt_BR.properties +++ b/client/WEB-INF/classes/resources/messages_pt_BR.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=Alteradas propriedades do item confirm.enable.s3=Por favor preencha as informa\u00e7\u00f5es abaixo para habilitar suporte a storage secund\u00e1ria fornecida por S3 confirm.enable.swift=Por favor preencha as informa\u00e7\u00f5es abaixo para habilitar suporte ao Swift @@ -1113,6 +1112,7 @@ label.zones=Zonas label.zone.type=Tipo de Zona label.zone.wide=Zone-Wide label.zoneWizard.trafficType.guest=H\u00f3spede\: tr\u00e1fego entre m\u00e1quinas virtuais de usu\u00e1rios finais +label.zoneWizard.trafficType.management=Ger\u00eancia\: tr\u00e1fego entre recursos internos do CloudStack, incluindo quaisquer componentes que se comunicam com o servidor de gerenciamento, tais como hosts e m\u00e1quinas virtuais de sistema do CloudStack label.zoneWizard.trafficType.public=P\u00fablico\: tr\u00e1fego entre a internet e m\u00e1quinas virtuais na nuvem. label.zoneWizard.trafficType.storage=Storage\: tr\u00e1fego entre servidores de storage prim\u00e1ria e secund\u00e1ria, tais como templates de m\u00e1quinas virtuais e snapshots label.zone=Zona diff --git a/client/WEB-INF/classes/resources/messages_ru_RU.properties b/client/WEB-INF/classes/resources/messages_ru_RU.properties index 5818abc9199..b28f6b69e6f 100644 --- a/client/WEB-INF/classes/resources/messages_ru_RU.properties +++ b/client/WEB-INF/classes/resources/messages_ru_RU.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b confirm.enable.swift=\u0417\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u0435 \u043d\u0438\u0436\u0435\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438 Swift error.could.not.enable.zone=\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0437\u043e\u043d\u0443 @@ -1131,6 +1130,7 @@ message.additional.networks.desc=\u041f\u043e\u0436\u0430\u043b\u0443\u0439\u044 message.add.load.balancer=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0443 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432 \u0437\u043e\u043d\u0443 message.add.load.balancer.under.ip=\u041f\u0440\u0430\u0432\u0438\u043b\u043e \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0431\u044b\u043b \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u0432 IP\: message.add.network=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0441\u0435\u0442\u044c \u0434\u043b\u044f \u0437\u043e\u043d\u044b\: +message.add.pod.during.zone.creation=\u041a\u0430\u0436\u0434\u0430\u044f \u0437\u043e\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u0441\u0442\u0435\u043d\u0434\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u0435 \u043f\u0435\u0440\u0432\u044b\u043c. \u0421\u0442\u0435\u043d\u0434 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0443\u0437\u043b\u044b \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u044b \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u0448\u0430\u0433\u0435. \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u044b\u0445 \u0430\u0434\u0440\u0435\u0441\u043e\u0432 IP \u0434\u043b\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u0441\u0435\u0442\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u0414\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u0440\u0435\u0437\u0435\u0440\u0432\u043d\u044b\u0445 IP \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0437\u043e\u043d\u044b \u043e\u0431\u043b\u0430\u043a\u0430. message.add.pod=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0441\u0442\u0435\u043d\u0434 \u0434\u043b\u044f \u0437\u043e\u043d\u044b message.add.primary.storage=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0434\u043b\u044f \u0437\u043e\u043d\u044b , \u0441\u0442\u0435\u043d\u0434\u0430 message.add.primary=\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 @@ -1185,6 +1185,7 @@ message.delete.user=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442 message.desc.advanced.zone=\u0414\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0441\u0435\u0442\u0435\u0432\u044b\u0445 \u0442\u043e\u043f\u043e\u043b\u043e\u0433\u0438\u0439. \u042d\u0442\u0430 \u0441\u0435\u0442\u0435\u0432\u0430\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u0433\u043e\u0441\u0442\u0435\u0432\u043e\u0439 \u0441\u0435\u0442\u0438 \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0443\u0441\u043b\u0443\u0433, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a \u043c\u0435\u0436\u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u044d\u043a\u0440\u0430\u043d, VPN, \u0438\u043b\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0438 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438. message.desc.basic.zone=\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0435\u0434\u0438\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u0441\u0435\u0442\u044c, \u0433\u0434\u0435 \u043a\u0430\u0436\u0434\u0430\u044f \u0412\u041c \u0438\u043c\u0435\u0435\u0442 \u00ab\u0431\u0435\u043b\u044b\u0439\u00bb IP-\u0430\u0434\u0440\u0435\u0441 \u0441\u0435\u0442\u0438. \u0418\u0437\u043e\u043b\u044f\u0446\u0438\u0438 \u0433\u043e\u0441\u0442\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u0435\u0442\u0438 3-\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0433\u0440\u0443\u043f\u043f\u044b \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 (\u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f IP-\u0432\u0434\u0440\u0435\u0441\u043e\u0432) message.desc.cluster=\u041a\u0430\u0436\u0434\u044b\u0439 \u0441\u0442\u0435\u043d\u0434 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u0435\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u043e\u0432, \u043f\u0435\u0440\u0432\u044b\u0439 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u044b \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u0435. \u041a\u043b\u0430\u0441\u0442\u0435\u0440 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0433\u0440\u0443\u043f\u043f\u0443 \u0443\u0437\u043b\u043e\u0432. \u0423\u0437\u043b\u044b \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 \u0438\u043c\u0435\u044e\u0442 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e\u0435 \u043e\u0431\u043e\u0440\u0443\u0434\u043e\u0432\u0430\u043d\u0438\u0435, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043e\u0434\u0438\u043d \u0433\u0438\u043f\u0435\u0440\u0432\u0438\u0437\u043e\u0440, \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u0439 \u0441\u0435\u0442\u0438 \u0438 \u0438\u043c\u0435\u044e\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u0438 \u0442\u043e\u043c\u0443 \u0436\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c\u0443 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0443. \u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u0443\u0437\u043b\u043e\u0432, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0438\u0435\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449. +message.desc.host=\u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u043e\u0434\u0438\u043d \u0443\u0437\u0435\u043b (\u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440) \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0412\u041c, \u043f\u0435\u0440\u0432\u044b\u0439 \u0438\u0437 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0432\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u0435 \u0441\u0435\u0439\u0447\u0430\u0441. \u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0443\u0437\u043b\u0430 \u0432 CloudStack \u0432\u0430\u0436\u043d\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0433\u0438\u043f\u0435\u0440\u0432\u0438\u0437\u043e\u0440\u0430 \u043d\u0430 \u0443\u0437\u0435\u043b, \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 IP \u043a \u0443\u0437\u043b\u0443 \u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0443\u0437\u043b\u0430 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f CloudStack.

\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u0438\u043c\u044f DNS \u0438\u043b\u0438 \u0430\u0434\u0440\u0435\u0441 IP, \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u043a \u041e\u0421 (\u043e\u0431\u044b\u0447\u043d\u043e root), \u0430 \u0442\u0430\u043a\u0436\u0435 \u043c\u0435\u0442\u043a\u0438 \u0434\u043b\u044f \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0443\u0437\u043b\u043e\u0432. message.desc.primary.storage=\u041a\u0430\u0436\u0434\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u0438 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u0441\u0435\u0439\u0447\u0430\u0441. \u041f\u0435\u0440\u0432\u0438\u0447\u043d\u0430\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u044b \u0436\u0435\u0441\u0442\u043a\u043e\u0433\u043e \u0434\u0438\u0441\u043a\u0430 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u0448\u0438\u043d, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0445 \u043d\u0430 \u0443\u0437\u043b\u0430\u0445 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043b\u044e\u0431\u043e\u0439 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0433\u0438\u043f\u0435\u0440\u0432\u0438\u0437\u043e\u0440\u0430. message.desc.secondary.storage=\u041a\u0430\u0436\u0434\u0430\u044f \u0437\u043e\u043d\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u043e\u0431\u043b\u0430\u0434\u0430\u0442\u044c \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u0438\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c NFS \u0438\u043b\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u0438 \u0438\u0445 \u043d\u0430\u0434\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c. \u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0412\u041c, \u043e\u0431\u0440\u0430\u0437\u043e\u0432 ISO \u0438 \u0441\u043d\u0438\u043c\u043a\u043e\u0432 \u0412\u041c. \u042d\u0442\u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0443\u0437\u043b\u043e\u0432 \u0437\u043e\u043d\u044b.

\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c IP-\u0430\u0434\u0440\u0435\u0441 \u0438 \u043f\u0443\u0442\u044c. message.desc.zone=layer 3 @@ -1309,6 +1310,7 @@ message.step.3.continue=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0434\ message.step.3.desc= message.step.4.continue=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u0443 \u0441\u0435\u0442\u044c \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u044f. message.step.4.desc=\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0441\u0435\u0442\u044c, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u043c\u0430\u0448\u0438\u043d\u0430. +message.storage.traffic=\u0422\u0440\u0430\u0444\u0438\u043a \u043c\u0435\u0436\u0434\u0443 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438 CloudStack, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0432\u0441\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0442 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0445\u043e\u0441\u0442\u044b \u0438 CloudStack \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0442\u0440\u0430\u0444\u0438\u043a \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0437\u0434\u0435\u0441\u044c. message.suspend.project=\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442? message.template.desc=\u041e\u0431\u0440\u0430\u0437 \u041e\u0421, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u043e\u0439 \u0432 \u0412\u041c message.tooltip.dns.1=\u0418\u043c\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 DNS \u0434\u043b\u044f \u0412\u041c \u044d\u0442\u043e\u0439 \u0437\u043e\u043d\u044b. \u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 IP-\u0430\u0434\u0440\u0435\u0441\u0430 \u044d\u0442\u043e\u0439 \u0437\u043e\u043d\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u043c\u0435\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442 \u0434\u043e \u044d\u0442\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430. diff --git a/client/WEB-INF/classes/resources/messages_zh_CN.properties b/client/WEB-INF/classes/resources/messages_zh_CN.properties index 687ef60b3c1..30daacc3627 100644 --- a/client/WEB-INF/classes/resources/messages_zh_CN.properties +++ b/client/WEB-INF/classes/resources/messages_zh_CN.properties @@ -15,7 +15,6 @@ # specific language governing permissions and limitations # under the License. - changed.item.properties=\u66f4\u6539\u9879\u76ee\u5c5e\u6027 confirm.enable.s3=\u8bf7\u586b\u5199\u4e0b\u5217\u4fe1\u606f\u4ee5\u542f\u7528\u652f\u6301S3\u7684\u4e8c\u7ea7\u5b58\u50a8 confirm.enable.swift=\u8bf7\u586b\u5199\u4ee5\u4e0b\u4fe1\u606f\u4ee5\u542f\u7528\u5bf9 SWIFT \u7684\u652f\u6301 @@ -622,12 +621,17 @@ label.keyboard.type=\u952e\u76d8\u7c7b\u578b label.key=\u5bc6\u94a5 label.kvm.traffic.label=KVM \u6d41\u91cf\u6807\u7b7e label.label=\u6807\u7b7e +label.lang.arabic=\u963f\u62c9\u4f2f\u8bed label.lang.brportugese=\u5df4\u897f\u8461\u8404\u7259\u8bed +label.lang.catalan=\u52a0\u6cf0\u7f57\u5c3c\u4e9a\u8bed label.lang.chinese=\u7b80\u4f53\u4e2d\u6587 label.lang.english=\u82f1\u8bed label.lang.french=\u6cd5\u8bed +label.lang.german=\u5fb7\u8bed +label.lang.italian=\u610f\u5927\u5229\u8bed label.lang.japanese=\u65e5\u8bed label.lang.korean=\u97e9\u56fd\u8bed +label.lang.norwegian=\u632a\u5a01\u8bed label.lang.russian=\u4fc4\u8bed label.lang.spanish=\u897f\u73ed\u7259\u8bed label.last.disconnected=\u4e0a\u6b21\u65ad\u5f00\u8fde\u63a5\u65f6\u95f4 @@ -1165,6 +1169,7 @@ label.zone.type=\u533a\u57df\u7c7b\u578b label.zone=\u533a\u57df label.zone.wide=\u6574\u4e2a\u533a\u57df label.zoneWizard.trafficType.guest=\u6765\u5bbe\u7f51\u7edc\: \u5ba2\u6237\u865a\u62df\u673a\u4e4b\u95f4\u7684\u7f51\u7edc\u6d41\u91cf +label.zoneWizard.trafficType.management=\u7ba1\u7406\u7f51\: CloudStack\u5185\u90e8\u8d44\u6e90\u4e4b\u95f4\u7684\u7f51\u7edc\u6d41\u91cf, \u5305\u62ec\u4e0e\u7ba1\u7406\u670d\u52a1\u5668\u4ea4\u4e92\u7684\u4efb\u4f55\u7ec4\u4ef6, \u6bd4\u5982\u4e3b\u673a\u548cCloudStack\u7cfb\u7edf\u865a\u62df\u673a label.zoneWizard.trafficType.public=\u516c\u5171\u7f51\u7edc\: \u4e91\u73af\u5883\u4e2d\u865a\u62df\u673a\u4e0e\u56e0\u7279\u7f51\u4e4b\u95f4\u7684\u7f51\u7edc\u6d41\u91cf. label.zoneWizard.trafficType.storage=\u5b58\u50a8\u7f51\: \u4e3b\u5b58\u50a8\u4e0e\u4e8c\u7ea7\u5b58\u50a8\u670d\u52a1\u5668\u4e4b\u95f4\u7684\u6d41\u91cf, \u6bd4\u5982\u865a\u673a\u6a21\u677f\u548c\u5feb\u7167 managed.state=\u6258\u7ba1\u72b6\u6001 @@ -1255,6 +1260,7 @@ message.add.load.balancer=\u5411\u533a\u57df\u4e2d\u6dfb\u52a0\u4e00\u4e2a\u8d1f message.add.load.balancer.under.ip=\u5df2\u5728\u4ee5\u4e0b IP \u4e0b\u6dfb\u52a0\u8d1f\u8f7d\u5e73\u8861\u5668\u89c4\u5219\: message.add.network=\u4e3a\u533a\u57df\u6dfb\u52a0\u4e00\u4e2a\u65b0\u7f51\u7edc\: message.add.new.gateway.to.vpc=\u8bf7\u6307\u5b9a\u5c06\u65b0\u7f51\u5173\u6dfb\u52a0\u5230\u6b64 VPC \u6240\u9700\u7684\u4fe1\u606f\u3002 +message.add.pod.during.zone.creation=\u6bcf\u4e2a\u533a\u57df\u4e2d\u5fc5\u987b\u5305\u542b\u4e00\u4e2a\u6216\u591a\u4e2a\u63d0\u4f9b\u70b9\uff0c\u73b0\u5728\u6211\u4eec\u5c06\u6dfb\u52a0\u7b2c\u4e00\u4e2a\u63d0\u4f9b\u70b9\u3002\u63d0\u4f9b\u70b9\u4e2d\u5305\u542b\u4e3b\u673a\u548c\u4e3b\u5b58\u50a8\u670d\u52a1\u5668\uff0c\u60a8\u5c06\u5728\u968f\u540e\u7684\u67d0\u4e2a\u6b65\u9aa4\u4e2d\u6dfb\u52a0\u8fd9\u4e9b\u4e3b\u673a\u548c\u670d\u52a1\u5668\u3002\u9996\u5148\uff0c\u8bf7\u4e3a CloudStack \u7684\u5185\u90e8\u7ba1\u7406\u6d41\u91cf\u914d\u7f6e\u4e00\u4e2a\u9884\u7559 IP \u5730\u5740\u8303\u56f4\u3002\u9884\u7559\u7684 IP \u8303\u56f4\u5bf9\u4e91\u4e2d\u7684\u6bcf\u4e2a\u533a\u57df\u6765\u8bf4\u5fc5\u987b\u552f\u4e00\u3002 message.add.pod=\u4e3a\u533a\u57df \u6dfb\u52a0\u4e00\u4e2a\u65b0\u63d0\u4f9b\u70b9 message.add.primary.storage=\u4e3a\u533a\u57df \u3001\u63d0\u4f9b\u70b9 \u6dfb\u52a0\u4e00\u4e2a\u65b0\u7684\u4e3b\u5b58\u50a8 message.add.primary=\u8bf7\u6307\u5b9a\u4ee5\u4e0b\u53c2\u6570\u4ee5\u6dfb\u52a0\u4e00\u4e2a\u65b0\u4e3b\u5b58\u50a8 @@ -1316,6 +1322,7 @@ message.delete.VPN.gateway=\u8bf7\u786e\u8ba4\u60a8\u786e\u5b9e\u8981\u5220\u966 message.desc.advanced.zone=\u9002\u7528\u4e8e\u66f4\u52a0\u590d\u6742\u7684\u7f51\u7edc\u62d3\u6251\u3002\u6b64\u7f51\u7edc\u6a21\u5f0f\u5728\u5b9a\u4e49\u6765\u5bbe\u7f51\u7edc\u5e76\u63d0\u4f9b\u9632\u706b\u5899\u3001VPN \u6216\u8d1f\u8f7d\u5e73\u8861\u5668\u652f\u6301\u7b49\u81ea\u5b9a\u4e49\u7f51\u7edc\u65b9\u6848\u65b9\u9762\u63d0\u4f9b\u4e86\u6700\u5927\u7684\u7075\u6d3b\u6027\u3002 message.desc.basic.zone=\u63d0\u4f9b\u4e00\u4e2a\u7f51\u7edc\uff0c\u5c06\u76f4\u63a5\u4ece\u6b64\u7f51\u7edc\u4e2d\u4e3a\u6bcf\u4e2a VM \u5b9e\u4f8b\u5206\u914d\u4e00\u4e2a IP\u3002\u53ef\u4ee5\u901a\u8fc7\u5b89\u5168\u7ec4\u7b49\u7b2c 3 \u5c42\u65b9\u5f0f\u63d0\u4f9b\u6765\u5bbe\u9694\u79bb(IP \u5730\u5740\u6e90\u8fc7\u6ee4)\u3002 message.desc.cluster=\u6bcf\u4e2a\u63d0\u4f9b\u70b9\u4e2d\u5fc5\u987b\u5305\u542b\u4e00\u4e2a\u6216\u591a\u4e2a\u7fa4\u96c6\uff0c\u73b0\u5728\u6211\u4eec\u5c06\u6dfb\u52a0\u7b2c\u4e00\u4e2a\u7fa4\u96c6\u3002\u7fa4\u96c6\u63d0\u4f9b\u4e86\u4e00\u79cd\u7f16\u7ec4\u4e3b\u673a\u7684\u65b9\u6cd5\u3002\u7fa4\u96c6\u4e2d\u7684\u6240\u6709\u4e3b\u673a\u90fd\u5177\u6709\u76f8\u540c\u7684\u786c\u4ef6\uff0c\u8fd0\u884c\u76f8\u540c\u7684\u865a\u62df\u673a\u7ba1\u7406\u7a0b\u5e8f\uff0c\u4f4d\u4e8e\u76f8\u540c\u7684\u5b50\u7f51\u4e2d\uff0c\u5e76\u8bbf\u95ee\u76f8\u540c\u7684\u5171\u4eab\u5b58\u50a8\u3002\u6bcf\u4e2a\u7fa4\u96c6\u7531\u4e00\u4e2a\u6216\u591a\u4e2a\u4e3b\u673a\u4ee5\u53ca\u4e00\u4e2a\u6216\u591a\u4e2a\u4e3b\u5b58\u50a8\u670d\u52a1\u5668\u7ec4\u6210\u3002 +message.desc.host=\u6bcf\u4e2a\u7fa4\u96c6\u4e2d\u5fc5\u987b\u81f3\u5c11\u5305\u542b\u4e00\u4e2a\u4e3b\u673a\u4ee5\u4f9b\u6765\u5bbe VM \u5728\u4e0a\u9762\u8fd0\u884c\uff0c\u73b0\u5728\u6211\u4eec\u5c06\u6dfb\u52a0\u7b2c\u4e00\u4e2a\u4e3b\u673a\u3002\u8981\u4f7f\u4e3b\u673a\u5728 CloudStack \u4e2d\u8fd0\u884c\uff0c\u5fc5\u987b\u5728\u6b64\u4e3b\u673a\u4e0a\u5b89\u88c5\u865a\u62df\u673a\u7ba1\u7406\u7a0b\u5e8f\u8f6f\u4ef6\uff0c\u4e3a\u5176\u5206\u914d\u4e00\u4e2a IP \u5730\u5740\uff0c\u5e76\u786e\u4fdd\u5c06\u5176\u8fde\u63a5\u5230 CloudStack \u7ba1\u7406\u670d\u52a1\u5668\u3002

\u8bf7\u63d0\u4f9b\u4e3b\u673a\u7684 DNS \u6216 IP \u5730\u5740\u3001\u7528\u6237\u540d(\u901a\u5e38\u4e3a root)\u548c\u5bc6\u7801\uff0c\u4ee5\u53ca\u7528\u4e8e\u5bf9\u4e3b\u673a\u8fdb\u884c\u5206\u7c7b\u7684\u4efb\u4f55\u6807\u7b7e\u3002 message.desc.primary.storage=\u6bcf\u4e2a\u7fa4\u96c6\u4e2d\u5fc5\u987b\u5305\u542b\u4e00\u4e2a\u6216\u591a\u4e2a\u4e3b\u5b58\u50a8\u670d\u52a1\u5668\uff0c\u73b0\u5728\u6211\u4eec\u5c06\u6dfb\u52a0\u7b2c\u4e00\u4e2a\u4e3b\u5b58\u50a8\u670d\u52a1\u5668\u3002\u4e3b\u5b58\u50a8\u4e2d\u5305\u542b\u5728\u7fa4\u96c6\u4e2d\u7684\u4e3b\u673a\u4e0a\u8fd0\u884c\u7684\u6240\u6709 VM \u7684\u78c1\u76d8\u5377\u3002\u8bf7\u4f7f\u7528\u5e95\u5c42\u865a\u62df\u673a\u7ba1\u7406\u7a0b\u5e8f\u652f\u6301\u7684\u7b26\u5408\u6807\u51c6\u7684\u534f\u8bae\u3002 message.desc.secondary.storage=\u6bcf\u4e2a\u533a\u57df\u4e2d\u5fc5\u987b\u81f3\u5c11\u5305\u542b\u4e00\u4e2a NFS \u6216\u8f85\u52a9\u5b58\u50a8\u670d\u52a1\u5668\uff0c\u73b0\u5728\u6211\u4eec\u5c06\u6dfb\u52a0\u7b2c\u4e00\u4e2a NFS \u6216\u8f85\u52a9\u5b58\u50a8\u670d\u52a1\u5668\u3002\u8f85\u52a9\u5b58\u50a8\u7528\u4e8e\u5b58\u50a8 VM \u6a21\u677f\u3001ISO \u6620\u50cf\u548c VM \u78c1\u76d8\u5377\u5feb\u7167\u3002\u6b64\u670d\u52a1\u5668\u5fc5\u987b\u5bf9\u533a\u57df\u4e2d\u7684\u6240\u6709\u670d\u52a1\u5668\u53ef\u7528\u3002

\u8bf7\u63d0\u4f9b IP \u5730\u5740\u548c\u5bfc\u51fa\u8def\u5f84\u3002 message.desc.zone=\u533a\u57df\u662f CloudStack \u4e2d\u6700\u5927\u7684\u7ec4\u7ec7\u5355\u4f4d\uff0c\u4e00\u4e2a\u533a\u57df\u901a\u5e38\u4e0e\u4e00\u4e2a\u6570\u636e\u4e2d\u5fc3\u76f8\u5bf9\u5e94\u3002\u533a\u57df\u53ef\u63d0\u4f9b\u7269\u7406\u9694\u79bb\u548c\u5197\u4f59\u3002\u4e00\u4e2a\u533a\u57df\u7531\u4e00\u4e2a\u6216\u591a\u4e2a\u63d0\u4f9b\u70b9\u4ee5\u53ca\u7531\u533a\u57df\u4e2d\u7684\u6240\u6709\u63d0\u4f9b\u70b9\u5171\u4eab\u7684\u4e00\u4e2a\u8f85\u52a9\u5b58\u50a8\u670d\u52a1\u5668\u7ec4\u6210\uff0c\u5176\u4e2d\u6bcf\u4e2a\u63d0\u4f9b\u70b9\u4e2d\u5305\u542b\u591a\u4e2a\u4e3b\u673a\u548c\u4e3b\u5b58\u50a8\u670d\u52a1\u5668\u3002 @@ -1445,6 +1452,7 @@ message.step.3.continue=\u8bf7\u9009\u62e9\u4e00\u79cd\u78c1\u76d8\u65b9\u6848\u message.step.3.desc= message.step.4.continue=\u8bf7\u81f3\u5c11\u9009\u62e9\u4e00\u4e2a\u7f51\u7edc\u4ee5\u7ee7\u7eed message.step.4.desc=\u8bf7\u9009\u62e9\u865a\u62df\u5b9e\u4f8b\u8981\u8fde\u63a5\u5230\u7684\u4e3b\u7f51\u7edc\u3002 +message.storage.traffic=CloudStack \u5185\u90e8\u8d44\u6e90(\u5305\u62ec\u4e0e\u7ba1\u7406\u670d\u52a1\u5668\u901a\u4fe1\u7684\u4efb\u4f55\u7ec4\u4ef6\uff0c\u4f8b\u5982\u4e3b\u673a\u548c CloudStack \u7cfb\u7edf VM)\u4e4b\u95f4\u7684\u6d41\u91cf\u3002\u8bf7\u5728\u6b64\u5904\u914d\u7f6e\u5b58\u50a8\u6d41\u91cf\u3002 message.suspend.project=\u662f\u5426\u786e\u5b9e\u8981\u6682\u505c\u6b64\u9879\u76ee? message.template.desc=\u53ef\u7528\u4e8e\u542f\u52a8 VM \u7684\u64cd\u4f5c\u7cfb\u7edf\u6620\u50cf message.tooltip.dns.1=\u4f9b\u533a\u57df\u4e2d\u7684 VM \u4f7f\u7528\u7684 DNS \u670d\u52a1\u5668\u540d\u79f0\u3002\u533a\u57df\u7684\u516c\u7528 IP \u5730\u5740\u5fc5\u987b\u8def\u7531\u5230\u6b64\u670d\u52a1\u5668\u3002 diff --git a/client/tomcatconf/nonossComponentContext.xml.in b/client/tomcatconf/nonossComponentContext.xml.in index 1b6ee6eb089..6fa9d38baa4 100644 --- a/client/tomcatconf/nonossComponentContext.xml.in +++ b/client/tomcatconf/nonossComponentContext.xml.in @@ -251,7 +251,7 @@ - + diff --git a/core/src/com/cloud/storage/template/HttpTemplateDownloader.java b/core/src/com/cloud/storage/template/HttpTemplateDownloader.java index 628ad64c0dc..c8aac27da8c 100644 --- a/core/src/com/cloud/storage/template/HttpTemplateDownloader.java +++ b/core/src/com/cloud/storage/template/HttpTemplateDownloader.java @@ -250,6 +250,13 @@ public class HttpTemplateDownloader implements TemplateDownloader { } } else { remoteSize2 = Long.parseLong(contentLengthHeader.getValue()); + if ( remoteSize2 == 0 ) { + status = TemplateDownloader.Status.DOWNLOAD_FINISHED; + String downloaded = "(download complete remote=" + remoteSize + "bytes)"; + errorString = "Downloaded " + totalBytes + " bytes " + downloaded; + downloadTime = 0; + return 0; + } } if (remoteSize == 0) { diff --git a/debian/cloudstack-management.install b/debian/cloudstack-management.install index 5a682d45862..a1325cdb2b5 100644 --- a/debian/cloudstack-management.install +++ b/debian/cloudstack-management.install @@ -15,7 +15,28 @@ # specific language governing permissions and limitations # under the License. -/etc/cloudstack/management/* +/etc/cloudstack/management/catalina.policy +/etc/cloudstack/management/catalina.properties +/etc/cloudstack/management/cloudmanagementserver.keystore +/etc/cloudstack/management/logging.properties +/etc/cloudstack/management/commands.properties +/etc/cloudstack/management/ehcache.xml +/etc/cloudstack/management/componentContext.xml +/etc/cloudstack/management/applicationContext.xml +/etc/cloudstack/management/server-ssl.xml +/etc/cloudstack/management/server-nonssl.xml +/etc/cloudstack/management/server.xml +/etc/cloudstack/management/classpath.conf +/etc/cloudstack/management/db.properties +/etc/cloudstack/management/tomcat6-ssl.conf +/etc/cloudstack/management/tomcat6-nonssl.conf +/etc/cloudstack/management/tomcat6.conf +/etc/cloudstack/management/web.xml +/etc/cloudstack/management/environment.properties +/etc/cloudstack/management/nonossComponentContext.xml +/etc/cloudstack/management/log4j-cloud.xml +/etc/cloudstack/management/tomcat-users.xml +/etc/cloudstack/management/context.xml /etc/init.d/cloudstack-management /etc/security/limits.d/cloudstack-limits.conf /etc/sudoers.d/cloudstack diff --git a/debian/control b/debian/control index eec9ca25c7b..46dd50536b0 100644 --- a/debian/control +++ b/debian/control @@ -9,7 +9,7 @@ Homepage: http://www.cloudstack.org/ Package: cloudstack-common Architecture: all -Depends: bash, genisoimage +Depends: bash, genisoimage, nfs-common Conflicts: cloud-scripts, cloud-utils, cloud-system-iso, cloud-console-proxy, cloud-daemonize, cloud-deps, cloud-python, cloud-setup Description: A common package which contains files which are shared by several CloudStack packages diff --git a/debian/rules b/debian/rules index e381b1a8ebe..e5ff5484fe5 100755 --- a/debian/rules +++ b/debian/rules @@ -34,7 +34,7 @@ build: build-indep build-indep: build-indep-stamp build-indep-stamp: configure - mvn package -Pawsapi -DskipTests -Dsystemvm \ + mvn clean package -Pawsapi -DskipTests -Dsystemvm \ -Dcs.replace.properties=replace.properties.tmp \ ${ACS_BUILD_OPTS} touch $@ @@ -69,8 +69,8 @@ install: install -D plugins/hypervisors/kvm/target/cloud-plugin-hypervisor-kvm-$(VERSION)-SNAPSHOT.jar $(DESTDIR)/usr/share/$(PACKAGE)-agent/lib/ 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/cloudstack-ssh + install -D agent/target/transformed/cloud-setup-agent $(DESTDIR)/usr/bin/cloudstack-setup-agent + install -D agent/target/transformed/cloud-ssh $(DESTDIR)/usr/bin/cloudstack-ssh install -D agent/target/transformed/* $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/agent # cloudstack-management @@ -102,7 +102,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/cloudstack-update-xenserver-licenses + install -D client/target/utilities/bin/cloud-update-xenserver-licenses $(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 diff --git a/docs/en-US/CloudStack_Nicira_NVP_Guide.xml b/docs/en-US/CloudStack_Nicira_NVP_Guide.xml index 7f156d5dc09..5431fc1cb43 100644 --- a/docs/en-US/CloudStack_Nicira_NVP_Guide.xml +++ b/docs/en-US/CloudStack_Nicira_NVP_Guide.xml @@ -48,6 +48,7 @@ + diff --git a/docs/en-US/Release_Notes.xml b/docs/en-US/Release_Notes.xml index 25e1175b148..2ae87320e40 100644 --- a/docs/en-US/Release_Notes.xml +++ b/docs/en-US/Release_Notes.xml @@ -36,8 +36,8 @@ under the License. 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;! + If you find any errors or problems in this guide, please see . + We hope you enjoy working with &PRODUCT;! Version 4.1.0 @@ -4396,6 +4396,13 @@ under the License. + + CLOUDSTACK-2709 + + Egress rules are are not supported on shared networks. + + CLOUDSTACK-1747 @@ -4648,9 +4655,12 @@ under the License. components.xml to be on the safe side. - After upgrading to 4.1, API clients are expected to send plain text passwords for login and user creation, instead of MD5 hash. Incase, api client changes are not acceptable, following changes are to be made for backward compatibility: - Modify componentsContext.xml, and make PlainTextUserAuthenticator as the default authenticator (1st entry in the userAuthenticators adapter list is default) - + After upgrading to 4.1, API clients are expected to send plain text passwords for + login and user creation, instead of MD5 hash. Incase, api client changes are not + acceptable, following changes are to be made for backward compatibility: + Modify componentsContext.xml, and make PlainTextUserAuthenticator as the default + authenticator (1st entry in the userAuthenticators adapter list is default) + <!-- Security adapters --> <bean id="userAuthenticators" class="com.cloud.utils.component.AdapterList"> <property name="Adapters"> @@ -4662,7 +4672,8 @@ under the License. </property> </bean> - PlainTextUserAuthenticator works the same way MD5UserAuthenticator worked prior to 4.1. + PlainTextUserAuthenticator works the same way MD5UserAuthenticator worked prior to + 4.1. If you are using Ubuntu, follow this procedure to upgrade your packages. If not, @@ -5128,9 +5139,12 @@ service cloudstack-agent start - After upgrading to 4.1, API clients are expected to send plain text passwords for login and user creation, instead of MD5 hash. Incase, api client changes are not acceptable, following changes are to be made for backward compatibility: - Modify componentsContext.xml, and make PlainTextUserAuthenticator as the default authenticator (1st entry in the userAuthenticators adapter list is default) - + After upgrading to 4.1, API clients are expected to send plain text passwords for + login and user creation, instead of MD5 hash. Incase, api client changes are not + acceptable, following changes are to be made for backward compatibility: + Modify componentsContext.xml, and make PlainTextUserAuthenticator as the default + authenticator (1st entry in the userAuthenticators adapter list is default) + <!-- Security adapters --> <bean id="userAuthenticators" class="com.cloud.utils.component.AdapterList"> <property name="Adapters"> @@ -5142,7 +5156,8 @@ service cloudstack-agent start </property> </bean> - PlainTextUserAuthenticator works the same way MD5UserAuthenticator worked prior to 4.1. + PlainTextUserAuthenticator works the same way MD5UserAuthenticator worked prior to + 4.1. Start the first Management Server. Do not start any other Management Server nodes @@ -5723,9 +5738,12 @@ service cloudstack-agent start - After upgrading to 4.1, API clients are expected to send plain text passwords for login and user creation, instead of MD5 hash. Incase, api client changes are not acceptable, following changes are to be made for backward compatibility: - Modify componentsContext.xml, and make PlainTextUserAuthenticator as the default authenticator (1st entry in the userAuthenticators adapter list is default) - + After upgrading to 4.1, API clients are expected to send plain text passwords for + login and user creation, instead of MD5 hash. Incase, api client changes are not + acceptable, following changes are to be made for backward compatibility: + Modify componentsContext.xml, and make PlainTextUserAuthenticator as the default + authenticator (1st entry in the userAuthenticators adapter list is default) + <!-- Security adapters --> <bean id="userAuthenticators" class="com.cloud.utils.component.AdapterList"> <property name="Adapters"> @@ -5737,7 +5755,8 @@ service cloudstack-agent start </property> </bean> - PlainTextUserAuthenticator works the same way MD5UserAuthenticator worked prior to 4.1. + PlainTextUserAuthenticator works the same way MD5UserAuthenticator worked prior to + 4.1. If you have made changes to your existing copy of the diff --git a/docs/en-US/egress-firewall-rule.xml b/docs/en-US/egress-firewall-rule.xml index ef0e25efd03..ab16517b458 100644 --- a/docs/en-US/egress-firewall-rule.xml +++ b/docs/en-US/egress-firewall-rule.xml @@ -23,13 +23,15 @@ The egress firewall rules are supported only on virtual routers. - The egress traffic originates from a private network to a public network, such as the Internet. By default, the egress traffic is blocked, so no outgoing traffic is allowed from a guest network to the Internet. However, you can control the egress traffic in an Advanced zone by creating egress firewall rules. When an egress firewall rule is applied, the traffic specific to the rule is allowed and the remaining traffic is blocked. When all the firewall rules are removed the default policy, Block, is applied. + + The egress firewall rules are not supported on shared networks. + Consider the following scenarios to apply egress firewall rules: diff --git a/docs/en-US/images/nvp-add-controller.png b/docs/en-US/images/nvp-add-controller.png new file mode 100644 index 00000000000..e02d31f0a37 Binary files /dev/null and b/docs/en-US/images/nvp-add-controller.png differ diff --git a/docs/en-US/images/nvp-enable-provider.png b/docs/en-US/images/nvp-enable-provider.png new file mode 100644 index 00000000000..0f2d02ddfa9 Binary files /dev/null and b/docs/en-US/images/nvp-enable-provider.png differ diff --git a/docs/en-US/images/nvp-network-offering.png b/docs/en-US/images/nvp-network-offering.png new file mode 100644 index 00000000000..c2d25c48c19 Binary files /dev/null and b/docs/en-US/images/nvp-network-offering.png differ diff --git a/docs/en-US/images/nvp-physical-network-stt.png b/docs/en-US/images/nvp-physical-network-stt.png new file mode 100644 index 00000000000..2ce7853ac54 Binary files /dev/null and b/docs/en-US/images/nvp-physical-network-stt.png differ diff --git a/docs/en-US/images/nvp-vpc-offering-edit.png b/docs/en-US/images/nvp-vpc-offering-edit.png new file mode 100644 index 00000000000..ff235e24cd6 Binary files /dev/null and b/docs/en-US/images/nvp-vpc-offering-edit.png differ diff --git a/docs/en-US/multiple-ip-nic.xml b/docs/en-US/multiple-ip-nic.xml index 561ba0757b5..926235c3518 100644 --- a/docs/en-US/multiple-ip-nic.xml +++ b/docs/en-US/multiple-ip-nic.xml @@ -24,8 +24,7 @@ &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. + IPs. In addition to the primary IP, you can assign additional IPs to the guest VM 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 diff --git a/docs/en-US/plugin-niciranvp-about.xml b/docs/en-US/plugin-niciranvp-about.xml index 8d2e20e7756..cfab83c73c3 100644 --- a/docs/en-US/plugin-niciranvp-about.xml +++ b/docs/en-US/plugin-niciranvp-about.xml @@ -1,5 +1,5 @@ - %BOOK_ENTITIES; diff --git a/docs/en-US/plugin-niciranvp-devicemanagement.xml b/docs/en-US/plugin-niciranvp-devicemanagement.xml index 57b8eee9d7d..761c39f3179 100644 --- a/docs/en-US/plugin-niciranvp-devicemanagement.xml +++ b/docs/en-US/plugin-niciranvp-devicemanagement.xml @@ -21,27 +21,15 @@ under the License. -->
- Device-management - In &PRODUCT; 4.0.x each Nicira NVP setup is considered a "device" that can be added and removed from a physical network. To complete the configuration of the Nicira NVP plugin a device needs to be added to the physical network using the "addNiciraNVPDevice" API call. The plugin is now enabled on the physical network and any guest networks created on that network will be provisioned using the Nicira NVP Controller. - The plugin introduces a set of new API calls to manage the devices, see below or refer to the API reference. - - addNiciraNvpDevice - - - physicalnetworkid: the UUID of the physical network on which the device is configured - hostname: the IP address of the NVP controller - username: the username for access to the NVP API - password: the password for access to the NVP API - transportzoneuuid: the UUID of the transportzone - - - deleteNiciraNVPDevice - - - nvpdeviceid: the UUID of the device - - - listNiciraNVPDevices - + Device Management + In &PRODUCT; a Nicira NVP setup is considered a "device" that can be added and removed from a physical network. To complete the configuration of the Nicira NVP plugin a device needs to be added to the physical network. Press the "Add NVP Controller" button on the provider panel and enter the configuration details. + + + + + + nvp-physical-network-stt.png: a screenshot of the device configuration popup. + +
diff --git a/docs/en-US/plugin-niciranvp-features.xml b/docs/en-US/plugin-niciranvp-features.xml index c346bfb64e3..e439f1b4923 100644 --- a/docs/en-US/plugin-niciranvp-features.xml +++ b/docs/en-US/plugin-niciranvp-features.xml @@ -22,12 +22,63 @@ -->
Features of the Nicira NVP Plugin - In &PRODUCT; release 4.0.0-incubating this plugin supports the Connectivity service. This service is responsible for creating Layer 2 networks supporting the networks created by Guests. In other words when an tenant creates a new network, instead of the traditional VLAN a logical network will be created by sending the appropriate calls to the Nicira NVP Controller. - The plugin has been tested with Nicira NVP versions 2.1.0, 2.2.0 and 2.2.1 - In &PRODUCT; 4.0.0-incubating only the XenServer hypervisor is supported for use in - combination with Nicira NVP. - In &PRODUCT; 4.1.0-incubating both KVM and XenServer hypervisors are - supported. - In &PRODUCT; 4.0.0-incubating the UI components for this plugin are not complete, - configuration is done by sending commands to the API. + The following table lists the CloudStack network services provided by the Nicira NVP Plugin. + + Supported Services + + + + Network Service + CloudStack version + NVP version + + + + + Virtual Networking + >= 4.0 + >= 2.2.1 + + + Source NAT + >= 4.1 + >= 3.0.1 + + + Static NAT + >= 4.1 + >= 3.0.1 + + + Port Forwarding + >= 4.1 + >= 3.0.1 + + + +
+ The Virtual Networking service was originally called 'Connectivity' in CloudStack 4.0 + The following hypervisors are supported by the Nicira NVP Plugin. + + Supported Hypervisors + + + + Hypervisor + CloudStack version + + + + + XenServer + >= 4.0 + + + KVM + >= 4.1 + + + +
+ Please refer to the Nicira NVP configuration guide on how to prepare the hypervisors for Nicira NVP integration.
diff --git a/docs/en-US/plugin-niciranvp-introduction.xml b/docs/en-US/plugin-niciranvp-introduction.xml index 9c1d42df32d..a06f12317e5 100644 --- a/docs/en-US/plugin-niciranvp-introduction.xml +++ b/docs/en-US/plugin-niciranvp-introduction.xml @@ -22,5 +22,8 @@ -->
Introduction to the Nicira NVP Plugin - The Nicira NVP plugin allows CloudStack to use the Nicira solution for virtualized network as a provider for CloudStack networks and services. + The Nicira NVP plugin adds Nicira NVP as one of the available SDN implementations in + CloudStack. With the plugin an exisiting Nicira NVP setup can be used by CloudStack to + implement isolated guest networks and to provide additional services like routing and + NAT.
diff --git a/docs/en-US/plugin-niciranvp-networkofferings.xml b/docs/en-US/plugin-niciranvp-networkofferings.xml new file mode 100644 index 00000000000..b30437e97ba --- /dev/null +++ b/docs/en-US/plugin-niciranvp-networkofferings.xml @@ -0,0 +1,131 @@ + + +%BOOK_ENTITIES; + +%xinclude; +]> + +
+ Network Offerings + Using the Nicira NVP plugin requires a network offering with Virtual Networking enabled and configured to use the NiciraNvp element. Typical use cases combine services from the Virtual Router appliance and the Nicira NVP plugin. + + Isolated network offering with regular services from the Virtual Router. + + + + Service + Provider + + + + + VPN + VirtualRouter + + + DHCP + VirtualRouter + + + DNS + VirtualRouter + + + Firewall + VirtualRouter + + + Load Balancer + VirtualRouter + + + User Data + VirtualRouter + + + Source NAT + VirtualRouter + + + Static NAT + VirtualRouter + + + Post Forwarding + VirtualRouter + + + Virtual Networking + NiciraNVP + + + +
+ + + + + + nvp-physical-network-stt.png: a screenshot of a network offering. + + + The tag in the network offering should be set to the name of the physical network with the NVP provider. + Isolated network with network services. The virtual router is still required to provide network services like dns and dhcp. + + Isolated network offering with network services + + + + Service + Provider + + + + + DHCP + VirtualRouter + + + DNS + VirtualRouter + + + User Data + VirtualRouter + + + Source NAT + NiciraNVP + + + Static NAT + NiciraNVP + + + Post Forwarding + NiciraNVP + + + Virtual Networking + NiciraNVP + + + +
+ +
diff --git a/docs/en-US/plugin-niciranvp-physicalnet.xml b/docs/en-US/plugin-niciranvp-physicalnet.xml new file mode 100644 index 00000000000..d3202905fb1 --- /dev/null +++ b/docs/en-US/plugin-niciranvp-physicalnet.xml @@ -0,0 +1,37 @@ + + +%BOOK_ENTITIES; + +%xinclude; +]> + +
+ Zone Configuration + &PRODUCT; needs to have at least one physical network with the isolation method set to "STT". This network should be enabled for the Guest traffic type. + The Guest traffic type should be configured with the traffic label that matches the name of + the Integration Bridge on the hypervisor. See the Nicira NVP User Guide for more details + on how to set this up in XenServer or KVM. + + + + + + nvp-physical-network-stt.png: a screenshot of a physical network with the STT isolation type + + +
diff --git a/docs/en-US/plugin-niciranvp-preparations.xml b/docs/en-US/plugin-niciranvp-preparations.xml index 762c941fd13..60725591fda 100644 --- a/docs/en-US/plugin-niciranvp-preparations.xml +++ b/docs/en-US/plugin-niciranvp-preparations.xml @@ -22,17 +22,16 @@ -->
Prerequisites - Before enabling the Nicira NVP plugin the NVP Controller needs to be configured. Please review the NVP User Guide on how to do that. - &PRODUCT; needs to have at least one physical network with the isolation method set to "STT". This network should be enabled for the Guest traffic type. - The Guest traffic type should be configured with the traffic label that matches the name of - the Integration Bridge on the hypervisor. See the Nicira NVP User Guide for more details - on how to set this up in XenServer or KVM. + Before enabling the Nicira NVP plugin the NVP Controller needs to be configured. Please review the NVP User Guide on how to do that. Make sure you have the following information ready: The IP address of the NVP Controller The username to access the API The password to access the API The UUID of the Transport Zone that contains the hypervisors in this Zone - The UUID of the Physical Network that will be used for the Guest networks + + The UUID of the Gateway Service used to provide router and NAT services. + + The gateway service uuid is optional and is used for Layer 3 services only (SourceNat, StaticNat and PortForwarding)
diff --git a/docs/en-US/plugin-niciranvp-provider.xml b/docs/en-US/plugin-niciranvp-provider.xml index 80fb2273238..8694478b483 100644 --- a/docs/en-US/plugin-niciranvp-provider.xml +++ b/docs/en-US/plugin-niciranvp-provider.xml @@ -22,21 +22,15 @@ -->
Enabling the service provider - To allow CloudStack to use the Nicira NVP Plugin the network service provider needs to be enabled on the physical network. The following sequence of API calls will enable the network service provider - - addNetworkServiceProvider - - - name = "NiciraNvp" - physicalnetworkid = <the uuid of the physical network> - - - updateNetworkServiceProvider - - - id = <the provider uuid returned by the previous call> - state = "Enabled" - - - + The Nicira NVP provider is disabled by default. Navigate to the "Network Service Providers" configuration of the physical network with the STT isolation type. Navigate to the Nicira NVP provider and press the "Enable Provider" button. + CloudStack 4.0 does not have the UI interface to configure the Nicira NVP plugin. Configuration needs to be done using the API directly. + + + + + + nvp-physical-network-stt.png: a screenshot of an enabled Nicira NVP provider + + +
\ No newline at end of file diff --git a/docs/en-US/plugin-niciranvp-revisions.xml b/docs/en-US/plugin-niciranvp-revisions.xml index b8e6935c5d1..b58d3336aba 100644 --- a/docs/en-US/plugin-niciranvp-revisions.xml +++ b/docs/en-US/plugin-niciranvp-revisions.xml @@ -40,6 +40,20 @@ + + 1-0 + Wed May 22 2013 + + Hugo + Trippaers + hugo@apache.org + + + + Documentation updated for &PRODUCT; 4.1.0 + + + diff --git a/docs/en-US/plugin-niciranvp-tables.xml b/docs/en-US/plugin-niciranvp-tables.xml index 4f816550b30..615f3494c09 100644 --- a/docs/en-US/plugin-niciranvp-tables.xml +++ b/docs/en-US/plugin-niciranvp-tables.xml @@ -23,29 +23,84 @@
Database tables The following tables are added to the cloud database for the Nicira NVP Plugin - - nicira_nvp_nic_map, contains a mapping from nic to logical switch port - - - id - logicalswitch, uuid of the logical switch this port is connected to - logicalswitchport, uuid of the logical switch port for this nic - nic, the CloudStack uuid for this nic, reference to the nics table - - - - - external_nicira_nvp_devices, contains all configured devices - - - id - uuid - physical_network_id, the physical network this device is configured on - provider_name, set to "NiciraNvp" - device_name, display name for this device - host_id, reference to the host table with the device configuration - - - - + + nicira_nvp_nic_map + + + + id + auto incrementing id + + + logicalswitch + uuid of the logical switch this port is connected to + + + logicalswitchport + uuid of the logical switch port for this nic + + + nic + the &PRODUCT; uuid for this nic, reference to the nics table + + + +
+ + + external_nicira_nvp_devices + + + + id + auto incrementing id + + + uuid + UUID identifying this device + + + physical_network_id + the physical network this device is configured on + + + provider_name + NiciraNVP + + + device_name + display name for this device + + + host_id + reference to the host table with the device configuration + + + +
+ + + nicira_nvp_router_map + + + + id + auto incrementing id + + + logicalrouter_uuid + uuid of the logical router + + + network_id + id of the network this router is linked to + + + +
+ + + nicira_nvp_router_map is only available in &PRODUCT; 4.1 and above + +
\ No newline at end of file diff --git a/docs/en-US/plugin-niciranvp-usage.xml b/docs/en-US/plugin-niciranvp-usage.xml index 76f9a0b5b05..9f04c382bd6 100644 --- a/docs/en-US/plugin-niciranvp-usage.xml +++ b/docs/en-US/plugin-niciranvp-usage.xml @@ -21,10 +21,13 @@ under the License. --> - Using the Nicira NVP Plugin + Configuring the Nicira NVP Plugin - - - + + + + diff --git a/docs/en-US/plugin-niciranvp-guide.xml b/docs/en-US/plugin-niciranvp-vpc.xml similarity index 65% rename from docs/en-US/plugin-niciranvp-guide.xml rename to docs/en-US/plugin-niciranvp-vpc.xml index 89c9871021d..a43c5fa85d3 100644 --- a/docs/en-US/plugin-niciranvp-guide.xml +++ b/docs/en-US/plugin-niciranvp-vpc.xml @@ -1,11 +1,10 @@ - + %BOOK_ENTITIES; %xinclude; ]> - - - Plugin Guide for the Nicira NVP Plugin - - - + + Using the Nicira NVP plugin with VPC + + + + + diff --git a/docs/en-US/plugin-niciranvp-vpcfeatures.xml b/docs/en-US/plugin-niciranvp-vpcfeatures.xml new file mode 100644 index 00000000000..a8d8194e9ba --- /dev/null +++ b/docs/en-US/plugin-niciranvp-vpcfeatures.xml @@ -0,0 +1,28 @@ + + +%BOOK_ENTITIES; + +%xinclude; +]> + +
+ Supported VPC features + The Nicira NVP plugin supports &PRODUCT; VPC to a certain extent. Starting with &PRODUCT; version 4.1 VPCs can be deployed using NVP isolated networks. + It is not possible to use a Nicira NVP Logical Router for as a VPC Router + It is not possible to connect a private gateway using a Nicira NVP Logical Switch +
diff --git a/docs/en-US/plugin-niciranvp-vpcnetworkoffering.xml b/docs/en-US/plugin-niciranvp-vpcnetworkoffering.xml new file mode 100644 index 00000000000..141006ee350 --- /dev/null +++ b/docs/en-US/plugin-niciranvp-vpcnetworkoffering.xml @@ -0,0 +1,81 @@ + + +%BOOK_ENTITIES; + +%xinclude; +]> + +
+ VPC Network Offerings + The VPC needs specific network offerings with the VPC flag enabled. Otherwise these network offerings are identical to regular network offerings. To allow VPC networks with a Nicira NVP isolated network the offerings need to support the Virtual Networking service with the NiciraNVP provider. + In a typical configuration two network offerings need to be created. One with the loadbalancing service enabled and one without loadbalancing. + + VPC Network Offering with Loadbalancing + + + + Service + Provider + + + + + VPN + VpcVirtualRouter + + + DHCP + VpcVirtualRouter + + + DNS + VpcVirtualRouter + + + Load Balancer + VpcVirtualRouter + + + User Data + VpcVirtualRouter + + + Source NAT + VpcVirtualRouter + + + Static NAT + VpcVirtualRouter + + + Post Forwarding + VpcVirtualRouter + + + NetworkACL + VpcVirtualRouter + + + Virtual Networking + NiciraNVP + + + +
+ +
diff --git a/docs/en-US/plugin-niciranvp-vpcoffering.xml b/docs/en-US/plugin-niciranvp-vpcoffering.xml new file mode 100644 index 00000000000..292621e516c --- /dev/null +++ b/docs/en-US/plugin-niciranvp-vpcoffering.xml @@ -0,0 +1,38 @@ + + +%BOOK_ENTITIES; + +%xinclude; +]> + +
+ VPC Offering with Nicira NVP + To allow a VPC to use the Nicira NVP plugin to provision networks, a new VPC offering needs to be created which allows the Virtual Networking service to be implemented by NiciraNVP. + This is not currently possible with the UI. The API does provide the proper calls to create a VPC offering with Virtual Networking enabled. However due to a limitation in the 4.1 API it is not possible to select the provider for this network service. To configure the VPC offering with the NiciraNVP provider edit the database table 'vpc_offering_service_map' and change the provider to NiciraNvp for the service 'Connectivity' + It is also possible to update the default VPC offering by adding a row to the + 'vpc_offering_service_map' with service 'Connectivity' and provider 'NiciraNvp' + + + + + + nvp-physical-network-stt.png: a screenshot of the mysql table. + + + When creating a new VPC offering please note that the UI does not allow you to select a VPC offering yet. The VPC needs to be created using the API with the offering UUID. +
diff --git a/engine/components-api/src/com/cloud/network/NetworkManager.java b/engine/components-api/src/com/cloud/network/NetworkManager.java index 24e422457f2..06db2e6cfbe 100755 --- a/engine/components-api/src/com/cloud/network/NetworkManager.java +++ b/engine/components-api/src/com/cloud/network/NetworkManager.java @@ -266,6 +266,11 @@ public interface NetworkManager { IPAddressVO associateIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException; + IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID) + throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException; + + boolean releasePortableIpAddress(long addrId); + IPAddressVO associatePortableIPToGuestNetwork(long ipAddrId, long networkId, boolean releaseOnFailure) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException; @@ -312,9 +317,6 @@ public interface NetworkManager { InsufficientAddressCapacityException, ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException; - PublicIp assignVpnGatewayIpAddress(long dcId, Account owner, long vpcId) throws InsufficientAddressCapacityException, ConcurrentOperationException; - - /** * @param addr */ @@ -341,9 +343,6 @@ public interface NetworkManager { int getNetworkLockTimeout(); - boolean cleanupIpResources(long addrId, long userId, Account caller); - - boolean restartNetwork(Long networkId, Account callerAccount, User callerUser, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; @@ -360,33 +359,26 @@ public interface NetworkManager { IpAddress allocateIp(Account ipOwner, boolean isSystem, Account caller, long callerId, DataCenter zone) throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException; - - IpAddress allocatePortableIp(Account ipOwner, Account caller, long dcId, Long networkId, Long vpcID) - throws ConcurrentOperationException, ResourceAllocationException, InsufficientAddressCapacityException; - Map finalizeServicesAndProvidersForNetwork(NetworkOffering offering, Long physicalNetworkId); - List getProvidersForServiceInNetwork(Network network, Service service); StaticNatServiceProvider getStaticNatProviderForNetwork(Network network); + boolean isNetworkInlineMode(Network network); int getRuleCountForIp(Long addressId, FirewallRule.Purpose purpose, FirewallRule.State state); LoadBalancingServiceProvider getLoadBalancingProviderForNetwork(Network network, Scheme lbScheme); - boolean isSecondaryIpSetForNic(long nicId); - public String allocateGuestIP(Account ipOwner, boolean isSystem, long zoneId, Long networkId, String requestedIp) - throws InsufficientAddressCapacityException; - + public String allocateGuestIP(Account ipOwner, boolean isSystem, long zoneId, Long networkId, String requestedIp) throws InsufficientAddressCapacityException; List listVmNics(Long vmId, Long nicId); + String allocatePublicIpForGuestNic(Long networkId, DataCenter dc, Pod pod, Account caller, String requestedIp) throws InsufficientAddressCapacityException; - boolean removeVmSecondaryIpsOfNic(long nicId); NicVO savePlaceholderNic(Network network, String ip4Address, Type vmType); diff --git a/engine/schema/src/com/cloud/upgrade/DatabaseUpgradeChecker.java b/engine/schema/src/com/cloud/upgrade/DatabaseUpgradeChecker.java index 9bc0ba599c2..e23815b7d28 100755 --- a/engine/schema/src/com/cloud/upgrade/DatabaseUpgradeChecker.java +++ b/engine/schema/src/com/cloud/upgrade/DatabaseUpgradeChecker.java @@ -261,7 +261,10 @@ public class DatabaseUpgradeChecker implements SystemIntegrityChecker { } txn.commit(); - } finally { + } catch (CloudRuntimeException e){ + s_logger.error("Unable to upgrade the database", e); + throw new CloudRuntimeException("Unable to upgrade the database", e); + }finally { txn.close(); } } diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade302to40.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade302to40.java index ecda872dfa4..6f31fdd2b8e 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade302to40.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade302to40.java @@ -18,6 +18,7 @@ package com.cloud.upgrade.dao; import java.io.File; +import java.io.UnsupportedEncodingException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -72,6 +73,7 @@ public class Upgrade302to40 extends Upgrade30xBase implements DbUpgrade { fixForeignKeys(conn); setupExternalNetworkDevices(conn); fixZoneUsingExternalDevices(conn); + encryptConfig(conn); } @Override @@ -1079,4 +1081,43 @@ public class Upgrade302to40 extends Upgrade30xBase implements DbUpgrade { s_logger.info("Successfully upgraded networks using F5 and SRX devices to have a entry in the network_external_lb_device_map and network_external_firewall_device_map"); } } + + private void encryptConfig(Connection conn){ + //Encrypt config params and change category to Hidden + s_logger.debug("Encrypting Config values"); + PreparedStatement pstmt = null; + ResultSet rs = null; + try { + pstmt = conn.prepareStatement("select name, value from `cloud`.`configuration` where name in ('router.ram.size', 'secondary.storage.vm', 'security.hash.key') and category <> 'Hidden'"); + rs = pstmt.executeQuery(); + while (rs.next()) { + String name = rs.getString(1); + String value = rs.getString(2); + if (value == null) { + continue; + } + String encryptedValue = DBEncryptionUtil.encrypt(value); + pstmt = conn.prepareStatement("update `cloud`.`configuration` set value=?, category = 'Hidden' where name=?"); + pstmt.setBytes(1, encryptedValue.getBytes("UTF-8")); + pstmt.setString(2, name); + pstmt.executeUpdate(); + } + } catch (SQLException e) { + throw new CloudRuntimeException("Unable encrypt configuration values ", e); + } catch (UnsupportedEncodingException e) { + throw new CloudRuntimeException("Unable encrypt configuration values ", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + s_logger.debug("Done encrypting Config values"); + } } diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java index c03d377cbe0..16ab05cea06 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -28,6 +28,8 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import com.cloud.network.vpc.NetworkACL; @@ -75,6 +77,36 @@ public class Upgrade410to420 implements DbUpgrade { updateNetworkACLs(conn); addHostDetailsIndex(conn); updateNetworksForPrivateGateways(conn); + removeFirewallServiceFromSharedNetworkOfferingWithSGService(conn); + fix22xKVMSnapshots(conn); + addIndexForAlert(conn); + } + + private void addIndexForAlert(Connection conn) { + + //First drop if it exists. (Due to patches shipped to customers some will have the index and some wont.) + List indexList = new ArrayList(); + s_logger.debug("Dropping index i_alert__last_sent if it exists"); + indexList.add("i_alert__last_sent"); + DbUpgradeUtils.dropKeysIfExist(conn, "alert", indexList, false); + + //Now add index. + PreparedStatement pstmt = null; + try { + pstmt = conn.prepareStatement("ALTER TABLE `cloud`.`alert` ADD INDEX `i_alert__last_sent`(`last_sent`)"); + pstmt.executeUpdate(); + s_logger.debug("Added index i_alert__last_sent for table alert"); + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to add index i_alert__last_sent to alert table for the column last_sent", e); + } finally { + try { + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + } private void updateSystemVmTemplates(Connection conn) { @@ -747,4 +779,74 @@ public class Upgrade410to420 implements DbUpgrade { throw new CloudRuntimeException("Failed to update private networks with VPC id.", e); } } + + private void removeFirewallServiceFromSharedNetworkOfferingWithSGService(Connection conn) { + PreparedStatement pstmt = null; + ResultSet rs = null; + + try { + pstmt = conn.prepareStatement("select id from `cloud`.`network_offerings` where unique_name='DefaultSharedNetworkOfferingWithSGService'"); + rs = pstmt.executeQuery(); + while (rs.next()) { + long id = rs.getLong(1); + // remove Firewall service for SG shared network offering + pstmt = conn.prepareStatement("DELETE from `cloud`.`ntwk_offering_service_map` where network_offering_id=? and service='Firewall'"); + pstmt.setLong(1, id); + pstmt.executeUpdate(); + } + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to remove Firewall service for SG shared network offering.", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + } + + private void fix22xKVMSnapshots(Connection conn) { + PreparedStatement pstmt = null; + ResultSet rs = null; + s_logger.debug("Updating KVM snapshots"); + try { + pstmt = conn.prepareStatement("select id, backup_snap_id from `cloud`.`snapshots` where hypervisor_type='KVM' and removed is null and backup_snap_id is not null"); + rs = pstmt.executeQuery(); + while (rs.next()) { + long id = rs.getLong(1); + String backUpPath = rs.getString(2); + // Update Backup Path. Remove anything before /snapshots/ + // e.g 22x Path /mnt/0f14da63-7033-3ca5-bdbe-fa62f4e2f38a/snapshots/1/2/6/i-2-6-VM_ROOT-6_20121219072022 + // Above path should change to /snapshots/1/2/6/i-2-6-VM_ROOT-6_20121219072022 + int index = backUpPath.indexOf("snapshots"+File.separator); + if (index > 1){ + String correctedPath = File.separator + backUpPath.substring(index); + s_logger.debug("Updating Snapshot with id: "+id+" original backup path: "+backUpPath+ " updated backup path: "+correctedPath); + pstmt = conn.prepareStatement("UPDATE `cloud`.`snapshots` set backup_snap_id=? where id = ?"); + pstmt.setString(1, correctedPath); + pstmt.setLong(2, id); + pstmt.executeUpdate(); + } + } + s_logger.debug("Done updating KVM snapshots"); + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to update backup id for KVM snapshots", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + } } diff --git a/engine/schema/src/com/cloud/usage/dao/UsageNetworkDao.java b/engine/schema/src/com/cloud/usage/dao/UsageNetworkDao.java index 0f7c771b2dc..aa43eab10e9 100644 --- a/engine/schema/src/com/cloud/usage/dao/UsageNetworkDao.java +++ b/engine/schema/src/com/cloud/usage/dao/UsageNetworkDao.java @@ -16,6 +16,7 @@ // under the License. package com.cloud.usage.dao; +import java.util.List; import java.util.Map; import com.cloud.usage.UsageNetworkVO; @@ -24,4 +25,5 @@ import com.cloud.utils.db.GenericDao; public interface UsageNetworkDao extends GenericDao { Map getRecentNetworkStats(); void deleteOldStats(long maxEventTime); + void saveUsageNetworks(List usageNetworks); } diff --git a/engine/schema/src/com/cloud/usage/dao/UsageNetworkDaoImpl.java b/engine/schema/src/com/cloud/usage/dao/UsageNetworkDaoImpl.java index d64fd807890..af8083aa65a 100644 --- a/engine/schema/src/com/cloud/usage/dao/UsageNetworkDaoImpl.java +++ b/engine/schema/src/com/cloud/usage/dao/UsageNetworkDaoImpl.java @@ -19,6 +19,7 @@ package com.cloud.usage.dao; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.ejb.Local; @@ -29,6 +30,7 @@ import org.springframework.stereotype.Component; import com.cloud.usage.UsageNetworkVO; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.Transaction; +import com.cloud.utils.exception.CloudRuntimeException; @Component @Local(value={UsageNetworkDao.class}) @@ -41,6 +43,8 @@ public class UsageNetworkDaoImpl extends GenericDaoBase im ") joinnet on u.account_id = joinnet.acct_id and u.zone_id = joinnet.z_id and u.event_time_millis = joinnet.max_date"; private static final String DELETE_OLD_STATS = "DELETE FROM cloud_usage.usage_network WHERE event_time_millis < ?"; + private static final String INSERT_USAGE_NETWORK = "INSERT INTO cloud_usage.usage_network (account_id, zone_id, host_id, host_type, network_id, bytes_sent, bytes_received, agg_bytes_received, agg_bytes_sent, event_time_millis) VALUES (?,?,?,?,?,?,?,?,?,?)"; + public UsageNetworkDaoImpl() { } @@ -95,4 +99,34 @@ public class UsageNetworkDaoImpl extends GenericDaoBase im s_logger.error("error deleting old usage network stats", ex); } } + + @Override + public void saveUsageNetworks (List usageNetworks) { + Transaction txn = Transaction.currentTxn(); + try { + txn.start(); + String sql = INSERT_USAGE_NETWORK; + PreparedStatement pstmt = null; + pstmt = txn.prepareAutoCloseStatement(sql); // in reality I just want CLOUD_USAGE dataSource connection + for (UsageNetworkVO usageNetwork : usageNetworks) { + pstmt.setLong(1, usageNetwork.getAccountId()); + pstmt.setLong(2, usageNetwork.getZoneId()); + pstmt.setLong(3, usageNetwork.getHostId()); + pstmt.setString(4, usageNetwork.getHostType()); + pstmt.setLong(5, usageNetwork.getNetworkId()); + pstmt.setLong(6, usageNetwork.getBytesSent()); + pstmt.setLong(7, usageNetwork.getBytesReceived()); + pstmt.setLong(8, usageNetwork.getAggBytesReceived()); + pstmt.setLong(9, usageNetwork.getAggBytesSent()); + pstmt.setLong(10, usageNetwork.getEventTimeMillis()); + pstmt.addBatch(); + } + pstmt.executeBatch(); + txn.commit(); + } catch (Exception ex) { + txn.rollback(); + s_logger.error("error saving usage_network to cloud_usage db", ex); + throw new CloudRuntimeException(ex.getMessage()); + } + } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java b/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java index 790ae13af0f..f95993985ef 100755 --- a/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java +++ b/engine/storage/src/org/apache/cloudstack/storage/allocator/AbstractStoragePoolAllocator.java @@ -167,12 +167,6 @@ public abstract class AbstractStoragePoolAllocator extends AdapterBase implement return false; } - DiskOfferingVO diskOffering = _diskOfferingDao.findById(dskCh.getDiskOfferingId()); - if (diskOffering.getSystemUse() && pool.getPoolType() == StoragePoolType.RBD) { - s_logger.debug("Skipping RBD pool " + pool.getName() + " as a suitable pool. RBD is not supported for System VM's"); - return false; - } - Long clusterId = pool.getClusterId(); ClusterVO cluster = _clusterDao.findById(clusterId); diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/AsyncJobDao.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/AsyncJobDao.java index ba284959adc..4c442c89780 100644 --- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/AsyncJobDao.java +++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/AsyncJobDao.java @@ -31,5 +31,7 @@ public interface AsyncJobDao extends GenericDao { void cleanupPseduoJobs(long msid); List getExpiredJobs(Date cutTime, int limit); + List getExpiredUnfinishedJobs(Date cutTime, int limit); void resetJobProcess(long msid, int jobResultCode, String jobResultMessage); + List getExpiredCompletedJobs(Date cutTime, int limit); } diff --git a/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/AsyncJobDaoImpl.java b/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/AsyncJobDaoImpl.java index 9559b9ce80e..276323c3cc6 100644 --- a/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/AsyncJobDaoImpl.java +++ b/framework/jobs/src/org/apache/cloudstack/framework/jobs/dao/AsyncJobDaoImpl.java @@ -31,41 +31,57 @@ import com.cloud.utils.db.Filter; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; -import com.cloud.utils.db.Transaction; import com.cloud.utils.db.SearchCriteria.Op; +import com.cloud.utils.db.Transaction; public class AsyncJobDaoImpl extends GenericDaoBase implements AsyncJobDao { private static final Logger s_logger = Logger.getLogger(AsyncJobDaoImpl.class.getName()); - private final SearchBuilder pendingAsyncJobSearch; - private final SearchBuilder pendingAsyncJobsSearch; - private final SearchBuilder expiringAsyncJobSearch; + private final SearchBuilder pendingAsyncJobSearch; + private final SearchBuilder pendingAsyncJobsSearch; + private final SearchBuilder expiringAsyncJobSearch; private final SearchBuilder pseudoJobSearch; private final SearchBuilder pseudoJobCleanupSearch; + private final SearchBuilder expiringUnfinishedAsyncJobSearch; + private final SearchBuilder expiringCompletedAsyncJobSearch; + public AsyncJobDaoImpl() { pendingAsyncJobSearch = createSearchBuilder(); - pendingAsyncJobSearch.and("instanceType", pendingAsyncJobSearch.entity().getInstanceType(), + pendingAsyncJobSearch.and("instanceType", pendingAsyncJobSearch.entity().getInstanceType(), SearchCriteria.Op.EQ); - pendingAsyncJobSearch.and("instanceId", pendingAsyncJobSearch.entity().getInstanceId(), + pendingAsyncJobSearch.and("instanceId", pendingAsyncJobSearch.entity().getInstanceId(), SearchCriteria.Op.EQ); - pendingAsyncJobSearch.and("status", pendingAsyncJobSearch.entity().getStatus(), + pendingAsyncJobSearch.and("status", pendingAsyncJobSearch.entity().getStatus(), SearchCriteria.Op.EQ); pendingAsyncJobSearch.done(); + expiringAsyncJobSearch = createSearchBuilder(); + expiringAsyncJobSearch.and("created", expiringAsyncJobSearch.entity().getCreated(), SearchCriteria.Op.LTEQ); + expiringAsyncJobSearch.done(); + pendingAsyncJobsSearch = createSearchBuilder(); - pendingAsyncJobsSearch.and("instanceType", pendingAsyncJobsSearch.entity().getInstanceType(), + pendingAsyncJobsSearch.and("instanceType", pendingAsyncJobsSearch.entity().getInstanceType(), SearchCriteria.Op.EQ); - pendingAsyncJobsSearch.and("accountId", pendingAsyncJobsSearch.entity().getAccountId(), + pendingAsyncJobsSearch.and("accountId", pendingAsyncJobsSearch.entity().getAccountId(), SearchCriteria.Op.EQ); - pendingAsyncJobsSearch.and("status", pendingAsyncJobsSearch.entity().getStatus(), + pendingAsyncJobsSearch.and("status", pendingAsyncJobsSearch.entity().getStatus(), SearchCriteria.Op.EQ); pendingAsyncJobsSearch.done(); - expiringAsyncJobSearch = createSearchBuilder(); - expiringAsyncJobSearch.and("created", expiringAsyncJobSearch.entity().getCreated(), + expiringUnfinishedAsyncJobSearch = createSearchBuilder(); + expiringUnfinishedAsyncJobSearch.and("created", expiringUnfinishedAsyncJobSearch.entity().getCreated(), SearchCriteria.Op.LTEQ); - expiringAsyncJobSearch.done(); + expiringUnfinishedAsyncJobSearch.and("completeMsId", expiringUnfinishedAsyncJobSearch.entity().getCompleteMsid(), SearchCriteria.Op.NULL); + expiringUnfinishedAsyncJobSearch.and("jobStatus", expiringUnfinishedAsyncJobSearch.entity().getStatus(), SearchCriteria.Op.EQ); + expiringUnfinishedAsyncJobSearch.done(); + + expiringCompletedAsyncJobSearch = createSearchBuilder(); + expiringCompletedAsyncJobSearch.and("created", expiringCompletedAsyncJobSearch.entity().getCreated(), + SearchCriteria.Op.LTEQ); + expiringCompletedAsyncJobSearch.and("completeMsId", expiringCompletedAsyncJobSearch.entity().getCompleteMsid(), SearchCriteria.Op.NNULL); + expiringCompletedAsyncJobSearch.and("jobStatus", expiringCompletedAsyncJobSearch.entity().getStatus(), SearchCriteria.Op.NEQ); + expiringCompletedAsyncJobSearch.done(); pseudoJobSearch = createSearchBuilder(); pseudoJobSearch.and("jobDispatcher", pseudoJobSearch.entity().getDispatcher(), Op.EQ); @@ -76,9 +92,11 @@ public class AsyncJobDaoImpl extends GenericDaoBase implements pseudoJobCleanupSearch = createSearchBuilder(); pseudoJobCleanupSearch.and("initMsid", pseudoJobCleanupSearch.entity().getInitMsid(), Op.EQ); pseudoJobCleanupSearch.done(); + } - public AsyncJobVO findInstancePendingAsyncJob(String instanceType, long instanceId) { + @Override + public AsyncJobVO findInstancePendingAsyncJob(String instanceType, long instanceId) { SearchCriteria sc = pendingAsyncJobSearch.create(); sc.setParameters("instanceType", instanceType); sc.setParameters("instanceId", instanceId); @@ -95,7 +113,8 @@ public class AsyncJobDaoImpl extends GenericDaoBase implements return null; } - public List findInstancePendingAsyncJobs(String instanceType, Long accountId) { + @Override + public List findInstancePendingAsyncJobs(String instanceType, Long accountId) { SearchCriteria sc = pendingAsyncJobsSearch.create(); sc.setParameters("instanceType", instanceType); @@ -107,7 +126,8 @@ public class AsyncJobDaoImpl extends GenericDaoBase implements return listBy(sc); } - public AsyncJobVO findPseudoJob(long threadId, long msid) { + @Override + public AsyncJobVO findPseudoJob(long threadId, long msid) { SearchCriteria sc = pseudoJobSearch.create(); sc.setParameters("jobDispatcher", AsyncJobConstants.JOB_DISPATCHER_PSEUDO); sc.setParameters("instanceType", AsyncJobConstants.PSEUDO_JOB_INSTANCE_TYPE); @@ -122,22 +142,43 @@ public class AsyncJobDaoImpl extends GenericDaoBase implements return null; } - public void cleanupPseduoJobs(long msid) { + @Override + public void cleanupPseduoJobs(long msid) { SearchCriteria sc = pseudoJobCleanupSearch.create(); sc.setParameters("initMsid", msid); this.expunge(sc); } - public List getExpiredJobs(Date cutTime, int limit) { - SearchCriteria sc = expiringAsyncJobSearch.create(); + @Override + public List getExpiredJobs(Date cutTime, int limit) { + SearchCriteria sc = expiringAsyncJobSearch.create(); + sc.setParameters("created", cutTime); + Filter filter = new Filter(AsyncJobVO.class, "created", true, 0L, (long)limit); + return listIncludingRemovedBy(sc, filter); + } + + @Override + public List getExpiredUnfinishedJobs(Date cutTime, int limit) { + SearchCriteria sc = expiringUnfinishedAsyncJobSearch.create(); sc.setParameters("created", cutTime); + sc.setParameters("jobStatus", 0); + Filter filter = new Filter(AsyncJobVO.class, "created", true, 0L, (long)limit); + return listIncludingRemovedBy(sc, filter); + } + + @Override + public List getExpiredCompletedJobs(Date cutTime, int limit) { + SearchCriteria sc = expiringCompletedAsyncJobSearch.create(); + sc.setParameters("created", cutTime); + sc.setParameters("jobStatus", 0); Filter filter = new Filter(AsyncJobVO.class, "created", true, 0L, (long)limit); return listIncludingRemovedBy(sc, filter); } - @DB + @Override + @DB public void resetJobProcess(long msid, int jobResultCode, String jobResultMessage) { - String sql = "UPDATE async_job SET job_status=" + AsyncJobConstants.STATUS_FAILED + ", job_result_code=" + jobResultCode + String sql = "UPDATE async_job SET job_status=" + AsyncJobConstants.STATUS_FAILED + ", job_result_code=" + jobResultCode + ", job_result='" + jobResultMessage + "' where job_status=0 AND (job_complete_msid=? OR (job_complete_msid IS NULL AND job_init_msid=?))"; Transaction txn = Transaction.currentTxn(); 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 d918670edab..ca3b970210b 100755 --- a/patches/systemvm/debian/config/etc/init.d/cloud-early-config +++ b/patches/systemvm/debian/config/etc/init.d/cloud-early-config @@ -33,6 +33,9 @@ PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" # Fix haproxy directory issue mkdir -p /var/lib/haproxy +# Clear boot up flag, it would be created by rc.local after boot up done +rm /var/cache/cloud/boot_up_done + [ -x /sbin/ifup ] || exit 0 . /lib/lsb/init-functions diff --git a/patches/systemvm/debian/config/etc/rc.local b/patches/systemvm/debian/config/etc/rc.local index cb434a23526..6119497596b 100755 --- a/patches/systemvm/debian/config/etc/rc.local +++ b/patches/systemvm/debian/config/etc/rc.local @@ -13,3 +13,6 @@ do logger -t cloud "Stopping $svc" service $svc stop done + +date > /var/cache/cloud/boot_up_done +logger -t cloud "Boot up process done" diff --git a/patches/systemvm/debian/config/opt/cloud/bin/get_template_version.sh b/patches/systemvm/debian/config/opt/cloud/bin/get_template_version.sh index 298bc380f82..233ec983f8e 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/get_template_version.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/get_template_version.sh @@ -16,5 +16,31 @@ # specific language governing permissions and limitations # under the License. +# As the last command send to router before any rules operation, wait until boot up done + +__TIMEOUT=60 +__FLAGFILE=/var/cache/cloud/boot_up_done +done=0 +for i in `seq 1 $(($__TIMEOUT * 10))` +do + if [ -e $__FLAGFILE ] + then + done=1 + break + fi + sleep 0.1 + if [ $((i % 10)) -eq 0 ] + then + logger -t cloud "Waiting for VM boot up done for one second" + fi +done + +if [ -z $done ] +then + # declare we failed booting process + echo "Waited 60 seconds but boot up haven't been completed" + exit +fi + echo -n `cat /etc/cloudstack-release`'&' cat /var/cache/cloud/cloud-scripts-signature diff --git a/patches/systemvm/debian/config/opt/cloud/bin/ipassoc.sh b/patches/systemvm/debian/config/opt/cloud/bin/ipassoc.sh index f326fac9e54..d23ec00de5e 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/ipassoc.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/ipassoc.sh @@ -227,7 +227,8 @@ add_first_ip() { if [ $if_keep_state -ne 1 -o $old_state -ne 0 ] then sudo ip link set $ethDev up - sudo arping -c 3 -I $ethDev -A -U -s $ipNoMask $ipNoMask; + sudo arping -c 1 -I $ethDev -A -U -s $ipNoMask $ipNoMask; + sudo arping -c 1 -I $ethDev -A -U -s $ipNoMask $ipNoMask; fi add_routing $1 @@ -273,7 +274,8 @@ add_an_ip () { if [ $if_keep_state -ne 1 -o $old_state -ne 0 ] then sudo ip link set $ethDev up - sudo arping -c 3 -I $ethDev -A -U -s $ipNoMask $ipNoMask; + sudo arping -c 1 -I $ethDev -A -U -s $ipNoMask $ipNoMask; + sudo arping -c 1 -I $ethDev -A -U -s $ipNoMask $ipNoMask; fi add_routing $1 return $? diff --git a/patches/systemvm/debian/config/root/redundant_router/backup.sh.templ b/patches/systemvm/debian/config/root/redundant_router/backup.sh.templ index 7a1bd44584a..32c811b26d4 100644 --- a/patches/systemvm/debian/config/root/redundant_router/backup.sh.templ +++ b/patches/systemvm/debian/config/root/redundant_router/backup.sh.templ @@ -16,6 +16,8 @@ # specific language governing permissions and limitations # under the License. +sleep 1 + source /root/func.sh lock="biglock" diff --git a/plugins/hypervisors/kvm/pom.xml b/plugins/hypervisors/kvm/pom.xml index 613c817668e..1babe7cbf56 100644 --- a/plugins/hypervisors/kvm/pom.xml +++ b/plugins/hypervisors/kvm/pom.xml @@ -24,6 +24,10 @@ libvirt-org http://libvirt.org/maven2 + + ceph-com + http://ceph.com/maven + @@ -36,6 +40,11 @@ libvirt ${cs.libvirt-java.version} + + com.ceph + rados + ${cs.rados-java.version} + install diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index f2352192758..f30505dc09c 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -39,11 +39,11 @@ import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.HashSet; import java.util.Properties; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; @@ -57,10 +57,6 @@ import javax.ejb.Local; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; -import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; -import org.apache.cloudstack.utils.qemu.QemuImg; -import org.apache.cloudstack.utils.qemu.QemuImgFile; -import org.apache.cloudstack.utils.qemu.QemuImgException; import org.libvirt.Connect; import org.libvirt.Domain; import org.libvirt.DomainInfo; @@ -69,6 +65,11 @@ import org.libvirt.DomainSnapshot; import org.libvirt.LibvirtException; import org.libvirt.NodeInfo; +import org.apache.cloudstack.utils.qemu.QemuImg; +import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; +import org.apache.cloudstack.utils.qemu.QemuImgException; +import org.apache.cloudstack.utils.qemu.QemuImgFile; + import com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachIsoCommand; import com.cloud.agent.api.AttachVolumeAnswer; @@ -167,8 +168,8 @@ import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer; import com.cloud.agent.api.storage.DestroyCommand; import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer; import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand; -import com.cloud.agent.api.storage.ResizeVolumeCommand; import com.cloud.agent.api.storage.ResizeVolumeAnswer; +import com.cloud.agent.api.storage.ResizeVolumeCommand; import com.cloud.agent.api.to.IpAddressTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.StorageFilerTO; @@ -195,8 +196,8 @@ import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InputDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.InterfaceDef.hostNicType; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SerialDef; -import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VirtioSerialDef; import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.TermPolicy; +import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VirtioSerialDef; import com.cloud.hypervisor.kvm.storage.KVMPhysicalDisk; import com.cloud.hypervisor.kvm.storage.KVMStoragePool; import com.cloud.hypervisor.kvm.storage.KVMStoragePoolManager; @@ -218,9 +219,9 @@ import com.cloud.storage.template.Processor.FormatInfo; import com.cloud.storage.template.QCOW2Processor; import com.cloud.storage.template.TemplateInfo; import com.cloud.storage.template.TemplateLocation; +import com.cloud.utils.FileUtil; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; -import com.cloud.utils.FileUtil; import com.cloud.utils.PropertiesUtil; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; @@ -985,7 +986,7 @@ ServerResource { if (! f.isDirectory()){ s_logger.debug("failing to get physical interface from bridge" - + bridgeName + ", does " + f.getAbsolutePath() + + bridgeName + ", does " + f.getAbsolutePath() + "exist?"); return ""; } @@ -1055,7 +1056,7 @@ ServerResource { return vnetId; } - private void passCmdLine(String vmName, String cmdLine) + private void passCmdLine(String vmName, String cmdLine) throws InternalErrorException { final Script command = new Script(_patchViaSocketPath, _timeout, s_logger); String result; @@ -1254,6 +1255,13 @@ ServerResource { } private CopyVolumeAnswer execute(CopyVolumeCommand cmd) { + /** + This method is only used for copying files from Primary Storage TO Secondary Storage + + It COULD also do it the other way around, but the code in the ManagementServerImpl shows + that it always sets copyToSecondary to true + + */ boolean copyToSecondary = cmd.toSecondaryStorage(); String volumePath = cmd.getVolumePath(); StorageFilerTO pool = cmd.getPool(); @@ -1363,7 +1371,7 @@ ServerResource { disksize = dskch.getSize(); if (cmd.getTemplateUrl() != null) { - if(primaryPool.getType() == StoragePoolType.CLVM) { + if(primaryPool.getType() == StoragePoolType.CLVM) { vol = templateToPrimaryDownload(cmd.getTemplateUrl(),primaryPool); } else { BaseVol = primaryPool.getPhysicalDisk(cmd.getTemplateUrl()); @@ -1452,7 +1460,7 @@ ServerResource { return null; } - /* uses a local script now, eventually support for virStorageVolResize() will maybe work on + /* uses a local script now, eventually support for virStorageVolResize() will maybe work on qcow2 and lvm and we can do this in libvirt calls */ public Answer execute(ResizeVolumeCommand cmd) { String volid = cmd.getPath(); @@ -1469,16 +1477,16 @@ ServerResource { String type = getResizeScriptType(pool, vol); if (type == null) { - return new ResizeVolumeAnswer(cmd, false, "Unsupported volume format: pool type '" + return new ResizeVolumeAnswer(cmd, false, "Unsupported volume format: pool type '" + pool.getType() + "' and volume format '" + vol.getFormat() + "'"); } else if (type.equals("QCOW2") && shrinkOk) { return new ResizeVolumeAnswer(cmd, false, "Unable to shrink volumes of type " + type); } - s_logger.debug("got to the stage where we execute the volume resize, params:" + s_logger.debug("got to the stage where we execute the volume resize, params:" + path + "," + currentSize + "," + newSize + "," + type + "," + vmInstanceName + "," + shrinkOk); final Script resizecmd = new Script(_resizeVolumePath, - _cmdsTimeout, s_logger); + _cmdsTimeout, s_logger); resizecmd.add("-s",String.valueOf(newSize)); resizecmd.add("-c",String.valueOf(currentSize)); resizecmd.add("-p",path); @@ -1503,7 +1511,7 @@ ServerResource { return new ResizeVolumeAnswer(cmd, false, error); } - } + } public Answer execute(DestroyCommand cmd) { VolumeTO vol = cmd.getVolume(); @@ -1529,7 +1537,7 @@ ServerResource { if(pifparts.length == 2) { return pifparts[1]; } else { - s_logger.debug("failed to get vlan id from bridge " + brName + s_logger.debug("failed to get vlan id from bridge " + brName + "attached to physical interface" + pif); return ""; } @@ -1771,7 +1779,7 @@ ServerResource { for (InterfaceDef pluggedNic : pluggedNics) { String pluggedVlanBr = pluggedNic.getBrName(); String pluggedVlanId = getVlanIdFromBridge(pluggedVlanBr); - if (pubVlan.equalsIgnoreCase(Vlan.UNTAGGED) + if (pubVlan.equalsIgnoreCase(Vlan.UNTAGGED) && pluggedVlanBr.equalsIgnoreCase(_publicBridgeName)) { break; } else if (pluggedVlanBr.equalsIgnoreCase(_linkLocalBridgeName)){ @@ -1818,7 +1826,7 @@ ServerResource { for (InterfaceDef pluggedNic : pluggedNics) { String pluggedVlan = pluggedNic.getBrName(); if (pluggedVlan.equalsIgnoreCase(_linkLocalBridgeName)) { - vlanToNicNum.put("LinkLocal",devNum); + vlanToNicNum.put("LinkLocal",devNum); } else if (pluggedVlan.equalsIgnoreCase(_publicBridgeName) || pluggedVlan.equalsIgnoreCase(_privBridgeName) || pluggedVlan.equalsIgnoreCase(_guestBridgeName)) { @@ -1864,8 +1872,8 @@ ServerResource { if (nic.getBrName().equalsIgnoreCase(_linkLocalBridgeName)) { vlanAllocatedToVM.put("LinkLocal", nicPos); } else { - if (nic.getBrName().equalsIgnoreCase(_publicBridgeName) - || nic.getBrName().equalsIgnoreCase(_privBridgeName) + if (nic.getBrName().equalsIgnoreCase(_publicBridgeName) + || nic.getBrName().equalsIgnoreCase(_privBridgeName) || nic.getBrName().equalsIgnoreCase(_guestBridgeName)) { vlanAllocatedToVM.put(Vlan.UNTAGGED, nicPos); } else { @@ -2623,6 +2631,8 @@ ServerResource { vms = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName .getBytes())); PowerState s = convertToState(vms.getInfo().state); +// vms = conn.domainLookupByName(vmName); +// State s = convertToState(vms.getInfo().state); return s; } catch (final LibvirtException e) { s_logger.warn("Can't get vm state " + vmName + e.getMessage() @@ -2713,8 +2723,7 @@ ServerResource { try { conn = LibvirtConnection.getConnectionByVmName(cmd.getVmName()); ifaces = getInterfaces(conn, vmName); - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); dconn = new Connect("qemu+tcp://" + cmd.getDestinationIp() + "/system"); /* @@ -2729,6 +2738,9 @@ ServerResource { } finally { try { if (dm != null) { + if (dm.isPersistent() == 1) { + dm.undefine(); + } dm.free(); } if (dconn != null) { @@ -3160,8 +3172,7 @@ ServerResource { protected LibvirtVMDef createVMFromSpec(VirtualMachineTO vmTO) { LibvirtVMDef vm = new LibvirtVMDef(); vm.setDomainName(vmTO.getName()); - vm.setDomUUID(UUID.nameUUIDFromBytes(vmTO.getName().getBytes()) - .toString()); + vm.setDomUUID(vmTO.getUuid()); vm.setDomDescription(vmTO.getOs()); GuestDef guest = new GuestDef(); @@ -3186,8 +3197,8 @@ ServerResource { if (vmTO.getMinRam() != vmTO.getMaxRam()){ grd.setMemBalloning(true); - grd.setCurrentMem((long)vmTO.getMinRam()/1024); - grd.setMemorySize((long)vmTO.getMaxRam()/1024); + grd.setCurrentMem(vmTO.getMinRam()/1024); + grd.setMemorySize(vmTO.getMaxRam()/1024); } else{ grd.setMemorySize(vmTO.getMaxRam() / 1024); @@ -3585,8 +3596,7 @@ ServerResource { KVMStoragePool attachingPool = attachingDisk.getPool(); try { if (!attach) { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); String xml = dm.getXMLDesc(0); parser.parseDomainXML(xml); @@ -3635,9 +3645,7 @@ ServerResource { InternalErrorException { Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes((vmName - .getBytes()))); - + dm = conn.domainLookupByName(vmName); if (attach) { s_logger.debug("Attaching device: " + xml); dm.attachDevice(xml); @@ -3877,8 +3885,7 @@ ServerResource { for (; i < 5; i++) { try { Connect conn = LibvirtConnection.getConnectionByVmName(vm); - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vm - .getBytes())); + dm = conn.domainLookupByName(vm); DomainInfo.DomainState vps = dm.getInfo().state; if (vps != null && vps != DomainInfo.DomainState.VIR_DOMAIN_SHUTOFF @@ -3950,19 +3957,23 @@ ServerResource { final HashMap vmStates = new HashMap(); Connect conn = null; + if (_hypervisorType == HypervisorType.LXC) { try { conn = LibvirtConnection.getConnectionByType(HypervisorType.LXC.toString()); vmStates.putAll(getAllVms(conn)); } catch (LibvirtException e) { s_logger.debug("Failed to get connection: " + e.getMessage()); } + } + if (_hypervisorType == HypervisorType.KVM) { try { conn = LibvirtConnection.getConnectionByType(HypervisorType.KVM.toString()); vmStates.putAll(getAllVms(conn)); } catch (LibvirtException e) { s_logger.debug("Failed to get connection: " + e.getMessage()); } + } return vmStates; } @@ -4015,8 +4026,7 @@ ServerResource { for (int i = 0; i < vms.length; i++) { try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vms[i] - .getBytes())); + dm = conn.domainLookupByName(vms[i]); DomainInfo.DomainState ps = dm.getInfo().state; final PowerState state = convertToState(ps); @@ -4121,8 +4131,7 @@ ServerResource { Domain dm = null; String msg = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); String vmDef = dm.getXMLDesc(0); s_logger.debug(vmDef); msg = stopVM(conn, vmName); @@ -4164,8 +4173,7 @@ ServerResource { /* Retry 3 times, to make sure we can get the vm's status */ for (int i = 0; i < 3; i++) { try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); state = dm.getInfo().state; break; } catch (LibvirtException e) { @@ -4201,8 +4209,7 @@ ServerResource { protected String stopVM(Connect conn, String vmName, boolean force) { Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); int persist = dm.isPersistent(); if (force) { if (dm.isActive() == 1) { @@ -4289,8 +4296,7 @@ ServerResource { LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); String xmlDesc = dm.getXMLDesc(0); parser.parseDomainXML(xmlDesc); return parser.getVncPort(); @@ -4335,8 +4341,7 @@ ServerResource { LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); String xmlDesc = dm.getXMLDesc(0); parser.parseDomainXML(xmlDesc); return parser.getDescription(); @@ -4434,15 +4439,14 @@ ServerResource { private Domain getDomain(Connect conn, String vmName) throws LibvirtException { return conn - .domainLookupByUUID(UUID.nameUUIDFromBytes(vmName.getBytes())); + .domainLookupByName(vmName); } protected List getInterfaces(Connect conn, String vmName) { LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); parser.parseDomainXML(dm.getXMLDesc(0)); return parser.getInterfaces(); @@ -4464,8 +4468,7 @@ ServerResource { LibvirtDomainXMLParser parser = new LibvirtDomainXMLParser(); Domain dm = null; try { - dm = conn.domainLookupByUUID(UUID.nameUUIDFromBytes(vmName - .getBytes())); + dm = conn.domainLookupByName(vmName); parser.parseDomainXML(dm.getXMLDesc(0)); return parser.getDisks(); diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java index e7e4bbf2c30..89e22c8d05e 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java @@ -17,6 +17,9 @@ package com.cloud.hypervisor.kvm.storage; import java.io.File; +import java.io.FileInputStream; +import java.io.BufferedInputStream; +import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; @@ -37,6 +40,12 @@ import org.libvirt.StoragePool; import org.libvirt.StoragePoolInfo; import org.libvirt.StorageVol; import org.libvirt.StoragePoolInfo.StoragePoolState; +import com.ceph.rados.Rados; +import com.ceph.rados.RadosException; +import com.ceph.rados.IoCTX; +import com.ceph.rbd.Rbd; +import com.ceph.rbd.RbdImage; +import com.ceph.rbd.RbdException; import com.cloud.agent.api.ManageSnapshotCommand; import com.cloud.hypervisor.kvm.resource.LibvirtConnection; @@ -63,6 +72,8 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { private String _mountPoint = "/mnt"; private String _manageSnapshotPath; + private String rbdTemplateSnapName = "cloudstack-base-snap"; + public LibvirtStorageAdaptor(StorageLayer storage) { _storageLayer = storage; _manageSnapshotPath = Script.findScript("scripts/storage/qcow2/", @@ -638,6 +649,15 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { } } + /** + * This function copies a physical disk from Secondary Storage to Primary Storage + * or from Primary to Primary Storage + * + * The first time a template is deployed in Primary Storage it will be copied from + * Secondary to Primary. + * + * If it has been created on Primary Storage, it will be copied on the Primary Storage + */ @Override public KVMPhysicalDisk createDiskFromTemplate(KVMPhysicalDisk template, String name, PhysicalDiskFormat format, long size, KVMStoragePool destPool) { @@ -690,21 +710,118 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { if (srcPool.getType() != StoragePoolType.RBD) { srcFile = new QemuImgFile(template.getPath(), template.getFormat()); + qemu.convert(srcFile, destFile); } else { - template.setFormat(PhysicalDiskFormat.RAW); - srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(srcPool.getSourceHost(), - srcPool.getSourcePort(), - srcPool.getAuthUserName(), - srcPool.getAuthSecret(), - template.getPath())); - srcFile.setFormat(template.getFormat()); + + /** + * We have to find out if the source file is in the same RBD pool and has + * RBD format 2 before we can do a layering/clone operation on the RBD image + * + * This will be the case when the template is already on Primary Storage and + * we want to copy it + */ + + /* Feature 1<<0 means layering in RBD format 2 */ + int rbdFeatures = (1<<0); + /* Order 0 means 4MB blocks (the default) */ + int rbdOrder = 0; + + try { + if ((srcPool.getSourceHost().equals(destPool.getSourceHost())) && (srcPool.getSourceDir().equals(destPool.getSourceDir()))) { + /* We are on the same Ceph cluster, but we require RBD format 2 on the source image */ + s_logger.debug("Trying to perform a RBD clone (layering) since we are operating in the same storage pool"); + + Rados r = new Rados(srcPool.getAuthUserName()); + r.confSet("mon_host", srcPool.getSourceHost() + ":" + srcPool.getSourcePort()); + r.confSet("key", srcPool.getAuthSecret()); + r.connect(); + s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host")); + + IoCTX io = r.ioCtxCreate(srcPool.getSourceDir()); + Rbd rbd = new Rbd(io); + RbdImage srcImage = rbd.open(template.getName()); + + if (srcImage.isOldFormat()) { + /* The source image is RBD format 1, we have to do a regular copy */ + s_logger.debug("The source image " + srcPool.getSourceDir() + "/" + template.getName() + + " is RBD format 1. We have to perform a regular copy (" + template.getVirtualSize() + " bytes)"); + + rbd.create(disk.getName(), template.getVirtualSize(), rbdFeatures, rbdOrder); + RbdImage destImage = rbd.open(disk.getName()); + + s_logger.debug("Starting to copy " + srcImage.getName() + " to " + destImage.getName() + " in Ceph pool " + srcPool.getSourceDir()); + rbd.copy(srcImage, destImage); + + s_logger.debug("Finished copying " + srcImage.getName() + " to " + destImage.getName() + " in Ceph pool " + srcPool.getSourceDir()); + rbd.close(destImage); + } else { + s_logger.debug("The source image " + srcPool.getSourceDir() + "/" + template.getName() + + " is RBD format 2. We will perform a RBD clone using snapshot " + + this.rbdTemplateSnapName); + /* The source image is format 2, we can do a RBD snapshot+clone (layering) */ + rbd.clone(template.getName(), this.rbdTemplateSnapName, io, disk.getName(), rbdFeatures, rbdOrder); + s_logger.debug("Succesfully cloned " + template.getName() + "@" + this.rbdTemplateSnapName + " to " + disk.getName()); + } + + rbd.close(srcImage); + r.ioCtxDestroy(io); + } else { + /* The source pool or host is not the same Ceph cluster, we do a simple copy with Qemu-Img */ + s_logger.debug("Both the source and destination are RBD, but not the same Ceph cluster. Performing a copy"); + + Rados rSrc = new Rados(srcPool.getAuthUserName()); + rSrc.confSet("mon_host", srcPool.getSourceHost() + ":" + srcPool.getSourcePort()); + rSrc.confSet("key", srcPool.getAuthSecret()); + rSrc.connect(); + s_logger.debug("Succesfully connected to source Ceph cluster at " + rSrc.confGet("mon_host")); + + Rados rDest = new Rados(destPool.getAuthUserName()); + rDest.confSet("mon_host", destPool.getSourceHost() + ":" + destPool.getSourcePort()); + rDest.confSet("key", destPool.getAuthSecret()); + rDest.connect(); + s_logger.debug("Succesfully connected to source Ceph cluster at " + rDest.confGet("mon_host")); + + IoCTX sIO = rSrc.ioCtxCreate(srcPool.getSourceDir()); + Rbd sRbd = new Rbd(sIO); + + IoCTX dIO = rDest.ioCtxCreate(destPool.getSourceDir()); + Rbd dRbd = new Rbd(dIO); + + s_logger.debug("Creating " + disk.getName() + " on the destination cluster " + rDest.confGet("mon_host") + + " in pool " + destPool.getSourceDir()); + dRbd.create(disk.getName(), template.getVirtualSize(), rbdFeatures, rbdOrder); + + RbdImage srcImage = sRbd.open(template.getName()); + RbdImage destImage = dRbd.open(disk.getName()); + + s_logger.debug("Copying " + template.getName() + " from Ceph cluster " + rSrc.confGet("mon_host") + " to " + disk.getName() + + " on cluster " + rDest.confGet("mon_host")); + sRbd.copy(srcImage, destImage); + + sRbd.close(srcImage); + dRbd.close(destImage); + + rSrc.ioCtxDestroy(sIO); + rDest.ioCtxDestroy(dIO); + } + } catch (RadosException e) { + s_logger.error("Failed to perform a RADOS action on the Ceph cluster, the error was: " + e.getMessage()); + disk = null; + } catch (RbdException e) { + s_logger.error("Failed to perform a RBD action on the Ceph cluster, the error was: " + e.getMessage()); + disk = null; + } } - qemu.convert(srcFile, destFile); } } catch (QemuImgException e) { s_logger.error("Failed to create " + disk.getPath() + " due to a failed executing of qemu-img: " + e.getMessage()); } + + if (disk == null) { + throw new CloudRuntimeException("Failed to create " + disk.getPath() + " from template " + template.getName()); + } + return disk; } @@ -733,17 +850,26 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { } } + /** + * This copies a volume from Primary Storage to Secondary Storage + * + * In theory it could also do it the other way around, but the current implementation + * in ManagementServerImpl shows that the destPool is always a Secondary Storage Pool + */ @Override public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name, KVMStoragePool destPool) { - /* + /** With RBD you can't run qemu-img convert with an existing RBD image as destination qemu-img will exit with the error that the destination already exists. So for RBD we don't create the image, but let qemu-img do that for us. We then create a KVMPhysicalDisk object that we can return - */ + + It is however very unlikely that the destPool will be RBD, since it isn't supported + for Secondary Storage + */ KVMPhysicalDisk newDisk; if (destPool.getType() != StoragePoolType.RBD) { @@ -785,21 +911,103 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { Script.runSimpleBashScript("cp -f " + sourcePath + " " + destPath); } else { destFile = new QemuImgFile(destPath, destFormat); + try { + qemu.convert(srcFile, destFile); + } catch (QemuImgException e) { + s_logger.error("Failed to convert " + srcFile.getFileName() + " to " + + destFile.getFileName() + " the error was: " + e.getMessage()); + newDisk = null; + } } } catch (QemuImgException e) { s_logger.error("Failed to fetch the information of file " + srcFile.getFileName() + " the error was: " + e.getMessage()); + newDisk = null; } } } else if ((srcPool.getType() != StoragePoolType.RBD) && (destPool.getType() == StoragePoolType.RBD)) { - srcFile = new QemuImgFile(sourcePath, sourceFormat); - destFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(), - destPool.getSourcePort(), - destPool.getAuthUserName(), - destPool.getAuthSecret(), - destPath)); - destFile.setFormat(destFormat); + /** + * Qemu doesn't support writing to RBD format 2 directly, so we have to write to a temporary RAW file first + * which we then convert to RBD format 2. + * + * A HUGE performance gain can be achieved here if QCOW2 -> RBD format 2 can be done in one step + */ + s_logger.debug("The source image is not RBD, but the destination is. We will convert into RBD format 2"); + String tmpFile = "/tmp/" + name; + int rbdFeatures = (1<<0); + int rbdOrder = 0; + + try { + srcFile = new QemuImgFile(sourcePath, sourceFormat); + destFile = new QemuImgFile(tmpFile); + s_logger.debug("Converting " + srcFile.getFileName() + " to " + tmpFile + " as a temporary file for RBD conversion"); + qemu.convert(srcFile, destFile); + + // We now convert the temporary file to a RBD image with format 2 + Rados r = new Rados(destPool.getAuthUserName()); + r.confSet("mon_host", destPool.getSourceHost() + ":" + destPool.getSourcePort()); + r.confSet("key", destPool.getAuthSecret()); + r.connect(); + s_logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host")); + + IoCTX io = r.ioCtxCreate(destPool.getSourceDir()); + Rbd rbd = new Rbd(io); + + s_logger.debug("Creating RBD image " + name + " in Ceph pool " + destPool.getSourceDir() + " with RBD format 2"); + rbd.create(name, disk.getVirtualSize(), rbdFeatures, rbdOrder); + + RbdImage image = rbd.open(name); + + // We now read the temporary file and write it to the RBD image + File fh = new File(tmpFile); + BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fh)); + + int chunkSize = 4194304; + long offset = 0; + s_logger.debug("Reading temporary file " + tmpFile + " (" + fh.length() + " bytes) into RBD image " + name + " in chunks of " + chunkSize + " bytes"); + while(true) { + byte[] buf = new byte[chunkSize]; + + int bytes = bis.read(buf); + if (bytes <= 0) { + break; + } + image.write(buf, offset, bytes); + offset += bytes; + } + s_logger.debug("Completed writing " + tmpFile + " to RBD image " + name + ". Bytes written: " + offset); + bis.close(); + s_logger.debug("Removing temporary file " + tmpFile); + fh.delete(); + + /* Snapshot the image and protect that snapshot so we can clone (layer) from it */ + s_logger.debug("Creating RBD snapshot " + this.rbdTemplateSnapName + " on image " + name); + image.snapCreate(this.rbdTemplateSnapName); + s_logger.debug("Protecting RBD snapshot " + this.rbdTemplateSnapName + " on image " + name); + image.snapProtect(this.rbdTemplateSnapName); + + rbd.close(image); + r.ioCtxDestroy(io); + } catch (QemuImgException e) { + s_logger.error("Failed to do a temp convert from " + srcFile.getFileName() + " to " + + destFile.getFileName() + " the error was: " + e.getMessage()); + newDisk = null; + } catch (RadosException e) { + s_logger.error("A Ceph RADOS operation failed (" + e.getReturnValue() + "). The error was: " + e.getMessage()); + newDisk = null; + } catch (RbdException e) { + s_logger.error("A Ceph RBD operation failed (" + e.getReturnValue() + "). The error was: " + e.getMessage()); + newDisk = null; + } catch (IOException e) { + s_logger.error("Failed reading the temporary file during the conversion to RBD: " + e.getMessage()); + newDisk = null; + } + } else { + /** + We let Qemu-Img do the work here. Although we could work with librbd and have that do the cloning + it doesn't benefit us. It's better to keep the current code in place which works + */ srcFile = new QemuImgFile(KVMPhysicalDisk.RBDStringBuilder(srcPool.getSourceHost(), srcPool.getSourcePort(), srcPool.getAuthUserName(), @@ -812,17 +1020,19 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { destPool.getAuthSecret(), destPath)); destFile.setFormat(destFormat); - } - if (srcFile != null && destFile != null) { try { qemu.convert(srcFile, destFile); } catch (QemuImgException e) { s_logger.error("Failed to convert " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage()); + newDisk = null; } } + if (newDisk == null) { + throw new CloudRuntimeException("Failed to copy " + disk.getPath() + " to " + name); + } return newDisk; } diff --git a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java index 39e36d65c65..0bafd073f68 100644 --- a/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java +++ b/plugins/hypervisors/kvm/test/com/cloud/hypervisor/kvm/resource/LibvirtComputingResourceTest.java @@ -60,6 +60,7 @@ public class LibvirtComputingResourceTest { LibvirtComputingResource lcr = new LibvirtComputingResource(); VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, speed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); to.setVncAddr(vncAddr); + to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); LibvirtVMDef vm = lcr.createVMFromSpec(to); vm.setHvsType(_hyperVisorType); @@ -135,6 +136,7 @@ public class LibvirtComputingResourceTest { LibvirtComputingResource lcr = new LibvirtComputingResource(); VirtualMachineTO to = new VirtualMachineTO(id, name, VirtualMachine.Type.User, cpus, minSpeed, maxSpeed, minRam, maxRam, BootloaderType.HVM, os, false, false, vncPassword); to.setVncAddr(vncAddr); + to.setUuid("b0f0a72d-7efb-3cad-a8ff-70ebf30b3af9"); LibvirtVMDef vm = lcr.createVMFromSpec(to); vm.setHvsType(_hyperVisorType); @@ -181,4 +183,4 @@ public class LibvirtComputingResourceTest { assertEquals(vmStr, vm.toString()); } -} \ No newline at end of file +} diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java index 9f1351e96f3..faadbacb0ef 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/manager/VmwareStorageManagerImpl.java @@ -491,6 +491,7 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { hyperHost, volumeId, new DatastoreMO(context, morDatastore), secondaryStorageURL, volumePath); + deleteVolumeDirOnSecondaryStorage(volumeId, secondaryStorageURL); } return new CopyVolumeAnswer(cmd, true, null, result.first(), result.second()); } catch (Throwable e) { @@ -1438,4 +1439,22 @@ public class VmwareStorageManagerImpl implements VmwareStorageManager { workingVM = hyperHost.findVmOnHyperHost(uniqueName); return workingVM; } + + + + private String deleteVolumeDirOnSecondaryStorage(long volumeId, String secStorageUrl) throws Exception { + String secondaryMountPoint = _mountService.getMountPoint(secStorageUrl); + String volumeMountRoot = secondaryMountPoint + "/" + getVolumeRelativeDirInSecStroage(volumeId); + + return deleteDir(volumeMountRoot); + } + + private String deleteDir(String dir) { + synchronized(dir.intern()) { + Script command = new Script(false, "rm", _timeout, s_logger); + command.add("-rf"); + command.add(dir); + return command.execute(); + } + } } diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 05613a81866..c7636407c75 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -1528,7 +1528,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa snatArgs += "eth" + ethDeviceNum; Pair result_gateway = SshHelper.sshExecute(routerIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, - "/opt/cloud/bin/vpc_privateGateway.sh " + args); + "/opt/cloud/bin/vpc_privateGateway.sh " + snatArgs); if (!result_gateway.first()) { throw new InternalErrorException("Unable to configure source NAT for public IP address."); diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpOssResource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpOssResource.java index 357b4333678..870049c8111 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpOssResource.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XcpOssResource.java @@ -17,17 +17,6 @@ package com.cloud.hypervisor.xen.resource; -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.ejb.Local; - -import org.apache.log4j.Logger; -import org.apache.xmlrpc.XmlRpcException; - import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; import com.cloud.agent.api.NetworkUsageAnswer; @@ -46,14 +35,24 @@ import com.cloud.utils.script.Script; import com.cloud.vm.VirtualMachine; import com.xensource.xenapi.Connection; import com.xensource.xenapi.Types; +import com.xensource.xenapi.Types.XenAPIException; import com.xensource.xenapi.VBD; import com.xensource.xenapi.VDI; import com.xensource.xenapi.VM; -import com.xensource.xenapi.Types.XenAPIException; +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import javax.ejb.Local; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; @Local(value=ServerResource.class) public class XcpOssResource extends CitrixResourceBase { - private final static Logger s_logger = Logger.getLogger(XcpServerResource.class); + private final static Logger s_logger = Logger.getLogger(XcpOssResource.class); + private static final long mem_32m = 33554432L; + @Override protected List getPatchFiles() { List files = new ArrayList(); @@ -167,4 +166,9 @@ public class XcpOssResource extends CitrixResourceBase { } return answer; } + + @Override + protected void setMemory(Connection conn, VM vm, long minMemsize, long maxMemsize) throws XmlRpcException, XenAPIException { + vm.setMemoryLimits(conn, mem_32m, maxMemsize, minMemsize, maxMemsize); + } } diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java index 54aeef5a022..8e378093f3f 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer56FP1Resource.java @@ -137,7 +137,7 @@ public class XenServer56FP1Resource extends XenServer56Resource { vmr.actionsAfterCrash = Types.OnCrashBehaviour.DESTROY; vmr.actionsAfterShutdown = Types.OnNormalExit.DESTROY; - if (isDmcEnabled(conn, host)) { + if (isDmcEnabled(conn, host) && vmSpec.isEnableDynamicallyScaleVm()) { //scaling is allowed vmr.memoryStaticMin = mem_128m; //128MB //TODO: Remove hardcoded 8GB and assign proportionate to ServiceOffering and mem overcommit ratio diff --git a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java index 4d21ad2aeb8..799e4493652 100644 --- a/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java +++ b/plugins/network-elements/cisco-vnmc/src/com/cloud/network/element/CiscoVnmcElement.java @@ -98,6 +98,8 @@ import com.cloud.network.cisco.NetworkAsa1000vMapVO; import com.cloud.network.dao.CiscoAsa1000vDao; import com.cloud.network.dao.CiscoNexusVSMDeviceDao; import com.cloud.network.dao.CiscoVnmcDao; +import com.cloud.network.dao.IPAddressDao; +import com.cloud.network.dao.IPAddressVO; import com.cloud.network.dao.NetworkAsa1000vMapDao; import com.cloud.network.dao.NetworkDao; import com.cloud.network.dao.PhysicalNetworkDao; @@ -149,6 +151,8 @@ public class CiscoVnmcElement extends AdapterBase implements SourceNatServicePro @Inject PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao; @Inject + IPAddressDao _ipAddressDao; + @Inject HostDetailsDao _hostDetailsDao; @Inject HostDao _hostDao; @@ -342,8 +346,18 @@ public class CiscoVnmcElement extends AdapterBase implements SourceNatServicePro } // due to VNMC limitation of not allowing source NAT ip as the outside ip of firewall, - // an additional public ip needs to acquired for assigning as firewall outside ip + // an additional public ip needs to acquired for assigning as firewall outside ip. + // In case there are already additional ip addresses available (network restart) use one + // of them such that it is not the source NAT ip IpAddress outsideIp = null; + List publicIps = _ipAddressDao.listByAssociatedNetwork(network.getId(), null); + for (IPAddressVO ip : publicIps) { + if (!ip.isSourceNat()) { + outsideIp = ip; + break; + } + } + if (outsideIp == null) { // none available, acquire one try { Account caller = UserContext.current().getCaller(); long callerUserId = UserContext.current().getCallerUserId(); @@ -359,6 +373,7 @@ public class CiscoVnmcElement extends AdapterBase implements SourceNatServicePro s_logger.error("Unable to assign allocated additional public Ip " + outsideIp.getAddress().addr() + " to network with vlan " + vlanId + ". Exception details " + e); return false; } + } // create logical edge firewall in VNMC String gatewayNetmask = NetUtils.getCidrNetmask(network.getCidr()); 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 d4b19a31b81..85d6de6817b 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 @@ -242,6 +242,7 @@ PortForwardingServiceProvider, RemoteAccessVPNServiceProvider, IpDeployer, Junip // Set capabilities for Firewall service Map firewallCapabilities = new HashMap(); firewallCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp"); + firewallCapabilities.put(Capability.SupportedEgressProtocols, "tcp,udp,icmp,all"); firewallCapabilities.put(Capability.MultipleIps, "true"); firewallCapabilities.put(Capability.TrafficStatistics, "per public ip"); firewallCapabilities.put(Capability.SupportedTrafficDirection, "ingress, egress"); 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 a0068c3784c..fd065d58f87 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 @@ -750,7 +750,7 @@ public class JuniperSrxResource implements ServerResource { s_logger.debug(msg); } - private void shutdownGuestNetwork(GuestNetworkType type, long accountId, Long publicVlanTag, String sourceNatIpAddress, long privateVlanTag, String privateGateway, String privateSubnet, long privateCidrSize) throws ExecutionException { + private void shutdownGuestNetwork(GuestNetworkType type, long accountId, Long publicVlanTag, String sourceNatIpAddress, long privateVlanTag, String privateGateway, String privateSubnet, long privateCidrSize) throws ExecutionException { // Remove static and destination NAT rules for the guest network removeStaticAndDestNatRulesInPrivateVlan(privateVlanTag, privateGateway, privateCidrSize); @@ -766,10 +766,10 @@ public class JuniperSrxResource implements ServerResource { manageSourceNatPool(SrxCommand.DELETE, sourceNatIpAddress); manageProxyArp(SrxCommand.DELETE, publicVlanTag, sourceNatIpAddress); manageUsageFilter(SrxCommand.DELETE, _usageFilterIPOutput, privateSubnet, null, genIpFilterTermName(sourceNatIpAddress)); - manageUsageFilter(SrxCommand.DELETE, _usageFilterIPInput, sourceNatIpAddress, null, genIpFilterTermName(sourceNatIpAddress)); + manageUsageFilter(SrxCommand.DELETE, _usageFilterIPInput, sourceNatIpAddress, null, genIpFilterTermName(sourceNatIpAddress)); } else if (type.equals(GuestNetworkType.INTERFACE_NAT)) { manageUsageFilter(SrxCommand.DELETE, _usageFilterVlanOutput, null, privateVlanTag, null); - manageUsageFilter(SrxCommand.DELETE, _usageFilterVlanInput, null, privateVlanTag, null); + manageUsageFilter(SrxCommand.DELETE, _usageFilterVlanInput, null, privateVlanTag, null); } String msg = "Shut down guest network with type " + type +". Guest VLAN tag: " + privateVlanTag + ", guest gateway: " + privateGateway; @@ -841,21 +841,24 @@ public class JuniperSrxResource implements ServerResource { commitConfiguration(); } else { for (FirewallRuleTO rule : rules) { - int startPort = 0, endPort = 0; + int startPort = NetUtils.PORT_RANGE_MIN, endPort = NetUtils.PORT_RANGE_MAX; 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(); + + 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()) { + manageProxyArp(SrxCommand.ADD, getVlanTag(rule.getSrcVlanTag()), rule.getSrcIp()); + manageFirewallFilter(SrxCommand.ADD, term, _publicZoneInputFilterName); + } else { + manageFirewallFilter(SrxCommand.DELETE, term, _publicZoneInputFilterName); + manageProxyArp(SrxCommand.DELETE, getVlanTag(rule.getSrcVlanTag()), rule.getSrcIp()); + } } + commitConfiguration(); } return new Answer(cmd); @@ -925,7 +928,6 @@ public class JuniperSrxResource implements ServerResource { } private void addStaticNatRule(Long publicVlanTag, String publicIp, String privateIp, List rules) throws ExecutionException { - manageProxyArp(SrxCommand.ADD, publicVlanTag, publicIp); manageStaticNatRule(SrxCommand.ADD, publicIp, privateIp); manageAddressBookEntry(SrxCommand.ADD, _privateZone, privateIp, null); @@ -937,7 +939,6 @@ public class JuniperSrxResource implements ServerResource { private void removeStaticNatRule(Long publicVlanTag, String publicIp, String privateIp) throws ExecutionException { manageStaticNatRule(SrxCommand.DELETE, publicIp, privateIp); - manageProxyArp(SrxCommand.DELETE, publicVlanTag, publicIp); // Remove any existing security policy and clean up applications removeSecurityPolicyAndApplications(SecurityPolicyType.STATIC_NAT, privateIp); @@ -1196,8 +1197,7 @@ public class JuniperSrxResource implements ServerResource { } private void addDestinationNatRule(Protocol protocol, Long publicVlanTag, String publicIp, String privateIp, int srcPortStart, int srcPortEnd, int destPortStart, int destPortEnd) throws ExecutionException { - manageProxyArp(SrxCommand.ADD, publicVlanTag, publicIp); - + int offset = 0; for (int srcPort = srcPortStart; srcPort <= srcPortEnd; srcPort++) { int destPort = destPortStart + offset; @@ -1220,7 +1220,6 @@ public class JuniperSrxResource implements ServerResource { private void removeDestinationNatRule(Long publicVlanTag, String publicIp, String privateIp, int srcPort, int destPort) throws ExecutionException { manageDestinationNatRule(SrxCommand.DELETE, publicIp, privateIp, srcPort, destPort); manageDestinationNatPool(SrxCommand.DELETE, privateIp, destPort); - manageProxyArp(SrxCommand.DELETE, publicVlanTag, publicIp); removeSecurityPolicyAndApplications(SecurityPolicyType.DESTINATION_NAT, privateIp); diff --git a/pom.xml b/pom.xml index d7e80d64548..67d9576715c 100644 --- a/pom.xml +++ b/pom.xml @@ -83,6 +83,7 @@ 0.10 build/replace.properties 0.4.9 + 0.1.1 target 1.0.10 diff --git a/python/lib/cloudutils/globalEnv.py b/python/lib/cloudutils/globalEnv.py index 94d981f4dab..867aa17670d 100644 --- a/python/lib/cloudutils/globalEnv.py +++ b/python/lib/cloudutils/globalEnv.py @@ -40,3 +40,5 @@ class globalEnv: self.privateNet = "cloudbr0" #distribution self.distribution = None + # bridgeType + self.bridgeType = "native" diff --git a/python/lib/cloudutils/networkConfig.py b/python/lib/cloudutils/networkConfig.py index b6b729a4fec..9e456e970be 100644 --- a/python/lib/cloudutils/networkConfig.py +++ b/python/lib/cloudutils/networkConfig.py @@ -19,6 +19,7 @@ from cloudException import CloudRuntimeException, CloudInternalException import logging import os import re +import subprocess class networkConfig: class devInfo: @@ -85,15 +86,22 @@ class networkConfig: @staticmethod def isNetworkDev(devName): - return os.path.exists("/sys/class/net/%s"%devName) + return os.path.exists("/sys/class/net/%s" % devName) @staticmethod def isBridgePort(devName): - return os.path.exists("/sys/class/net/%s/brport"%devName) + return os.path.exists("/sys/class/net/%s/brport" % devName) @staticmethod def isBridge(devName): - return os.path.exists("/sys/class/net/%s/bridge"%devName) + return os.path.exists("/sys/class/net/%s/bridge" % devName) + + @staticmethod + def isOvsBridge(devName): + try: + return 0==subprocess.check_call(("ovs-vsctl", "br-exists", devName)) + except subprocess.CalledProcessError: + return False @staticmethod def getBridge(devName): diff --git a/python/lib/cloudutils/serviceConfig.py b/python/lib/cloudutils/serviceConfig.py index 1e32d0f3b0f..d129e00c45b 100755 --- a/python/lib/cloudutils/serviceConfig.py +++ b/python/lib/cloudutils/serviceConfig.py @@ -94,8 +94,10 @@ class networkConfigBase: if not self.netcfg.isNetworkDev(br): logging.debug("%s is not a network device, is it down?"%br) return False - if not self.netcfg.isBridge(br): - raise CloudInternalException("%s is not a bridge"%br) + if self.syscfg.env.bridgeType == "openvswitch" and not self.netcfg.isOvsBridge(br): + raise CloudInternalException("%s is not an openvswitch bridge" % br) + if self.syscfg.env.bridgeType == "native" and not self.netcfg.isBridge(br): + raise CloudInternalException("%s is not a bridge" % br) preCfged = True return preCfged @@ -153,11 +155,28 @@ class networkConfigUbuntu(serviceCfgBase, networkConfigBase): match = re.match("^ *iface %s.*"%dev.name, line) if match is not None: dev.method = self.getNetworkMethod(match.group(0)) - bridgeCfg = "\niface %s inet manual\n \ - auto %s\n \ - iface %s inet %s\n \ - bridge_ports %s\n"%(dev.name, br, br, dev.method, dev.name) cfo = configFileOps(self.netCfgFile, self) + if self.syscfg.env.bridgeType == "openvswitch": + bridgeCfg = "\n".join(("", + "iface {device} inet manual", + " ovs_type OVSPort", + " ovs_bridge {bridge}", + "", + "auto {bridge}", + "allow-ovs {bridge}", + "iface {bridge} inet {device_method}", + " ovs_type OVSBridge", + " ovs_ports {device}", + "")).format(bridge=br, device=dev.name, device_method=dev.method) + cfo.replace_line("^ *auto %s.*" % dev.name, + "allow-{bridge} {device}".format(bridge=br, device=dev.name)) + elif self.syscfg.env.bridgeType == "native": + bridgeCfg = "\niface %s inet manual\n \ + auto %s\n \ + iface %s inet %s\n \ + bridge_ports %s\n"%(dev.name, br, br, dev.method, dev.name) + else: + raise CloudInternalException("Unknown network.bridge.type %s" % self.syscfg.env.bridgeType) cfo.replace_line("^ *iface %s.*"%dev.name, bridgeCfg) def addDev(self, br, dev): @@ -193,8 +212,9 @@ class networkConfigUbuntu(serviceCfgBase, networkConfigBase): self.syscfg.svo.stopService("network-manager") self.syscfg.svo.disableService("network-manager") - if not bash("ifup %s"%self.brName).isSuccess(): - raise CloudInternalException("Can't start network:%s"%self.brName, bash.getErrMsg(self)) + ifup_op = bash("ifup %s"%self.brName) + if not ifup_op.isSuccess(): + raise CloudInternalException("Can't start network:%s %s" % (self.brName, ifup_op.getErrMsg())) self.syscfg.env.nics.append(self.brName) self.syscfg.env.nics.append(self.brName) @@ -222,8 +242,8 @@ class networkConfigRedhat(serviceCfgBase, networkConfigBase): networkConfigBase.__init__(self, syscfg) def writeToCfgFile(self, brName, dev): - self.devCfgFile = "/etc/sysconfig/network-scripts/ifcfg-%s"%dev.name - self.brCfgFile = "/etc/sysconfig/network-scripts/ifcfg-%s"%brName + self.devCfgFile = "/etc/sysconfig/network-scripts/ifcfg-%s" % dev.name + self.brCfgFile = "/etc/sysconfig/network-scripts/ifcfg-%s" % brName isDevExist = os.path.exists(self.devCfgFile) isBrExist = os.path.exists(self.brCfgFile) @@ -241,7 +261,7 @@ class networkConfigRedhat(serviceCfgBase, networkConfigBase): def addBridge(self, brName, dev): - bash("ifdown %s"%dev.name) + bash("ifdown %s" % dev.name) if not os.path.exists(self.brCfgFile): shutil.copy(self.devCfgFile, self.brCfgFile) @@ -250,14 +270,34 @@ class networkConfigRedhat(serviceCfgBase, networkConfigBase): cfo = configFileOps(self.devCfgFile, self) cfo.addEntry("NM_CONTROLLED", "no") cfo.addEntry("ONBOOT", "yes") - cfo.addEntry("BRIDGE", brName) + if self.syscfg.env.bridgeType == "openvswitch": + if cfo.getEntry("IPADDR"): + cfo.rmEntry("IPADDR", cfo.getEntry("IPADDR")) + cfo.addEntry("DEVICETYPE", "ovs") + cfo.addEntry("TYPE", "OVSPort") + cfo.addEntry("OVS_BRIDGE", brName) + elif self.syscfg.env.bridgeType == "native": + cfo.addEntry("BRIDGE", brName) + else: + raise CloudInternalException("Unknown network.bridge.type %s" % self.syscfg.env.bridgeType) cfo.save() cfo = configFileOps(self.brCfgFile, self) cfo.addEntry("NM_CONTROLLED", "no") cfo.addEntry("ONBOOT", "yes") cfo.addEntry("DEVICE", brName) - cfo.addEntry("TYPE", "Bridge") + if self.syscfg.env.bridgeType == "openvswitch": + if cfo.getEntry("HWADDR"): + cfo.rmEntry("HWADDR", cfo.getEntry("HWADDR")) + if cfo.getEntry("UUID"): + cfo.rmEntry("UUID", cfo.getEntry("UUID")) + cfo.addEntry("STP", "yes") + cfo.addEntry("DEVICETYPE", "ovs") + cfo.addEntry("TYPE", "OVSBridge") + elif self.syscfg.env.bridgeType == "native": + cfo.addEntry("TYPE", "Bridge") + else: + raise CloudInternalException("Unknown network.bridge.type %s" % self.syscfg.env.bridgeType) cfo.save() def config(self): diff --git a/scripts/storage/qcow2/modifyvlan.sh b/scripts/storage/qcow2/modifyvlan.sh deleted file mode 100755 index 5e26af0ba02..00000000000 --- a/scripts/storage/qcow2/modifyvlan.sh +++ /dev/null @@ -1,269 +0,0 @@ -#!/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. - - -# $Id: modifyvlan.sh 9132 2010-06-04 20:17:43Z manuel $ $HeadURL: svn://svn.lab.vmops.com/repos/vmdev/java/scripts/storage/qcow2/modifyvlan.sh $ -# modifyvlan.sh -- adds and deletes VLANs from a Routing Server -# set -x - -usage() { - printf "Usage: %s: -o -v -g \n" -} - -addVlan() { - local vlanId=$1 - - ifconfig bond1.$vlanId > /dev/null - - if [ $? -gt 0 ] - then - vconfig add bond1 $vlanId - - if [ $? -gt 0 ] - then - return 1 - fi - fi - - # Make ifcfg-bond1.$vlanId - rm /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - touch /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - echo "DEVICE=bond1.$vlanId" >> /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - echo "ONBOOT=yes" >> /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - echo "BOOTPROTO=none" >> /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - echo "VLAN=yes" >> /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - echo "BRIDGE=xenbr1.$vlanId" >> /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - - # Try to add xenbr1.$vlanId over bond1.$vlanId, if it does not already exist - - ifconfig xenbr1.$vlanId > /dev/null - - if [ $? -gt 0 ] - then - brctl addbr xenbr1.$vlanId - - if [ $? -gt 0 ] - then - return 1 - fi - - brctl addif xenbr1.$vlanId bond1.$vlanId - - if [ $? -gt 0 ] - then - return 1 - fi - - fi - - ifconfig xenbr1.$vlanId up - - if [ $? -gt 0 ] - then - return 1 - fi - - # Make ifcfg-xenbr1.$vlanId - rm /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - touch /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - echo "TYPE=bridge" >> /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - echo "DEVICE=xenbr1.$vlanId" >> /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - echo "ONBOOT=yes" >> /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - echo "BOOTPROTO=none" >> /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - - return 0 -} - -deleteVlan() { - local vlanId=$1 - - # Try to remove xenbr1.$vlanId - ifconfig xenbr1.$vlanId down - - if [ $? -gt 0 ] - then - return 1 - fi - - brctl delbr xenbr1.$vlanId - - if [ $? -gt 0 ] - then - return 1 - fi - - # Remove ifcfg-xenbr1.$vlanId - rm /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId - - # Try to remove bond1.$vlanId - - vconfig rem bond1.$vlanId - - if [ $? -gt 0 ] - then - return 1 - fi - - # Remove ifcfg-bond1.$vlanId - rm /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId - - return 0 - -} - -checkIfVlanExists() { - local vlanId=$1 - - if [ "$vlanId" == "untagged" ] - then - # This VLAN should always exist, since the bridge is xenbr1, which is created during vsetup - return 0 - fi - - ifconfig bond1.$vlanId > /dev/null - - if [ $? -gt 0 ] - then - return 1 - fi - - ifconfig xenbr1.$vlanId > /dev/null - - if [ $? -gt 0 ] - then - return 1 - fi - - if [ ! -f /etc/sysconfig/network-scripts/ifcfg-xenbr1.$vlanId ] - then - return 1 - fi - - if [ ! -f /etc/sysconfig/network-scripts/ifcfg-bond1.$vlanId ] - then - return 1 - fi - - return 0 -} - -arpingVlan() { - local vlanId=$1 - local vlanGateway=$2 - - # Change!!! - return 0 - - success=1 - for i in $(seq 1 3) - do - arping -I xenbr1.$vlanId $vlanGateway > /dev/null - - if [ $? -gt 0 ] - then - success=0 - break - fi - done - - return $success -} - -op= -vlanId= -vlanGateway= -option=$@ - -while getopts 'o:v:g:' OPTION -do - case $OPTION in - o) oflag=1 - op="$OPTARG" - ;; - v) vflag=1 - vlanId="$OPTARG" - ;; - g) gflag=1 - vlanGateway="$OPTARG" - ;; - ?) usage - exit 2 - ;; - esac -done - -# Check that all arguments were passed in -if [ "$oflag$vflag$gflag" != "111" ] -then - usage - exit 2 -fi - -if [ "$op" == "add" ] -then - # Check if the vlan already exists, and exit with success if it does - checkIfVlanExists $vlanId - - if [ $? -eq 0 ] - then - exit 0 - fi - - # Add the vlan - addVlan $vlanId - - # If the add fails then return failure - if [ $? -gt 0 ] - then - exit 1 - fi - - # Ping the vlan - arpingVlan $vlanId $vlanGateway - - # If the ping fails then delete the vlan and return failure. Else, return success. - if [ $? -gt 0 ] - then - deleteVlan $vlanId - exit 1 - else - exit 0 - fi -else - if [ "$op" == "delete" ] - then - # Delete the vlan - deleteVlan $vlanId - - # Always exit with success - exit 0 - fi -fi - - - - - - - - - - - - - diff --git a/scripts/vm/hypervisor/kvm/patchviasocket.pl b/scripts/vm/hypervisor/kvm/patchviasocket.pl old mode 100644 new mode 100755 diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 10e47d3e9a6..b83b343cb62 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -46,8 +46,6 @@ import org.apache.cloudstack.api.ApiConstants.VMDetails; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.ResponseGenerator; import org.apache.cloudstack.api.command.user.job.QueryAsyncJobResultCmd; -import org.apache.cloudstack.region.PortableIp; -import org.apache.cloudstack.region.PortableIpRange; import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.ApplicationLoadBalancerInstanceResponse; import org.apache.cloudstack.api.response.ApplicationLoadBalancerResponse; @@ -143,6 +141,8 @@ import org.apache.cloudstack.api.response.VpnUsersResponse; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.framework.jobs.AsyncJob; import org.apache.cloudstack.network.lb.ApplicationLoadBalancerRule; +import org.apache.cloudstack.region.PortableIp; +import org.apache.cloudstack.region.PortableIpRange; import org.apache.cloudstack.region.Region; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.usage.Usage; @@ -211,6 +211,7 @@ import com.cloud.network.Site2SiteVpnConnection; import com.cloud.network.Site2SiteVpnGateway; import com.cloud.network.VirtualRouterProvider; import com.cloud.network.VpnUser; +import com.cloud.network.VpnUserVO; import com.cloud.network.as.AutoScalePolicy; import com.cloud.network.as.AutoScaleVmGroup; import com.cloud.network.as.AutoScaleVmProfile; @@ -219,6 +220,7 @@ import com.cloud.network.as.Condition; import com.cloud.network.as.ConditionVO; import com.cloud.network.as.Counter; import com.cloud.network.dao.IPAddressVO; +import com.cloud.network.dao.LoadBalancerVO; import com.cloud.network.dao.NetworkVO; import com.cloud.network.dao.PhysicalNetworkVO; import com.cloud.network.router.VirtualRouter; @@ -228,6 +230,7 @@ import com.cloud.network.rules.HealthCheckPolicy; import com.cloud.network.rules.LoadBalancer; import com.cloud.network.rules.LoadBalancerContainer.Scheme; import com.cloud.network.rules.PortForwardingRule; +import com.cloud.network.rules.PortForwardingRuleVO; import com.cloud.network.rules.StaticNatRule; import com.cloud.network.rules.StickinessPolicy; import com.cloud.network.security.SecurityGroup; @@ -776,6 +779,9 @@ public class ApiResponseHelper implements ResponseGenerator { } lbResponse.setTags(tagResponses); + Network ntwk = ApiDBUtils.findNetworkById(loadBalancer.getNetworkId()); + lbResponse.setNetworkId(ntwk.getUuid()); + lbResponse.setObjectName("loadbalancer"); return lbResponse; } @@ -3546,11 +3552,12 @@ public class ApiResponseHelper implements ResponseGenerator { } else if(usageRecord.getUsageType() == UsageTypes.LOAD_BALANCER_POLICY){ //Load Balancer Policy ID - usageRecResponse.setUsageId(usageRecord.getUsageId().toString()); - + LoadBalancerVO lb = _entityMgr.findByIdIncludingRemoved(LoadBalancerVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(lb.getUuid()); } else if(usageRecord.getUsageType() == UsageTypes.PORT_FORWARDING_RULE){ //Port Forwarding Rule ID - usageRecResponse.setUsageId(usageRecord.getUsageId().toString()); + PortForwardingRuleVO pf = _entityMgr.findByIdIncludingRemoved(PortForwardingRuleVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(pf.getUuid()); } else if(usageRecord.getUsageType() == UsageTypes.NETWORK_OFFERING){ //Network Offering Id @@ -3561,7 +3568,8 @@ public class ApiResponseHelper implements ResponseGenerator { } else if(usageRecord.getUsageType() == UsageTypes.VPN_USERS){ //VPN User ID - usageRecResponse.setUsageId(usageRecord.getUsageId().toString()); + VpnUserVO vpnUser = _entityMgr.findByIdIncludingRemoved(VpnUserVO.class, usageRecord.getUsageId().toString()); + usageRecResponse.setUsageId(vpnUser.getUuid()); } else if(usageRecord.getUsageType() == UsageTypes.SECURITY_GROUP){ //Security Group Id diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index b68e8e177d2..28d79f0cfba 100755 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -151,6 +151,7 @@ import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.exception.ExceptionProxyObject; @Component public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiServerService { @@ -393,9 +394,16 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer throw new ServerApiException(ApiErrorCode.PARAM_ERROR, ex.getMessage(), ex); } catch (PermissionDeniedException ex){ - ArrayList idList = ex.getIdProxyList(); + ArrayList idList = ex.getIdProxyList(); if (idList != null) { - s_logger.info("PermissionDenied: " + ex.getMessage() + " on uuids: [" + StringUtils.listToCsvTags(idList) + "]"); + StringBuffer buf = new StringBuffer(); + for (ExceptionProxyObject obj : idList){ + buf.append(obj.getDescription()); + buf.append(":"); + buf.append(obj.getUuid()); + buf.append(" "); + } + s_logger.info("PermissionDenied: " + ex.getMessage() + " on objs: [" + buf.toString() + "]"); } else { s_logger.info("PermissionDenied: " + ex.getMessage()); } @@ -1086,7 +1094,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer apiResponse.setErrorCode(ex.getErrorCode().getHttpCode()); apiResponse.setErrorText(ex.getDescription()); apiResponse.setResponseName(responseName); - ArrayList idList = ex.getIdProxyList(); + ArrayList idList = ex.getIdProxyList(); if (idList != null) { for (int i=0; i < idList.size(); i++) { apiResponse.addProxyObject(idList.get(i)); diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index a126925e5f0..5a25732bca0 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -1095,7 +1095,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { } if (networkId != null) { - sc.setJoinParameters("nicSearch", "networkId", networkId); + sc.setParameters("networkId", networkId); } if (vpcId != null) { @@ -2176,7 +2176,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { UserVmVO vmInstance = _userVmDao.findById(vmId); if ((vmInstance == null) || (vmInstance.getRemoved() != null)) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a virtual machine with specified id"); - ex.addProxyObject(vmInstance, vmId, "vmId"); + ex.addProxyObject(vmId.toString(), "vmId"); throw ex; } diff --git a/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java index ce20562d5f7..56e4d0a369e 100644 --- a/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/ServiceOfferingJoinDaoImpl.java @@ -68,6 +68,7 @@ public class ServiceOfferingJoinDaoImpl extends GenericDaoBase"); + sb.append("<" + serializedName.value() + ">"); usedUuidList = true; } - sb.append("").append(value).append(""); - // We have removed uuid property field due to removal of IdentityProxy class. + sb.append("<" + "uuid" + ">" + idProxy.getUuid() + ""); + // Append the new descriptive property also. + String idFieldName = idProxy.getDescription(); + if (idFieldName != null) { + sb.append("<" + "uuidProperty" + ">" + idFieldName + ""); + } } } if (usedUuidList) { - // close the uuidList. - sb.append(""); + // close the uuidList. + sb.append(""); } } else if (fieldValue instanceof Date) { sb.append("<").append(serializedName.value()).append(">").append(BaseCmd.getDateString((Date) fieldValue)). diff --git a/server/src/com/cloud/async/AsyncJobManagerImpl.java b/server/src/com/cloud/async/AsyncJobManagerImpl.java index 255621960e3..cf5cc70431d 100644 --- a/server/src/com/cloud/async/AsyncJobManagerImpl.java +++ b/server/src/com/cloud/async/AsyncJobManagerImpl.java @@ -770,11 +770,18 @@ public class AsyncJobManagerImpl extends ManagerBase implements AsyncJobManager, // limit to 100 jobs per turn, this gives cleanup throughput as 600 jobs per minute // hopefully this will be fast enough to balance potential growth of job table - List l = _jobDao.getExpiredJobs(cutTime, 100); - if(l != null && l.size() > 0) { + //1) Expire unfinished jobs that weren't processed yet + List l = _jobDao.getExpiredUnfinishedJobs(cutTime, 100); for(AsyncJobVO job : l) { + s_logger.trace("Expunging unfinished job " + job); expungeAsyncJob(job); } + + //2) Expunge finished jobs + List completedJobs = _jobDao.getExpiredCompletedJobs(cutTime, 100); + for(AsyncJobVO job : completedJobs) { + s_logger.trace("Expunging completed job " + job); + expungeAsyncJob(job); } // forcefully cancel blocking queue items if they've been staying there for too long diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index e1d3751f290..929d56bf10c 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -180,7 +180,8 @@ public enum Config { RouterTemplateLXC("Advanced", NetworkManager.class, String.class, "router.template.lxc", "SystemVM Template (LXC)", "Name of the default router template on LXC.", null, ConfigurationParameterScope.zone.toString()), RouterExtraPublicNics("Advanced", NetworkManager.class, Integer.class, "router.extra.public.nics", "2", "specify extra public nics used for virtual router(up to 5)", "0-5"), StartRetry("Advanced", AgentManager.class, Integer.class, "start.retry", "10", "Number of times to retry create and start commands", null), - ScaleRetry("Advanced", AgentManager.class, Integer.class, "scale.retry", "2", "Number of times to retry scaling up the vm", null), + EnableDynamicallyScaleVm("Advanced", ManagementServer.class, Boolean.class, "enable.dynamic.scale.vm", "false", "Enables/Diables dynamically scaling a vm", null, ConfigurationParameterScope.zone.toString()), + ScaleRetry("Advanced", ManagementServer.class, Integer.class, "scale.retry", "2", "Number of times to retry scaling up the vm", null), StopRetryInterval("Advanced", HighAvailabilityManager.class, Integer.class, "stop.retry.interval", "600", "Time in seconds between retries to stop or destroy a vm" , null), StorageCleanupInterval("Advanced", StorageManager.class, Integer.class, "storage.cleanup.interval", "86400", "The interval (in seconds) to wait before running the storage cleanup thread.", null), StorageCleanupEnabled("Advanced", StorageManager.class, Boolean.class, "storage.cleanup.enabled", "true", "Enables/disables the storage cleanup thread.", null), @@ -408,7 +409,7 @@ public enum Config { 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", "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), + CloudDnsName("Advanced", ManagementServer.class, String.class, "cloud.dns.name", null, "DNS name of the cloud for the GSLB service", null), BlacklistedRoutes("Advanced", VpcManager.class, String.class, "blacklisted.routes", null, "Routes that are blacklisted, can not be used for Static Routes creation for the VPC Private Gateway", "routes", ConfigurationParameterScope.zone.toString()), diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index e132ec6775a..779ef4812c9 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -895,10 +895,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati */ } - Grouping.AllocationState allocationState = null; if (allocationStateStr != null && !allocationStateStr.isEmpty()) { try { - allocationState = Grouping.AllocationState.valueOf(allocationStateStr); + Grouping.AllocationState.valueOf(allocationStateStr); } catch (IllegalArgumentException ex) { throw new InvalidParameterValueException("Unable to resolve Allocation State '" + allocationStateStr + "' to a supported state"); } @@ -1320,10 +1319,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("Please enter a valid IPv6 address for IP6 DNS2"); } - Grouping.AllocationState allocationState = null; if (allocationStateStr != null && !allocationStateStr.isEmpty()) { try { - allocationState = Grouping.AllocationState.valueOf(allocationStateStr); + Grouping.AllocationState.valueOf(allocationStateStr); } catch (IllegalArgumentException ex) { throw new InvalidParameterValueException("Unable to resolve Allocation State '" + allocationStateStr + "' to a supported state"); } @@ -1744,13 +1742,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // check if zone has necessary trafficTypes before enabling try { PhysicalNetwork mgmtPhyNetwork; - if (NetworkType.Advanced == zone.getNetworkType()) { - // zone should have a physical network with public and management traffiType - _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Public); - mgmtPhyNetwork = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Management); - } else { // zone should have a physical network with management traffiType mgmtPhyNetwork = _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Management); + if (NetworkType.Advanced == zone.getNetworkType() && ! zone.isSecurityGroupEnabled() ) { + // advanced zone without SG should have a physical network with public Thpe + _networkModel.getDefaultPhysicalNetworkByZoneAndTrafficType(zoneId, TrafficType.Public); } try { @@ -2305,7 +2301,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati String endIP = cmd.getEndIp(); String newVlanGateway = cmd.getGateway(); String newVlanNetmask = cmd.getNetmask(); - Long userId = UserContext.current().getCallerUserId(); String vlanId = cmd.getVlan(); Boolean forVirtualNetwork = cmd.isForVirtualNetwork(); Long networkId = cmd.getNetworkID(); @@ -3028,9 +3023,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } + } else { + // when there is no dhcp support in the network. + if (!deletePublicIPRange(vlanDbId)) { + return false; + } + _vlanDao.expunge(vlanDbId); + return true; } } - throw new InvalidParameterValueException("One of the ips in the range is used to provide Dhcp service to this subnet. cannot delete this range as "); + return false; } @@ -3304,42 +3306,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } - private void checkPrivateIpRangeErrors(Long podId, String startIP, String endIP) { - HostPodVO pod = _podDao.findById(podId); - if (pod == null) { - throw new InvalidParameterValueException("Please specify a valid pod."); - } - - // Check that the start and end IPs are valid - if (!NetUtils.isValidIp(startIP)) { - throw new InvalidParameterValueException("Please specify a valid start IP"); - } - - if (endIP != null && !NetUtils.isValidIp(endIP)) { - throw new InvalidParameterValueException("Please specify a valid end IP"); - } - - if (endIP != null && !NetUtils.validIpRange(startIP, endIP)) { - throw new InvalidParameterValueException("Please specify a valid IP range."); - } - - // Check that the IPs that are being added are compatible with the pod's - // CIDR - String cidrAddress = getCidrAddress(podId); - long cidrSize = getCidrSize(podId); - - if (endIP != null && !NetUtils.sameSubnetCIDR(startIP, endIP, cidrSize)) { - throw new InvalidParameterValueException("Please ensure that your start IP and end IP are in the same subnet, as per the pod's CIDR size."); - } - - if (!NetUtils.sameSubnetCIDR(startIP, cidrAddress, cidrSize)) { - throw new InvalidParameterValueException("Please ensure that your start IP is in the same subnet as the pod's CIDR address."); - } - - if (endIP != null && !NetUtils.sameSubnetCIDR(endIP, cidrAddress, cidrSize)) { - throw new InvalidParameterValueException("Please ensure that your end IP is in the same subnet as the pod's CIDR address."); - } - } private String getCidrAddress(String cidr) { String[] cidrPair = cidr.split("\\/"); @@ -3351,15 +3317,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati return Integer.parseInt(cidrPair[1]); } - private String getCidrAddress(long podId) { - HostPodVO pod = _podDao.findById(podId); - return pod.getCidrAddress(); - } - - private long getCidrSize(long podId) { - HostPodVO pod = _podDao.findById(podId); - return pod.getCidrSize(); - } @Override public void checkPodCidrSubnets(long dcId, Long podIdToBeSkipped, String cidr) { @@ -4311,7 +4268,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati public boolean isOfferingForVpc(NetworkOffering offering) { boolean vpcProvider = _ntwkOffServiceMapDao.isProviderForNetworkOffering(offering.getId(), Provider.VPCVirtualRouter); - boolean internalLb = offering.getInternalLb(); return vpcProvider; } @@ -4468,6 +4424,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati // Note: This method will be used for entity name validations in the coming // releases (place holder for now) + @SuppressWarnings("unused") private void validateEntityName(String str) { String forbidden = "~!@#$%^&*()+="; char[] searchChars = forbidden.toCharArray(); @@ -4698,7 +4655,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati String endIP = cmd.getEndIp(); String gateway = cmd.getGateway(); String netmask = cmd.getNetmask(); - Long userId = UserContext.current().getCallerUserId(); String vlanId = cmd.getVlan(); Region region = _regionDao.findById(regionId); diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 9db1858de33..e05780eb1a3 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -678,19 +678,28 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy DataCenterDeployment plan = new DataCenterDeployment(dataCenterId); + NetworkVO defaultNetwork = null; + if (dc.getNetworkType() == NetworkType.Advanced && dc.isSecurityGroupEnabled()) { + List networks = _networkDao.listByZoneSecurityGroup(dataCenterId); + if (networks == null || networks.size() == 0) { + throw new CloudRuntimeException("Can not found security enabled network in SG Zone " + dc); + } + defaultNetwork = networks.get(0); + } else { TrafficType defaultTrafficType = TrafficType.Public; if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) { defaultTrafficType = TrafficType.Guest; } - List defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType); + // api should never allow this situation to happen if (defaultNetworks.size() != 1) { - throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + defaultTrafficType + " when expect to find 1"); + throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + + defaultTrafficType + " when expect to find 1"); + } + defaultNetwork = defaultNetworks.get(0); } - NetworkVO defaultNetwork = defaultNetworks.get(0); - List offerings = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemControlNetwork, NetworkOffering.SystemManagementNetwork); List> networks = new ArrayList>(offerings.size() + 1); NicProfile defaultNic = new NicProfile(); diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java index b2a684991bd..fa326d8b91a 100644 --- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -378,7 +378,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy if (planner instanceof DeploymentClusterPlanner) { - ExcludeList PlannerAvoidInput = new ExcludeList(avoids.getDataCentersToAvoid(), + ExcludeList plannerAvoidInput = new ExcludeList(avoids.getDataCentersToAvoid(), avoids.getPodsToAvoid(), avoids.getClustersToAvoid(), avoids.getHostsToAvoid(), avoids.getPoolsToAvoid()); @@ -386,19 +386,19 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy if (clusterList != null && !clusterList.isEmpty()) { // planner refactoring. call allocators to list hosts - ExcludeList PlannerAvoidOutput = new ExcludeList(avoids.getDataCentersToAvoid(), + ExcludeList plannerAvoidOutput = new ExcludeList(avoids.getDataCentersToAvoid(), avoids.getPodsToAvoid(), avoids.getClustersToAvoid(), avoids.getHostsToAvoid(), avoids.getPoolsToAvoid()); - resetAvoidSet(PlannerAvoidOutput, PlannerAvoidInput); + resetAvoidSet(plannerAvoidOutput, plannerAvoidInput); dest = checkClustersforDestination(clusterList, vmProfile, plan, avoids, dc, - getPlannerUsage(planner), PlannerAvoidOutput); + getPlannerUsage(planner), plannerAvoidOutput); if (dest != null) { return dest; } // reset the avoid input to the planners - resetAvoidSet(avoids, PlannerAvoidOutput); + resetAvoidSet(avoids, plannerAvoidOutput); } else { return null; @@ -813,12 +813,8 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy // remove any hosts/pools that the planners might have added // to get the list of hosts/pools that Allocators flagged as 'avoid' - if (allocatorAvoidOutput.getHostsToAvoid() != null && plannerAvoidOutput.getHostsToAvoid() != null) { - allocatorAvoidOutput.getHostsToAvoid().removeAll(plannerAvoidOutput.getHostsToAvoid()); - } - if (allocatorAvoidOutput.getPoolsToAvoid() != null && plannerAvoidOutput.getPoolsToAvoid() != null) { - allocatorAvoidOutput.getPoolsToAvoid().removeAll(plannerAvoidOutput.getPoolsToAvoid()); - } + + resetAvoidSet(allocatorAvoidOutput, plannerAvoidOutput); // if all hosts or all pools in the cluster are in avoid set after this // pass, then put the cluster in avoid set. @@ -827,8 +823,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy List allhostsInCluster = _hostDao.listAllUpAndEnabledNonHAHosts(Host.Type.Routing, clusterVO.getId(), clusterVO.getPodId(), clusterVO.getDataCenterId(), null); for (HostVO host : allhostsInCluster) { - if (allocatorAvoidOutput.getHostsToAvoid() == null - || !allocatorAvoidOutput.getHostsToAvoid().contains(host.getId())) { + if (!allocatorAvoidOutput.shouldAvoid(host)) { // there's some host in the cluster that is not yet in avoid set avoidAllHosts = false; } @@ -837,8 +832,7 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy List allPoolsInCluster = _storagePoolDao.findPoolsByTags(clusterVO.getDataCenterId(), clusterVO.getPodId(), clusterVO.getId(), null); for (StoragePoolVO pool : allPoolsInCluster) { - if (allocatorAvoidOutput.getPoolsToAvoid() == null - || !allocatorAvoidOutput.getPoolsToAvoid().contains(pool.getId())) { + if (!allocatorAvoidOutput.shouldAvoid(pool)) { // there's some pool in the cluster that is not yet in avoid set avoidAllPools = false; } diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java index b9e37682fa6..e18c164ed36 100644 --- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java +++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java @@ -25,7 +25,9 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VolumeTO; +import com.cloud.configuration.Config; import com.cloud.offering.ServiceOffering; +import com.cloud.server.ConfigurationServer; import com.cloud.storage.dao.VMTemplateDetailsDao; import com.cloud.utils.component.AdapterBase; import com.cloud.vm.NicProfile; @@ -43,6 +45,8 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis @Inject NicDao _nicDao; @Inject VMInstanceDao _virtualMachineDao; @Inject NicSecondaryIpDao _nicSecIpDao; + @Inject ConfigurationServer _configServer; + protected HypervisorGuruBase() { super(); @@ -122,6 +126,9 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis VMInstanceVO vmInstance = _virtualMachineDao.findById(to.getId()); to.setUuid(vmInstance.getUuid()); + // + to.setEnableDynamicallyScaleVm(Boolean.parseBoolean(_configServer.getConfigValue(Config.EnableDynamicallyScaleVm.key(), Config.ConfigurationParameterScope.zone.toString(), vm.getDataCenterId()))); + return to; } diff --git a/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java index 4a90a77f428..9d24e478fe2 100644 --- a/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java @@ -550,7 +550,9 @@ public abstract class ExternalFirewallDeviceManagerImpl extends AdapterBase impl ruleTO = new FirewallRuleTO(rule, guestVlanTag, rule.getTrafficType()); } else { IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId()); - ruleTO = new FirewallRuleTO(rule, null, sourceIp.getAddress().addr()); + Vlan vlan = _vlanDao.findById(sourceIp.getVlanId()); + + ruleTO = new FirewallRuleTO(rule, vlan.getVlanTag(), sourceIp.getAddress().addr()); } rulesTO.add(ruleTO); } diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java index f93bf7ae9b5..04f96825abb 100644 --- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java @@ -138,6 +138,8 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase @Inject NetworkManager _networkMgr; @Inject + NetworkDao _networksDao = null; + @Inject InlineLoadBalancerNicMapDao _inlineLoadBalancerNicMapDao; @Inject NicDao _nicDao; @@ -208,6 +210,17 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase } zoneId = pNetwork.getDataCenterId(); + DataCenter dc = _dcDao.findById(zoneId); + if (dc.getNetworkType() == DataCenter.NetworkType.Basic) { + List guestNetworks = _networksDao.listByZoneAndTrafficType(dc.getId(), TrafficType.Guest); + com.cloud.network.dao.NetworkVO basicZoneNetwork = guestNetworks.get(0); + NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(basicZoneNetwork.getNetworkOfferingId()); + if (!ntwkOff.getElasticIp() && !ntwkOff.getElasticLb()) { + throw new InvalidParameterValueException("Could not add external load balancer device in to basic zone " + + " with no Elastic IP and Elastic LB services."); + } + } + PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), ntwkDevice.getNetworkServiceProvder()); if (gslbProvider) { diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index eb18eaa34e2..13a93f0a655 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -84,6 +84,7 @@ import com.cloud.deploy.DeployDestination; import com.cloud.deploy.DeploymentPlan; import com.cloud.domain.Domain; import com.cloud.domain.dao.DomainDao; +import com.cloud.event.ActionEventUtils; import com.cloud.event.EventTypes; import com.cloud.event.UsageEventUtils; import com.cloud.event.dao.UsageEventDao; @@ -346,9 +347,6 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L PortableIpDao _portableIpDao; protected StateMachine2 _stateMachine; - private final HashMap _systemNetworks = new HashMap(5); - private static Long _privateOfferingId = null; - ScheduledExecutorService _executor; SearchBuilder AssignIpAddressSearch; @@ -574,11 +572,6 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return ipToReturn; } - @Override - public PublicIp assignVpnGatewayIpAddress(long dcId, Account owner, long vpcId) throws InsufficientAddressCapacityException, ConcurrentOperationException { - return assignDedicateIpAddress(owner, null, vpcId, dcId, false); - } - @DB @Override @@ -598,6 +591,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L // this ownerId comes from owner or type Account. See the class "AccountVO" and the annotations in that class // to get the table name and field name that is queried to fill this ownerid. ConcurrentOperationException ex = new ConcurrentOperationException("Unable to lock account"); + throw ex; } if (s_logger.isDebugEnabled()) { s_logger.debug("lock account " + ownerId + " is acquired"); @@ -744,7 +738,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L // zone is of type DataCenter. See DataCenterVO.java. PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation, " + "Zone is currently disabled"); - ex.addProxyObject("data_center", zone.getId(), "zoneId"); + ex.addProxyObject(zone.getUuid(), "zoneId"); throw ex; } @@ -1150,6 +1144,9 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L _ipAddressDao.update(ipAddrId, ip); txn.commit(); + ActionEventUtils.onActionEvent(User.UID_SYSTEM, Account.ACCOUNT_ID_SYSTEM, Domain.ROOT_DOMAIN, + EventTypes.EVENT_PORTABLE_IP_TRANSFER, "Portable IP associated is transferred from network " + + currentNetworkId + " to " + newNetworkId); } @Override @@ -1201,7 +1198,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } @DB - private void releasePortableIpAddress(long addrId) { + @Override + public boolean releasePortableIpAddress(long addrId) { Transaction txn = Transaction.currentTxn(); GlobalLock portableIpLock = GlobalLock.getInternLock("PortablePublicIpRange"); @@ -1216,12 +1214,13 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L // removed the provisioned vlan VlanVO vlan = _vlanDao.findById(ip.getVlanId()); - _vlanDao.expunge(vlan.getId()); + _vlanDao.remove(vlan.getId()); // remove the provisioned public ip address - _ipAddressDao.expunge(ip.getId()); + _ipAddressDao.remove(ip.getId()); txn.commit(); + return true; } finally { portableIpLock.releaseRef(); } @@ -1485,8 +1484,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L if (errorIfAlreadySetup) { InvalidParameterValueException ex = new InvalidParameterValueException("Found existing network configuration (with specified id) for offering (with specified id)"); - ex.addProxyObject(offering, offering.getId(), "offeringId"); - ex.addProxyObject(configs.get(0), configs.get(0).getId(), "networkConfigId"); + ex.addProxyObject(offering.getUuid(), "offeringId"); + ex.addProxyObject(configs.get(0).getUuid(), "networkConfigId"); throw ex; } else { return configs; @@ -1502,8 +1501,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L if (errorIfAlreadySetup) { InvalidParameterValueException ex = new InvalidParameterValueException("Found existing network configuration (with specified id) for offering (with specified id)"); - ex.addProxyObject(offering, offering.getId(), "offeringId"); - ex.addProxyObject(configs.get(0), configs.get(0).getId(), "networkConfigId"); + ex.addProxyObject(offering.getUuid(), "offeringId"); + ex.addProxyObject(configs.get(0).getUuid(), "networkConfigId"); throw ex; } else { return configs; @@ -1555,7 +1554,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L if (networks.size() < 1) { // see networkOfferingVO.java CloudRuntimeException ex = new CloudRuntimeException("Unable to convert network offering with specified id to network profile"); - ex.addProxyObject(offering, offering.getId(), "offeringId"); + ex.addProxyObject(offering.getUuid(), "offeringId"); throw ex; } @@ -1934,7 +1933,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L if (!element.implement(network, offering, dest, context)) { CloudRuntimeException ex = new CloudRuntimeException("Failed to implement provider " + element.getProvider().getName() + " for network with specified id"); - ex.addProxyObject(network, network.getId(), "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } } @@ -2254,6 +2253,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } } + @Override public void removeNic(VirtualMachineProfile vm, Nic nic) { removeNic(vm, _nicDao.findById(nic.getId())); @@ -2330,7 +2330,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L if (ntwkOff.getState() != NetworkOffering.State.Enabled) { // see NetworkOfferingVO InvalidParameterValueException ex = new InvalidParameterValueException("Can't use specified network offering id as its stat is not " + NetworkOffering.State.Enabled); - ex.addProxyObject(ntwkOff, ntwkOff.getId(), "networkOfferingId"); + ex.addProxyObject(ntwkOff.getUuid(), "networkOfferingId"); throw ex; } @@ -2339,7 +2339,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L // see PhysicalNetworkVO.java InvalidParameterValueException ex = new InvalidParameterValueException("Specified physical network id is" + " in incorrect state:" + pNtwk.getState()); - ex.addProxyObject("physical_network", pNtwk.getId(), "physicalNetworkId"); + ex.addProxyObject(pNtwk.getUuid(), "physicalNetworkId"); throw ex; } @@ -2992,7 +2992,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L NetworkVO network = _networksDao.findById(networkId); if (network == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Network with specified id doesn't exist"); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(String.valueOf(networkId), "networkId"); throw ex; } @@ -3241,7 +3241,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L " network provision due to ", ex); CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified id)" + " elements and resources as a part of network provision for persistent network"); - e.addProxyObject(guestNetwork, guestNetwork.getId(), "networkId"); + e.addProxyObject(guestNetwork.getUuid(), "networkId"); throw e; } } @@ -3320,8 +3320,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return false; } - @Override - public boolean cleanupIpResources(long ipId, long userId, Account caller) { + + protected boolean cleanupIpResources(long ipId, long userId, Account caller) { boolean success = true; // Revoke all firewall rules for the ip @@ -3360,7 +3360,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L // the code would be triggered s_logger.debug("Cleaning up remote access vpns as a part of public IP id=" + ipId + " release..."); try { - _vpnMgr.destroyRemoteAccessVpn(ipId, caller); + _vpnMgr.destroyRemoteAccessVpnForIp(ipId, caller); } catch (ResourceUnavailableException e) { s_logger.warn("Unable to destroy remote access vpn for ip id=" + ipId + " as a part of ip release", e); success = false; @@ -3429,9 +3429,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L throws InsufficientAddressCapacityException { String ipaddr = null; Account caller = UserContext.current().getCaller(); - long callerUserId = UserContext.current().getCallerUserId(); // check permissions - DataCenter zone = _configMgr.getZone(zoneId); Network network = _networksDao.findById(networkId); _accountMgr.checkAccess(caller, null, false, network); @@ -3620,8 +3618,16 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L List ipsToRelease = _ipAddressDao.listByAssociatedNetwork(networkId, null); for (IPAddressVO ipToRelease : ipsToRelease) { if (ipToRelease.getVpcId() == null) { + if (!ipToRelease.isPortable()) { IPAddressVO ip = markIpAsUnavailable(ipToRelease.getId()); assert (ip != null) : "Unable to mark the ip address id=" + ipToRelease.getId() + " as unavailable."; + } else { + // portable IP address are associated with owner, until explicitly requested to be disassociated + // so as part of network clean up just break IP association with guest network + ipToRelease.setAssociatedWithNetworkId(null); + _ipAddressDao.update(ipToRelease.getId(), ipToRelease); + s_logger.debug("Portable IP address " + ipToRelease + " is no longer associated with any network"); + } } else { _vpcMgr.unassignIPFromVpcNetwork(ipToRelease.getId(), network.getId()); } @@ -4028,7 +4034,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L String requestedIpv4, String requestedIpv6) throws InsufficientVirtualNetworkCapcityException, InsufficientAddressCapacityException { //This method allocates direct ip for the Shared network in Advance zones - boolean ipv4 = false, ipv6 = false; + boolean ipv4 = false; Transaction txn = Transaction.currentTxn(); txn.start(); @@ -4071,7 +4077,6 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L //FIXME - get ipv6 address from the placeholder if it's stored there if (network.getIp6Gateway() != null) { if (nic.getIp6Address() == null) { - ipv6 = true; UserIpv6Address ip = _ipv6Mgr.assignDirectIp6Address(dc.getId(), vm.getOwner(), network.getId(), requestedIpv6); Vlan vlan = _vlanDao.findById(ip.getVlanId()); nic.setIp6Address(ip.getAddress().toString()); @@ -4161,6 +4166,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return nic; } + + @Override public List getNicProfiles(VirtualMachine vm) { List nics = _nicDao.listByVmId(vm.getId()); @@ -4210,6 +4217,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return map; } + @Override public List getProvidersForServiceInNetwork(Network network, Service service) { Map> service2ProviderMap = getServiceProvidersMap(network.getId()); @@ -4220,6 +4228,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return null; } + protected List getElementForServiceInNetwork(Network network, Service service) { List elements = new ArrayList(); List providers = getProvidersForServiceInNetwork(network, service); @@ -4242,6 +4251,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return elements; } + @Override public StaticNatServiceProvider getStaticNatProviderForNetwork(Network network) { //only one provider per Static nat service is supoprted @@ -4250,6 +4260,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return (StaticNatServiceProvider)element; } + @Override public LoadBalancingServiceProvider getLoadBalancingProviderForNetwork(Network network, Scheme lbScheme) { List lbElements = getElementForServiceInNetwork(network, Service.Lb); @@ -4276,6 +4287,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return (LoadBalancingServiceProvider)lbElement; } + @Override public boolean isNetworkInlineMode(Network network) { NetworkOfferingVO offering = _networkOfferingDao.findById(network.getNetworkOfferingId()); @@ -4291,14 +4303,15 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return rules.size(); } + @Override public boolean isSecondaryIpSetForNic(long nicId) { NicVO nic = _nicDao.findById(nicId); return nic.getSecondaryIp(); } - @Override - public boolean removeVmSecondaryIpsOfNic(long nicId) { + + private boolean removeVmSecondaryIpsOfNic(long nicId) { Transaction txn = Transaction.currentTxn(); txn.start(); List ipList = _nicSecondaryIpDao.listByNicId(nicId); @@ -4312,6 +4325,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return true; } + @Override public String allocatePublicIpForGuestNic(Long networkId, DataCenter dc, Pod pod,Account owner, String requestedIp) throws InsufficientAddressCapacityException { @@ -4324,6 +4338,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L return ipAddr.addr(); } + @Override public NicVO savePlaceholderNic(Network network, String ip4Address, Type vmType) { NicVO nic = new NicVO(null, null, network.getId(), null); diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java index 8971f8c163b..f6bd646a91d 100755 --- a/server/src/com/cloud/network/NetworkModelImpl.java +++ b/server/src/com/cloud/network/NetworkModelImpl.java @@ -32,13 +32,16 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import org.apache.cloudstack.acl.ControlledEntity.ACLType; import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.api.ApiDBUtils; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.DataCenter; import com.cloud.dc.PodVlanMapVO; import com.cloud.dc.Vlan; import com.cloud.dc.Vlan.VlanType; @@ -282,7 +285,12 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { } else { CloudRuntimeException ex = new CloudRuntimeException("Multiple generic soure NAT IPs provided for network"); // see the IPAddressVO.java class. - ex.addProxyObject("user_ip_address", ip.getAssociatedWithNetworkId(), "networkId"); + IPAddressVO ipAddr = ApiDBUtils.findIpAddressById(ip.getAssociatedWithNetworkId()); + String ipAddrUuid = ip.getAssociatedWithNetworkId().toString(); + if ( ipAddr != null){ + ipAddrUuid = ipAddr.getUuid(); + } + ex.addProxyObject(ipAddrUuid, "networkId"); throw ex; } } @@ -1128,17 +1136,21 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { public PhysicalNetwork getDefaultPhysicalNetworkByZoneAndTrafficType(long zoneId, TrafficType trafficType) { List networkList = _physicalNetworkDao.listByZoneAndTrafficType(zoneId, trafficType); + DataCenter dc = ApiDBUtils.findZoneById(zoneId); + String dcUuid = String.valueOf(zoneId); + if ( dc != null ){ + dcUuid = dc.getUuid(); + } if (networkList.isEmpty()) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find the default physical network with traffic=" + trafficType + " in the specified zone id"); - // Since we don't have a DataCenterVO object at our disposal, we just set the table name that the zoneId's corresponding uuid is looked up from, manually. - ex.addProxyObject("data_center", zoneId, "zoneId"); + ex.addProxyObject(dcUuid, "zoneId"); throw ex; } if (networkList.size() > 1) { InvalidParameterValueException ex = new InvalidParameterValueException("More than one physical networks exist in zone id=" + zoneId + " with traffic type=" + trafficType); - ex.addProxyObject("data_center", zoneId, "zoneId"); + ex.addProxyObject(dcUuid, "zoneId"); throw ex; } @@ -1488,24 +1500,25 @@ public class NetworkModelImpl extends ManagerBase implements NetworkModel { @Override public void checkNetworkPermissions(Account owner, Network network) { // Perform account permission check - if (network.getGuestType() != Network.GuestType.Shared) { + if (network.getGuestType() != Network.GuestType.Shared + || (network.getGuestType() == Network.GuestType.Shared && network.getAclType() == ACLType.Account)) { AccountVO networkOwner = _accountDao.findById(network.getAccountId()); if(networkOwner == null) - throw new PermissionDeniedException("Unable to use network with id= " + network.getId() + ", network does not have an owner"); + throw new PermissionDeniedException("Unable to use network with id= " + ((network != null)? ((NetworkVO)network).getUuid() : "") + ", network does not have an owner"); if(owner.getType() != Account.ACCOUNT_TYPE_PROJECT && networkOwner.getType() == Account.ACCOUNT_TYPE_PROJECT){ if(!_projectAccountDao.canAccessProjectAccount(owner.getAccountId(), network.getAccountId())){ - throw new PermissionDeniedException("Unable to use network with id= " + network.getId() + ", permission denied"); + throw new PermissionDeniedException("Unable to use network with id= " + ((network != null)? ((NetworkVO)network).getUuid() : "") + ", permission denied"); } }else{ List networkMap = _networksDao.listBy(owner.getId(), network.getId()); if (networkMap == null || networkMap.isEmpty()) { - throw new PermissionDeniedException("Unable to use network with id= " + network.getId() + ", permission denied"); + throw new PermissionDeniedException("Unable to use network with id= " + ((network != null)? ((NetworkVO)network).getUuid() : "") + ", permission denied"); } } } else { if (!isNetworkAvailableInDomain(network.getId(), owner.getDomainId())) { - throw new PermissionDeniedException("Shared network id=" + network.getUuid() + " is not available in domain id=" + owner.getDomainId()); + throw new PermissionDeniedException("Shared network id=" + ((network != null)? ((NetworkVO)network).getUuid() : "") + " is not available in domain id=" + owner.getDomainId()); } } } diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 1533ca9bc4f..98992846c4e 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -65,6 +65,7 @@ import org.springframework.stereotype.Component; import org.apache.cloudstack.api.command.user.vm.ListNicsCmd; import org.bouncycastle.util.IPAddress; +import com.cloud.api.ApiDBUtils; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ConfigurationDao; @@ -317,7 +318,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } else { CloudRuntimeException ex = new CloudRuntimeException("Multiple generic soure NAT IPs provided for network"); // see the IPAddressVO.java class. - ex.addProxyObject("user_ip_address", ip.getAssociatedWithNetworkId(), "networkId"); + IPAddressVO ipAddr = ApiDBUtils.findIpAddressById(ip.getAssociatedWithNetworkId()); + String ipAddrUuid = ip.getAssociatedWithNetworkId().toString(); + if ( ipAddr != null ){ + ipAddrUuid = ipAddr.getUuid(); + } + ex.addProxyObject(ipAddrUuid, "networkId"); throw ex; } } @@ -591,8 +597,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { @Override @ActionEvent(eventType = EventTypes.EVENT_PORTABLE_IP_RELEASE, eventDescription = "disassociating portable Ip", async = true) - public boolean releasePortableIpAddress(long ipAddressId) throws InsufficientAddressCapacityException { - return releaseIpAddressInternal(ipAddressId); + public boolean releasePortableIpAddress(long ipAddressId) { + try { + return releaseIpAddressInternal(ipAddressId); + } catch (Exception e) { + return false; + } } @Override @@ -873,14 +883,14 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { // don't allow releasing system ip address if (ipVO.getSystem()) { InvalidParameterValueException ex = new InvalidParameterValueException("Can't release system IP address with specified id"); - ex.addProxyObject(ipVO, ipVO.getId(), "systemIpAddrId"); + ex.addProxyObject(ipVO.getUuid(), "systemIpAddrId"); throw ex; } boolean success = _networkMgr.disassociatePublicIpAddress(ipAddressId, userId, caller); if (success) { - if (!ipVO.isPortable()) { + if (ipVO.isPortable()) { return success; } Long networkId = ipVO.getAssociatedWithNetworkId(); @@ -990,12 +1000,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (ntwkOff == null || ntwkOff.isSystemOnly()) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find network offering by specified id"); if (ntwkOff != null) { - ex.addProxyObject(ntwkOff, networkOfferingId, "networkOfferingId"); - // Get the VO object's table name. - String tablename = AnnotationHelper.getTableName(ntwkOff); - if (tablename != null) { - ex.addProxyObject(tablename, networkOfferingId, "networkOfferingId"); - } + ex.addProxyObject(ntwkOff.getUuid(), "networkOfferingId"); } throw ex; } @@ -1029,7 +1034,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) { // See DataCenterVO.java PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation since specified Zone is currently disabled"); - ex.addProxyObject(zone, zoneId, "zoneId"); + ex.addProxyObject(zone.getUuid(), "zoneId"); throw ex; } @@ -1251,13 +1256,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { // Can add vlan range only to the network which allows it if (createVlan && !ntwkOff.getSpecifyIpRanges()) { InvalidParameterValueException ex = new InvalidParameterValueException("Network offering with specified id doesn't support adding multiple ip ranges"); - ex.addProxyObject(ntwkOff, ntwkOff.getId(), "networkOfferingId"); - String tablename = AnnotationHelper.getTableName(ntwkOff); - if (tablename != null) { - ex.addProxyObject(tablename, ntwkOff.getId(), "networkOfferingId"); - } else { - s_logger.info("\nCould not retrieve table name (annotation) from " + tablename + " VO proxy object\n"); - } + ex.addProxyObject(ntwkOff.getUuid(), "networkOfferingId"); throw ex; } @@ -1342,7 +1341,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } catch (ResourceUnavailableException ex) { s_logger.warn("Failed to implement persistent guest network " + network + "due to ", ex); CloudRuntimeException e = new CloudRuntimeException("Failed to implement persistent guest network"); - e.addProxyObject(network, network.getId(), "networkId"); + e.addProxyObject(network.getUuid(), "networkId"); throw e; } } @@ -1428,7 +1427,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (!_projectMgr.canAccessProjectAccount(caller, project.getProjectAccountId())) { // getProject() returns type ProjectVO. InvalidParameterValueException ex = new InvalidParameterValueException("Account " + caller + " cannot access specified project id"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(project.getUuid(), "projectId"); throw ex; } permittedAccounts.add(project.getProjectAccountId()); @@ -1753,14 +1752,14 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { // see NetworkVO.java InvalidParameterValueException ex = new InvalidParameterValueException("unable to find network with specified id"); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(String.valueOf(networkId), "networkId"); throw ex; } // don't allow to delete system network if (isNetworkSystem(network)) { InvalidParameterValueException ex = new InvalidParameterValueException("Network with specified id is system and can't be removed"); - ex.addProxyObject(network, network.getId(), "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } @@ -1789,7 +1788,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { NetworkVO network = _networksDao.findById(networkId); if (network == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Network with specified id doesn't exist"); - ex.addProxyObject("networks", networkId, "networkId"); + ex.addProxyObject(networkId.toString(), "networkId"); throw ex; } @@ -1932,7 +1931,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (network == null) { // see NetworkVO.java InvalidParameterValueException ex = new InvalidParameterValueException("Specified network id doesn't exist in the system"); - ex.addProxyObject("networks", networkId, "networkId"); + ex.addProxyObject(String.valueOf(networkId), "networkId"); throw ex; } @@ -1988,14 +1987,14 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (networkOfferingId != null) { if (networkOffering == null || networkOffering.isSystemOnly()) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find network offering with specified id"); - ex.addProxyObject(networkOffering, networkOfferingId, "networkOfferingId"); + ex.addProxyObject(networkOfferingId.toString(), "networkOfferingId"); throw ex; } // network offering should be in Enabled state if (networkOffering.getState() != NetworkOffering.State.Enabled) { InvalidParameterValueException ex = new InvalidParameterValueException("Network offering with specified id is not in " + NetworkOffering.State.Enabled + " state, can't upgrade to it"); - ex.addProxyObject(networkOffering, networkOfferingId, "networkOfferingId"); + ex.addProxyObject(networkOffering.getUuid(), "networkOfferingId"); throw ex; } //can't update from vpc to non-vpc network offering @@ -2017,7 +2016,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (changeCidr) { if (!checkForNonStoppedVmInNetwork(network.getId())) { InvalidParameterValueException ex = new InvalidParameterValueException("All user vm of network of specified id should be stopped before changing CIDR!"); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } } @@ -2150,7 +2149,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (!_networkMgr.shutdownNetworkElementsAndResources(context, true, network)) { s_logger.warn("Failed to shutdown the network elements and resources as a part of network restart: " + network); CloudRuntimeException ex = new CloudRuntimeException("Failed to shutdown the network elements and resources as a part of update to network of specified id"); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } } else { @@ -2169,13 +2168,13 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (!_networkMgr.shutdownNetwork(network.getId(), context, true)) { s_logger.warn("Failed to shutdown the network as a part of update to network with specified id"); CloudRuntimeException ex = new CloudRuntimeException("Failed to shutdown the network as a part of update of specified network id"); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } } } else { CloudRuntimeException ex = new CloudRuntimeException("Failed to shutdown the network elements and resources as a part of update to network with specified id; network is in wrong state: " + network.getState()); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } } @@ -2186,7 +2185,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { boolean validStateToImplement = (networkState == Network.State.Implemented || networkState == Network.State.Setup || networkState == Network.State.Allocated); if (restartNetwork && !validStateToImplement) { CloudRuntimeException ex = new CloudRuntimeException("Failed to implement the network elements and resources as a part of update to network with specified id; network is in wrong state: " + networkState); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } @@ -2237,7 +2236,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } catch (Exception ex) { s_logger.warn("Failed to implement network " + network + " elements and resources as a part of network update due to ", ex); CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified id) elements and resources as a part of network update"); - e.addProxyObject(network, networkId, "networkId"); + e.addProxyObject(network.getUuid(), "networkId"); throw e; } } @@ -2255,7 +2254,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { "f network update due to ", ex); CloudRuntimeException e = new CloudRuntimeException("Failed to implement network (with specified" + " id) elements and resources as a part of network update"); - e.addProxyObject(network, networkId, "networkId"); + e.addProxyObject(network.getUuid(), "networkId"); throw e; } } @@ -2523,7 +2522,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { PhysicalNetworkVO network = _physicalNetworkDao.findById(id); if (network == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Physical Network with specified id doesn't exist in the system"); - ex.addProxyObject(network, id, "physicalNetworkId"); + ex.addProxyObject(id.toString(), "physicalNetworkId"); throw ex; } @@ -2531,7 +2530,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { DataCenter zone = _dcDao.findById(network.getDataCenterId()); if (zone == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Zone with id=" + network.getDataCenterId() + " doesn't exist in the system"); - ex.addProxyObject(zone, network.getDataCenterId(), "dataCenterId"); + ex.addProxyObject(String.valueOf(network.getDataCenterId()), "dataCenterId"); throw ex; } if (newVnetRangeString != null) { @@ -2545,7 +2544,6 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (removeVlan != null){ List tokens = processVlanRange(network,removeVlan); boolean result = removeVlanRange(network, tokens.get(0), tokens.get(1)); - } if (tags != null && tags.size() > 1) { @@ -2791,9 +2789,6 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { return true; } - private boolean physicalNetworkHasAllocatedVnets(long zoneId, long physicalNetworkId) { - return !_dcDao.listAllocatedVnets(physicalNetworkId).isEmpty(); - } @Override @ActionEvent(eventType = EventTypes.EVENT_PHYSICAL_NETWORK_DELETE, eventDescription = "deleting physical network", async = true) @@ -2804,7 +2799,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { PhysicalNetworkVO pNetwork = _physicalNetworkDao.findById(physicalNetworkId); if (pNetwork == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Physical Network with specified id doesn't exist in the system"); - ex.addProxyObject(pNetwork, physicalNetworkId, "physicalNetworkId"); + ex.addProxyObject(physicalNetworkId.toString(), "physicalNetworkId"); throw ex; } @@ -3100,7 +3095,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { Account account = _accountDao.findActiveAccount(accountName, domainId); if (account == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find account " + accountName); - ex.addProxyObject("domain", domainId, "domainId"); + DomainVO domain = ApiDBUtils.findDomainById(domainId); + String domainUuid = domainId.toString(); + if (domain != null ){ + domainUuid = domain.getUuid(); + } + ex.addProxyObject(domainUuid, "domainId"); throw ex; } else { accountId = account.getId(); @@ -3112,7 +3112,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { Project project = _projectMgr.getProject(projectId); if (project == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find project by id " + projectId); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(projectId.toString(), "projectId"); throw ex; } accountId = project.getProjectAccountId(); @@ -3210,7 +3210,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { PhysicalNetworkVO network = _physicalNetworkDao.findById(physicalNetworkId); if (network == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Physical Network with specified id doesn't exist in the system"); - ex.addProxyObject(network, physicalNetworkId, "physicalNetworkId"); + ex.addProxyObject(physicalNetworkId.toString(), "physicalNetworkId"); throw ex; } @@ -3219,7 +3219,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { PhysicalNetworkVO destNetwork = _physicalNetworkDao.findById(destinationPhysicalNetworkId); if (destNetwork == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Destination Physical Network with specified id doesn't exist in the system"); - ex.addProxyObject(destNetwork, destinationPhysicalNetworkId, "destinationPhysicalNetworkId"); + ex.addProxyObject(destinationPhysicalNetworkId.toString(), "destinationPhysicalNetworkId"); throw ex; } } @@ -3646,7 +3646,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { PhysicalNetworkVO network = _physicalNetworkDao.findById(physicalNetworkId); if (network == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Physical Network with specified id doesn't exist in the system"); - ex.addProxyObject(network, physicalNetworkId, "physicalNetworkId"); + ex.addProxyObject(physicalNetworkId.toString(), "physicalNetworkId"); throw ex; } @@ -3754,14 +3754,12 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } } - - + private boolean getAllowSubdomainAccessGlobal() { return _allowSubdomainNetworkAccess; } - - + @Override public List> listTrafficTypeImplementor(ListTrafficTypeImplementorsCmd cmd) { String type = cmd.getTrafficType(); @@ -3820,7 +3818,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (pNtwk == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find a physical network" + " having the given id"); - ex.addProxyObject("physical_network", physicalNetworkId, "physicalNetworkId"); + ex.addProxyObject(String.valueOf(physicalNetworkId), "physicalNetworkId"); throw ex; } @@ -3914,7 +3912,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { if (userVm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Virtual mahine id does not exist"); - ex.addProxyObject(userVm, vmId, "vmId"); + ex.addProxyObject(vmId.toString(), "vmId"); throw ex; } _accountMgr.checkAccess(caller, null, true, userVm); diff --git a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java index 4e01cdba183..f9bbf1f25bb 100755 --- a/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java +++ b/server/src/com/cloud/network/lb/LoadBalancingRulesManagerImpl.java @@ -949,7 +949,11 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements UserVm vm = _vmDao.findById(instanceId); if (vm == null || vm.getState() == State.Destroyed || vm.getState() == State.Expunging) { InvalidParameterValueException ex = new InvalidParameterValueException("Invalid instance id specified"); - ex.addProxyObject(vm, instanceId, "instanceId"); + if (vm == null) { + ex.addProxyObject(instanceId.toString(), "instanceId"); + } else { + ex.addProxyObject(vm.getUuid(), "instanceId"); + } throw ex; } @@ -973,7 +977,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (nicInSameNetwork == null) { InvalidParameterValueException ex = new InvalidParameterValueException("VM " + instanceId + " cannot be added because it doesn't belong in the same network."); - ex.addProxyObject(vm, instanceId, "instanceId"); + ex.addProxyObject(vm.getUuid(), "instanceId"); throw ex; } @@ -1026,7 +1030,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (!success) { CloudRuntimeException ex = new CloudRuntimeException("Failed to add specified loadbalancerruleid for vms " + instanceIds); - ex.addProxyObject(loadBalancer, loadBalancerId, "loadBalancerId"); + ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId"); // TBD: Also pack in the instanceIds in the exception using the // right VO object or table name. throw ex; @@ -1077,7 +1081,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements s_logger.warn("Failed to remove load balancer rule id " + loadBalancerId + " for vms " + instanceIds); CloudRuntimeException ex = new CloudRuntimeException( "Failed to remove specified load balancer rule id for vms " + instanceIds); - ex.addProxyObject(loadBalancer, loadBalancerId, "loadBalancerId"); + ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId"); throw ex; } success = true; @@ -1100,7 +1104,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (!success) { CloudRuntimeException ex = new CloudRuntimeException( "Failed to remove specified load balancer rule id for vms " + instanceIds); - ex.addProxyObject(loadBalancer, loadBalancerId, "loadBalancerId"); + ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId"); throw ex; } return success; @@ -1370,12 +1374,17 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (ipAddr == null || !ipAddr.readyToUse()) { InvalidParameterValueException ex = new InvalidParameterValueException( "Unable to create load balancer rule, invalid IP address id specified"); - ex.addProxyObject(ipAddr, sourceIpId, "sourceIpId"); + if (ipAddr == null){ + ex.addProxyObject(String.valueOf(sourceIpId), "sourceIpId"); + } + else{ + ex.addProxyObject(ipAddr.getUuid(), "sourceIpId"); + } throw ex; } else if (ipAddr.isOneToOneNat()) { InvalidParameterValueException ex = new InvalidParameterValueException( "Unable to create load balancer rule; specified sourceip id has static nat enabled"); - ex.addProxyObject(ipAddr, sourceIpId, "sourceIpId"); + ex.addProxyObject(ipAddr.getUuid(), "sourceIpId"); throw ex; } @@ -1386,7 +1395,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (networkId == null) { InvalidParameterValueException ex = new InvalidParameterValueException( "Unable to create load balancer rule ; specified sourceip id is not associated with any network"); - ex.addProxyObject(ipAddr, sourceIpId, "sourceIpId"); + ex.addProxyObject(ipAddr.getUuid(), "sourceIpId"); throw ex; } @@ -1397,7 +1406,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements Purpose.LoadBalancing, FirewallRuleType.User, networkId, null); LoadBalancerVO newRule = new LoadBalancerVO(xId, name, description, - sourceIpId, srcPort, srcPort, algorithm, + sourceIpId, srcPort, destPort, algorithm, networkId, ipAddr.getAllocatedToAccountId(), ipAddr.getAllocatedInDomainId()); // verify rule is supported by Lb provider of the network @@ -1903,6 +1912,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements String name = cmd.getLoadBalancerRuleName(); String keyword = cmd.getKeyword(); Long instanceId = cmd.getVirtualMachineId(); + Long networkId = cmd.getNetworkId(); Map tags = cmd.getTags(); Account caller = UserContext.current().getCaller(); @@ -1923,6 +1933,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); sb.and("name", sb.entity().getName(), SearchCriteria.Op.LIKE); sb.and("sourceIpAddress", sb.entity().getSourceIpAddressId(), SearchCriteria.Op.EQ); + sb.and("networkId", sb.entity().getNetworkId(), SearchCriteria.Op.EQ); if (instanceId != null) { SearchBuilder lbVMSearch = _lb2VmMapDao.createSearchBuilder(); @@ -1981,6 +1992,10 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements sc.setJoinParameters("ipSearch", "zoneId", zoneId); } + if (networkId != null) { + sc.setParameters("networkId", networkId); + } + if (tags != null && !tags.isEmpty()) { int count = 0; sc.setJoinParameters("tagSearch", "resourceType", TaggedResourceType.LoadBalancer.toString()); @@ -2078,7 +2093,7 @@ public class LoadBalancingRulesManagerImpl extends ManagerBase implements if (!_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Lb)) { InvalidParameterValueException ex = new InvalidParameterValueException( "LB service is not supported in specified network id"); - ex.addProxyObject(network, network.getId(), "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index 883455377f4..dd5f99ba574 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -490,10 +490,9 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules "a part of enable static nat"); return false; } - performedIpAssoc = true; } else if (ipAddress.isPortable()) { - s_logger.info("Portable IP " + ipAddress.getUuid() + " is not associated with the network, so" + - "associate IP with the network " + networkId); + s_logger.info("Portable IP " + ipAddress.getUuid() + " is not associated with the network yet " + + " so associate IP with the network " + networkId); try { // check if StaticNat service is enabled in the network _networkModel.checkIpForService(ipAddress, Service.StaticNat, networkId); @@ -504,13 +503,12 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules } // associate portable IP with guest network - _networkMgr.associatePortableIPToGuestNetwork(ipId, networkId, false); + ipAddress = _networkMgr.associatePortableIPToGuestNetwork(ipId, networkId, false); } catch (Exception e) { s_logger.warn("Failed to associate portable id=" + ipId + " to network id=" + networkId + " as " + "a part of enable static nat"); return false; } - performedIpAssoc = true; } } else if (ipAddress.getAssociatedWithNetworkId() != networkId) { if (ipAddress.isPortable()) { @@ -520,14 +518,16 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules // check if portable IP can be transferred across the networks if (_networkMgr.isPortableIpTransferableFromNetwork(ipId, ipAddress.getAssociatedWithNetworkId() )) { try { + // transfer the portable IP and refresh IP details _networkMgr.transferPortableIP(ipId, ipAddress.getAssociatedWithNetworkId(), networkId); + ipAddress = _ipAddressDao.findById(ipId); } catch (Exception e) { s_logger.warn("Failed to associate portable id=" + ipId + " to network id=" + networkId + " as " + "a part of enable static nat"); return false; } } else { - throw new InvalidParameterValueException("Portable IP: " + ipId + " has associated services" + + throw new InvalidParameterValueException("Portable IP: " + ipId + " has associated services " + "in network " + ipAddress.getAssociatedWithNetworkId() + " so can not be transferred to " + " network " + networkId); } @@ -1257,14 +1257,14 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules if (ipAddress.getSystem()) { InvalidParameterValueException ex = new InvalidParameterValueException("Can't disable static nat for system IP address with specified id"); - ex.addProxyObject(ipAddress, ipId, "ipId"); + ex.addProxyObject(ipAddress.getUuid(), "ipId"); throw ex; } Long vmId = ipAddress.getAssociatedWithVmId(); if (vmId == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Specified IP address id is not associated with any vm Id"); - ex.addProxyObject(ipAddress, ipId, "ipId"); + ex.addProxyObject(ipAddress.getUuid(), "ipId"); throw ex; } @@ -1292,7 +1292,7 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules if (!ipAddress.isOneToOneNat()) { InvalidParameterValueException ex = new InvalidParameterValueException("One to one nat is not enabled for the specified ip id"); - ex.addProxyObject(ipAddress, ipId, "ipId"); + ex.addProxyObject(ipAddress.getUuid(), "ipId"); throw ex; } @@ -1353,14 +1353,14 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules if (ip == null || !ip.isOneToOneNat() || ip.getAssociatedWithVmId() == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Source ip address of the specified firewall rule id is not static nat enabled"); - ex.addProxyObject(ruleVO, rule.getId(), "ruleId"); + ex.addProxyObject(ruleVO.getUuid(), "ruleId"); throw ex; } String dstIp = ip.getVmIp(); if (dstIp == null) { InvalidParameterValueException ex = new InvalidParameterValueException("VM ip address of the specified public ip is not set "); - ex.addProxyObject(ruleVO, rule.getId(), "ruleId"); + ex.addProxyObject(ruleVO.getUuid(), "ruleId"); throw ex; } @@ -1432,7 +1432,7 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules Network network = _networkModel.getNetwork(networkId); if (network == null) { CloudRuntimeException ex = new CloudRuntimeException("Unable to find an ip address to map to specified vm id"); - ex.addProxyObject(vm, vm.getId(), "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index 1aab7320fb4..380a95e1882 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -587,7 +587,11 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis if (vpcOff == null || vpcOff.getState() != State.Enabled) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find vpc offering in " + State.Enabled + " state by specified id"); - ex.addProxyObject("vpc_offerings", vpcOffId, "vpcOfferingId"); + if (vpcOff == null) { + ex.addProxyObject(String.valueOf(vpcOffId), "vpcOfferingId"); + } else { + ex.addProxyObject(vpcOff.getUuid(), "vpcOfferingId"); + } throw ex; } @@ -596,7 +600,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) { // See DataCenterVO.java PermissionDeniedException ex = new PermissionDeniedException("Cannot perform this operation since specified Zone is currently disabled"); - ex.addProxyObject("data_center", zone.getId(), "zoneId"); + ex.addProxyObject(zone.getUuid(), "zoneId"); throw ex; } @@ -943,7 +947,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis Vpc vpc = getActiveVpc(vpcId); if (vpc == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC by id specified"); - ex.addProxyObject("vpc", vpcId, "VPC"); + ex.addProxyObject(String.valueOf(vpcId), "VPC"); throw ex; } @@ -1217,9 +1221,18 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis List ipsToRelease = _ipAddressDao.listByAssociatedVpc(vpcId, null); s_logger.debug("Releasing ips for vpc id=" + vpcId + " as a part of vpc cleanup"); for (IPAddressVO ipToRelease : ipsToRelease) { - success = success && _ntwkMgr.disassociatePublicIpAddress(ipToRelease.getId(), callerUserId, caller); - if (!success) { - s_logger.warn("Failed to cleanup ip " + ipToRelease + " as a part of vpc id=" + vpcId + " cleanup"); + if (ipToRelease.isPortable()) { + // portable IP address are associated with owner, until explicitly requested to be disassociated. + // so as part of VPC clean up just break IP association with VPC + ipToRelease.setVpcId(null); + ipToRelease.setAssociatedWithNetworkId(null); + _ipAddressDao.update(ipToRelease.getId(), ipToRelease); + s_logger.debug("Portable IP address " + ipToRelease + " is no longer associated with any VPC"); + } else { + success = success && _ntwkMgr.disassociatePublicIpAddress(ipToRelease.getId(), callerUserId, caller); + if (!success) { + s_logger.warn("Failed to cleanup ip " + ipToRelease + " as a part of vpc id=" + vpcId + " cleanup"); + } } } @@ -1266,7 +1279,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis Vpc vpc = getActiveVpc(vpcId); if (vpc == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC by id specified"); - ex.addProxyObject("vpc", vpcId, "VPC"); + ex.addProxyObject(String.valueOf(vpcId), "VPC"); throw ex; } @@ -1345,7 +1358,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis Vpc vpc = getActiveVpc(vpcId); if (vpc == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC by id specified"); - ex.addProxyObject("vpc", vpcId, "VPC"); + ex.addProxyObject(String.valueOf(vpcId), "VPC"); throw ex; } @@ -2007,7 +2020,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis if (vpc == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find Enabled VPC "); - ex.addProxyObject("vpc", vpcId, "VPC"); + ex.addProxyObject(String.valueOf(vpcId), "VPC"); throw ex; } _accountMgr.checkAccess(caller, null, false, vpc); diff --git a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java index 062743b23af..9e7bb13b867 100755 --- a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java @@ -226,10 +226,10 @@ public class RemoteAccessVpnManagerImpl extends ManagerBase implements RemoteAcc } @Override @DB - public void destroyRemoteAccessVpn(long ipId, Account caller) throws ResourceUnavailableException { + public void destroyRemoteAccessVpnForIp(long ipId, Account caller) throws ResourceUnavailableException { RemoteAccessVpnVO vpn = _remoteAccessVpnDao.findByPublicIpAddress(ipId); if (vpn == null) { - s_logger.debug("vpn id=" + ipId + " does not exists "); + s_logger.debug("there are no Remote access vpns for public ip address id=" + ipId); return; } diff --git a/server/src/com/cloud/projects/ProjectManagerImpl.java b/server/src/com/cloud/projects/ProjectManagerImpl.java index de4f3ccd11b..7ab385f2de4 100755 --- a/server/src/com/cloud/projects/ProjectManagerImpl.java +++ b/server/src/com/cloud/projects/ProjectManagerImpl.java @@ -43,6 +43,7 @@ import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.api.ApiDBUtils; import com.cloud.api.query.dao.ProjectAccountJoinDao; import com.cloud.api.query.dao.ProjectInvitationJoinDao; import com.cloud.api.query.dao.ProjectJoinDao; @@ -50,6 +51,7 @@ import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.Resource.ResourceType; import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.event.ActionEvent; import com.cloud.event.EventTypes; @@ -508,14 +510,14 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { if (project == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find project with specified id"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(String.valueOf(projectId), "projectId"); throw ex; } //User can be added to Active project only if (project.getState() != Project.State.Active) { InvalidParameterValueException ex = new InvalidParameterValueException("Can't add account to the specified project id in state=" + project.getState() + " as it's no longer active"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(project.getUuid(),"projectId"); throw ex; } @@ -525,8 +527,12 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { account = _accountMgr.getActiveAccountByName(accountName, project.getDomainId()); if (account == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find account name=" + accountName + " in specified domain id"); - // We don't have a DomainVO object with us, so just pass the tablename "domain" manually. - ex.addProxyObject("domain", project.getDomainId(), "domainId"); + DomainVO domain = ApiDBUtils.findDomainById(project.getDomainId()); + String domainUuid = String.valueOf(project.getDomainId()); + if ( domain != null ){ + domainUuid = domain.getUuid(); + } + ex.addProxyObject(domainUuid, "domainId"); throw ex; } @@ -590,7 +596,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { if (project == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find project with specified id"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(String.valueOf(projectId), "projectId"); throw ex; } @@ -598,8 +604,12 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { Account account = _accountMgr.getActiveAccountByName(accountName, project.getDomainId()); if (account == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find account name=" + accountName + " in domain id=" + project.getDomainId()); - // Since we don't have a domainVO object, pass the table name manually. - ex.addProxyObject("domain", project.getDomainId(), "domainId"); + DomainVO domain = ApiDBUtils.findDomainById(project.getDomainId()); + String domainUuid = String.valueOf(project.getDomainId()); + if ( domain != null ){ + domainUuid = domain.getUuid(); + } + ex.addProxyObject(domainUuid, "domainId"); } //verify permissions @@ -610,14 +620,14 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { if (projectAccount == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Account " + accountName + " is not assigned to the project with specified id"); // Use the projectVO object and not the projectAccount object to inject the projectId. - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(project.getUuid(), "projectId"); throw ex; } //can't remove the owner of the project if (projectAccount.getAccountRole() == Role.Admin) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to delete account " + accountName + " from the project with specified id as the account is the owner of the project"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(project.getUuid(), "projectId"); throw ex; } @@ -791,7 +801,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { if (project == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find project with specified id"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(String.valueOf(projectId), "projectId"); throw ex; } @@ -833,7 +843,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { //verify input parameters if (project == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find project with specified id"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(String.valueOf(projectId), "projectId"); throw ex; } @@ -844,7 +854,7 @@ public class ProjectManagerImpl extends ManagerBase implements ProjectManager { return _projectDao.findById(projectId); } else { CloudRuntimeException ex = new CloudRuntimeException("Failed to suspend project with specified id"); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(project.getUuid(), "projectId"); throw ex; } diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java b/server/src/com/cloud/resource/ResourceManagerImpl.java index 13b42a5d382..1359e924abf 100755 --- a/server/src/com/cloud/resource/ResourceManagerImpl.java +++ b/server/src/com/cloud/resource/ResourceManagerImpl.java @@ -163,6 +163,7 @@ import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.VirtualMachineManager; import com.cloud.vm.dao.VMInstanceDao; +import com.cloud.dc.DataCenter.NetworkType; @Component @Local({ ResourceManager.class, ResourceService.class }) @@ -395,7 +396,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (zone == null) { InvalidParameterValueException ex = new InvalidParameterValueException( "Can't find zone by the id specified"); - ex.addProxyObject(zone, dcId, "dcId"); + ex.addProxyObject(String.valueOf(dcId), "dcId"); throw ex; } @@ -404,7 +405,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, && !_accountMgr.isRootAdmin(account.getType())) { PermissionDeniedException ex = new PermissionDeniedException( "Cannot perform this operation, Zone with specified id is currently disabled"); - ex.addProxyObject(zone, dcId, "dcId"); + ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } @@ -423,8 +424,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (!Long.valueOf(pod.getDataCenterId()).equals(dcId)) { InvalidParameterValueException ex = new InvalidParameterValueException( "Pod with specified id doesn't belong to the zone " + dcId); - ex.addProxyObject(pod, podId, "podId"); - ex.addProxyObject(zone, dcId, "dcId"); + ex.addProxyObject(pod.getUuid(), "podId"); + ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } @@ -448,6 +449,13 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, + cmd.getHypervisor() + " to a supported "); } + if (zone.isSecurityGroupEnabled() && zone.getNetworkType().equals(NetworkType.Advanced)) { + if (hypervisorType != HypervisorType.KVM && hypervisorType != HypervisorType.XenServer + && hypervisorType != HypervisorType.Simulator) { + throw new InvalidParameterValueException("Don't support hypervisor type " + hypervisorType + " in advanced security enabled zone"); + } + } + Cluster.ClusterType clusterType = null; if (cmd.getClusterType() != null && !cmd.getClusterType().isEmpty()) { clusterType = Cluster.ClusterType.valueOf(cmd.getClusterType()); @@ -502,8 +510,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, "Unable to create cluster " + clusterName + " in pod and data center with specified ids", e); // Get the pod VO object's table name. - ex.addProxyObject(pod, podId, "podId"); - ex.addProxyObject(zone, dcId, "dcId"); + ex.addProxyObject(pod.getUuid(), "podId"); + ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } clusterId = cluster.getId(); @@ -637,7 +645,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (cluster == null) { InvalidParameterValueException ex = new InvalidParameterValueException( "can not find cluster for specified clusterId"); - ex.addProxyObject(cluster, clusterId, "clusterId"); + ex.addProxyObject(clusterId.toString(), "clusterId"); throw ex; } else { if (cluster.getGuid() == null) { @@ -645,7 +653,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, if (!hosts.isEmpty()) { CloudRuntimeException ex = new CloudRuntimeException( "Guid is not updated for cluster with specified cluster id; need to wait for hosts in this cluster to come up"); - ex.addProxyObject(cluster, clusterId, "clusterId"); + ex.addProxyObject(cluster.getUuid(), "clusterId"); throw ex; } } @@ -701,7 +709,7 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, && !_accountMgr.isRootAdmin(account.getType())) { PermissionDeniedException ex = new PermissionDeniedException( "Cannot perform this operation, Zone with specified id is currently disabled"); - ex.addProxyObject(zone, dcId, "dcId"); + ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } @@ -719,8 +727,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, + podId + " doesn't belong to the zone with specified zoneId" + dcId); - ex.addProxyObject(pod, podId, "podId"); - ex.addProxyObject(zone, dcId, "dcId"); + ex.addProxyObject(pod.getUuid(), "podId"); + ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } } @@ -790,8 +798,8 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager, + clusterName + " in pod with specified podId and data center with specified dcID", e); - ex.addProxyObject(pod, podId, "podId"); - ex.addProxyObject(zone, dcId, "dcId"); + ex.addProxyObject(pod.getUuid(), "podId"); + ex.addProxyObject(zone.getUuid(), "dcId"); throw ex; } } diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index bc52e9a881c..35f977b5921 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -36,18 +36,12 @@ import java.util.Map; import java.util.Properties; import java.util.UUID; import java.util.regex.Pattern; -import java.util.StringTokenizer; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.inject.Inject; import javax.naming.ConfigurationException; -import com.cloud.configuration.*; -import com.cloud.dc.*; -import com.cloud.dc.dao.DcDetailsDao; -import com.cloud.user.*; -import com.cloud.utils.db.GenericDao; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailVO; import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; @@ -56,13 +50,25 @@ import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.configuration.Config; +import com.cloud.configuration.ConfigurationVO; +import com.cloud.configuration.Resource; import com.cloud.configuration.Resource.ResourceOwnerType; import com.cloud.configuration.Resource.ResourceType; +import com.cloud.configuration.ResourceCountVO; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.configuration.dao.ResourceCountDao; +import com.cloud.dc.ClusterDetailsDao; +import com.cloud.dc.ClusterDetailsVO; +import com.cloud.dc.ClusterVO; import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.DcDetailVO; +import com.cloud.dc.HostPodVO; +import com.cloud.dc.VlanVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.DcDetailsDao; import com.cloud.dc.dao.HostPodDao; import com.cloud.dc.dao.VlanDao; import com.cloud.domain.DomainVO; @@ -95,6 +101,11 @@ import com.cloud.service.dao.ServiceOfferingDao; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.test.IPRangeConfig; +import com.cloud.user.Account; +import com.cloud.user.AccountDetailVO; +import com.cloud.user.AccountDetailsDao; +import com.cloud.user.AccountVO; +import com.cloud.user.User; import com.cloud.user.dao.AccountDao; import com.cloud.utils.PasswordGenerator; import com.cloud.utils.PropertiesUtil; @@ -106,7 +117,6 @@ import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils; import com.cloud.utils.script.Script; -import com.cloud.uuididentity.dao.IdentityDao; @Component @@ -124,12 +134,10 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio @Inject private DataCenterDao _dataCenterDao; @Inject private NetworkDao _networkDao; @Inject private VlanDao _vlanDao; - private String _domainSuffix; @Inject private DomainDao _domainDao; @Inject private AccountDao _accountDao; @Inject private ResourceCountDao _resourceCountDao; @Inject private NetworkOfferingServiceMapDao _ntwkOfferingServiceMapDao; - @Inject private IdentityDao _identityDao; @Inject private DcDetailsDao _dcDetailsDao; @Inject private ClusterDetailsDao _clusterDetailsDao; @Inject private StoragePoolDetailsDao _storagePoolDetailsDao; @@ -162,9 +170,6 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio // Get init String init = _configDao.getValue("init"); - // Get domain suffix - needed for network creation - _domainSuffix = _configDao.getValue("guest.domain.suffix"); - if (init == null || init.equals("false")) { s_logger.debug("ConfigurationServer is saving default values to the database."); diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index e2f15b4cd16..227b20c0c5d 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -1179,7 +1179,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } InvalidParameterValueException ex = new InvalidParameterValueException("VM is not Running, cannot " + "migrate the vm with specified id"); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } @@ -1200,8 +1200,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } InvalidParameterValueException ex = new InvalidParameterValueException( "Unable to find the host (with specified id) of VM with specified id"); - ex.addProxyObject(srcHost, srcHostId, "hostId"); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(String.valueOf(srcHostId), "hostId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } @@ -1357,7 +1357,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (volume == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find volume with" + " specified id."); - ex.addProxyObject(volume, volumeId, "volumeId"); + ex.addProxyObject(volumeId.toString(), "volumeId"); throw ex; } @@ -1611,8 +1611,12 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe + " in specified domain"); // Since we don't have a DomainVO object here, we directly set // tablename to "domain". - String tablename = "domain"; - ex.addProxyObject(tablename, domainId, "domainId"); + DomainVO domain = ApiDBUtils.findDomainById(domainId); + String domainUuid = domainId.toString(); + if ( domain != null ){ + domainUuid = domain.getUuid(); + } + ex.addProxyObject(domainUuid, "domainId"); throw ex; } else { accountId = account.getId(); @@ -1632,7 +1636,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe Project project = _projectMgr.getProject(projectId); if (project == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find project by id " + projectId); - ex.addProxyObject(project, projectId, "projectId"); + ex.addProxyObject(projectId.toString(), "projectId"); throw ex; } accountId = project.getProjectAccountId(); @@ -1866,14 +1870,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (isIso && template.getFormat() != ImageFormat.ISO) { s_logger.error("Template Id " + templateId + " is not an ISO"); InvalidParameterValueException ex = new InvalidParameterValueException("Specified Template Id is not an ISO"); - ex.addProxyObject(template, templateId, "templateId"); + ex.addProxyObject(template.getUuid(), "templateId"); throw ex; }// If ISO not requested then it shouldn't be an ISO. if (!isIso && template.getFormat() == ImageFormat.ISO) { s_logger.error("Incorrect format of the template id " + templateId); InvalidParameterValueException ex = new InvalidParameterValueException("Incorrect format " + template.getFormat() + " of the specified template id"); - ex.addProxyObject(template, templateId, "templateId"); + ex.addProxyObject(template.getUuid(), "templateId"); throw ex; } } @@ -1977,14 +1981,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe VMTemplateVO template = _templateDao.findById(id); if (template == null || template.getRemoved() != null) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find template/iso with specified id"); - ex.addProxyObject(template, id, "templateId"); + ex.addProxyObject(id.toString(), "templateId"); throw ex; } // Don't allow to modify system template if (id.equals(Long.valueOf(1))) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to update template/iso of specified id"); - ex.addProxyObject(template, id, "templateId"); + ex.addProxyObject(template.getUuid(), "templateId"); throw ex; } @@ -2330,7 +2334,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe DomainVO domain = _domainDao.findById(domainId); if (domain == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find domain with specified domain id"); - ex.addProxyObject(domain, domainId, "domainId"); + ex.addProxyObject(domainId.toString(), "domainId"); throw ex; } else if (domain.getParent() == null && domainName != null) { // check if domain is ROOT domain - and deny to edit it with the new @@ -2354,7 +2358,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (!domains.isEmpty() && !sameDomain) { InvalidParameterValueException ex = new InvalidParameterValueException("Failed to update specified domain id with name '" + domainName + "' since it already exists in the system"); - ex.addProxyObject(domain, domainId, "domainId"); + ex.addProxyObject(domain.getUuid(), "domainId"); throw ex; } } @@ -3258,7 +3262,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(instanceId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm); if (systemVm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find a system vm of specified instanceId"); - ex.addProxyObject(systemVm, instanceId, "instanceId"); + ex.addProxyObject(String.valueOf(instanceId), "instanceId"); throw ex; } return systemVm.getType(); @@ -3270,7 +3274,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(vmId, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm); if (systemVm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a system vm with specified vmId"); - ex.addProxyObject(systemVm, vmId, "vmId"); + ex.addProxyObject(String.valueOf(vmId), "vmId"); throw ex; } @@ -3280,7 +3284,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe return startSecondaryStorageVm(vmId); } else { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find a system vm with specified vmId"); - ex.addProxyObject(systemVm, vmId, "vmId"); + ex.addProxyObject(systemVm.getUuid(), "vmId"); throw ex; } } @@ -3293,7 +3297,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe VMInstanceVO systemVm = _vmInstanceDao.findByIdTypes(id, VirtualMachine.Type.ConsoleProxy, VirtualMachine.Type.SecondaryStorageVm); if (systemVm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a system vm with specified vmId"); - ex.addProxyObject(systemVm, id, "vmId"); + ex.addProxyObject(id.toString(), "vmId"); throw ex; } @@ -3315,7 +3319,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (systemVm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a system vm with specified vmId"); - ex.addProxyObject(systemVm, cmd.getId(), "vmId"); + ex.addProxyObject(cmd.getId().toString(), "vmId"); throw ex; } @@ -3332,7 +3336,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (systemVm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a system vm with specified vmId"); - ex.addProxyObject(systemVm, cmd.getId(), "vmId"); + ex.addProxyObject(cmd.getId().toString(), "vmId"); throw ex; } @@ -3370,7 +3374,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe User user = _accountMgr.getUserIncludingRemoved(userId); if ((user == null) || (user.getRemoved() != null)) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find active user of specified id"); - ex.addProxyObject(user, userId, "userId"); + ex.addProxyObject(String.valueOf(userId), "userId"); throw ex; } @@ -3466,7 +3470,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe VolumeVO volume = _volumeDao.findById(volumeId); if (volume == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find volume with specified volumeId"); - ex.addProxyObject(volume, volumeId, "volumeId"); + ex.addProxyObject(volumeId.toString(), "volumeId"); throw ex; } @@ -3486,7 +3490,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe + ". It should be either detached or the VM should be in stopped state."); PermissionDeniedException ex = new PermissionDeniedException( "Invalid state of the volume with specified ID. It should be either detached or the VM should be in stopped state."); - ex.addProxyObject(volume, volumeId, "volumeId"); + ex.addProxyObject(volume.getUuid(), "volumeId"); throw ex; } @@ -3503,7 +3507,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (!isExtractable && account != null && account.getType() != Account.ACCOUNT_TYPE_ADMIN) { // Global // admins are always allowed to extract PermissionDeniedException ex = new PermissionDeniedException("The volume with specified volumeId is not allowed to be extracted"); - ex.addProxyObject(volume, volumeId, "volumeId"); + ex.addProxyObject(volume.getUuid(), "volumeId"); throw ex; } } @@ -3661,7 +3665,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe InstanceGroupVO group = _vmGroupDao.findById(groupId.longValue()); if (group == null) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find a vm group with specified groupId"); - ex.addProxyObject(group, groupId, "groupId"); + ex.addProxyObject(groupId.toString(), "groupId"); throw ex; } @@ -3867,7 +3871,12 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (s == null) { InvalidParameterValueException ex = new InvalidParameterValueException("A key pair with name '" + cmd.getName() + "' does not exist for account " + owner.getAccountName() + " in specified domain id"); - ex.addProxyObject(owner, owner.getDomainId(), "domainId"); + DomainVO domain = ApiDBUtils.findDomainById(owner.getDomainId()); + String domainUuid = String.valueOf(owner.getDomainId()); + if (domain != null){ + domainUuid = domain.getUuid(); + } + ex.addProxyObject(domainUuid, "domainId"); throw ex; } @@ -3954,7 +3963,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe UserVmVO vm = _userVmDao.findById(cmd.getId()); if (vm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("No VM with specified id found."); - ex.addProxyObject(vm, cmd.getId(), "vmId"); + ex.addProxyObject(cmd.getId().toString(), "vmId"); throw ex; } @@ -3965,7 +3974,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe String password = vm.getDetail("Encrypted.Password"); if (password == null || password.equals("")) { InvalidParameterValueException ex = new InvalidParameterValueException("No password for VM with specified id found."); - ex.addProxyObject(vm, cmd.getId(), "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } @@ -4075,7 +4084,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (hpvCapabilities == null) { InvalidParameterValueException ex = new InvalidParameterValueException("unable to find the hypervisor capabilities for specified id"); - ex.addProxyObject(hpvCapabilities, id, "Id"); + ex.addProxyObject(id.toString(), "Id"); throw ex; } diff --git a/server/src/com/cloud/storage/VolumeManagerImpl.java b/server/src/com/cloud/storage/VolumeManagerImpl.java index d68b6d9ec64..f91c9718832 100644 --- a/server/src/com/cloud/storage/VolumeManagerImpl.java +++ b/server/src/com/cloud/storage/VolumeManagerImpl.java @@ -376,6 +376,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { throws ResourceAllocationException { Account caller = UserContext.current().getCaller(); long ownerId = cmd.getEntityOwnerId(); + Account owner = _accountDao.findById(ownerId); Long zoneId = cmd.getZoneId(); String volumeName = cmd.getVolumeName(); String url = cmd.getUrl(); @@ -385,7 +386,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { validateVolume(caller, ownerId, zoneId, volumeName, url, format); - VolumeVO volume = persistVolume(caller, ownerId, zoneId, volumeName, + VolumeVO volume = persistVolume(owner, zoneId, volumeName, url, cmd.getFormat()); VolumeInfo vol = volFactory.getVolume(volume.getId()); @@ -718,7 +719,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { return UUID.randomUUID().toString(); } - private VolumeVO persistVolume(Account caller, long ownerId, Long zoneId, + private VolumeVO persistVolume(Account owner, Long zoneId, String volumeName, String url, String format) { Transaction txn = Transaction.currentTxn(); @@ -726,20 +727,17 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { VolumeVO volume = new VolumeVO(volumeName, zoneId, -1, -1, -1, new Long(-1), null, null, 0, Volume.Type.DATADISK); - Account owner = (caller.getId() == ownerId) ? caller : _accountMgr - .getActiveAccountById(ownerId); volume.setPoolId(null); volume.setDataCenterId(zoneId); volume.setPodId(null); - volume.setAccountId(ownerId); + volume.setAccountId(owner.getAccountId()); + volume.setDomainId(owner.getDomainId()); long diskOfferingId = _diskOfferingDao.findByUniqueName( "Cloud.com-Custom").getId(); volume.setDiskOfferingId(diskOfferingId); // volume.setSize(size); volume.setInstanceId(null); volume.setUpdated(new Date()); - volume.setDomainId((owner == null) ? Domain.ROOT_DOMAIN : owner - .getDomainId()); volume = _volsDao.persist(volume); try { diff --git a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java index ba74985e9a9..10264d670d0 100755 --- a/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java +++ b/server/src/com/cloud/storage/secondary/SecondaryStorageManagerImpl.java @@ -528,19 +528,27 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar DataCenterDeployment plan = new DataCenterDeployment(dataCenterId); DataCenter dc = _dcDao.findById(plan.getDataCenterId()); + NetworkVO defaultNetwork = null; + if (dc.getNetworkType() == NetworkType.Advanced && dc.isSecurityGroupEnabled()) { + List networks = _networkDao.listByZoneSecurityGroup(dataCenterId); + if (networks == null || networks.size() == 0) { + throw new CloudRuntimeException("Can not found security enabled network in SG Zone " + dc); + } + defaultNetwork = networks.get(0); + } else { TrafficType defaultTrafficType = TrafficType.Public; + if (dc.getNetworkType() == NetworkType.Basic || dc.isSecurityGroupEnabled()) { defaultTrafficType = TrafficType.Guest; } - List defaultNetworks = _networkDao.listByZoneAndTrafficType(dataCenterId, defaultTrafficType); - - //api should never allow this situation to happen + // api should never allow this situation to happen if (defaultNetworks.size() != 1) { - throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + defaultTrafficType + " when expect to find 1"); + throw new CloudRuntimeException("Found " + defaultNetworks.size() + " networks of type " + + defaultTrafficType + " when expect to find 1"); + } + defaultNetwork = defaultNetworks.get(0); } - - NetworkVO defaultNetwork = defaultNetworks.get(0); List offerings = _networkModel.getSystemAccountNetworkOfferings(NetworkOfferingVO.SystemControlNetwork, NetworkOfferingVO.SystemManagementNetwork, NetworkOfferingVO.SystemStorageNetwork); List> networks = new ArrayList>(offerings.size() + 1); diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index 26aae48ba38..92d80ee6cc8 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -1033,12 +1033,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, // Snapshot Name: VMInstancename + volumeName + timeString String timeString = DateUtil.getDateDisplayString(DateUtil.GMT_TIMEZONE, new Date(), DateUtil.YYYYMMDD_FORMAT); - VMInstanceVO vmInstance = _vmDao.findById(volume.getInstanceId()); - String vmDisplayName = "detached"; - if (vmInstance != null) { - vmDisplayName = vmInstance.getHostName(); - } - String snapshotName = vmDisplayName + "_" + volume.getName() + "_" + timeString; + String snapshotName = volume.getUuid() + "_" + timeString; // Create the Snapshot object and save it so we can return it to the // user diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index bc02819925c..daaa6bac06e 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -1553,6 +1553,13 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, accountNames.add(acct.getAccountName()); } } + + // also add the owner if not public + if (!template.isPublicTemplate()) { + Account templateOwner = _accountDao.findById(template.getAccountId()); + accountNames.add(templateOwner.getAccountName()); + } + return accountNames; } diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index b95cc079f2b..89882742053 100755 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -626,7 +626,7 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M try { for (RemoteAccessVpnVO vpn : remoteAccessVpns) { - _remoteAccessVpnMgr.destroyRemoteAccessVpn(vpn.getServerAddressId(), caller); + _remoteAccessVpnMgr.destroyRemoteAccessVpnForIp(vpn.getServerAddressId(), caller); } } catch (ResourceUnavailableException ex) { s_logger.warn("Failed to cleanup remote access vpn resources as a part of account id=" + accountId + " cleanup due to Exception: ", ex); @@ -729,6 +729,14 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M _resourceCountDao.removeEntriesByOwner(accountId, ResourceOwnerType.Account); _resourceLimitDao.removeEntriesByOwner(accountId, ResourceOwnerType.Account); + // release account specific acquired portable IP's. Since all the portable IP's must have been already + // disassociated with VPC/guest network (due to deletion), so just mark portable IP as free. + List portableIpsToRelease = _ipAddressDao.listByAccount(accountId); + for (IpAddress ip : portableIpsToRelease) { + s_logger.debug("Releasing portable ip " + ip + " as a part of account id=" + accountId + " cleanup"); + _networkMgr.releasePortableIpAddress(ip.getId()); + } + return true; } catch (Exception ex) { s_logger.warn("Failed to cleanup account " + account + " due to ", ex); diff --git a/server/src/com/cloud/user/DomainManagerImpl.java b/server/src/com/cloud/user/DomainManagerImpl.java index c451041d951..00a779e2ff9 100644 --- a/server/src/com/cloud/user/DomainManagerImpl.java +++ b/server/src/com/cloud/user/DomainManagerImpl.java @@ -226,7 +226,7 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom if ((cleanup != null) && cleanup.booleanValue()) { if (!cleanupDomain(domain.getId(), ownerId)) { CloudRuntimeException e = new CloudRuntimeException("Failed to clean up domain resources and sub domains, delete failed on domain " + domain.getName() + " (id: " + domain.getId() + ")."); - e.addProxyObject(domain, domain.getId(), "domainId"); + e.addProxyObject(domain.getUuid(), "domainId"); throw e; } } else { @@ -235,13 +235,13 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom if (!_domainDao.remove(domain.getId())) { rollBackState = true; CloudRuntimeException e = new CloudRuntimeException("Delete failed on domain " + domain.getName() + " (id: " + domain.getId() + "); Please make sure all users and sub domains have been removed from the domain before deleting"); - e.addProxyObject(domain, domain.getId(), "domainId"); + e.addProxyObject(domain.getUuid(), "domainId"); throw e; } } else { rollBackState = true; CloudRuntimeException e = new CloudRuntimeException("Can't delete the domain yet because it has " + accountsForCleanup.size() + "accounts that need a cleanup"); - e.addProxyObject(domain, domain.getId(), "domainId"); + e.addProxyObject(domain.getUuid(), "domainId"); throw e; } } @@ -480,7 +480,7 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom DomainVO domain = _domainDao.findById(domainId); if (domain == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find domain with specified domain id"); - ex.addProxyObject(domain, domainId, "domainId"); + ex.addProxyObject(domainId.toString(), "domainId"); throw ex; } else if (domain.getParent() == null && domainName != null) { // check if domain is ROOT domain - and deny to edit it with the new name @@ -501,7 +501,7 @@ public class DomainManagerImpl extends ManagerBase implements DomainManager, Dom if (!domains.isEmpty() && !sameDomain) { InvalidParameterValueException ex = new InvalidParameterValueException("Failed to update specified domain id with name '" + domainName + "' since it already exists in the system"); - ex.addProxyObject(domain, domainId, "domainId"); + ex.addProxyObject(domain.getUuid(), "domainId"); throw ex; } } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 1d5b973da7c..06c1d5d8f33 100755 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -162,6 +162,7 @@ import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.projects.ProjectManager; import com.cloud.resource.ResourceManager; import com.cloud.resource.ResourceState; +import com.cloud.server.ConfigurationServer; import com.cloud.server.Criteria; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; @@ -396,6 +397,8 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use AffinityGroupVMMapDao _affinityGroupVMMapDao; @Inject AffinityGroupDao _affinityGroupDao; + @Inject + ConfigurationServer _configServer; protected ScheduledExecutorService _executor = null; protected int _expungeInterval; @@ -815,6 +818,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } + @Override public UserVm addNicToVirtualMachine(AddNicToVMCmd cmd) throws InvalidParameterValueException, PermissionDeniedException, CloudRuntimeException { Long vmId = cmd.getVmId(); @@ -1108,21 +1112,52 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use //Check if its a scale "up" ServiceOffering newServiceOffering = _configMgr.getServiceOffering(newServiceOfferingId); - ServiceOffering oldServiceOffering = _configMgr.getServiceOffering(vmInstance.getServiceOfferingId()); - if(newServiceOffering.getSpeed() <= oldServiceOffering.getSpeed() - && newServiceOffering.getRamSize() <= oldServiceOffering.getRamSize()){ + ServiceOffering currentServiceOffering = _configMgr.getServiceOffering(vmInstance.getServiceOfferingId()); + int newCpu = newServiceOffering.getCpu(); + int newMemory = newServiceOffering.getRamSize(); + int newSpeed = newServiceOffering.getSpeed(); + int currentCpu = currentServiceOffering.getCpu(); + int currentMemory = currentServiceOffering.getRamSize(); + int currentSpeed = currentServiceOffering.getSpeed(); + + if(newSpeed <= currentSpeed + && newMemory <= currentMemory + && newCpu <= currentCpu){ throw new InvalidParameterValueException("Only scaling up the vm is supported, new service offering should have both cpu and memory greater than the old values"); } + // Check resource limits + if (newCpu > currentCpu) { + _resourceLimitMgr.checkResourceLimit(caller, ResourceType.cpu, + newCpu - currentCpu); + } + if (newMemory > currentMemory) { + _resourceLimitMgr.checkResourceLimit(caller, ResourceType.memory, + newMemory - currentMemory); + } + // Dynamically upgrade the running vms boolean success = false; if(vmInstance.getState().equals(State.Running)){ int retry = _scaleRetry; + boolean enableDynamicallyScaleVm = Boolean.parseBoolean(_configServer.getConfigValue(Config.EnableDynamicallyScaleVm.key(), Config.ConfigurationParameterScope.zone.toString(), vmInstance.getDataCenterId())); + if(!enableDynamicallyScaleVm){ + throw new PermissionDeniedException("Dynamically scaling virtual machines is disabled for this zone, please contact your admin"); + } + + // Increment CPU and Memory count accordingly. + if (newCpu > currentCpu) { + _resourceLimitMgr.incrementResourceCount(caller.getAccountId(), ResourceType.cpu, new Long (newCpu - currentCpu)); + } + if (newMemory > currentMemory) { + _resourceLimitMgr.incrementResourceCount(caller.getAccountId(), ResourceType.memory, new Long (newMemory - currentMemory)); + } + while (retry-- != 0) { // It's != so that it can match -1. try{ // #1 Check existing host has capacity - boolean existingHostHasCapacity = _capacityMgr.checkIfHostHasCapacity(vmInstance.getHostId(), newServiceOffering.getSpeed() - oldServiceOffering.getSpeed(), - (newServiceOffering.getRamSize() - oldServiceOffering.getRamSize()) * 1024L * 1024L, false, ApiDBUtils.getCpuOverprovisioningFactor(), 1f, false); // TO DO fill it with mem. + boolean existingHostHasCapacity = _capacityMgr.checkIfHostHasCapacity(vmInstance.getHostId(), newServiceOffering.getSpeed() - currentServiceOffering.getSpeed(), + (newServiceOffering.getRamSize() - currentServiceOffering.getRamSize()) * 1024L * 1024L, false, ApiDBUtils.getCpuOverprovisioningFactor(), 1f, false); // TO DO fill it with mem. // #2 migrate the vm if host doesn't have capacity if (!existingHostHasCapacity){ @@ -1132,9 +1167,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use // #3 scale the vm now _itMgr.upgradeVmDb(vmId, newServiceOfferingId); vmInstance = _vmInstanceDao.findById(vmId); - _itMgr.reConfigureVm(vmInstance, oldServiceOffering, existingHostHasCapacity); - success = true; - return success; + return _itMgr.reConfigureVm(vmInstance, currentServiceOffering, existingHostHasCapacity); }catch(InsufficientCapacityException e ){ s_logger.warn("Received exception while scaling ",e); } catch (ResourceUnavailableException e) { @@ -1147,8 +1180,17 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use s_logger.warn("Received exception while scaling ",e); }finally{ if(!success){ - _itMgr.upgradeVmDb(vmId, oldServiceOffering.getId()); // rollback + _itMgr.upgradeVmDb(vmId, currentServiceOffering.getId()); // rollback + // Decrement CPU and Memory count accordingly. + if (newCpu > currentCpu) { + _resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.cpu, new Long (newCpu - currentCpu)); } + if (newMemory > currentMemory) { + _resourceLimitMgr.decrementResourceCount(caller.getAccountId(), ResourceType.memory, new Long (newMemory - currentMemory)); + } + } + + } } } @@ -3245,7 +3287,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } catch (CloudException e) { CloudRuntimeException ex = new CloudRuntimeException( "Unable to destroy with specified vmId", e); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } @@ -3272,7 +3314,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } else { CloudRuntimeException ex = new CloudRuntimeException( "Failed to destroy vm with specified vmId"); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } } @@ -3465,7 +3507,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (userVm == null) { InvalidParameterValueException ex = new InvalidParameterValueException( "unable to find a virtual machine with specified id"); - ex.addProxyObject(userVm, vmId, "vmId"); + ex.addProxyObject(String.valueOf(vmId), "vmId"); throw ex; } @@ -3507,7 +3549,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (vm.getState() != State.Stopped) { InvalidParameterValueException ex = new InvalidParameterValueException( "VM is not Stopped, unable to migrate the vm having the specified id"); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } @@ -3584,7 +3626,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } InvalidParameterValueException ex = new InvalidParameterValueException( "VM is not Running, unable to migrate the vm with specified id"); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } if (!vm.getHypervisorType().equals(HypervisorType.XenServer) @@ -3675,7 +3717,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } CloudRuntimeException ex = new CloudRuntimeException("VM is not Running, unable to migrate the vm with" + " specified id"); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } @@ -3804,7 +3846,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } InvalidParameterValueException ex = new InvalidParameterValueException( "VM is Running, unable to move the vm with specified vmId"); - ex.addProxyObject(vm, cmd.getVmId(), "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } @@ -3818,7 +3860,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (oldAccount.getType() == Account.ACCOUNT_TYPE_PROJECT) { InvalidParameterValueException ex = new InvalidParameterValueException( "Specified Vm id belongs to the project and can't be moved"); - ex.addProxyObject(vm, cmd.getVmId(), "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } Account newAccount = _accountService.getActiveAccountByName( @@ -4069,7 +4111,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (network == null) { InvalidParameterValueException ex = new InvalidParameterValueException( "Unable to find specified network id"); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(networkId.toString(), "networkId"); throw ex; } @@ -4082,7 +4124,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (networkOffering.isSystemOnly()) { InvalidParameterValueException ex = new InvalidParameterValueException( "Specified Network id is system only and can't be used for vm deployment"); - ex.addProxyObject(network, networkId, "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } applicableNetworks.add(network); @@ -4133,7 +4175,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use " resources as a part of network provision for persistent network due to ", ex); CloudRuntimeException e = new CloudRuntimeException("Failed to implement network" + " (with specified id) elements and resources as a part of network provision"); - e.addProxyObject(newNetwork, newNetwork.getId(), "networkId"); + e.addProxyObject(newNetwork.getUuid(), "networkId"); throw e; } } @@ -4188,10 +4230,11 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use long vmId = cmd.getVmId(); Long newTemplateId = cmd.getTemplateId(); + UserVmVO vm = _vmDao.findById(vmId); if (vm == null) { InvalidParameterValueException ex = new InvalidParameterValueException("Cannot find VM with ID " + vmId); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(String.valueOf(vmId), "vmId"); throw ex; } @@ -4237,29 +4280,43 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use if (rootVols.isEmpty()) { InvalidParameterValueException ex = new InvalidParameterValueException( "Can not find root volume for VM " + vm.getUuid()); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } VolumeVO root = rootVols.get(0); Long templateId = root.getTemplateId(); + boolean isISO = false; if(templateId == null) { - InvalidParameterValueException ex = new InvalidParameterValueException("Currently there is no support to reset a vm that is deployed using ISO " + vm.getUuid()); - ex.addProxyObject(vm, vmId, "vmId"); - throw ex; + // Assuming that for a vm deployed using ISO, template ID is set to NULL + isISO = true; + templateId = vm.getIsoId(); } VMTemplateVO template = null; + //newTemplateId can be either template or ISO id. In the following snippet based on the vm deployment (from template or ISO) it is handled accordingly if(newTemplateId != null) { template = _templateDao.findById(newTemplateId); _accountMgr.checkAccess(caller, null, true, template); + if (isISO) { + if (!template.getFormat().equals(ImageFormat.ISO)) { + throw new InvalidParameterValueException("Invalid ISO id provided to restore the VM "); + } + } else { + if (template.getFormat().equals(ImageFormat.ISO)) { + throw new InvalidParameterValueException("Invalid template id provided to restore the VM "); + } + } } else { + if (isISO && templateId == null) { + throw new CloudRuntimeException("Cannot restore the VM since there is no ISO attached to VM"); + } template = _templateDao.findById(templateId); if (template == null) { InvalidParameterValueException ex = new InvalidParameterValueException( - "Cannot find template for specified volumeid and vmId"); - ex.addProxyObject(vm, vmId, "vmId"); - ex.addProxyObject(root, root.getId(), "volumeId"); + "Cannot find template/ISO for specified volumeid and vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); + ex.addProxyObject(root.getUuid(), "volumeId"); throw ex; } } @@ -4270,18 +4327,26 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use } catch (CloudRuntimeException e) { s_logger.debug("Stop vm " + vm.getUuid() + " failed"); CloudRuntimeException ex = new CloudRuntimeException("Stop vm failed for specified vmId"); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } } - /* If new template is provided allocate a new volume from new template otherwise allocate new volume from original template */ + /* If new template/ISO is provided allocate a new volume from new template/ISO otherwise allocate new volume from original template/ISO */ VolumeVO newVol = null; - if (newTemplateId != null){ + if (newTemplateId != null) { + if (isISO) { + newVol = volumeMgr.allocateDuplicateVolume(root, null); + vm.setIsoId(newTemplateId); + vm.setGuestOSId(template.getGuestOSId()); + vm.setTemplateId(newTemplateId); + _vmDao.update(vmId, vm); + } else { newVol = volumeMgr.allocateDuplicateVolume(root, newTemplateId); vm.setGuestOSId(template.getGuestOSId()); vm.setTemplateId(newTemplateId); _vmDao.update(vmId, vm); + } } else { newVol = volumeMgr.allocateDuplicateVolume(root, null); } @@ -4323,7 +4388,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use s_logger.debug("Unable to start VM " + vm.getUuid(), e); CloudRuntimeException ex = new CloudRuntimeException( "Unable to start VM with specified id" + e.getMessage()); - ex.addProxyObject(vm, vmId, "vmId"); + ex.addProxyObject(vm.getUuid(), "vmId"); throw ex; } } diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 2501cb4f0a9..037cbf3a2bf 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -382,7 +382,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } if (s_logger.isDebugEnabled()) { - s_logger.debug("Allocaing disks for " + vm); + s_logger.debug("Allocating disks for " + vm); } if (template.getFormat() == ImageFormat.ISO) { diff --git a/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java b/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java index ec0be8c9d96..ac3b8f56e61 100644 --- a/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java +++ b/server/src/org/apache/cloudstack/network/lb/ApplicationLoadBalancerManagerImpl.java @@ -201,7 +201,7 @@ public class ApplicationLoadBalancerManagerImpl extends ManagerBase implements A if (!_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Lb)) { InvalidParameterValueException ex = new InvalidParameterValueException( "LB service is not supported in specified network id"); - ex.addProxyObject(network, network.getId(), "networkId"); + ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java index a1865c64af7..96ac76e3eae 100644 --- a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java @@ -126,7 +126,8 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR throw new InvalidParameterValueException("Invalid region ID: " + regionId); } - if (!region.checkIfServiceEnabled(Region.Service.Gslb)) { + String providerDnsName = _globalConfigDao.getValue(Config.CloudDnsName.key()); + if (!region.checkIfServiceEnabled(Region.Service.Gslb) || (providerDnsName == null)) { throw new CloudRuntimeException("GSLB service is not enabled in region : " + region.getName()); } @@ -203,6 +204,10 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR _accountMgr.checkAccess(caller, null, true, loadBalancer); + if (gslbRule.getAccountId() != loadBalancer.getAccountId()) { + throw new InvalidParameterValueException("GSLB rule and load balancer rule does not belong to same account"); + } + if (loadBalancer.getState() == LoadBalancer.State.Revoke) { throw new InvalidParameterValueException("Load balancer ID " + loadBalancer.getUuid() + " is in revoke state"); } diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java index ed6e224946a..996be88c5c8 100755 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java @@ -507,14 +507,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage return false; } - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#cleanupIpResources(long, long, com.cloud.user.Account) - */ - @Override - public boolean cleanupIpResources(long addrId, long userId, Account caller) { - // TODO Auto-generated method stub - return false; - } /* (non-Javadoc) * @see com.cloud.network.NetworkManager#restartNetwork(java.lang.Long, com.cloud.user.Account, com.cloud.user.User, boolean) @@ -784,15 +776,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage return null; } - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#assignVpnGatewayIpAddress(long, com.cloud.user.Account, long) - */ - @Override - public PublicIp assignVpnGatewayIpAddress(long dcId, Account owner, long vpcId) - throws InsufficientAddressCapacityException, ConcurrentOperationException { - // TODO Auto-generated method stub - return null; - } /* (non-Javadoc) * @see com.cloud.network.NetworkManager#markPublicIpAsAllocated(com.cloud.network.IPAddressVO) @@ -876,7 +859,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } @Override - public boolean releasePortableIpAddress(long ipAddressId) throws InsufficientAddressCapacityException { + public boolean releasePortableIpAddress(long ipAddressId) { return false;// TODO Auto-generated method stub } @@ -928,11 +911,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage return null; } - @Override - public boolean removeVmSecondaryIpsOfNic(long nicId) { - // TODO Auto-generated method stub - return false; - } @Override public NicVO savePlaceholderNic(Network network, String ip4Address, Type vmType) { diff --git a/server/test/com/cloud/vm/UserVmManagerTest.java b/server/test/com/cloud/vm/UserVmManagerTest.java index d47c8e74f82..5c4e5e46443 100755 --- a/server/test/com/cloud/vm/UserVmManagerTest.java +++ b/server/test/com/cloud/vm/UserVmManagerTest.java @@ -24,10 +24,8 @@ import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.times; import java.lang.reflect.Field; import java.util.List; @@ -65,6 +63,7 @@ import com.cloud.storage.VolumeManager; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.Storage.ImageFormat; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.AccountService; @@ -201,6 +200,7 @@ public class UserVmManagerTest { doReturn(false).when(_rootVols).isEmpty(); when(_rootVols.get(eq(0))).thenReturn(_volumeMock); doReturn(3L).when(_volumeMock).getTemplateId(); + doReturn(ImageFormat.VHD).when(_templateMock).getFormat(); when(_templateDao.findById(anyLong())).thenReturn(_templateMock); doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock); // when(_itMgr.stop(null, _userMock, _account)).thenReturn(true); @@ -221,6 +221,40 @@ public class UserVmManagerTest { } + // Test restoreVM on providing new ISO Id, when VM(deployed using ISO) is in running state + @Test + public void testRestoreVMF5() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, + ConcurrentOperationException, ResourceAllocationException { + doReturn(VirtualMachine.State.Running).when(_vmMock).getState(); + when(_vmDao.findById(anyLong())).thenReturn(_vmMock); + when(_volsDao.findByInstanceAndType(314L, Volume.Type.ROOT)).thenReturn(_rootVols); + doReturn(false).when(_rootVols).isEmpty(); + when(_rootVols.get(eq(0))).thenReturn(_volumeMock); + doReturn(null).when(_volumeMock).getTemplateId(); + doReturn(3L).when(_vmMock).getIsoId(); + doReturn(ImageFormat.ISO).when(_templateMock).getFormat(); + when(_templateDao.findById(anyLong())).thenReturn(_templateMock); + doNothing().when(_accountMgr).checkAccess(_account, null, true, _templateMock); + when(_itMgr.stop(_vmMock, _userMock, _account)).thenReturn(true); + when(_storageMgr.allocateDuplicateVolume(_volumeMock, null)).thenReturn(_volumeMock); + doNothing().when(_vmMock).setIsoId(14L); + when(_templateMock.getGuestOSId()).thenReturn(5L); + doNothing().when(_vmMock).setGuestOSId(anyLong()); + doNothing().when(_vmMock).setTemplateId(3L); + when(_vmDao.update(314L, _vmMock)).thenReturn(true); + when(_itMgr.start(_vmMock, null, _userMock, _account)).thenReturn(_vmMock); + when(_storageMgr.allocateDuplicateVolume(_volumeMock, null)).thenReturn(_volumeMock); + doNothing().when(_volsDao).attachVolume(anyLong(), anyLong(), anyLong()); + when(_volumeMock.getId()).thenReturn(3L); + doNothing().when(_volsDao).detachVolume(anyLong()); + + when(_templateMock.getUuid()).thenReturn("b1a3626e-72e0-4697-8c7c-a110940cc55d"); + + _userVmMgr.restoreVMInternal(_account, _vmMock, 14L); + + verify(_vmMock, times(1)).setIsoId(14L); + + } // Test scaleVm on incompatible HV. @Test(expected=InvalidParameterValueException.class) public void testScaleVMF1() throws Exception { diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index 5e0f0541e25..de998feeecd 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -210,7 +210,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } @Override - public boolean releasePortableIpAddress(long ipAddressId) throws InsufficientAddressCapacityException { + public boolean releasePortableIpAddress(long ipAddressId) { return false;// TODO Auto-generated method stub } @@ -1143,9 +1143,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } - - - /* (non-Javadoc) * @see com.cloud.network.NetworkManager#releaseNic(com.cloud.vm.VirtualMachineProfile, com.cloud.vm.Nic) */ @@ -1156,10 +1153,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } - - - - /* (non-Javadoc) * @see com.cloud.network.NetworkManager#createNicForVm(com.cloud.network.Network, com.cloud.vm.NicProfile, com.cloud.vm.ReservationContext, com.cloud.vm.VirtualMachineProfileImpl, boolean, boolean) */ @@ -1173,23 +1166,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } - - - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#assignVpnGatewayIpAddress(long, com.cloud.user.Account, long) - */ - @Override - public PublicIp assignVpnGatewayIpAddress(long dcId, Account owner, long vpcId) - throws InsufficientAddressCapacityException, ConcurrentOperationException { - // TODO Auto-generated method stub - return null; - } - - - - - /* (non-Javadoc) * @see com.cloud.network.NetworkManager#markPublicIpAsAllocated(com.cloud.network.IPAddressVO) */ @@ -1200,9 +1176,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } - - - /* (non-Javadoc) * @see com.cloud.network.NetworkManager#assignDedicateIpAddress(com.cloud.user.Account, java.lang.Long, java.lang.Long, long, boolean) */ @@ -1240,22 +1213,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } - - - - /* (non-Javadoc) - * @see com.cloud.network.NetworkManager#cleanupIpResources(long, long, com.cloud.user.Account) - */ - @Override - public boolean cleanupIpResources(long addrId, long userId, Account caller) { - // TODO Auto-generated method stub - return false; - } - - - - - /* (non-Javadoc) * @see com.cloud.network.NetworkManager#restartNetwork(java.lang.Long, com.cloud.user.Account, com.cloud.user.User, boolean) */ @@ -1435,13 +1392,6 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } - @Override - public boolean removeVmSecondaryIpsOfNic(long nicId) { - // TODO Auto-generated method stub - return false; - } - - @Override public NicVO savePlaceholderNic(Network network, String ip4Address, Type vmType) { // TODO Auto-generated method stub diff --git a/server/test/com/cloud/vpc/NetworkACLServiceTest.java b/server/test/com/cloud/vpc/NetworkACLServiceTest.java index 9a368b94ae4..e71fabfef2d 100644 --- a/server/test/com/cloud/vpc/NetworkACLServiceTest.java +++ b/server/test/com/cloud/vpc/NetworkACLServiceTest.java @@ -138,6 +138,7 @@ public class NetworkACLServiceTest extends TestCase{ Mockito.when(_networkAclMgr.getNetworkACL(Mockito.anyLong())).thenReturn(acl); Mockito.when(_networkAclMgr.createNetworkACLItem(Mockito.anyInt(), Mockito.anyInt(), Mockito.anyString(), Mockito.anyList(), Mockito.anyInt(), Mockito.anyInt(), Mockito.any(NetworkACLItem.TrafficType.class), Mockito.anyLong(), Mockito.anyString(), Mockito.anyInt())).thenReturn(new NetworkACLItemVO()); + Mockito.when(_networkACLItemDao.findByAclAndNumber(Mockito.anyLong(), Mockito.anyInt())).thenReturn(null); assertNotNull(_aclService.createNetworkACLItem(createACLItemCmd)); } diff --git a/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java b/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java index 1c281a08bed..ab545342cfa 100644 --- a/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java +++ b/server/test/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImplTest.java @@ -577,8 +577,14 @@ public class GlobalLoadBalancingRulesServiceImplTest extends TestCase { LoadBalancerVO lbRule1 = new LoadBalancerVO(); lbRule1.setState(FirewallRule.State.Active); Field networkIdField1 = LoadBalancerVO.class.getSuperclass().getDeclaredField("networkId"); + Field accountIdField1 = LoadBalancerVO.class.getSuperclass().getDeclaredField("accountId"); + Field domainIdField1 = LoadBalancerVO.class.getSuperclass().getDeclaredField("domainId"); networkIdField1.setAccessible(true); + accountIdField1.setAccessible(true); + domainIdField1.setAccessible(true); networkIdField1.set(lbRule1, new Long(1)); + accountIdField1.set(lbRule1, new Long(3)); + domainIdField1.set(lbRule1, new Long(1)); Field idField1 = LoadBalancerVO.class.getSuperclass().getDeclaredField("id"); idField1.setAccessible(true); idField1.set(lbRule1, new Long(1)); @@ -586,8 +592,14 @@ public class GlobalLoadBalancingRulesServiceImplTest extends TestCase { LoadBalancerVO lbRule2 = new LoadBalancerVO(); lbRule2.setState(FirewallRule.State.Active); Field networkIdField2 = LoadBalancerVO.class.getSuperclass().getDeclaredField("networkId"); + Field accountIdField2 = LoadBalancerVO.class.getSuperclass().getDeclaredField("accountId"); + Field domainIdField2 = LoadBalancerVO.class.getSuperclass().getDeclaredField("domainId"); networkIdField2.setAccessible(true); + accountIdField2.setAccessible(true); + domainIdField2.setAccessible(true); networkIdField2.set(lbRule2, new Long(1)); + accountIdField2.set(lbRule2, new Long(3)); + domainIdField2.set(lbRule2, new Long(1)); Field idField2 = LoadBalancerVO.class.getSuperclass().getDeclaredField("id"); idField2.setAccessible(true); idField2.set(lbRule2, new Long(2)); @@ -611,6 +623,7 @@ public class GlobalLoadBalancingRulesServiceImplTest extends TestCase { try { gslbServiceImpl.assignToGlobalLoadBalancerRule(assignCmd); } catch (InvalidParameterValueException e) { + s_logger.info(e.getMessage()); Assert.assertTrue(e.getMessage().contains("Load balancer rule specified should be in unique zone")); } } diff --git a/setup/db/db/schema-302to40.sql b/setup/db/db/schema-302to40.sql index f17f067c6ef..832228cb434 100644 --- a/setup/db/db/schema-302to40.sql +++ b/setup/db/db/schema-302to40.sql @@ -114,9 +114,6 @@ UPDATE `cloud`.`configuration` set component='NetworkManager' where name='router UPDATE `cloud`.`configuration` set component='NetworkManager' where name='router.template.id'; UPDATE `cloud`.`configuration` set category='Advanced' where name='capacity.skipcounting.hours'; UPDATE `cloud`.`configuration` set category='Advanced' where name='use.local.storage'; -UPDATE `cloud`.`configuration` set category='Hidden' where name='router.ram.size'; -UPDATE `cloud`.`configuration` set category='Hidden' where name='secondary.storage.vm'; -UPDATE `cloud`.`configuration` set category='Hidden' where name='security.hash.key'; UPDATE `cloud`.`configuration` set description = 'Percentage (as a value between 0 and 1) of local storage utilization above which alerts will be sent about low local storage available.' where name = 'cluster.localStorage.capacity.notificationthreshold'; DELETE FROM `cloud`.`configuration` WHERE name='direct.agent.pool.size'; @@ -134,7 +131,7 @@ ALTER TABLE `cloud`.`account` ADD COLUMN `default_zone_id` bigint unsigned; ALTER TABLE `cloud`.`account` ADD CONSTRAINT `fk_account__default_zone_id` FOREIGN KEY `fk_account__default_zone_id`(`default_zone_id`) REFERENCES `data_center`(`id`) ON DELETE CASCADE; -DELETE FROM `cloud`.`storage_pool_host_ref` WHERE pool_id IN (SELECT id FROM storage_pool WHERE removed IS NOT NULL); +DELETE FROM `cloud`.`storage_pool_host_ref` WHERE pool_id IN (SELECT id FROM `cloud`.`storage_pool` WHERE removed IS NOT NULL); DROP TABLE IF EXISTS `cloud`.`cluster_vsm_map`; DROP TABLE IF EXISTS `cloud`.`virtual_supervisor_module`; @@ -179,14 +176,14 @@ CREATE TABLE `cloud`.`port_profile` ( PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -DELETE FROM `cloud`.`storage_pool_host_ref` WHERE pool_id IN (SELECT id FROM storage_pool WHERE removed IS NOT NULL); +DELETE FROM `cloud`.`storage_pool_host_ref` WHERE pool_id IN (SELECT id FROM `cloud`.`storage_pool` WHERE removed IS NOT NULL); ALTER TABLE `cloud`.`service_offering` MODIFY `nw_rate` smallint(5) unsigned DEFAULT '200' COMMENT 'network rate throttle mbits/s'; -- RBD Primary Storage pool support (commit: 406fd95d87bfcdbb282d65589ab1fb6e9fd0018a) -ALTER TABLE `storage_pool` ADD `user_info` VARCHAR( 255 ) NULL COMMENT 'Authorization information for the storage pool. Used by network filesystems' AFTER `host_address`; +ALTER TABLE `cloud`.`storage_pool` ADD `user_info` VARCHAR( 255 ) NULL COMMENT 'Authorization information for the storage pool. Used by network filesystems' AFTER `host_address`; -- Resource tags (commit: 62d45b9670520a1ee8b520509393d4258c689b50) CREATE TABLE `cloud`.`resource_tags` ( @@ -232,9 +229,9 @@ CREATE TABLE `cloud`.`nicira_nvp_nic_map` ( -- Remove the unique constraint on physical_network_id, provider_name from physical_network_service_providers -- Because the name of this contraint is not set we need this roundabout way -- The key is also used by the foreign key constraint so drop and recreate that one -ALTER TABLE physical_network_service_providers DROP FOREIGN KEY fk_pnetwork_service_providers__physical_network_id; +ALTER TABLE `cloud`.`physical_network_service_providers` DROP FOREIGN KEY fk_pnetwork_service_providers__physical_network_id; -SET @constraintname = (select CONCAT(CONCAT('DROP INDEX ', A.CONSTRAINT_NAME), ' ON physical_network_service_providers' ) +SET @constraintname = (select CONCAT(CONCAT('DROP INDEX ', A.CONSTRAINT_NAME), ' ON cloud.physical_network_service_providers' ) from information_schema.key_column_usage A JOIN information_schema.key_column_usage B ON B.table_name = 'physical_network_service_providers' AND B.COLUMN_NAME = 'provider_name' AND A.COLUMN_NAME ='physical_network_id' AND B.CONSTRAINT_NAME=A.CONSTRAINT_NAME where A.table_name = 'physical_network_service_providers' LIMIT 1); @@ -243,7 +240,7 @@ PREPARE stmt1 FROM @constraintname; EXECUTE stmt1; DEALLOCATE PREPARE stmt1; -AlTER TABLE physical_network_service_providers ADD CONSTRAINT `fk_pnetwork_service_providers__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE; +AlTER TABLE `cloud`.`physical_network_service_providers` ADD CONSTRAINT `fk_pnetwork_service_providers__physical_network_id` FOREIGN KEY (`physical_network_id`) REFERENCES `physical_network`(`id`) ON DELETE CASCADE; UPDATE `cloud`.`configuration` SET description='In second, timeout for creating volume from snapshot' WHERE name='create.volume.from.snapshot.wait'; ALTER TABLE `cloud`.`data_center` ADD COLUMN `is_local_storage_enabled` tinyint NOT NULL DEFAULT 0 COMMENT 'Is local storage offering enabled for this data center; 1: enabled, 0: not'; diff --git a/setup/db/db/schema-40to410.sql b/setup/db/db/schema-40to410.sql index b7b1c7a91dd..f0e8cf31846 100644 --- a/setup/db/db/schema-40to410.sql +++ b/setup/db/db/schema-40to410.sql @@ -184,6 +184,7 @@ UPDATE `cloud`.`alert` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`async_job` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`cluster` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`data_center` set uuid=id WHERE uuid is NULL; +UPDATE `cloud`.`dc_storage_network_ip_range` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`disk_offering` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`domain` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`event` set uuid=id WHERE uuid is NULL; @@ -217,6 +218,7 @@ UPDATE `cloud`.`security_group` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`security_group_rule` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`snapshot_schedule` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`snapshots` set uuid=id WHERE uuid is NULL; +UPDATE `cloud`.`snapshot_policy` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`static_routes` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`storage_pool` set uuid=id WHERE uuid is NULL; UPDATE `cloud`.`swift` set uuid=id WHERE uuid is NULL; @@ -1639,3 +1641,19 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Usage', 'DEFAULT', 'manageme INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (163, UUID(), 10, 'Ubuntu 12.04 (32-bit)'); INSERT IGNORE INTO `cloud`.`guest_os` (id, uuid, category_id, display_name) VALUES (164, UUID(), 10, 'Ubuntu 12.04 (64-bit)'); + +DROP TABLE IF EXISTS `cloud`.`netscaler_pod_ref`; +CREATE TABLE `cloud`.`netscaler_pod_ref` ( + `id` bigint unsigned NOT NULL auto_increment COMMENT 'id', + `external_load_balancer_device_id` bigint unsigned NOT NULL COMMENT 'id of external load balancer device', + `pod_id` bigint unsigned NOT NULL COMMENT 'pod id', + PRIMARY KEY (`id`), + CONSTRAINT `fk_ns_pod_ref__pod_id` FOREIGN KEY (`pod_id`) REFERENCES `cloud`.`host_pod_ref`(`id`) ON DELETE CASCADE, + CONSTRAINT `fk_ns_pod_ref__device_id` FOREIGN KEY (`external_load_balancer_device_id`) REFERENCES `external_load_balancer_devices`(`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'eip.use.multiple.netscalers' , 'false', 'Should be set to true, if there will be multiple NetScaler devices providing EIP service in a zone'); + +UPDATE `cloud`.`configuration` set category='Advanced' where category='Advanced '; +UPDATE `cloud`.`configuration` set category='Hidden' where category='Hidden '; + diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index 19905702252..6517cc4d71d 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -25,8 +25,8 @@ SET foreign_key_checks = 0; ALTER TABLE `cloud`.`hypervisor_capabilities` ADD COLUMN `max_hosts_per_cluster` int unsigned DEFAULT NULL COMMENT 'Max. hosts in cluster supported by hypervisor'; ALTER TABLE `cloud`.`hypervisor_capabilities` ADD COLUMN `storage_motion_supported` int(1) unsigned DEFAULT 0 COMMENT 'Is storage motion supported'; UPDATE `cloud`.`hypervisor_capabilities` SET `max_hosts_per_cluster`=32 WHERE `hypervisor_type`='VMware'; -INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_data_volumes_limit, storage_motion_supported) VALUES ('XenServer', '6.1.0', 50, 1, 13, 1); -INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_hosts_per_cluster) VALUES ('VMware', '5.1', 128, 0, 32); +INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(uuid, hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_data_volumes_limit, storage_motion_supported) VALUES (UUID(), 'XenServer', '6.1.0', 50, 1, 13, 1); +INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(uuid, hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled, max_hosts_per_cluster) VALUES (UUID(), 'VMware', '5.1', 128, 0, 32); DELETE FROM `cloud`.`configuration` where name='vmware.percluster.host.max'; INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'AgentManager', 'xen.nics.max', '7', 'Maximum allowed nics for Vms created on Xen'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Network', 'DEFAULT', 'management-server', 'midonet.apiserver.address', 'http://localhost:8081', 'Specify the address at which the Midonet API server can be contacted (if using Midonet)'); @@ -332,6 +332,8 @@ CREATE TABLE `cloud`.`global_load_balancer_lb_rule_map` ( CONSTRAINT `fk_lb_rule_id` FOREIGN KEY(`lb_rule_id`) REFERENCES `load_balancing_rules`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'cloud.dns.name', null, 'DNS name of the cloud for the GSLB service'); + INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Account Defaults', 'DEFAULT', 'management-server', 'max.account.cpus', '40', 'The default maximum number of cpu cores that can be used for an account'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Account Defaults', 'DEFAULT', 'management-server', 'max.account.memory', '40960', 'The default maximum memory (in MiB) that can be used for an account'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Account Defaults', 'DEFAULT', 'management-server', 'max.account.primary.storage', '200', 'The default maximum primary storage space (in GiB) that can be used for an account'); @@ -348,13 +350,13 @@ ALTER TABLE `cloud`.`remote_access_vpn` ADD COLUMN `uuid` varchar(40) UNIQUE; -- START: support for LXC -INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES ('LXC', 'default', 50, 1); +INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(uuid, hypervisor_type, hypervisor_version, max_guests_limit, security_group_enabled) VALUES (UUID(), 'LXC', 'default', 50, 1); ALTER TABLE `cloud`.`physical_network_traffic_types` ADD COLUMN `lxc_network_label` varchar(255) DEFAULT 'cloudbr0' COMMENT 'The network name label of the physical device dedicated to this traffic on a LXC host'; UPDATE configuration SET value='KVM,XenServer,VMware,BareMetal,Ovm,LXC' WHERE name='hypervisor.list'; -INSERT INTO `cloud`.`vm_template` (id, unique_name, name, public, created, type, hvm, bits, account_id, url, checksum, enable_password, display_text, format, guest_os_id, featured, cross_zones, hypervisor_type) - VALUES (10, 'routing-10', 'SystemVM Template (LXC)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2', '2755de1f9ef2ce4d6f2bee2efbb4da92', 0, 'SystemVM Template (LXC)', 'QCOW2', 15, 0, 1, 'LXC'); +INSERT INTO `cloud`.`vm_template` (id, uuid, unique_name, name, public, created, type, hvm, bits, account_id, url, checksum, enable_password, display_text, format, guest_os_id, featured, cross_zones, hypervisor_type) + VALUES (10, UUID(), 'routing-10', 'SystemVM Template (LXC)', 0, now(), 'SYSTEM', 0, 64, 1, 'http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2', '2755de1f9ef2ce4d6f2bee2efbb4da92', 0, 'SystemVM Template (LXC)', 'QCOW2', 15, 0, 1, 'LXC'); ALTER TABLE `cloud`.`user_vm` MODIFY user_data TEXT(32768); @@ -1026,6 +1028,7 @@ CREATE VIEW `cloud`.`service_offering_view` AS service_offering.default_use, service_offering.vm_type, service_offering.sort_key, + service_offering.is_volatile, service_offering.deployment_planner, domain.id domain_id, domain.uuid domain_uuid, @@ -1040,8 +1043,10 @@ CREATE VIEW `cloud`.`service_offering_view` AS -- Add "default" field to account/user tables ALTER TABLE `cloud`.`account` ADD COLUMN `default` int(1) unsigned NOT NULL DEFAULT '0' COMMENT '1 if account is default'; +ALTER TABLE `cloud_usage`.`account` ADD COLUMN `default` int(1) unsigned NOT NULL DEFAULT '0' COMMENT '1 if account is default'; ALTER TABLE `cloud`.`user` ADD COLUMN `default` int(1) unsigned NOT NULL DEFAULT '0' COMMENT '1 if user is default'; UPDATE `cloud`.`account` SET `cloud`.`account`.`default`=1 WHERE id IN (1,2); +UPDATE `cloud_usage`.`account` SET `default`=1 WHERE id IN (1,2); UPDATE `cloud`.`user` SET `cloud`.`user`.`default`=1 WHERE id IN (1,2); ALTER VIEW `cloud`.`user_view` AS @@ -1774,8 +1779,15 @@ update `cloud`.`vpc_gateways` set network_acl_id = 2; INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'VpcManager', 'blacklisted.routes', NULL, 'Routes that are blacklisted, can not be used for Static Routes creation for the VPC Private Gateway'); +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'enable.dynamic.scale.vm', 'false', 'Enables/Diables dynamically scaling a vm'); + +INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Advanced', 'DEFAULT', 'management-server', 'scale.retry', '2', 'Number of times to retry scaling up the vm'); + +UPDATE `cloud`.`snapshots` set swift_id=null where swift_id=0; + -- Re-enable foreign key checking, at the end of the upgrade path SET foreign_key_checks = 1; - - +UPDATE `cloud`.`snapshot_policy` set uuid=id WHERE uuid is NULL; +#update shared sg enabled network with not null name in Advance Security Group enabled network +UPDATE `cloud`.`networks` set name='Shared SG enabled network', display_text='Shared SG enabled network' WHERE name IS null AND traffic_type='Guest' AND data_center_id IN (select id from data_center where networktype='Advanced' and is_security_group_enabled=1) AND acl_type='Domain'; diff --git a/setup/dev/advancedsg.cfg b/setup/dev/advancedsg.cfg new file mode 100644 index 00000000000..e6922b639e5 --- /dev/null +++ b/setup/dev/advancedsg.cfg @@ -0,0 +1,185 @@ +# 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": "Sandbox-Simulator", + "dns1": "10.147.28.6", + "physical_networks": [ + { + "name": "Sandbox-pnet", + "tags": [ + "cloud-simulator-pnet" + ], + "broadcastdomainrange": "Zone", + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "VirtualRouter" + }, + { + "broadcastdomainrange": "ZONE", + "name": "SecurityGroupProvider" + } + ], + "traffictypes": [ + { + "typ": "Guest" + }, + { + "typ": "Management", + "simulator": "cloud-simulator-mgmt" + } + ], + "isolationmethods": [ + "VLAN" + ] + } + ], + "securitygroupenabled": "true", + "ipranges": [ + { + "startip": "10.147.31.150", + "endip": "10.147.31.159", + "netmask": "255.255.255.0", + "vlan": "31", + "gateway": "10.147.31.1" + } + ], + "networktype": "Advanced", + "pods": [ + { + "endip": "10.147.29.159", + "name": "POD0", + "startip": "10.147.29.150", + "netmask": "255.255.255.0", + "clusters": [ + { + "clustername": "C0", + "hypervisor": "Simulator", + "hosts": [ + { + "username": "root", + "url": "http://simulator0", + "password": "password" + } + ], + "clustertype": "CloudManaged", + "primaryStorages": [ + { + "url": "nfs://10.147.28.6:/export/home/sandbox/primary", + "name": "PS0" + } + ] + } + ], + "gateway": "10.147.29.1" + } + ], + "internaldns1": "10.147.28.6", + "secondaryStorages": [ + { + "url": "nfs://10.147.28.6:/export/home/sandbox/sstor" + } + ] + } + ], + "dbSvr": { + "dbSvr": "localhost", + "passwd": "cloud", + "db": "cloud", + "port": 3306, + "user": "cloud" + }, + "logger": [ + { + "name": "TestClient", + "file": "testclient.log" + }, + { + "name": "TestCase", + "file": "testcase.log" + } + ], + "globalConfig": [ + { + "name": "storage.cleanup.interval", + "value": "300" + }, + { + "name": "direct.agent.load.size", + "value": "1000" + }, + { + "name": "default.page.size", + "value": "10000" + }, + { + "name": "instance.name", + "value": "QA" + }, + { + "name": "workers", + "value": "10" + }, + { + "name": "vm.op.wait.interval", + "value": "5" + }, + { + "name": "account.cleanup.interval", + "value": "600" + }, + { + "name": "guest.domain.suffix", + "value": "sandbox.simulator" + }, + { + "name": "expunge.delay", + "value": "60" + }, + { + "name": "vm.allocation.algorithm", + "value": "random" + }, + { + "name": "expunge.interval", + "value": "60" + }, + { + "name": "expunge.workers", + "value": "3" + }, + { + "name": "secstorage.allowed.internal.sites", + "value": "10.147.28.0/24" + }, + { + "name": "check.pod.cidrs", + "value": "true" + } + ], + "mgtSvr": [ + { + "mgtSvrIp": "localhost", + "passwd": "password", + "user": "root", + "port": 8096 + } + ] +} diff --git a/test/integration/component/test_advancedsg_networks.py b/test/integration/component/test_advancedsg_networks.py new file mode 100644 index 00000000000..e24254d4b90 --- /dev/null +++ b/test/integration/component/test_advancedsg_networks.py @@ -0,0 +1,753 @@ +# 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. + +""" P1 tests for networks in advanced zone with security groups +""" +#Import Local Modules +import marvin +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime +import netaddr + +class Services: + """ Test networks in advanced zone with security groups""" + + def __init__(self): + self.services = { + "domain": { + "name": "DOM", + }, + "project": { + "name": "Project", + "displaytext": "Test project", + }, + "account": { + "email": "admin-XABU1@test.com", + "firstname": "admin-XABU1", + "lastname": "admin-XABU1", + "username": "admin-XABU1", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "shared_network_offering_sg": { + "name": 'MySharedOffering-sg', + "displaytext": 'MySharedOffering-sg', + "guestiptype": 'Shared', + "supportedservices": 'Dhcp,Dns,UserData,SecurityGroup', + "specifyVlan" : "False", + "specifyIpRanges" : "False", + "traffictype": 'GUEST', + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "UserData": 'VirtualRouter', + "SecurityGroup": 'SecurityGroupProvider' + }, + }, + "shared_network_offering": { + "name": 'MySharedOffering', + "displaytext": 'MySharedOffering', + "guestiptype": 'Shared', + "supportedservices": 'Dhcp,Dns,UserData', + "specifyVlan" : "False", + "specifyIpRanges" : "False", + "traffictype": 'GUEST', + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "UserData": 'VirtualRouter' + }, + }, + "shared_network_sg": { + "name": "MyIsolatedNetwork - Test", + "displaytext": "MyIsolatedNetwork", + "networkofferingid":"1", + "vlan" :1200, + "gateway" :"172.16.15.1", + "netmask" :"255.255.255.0", + "startip" :"172.16.15.2", + "endip" :"172.16.15.20", + "acltype" : "Domain", + "scope":"all", + }, + "shared_network": { + "name": "MySharedNetwork - Test", + "displaytext": "MySharedNetwork", + "vlan" :1201, + "gateway" :"172.16.15.1", + "netmask" :"255.255.255.0", + "startip" :"172.16.15.21", + "endip" :"172.16.15.41", + "acltype" : "Domain", + "scope":"all", + }, + "isolated_network_offering": { + "name": 'Network offering-DA services', + "displaytext": 'Network offering-DA services', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList": { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'VirtualRouter', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "isolated_network": { + "name": "Isolated Network", + "displaytext": "Isolated Network", + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 90, + "timeout": 10, + "mode": 'advanced', + "securitygroupenabled": 'true' + } + +class TestNetworksInAdvancedSG(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestSharedNetworks, + cls + ).getClsTestClient().getApiClient() + + cls.services = Services().services + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + + cls._cleanup = [ + cls.service_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.api_client = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + self.cleanup_networks = [] + self.cleanup_accounts = [] + self.cleanup_domains = [] + self.cleanup_projects = [] + self.cleanup_vms = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.api_client, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + #below components is not a part of cleanup because to mandate the order and to cleanup network + try: + for vm in self.cleanup_vms: + vm.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during virtual machines cleanup : %s" % e) + + try: + for project in self.cleanup_projects: + project.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during project cleanup : %s" % e) + + try: + for account in self.cleanup_accounts: + account.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during account cleanup : %s" % e) + + try: + for domain in self.cleanup_domains: + domain.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during domain cleanup : %s" % e) + + #Wait till all resources created are cleaned up completely and then attempt to delete Network + time.sleep(self.services["sleep"]) + + try: + for network in self.cleanup_networks: + network.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during network cleanup : %s" % e) + return + + def test_createIsolatedNetwork(self): + """ Test Isolated Network """ + + # Steps, + # 1. create an Admin Account - admin-XABU1 + # 2. listPhysicalNetworks in available zone + # 3. createNetworkOffering: + # 4. Enable network offering - updateNetworkOffering - state=Enabled + # 5. createNetwork + # Validations, + # 1. listAccounts name=admin-XABU1, state=enabled returns your account + # 2. listPhysicalNetworks should return at least one active physical network + # 4. listNetworkOfferings - name=myisolatedoffering, should list enabled offering + # 5. network creation should FAIL since isolated network is not supported in advanced zone with security groups. + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin type account created: %s" % self.admin_account.name) + + #Create an user account + self.user_account = Account.create( + self.api_client, + self.services["account"], + admin=False, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.user_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.user_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The user account created is not enabled." + ) + + self.debug("User type account created: %s" % self.user_account.name) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical network found: %s" % physical_network.id) + + #Create Network Offering + self.isolated_network_offering = NetworkOffering.create( + self.api_client, + self.services["isolated_network_offering"], + conservemode=False + ) + + self.cleanup.append(self.isolated_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.isolated_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Isolated Network offering created: %s" % self.isolated_network_offering.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.isolated_network_offering, + self.api_client, + id=self.isolated_network_offering.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.isolated_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + #create network using the isolated network offering created + try: + self.isolated_network = Network.create( + self.api_client, + self.services["isolated_network"], + networkofferingid=self.isolated_network_offering.id, + zoneid=self.zone.id, + ) + self.cleanup_networks.append(self.isolated_network) + self.fail("Create isolated network is invalid in advanced zone with security groups.") + except Exception as e: + self.debug("Network creation failed because create isolated network is invalid in advanced zone with security groups.") + + def test_createSharedNetwork_withoutSG(self): + """ Test Shared Network with used vlan 01 """ + + # Steps, + # 1. create an Admin account + # 2. create a shared NetworkOffering + # 3. enable the network offering + # 4. listPhysicalNetworks + # 5. createNetwork + # Validations, + # 1. listAccounts state=enabled returns your account + # 2. listNetworkOfferings - name=mysharedoffering , should list offering in disabled state + # 3. listNetworkOfferings - name=mysharedoffering, should list enabled offering + # 4. listPhysicalNetworks should return at least one active physical network + # 5. network creation should FAIL since there is no SecurityProvide in the network offering + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Domain admin account created: %s" % self.admin_account.account.id) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical Network found: %s" % physical_network.id) + + self.services["shared_network_offering"]["specifyVlan"] = "True" + self.services["shared_network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["shared_network_offering"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Shared Network Offering created: %s" % self.shared_network_offering.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering, + self.api_client, + id=self.shared_network_offering.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + #create network using the shared network offering created + self.services["shared_network"]["acltype"] = "domain" + self.services["shared_network"]["networkofferingid"] = self.shared_network_offering.id + self.services["shared_network"]["physicalnetworkid"] = physical_network.id + + try: + self.shared_network = Network.create( + self.api_client, + self.services["shared_network"], + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id + ) + self.cleanup_networks.append(self.shared_network) + self.fail("Network created without SecurityProvider , which is invalid") + except Exception as e: + self.debug("Network creation failed because there is no SecurityProvider in the network offering.") + + def test_deployVM_SharedwithSG(self): + """ Test VM deployment in shared networks with SecurityProvider """ + + # Steps, + # 0. create a user account + # 1. Create one shared Network (scope=ALL, different IP ranges) + # 2. deployVirtualMachine in the above networkid within the user account + # 3. delete the user account + # Validations, + # 1. shared network should be created successfully + # 2. VM should deploy successfully + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + liistall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin type account created: %s" % self.admin_account.name) + + self.services["shared_network_offering_sg"]["specifyVlan"] = "True" + self.services["shared_network_offering_sg"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering_sg = NetworkOffering.create( + self.api_client, + self.services["shared_network_offering_sg"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering_sg) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering_sg.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Shared Network offering created: %s" % self.shared_network_offering_sg.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering_sg, + self.api_client, + id=self.shared_network_offering_sg.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering_sg.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + physical_network = list_physical_networks_response[0] + + #create network using the shared network offering created + self.services["shared_network_sg"]["acltype"] = "domain" + self.services["shared_network_sg"]["networkofferingid"] = self.shared_network_offering_sg.id + self.services["shared_network_sg"]["physicalnetworkid"] = physical_network.id + self.shared_network_sg = Network.create( + self.api_client, + self.services["shared_network_sg"], + domainid=self.admin_account.account.domainid, + networkofferingid=self.shared_network_offering_sg.id, + zoneid=self.zone.id + ) + + self.cleanup_networks.append(self.shared_network_sg) + + list_networks_response = Network.list( + self.api_client, + id=self.shared_network_sg.id + ) + self.assertEqual( + isinstance(list_networks_response, list), + True, + "listNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_networks_response), + 0, + "listNetworks returned empty list." + ) + self.assertEqual( + list_networks_response[0].specifyipranges, + True, + "The network is created with ip range but the flag is set to False." + ) + + self.debug("Shared Network created: %s" % self.shared_network_sg.id) + + self.shared_network_admin_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.admin_account.name, + domainid=self.admin_account.account.domainid, + networkids=self.shared_network_sg.id, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.api_client, + id=self.shared_network_admin_account_virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + self.debug("Virtual Machine created: %s" % self.shared_network_admin_account_virtual_machine.id) + + ip_range = list(netaddr.iter_iprange(unicode(self.services["shared_network_sg"]["startip"]), unicode(self.services["shared_network_sg"]["endip"]))) + if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: + self.fail("Virtual machine ip should be from the ip range assigned to network created.") + diff --git a/test/integration/component/test_custom_hostname.py b/test/integration/component/test_custom_hostname.py index e5452141d9c..a85f619fc00 100644 --- a/test/integration/component/test_custom_hostname.py +++ b/test/integration/component/test_custom_hostname.py @@ -104,7 +104,7 @@ class TestInstanceNameFlagTrue(cloudstackTestCase): cls.services = Services().services # Get Zone, default template cls.zone = get_zone(cls.api_client, cls.services) - cls.services["mode"] = cls.zone.networktype + cls.services["mode"] = cls.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/component/test_egress_rules.py b/test/integration/component/test_egress_rules.py index 872ca2c7b5d..607bac86325 100644 --- a/test/integration/component/test_egress_rules.py +++ b/test/integration/component/test_egress_rules.py @@ -194,7 +194,7 @@ class TestDefaultSecurityGroupEgress(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_deployVM_InDefaultSecurityGroup(self): """Test deploy VM in default security group with no egress rules """ @@ -351,7 +351,7 @@ class TestAuthorizeIngressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_authorizeIngressRule(self): """Test authorize ingress rule """ @@ -509,7 +509,7 @@ class TestDefaultGroupEgress(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_default_group_with_egress(self): """Test default group with egress rule before VM deploy and ping, ssh """ @@ -710,7 +710,7 @@ class TestDefaultGroupEgressAfterDeploy(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_default_group_with_egress(self): """ Test default group with egress rule added after vm deploy and ping, ssh test @@ -893,7 +893,7 @@ class TestRevokeEgressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_revoke_egress_rule(self): """Test revoke security group egress rule """ @@ -1155,7 +1155,7 @@ class TestInvalidAccountAuthroize(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_invalid_account_authroize(self): """Test invalid account authroize """ @@ -1283,7 +1283,7 @@ class TestMultipleAccountsEgressRuleNeg(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_multiple_account_egress_rule_negative(self): """Test multiple account egress rules negative case """ @@ -1531,7 +1531,7 @@ class TestMultipleAccountsEgressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_multiple_account_egress_rule_positive(self): """Test multiple account egress rules positive case """ @@ -1822,7 +1822,7 @@ class TestStartStopVMWithEgressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_start_stop_vm_egress(self): """ Test stop start Vm with egress rules """ @@ -2034,7 +2034,7 @@ class TestInvalidParametersForEgress(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_invalid_parameters(self): """ Test invalid parameters for egress rules """ diff --git a/test/integration/component/test_high_availability.py b/test/integration/component/test_high_availability.py index cd2dfcea559..7b0f78e2446 100644 --- a/test/integration/component/test_high_availability.py +++ b/test/integration/component/test_high_availability.py @@ -169,7 +169,6 @@ class TestHighAvailability(cloudstackTestCase): try: #Clean up, terminate the created accounts, domains etc cleanup_resources(self.apiclient, self.cleanup) - self.testClient.close() except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) return diff --git a/test/integration/component/test_host_high_availability.py b/test/integration/component/test_host_high_availability.py index 8c66d175dd7..57eb5edede9 100644 --- a/test/integration/component/test_host_high_availability.py +++ b/test/integration/component/test_host_high_availability.py @@ -18,15 +18,12 @@ """ P1 tests for dedicated Host high availability """ #Import Local Modules -import marvin from nose.plugins.attrib import attr from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * from marvin.integration.lib.utils import * from marvin.integration.lib.base import * from marvin.integration.lib.common import * -from marvin import remoteSSHClient -import datetime class Services: @@ -34,90 +31,90 @@ class Services: def __init__(self): self.services = { - "account": { - "email": "test@test.com", - "firstname": "HA", - "lastname": "HA", - "username": "HA", - # Random characters are appended for unique - # username - "password": "password", - }, - "service_offering_with_ha": { - "name": "Tiny Instance With HA Enabled", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 100, # in MHz - "memory": 128, # In MBs - }, - "service_offering_without_ha": { - "name": "Tiny Instance Without HA", - "displaytext": "Tiny Instance", - "cpunumber": 1, - "cpuspeed": 100, # in MHz - "memory": 128, # In MBs - }, - "virtual_machine": { - "displayname": "VM", - "username": "root", - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - # Hypervisor type should be same as - # hypervisor type of cluster - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "ostype": 'CentOS 5.3 (64-bit)', - "timeout": 100, - } + "account": { + "email": "test@test.com", + "firstname": "HA", + "lastname": "HA", + "username": "HA", + # Random characters are appended for unique + # username + "password": "password", + }, + "service_offering_with_ha": { + "name": "Tiny Instance With HA Enabled", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "service_offering_without_ha": { + "name": "Tiny Instance Without HA", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "virtual_machine": { + "displayname": "VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + "timeout": 100, + } + class TestHostHighAvailability(cloudstackTestCase): """ Dedicated host HA test cases """ - + @classmethod def setUpClass(cls): - cls.api_client = super( - TestHostHighAvailability, - cls - ).getClsTestClient().getApiClient() + TestHostHighAvailability, + cls + ).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain( - cls.api_client, - cls.services - ) + cls.api_client, + cls.services + ) cls.zone = get_zone( - cls.api_client, - cls.services - ) + cls.api_client, + cls.services + ) cls.template = get_template( - cls.api_client, - cls.zone.id, - cls.services["ostype"] - ) + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.services["virtual_machine"]["template"] = cls.template.id cls.service_offering_with_ha = ServiceOffering.create( - cls.api_client, - cls.services["service_offering_with_ha"], - offerha=True - ) - + cls.api_client, + cls.services["service_offering_with_ha"], + offerha=True + ) + cls.service_offering_without_ha = ServiceOffering.create( - cls.api_client, - cls.services["service_offering_without_ha"], - offerha=False - ) - + cls.api_client, + cls.services["service_offering_without_ha"], + offerha=False + ) + cls._cleanup = [ - cls.service_offering_with_ha, - cls.service_offering_without_ha, - ] + cls.service_offering_with_ha, + cls.service_offering_without_ha, + ] return @classmethod @@ -133,11 +130,11 @@ class TestHostHighAvailability(cloudstackTestCase): self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() self.account = Account.create( - self.apiclient, - self.services["account"], - admin=True, - domainid=self.domain.id - ) + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) self.cleanup = [self.account] return @@ -150,76 +147,76 @@ class TestHostHighAvailability(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(configuration = "ha.tag") - @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator"]) + @attr(configuration="ha.tag") + @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator"]) def test_01_vm_deployment_with_compute_offering_with_ha_enabled(self): """ Test VM deployments (Create HA enabled Compute Service Offering and VM) """ - + # Steps, - #1. Create a Compute service offering with the “Offer HA” option selected. + #1. Create a Compute service offering with the 'Offer HA' option selected. #2. Create a Guest VM with the compute service offering created above. # Validations, - #1. Ensure that the offering is created and that in the UI the “Offer HA” field is enabled (Yes) - #The listServiceOffering API should list “offerha” as true. + #1. Ensure that the offering is created and that in the UI the 'Offer HA' field is enabled (Yes) + #The listServiceOffering API should list 'offerha' as true. #2. Select the newly created VM and ensure that the Compute offering field value lists the compute service offering that was selected. - # Also, check that the HA Enabled field is enabled “Yes”. - + # Also, check that the HA Enabled field is enabled 'Yes'. + #list and validate above created service offering with Ha enabled list_service_response = list_service_offering( - self.apiclient, - id=self.service_offering_with_ha.id - ) + self.apiclient, + id=self.service_offering_with_ha.id + ) self.assertEqual( isinstance(list_service_response, list), True, "listServiceOfferings returned invalid object in response." - ) + ) self.assertNotEqual( len(list_service_response), 0, "listServiceOfferings returned empty list." - ) + ) self.assertEqual( list_service_response[0].offerha, True, "The service offering is not HA enabled" - ) - + ) + #create virtual machine with the service offering with Ha enabled virtual_machine = VirtualMachine.create( - self.apiclient, - self.services["virtual_machine"], - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering_with_ha.id - ) + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_with_ha.id + ) vms = VirtualMachine.list( - self.apiclient, - id=virtual_machine.id, - listall=True - ) + self.apiclient, + id=virtual_machine.id, + listall=True + ) self.assertEqual( isinstance(vms, list), True, "listVirtualMachines returned invalid object in response." - ) + ) self.assertNotEqual( len(vms), 0, "listVirtualMachines returned empty list." - ) + ) self.debug("Deployed VM on host: %s" % vms[0].hostid) self.assertEqual( vms[0].haenable, True, "VM not created with HA enable tag" - ) + ) - @attr(configuration = "ha.tag") - @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) + @attr(configuration="ha.tag") + @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) def test_02_no_vm_creation_on_host_with_haenabled(self): """ Verify you can not create new VMs on hosts with an ha.tag """ - + # Steps, #1. Fresh install CS (Bonita) that supports this feature #2. Create Basic zone, pod, cluster, add 3 hosts to cluster (host1, host2, host3), secondary & primary Storage @@ -229,184 +226,184 @@ class TestHostHighAvailability(cloudstackTestCase): # Validations, #Check to make sure the newly created VM is not on any HA enabled hosts #The VM should be created only on host1 or host2 and never host3 (HA enabled) - + #create and verify virtual machine with HA enabled service offering virtual_machine_with_ha = VirtualMachine.create( - self.apiclient, - self.services["virtual_machine"], - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering_with_ha.id - ) - + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_with_ha.id + ) + vms = VirtualMachine.list( - self.apiclient, - id=virtual_machine_with_ha.id, - listall=True - ) - + self.apiclient, + id=virtual_machine_with_ha.id, + listall=True + ) + self.assertEqual( isinstance(vms, list), True, "listVirtualMachines returned invalid object in response." - ) - + ) + self.assertNotEqual( len(vms), 0, "listVirtualMachines returned empty list." - ) - + ) + vm = vms[0] - + self.debug("Deployed VM on host: %s" % vm.hostid) - + #validate the virtual machine created is host Ha enabled list_hosts_response = list_hosts( - self.apiclient, - id=vm.hostid - ) + self.apiclient, + id=vm.hostid + ) self.assertEqual( isinstance(list_hosts_response, list), True, "listHosts returned invalid object in response." - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "listHosts retuned empty list in response." - ) - + ) + self.assertEqual( list_hosts_response[0].hahost, False, "VM created on HA enabled host." - ) - + ) + #create and verify virtual machine with Ha disabled service offering virtual_machine_without_ha = VirtualMachine.create( - self.apiclient, - self.services["virtual_machine"], - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering_without_ha.id - ) - + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_without_ha.id + ) + vms = VirtualMachine.list( - self.apiclient, - id=virtual_machine_without_ha.id, - listall=True - ) - + self.apiclient, + id=virtual_machine_without_ha.id, + listall=True + ) + self.assertEqual( isinstance(vms, list), True, "listVirtualMachines returned invalid object in response." - ) - + ) + self.assertNotEqual( len(vms), 0, "listVirtualMachines returned empty list." - ) - + ) + vm = vms[0] - + self.debug("Deployed VM on host: %s" % vm.hostid) - + #verify that the virtual machine created on the host is Ha disabled list_hosts_response = list_hosts( - self.apiclient, - id=vm.hostid - ) + self.apiclient, + id=vm.hostid + ) self.assertEqual( isinstance(list_hosts_response, list), True, "listHosts returned invalid object in response." - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "listHosts returned empty list." - ) - + ) + host = list_hosts_response[0] - + self.assertEqual( host.hahost, False, "VM migrated to HA enabled host." - ) + ) - @attr(configuration = "ha.tag") - @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) + @attr(configuration="ha.tag") + @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) def test_03_cant_migrate_vm_to_host_with_ha_positive(self): """ Verify you can not migrate VMs to hosts with an ha.tag (positive) """ - + # Steps, - #1. Create a Compute service offering with the “Offer HA” option selected. + #1. Create a Compute service offering with the 'Offer HA' option selected. #2. Create a Guest VM with the compute service offering created above. - #3. Select the VM and migrate VM to another host. Choose a “Suitable” host (i.e. host2) + #3. Select the VM and migrate VM to another host. Choose a 'Suitable' host (i.e. host2) # Validations - #The option from the “Migrate instance to another host” dialog box” should list host3 as “Not Suitable” for migration. - #Confirm that the VM is migrated to the “Suitable” host you selected (i.e. host2) - + #The option from the 'Migrate instance to another host' dialog box' should list host3 as 'Not Suitable' for migration. + #Confirm that the VM is migrated to the 'Suitable' host you selected (i.e. host2) + #create and verify the virtual machine with HA enabled service offering virtual_machine_with_ha = VirtualMachine.create( - self.apiclient, - self.services["virtual_machine"], - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering_with_ha.id - ) - + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_with_ha.id + ) + vms = VirtualMachine.list( - self.apiclient, - id=virtual_machine_with_ha.id, - listall=True, - ) - + self.apiclient, + id=virtual_machine_with_ha.id, + listall=True, + ) + self.assertEqual( isinstance(vms, list), True, "List VMs should return valid response for deployed VM" - ) - + ) + self.assertNotEqual( len(vms), 0, "List VMs should return valid response for deployed VM" - ) - + ) + vm = vms[0] - + self.debug("Deployed VM on host: %s" % vm.hostid) - + #Find out a Suitable host for VM migration list_hosts_response = list_hosts( - self.apiclient, - ) + self.apiclient, + ) self.assertEqual( isinstance(list_hosts_response, list), True, "The listHosts API returned the invalid list" - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "The listHosts returned nothing." - ) + ) suitableHost = None for host in list_hosts_response: if host.suitableformigration == True and host.hostid != vm.hostid: suitableHost = host break - + self.assertTrue(suitableHost is not None, "suitablehost should not be None") - + #Migration of the VM to a suitable host self.debug("Migrating VM-ID: %s to Host: %s" % (self.vm.id, suitableHost.id)) @@ -417,20 +414,20 @@ class TestHostHighAvailability(cloudstackTestCase): #Verify that the VM migrated to a targeted Suitable host list_vm_response = list_virtual_machines( - self.apiclient, - id=vm.id - ) + self.apiclient, + id=vm.id + ) self.assertEqual( isinstance(list_vm_response, list), True, "The listVirtualMachines returned the invalid list." - ) + ) self.assertNotEqual( list_vm_response, None, "The listVirtualMachines API returned nothing." - ) + ) vm_response = list_vm_response[0] @@ -438,82 +435,82 @@ class TestHostHighAvailability(cloudstackTestCase): vm_response.id, vm.id, "The virtual machine id and the the virtual machine from listVirtualMachines is not matching." - ) + ) self.assertEqual( vm_response.hostid, suitableHost.id, "The VM is not migrated to targeted suitable host." - ) - - @attr(configuration = "ha.tag") - @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) + ) + + @attr(configuration="ha.tag") + @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) def test_04_cant_migrate_vm_to_host_with_ha_negative(self): """ Verify you can not migrate VMs to hosts with an ha.tag (negative) """ - + # Steps, - #1. Create a Compute service offering with the “Offer HA” option selected. + #1. Create a Compute service offering with the 'Offer HA' option selected. #2. Create a Guest VM with the compute service offering created above. - #3. Select the VM and migrate VM to another host. Choose a “Not Suitable” host. + #3. Select the VM and migrate VM to another host. Choose a 'Not Suitable' host. # Validations, - #The option from the “Migrate instance to another host” dialog box” should list host3 as “Not Suitable” for migration. + #The option from the 'Migrate instance to another host' dialog box should list host3 as 'Not Suitable' for migration. #By design, The Guest VM can STILL can be migrated to host3 if the admin chooses to do so. - + #create and verify virtual machine with HA enabled service offering virtual_machine_with_ha = VirtualMachine.create( - self.apiclient, - self.services["virtual_machine"], - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering_with_ha.id - ) - + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_with_ha.id + ) + vms = VirtualMachine.list( - self.apiclient, - id=virtual_machine_with_ha.id, - listall=True - ) - + self.apiclient, + id=virtual_machine_with_ha.id, + listall=True + ) + self.assertEqual( isinstance(vms, list), True, "The listVirtualMachines returned invalid object in response." - ) - + ) + self.assertNotEqual( len(vms), 0, "The listVirtualMachines returned empty response." - ) - + ) + vm = vms[0] - + self.debug("Deployed VM on host: %s" % vm.hostid) - + #Find out Non-Suitable host for VM migration list_hosts_response = list_hosts( - self.apiclient, - ) + self.apiclient, + ) self.assertEqual( isinstance(list_hosts_response, list), True, "listHosts returned invalid object in response." - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "listHosts returned empty response." - ) - - notSuitableHost = None + ) + + notSuitableHost = None for host in list_hosts_response: if not host.suitableformigration and host.hostid != vm.hostid: notSuitableHost = host - break - + break + self.assertTrue(notSuitableHost is not None, "notsuitablehost should not be None") - + #Migrate VM to Non-Suitable host self.debug("Migrating VM-ID: %s to Host: %s" % (vm.id, notSuitableHost.id)) @@ -524,290 +521,290 @@ class TestHostHighAvailability(cloudstackTestCase): #Verify that the virtual machine got migrated to targeted Non-Suitable host list_vm_response = list_virtual_machines( - self.apiclient, - id=vm.id - ) + self.apiclient, + id=vm.id + ) self.assertEqual( isinstance(list_vm_response, list), True, "listVirtualMachine returned invalid object in response." - ) + ) self.assertNotEqual( len(list_vm_response), 0, "listVirtualMachines returned empty response." - ) + ) self.assertEqual( list_vm_response[0].id, vm.id, "Virtual machine id with the virtual machine from listVirtualMachine is not matching." - ) + ) self.assertEqual( list_vm_response[0].hostid, notSuitableHost.id, "The detination host id of migrated VM is not matching." - ) + ) - @attr(configuration = "ha.tag") - @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) + @attr(configuration="ha.tag") + @attr(speed="slow") + @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) def test_05_no_vm_with_ha_gets_migrated_to_ha_host_in_live_migration(self): """ Verify that none of the VMs with HA enabled migrate to an ha tagged host during live migration """ - + # Steps, - #1. Fresh install CS (Bonita) that supports this feature + #1. Fresh install CS that supports this feature #2. Create Basic zone, pod, cluster, add 3 hosts to cluster (host1, host2, host3), secondary & primary Storage #3. When adding host3, assign the HA host tag. #4. Create VMs with and without the Compute Service Offering with the HA tag. - #5. Note the VMs on host1 and whether any of the VMs have their “HA enabled” flags enabled. + #5. Note the VMs on host1 and whether any of the VMs have their 'HA enabled' flags enabled. #6. Put host1 into maintenance mode. # Validations, #1. Make sure the VMs are created on either host1 or host2 and not on host3 #2. Putting host1 into maintenance mode should trigger a live migration. Make sure the VMs are not migrated to HA enabled host3. - + # create and verify virtual machine with HA disabled service offering virtual_machine_with_ha = VirtualMachine.create( - self.apiclient, - self.services["virtual_machine"], - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering_with_ha.id - ) - + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_with_ha.id + ) + vms = VirtualMachine.list( - self.apiclient, - id=virtual_machine_with_ha.id, - listall=True - ) - + self.apiclient, + id=virtual_machine_with_ha.id, + listall=True + ) + self.assertEqual( isinstance(vms, list), True, "List VMs should return valid response for deployed VM" - ) - + ) + self.assertNotEqual( len(vms), 0, "List VMs should return valid response for deployed VM" - ) - + ) + vm_with_ha_enabled = vms[0] - + #Verify the virtual machine got created on non HA host list_hosts_response = list_hosts( - self.apiclient, - id=vm_with_ha_enabled.hostid - ) + self.apiclient, + id=vm_with_ha_enabled.hostid + ) self.assertEqual( isinstance(list_hosts_response, list), True, "Check list response returns a valid list" - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "Check Host is available" - ) - + ) + self.assertEqual( list_hosts_response[0].hahost, False, "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled" - ) - + ) + #put the Host in maintainance mode self.debug("Enabling maintenance mode for host %s" % vm_with_ha_enabled.hostid) cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() cmd.id = vm_with_ha_enabled.hostid self.apiclient.prepareHostForMaintenance(cmd) - + timeout = self.services["timeout"] - + #verify the VM live migration happened to another running host self.debug("Waiting for VM to come up") wait_for_vm( self.apiclient, virtualmachineid=vm_with_ha_enabled.id, interval=timeout - ) - + ) + vms = VirtualMachine.list( - self.apiclient, - id=vm_with_ha_enabled.id, - listall=True, - ) - + self.apiclient, + id=vm_with_ha_enabled.id, + listall=True, + ) + self.assertEqual( isinstance(vms, list), True, "List VMs should return valid response for deployed VM" - ) - + ) + self.assertNotEqual( len(vms), 0, "List VMs should return valid response for deployed VM" - ) - + ) + vm_with_ha_enabled1 = vms[0] - + list_hosts_response = list_hosts( - self.apiclient, - id=vm_with_ha_enabled1.hostid - ) + self.apiclient, + id=vm_with_ha_enabled1.hostid + ) self.assertEqual( isinstance(list_hosts_response, list), True, "Check list response returns a valid list" - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "Check Host is available" - ) - + ) + self.assertEqual( list_hosts_response[0].hahost, False, "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled" - ) - + ) + self.debug("Disabling the maintenance mode for host %s" % vm_with_ha_enabled.hostid) cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() cmd.id = vm_with_ha_enabled.hostid self.apiclient.cancelHostMaintenance(cmd) - - @attr(configuration = "ha.tag") - @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) + + @attr(configuration="ha.tag") + @attr(speed="slow") + @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) def test_06_no_vm_without_ha_gets_migrated_to_ha_host_in_live_migration(self): """ Verify that none of the VMs without HA enabled migrate to an ha tagged host during live migration """ - + # Steps, - #1. Fresh install CS (Bonita) that supports this feature + #1. Fresh install CS that supports this feature #2. Create Basic zone, pod, cluster, add 3 hosts to cluster (host1, host2, host3), secondary & primary Storage #3. When adding host3, assign the HA host tag. #4. Create VMs with and without the Compute Service Offering with the HA tag. - #5. Note the VMs on host1 and whether any of the VMs have their “HA enabled” flags enabled. + #5. Note the VMs on host1 and whether any of the VMs have their 'HA enabled' flags enabled. #6. Put host1 into maintenance mode. # Validations, #1. Make sure the VMs are created on either host1 or host2 and not on host3 #2. Putting host1 into maintenance mode should trigger a live migration. Make sure the VMs are not migrated to HA enabled host3. - + # create and verify virtual machine with HA disabled service offering virtual_machine_without_ha = VirtualMachine.create( - self.apiclient, - self.services["virtual_machine"], - accountid=self.account.name, - domainid=self.account.domainid, - serviceofferingid=self.service_offering_without_ha.id - ) - + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering_without_ha.id + ) + vms = VirtualMachine.list( - self.apiclient, - id=virtual_machine_without_ha.id, - listall=True - ) - + self.apiclient, + id=virtual_machine_without_ha.id, + listall=True + ) + self.assertEqual( isinstance(vms, list), True, "List VMs should return valid response for deployed VM" - ) - + ) + self.assertNotEqual( len(vms), 0, "List VMs should return valid response for deployed VM" - ) - + ) + vm_with_ha_disabled = vms[0] - + #Verify the virtual machine got created on non HA host list_hosts_response = list_hosts( - self.apiclient, - id=vm_with_ha_disabled.hostid - ) + self.apiclient, + id=vm_with_ha_disabled.hostid + ) self.assertEqual( isinstance(list_hosts_response, list), True, "Check list response returns a valid list" - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "Check Host is available" - ) - + ) + self.assertEqual( list_hosts_response[0].hahost, False, "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled" - ) - + ) + #put the Host in maintainance mode self.debug("Enabling maintenance mode for host %s" % vm_with_ha_disabled.hostid) cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() cmd.id = vm_with_ha_disabled.hostid self.apiclient.prepareHostForMaintenance(cmd) - + timeout = self.services["timeout"] - + #verify the VM live migration happened to another running host self.debug("Waiting for VM to come up") wait_for_vm( self.apiclient, virtualmachineid=vm_with_ha_disabled.id, interval=timeout - ) - + ) + vms = VirtualMachine.list( - self.apiclient, - id=vm_with_ha_disabled.id, - listall=True - ) - + self.apiclient, + id=vm_with_ha_disabled.id, + listall=True + ) + self.assertEqual( isinstance(vms, list), True, "List VMs should return valid response for deployed VM" - ) - + ) + self.assertNotEqual( len(vms), 0, "List VMs should return valid response for deployed VM" - ) - + ) + list_hosts_response = list_hosts( - self.apiclient, - id=vms[0].hostid - ) + self.apiclient, + id=vms[0].hostid + ) self.assertEqual( isinstance(list_hosts_response, list), True, "Check list response returns a valid list" - ) - + ) + self.assertNotEqual( len(list_hosts_response), 0, "Check Host is available" - ) - + ) + self.assertEqual( list_hosts_response[0].hahost, False, "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled" - ) - + ) + self.debug("Disabling the maintenance mode for host %s" % vm_with_ha_disabled.hostid) cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() cmd.id = vm_with_ha_disabled.hostid diff --git a/test/integration/component/test_project_limits.py b/test/integration/component/test_project_limits.py index 9184dca5202..af99717ad16 100644 --- a/test/integration/component/test_project_limits.py +++ b/test/integration/component/test_project_limits.py @@ -201,8 +201,8 @@ class TestProjectLimits(cloudstackTestCase): project = Project.create( self.apiclient, self.services["project"], - account=self.admin.account.name, - domainid=self.admin.account.domainid + account=self.admin.name, + domainid=self.admin.domainid ) # Cleanup created project at end of test self.cleanup.append(project) @@ -343,8 +343,8 @@ class TestProjectLimits(cloudstackTestCase): project = Project.create( self.apiclient, self.services["project"], - account=self.admin.account.name, - domainid=self.admin.account.domainid + account=self.admin.name, + domainid=self.admin.domainid ) # Cleanup created project at end of test self.cleanup.append(project) diff --git a/test/integration/component/test_project_resources.py b/test/integration/component/test_project_resources.py index 84141889f3f..378238e70fd 100644 --- a/test/integration/component/test_project_resources.py +++ b/test/integration/component/test_project_resources.py @@ -651,9 +651,9 @@ class TestTemplates(cloudstackTestCase): """Test use of private template in a project """ # 1. Create a project - # 2. Verify that in order to use somebody’s Private template for vm + # 2. Verify that in order to use somebody's Private template for vm # creation in the project, permission to use the template has to - # be granted to the Project (use API “updateTemplatePermissions” + # be granted to the Project (use API 'updateTemplatePermissions' # with project id to achieve that). self.debug("Deploying VM for with public template: %s" % diff --git a/test/integration/component/test_project_usage.py b/test/integration/component/test_project_usage.py index ab789e1c13d..bb253e1c04a 100644 --- a/test/integration/component/test_project_usage.py +++ b/test/integration/component/test_project_usage.py @@ -124,7 +124,7 @@ class TestVmUsage(cloudstackTestCase): # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) - cls.services['mode'] = cls.cls.zone.networktype + cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, diff --git a/test/integration/component/test_security_groups.py b/test/integration/component/test_security_groups.py index 2ed27fe0c5d..3c25e25a34f 100644 --- a/test/integration/component/test_security_groups.py +++ b/test/integration/component/test_security_groups.py @@ -164,7 +164,7 @@ class TestDefaultSecurityGroup(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_deployVM_InDefaultSecurityGroup(self): """Test deploy VM in default security group """ @@ -243,7 +243,7 @@ class TestDefaultSecurityGroup(cloudstackTestCase): ) return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_02_listSecurityGroups(self): """Test list security groups for admin account """ @@ -278,7 +278,7 @@ class TestDefaultSecurityGroup(cloudstackTestCase): ) return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_03_accessInDefaultSecurityGroup(self): """Test access in default security group """ @@ -435,7 +435,7 @@ class TestAuthorizeIngressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_authorizeIngressRule(self): """Test authorize ingress rule """ @@ -571,7 +571,7 @@ class TestRevokeIngressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_revokeIngressRule(self): """Test revoke ingress rule """ @@ -868,7 +868,7 @@ class TestdeployVMWithUserData(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_deployVMWithUserData(self): """Test Deploy VM with User data""" @@ -1044,7 +1044,7 @@ class TestDeleteSecurityGroup(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_delete_security_grp_running_vm(self): """Test delete security group with running VM""" @@ -1128,7 +1128,7 @@ class TestDeleteSecurityGroup(cloudstackTestCase): ) return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_02_delete_security_grp_withoout_running_vm(self): """Test delete security group without running VM""" @@ -1290,7 +1290,7 @@ class TestIngressRule(cloudstackTestCase): return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_01_authorizeIngressRule_AfterDeployVM(self): """Test delete security group with running VM""" @@ -1402,7 +1402,7 @@ class TestIngressRule(cloudstackTestCase): % (ingress_rule_2["id"], e)) return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_02_revokeIngressRule_AfterDeployVM(self): """Test Revoke ingress rule after deploy VM""" @@ -1556,7 +1556,7 @@ class TestIngressRule(cloudstackTestCase): % (icmp_rule["ruleid"], e)) return - @attr(tags = ["sg", "eip"]) + @attr(tags = ["sg", "eip", "advancedsg"]) def test_03_stopStartVM_verifyIngressAccess(self): """Test Start/Stop VM and Verify ingress rule""" diff --git a/test/integration/component/test_shared_networks.py b/test/integration/component/test_shared_networks.py index 9845826bea6..5f964190356 100644 --- a/test/integration/component/test_shared_networks.py +++ b/test/integration/component/test_shared_networks.py @@ -235,6 +235,7 @@ class TestSharedNetworks(cloudstackTestCase): raise Exception("Warning: Exception during network cleanup : %s" % e) return + @attr(tags=["advanced", "advancedns"]) def test_sharedNetworkOffering_01(self): """ Test shared network Offering 01 """ @@ -372,6 +373,7 @@ class TestSharedNetworks(cloudstackTestCase): ) self.debug("NetworkOffering created and enabled: %s" % self.shared_network_offering.id) + @attr(tags=["advanced", "advancedns"]) def test_sharedNetworkOffering_02(self): """ Test Shared Network Offering 02 """ @@ -459,6 +461,7 @@ class TestSharedNetworks(cloudstackTestCase): except Exception as e: self.debug("Network Offering creation failed with vlan as False in advance mode and shared guest type.") + @attr(tags=["advanced", "advancedns"]) def test_sharedNetworkOffering_03(self): """ Test Shared Network Offering 03 """ @@ -547,6 +550,7 @@ class TestSharedNetworks(cloudstackTestCase): except Exception as e: self.debug("Network Offering creation failed with vlan as true and ip ranges as False in advance mode and with shared guest type.") + @attr(tags=["advanced", "advancedns"]) def test_createSharedNetwork_All(self): """ Test Shared Network ALL """ @@ -829,6 +833,7 @@ class TestSharedNetworks(cloudstackTestCase): if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: self.fail("Virtual machine ip should be from the ip range assigned to network created.") + @attr(tags=["advanced", "advancedns"]) def test_createSharedNetwork_accountSpecific(self): """ Test Shared Networm with scope account """ @@ -1092,6 +1097,7 @@ class TestSharedNetworks(cloudstackTestCase): if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: self.fail("Virtual machine ip should be from the ip range assigned to network created.") + @attr(tags=["advanced", "advancedns"]) def test_createSharedNetwork_domainSpecific(self): """ Test Shared Network with scope domain """ @@ -1446,6 +1452,7 @@ class TestSharedNetworks(cloudstackTestCase): if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: self.fail("Virtual machine ip should be from the ip range assigned to network created.") + @attr(tags=["advanced", "advancedns"]) def test_createSharedNetwork_projectSpecific(self): """ Test Shared Network with scope project """ @@ -1740,6 +1747,7 @@ class TestSharedNetworks(cloudstackTestCase): if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: self.fail("Virtual machine ip should be from the ip range assigned to network created.") + @attr(tags=["advanced", "advancedns"]) def test_createSharedNetwork_usedVlan(self): """ Test Shared Network with used vlan 01 """ @@ -1898,6 +1906,7 @@ class TestSharedNetworks(cloudstackTestCase): except Exception as e: self.debug("Network creation failed because the valn id being used by another network.") + @attr(tags=["advanced", "advancedns"]) def test_createSharedNetwork_usedVlan2(self): """ Test Shared Network with used vlan 02 """ @@ -2093,6 +2102,7 @@ class TestSharedNetworks(cloudstackTestCase): except Exception as e: self.debug("Network creation failed because the valn id being used by another network.") + @attr(tags=["advanced", "advancedns"]) def test_deployVM_multipleSharedNetwork(self): """ Test Vm deployment with multiple shared networks """ @@ -2350,6 +2360,7 @@ class TestSharedNetworks(cloudstackTestCase): self.assertTrue(self.network1_admin_account_virtual_machine.nic[0].ipaddress is not None, "ip should be assigned to running virtual machine") + @attr(tags=["advanced", "advancedns"]) def test_deployVM_isolatedAndShared(self): """ Test VM deployment in shared and isolated networks """ @@ -2697,6 +2708,7 @@ class TestSharedNetworks(cloudstackTestCase): except Exception as e: self.fail("SSH Access failed for %s: %s" % (self.isolated_network_admin_account_virtual_machine.ipaddress, e)) + @attr(tags=["advanced", "advancedns"]) def test_networkWithsubdomainaccessTrue(self): """ Test Shared Network with subdomainaccess=True """ @@ -2841,6 +2853,7 @@ class TestSharedNetworks(cloudstackTestCase): except: self.debug("Network creation failed because subdomainaccess parameter was passed when scope was account.") + @attr(tags=["advanced", "advancedns"]) def test_networkWithsubdomainaccessFalse(self): """ Test shared Network with subdomainaccess=False """ diff --git a/test/integration/component/test_stopped_vm.py b/test/integration/component/test_stopped_vm.py index f1096919824..0527b3d7ebf 100644 --- a/test/integration/component/test_stopped_vm.py +++ b/test/integration/component/test_stopped_vm.py @@ -78,7 +78,7 @@ class Services: { "displaytext": "Test ISO", "name": "testISO", - "url": "http://iso.linuxquestions.org/download/504/1819/http/gd4.tuwien.ac.at/dsl-4.4.10.iso", + "url": "http://people.apache.org/~tsp/dummy.iso", # Source URL where ISO is located "ostype": 'CentOS 5.3 (64-bit)', "mode": 'HTTP_DOWNLOAD', # Downloading existing ISO @@ -219,10 +219,6 @@ class TestDeployVM(cloudstackTestCase): "Running", "VM should be in Running state after deployment" ) - try: - ssh = self.virtual_machine.get_ssh_client() - except Exception as e: - self.fail("SSH to VM instance failed!") return @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) @@ -274,10 +270,6 @@ class TestDeployVM(cloudstackTestCase): "Running", "VM should be in Running state after deployment" ) - try: - ssh = self.virtual_machine.get_ssh_client() - except Exception as e: - self.fail("SSH to VM instance failed!") return @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) diff --git a/test/integration/component/test_storage_motion.py b/test/integration/component/test_storage_motion.py index cf110d34e61..0dcc7f8e8d1 100644 --- a/test/integration/component/test_storage_motion.py +++ b/test/integration/component/test_storage_motion.py @@ -178,8 +178,6 @@ class TestStorageMotion(cloudstackTestCase): # Migrate to a host that requires storage motion hosts[:] = [host for host in hosts if host.requiresStorageMotion] - self.assert_(hosts is not None, msg="No valid hosts for storage motion") - self.assert_(len(hosts)>0, msg="No valid hosts for storage motion. Skipping") if hosts is None or len(hosts) == 0: self.skipTest("No valid hosts for storage motion. Skipping") diff --git a/test/integration/component/test_tags.py b/test/integration/component/test_tags.py index 12a586313f1..992ca1daf58 100644 --- a/test/integration/component/test_tags.py +++ b/test/integration/component/test_tags.py @@ -102,9 +102,9 @@ class Services: }, "iso": { - "displaytext": "DSL ISO", - "name": "DSL ISO", - "url": "http://iso.linuxquestions.org/download/504/1819/http/gd4.tuwien.ac.at/dsl-4.4.10.iso", + "displaytext": "Dummy ISO", + "name": "Dummy ISO", + "url": "http://people.apache.org/~tsp/dummy.iso", # Source URL where ISO is located "isextractable": True, "isfeatured": True, @@ -216,7 +216,7 @@ class TestResourceTags(cloudstackTestCase): cls.api_client, cls.services["virtual_machine"], accountid=cls.account.name, - domainid=cls.account.account.domainid, + domainid=cls.account.domainid, serviceofferingid=cls.service_offering.id, mode=cls.zone.networktype ) diff --git a/test/integration/component/test_templates.py b/test/integration/component/test_templates.py index 1a60123b820..65beabfc98f 100644 --- a/test/integration/component/test_templates.py +++ b/test/integration/component/test_templates.py @@ -93,7 +93,6 @@ class Services: "templatefilter": 'self', }, "templatefilter": 'self', - "destzoneid": 2, # For Copy template (Destination zone) "ostype": 'CentOS 5.3 (64-bit)', "sleep": 60, "timeout": 10, @@ -423,94 +422,6 @@ class TestTemplates(cloudstackTestCase): ) return - @attr(tags = ["advanced", "advancedns", "multizone"]) - def test_02_copy_template(self): - """Test for copy template from one zone to another""" - - # Validate the following - # 1. copy template should be successful and - # secondary storage should contain new copied template. - - self.debug( - "Copying template from zone: %s to %s" % ( - self.template.id, - self.services["destzoneid"] - )) - cmd = copyTemplate.copyTemplateCmd() - cmd.id = self.template.id - cmd.destzoneid = self.services["destzoneid"] - cmd.sourcezoneid = self.zone.id - self.apiclient.copyTemplate(cmd) - - # Verify template is copied to another zone using ListTemplates - list_template_response = list_templates( - self.apiclient, - templatefilter=\ - self.services["templatefilter"], - id=self.template.id, - zoneid=self.services["destzoneid"] - ) - self.assertEqual( - isinstance(list_template_response, list), - True, - "Check for list template response return valid list" - ) - - self.assertNotEqual( - len(list_template_response), - 0, - "Check template extracted in List Templates" - ) - - template_response = list_template_response[0] - self.assertEqual( - template_response.id, - self.template.id, - "Check ID of the downloaded template" - ) - self.assertEqual( - template_response.zoneid, - self.services["destzoneid"], - "Check zone ID of the copied template" - ) - - # Cleanup- Delete the copied template - timeout = self.services["timeout"] - while True: - time.sleep(self.services["sleep"]) - list_template_response = list_templates( - self.apiclient, - templatefilter=\ - self.services["templatefilter"], - id=self.template_2.id, - zoneid=self.services["destzoneid"] - ) - self.assertEqual( - isinstance(list_template_response, list), - True, - "Check list response returns a valid list" - ) - self.assertNotEqual( - len(list_template_response), - 0, - "Check template extracted in List Templates" - ) - - template_response = list_template_response[0] - if template_response.isready == True: - break - - if timeout == 0: - raise Exception( - "Failed to download copied template(ID: %s)" % template_response.id) - - timeout = timeout - 1 - cmd = deleteTemplate.deleteTemplateCmd() - cmd.id = self.template.id - cmd.zoneid = self.services["destzoneid"] - self.apiclient.deleteTemplate(cmd) - return - @attr(tags = ["advanced", "advancedns"]) def test_03_delete_template(self): """Test Delete template diff --git a/test/integration/component/test_vm_passwdenabled.py b/test/integration/component/test_vm_passwdenabled.py index e89253c407a..e22a1a0a75a 100644 --- a/test/integration/component/test_vm_passwdenabled.py +++ b/test/integration/component/test_vm_passwdenabled.py @@ -90,8 +90,8 @@ class TestVMPasswordEnabled(cloudstackTestCase): cls.services["ostype"] ) # Set Zones and disk offerings - cls.services["small"]["zoneid"] = zone.id - cls.services["small"]["template"] = template.id + cls.services["service_offerings"]["small"]["zoneid"] = zone.id + cls.services["service_offerings"]["small"]["template"] = template.id # Create VMs, NAT Rules etc cls.account = Account.create( diff --git a/test/integration/component/test_vpc_host_maintenance.py b/test/integration/component/test_vpc_host_maintenance.py index 1cce2764fe8..d28b7985b9b 100644 --- a/test/integration/component/test_vpc_host_maintenance.py +++ b/test/integration/component/test_vpc_host_maintenance.py @@ -186,7 +186,6 @@ class Services: } -@unittest.skip("No suitable setup available for testing") class TestVMLifeCycleHostmaintenance(cloudstackTestCase): @classmethod @@ -562,7 +561,6 @@ class TestVMLifeCycleHostmaintenance(cloudstackTestCase): return -@unittest.skip("No suitable setup available for testing") class TestVPCNetworkRules(cloudstackTestCase): @classmethod diff --git a/test/integration/component/test_vpc_network_lbrules.py b/test/integration/component/test_vpc_network_lbrules.py index b4a66070d5b..66d6c4d4018 100644 --- a/test/integration/component/test_vpc_network_lbrules.py +++ b/test/integration/component/test_vpc_network_lbrules.py @@ -505,7 +505,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return nwacl_internet_1 @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_01_VPC_LBRulesListing(self): """ Test case no 210 and 227: List Load Balancing Rules belonging to a VPC """ @@ -551,7 +550,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_02_VPC_LBRulesAndVMListing(self): """ Test case no 211 and 228: List only VMs suitable for the Virtual Network on VPC for LB Rule """ @@ -595,7 +593,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_03_VPC_CreateLBRuleInMultipleNetworks(self): """ Test case no 212 : Create LB rules for 1 network which is part of a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Running State @@ -623,7 +620,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_04_VPC_CreateLBRuleInMultipleNetworksVRStoppedState(self): """ Test case no 222 : Create LB rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Stopped State @@ -651,7 +647,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_05_VPC_CreateAndDeleteLBRule(self): """ Test case no 214 : Delete few(not all) LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Running State @@ -683,7 +678,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_06_VPC_CreateAndDeleteLBRuleVRStopppedState(self): """ Test case no 224 : Delete few(not all) LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Stopped State @@ -715,7 +709,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_07_VPC_CreateAndDeleteAllLBRule(self): """ Test case no 215 : Delete all LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Running State @@ -749,7 +742,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_08_VPC_CreateAndDeleteAllLBRuleVRStoppedState(self): """ Test case no 225 and 226 : Delete all LB rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Stopped State @@ -783,7 +775,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_09_VPC_LBRuleCreateFailMultipleVPC(self): """ Test case no 234 : User should not be allowed to create a LB rule for a VM that belongs to a different VPC. """ @@ -822,7 +813,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_10_VPC_FailedToCreateLBRuleNonVPCNetwork(self): """ Test case no 216 and 235: User should not be allowed to create a LB rule for a VM that does not belong to any VPC. """ @@ -860,7 +850,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_11_VPC_LBRuleCreateNotAllowed(self): """ Test case no 217 and 236: User should not be allowed to create a LB rule for a VM that does not belong to the same network but belongs to the same VPC. @@ -899,7 +888,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_12_VPC_LBRuleCreateFailForRouterIP(self): """ Test case no 218 and 237: User should not be allowed to create a LB rule on an Ipaddress that Source Nat enabled. """ @@ -928,7 +916,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_13_VPC_LBRuleCreateFailForPFSourceNATIP(self): """ Test case no 219 : User should not be allowed to create a LB rule on an Ipaddress that already has a PF rule. """ @@ -959,7 +946,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_14_VPC_LBRuleCreateFailForStaticNatRule(self): """ Test case no 220 : User should not be allowed to create a LB rule on an Ipaddress that already has a Static Nat rule. """ @@ -990,7 +976,6 @@ class TestVPCNetworkLBRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_15_VPC_RleaseIPForLBRuleCreated(self): """ Test case no 221 : Release Ip address that has a LB rule assigned to it. """ diff --git a/test/integration/component/test_vpc_network_pfrules.py b/test/integration/component/test_vpc_network_pfrules.py index 56792f49d00..c0c2b86426c 100644 --- a/test/integration/component/test_vpc_network_pfrules.py +++ b/test/integration/component/test_vpc_network_pfrules.py @@ -553,7 +553,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_03_network_services_VPC_StopCreateMultiplePF(self): """ Test case no 205 : Create PF rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when Virtual Router is in Stopped State @@ -587,7 +586,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_04_network_services_VPC_CreateMultiplePF(self): """ Test case no 191 : Create PF rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when Virtual Router is in Running State @@ -620,7 +618,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_05_network_services_VPC_StopDeletePF(self): """ Test case no 207 : Delete few(not all) PF rules for a single virtual network of a VPC belonging to a single Public IP Address when Virtual Router is in Stopped State @@ -654,7 +651,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_06_network_services_VPC_DeletePF(self): """ Test case no 193 : Delete few(not all) PF rules for a single virtual network of a VPC belonging to a single Public IP Address when Virtual Router is in Running State @@ -684,7 +680,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_07_network_services_VPC_StopDeleteAllPF(self): """ Test case no 208 : Delete all PF rules for a single virtual network of a VPC belonging to a single Public IP Address when Virtual Router is in Stopped State @@ -721,7 +716,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_08_network_services_VPC_DeleteAllPF(self): """ Test case no 194 : Delete all PF rules for a single virtual network of a VPC belonging to a single Public IP Address when Virtual Router is in Running State @@ -754,7 +748,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_09_network_services_VPC_StopDeleteAllMultiplePF(self): """ Test case no 209 : Delete all PF rules for two/multiple virtual networks of a VPC. Observe the status of the Public IP Addresses of the rules when Virtual Router is in Stopped State @@ -817,7 +810,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_10_network_services_VPC_DeleteAllMultiplePF(self): """ Test case no 195: Delete all PF rules for two/multiple virtual networks of a VPC. Observe the status of the Public IP Addresses of the rules when Virtual Router is in Running State diff --git a/test/integration/component/test_vpc_network_staticnatrule.py b/test/integration/component/test_vpc_network_staticnatrule.py index aceca62d1fb..bed1b5298b3 100644 --- a/test/integration/component/test_vpc_network_staticnatrule.py +++ b/test/integration/component/test_vpc_network_staticnatrule.py @@ -552,7 +552,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_03_VPC_StopCreateMultipleStaticNatRuleStopppedState(self): """ Test case no extra : Create Static Nat Rule rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when Virtual Router is in Stopped State @@ -586,7 +585,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_04_VPC_CreateMultipleStaticNatRule(self): """ Test case no 230 : Create Static NAT Rules for a two/multiple virtual networks of a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Running State @@ -619,7 +617,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_05_network_services_VPC_DeleteAllPF(self): """ Test case no 232: Delete all Static NAT Rules for a single virtual network of a VPC belonging to a single Public IP Address when the Virtual Router is in Running State @@ -651,7 +648,6 @@ class TestVPCNetworkPFRules(cloudstackTestCase): return @attr(tags=["advanced", "intervlan"]) - @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") def test_06_network_services_VPC_DeleteAllMultiplePF(self): """ Test case no 233: Delete all Static NAT rules for two/multiple virtual networks of a VPC. Observe the status of the Public IP Addresses of the rules when the Virtual Router is in Running State. diff --git a/test/integration/smoke/test_internal_lb.py b/test/integration/smoke/test_internal_lb.py index ae64297bf1c..07a539592ca 100644 --- a/test/integration/smoke/test_internal_lb.py +++ b/test/integration/smoke/test_internal_lb.py @@ -22,6 +22,7 @@ from marvin.cloudstackAPI import * from marvin.integration.lib.utils import * from marvin.integration.lib.base import * from marvin.integration.lib.common import * +from nose.plugins.attrib import attr class TestInternalLb(cloudstackTestCase): @@ -97,6 +98,7 @@ class TestInternalLb(cloudstackTestCase): + @attr(tags=["advanced"]) def test_internallb(self): #1) Create and enable network offering with Internal Lb vm service diff --git a/test/integration/smoke/test_network.py b/test/integration/smoke/test_network.py index 61ddf46e9ef..eb33c630ccf 100644 --- a/test/integration/smoke/test_network.py +++ b/test/integration/smoke/test_network.py @@ -189,8 +189,7 @@ class TestPublicIP(cloudstackTestCase): @attr(tags = ["advanced", "advancedns", "smoke"]) def test_public_ip_admin_account(self): - """Test for Associate/Disassociate - public IP address for admin account""" + """Test for Associate/Disassociate public IP address for admin account""" # Validate the following: # 1. listPubliIpAddresses API returns the list of acquired addresses @@ -240,8 +239,7 @@ class TestPublicIP(cloudstackTestCase): @attr(tags = ["advanced", "advancedns", "smoke"]) def test_public_ip_user_account(self): - """Test for Associate/Disassociate - public IP address for user account""" + """Test for Associate/Disassociate public IP address for user account""" # Validate the following: # 1. listPubliIpAddresses API returns the list of acquired addresses @@ -885,102 +883,102 @@ class TestLoadBalancingRule(cloudstackTestCase): # Check if VM is in Running state before creating LB rule vm_response = VirtualMachine.list( - self.apiclient, - account=self.account.name, - domainid=self.account.domainid - ) + self.apiclient, + account=self.account.name, + domainid=self.account.domainid + ) self.assertEqual( - isinstance(vm_response, list), - True, - "Check list VM returns a valid list" - ) + isinstance(vm_response, list), + True, + "Check list VM returns a valid list" + ) self.assertNotEqual( - len(vm_response), - 0, - "Check Port Forwarding Rule is created" - ) + len(vm_response), + 0, + "Check Port Forwarding Rule is created" + ) for vm in vm_response: self.assertEqual( - vm.state, - 'Running', - "VM state should be Running before creating a NAT rule." - ) + vm.state, + 'Running', + "VM state should be Running before creating a NAT rule." + ) #Create Load Balancer rule and assign VMs to rule lb_rule = LoadBalancerRule.create( - self.apiclient, - self.services["lbrule"], - self.non_src_nat_ip.ipaddress.id, - accountid=self.account.name - ) + self.apiclient, + self.services["lbrule"], + self.non_src_nat_ip.ipaddress.id, + accountid=self.account.name + ) self.cleanup.append(lb_rule) lb_rule.assign(self.apiclient, [self.vm_1, self.vm_2]) lb_rules = list_lb_rules( - self.apiclient, - id=lb_rule.id - ) + self.apiclient, + id=lb_rule.id + ) self.assertEqual( - isinstance(lb_rules, list), - True, - "Check list response returns a valid list" - ) + isinstance(lb_rules, list), + True, + "Check list response returns a valid list" + ) #verify listLoadBalancerRules lists the added load balancing rule self.assertNotEqual( - len(lb_rules), - 0, - "Check Load Balancer Rule in its List" - ) + len(lb_rules), + 0, + "Check Load Balancer Rule in its List" + ) self.assertEqual( - lb_rules[0].id, - lb_rule.id, - "Check List Load Balancer Rules returns valid Rule" - ) + lb_rules[0].id, + lb_rule.id, + "Check List Load Balancer Rules returns valid Rule" + ) # listLoadBalancerRuleInstances should list # all instances associated with that LB rule lb_instance_rules = list_lb_instances( - self.apiclient, - id=lb_rule.id - ) + self.apiclient, + id=lb_rule.id + ) self.assertEqual( - isinstance(lb_instance_rules, list), - True, - "Check list response returns a valid list" - ) + isinstance(lb_instance_rules, list), + True, + "Check list response returns a valid list" + ) self.assertNotEqual( - len(lb_instance_rules), - 0, - "Check Load Balancer instances Rule in its List" - ) + len(lb_instance_rules), + 0, + "Check Load Balancer instances Rule in its List" + ) self.assertIn( - lb_instance_rules[0].id, - [self.vm_1.id, self.vm_2.id], - "Check List Load Balancer instances Rules returns valid VM ID" - ) + lb_instance_rules[0].id, + [self.vm_1.id, self.vm_2.id], + "Check List Load Balancer instances Rules returns valid VM ID" + ) self.assertIn( - lb_instance_rules[1].id, - [self.vm_1.id, self.vm_2.id], - "Check List Load Balancer instances Rules returns valid VM ID" - ) + lb_instance_rules[1].id, + [self.vm_1.id, self.vm_2.id], + "Check List Load Balancer instances Rules returns valid VM ID" + ) try: self.debug("SSHing into IP address: %s after adding VMs (ID: %s , %s)" % - ( - self.non_src_nat_ip.ipaddress, - self.vm_1.id, - self.vm_2.id - )) + ( + self.non_src_nat_ip.ipaddress.ipaddress, + self.vm_1.id, + self.vm_2.id + )) ssh_1 = remoteSSHClient( - self.non_src_nat_ip.ipaddress, - self.services['lbrule']["publicport"], - self.vm_1.username, - self.vm_1.password - ) + self.non_src_nat_ip.ipaddress.ipaddress, + self.services['lbrule']["publicport"], + self.vm_1.username, + self.vm_1.password + ) # If Round Robin Algorithm is chosen, # each ssh command should alternate between VMs @@ -989,71 +987,71 @@ class TestLoadBalancingRule(cloudstackTestCase): time.sleep(self.services["lb_switch_wait"]) self.debug("SSHing again into IP address: %s with VMs (ID: %s , %s) added to LB rule" % - ( - self.non_src_nat_ip.ipaddress, - self.vm_1.id, - self.vm_2.id - )) + ( + self.non_src_nat_ip.ipaddress.ipaddress, + self.vm_1.id, + self.vm_2.id + )) ssh_2 = remoteSSHClient( - self.non_src_nat_ip.ipaddress, - self.services['lbrule']["publicport"], - self.vm_1.username, - self.vm_1.password - ) + self.non_src_nat_ip.ipaddress.ipaddress, + self.services['lbrule']["publicport"], + self.vm_1.username, + self.vm_1.password + ) hostnames.append(ssh_2.execute("hostname")[0]) self.debug("Hostnames after adding 2 VMs to LB rule: %s" % str(hostnames)) self.assertIn( - self.vm_1.name, - hostnames, - "Check if ssh succeeded for server1" - ) + self.vm_1.name, + hostnames, + "Check if ssh succeeded for server1" + ) self.assertIn( - self.vm_2.name, - hostnames, - "Check if ssh succeeded for server2" - ) + self.vm_2.name, + hostnames, + "Check if ssh succeeded for server2" + ) #SSH should pass till there is a last VM associated with LB rule lb_rule.remove(self.apiclient, [self.vm_2]) self.debug("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % - ( - self.non_src_nat_ip.ipaddress, - self.vm_2.id - )) + ( + self.non_src_nat_ip.ipaddress.ipaddress, + self.vm_2.id + )) ssh_1 = remoteSSHClient( - self.non_src_nat_ip.ipaddress, - self.services['lbrule']["publicport"], - self.vm_1.username, - self.vm_1.password - ) + self.non_src_nat_ip.ipaddress.ipaddress, + self.services['lbrule']["publicport"], + self.vm_1.username, + self.vm_1.password + ) hostnames.append(ssh_1.execute("hostname")[0]) self.debug("Hostnames after removing VM2: %s" % str(hostnames)) except Exception as e: self.fail("%s: SSH failed for VM with IP Address: %s" % - (e, self.non_src_nat_ip.ipaddress)) + (e, self.non_src_nat_ip.ipaddress.ipaddress)) self.assertIn( - self.vm_1.name, - hostnames, - "Check if ssh succeeded for server1" - ) + self.vm_1.name, + hostnames, + "Check if ssh succeeded for server1" + ) lb_rule.remove(self.apiclient, [self.vm_1]) with self.assertRaises(Exception): - self.fail("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % - ( - self.non_src_nat_ip.ipaddress, - self.vm_1.id - )) + self.debug("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % + ( + self.non_src_nat_ip.ipaddress.ipaddress, + self.vm_1.id + )) ssh_1 = remoteSSHClient( - self.non_src_nat_ip.ipaddress, - self.services['lbrule']["publicport"], - self.vm_1.username, - self.vm_1.password - ) + self.non_src_nat_ip.ipaddress.ipaddress, + self.services['lbrule']["publicport"], + self.vm_1.username, + self.vm_1.password + ) ssh_1.execute("hostname")[0] return @@ -1203,7 +1201,7 @@ class TestRebootRouter(cloudstackTestCase): self.debug("SSH into VM (ID : %s ) after reboot" % self.vm_1.id) remoteSSHClient( - self.nat_rule.ipaddress, + self.nat_rule.ipaddress.ipaddress, self.services["natrule"]["publicport"], self.vm_1.username, self.vm_1.password @@ -1211,8 +1209,7 @@ class TestRebootRouter(cloudstackTestCase): except Exception as e: self.fail( "SSH Access failed for %s: %s" % \ - (self.vm_1.ipaddress, e) - ) + (self.vm_1.ipaddress, e)) return def tearDown(self): @@ -1557,7 +1554,7 @@ class TestReleaseIP(cloudstackTestCase): @attr(tags = ["advanced", "advancedns", "smoke"]) def test_releaseIP(self): - """Test for Associate/Disassociate public IP address""" + """Test for release public IP address""" self.debug("Deleting Public IP : %s" % self.ip_addr.id) @@ -1579,7 +1576,6 @@ class TestReleaseIP(cloudstackTestCase): "Check if disassociated IP Address is no longer available" ) - self.debug("List NAT Rule response" + str(list_nat_rule)) # ListPortForwardingRules should not list # associated rules with Public IP address try: @@ -1587,18 +1583,18 @@ class TestReleaseIP(cloudstackTestCase): self.apiclient, id=self.nat_rule.id ) + self.debug("List NAT Rule response" + str(list_nat_rule)) except cloudstackAPIException: self.debug("Port Forwarding Rule is deleted") # listLoadBalancerRules should not list # associated rules with Public IP address - self.debug("List LB Rule response" + str(list_lb_rule)) try: list_lb_rule = list_lb_rules( self.apiclient, id=self.lb_rule.id ) - + self.debug("List LB Rule response" + str(list_lb_rule)) except cloudstackAPIException: self.debug("Port Forwarding Rule is deleted") @@ -1658,7 +1654,6 @@ class TestDeleteAccount(cloudstackTestCase): try: src_nat_ip_addr = src_nat_ip_addrs[0] - except Exception as e: self.fail("SSH failed for VM with IP: %s" % src_nat_ip_addr.ipaddress) @@ -1740,10 +1735,9 @@ class TestDeleteAccount(cloudstackTestCase): "Check routers are properly deleted." ) except Exception as e: - raise Exception( - "Exception raised while fetching routers for account: %s" % - self.account.name) + "Encountered %s raised while fetching routers for account: %s" % (e, + self.account.name)) return def tearDown(self): diff --git a/test/integration/smoke/test_network_acl.py b/test/integration/smoke/test_network_acl.py index 66f0a6fc1c5..3ed45be9cd0 100644 --- a/test/integration/smoke/test_network_acl.py +++ b/test/integration/smoke/test_network_acl.py @@ -22,7 +22,7 @@ from marvin.cloudstackAPI import * from marvin.integration.lib.utils import * from marvin.integration.lib.base import * from marvin.integration.lib.common import * - +from nose.plugins.attrib import attr class TestNetworkACL(cloudstackTestCase): networkOfferingId = 11 @@ -40,6 +40,7 @@ class TestNetworkACL(cloudstackTestCase): + @attr(tags=["advanced"]) def test_networkAcl(self): # 1) Create VPC diff --git a/test/integration/smoke/test_nic.py b/test/integration/smoke/test_nic.py index bae6dfda15d..8e8d3407dfb 100644 --- a/test/integration/smoke/test_nic.py +++ b/test/integration/smoke/test_nic.py @@ -79,11 +79,35 @@ class Services: "PortForwarding": 'VirtualRouter', }, }, + "network_offering_shared": { + "name": 'Test Network offering shared', + "displaytext": 'Test Network offering Shared', + "guestiptype": 'Shared', + "supportedservices": 'Dhcp,Dns,UserData', + "traffictype": 'GUEST', + "specifyVlan" : "True", + "specifyIpRanges" : "True", + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "UserData": 'VirtualRouter', + }, + }, "network": { "name": "Test Network", "displaytext": "Test Network", "acltype": "Account", }, + "network2": { + "name": "Test Network Shared", + "displaytext": "Test Network Shared", + "vlan" :1201, + "gateway" :"172.16.15.1", + "netmask" :"255.255.255.0", + "startip" :"172.16.15.21", + "endip" :"172.16.15.41", + "acltype": "Account", + }, # ISO settings for Attach/Detach ISO tests "iso": { "displaytext": "Test ISO", @@ -176,6 +200,14 @@ class TestDeployVM(cloudstackTestCase): self.network_offering.update(self.apiclient, state='Enabled') # Enable Network offering self.services["network"]["networkoffering"] = self.network_offering.id + self.network_offering_shared = NetworkOffering.create( + self.apiclient, + self.services["network_offering_shared"], + ) + self.cleanup.insert(0, self.network_offering_shared) + self.network_offering_shared.update(self.apiclient, state='Enabled') # Enable Network offering + self.services["network2"]["networkoffering"] = self.network_offering_shared.id + ################ ### Test Network self.test_network = Network.create( @@ -185,6 +217,14 @@ class TestDeployVM(cloudstackTestCase): self.account.domainid, ) self.cleanup.insert(0, self.test_network) + self.test_network2 = Network.create( + self.apiclient, + self.services["network2"], + self.account.name, + self.account.domainid, + zoneid=self.services["network"]["zoneid"] + ) + self.cleanup.insert(0, self.test_network2) except Exception as ex: self.debug("Exception during NIC test SETUP!: " + str(ex)) self.assertEqual(True, False, "Exception during NIC test SETUP!: " + str(ex)) @@ -201,10 +241,10 @@ class TestDeployVM(cloudstackTestCase): accountid=self.account.name, domainid=self.account.domainid, serviceofferingid=self.service_offering.id, - mode=self.services['mode'] + mode=self.services['mode'], + networkids=[self.test_network.id] ) self.cleanup.insert(0, self.virtual_machine) - list_vm_response = list_virtual_machines( self.apiclient, id=self.virtual_machine.id @@ -256,7 +296,7 @@ class TestDeployVM(cloudstackTestCase): existing_nic_id = vm_response.nic[0].id # 1. add a nic - add_response = self.virtual_machine.add_nic(self.apiclient, self.test_network.id) + add_response = self.virtual_machine.add_nic(self.apiclient, self.test_network2.id) time.sleep(5) # now go get the vm list? @@ -308,8 +348,9 @@ class TestDeployVM(cloudstackTestCase): sawException = True self.assertEqual(sawException, True, "Make sure we cannot delete the default NIC") - - self.virtual_machine.remove_nic(self.apiclient, existing_nic_id) + self.virtual_machine.update_default_nic(self.apiclient, existing_nic_id) + time.sleep(5) + self.virtual_machine.remove_nic(self.apiclient, new_nic_id) time.sleep(5) list_vm_response = list_virtual_machines( diff --git a/test/integration/smoke/test_nicdetail.py b/test/integration/smoke/test_nicdetail.py deleted file mode 100644 index 3d8b1d62a47..00000000000 --- a/test/integration/smoke/test_nicdetail.py +++ /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. -""" P1 tests for Scaling up Vm -""" -#Import Local Modules -import marvin -from marvin.cloudstackTestCase import * -from marvin.cloudstackAPI import * -from marvin.remoteSSHClient import remoteSSHClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * -from nose.plugins.attrib import attr -#Import System modules -import time - -_multiprocess_shared_ = True -class Services: - """Test VM Life Cycle Services - """ - - def __init__(self): - self.services = { - - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - # Random characters are appended in create account to - # ensure unique username generated each time - "password": "password", - }, - "small": - # Create a small virtual machine instance with disk offering - { - "displayname": "testserver", - "username": "root", # VM creds for SSH - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "disk_offering": { - "displaytext": "Small", - "name": "Small", - "storagetype": "shared", - "disksize": 1 - }, - "service_offerings": - { - "small": - { - # Small service offering ID to for change VM - # service offering from medium to small - "name": "SmallInstance", - "displaytext": "SmallInstance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - }, - "big": - { - # Big service offering ID to for change VM - "name": "BigInstance", - "displaytext": "BigInstance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 512, - } - }, - #Change this - "template": { - "displaytext": "xs", - "name": "xs", - "passwordenabled": False, - }, - "diskdevice": '/dev/xvdd', - # Disk device where ISO is attached to instance - "mount_dir": "/mnt/tmp", - "sleep": 60, - "timeout": 10, - #Migrate VM to hostid - "ostype": 'CentOS 5.6 (64-bit)', - # CentOS 5.3 (64-bit) - } - -class TestNicDetail(cloudstackTestCase): - - @classmethod - def setUpClass(cls): - cls.api_client = super(TestNicDetail, cls).getClsTestClient().getApiClient() - cls.services = Services().services - - # Get Zone, Domain and templates - domain = get_domain(cls.api_client, cls.services) - zone = get_zone(cls.api_client, cls.services) - cls.services['mode'] = zone.networktype - - # Set Zone - - # Create account, service offerings, vm. - cls.account = Account.create( - cls.api_client, - cls.services["account"], - domainid=domain.id - ) - - cls.nic = "163738c7-ce3a-481d-ac68-4a8337043415"; - #how does it work - cls._cleanup = [ - cls.account - ] - - @classmethod - def tearDownClass(cls): - cls.api_client = super(TestNicDetail, cls).getClsTestClient().getApiClient() - cleanup_resources(cls.api_client, cls._cleanup) - return - - def setUp(self): - self.apiclient = self.testClient.getApiClient() - self.dbclient = self.testClient.getDbConnection() - self.cleanup = [] - - def tearDown(self): - #Clean up, terminate the created ISOs - cleanup_resources(self.apiclient, self.cleanup) - return - - @attr(tags = ["advanced", "xenserver"]) - def test_01_updatenicdetail(self): - """Test nic detail - """ - # Validate the following - # Scale up the vm and see if it scales to the new svc offering and is finally in running state - - self.debug("Testing ADD nic detail Nic-ID: %s " % ( - self.nic - )) - - cmd = addNicDetail.addNicDetailCmd() - cmd.name = self.nic - cmd.value = self.nic - cmd.id = self.nic - self.apiclient.addNicDetail(cmd) - - listNicDetailCmd = listNicDetails.listNicDetailsCmd() - listNicDetailCmd.id = self.nic - listNicDetailResponse = self.api_client.listVirtualMachines(listNicDetailCmd) - - self.assertNotEqual(len(listNicDetailResponse), 0, "Check if the list API \ - returns a non-empty response") - - nicdetail = listNicDetailResponse[0] - - #self.assertEqual(nicdetail.id, self.nic, "Check if the Nic returned is the same as the one we asked for") - - - self.assertEqual(nicdetail.name, self.nic, "Check if Nic has right name") - - self.assertEqual(nicdetail.value, self.nic, "Check if Nic has right value") - - #updatenicdetail - self.debug("Testing UPDATE nic detail Nic-ID: %s " % ( - self.nic - )) - cmd = updateNicDetail.updateNicDetailCmd() - cmd.name = self.nic - cmd.value = self.disk_offering.id - cmd.id = self.nic - self.apiclient.addNicDetail(cmd) - - listNicDetailCmd = listNicDetails.listNicDetailsCmd() - listNicDetailCmd.id = self.nic - listNicDetailResponse = self.api_client.listVirtualMachines(listNicDetailCmd) - - self.assertNotEqual(len(listNicDetailResponse), 0, "Check if the list API \ - returns a non-empty response") - - nicdetail = listNicDetailResponse[0] - - #self.assertEqual(nicdetail.id, self.nic, "Check if the Nic returned is the same as the one we asked for") - - - self.assertEqual(nicdetail.name, self.nic, "Check if Nic has right name") - - self.assertEqual(nicdetail.value, self.disk_offering.id, "Check if Nic has right value") - - - #remove detail - self.debug("Testing REMOVE nic detail Nic-ID: %s " % ( - self.nic - )) - cmd = removeNicDetail.removeNicDetailCmd() - cmd.name = self.nic - cmd.id = self.nic - self.apiclient.removeNicDetail(cmd) - - listNicDetailCmd = listNicDetails.listNicDetailsCmd() - listNicDetailCmd.id = self.nic - listNicDetailResponse = self.api_client.listVirtualMachines(listNicDetailCmd) - - self.assertEqual(listNicDetailResponse, None, "Check if the list API \ - returns a non-empty response") - - - return diff --git a/test/integration/smoke/test_primary_storage.py b/test/integration/smoke/test_primary_storage.py index eb747fa6588..598654da112 100644 --- a/test/integration/smoke/test_primary_storage.py +++ b/test/integration/smoke/test_primary_storage.py @@ -35,32 +35,17 @@ class Services: def __init__(self): self.services = { - "nfs": { - 0: { - "url": "nfs://192.168.100.131/testprimary", + "nfs": + { + "url": "nfs://10.147.28.7/export/home/talluri/testprimary", # Format: File_System_Type/Location/Path - "name": "Primary XEN", - "hypervisor": 'XEN', + "name": "Primary XEN" }, - 1: { - "url": "nfs://192.168.100.131/Primary", - "name": "Primary KVM", - "hypervisor": 'KVM', - }, - 2: { - "url": "nfs://192.168.100.131/Primary", - "name": "Primary VMWare", - "hypervisor": 'VMWare', - }, - }, "iscsi": { - 0: { "url": "iscsi://192.168.100.21/iqn.2012-01.localdomain.clo-cstack-cos6:iser/1", # Format : iscsi://IP Address/IQN number/LUN# - "name": "Primary iSCSI", - "hypervisor": 'XEN', - }, - }, + "name": "Primary iSCSI" + } } class TestPrimaryStorageServices(cloudstackTestCase): @@ -85,31 +70,27 @@ class TestPrimaryStorageServices(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @unittest.skip("skipped - will not be adding storage in our environments") - def test_01_primary_storage(self): + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + def test_01_primary_storage_nfs(self): """Test primary storage pools - XEN, KVM, VMWare """ # Validate the following: - # 1. verify hypervisortype returned by api is Xen/KVM/VMWare + # 1. List Clusters # 2. verify that the cluster is in 'Enabled' allocation state # 3. verify that the host is added successfully and # in Up state with listHosts api response #Create NFS storage pools with on XEN/KVM/VMWare clusters - for k, v in self.services["nfs"].items(): - clusters = list_clusters( - self.apiclient, - zoneid=self.zone.id, - hypervisortype=v["hypervisor"] - ) - self.assertEqual( - isinstance(clusters, list), - True, - "Check list response returns a valid list" - ) - cluster = clusters[0] + + clusters = list_clusters( + self.apiclient, + zoneid=self.zone.id + ) + assert isinstance(clusters,list) and len(clusters)>0 + for cluster in clusters: + #Host should be present before adding primary storage list_hosts_response = list_hosts( self.apiclient, @@ -124,11 +105,11 @@ class TestPrimaryStorageServices(cloudstackTestCase): self.assertNotEqual( len(list_hosts_response), 0, - "Check list Hosts for hypervisor: " + v["hypervisor"] + "Check list Hosts in the cluster: " + cluster.name ) storage = StoragePool.create(self.apiclient, - v, + self.services["nfs"], clusterid=cluster.id, zoneid=self.zone.id, podid=self.pod.id @@ -140,13 +121,13 @@ class TestPrimaryStorageServices(cloudstackTestCase): self.assertEqual( storage.state, 'Up', - "Check primary storage state for hypervisor: " + v["hypervisor"] + "Check primary storage state " ) self.assertEqual( storage.type, 'NetworkFilesystem', - "Check storage pool type for hypervisor : " + v["hypervisor"] + "Check storage pool type " ) #Verify List Storage pool Response has newly added storage pool @@ -169,45 +150,76 @@ class TestPrimaryStorageServices(cloudstackTestCase): self.assertEqual( storage_response.id, storage.id, - "Check storage pool ID for hypervisor: " + v["hypervisor"] + "Check storage pool ID" ) self.assertEqual( storage.type, storage_response.type, - "Check storage pool type for hypervisor: " + v["hypervisor"] + "Check storage pool type " ) # Call cleanup for reusing primary storage cleanup_resources(self.apiclient, self.cleanup) self.cleanup = [] + return + + + @attr(tags = ["advanced", "advancedns", "smoke", "basic", "sg"]) + def test_01_primary_storage_iscsi(self): + """Test primary storage pools - XEN, KVM, VMWare + """ + + # Validate the following: + # 1. List Clusters + # 2. verify that the cluster is in 'Enabled' allocation state + # 3. verify that the host is added successfully and + # in Up state with listHosts api response # Create iSCSI storage pools with on XEN/KVM clusters - for k, v in self.services["iscsi"].items(): - clusters = list_clusters( - self.apiclient, - zoneid=self.zone.id, - hypervisortype=v["hypervisor"] - ) + clusters = list_clusters( + self.apiclient, + zoneid=self.zone.id + ) + assert isinstance(clusters,list) and len(clusters)>0 + for cluster in clusters: + + #Host should be present before adding primary storage + list_hosts_response = list_hosts( + self.apiclient, + clusterid=cluster.id + ) self.assertEqual( - isinstance(clusters, list), + isinstance(list_hosts_response, list), True, "Check list response returns a valid list" ) - cluster = clusters[0] + + self.assertNotEqual( + len(list_hosts_response), + 0, + "Check list Hosts in the cluster: " + cluster + ) + storage = StoragePool.create(self.apiclient, - v, + self.services["iscsi"], clusterid=cluster.id, zoneid=self.zone.id, podid=self.pod.id ) self.cleanup.append(storage) - self.debug("Created iSCSI storage pool in cluster: %s" % cluster.id) - + self.debug("Created storage pool in cluster: %s" % cluster.id) + self.assertEqual( storage.state, 'Up', - "Check primary storage state for hypervisor: " + v["hypervisor"] + "Check primary storage state " + ) + + self.assertEqual( + storage.type, + 'NetworkFilesystem', + "Check storage pool type " ) #Verify List Storage pool Response has newly added storage pool @@ -221,24 +233,24 @@ class TestPrimaryStorageServices(cloudstackTestCase): "Check list response returns a valid list" ) self.assertNotEqual( - len(storage_pools_response), - 0, - "Check Hosts response for hypervisor: " + v["hypervisor"] + len(storage_pools_response), + 0, + "Check list Hosts response" ) storage_response = storage_pools_response[0] self.assertEqual( storage_response.id, storage.id, - "Check storage pool ID for hypervisor: " + v["hypervisor"] - ) + "Check storage pool ID" + ) self.assertEqual( storage.type, storage_response.type, - "Check storage pool type hypervisor: " + v["hypervisor"] + "Check storage pool type " ) - # Call cleanup for reusing primary storage cleanup_resources(self.apiclient, self.cleanup) self.cleanup = [] + return diff --git a/test/integration/smoke/test_privategw_acl.py b/test/integration/smoke/test_privategw_acl.py index 5daf6ca0a59..9c37e5e7fc0 100644 --- a/test/integration/smoke/test_privategw_acl.py +++ b/test/integration/smoke/test_privategw_acl.py @@ -22,6 +22,7 @@ from marvin.cloudstackAPI import * from marvin.integration.lib.utils import * from marvin.integration.lib.base import * from marvin.integration.lib.common import * +from nose.plugins.attrib import attr class TestPrivateGwACL(cloudstackTestCase): @@ -37,6 +38,8 @@ class TestPrivateGwACL(cloudstackTestCase): self.templateId = 5 self.privateGwId = None + + @attr(tags=["advanced"]) def test_privategw_acl(self): # 1) Create VPC diff --git a/test/integration/smoke/test_service_offerings.py b/test/integration/smoke/test_service_offerings.py index 7f4d130ee80..3d3b94684e8 100644 --- a/test/integration/smoke/test_service_offerings.py +++ b/test/integration/smoke/test_service_offerings.py @@ -27,24 +27,80 @@ from nose.plugins.attrib import attr _multiprocess_shared_ = True + class Services: """Test Service offerings Services """ def __init__(self): self.services = { - "off": - { - "name": "Service Offering", - "displaytext": "Service Offering", - "cpunumber": 1, - "cpuspeed": 100, # MHz - "memory": 128, # in MBs - }, - } + "off": + { + "name": "Service Offering", + "displaytext": "Service Offering", + "cpunumber": 1, + "cpuspeed": 100, # MHz + "memory": 128, # in MBs + }, + "small": + # Create a small virtual machine instance with disk offering + { + "displayname": "testserver", + "username": "root", # VM creds for SSH + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "medium": # Create a medium virtual machine instance + { + "displayname": "testserver", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "service_offerings": + { + "tiny": + { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "small": + { + # Small service offering ID to for change VM + # service offering from medium to small + "name": "Small Instance", + "displaytext": "Small Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + }, + "medium": + { + # Medium service offering ID to for + # change VM service offering from small to medium + "name": "Medium Instance", + "displaytext": "Medium Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + } + }, + "ostype": 'CentOS 5.3 (64-bit)', + } + class TestCreateServiceOffering(cloudstackTestCase): - def setUp(self): self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() @@ -60,8 +116,8 @@ class TestCreateServiceOffering(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + + @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) def test_01_create_service_offering(self): """Test to create service offering""" @@ -70,67 +126,65 @@ class TestCreateServiceOffering(cloudstackTestCase): # 2. The Cloud Database contains the valid information service_offering = ServiceOffering.create( - self.apiclient, - self.services["off"] - ) + self.apiclient, + self.services["off"] + ) self.cleanup.append(service_offering) self.debug("Created service offering with ID: %s" % service_offering.id) list_service_response = list_service_offering( - self.apiclient, - id=service_offering.id - ) + self.apiclient, + id=service_offering.id + ) self.assertEqual( - isinstance(list_service_response, list), - True, - "Check list response returns a valid list" - ) - + isinstance(list_service_response, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( - len(list_service_response), - 0, - "Check Service offering is created" - ) + len(list_service_response), + 0, + "Check Service offering is created" + ) service_response = list_service_response[0] self.assertEqual( - list_service_response[0].cpunumber, - self.services["off"]["cpunumber"], - "Check server id in createServiceOffering" - ) + list_service_response[0].cpunumber, + self.services["off"]["cpunumber"], + "Check server id in createServiceOffering" + ) self.assertEqual( - list_service_response[0].cpuspeed, - self.services["off"]["cpuspeed"], - "Check cpuspeed in createServiceOffering" - ) + list_service_response[0].cpuspeed, + self.services["off"]["cpuspeed"], + "Check cpuspeed in createServiceOffering" + ) self.assertEqual( - list_service_response[0].displaytext, - self.services["off"]["displaytext"], - "Check server displaytext in createServiceOfferings" - ) + list_service_response[0].displaytext, + self.services["off"]["displaytext"], + "Check server displaytext in createServiceOfferings" + ) self.assertEqual( - list_service_response[0].memory, - self.services["off"]["memory"], - "Check memory in createServiceOffering" - ) + list_service_response[0].memory, + self.services["off"]["memory"], + "Check memory in createServiceOffering" + ) self.assertEqual( - list_service_response[0].name, - self.services["off"]["name"], - "Check name in createServiceOffering" - ) + list_service_response[0].name, + self.services["off"]["name"], + "Check name in createServiceOffering" + ) return class TestServiceOfferings(cloudstackTestCase): - def setUp(self): self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() self.cleanup = [] def tearDown(self): - try: #Clean up, terminate the created templates cleanup_resources(self.apiclient, self.cleanup) @@ -142,17 +196,61 @@ class TestServiceOfferings(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.services = Services().services cls.api_client = super(TestServiceOfferings, cls).getClsTestClient().getApiClient() + cls.services = Services().services + domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype + cls.service_offering_1 = ServiceOffering.create( - cls.api_client, - cls.services["off"] - ) + cls.api_client, + cls.services["off"] + ) cls.service_offering_2 = ServiceOffering.create( - cls.api_client, - cls.services["off"] - ) - cls._cleanup = [cls.service_offering_1] + cls.api_client, + cls.services["off"] + ) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + # Set Zones and disk offerings + cls.services["small"]["zoneid"] = cls.zone.id + cls.services["small"]["template"] = template.id + + cls.services["medium"]["zoneid"] = cls.zone.id + cls.services["medium"]["template"] = template.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=domain.id + ) + + cls.small_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offerings"]["small"] + ) + + cls.medium_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offerings"]["medium"] + ) + cls.medium_virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["medium"], + accountid=cls.account.name, + domainid=cls.account.domainid, + serviceofferingid=cls.medium_offering.id, + mode=cls.services["mode"] + ) + cls._cleanup = [ + cls.small_offering, + cls.medium_offering, + cls.account + ] return @classmethod @@ -166,7 +264,7 @@ class TestServiceOfferings(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) def test_02_edit_service_offering(self): """Test to update existing service offering""" @@ -178,8 +276,8 @@ class TestServiceOfferings(cloudstackTestCase): random_displaytext = random_gen() random_name = random_gen() - self.debug("Updating service offering with ID: %s" % - self.service_offering_1.id) + self.debug("Updating service offering with ID: %s" % + self.service_offering_1.id) cmd = updateServiceOffering.updateServiceOfferingCmd() #Add parameters for API call @@ -189,35 +287,35 @@ class TestServiceOfferings(cloudstackTestCase): self.apiclient.updateServiceOffering(cmd) list_service_response = list_service_offering( - self.apiclient, - id=self.service_offering_1.id - ) + self.apiclient, + id=self.service_offering_1.id + ) self.assertEqual( - isinstance(list_service_response, list), - True, - "Check list response returns a valid list" - ) - + isinstance(list_service_response, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( - len(list_service_response), - 0, - "Check Service offering is updated" - ) + len(list_service_response), + 0, + "Check Service offering is updated" + ) self.assertEqual( - list_service_response[0].displaytext, - random_displaytext, - "Check server displaytext in updateServiceOffering" - ) + list_service_response[0].displaytext, + random_displaytext, + "Check server displaytext in updateServiceOffering" + ) self.assertEqual( - list_service_response[0].name, - random_name, - "Check server name in updateServiceOffering" - ) + list_service_response[0].name, + random_name, + "Check server name in updateServiceOffering" + ) return - @attr(tags = ["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) + @attr(tags=["advanced", "advancedns", "smoke", "basic", "eip", "sg"]) def test_03_delete_service_offering(self): """Test to delete service offering""" @@ -225,20 +323,108 @@ class TestServiceOfferings(cloudstackTestCase): # 1. deleteServiceOffering should return # a valid information for newly created offering - self.debug("Deleting service offering with ID: %s" % - self.service_offering_2.id) + self.debug("Deleting service offering with ID: %s" % + self.service_offering_2.id) self.service_offering_2.delete(self.apiclient) list_service_response = list_service_offering( - self.apiclient, - id=self.service_offering_2.id - ) + self.apiclient, + id=self.service_offering_2.id + ) self.assertEqual( - list_service_response, - None, - "Check if service offering exists in listDiskOfferings" - ) + list_service_response, + None, + "Check if service offering exists in listDiskOfferings" + ) return + + @attr(tags=["advanced", "advancedns", "smoke"]) + def test_04_change_offering_small(self): + """Test to change service to a small capacity + """ + # Validate the following + # 1. Log in to the Vm .We should see that the CPU and memory Info of + # this Vm matches the one specified for "Small" service offering. + # 2. Using listVM command verify that this Vm + # has Small service offering Id. + + self.debug("Stopping VM - ID: %s" % self.medium_virtual_machine.id) + self.medium_virtual_machine.stop(self.apiclient) + # Ensure that VM is in stopped state + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.medium_virtual_machine.id + ) + if isinstance(list_vm_response, list): + vm = list_vm_response[0] + if vm.state == 'Stopped': + self.debug("VM state: %s" % vm.state) + else: + raise Exception( + "Failed to stop VM (ID: %s) in change service offering" % vm.id) + + self.debug("Change Service offering VM - ID: %s" % + self.medium_virtual_machine.id) + + cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd() + cmd.id = self.medium_virtual_machine.id + cmd.serviceofferingid = self.small_offering.id + self.apiclient.changeServiceForVirtualMachine(cmd) + + self.debug("Starting VM - ID: %s" % self.medium_virtual_machine.id) + self.medium_virtual_machine.start(self.apiclient) + # Ensure that VM is in running state + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.medium_virtual_machine.id + ) + + if isinstance(list_vm_response, list): + vm = list_vm_response[0] + if vm.state == 'Running': + self.debug("VM state: %s" % vm.state) + else: + raise Exception( + "Failed to start VM (ID: %s) after changing service offering" % vm.id) + + try: + ssh = self.medium_virtual_machine.get_ssh_client() + except Exception as e: + self.fail( + "SSH Access failed for %s: %s" %\ + (self.medium_virtual_machine.ipaddress, e) + ) + + cpuinfo = ssh.execute("cat /proc/cpuinfo") + cpu_cnt = len([i for i in cpuinfo if "processor" in i]) + #'cpu MHz\t\t: 2660.499' + cpu_speed = [i for i in cpuinfo if "cpu MHz" in i][0].split()[3] + meminfo = ssh.execute("cat /proc/meminfo") + #MemTotal: 1017464 kB + total_mem = [i for i in meminfo if "MemTotal" in i][0].split()[1] + + self.debug( + "CPU count: %s, CPU Speed: %s, Mem Info: %s" % ( + cpu_cnt, + cpu_speed, + total_mem + )) + self.assertAlmostEqual( + int(cpu_cnt), + self.small_offering.cpunumber, + "Check CPU Count for small offering" + ) + self.assertAlmostEqual( + list_vm_response[0].cpuspeed, + self.small_offering.cpuspeed, + "Check CPU Speed for small offering" + ) + self.assertAlmostEqual( + int(total_mem) / 1024, # In MBs + self.small_offering.memory, + "Check Memory(kb) for small offering" + ) + return diff --git a/test/integration/smoke/test_vm_life_cycle.py b/test/integration/smoke/test_vm_life_cycle.py index d52ed9b8df6..8c78149addf 100644 --- a/test/integration/smoke/test_vm_life_cycle.py +++ b/test/integration/smoke/test_vm_life_cycle.py @@ -489,245 +489,6 @@ class TestVMLifeCycle(cloudstackTestCase): ) return - @attr(tags = ["advanced", "advancedns", "smoke"]) - def test_04_change_offering_small(self): - """Change Offering to a small capacity - """ - - # Validate the following - # 1. Log in to the Vm .We should see that the CPU and memory Info of - # this Vm matches the one specified for "Small" service offering. - # 2. Using listVM command verify that this Vm - # has Small service offering Id. - - self.debug("Stopping VM - ID: %s" % self.medium_virtual_machine.id) - - self.medium_virtual_machine.stop(self.apiclient) - - # Poll listVM to ensure VM is stopped properly - timeout = self.services["timeout"] - - while True: - time.sleep(self.services["sleep"]) - - # Ensure that VM is in stopped state - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.medium_virtual_machine.id - ) - - if isinstance(list_vm_response, list): - - vm = list_vm_response[0] - if vm.state == 'Stopped': - self.debug("VM state: %s" % vm.state) - break - - if timeout == 0: - raise Exception( - "Failed to stop VM (ID: %s) in change service offering" % vm.id) - - timeout = timeout - 1 - - self.debug("Change Service offering VM - ID: %s" % - self.medium_virtual_machine.id) - - cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd() - cmd.id = self.medium_virtual_machine.id - cmd.serviceofferingid = self.small_offering.id - self.apiclient.changeServiceForVirtualMachine(cmd) - - self.debug("Starting VM - ID: %s" % self.medium_virtual_machine.id) - self.medium_virtual_machine.start(self.apiclient) - - # Poll listVM to ensure VM is started properly - timeout = self.services["timeout"] - - while True: - time.sleep(self.services["sleep"]) - - # Ensure that VM is in running state - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.medium_virtual_machine.id - ) - - if isinstance(list_vm_response, list): - - vm = list_vm_response[0] - if vm.state == 'Running': - self.debug("VM state: %s" % vm.state) - break - - if timeout == 0: - raise Exception( - "Failed to start VM (ID: %s) after changing service offering" % vm.id) - - timeout = timeout - 1 - - try: - ssh = self.medium_virtual_machine.get_ssh_client() - except Exception as e: - self.fail( - "SSH Access failed for %s: %s" % \ - (self.medium_virtual_machine.ipaddress, e) - ) - - cpuinfo = ssh.execute("cat /proc/cpuinfo") - - cpu_cnt = len([i for i in cpuinfo if "processor" in i]) - #'cpu MHz\t\t: 2660.499' - cpu_speed = [i for i in cpuinfo if "cpu MHz" in i ][0].split()[3] - - meminfo = ssh.execute("cat /proc/meminfo") - #MemTotal: 1017464 kB - total_mem = [i for i in meminfo if "MemTotal" in i][0].split()[1] - - self.debug( - "CPU count: %s, CPU Speed: %s, Mem Info: %s" % ( - cpu_cnt, - cpu_speed, - total_mem - )) - self.assertAlmostEqual( - int(cpu_cnt), - self.small_offering.cpunumber, - "Check CPU Count for small offering" - ) - - self.assertAlmostEqual( - list_vm_response[0].cpuspeed, - self.small_offering.cpuspeed, - "Check CPU Speed for small offering" - ) - self.assertAlmostEqual( - int(total_mem) / 1024, # In MBs - self.small_offering.memory, - "Check Memory(kb) for small offering" - ) - return - - @attr(tags = ["advanced", "advancedns", "smoke"]) - def test_05_change_offering_medium(self): - """Change Offering to a medium capacity - """ - # Validate the following - # 1. Log in to the Vm .We should see that the CPU and memory Info of - # this Vm matches the one specified for "Medium" service offering. - # 2. Using listVM command verify that this Vm - # has Medium service offering Id. - - self.debug("Stopping VM - ID: %s" % self.small_virtual_machine.id) - self.small_virtual_machine.stop(self.apiclient) - - # Poll listVM to ensure VM is stopped properly - timeout = self.services["timeout"] - - while True: - time.sleep(self.services["sleep"]) - - # Ensure that VM is in stopped state - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.small_virtual_machine.id - ) - - if isinstance(list_vm_response, list): - - vm = list_vm_response[0] - if vm.state == 'Stopped': - self.debug("VM state: %s" % vm.state) - break - - if timeout == 0: - raise Exception( - "Failed to stop VM (ID: %s) in change service offering" % vm.id) - - timeout = timeout - 1 - - self.debug("Change service offering VM - ID: %s" % - self.small_virtual_machine.id) - - cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd() - cmd.id = self.small_virtual_machine.id - cmd.serviceofferingid = self.medium_offering.id - self.apiclient.changeServiceForVirtualMachine(cmd) - - self.debug("Starting VM - ID: %s" % self.small_virtual_machine.id) - self.small_virtual_machine.start(self.apiclient) - - # Poll listVM to ensure VM is started properly - timeout = self.services["timeout"] - - while True: - time.sleep(self.services["sleep"]) - - # Ensure that VM is in running state - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.small_virtual_machine.id - ) - - if isinstance(list_vm_response, list): - - vm = list_vm_response[0] - if vm.state == 'Running': - self.debug("VM state: %s" % vm.state) - break - - if timeout == 0: - raise Exception( - "Failed to start VM (ID: %s) after changing service offering" % vm.id) - - timeout = timeout - 1 - - list_vm_response = list_virtual_machines( - self.apiclient, - id=self.small_virtual_machine.id - ) - - try: - ssh_client = self.small_virtual_machine.get_ssh_client() - except Exception as e: - self.fail( - "SSH Access failed for %s: %s" % \ - (self.small_virtual_machine.ipaddress, e) - ) - - cpuinfo = ssh_client.execute("cat /proc/cpuinfo") - - cpu_cnt = len([i for i in cpuinfo if "processor" in i]) - #'cpu MHz\t\t: 2660.499' - cpu_speed = [i for i in cpuinfo if "cpu MHz" in i][0].split()[3] - - meminfo = ssh_client.execute("cat /proc/meminfo") - #MemTotal: 1017464 kB - total_mem = [i for i in meminfo if "MemTotal" in i][0].split()[1] - - self.debug( - "CPU count: %s, CPU Speed: %s, Mem Info: %s" % ( - cpu_cnt, - cpu_speed, - total_mem - )) - self.assertAlmostEqual( - int(cpu_cnt), - self.medium_offering.cpunumber, - "Check CPU Count for medium offering" - ) - - self.assertAlmostEqual( - list_vm_response[0].cpuspeed, - self.medium_offering.cpuspeed, - "Check CPU Speed for medium offering" - ) - - self.assertAlmostEqual( - int(total_mem) / 1024, # In MBs - self.medium_offering.memory, - "Check Memory(kb) for medium offering" - ) - return @attr(tags = ["devcloud", "advanced", "advancedns", "smoke", "basic", "sg"]) def test_06_destroy_vm(self): diff --git a/test/integration/smoke/test_volumedetail.py b/test/integration/smoke/test_volumedetail.py deleted file mode 100644 index f734dbb4de6..00000000000 --- a/test/integration/smoke/test_volumedetail.py +++ /dev/null @@ -1,239 +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. -""" P1 tests for Scaling up Vm -""" -#Import Local Modules -import marvin -from marvin.cloudstackTestCase import * -from marvin.cloudstackAPI import * -from marvin.remoteSSHClient import remoteSSHClient -from marvin.integration.lib.utils import * -from marvin.integration.lib.base import * -from marvin.integration.lib.common import * -from nose.plugins.attrib import attr -#Import System modules -import time - -_multiprocess_shared_ = True -class Services: - """Test VM Life Cycle Services - """ - - def __init__(self): - self.services = { - - "account": { - "email": "test@test.com", - "firstname": "Test", - "lastname": "User", - "username": "test", - # Random characters are appended in create account to - # ensure unique username generated each time - "password": "password", - }, - "small": - # Create a small virtual machine instance with disk offering - { - "displayname": "testserver", - "username": "root", # VM creds for SSH - "password": "password", - "ssh_port": 22, - "hypervisor": 'XenServer', - "privateport": 22, - "publicport": 22, - "protocol": 'TCP', - }, - "disk_offering": { - "displaytext": "Small", - "name": "Small", - "storagetype": "shared", - "disksize": 1 - }, - "service_offerings": - { - "small": - { - # Small service offering ID to for change VM - # service offering from medium to small - "name": "SmallInstance", - "displaytext": "SmallInstance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 256, - }, - "big": - { - # Big service offering ID to for change VM - "name": "BigInstance", - "displaytext": "BigInstance", - "cpunumber": 1, - "cpuspeed": 100, - "memory": 512, - } - }, - #Change this - "template": { - "displaytext": "xs", - "name": "xs", - "passwordenabled": False, - }, - "diskdevice": '/dev/xvdd', - # Disk device where ISO is attached to instance - "mount_dir": "/mnt/tmp", - "sleep": 60, - "timeout": 10, - #Migrate VM to hostid - "ostype": 'CentOS 5.6 (64-bit)', - # CentOS 5.3 (64-bit) - } - -class TestVolumeDetail(cloudstackTestCase): - - @classmethod - def setUpClass(cls): - cls.api_client = super(TestVolumeDetail, cls).getClsTestClient().getApiClient() - cls.services = Services().services - - # Get Zone, Domain and templates - domain = get_domain(cls.api_client, cls.services) - zone = get_zone(cls.api_client, cls.services) - cls.services['mode'] = zone.networktype - - # Set Zones and disk offerings ?? - - # Create account, service offerings, vm. - cls.account = Account.create( - cls.api_client, - cls.services["account"], - domainid=domain.id - ) - - - cls.disk_offering = DiskOffering.create( - cls.api_client, - cls.services["disk_offering"] - ) - - #create a volume - cls.volume = Volume.create( - cls.api_client, - { "diskname" : "ndm"}, - zoneid=zone.id, - account=cls.account.name, - domainid=cls.account.domainid, - diskofferingid=cls.disk_offering.id - ) - #how does it work ?? - cls._cleanup = [ - cls.volume, - cls.account - ] - - @classmethod - def tearDownClass(cls): - cls.api_client = super(TestVolumeDetail, cls).getClsTestClient().getApiClient() - cleanup_resources(cls.api_client, cls._cleanup) - return - - def setUp(self): - self.apiclient = self.testClient.getApiClient() - self.dbclient = self.testClient.getDbConnection() - self.cleanup = [] - - def tearDown(self): - #Clean up, terminate the created ISOs - cleanup_resources(self.apiclient, self.cleanup) - return - - @attr(tags = ["advanced", "xenserver"]) - def test_01_updatevolumedetail(self): - """Test volume detail - """ - # Validate the following - # Scale up the vm and see if it scales to the new svc offering and is finally in running state - - self.debug("Testing ADD volume detail Volume-ID: %s " % ( - self.volume.id - )) - - cmd = addVolumeDetail.addVolumeDetailCmd() - cmd.name = self.volume.id - cmd.value = self.volume.id - cmd.id = self.volume.id - self.apiclient.addVolumeDetail(cmd) - - listVolumeDetailCmd = listVolumeDetails.listVolumeDetailsCmd() - listVolumeDetailCmd.id = self.volume.id - listVolumeDetailResponse = self.api_client.listVirtualMachines(listVolumeDetailCmd) - - self.assertNotEqual(len(listVolumeDetailResponse), 0, "Check if the list API \ - returns a non-empty response") - - volumedetail = listVolumeDetailResponse[0] - - #self.assertEqual(volumedetail.id, self.volume.id, "Check if the Volume returned is the same as the one we asked for") - - - self.assertEqual(volumedetail.name, self.volume.id, "Check if Volume has right name") - - self.assertEqual(volumedetail.value, self.volume.id, "Check if Volume has right value") - - #updatevolumedetail - self.debug("Testing UPDATE volume detail Volume-ID: %s " % ( - self.volume.id - )) - cmd = updateVolumeDetail.updateVolumeDetailCmd() - cmd.name = self.volume.id - cmd.value = self.disk_offering.id - cmd.id = self.volume.id - self.apiclient.addVolumeDetail(cmd) - - listVolumeDetailCmd = listVolumeDetails.listVolumeDetailsCmd() - listVolumeDetailCmd.id = self.volume.id - listVolumeDetailResponse = self.api_client.listVirtualMachines(listVolumeDetailCmd) - - self.assertNotEqual(len(listVolumeDetailResponse), 0, "Check if the list API \ - returns a non-empty response") - - volumedetail = listVolumeDetailResponse[0] - - #self.assertEqual(volumedetail.id, self.volume.id, "Check if the Volume returned is the same as the one we asked for") - - - self.assertEqual(volumedetail.name, self.volume.id, "Check if Volume has right name") - - self.assertEqual(volumedetail.value, self.disk_offering.id, "Check if Volume has right value") - - - #remove detail - self.debug("Testing REMOVE volume detail Volume-ID: %s " % ( - self.volume.id - )) - cmd = removeVolumeDetail.removeVolumeDetailCmd() - cmd.name = self.volume.id - cmd.id = self.volume.id - self.apiclient.removeVolumeDetail(cmd) - - listVolumeDetailCmd = listVolumeDetails.listVolumeDetailsCmd() - listVolumeDetailCmd.id = self.volume.id - listVolumeDetailResponse = self.api_client.listVirtualMachines(listVolumeDetailCmd) - - self.assertEqual(listVolumeDetailResponse, None, "Check if the list API \ - returns a non-empty response") - - - return diff --git a/test/integration/smoke/test_volumes.py b/test/integration/smoke/test_volumes.py index 89b013a516f..d9c808a01d9 100644 --- a/test/integration/smoke/test_volumes.py +++ b/test/integration/smoke/test_volumes.py @@ -209,8 +209,8 @@ class TestCreateVolume(cloudstackTestCase): ) try: ssh = self.virtual_machine.get_ssh_client() + self.debug("Rebooting VM %s" % self.virtual_machine.id) ssh.execute("reboot") - except Exception as e: self.fail("SSH access failed for VM %s - %s" % (self.virtual_machine.ipaddress, e)) @@ -536,7 +536,7 @@ class TestVolumes(cloudstackTestCase): @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) def test_07_resize_fail(self): - """Verify invalid options fail to Resize a volume""" + """Test resize (negative) non-existent volume""" # Verify the size is the new size is what we wanted it to be. self.debug("Fail Resize Volume ID: %s" % self.volume.id) @@ -584,7 +584,12 @@ class TestVolumes(cloudstackTestCase): self.virtual_machine.attach_volume(self.apiClient, self.volume) self.attached = True #stop the vm if it is on xenserver - if self.services['hypervisor'].lower() == "xenserver": + hosts = Host.list(self.apiClient, id=self.virtual_machine.hostid) + self.assertTrue(isinstance(hosts, list)) + self.assertTrue(len(hosts) > 0) + self.debug("Found %s host" % hosts[0].hypervisor) + + if hosts[0].hypervisor == "XenServer": self.virtual_machine.stop(self.apiClient) self.apiClient.resizeVolume(cmd) @@ -610,23 +615,28 @@ class TestVolumes(cloudstackTestCase): True, "Verify the volume did not resize" ) - if self.services['hypervisor'].lower() == "xenserver": + if hosts[0].hypervisor == "XenServer": self.virtual_machine.start(self.apiClient) @attr(tags = ["advanced", "advancedns", "smoke", "basic"]) def test_08_resize_volume(self): - """Resize a volume""" + """Test resize a volume""" # Verify the size is the new size is what we wanted it to be. self.debug( "Attaching volume (ID: %s) to VM (ID: %s)" % ( self.volume.id, self.virtual_machine.id )) + self.virtual_machine.attach_volume(self.apiClient, self.volume) self.attached = True + hosts = Host.list(self.apiClient, id=self.virtual_machine.hostid) + self.assertTrue(isinstance(hosts, list)) + self.assertTrue(len(hosts) > 0) + self.debug("Found %s host" % hosts[0].hypervisor) - if self.services['hypervisor'].lower() == "xenserver": + if hosts[0].hypervisor == "XenServer": self.virtual_machine.stop(self.apiClient) self.debug("Resize Volume ID: %s" % self.volume.id) @@ -659,7 +669,9 @@ class TestVolumes(cloudstackTestCase): "Check if the volume resized appropriately" ) - if self.services['hypervisor'].lower() == "xenserver": + #start the vm if it is on xenserver + + if hosts[0].hypervisor == "XenServer": self.virtual_machine.start(self.apiClient) @attr(tags = ["advanced", "advancedns", "smoke","basic"]) diff --git a/test/setup-test-data.sh b/test/setup-test-data.sh deleted file mode 100755 index 844c275da7c..00000000000 --- a/test/setup-test-data.sh +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/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. - -usage() { - printf "Usage: %s:\n - [-t path to tests ] \n - [-m mgmt-server ] \n - [-h hypervisor (xen|kvm) ] \n - [-p hypervisor root password ] \n - [-d db node url ]\n" $(basename $0) >&2 -} - -failed() { - exit $1 -} - -#defaults -TESTDIR="/root/cloudstack/test/" -MGMT_SVR="localhost" -DB_SVR="localhost" -HV_PASSWD="password" - -while getopts 't:d:m:p:h:' OPTION -do - case $OPTION in - d) dflag=1 - DB_SVR="$OPTARG" - ;; - t) tflag=1 - TESTDIR="$OPTARG" - ;; - m) mflag=1 - MGMT_SVR="$OPTARG" - ;; - h) hflag=1 - HV="$OPTARG" - ;; - p) pflag=1 - HV_PASSWD="$OPTARG" - ;; - ?) usage - failed 2 - ;; - esac -done - -#Damn Small Linux ISO type -if [[ $HV == "kvm" ]]; then - ostypeid=$(mysql -ucloud -Dcloud -pcloud -h$DB_SVR -s -N -r -e"select uuid from guest_os where display_name='CentOS 5.5 (64-bit)'") -else - ostypeid=$(mysql -ucloud -Dcloud -pcloud -h$DB_SVR -s -N -r -e"select uuid from guest_os where display_name='CentOS 5.3 (64-bit)'") -fi -if [[ $ostypeid == "" ]]; then - echo "Unable to contact DB server @ $DB_SVR" - exit 2 -fi - -nc -z $MGMT_SVR 8096 -if [[ $? -ne 0 ]]; then - echo "$MGMT_SVR doesn't have port 8096 open" - exit 2 -fi - -if [[ ! -d $TESTDIR ]]; then - echo "No directory $TESTDIR found" - exit 2 -fi -for file in `find $TESTDIR -name *.py -type f` -do - old_ostypeid=$(grep ostypeid $file | head -1 | cut -d: -f2 | tr -d " ,'") - if [[ $old_ostypeid != "" ]] - then - echo "replacing:" $old_ostypeid, "with:" $ostypeid,"in " $file - sed -i "s/$old_ostypeid/$ostypeid/g" $file - #sed -i "s/http:\/\/iso.linuxquestions.org\/download\/504\/1819\/http\/gd4.tuwien.ac.at\/dsl-4.4.10.iso/http:\/\/nfs1.lab.vmops.com\/isos_32bit\/dsl-4.4.10.iso/g" $file - sed -i "s/fr3sca/$HV_PASSWD/g" $file - fi -done - -#Python version check -version_tuple=$(python -c 'import sys; print(sys.version_info[:2])') -if [[ $version_tuple == "(2, 7)" ]] -then - echo "Done" -else - echo "WARN: Python version 2.7 not detected on system." -fi diff --git a/tools/cli/cloudmonkey/cachemaker.py b/tools/cli/cloudmonkey/cachemaker.py index a625b014d38..47749e5ae74 100644 --- a/tools/cli/cloudmonkey/cachemaker.py +++ b/tools/cli/cloudmonkey/cachemaker.py @@ -101,7 +101,7 @@ def monkeycache(apis): cache['asyncapis'] = [] apilist = getvalue(apis[responsekey], 'api') - if apilist == None: + if apilist is None: print "[monkeycache] Server response issue, no apis found" for api in apilist: diff --git a/tools/devcloud/devcloud-advancedsg.cfg b/tools/devcloud/devcloud-advancedsg.cfg new file mode 100644 index 00000000000..6c26b15f5da --- /dev/null +++ b/tools/devcloud/devcloud-advancedsg.cfg @@ -0,0 +1,119 @@ +# 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. +# +# This configuration is meant for running advanced networking with security groups, with management server on the laptop. +# It requires that the user run a DNS resolver within devcloud via 'apt-get install dnsmasq' + +{ + "zones": [ + { + "localstorageenabled": "true", + "name": "testzone", + "dns1": "8.8.8.8", + "physical_networks": [ + { + "broadcastdomainrange": "Zone", + "name": "shared", + "traffictypes": [ + { + "typ": "Management" + }, + { + "typ": "Guest" + } + ], + "providers": [ + { + "broadcastdomainrange": "ZONE", + "name": "VirtualRouter" + }, + { + "broadcastdomainrange": "ZONE", + "name": "SecurityGroupProvider" + } + ], + "isolationmethods": [ + "VLAN" + ] + } + ], + "securitygroupenabled": "true", + "ipranges": [ + { + "startip": "10.0.3.100", + "endip": "10.0.3.199", + "netmask": "255.255.255.0", + "vlan": "1003", + "gateway": "10.0.3.2" + } + ], + "networktype": "Advanced", + "pods": [ + { + "endip": "192.168.56.249", + "name": "testpod", + "startip": "192.168.56.200", + "netmask": "255.255.255.0", + "clusters": [ + { + "clustername": "testcluster", + "hypervisor": "XenServer", + "hosts": [ + { + "username": "root", + "url": "http://192.168.56.10/", + "password": "password" + } + ], + "clustertype": "CloudManaged" + } + ], + "gateway": "192.168.56.1" + } + ], + "internaldns1": "192.168.56.10", + "secondaryStorages": [ + { + "url": "nfs://192.168.56.10/opt/storage/secondary" + } + ] + } + ], + "dbSvr": { + "dbSvr": "localhost", + "passwd": "cloud", + "db": "cloud", + "port": 3306, + "user": "cloud" + }, + "logger": [ + { + "name": "TestClient", + "file": "/var/log/testclient.log" + }, + { + "name": "TestCase", + "file": "/var/log/testcase.log" + } + ], + "mgtSvr": [ + { + "mgtSvrIp": "127.0.0.1", + "port": 8096 + } + ] +} diff --git a/tools/marvin/marvin/TestCaseExecuteEngine.py b/tools/marvin/marvin/TestCaseExecuteEngine.py index 57438688486..4b64aaee835 100644 --- a/tools/marvin/marvin/TestCaseExecuteEngine.py +++ b/tools/marvin/marvin/TestCaseExecuteEngine.py @@ -72,7 +72,7 @@ class TestCaseExecuteEngine(object): self.injectTestCase(test) else: #logger bears the name of the test class - testcaselogger = logging.getLogger("testclient.testcase.%s"%test.__class__.__name__) + testcaselogger = logging.getLogger("%s" % (test)) fh = logging.FileHandler(self.logfile) fh.setFormatter(self.logformat) testcaselogger.addHandler(fh) diff --git a/tools/marvin/marvin/cloudstackConnection.py b/tools/marvin/marvin/cloudstackConnection.py index e3977dcf7d4..b092ef0c32f 100644 --- a/tools/marvin/marvin/cloudstackConnection.py +++ b/tools/marvin/marvin/cloudstackConnection.py @@ -219,7 +219,10 @@ class cloudConnection(object): cmdname, self.auth, payload=payload, method=method) self.logging.debug("Request: %s Response: %s" % (response.url, response.text)) - response = jsonHelper.getResultObj(response.json(), response_type) + try: + response = jsonHelper.getResultObj(response.json(), response_type) + except TypeError: + response = jsonHelper.getResultObj(response.json, response_type) if isAsync == "false": return response diff --git a/tools/marvin/marvin/configGenerator.py b/tools/marvin/marvin/configGenerator.py index 4e82bbe387d..c970ada850a 100644 --- a/tools/marvin/marvin/configGenerator.py +++ b/tools/marvin/marvin/configGenerator.py @@ -638,6 +638,126 @@ def describe_setup_in_advanced_mode(): return zs +'''sample code to generate setup configuration file''' +def describe_setup_in_advancedsg_mode(): + zs = cloudstackConfiguration() + + for l in range(1): + z = zone() + z.dns1 = "8.8.8.8" + z.dns2 = "4.4.4.4" + z.internaldns1 = "192.168.110.254" + z.internaldns2 = "192.168.110.253" + z.name = "test"+str(l) + z.networktype = 'Advanced' + z.vlan = "100-2000" + z.securitygroupenabled = "true" + + pn = physical_network() + pn.name = "test-network" + pn.traffictypes = [traffictype("Guest"), traffictype("Management")] + + #If security groups are reqd + sgprovider = provider() + sgprovider.broadcastdomainrange = 'ZONE' + sgprovider.name = 'SecurityGroupProvider' + + pn.providers.append(sgprovider) + z.physical_networks.append(pn) + + '''create 10 pods''' + for i in range(2): + p = pod() + p.name = "test" +str(l) + str(i) + p.gateway = "192.168.%d.1"%i + p.netmask = "255.255.255.0" + p.startip = "192.168.%d.200"%i + p.endip = "192.168.%d.220"%i + + '''add 10 clusters''' + for j in range(2): + c = cluster() + c.clustername = "test"+str(l)+str(i) + str(j) + c.clustertype = "CloudManaged" + c.hypervisor = "Simulator" + + '''add 10 hosts''' + for k in range(2): + h = host() + h.username = "root" + h.password = "password" + memory = 8*1024*1024*1024 + localstorage=1*1024*1024*1024*1024 + #h.url = "http://sim/%d%d%d%d/cpucore=1&cpuspeed=8000&memory=%d&localstorage=%d"%(l,i,j,k,memory,localstorage) + h.url = "http://sim/%d%d%d%d"%(l,i,j,k) + c.hosts.append(h) + + '''add 2 primary storages''' + for m in range(2): + primary = primaryStorage() + primary.name = "primary"+str(l) + str(i) + str(j) + str(m) + #primary.url = "nfs://localhost/path%s/size=%d"%(str(l) + str(i) + str(j) + str(m), size) + primary.url = "nfs://localhost/path%s"%(str(l) + str(i) + str(j) + str(m)) + c.primaryStorages.append(primary) + + p.clusters.append(c) + + z.pods.append(p) + + '''add two secondary''' + for i in range(5): + secondary = secondaryStorage() + secondary.url = "nfs://localhost/path"+str(l) + str(i) + z.secondaryStorages.append(secondary) + + '''add default guest network''' + ips = iprange() + ips.vlan = "26" + ips.startip = "172.16.26.2" + ips.endip = "172.16.26.100" + ips.gateway = "172.16.26.1" + ips.netmask = "255.255.255.0" + z.ipranges.append(ips) + + + zs.zones.append(z) + + '''Add one mgt server''' + mgt = managementServer() + mgt.mgtSvrIp = "localhost" + zs.mgtSvr.append(mgt) + + '''Add a database''' + db = dbServer() + db.dbSvr = "localhost" + + zs.dbSvr = db + + '''add global configuration''' + global_settings = {'expunge.delay': '60', + 'expunge.interval': '60', + 'expunge.workers': '3', + } + for k,v in global_settings.iteritems(): + cfg = configuration() + cfg.name = k + cfg.value = v + zs.globalConfig.append(cfg) + + ''''add loggers''' + testClientLogger = logger() + testClientLogger.name = "TestClient" + testClientLogger.file = "/tmp/testclient.log" + + testCaseLogger = logger() + testCaseLogger.name = "TestCase" + testCaseLogger.file = "/tmp/testcase.log" + + zs.logger.append(testClientLogger) + zs.logger.append(testCaseLogger) + + return zs + def generate_setup_config(config, file=None): describe = config if file is None: @@ -666,6 +786,7 @@ if __name__ == "__main__": parser.add_option("-i", "--input", action="store", default=None , dest="inputfile", help="input file") parser.add_option("-a", "--advanced", action="store_true", default=False, dest="advanced", help="use advanced networking") + parser.add_option("-s", "--advancedsg", action="store_true", default=False, dest="advancedsg", help="use advanced networking with security groups") parser.add_option("-o", "--output", action="store", default="./datacenterCfg", dest="output", help="the path where the json config file generated, by default is ./datacenterCfg") (options, args) = parser.parse_args() @@ -674,6 +795,8 @@ if __name__ == "__main__": config = get_setup_config(options.inputfile) if options.advanced: config = describe_setup_in_advanced_mode() + elif options.advancedsg: + config = describe_setup_in_advancedsg_mode() else: config = describe_setup_in_basic_mode() diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py index 7059059beb1..cf5cf782676 100644 --- a/tools/marvin/marvin/deployDataCenter.py +++ b/tools/marvin/marvin/deployDataCenter.py @@ -300,7 +300,8 @@ class deployDataCenters(): createzone.securitygroupenabled = zone.securitygroupenabled createzone.localstorageenabled = zone.localstorageenabled createzone.networktype = zone.networktype - createzone.guestcidraddress = zone.guestcidraddress + if zone.securitygroupenabled != "true": + createzone.guestcidraddress = zone.guestcidraddress zoneresponse = self.apiClient.createZone(createzone) zoneId = zoneresponse.id @@ -334,10 +335,37 @@ class deployDataCenters(): self.createVlanIpRanges(zone.networktype, zone.ipranges, \ zoneId, forvirtualnetwork=True) - if zone.networktype == "Advanced": + if zone.networktype == "Advanced" and zone.securitygroupenabled != "true": self.createpods(zone.pods, zoneId) self.createVlanIpRanges(zone.networktype, zone.ipranges, \ zoneId) + elif zone.networktype == "Advanced" and zone.securitygroupenabled == "true": + listnetworkoffering = listNetworkOfferings.listNetworkOfferingsCmd() + listnetworkoffering.name = "DefaultSharedNetworkOfferingWithSGService" + if zone.networkofferingname is not None: + listnetworkoffering.name = zone.networkofferingname + + listnetworkofferingresponse = \ + self.apiClient.listNetworkOfferings(listnetworkoffering) + + networkcmd = createNetwork.createNetworkCmd() + networkcmd.displaytext = "Shared SG enabled network" + networkcmd.name = "Shared SG enabled network" + networkcmd.networkofferingid = listnetworkofferingresponse[0].id + networkcmd.zoneid = zoneId + + ipranges = zone.ipranges + if ipranges: + iprange = ipranges.pop() + networkcmd.startip = iprange.startip + networkcmd.endip = iprange.endip + networkcmd.gateway = iprange.gateway + networkcmd.netmask = iprange.netmask + networkcmd.vlan = iprange.vlan + + networkcmdresponse = self.apiClient.createNetwork(networkcmd) + networkId = networkcmdresponse.id + self.createpods(zone.pods, zoneId, networkId) self.createSecondaryStorages(zone.secondaryStorages, zoneId) diff --git a/tools/marvin/marvin/sandbox/advancedsg/__init__.py b/tools/marvin/marvin/sandbox/advancedsg/__init__.py new file mode 100644 index 00000000000..57823fcc162 --- /dev/null +++ b/tools/marvin/marvin/sandbox/advancedsg/__init__.py @@ -0,0 +1,18 @@ +# 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. + + diff --git a/tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py b/tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py new file mode 100644 index 00000000000..f9edf4d5803 --- /dev/null +++ b/tools/marvin/marvin/sandbox/advancedsg/advancedsg_env.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python +# 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. +''' +############################################################ +# Experimental state of scripts +# * Need to be reviewed +# * Only a sandbox +############################################################ +''' +import random +import marvin +from ConfigParser import SafeConfigParser +from optparse import OptionParser +from marvin.configGenerator import * + + +def getGlobalSettings(config): + for k, v in dict(config.items('globals')).iteritems(): + cfg = configuration() + cfg.name = k + cfg.value = v + yield cfg + + +def describeResources(config): + zs = cloudstackConfiguration() + + z = zone() + z.dns1 = config.get('environment', 'dns') + z.internaldns1 = config.get('environment', 'dns') + z.name = 'Sandbox-%s'%(config.get('cloudstack', 'hypervisor')) + z.networktype = 'Advanced' + z.securitygroupenabled = 'true' + + sgprovider = provider() + sgprovider.broadcastdomainrange = 'ZONE' + sgprovider.name = 'SecurityGroupProvider' + + pn = physical_network() + pn.name = "Sandbox-pnet" + pn.tags = ["cloud-simulator-pnet"] + pn.traffictypes = [traffictype("Guest"), + traffictype("Management", {"simulator" : "cloud-simulator-mgmt"})] + pn.isolationmethods = ["VLAN"] + pn.providers.append(sgprovider) + + z.physical_networks.append(pn) + + p = pod() + p.name = 'POD0' + p.gateway = config.get('cloudstack', 'private.gateway') + p.startip = config.get('cloudstack', 'private.pod.startip') + p.endip = config.get('cloudstack', 'private.pod.endip') + p.netmask = config.get('cloudstack', 'private.netmask') + + v = iprange() + v.gateway = config.get('cloudstack', 'guest.gateway') + v.startip = config.get('cloudstack', 'guest.vlan.startip') + v.endip = config.get('cloudstack', 'guest.vlan.endip') + v.netmask = config.get('cloudstack', 'guest.netmask') + v.vlan = config.get('cloudstack', 'guest.vlan') + z.ipranges.append(v) + + c = cluster() + c.clustername = 'C0' + c.hypervisor = config.get('cloudstack', 'hypervisor') + c.clustertype = 'CloudManaged' + + h = host() + h.username = 'root' + h.password = config.get('cloudstack', 'host.password') + h.url = 'http://%s'%(config.get('cloudstack', 'host')) + c.hosts.append(h) + + ps = primaryStorage() + ps.name = 'PS0' + ps.url = config.get('cloudstack', 'primary.pool') + c.primaryStorages.append(ps) + + p.clusters.append(c) + z.pods.append(p) + + secondary = secondaryStorage() + secondary.url = config.get('cloudstack', 'secondary.pool') + z.secondaryStorages.append(secondary) + + '''Add zone''' + zs.zones.append(z) + + '''Add mgt server''' + mgt = managementServer() + mgt.mgtSvrIp = config.get('environment', 'mshost') + mgt.user = config.get('environment', 'mshost.user') + mgt.passwd = config.get('environment', 'mshost.passwd') + zs.mgtSvr.append(mgt) + + '''Add a database''' + db = dbServer() + db.dbSvr = config.get('environment', 'mysql.host') + db.user = config.get('environment', 'mysql.cloud.user') + db.passwd = config.get('environment', 'mysql.cloud.passwd') + zs.dbSvr = db + + '''Add some configuration''' + [zs.globalConfig.append(cfg) for cfg in getGlobalSettings(config)] + + ''''add loggers''' + testClientLogger = logger() + testClientLogger.name = 'TestClient' + testClientLogger.file = 'testclient.log' + + testCaseLogger = logger() + testCaseLogger.name = 'TestCase' + testCaseLogger.file = 'testcase.log' + + zs.logger.append(testClientLogger) + zs.logger.append(testCaseLogger) + return zs + + +if __name__ == '__main__': + parser = OptionParser() + parser.add_option('-i', '--input', action='store', default='setup.properties', \ + dest='input', help='file containing environment setup information') + parser.add_option('-o', '--output', action='store', default='./sandbox.cfg', \ + dest='output', help='path where environment json will be generated') + + + (opts, args) = parser.parse_args() + + cfg_parser = SafeConfigParser() + cfg_parser.read(opts.input) + + cfg = describeResources(cfg_parser) + generate_setup_config(cfg, opts.output) diff --git a/tools/marvin/marvin/sandbox/advancedsg/setup.properties b/tools/marvin/marvin/sandbox/advancedsg/setup.properties new file mode 100644 index 00000000000..ee07ce23938 --- /dev/null +++ b/tools/marvin/marvin/sandbox/advancedsg/setup.properties @@ -0,0 +1,61 @@ +# 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. + + +[globals] +#global settings in cloudstack +expunge.delay=60 +expunge.interval=60 +storage.cleanup.interval=300 +account.cleanup.interval=600 +expunge.workers=3 +workers=10 +vm.allocation.algorithm=random +vm.op.wait.interval=5 +guest.domain.suffix=sandbox.simulator +instance.name=QA +direct.agent.load.size=1000 +default.page.size=10000 +check.pod.cidrs=true +secstorage.allowed.internal.sites=10.147.28.0/24 +[environment] +dns=10.147.28.6 +mshost=localhost +mshost.user=root +mshost.passwd=password +mysql.host=localhost +mysql.cloud.user=cloud +mysql.cloud.passwd=cloud +[cloudstack] +#management network +private.gateway=10.147.29.1 +private.pod.startip=10.147.29.150 +private.pod.endip=10.147.29.159 +private.netmask=255.255.255.0 +#guest network +guest.gateway=10.147.31.1 +guest.vlan=31 +guest.vlan.startip=10.147.31.150 +guest.vlan.endip=10.147.31.159 +guest.netmask=255.255.255.0 +#hypervisor host information +hypervisor=Simulator +host=simulator0 +host.password=password +#storage pools +primary.pool=nfs://10.147.28.6:/export/home/sandbox/primary +secondary.pool=nfs://10.147.28.6:/export/home/sandbox/sstor diff --git a/tools/marvin/setup.py b/tools/marvin/setup.py index 8dfd1b895d0..eeed3bfa8fd 100644 --- a/tools/marvin/setup.py +++ b/tools/marvin/setup.py @@ -45,7 +45,7 @@ setup(name="Marvin", url="https://builds.apache.org/job/cloudstack-marvin/", packages=["marvin", "marvin.cloudstackAPI", "marvin.integration", "marvin.integration.lib", "marvin.sandbox", - "marvin.sandbox.advanced", "marvin.sandbox.basic"], + "marvin.sandbox.advanced", "marvin.sandbox.advancedsg", "marvin.sandbox.basic"], license="LICENSE.txt", install_requires=[ "mysql-connector-python", diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 7f6df22797e..da647877f27 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -7925,6 +7925,7 @@ div.ui-dialog div.multi-edit-add-list div.view div.data-table table.body tbody t width: 87px !important; min-width: 87px !important; max-width: 87px !important; + font-size: 10px; } /** Header fields*/ @@ -7974,6 +7975,15 @@ div.ui-dialog div.multi-edit-add-list div.view div.data-table table.body tbody t .multi-edit .header-fields input[type=submit] { } +/* Sortable */ +.multi-edit table tbody tr td.reorder, +.multi-edit table thead tr th.reorder { + width: 30px !important; + min-width: 30px !important; + max-width: 30px !important; +} + + /*Security Rules*/ .security-rules .multi-edit input { width: 69px; @@ -11726,13 +11736,15 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it .destroy .icon, .remove .icon, .delete .icon, -.decline .icon { +.decline .icon, +.deleteacllist .icon { background-position: 1px -92px; } .destroy:hover .icon, .remove:hover .icon, -.delete:hover .icon { +.delete:hover .icon, +.deleteacllist:hover .icon { background-position: 1px -674px; } @@ -11818,13 +11830,15 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it .downloadVolume .icon, .downloadTemplate .icon, -.downloadISO .icon { +.downloadISO .icon, +.replaceacllist .icon { background-position: -35px -125px; } .downloadVolume:hover .icon, .downloadTemplate:hover .icon, -.downloadISO:hover .icon { +.downloadISO:hover .icon, +.replaceacllist:hover .icon { background-position: -35px -707px; } @@ -11857,12 +11871,14 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it } .add .icon, -.addNew .icon { +.addNew .icon, +.assignVm .icon { background-position: -37px -61px; } .add:hover .icon, -.addNew:hover .icon { +.addNew:hover .icon, +.assignVm:hover .icon { background-position: -37px -643px; } diff --git a/ui/images/sprites.png b/ui/images/sprites.png index 132588d1004..f3c8226b64a 100644 Binary files a/ui/images/sprites.png and b/ui/images/sprites.png differ diff --git a/ui/index.jsp b/ui/index.jsp index 8f31740a039..2992afb5c31 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -15,7 +15,7 @@ software distributed under the License is distributed on an KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ---%> +--%><%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> diff --git a/ui/modules/modules.js b/ui/modules/modules.js index d4502a195bc..1e4cd45c833 100644 --- a/ui/modules/modules.js +++ b/ui/modules/modules.js @@ -16,6 +16,7 @@ // under the License. (function($, cloudStack) { cloudStack.modules = [ + 'vpc', 'infrastructure', 'vnmcNetworkProvider', 'vnmcAsa1000v' diff --git a/ui/modules/vpc/vpc.css b/ui/modules/vpc/vpc.css new file mode 100644 index 00000000000..51c3f7e05bd --- /dev/null +++ b/ui/modules/vpc/vpc.css @@ -0,0 +1,313 @@ +/*[fmt]1C20-1C0D-E*/ +/* +* 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. +*/ +.vpc-network-chart { + width: 100%; + height: 100%; + overflow: auto; +} + +.vpc-network-chart .tiers { + margin: 40px 46px 0 0; + width: 362px; + float: right; +} + +.vpc-network-chart .tier-item { + border: 1px solid #477FB4; + overflow: hidden; + width: 326px; + height: 182px; + margin: 18px; + /*+border-radius:4px;*/ + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; + background: #8DB1D3; +} + +.vpc-network-chart .tier-item .header { + width: 100%; + float: left; + padding: 7px 0 6px; + position: relative; + /*+box-shadow:inset 0px 1px 1px #FFFFFF;*/ + -moz-box-shadow: inset 0px 1px 1px #FFFFFF; + -webkit-box-shadow: inset 0px 1px 1px #FFFFFF; + -o-box-shadow: inset 0px 1px 1px #FFFFFF; + box-shadow: inset 0px 1px 1px #FFFFFF; + background: #69839D; + border-bottom: 1px solid #40639E; +} + +.vpc-network-chart .tier-item .header .detail-link { + cursor: pointer; + background: #435667 url(../../images/sprites.png) -428px -83px; + /*+box-shadow:inset 0px 1px 4px #2F2F2F;*/ + -moz-box-shadow: inset 0px 1px 4px #2F2F2F; + -webkit-box-shadow: inset 0px 1px 4px #2F2F2F; + -o-box-shadow: inset 0px 1px 4px #2F2F2F; + box-shadow: inset 0px 1px 4px #2F2F2F; + width: 16px; + height: 16px; + float: right; + /*+placement:shift -8px 2px;*/ + position: relative; + left: -8px; + top: 2px; + /*+border-radius:10px;*/ + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + -khtml-border-radius: 10px; + border-radius: 10px; +} + +.vpc-network-chart .tier-item .header .detail-link:hover { + background-color: #454545; +} + +.vpc-network-chart .tier-item .header .title { + margin-left: 9px; + width: 268px; + height: 20px; + float: left; + overflow: hidden; +} + +.vpc-network-chart .tier-item .header .title span { + font-size: 20px; + color: #FFFFFF; + /*+text-shadow:0px 1px 1px #000000;*/ + -moz-text-shadow: 0px 1px 1px #000000; + -webkit-text-shadow: 0px 1px 1px #000000; + -o-text-shadow: 0px 1px 1px #000000; + text-shadow: 0px 1px 1px #000000; +} + +.vpc-network-chart .tier-item .content { + width: 100%; + height: 100%; + /*+box-shadow:inset 0px 1px 1px #FFFFFF;*/ + -moz-box-shadow: inset 0px 1px 1px #FFFFFF; + -webkit-box-shadow: inset 0px 1px 1px #FFFFFF; + -o-box-shadow: inset 0px 1px 1px #FFFFFF; + box-shadow: inset 0px 1px 1px #FFFFFF; + border-bottom: 1px solid #8DB1D3; +} + +.vpc-network-chart .tier-item .content .dashboard { + height: 117px; +} + +.vpc-network-chart .tier-item .content .dashboard-item { + width: 145px; + height: 54px; + margin: 7px 9px 0; + background: #C1E0FE; + /*+border-radius:4px;*/ + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; + float: left; + cursor: pointer; +} + +.vpc-network-chart .tier-item .content .dashboard-item:hover { + background-color: #DBEDFE; + /*+box-shadow:inset 0px 1px 2px #000000;*/ + -moz-box-shadow: inset 0px 1px 2px #000000; + -webkit-box-shadow: inset 0px 1px 2px #000000; + -o-box-shadow: inset 0px 1px 2px #000000; + box-shadow: inset 0px 1px 2px #000000; +} + +.vpc-network-chart .tier-item .content .dashboard-item .total { + font-size: 30px; + /*+placement:shift 7px 5px;*/ + position: relative; + left: 7px; + top: 5px; + color: #145CA1; + font-weight: 100; + /*+text-shadow:0px 1px 1px #FFFFFF;*/ + -moz-text-shadow: 0px 1px 1px #FFFFFF; + -webkit-text-shadow: 0px 1px 1px #FFFFFF; + -o-text-shadow: 0px 1px 1px #FFFFFF; + text-shadow: 0px 1px 1px #FFFFFF; +} + +.vpc-network-chart .tier-item .content .dashboard-item .total.multiline { + font-size: 14px; +} + +.vpc-network-chart .tier-item .content .dashboard-item .name { + font-size: 11px; + text-transform: uppercase; + color: #0861B7; + /*+placement:shift 8px 7px;*/ + position: relative; + left: 8px; + top: 7px; + /*+text-shadow:0px 1px 1px #FFFFFF;*/ + -moz-text-shadow: 0px 1px 1px #FFFFFF; + -webkit-text-shadow: 0px 1px 1px #FFFFFF; + -o-text-shadow: 0px 1px 1px #FFFFFF; + text-shadow: 0px 1px 1px #FFFFFF; +} + +.vpc-network-chart .tier-item .content .info { + /*+placement:shift 10px 5px;*/ + position: relative; + left: 10px; + top: 5px; +} + +.vpc-network-chart .tier-item .content .info .cidr-label { + font-size: 10px; + color: #1860A7; +} + +.vpc-network-chart .tier-item .content .info .cidr { + color: #364553; + font-size: 10px; + /*+text-shadow:0px 1px #C7D8E9;*/ + -moz-text-shadow: 0px 1px #C7D8E9; + -webkit-text-shadow: 0px 1px #C7D8E9; + -o-text-shadow: 0px 1px #C7D8E9; + text-shadow: 0px 1px #C7D8E9; +} + +.vpc-network-chart .tier-placeholder { + cursor: pointer; + background: #EFEFEF; + border: 4px dotted #B1B1B1; + /*+border-radius:8px;*/ + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + -khtml-border-radius: 8px; + border-radius: 8px; + width: 325px; + text-align: center; + padding: 57px 0 55px; + margin: 0 0 0 18px; +} + +.vpc-network-chart .tier-placeholder:hover { + background: #DCDCDC; + /*+border-radius:8px;*/ + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + -khtml-border-radius: 8px; + border-radius: 8px; + /*+box-shadow:inset 0px 1px 4px #000000;*/ + -moz-box-shadow: inset 0px 1px 4px #000000; + -webkit-box-shadow: inset 0px 1px 4px #000000; + -o-box-shadow: inset 0px 1px 4px #000000; + box-shadow: inset 0px 1px 4px #000000; + /*+text-shadow:0px 1px #FFFFFF;*/ + -moz-text-shadow: 0px 1px #FFFFFF; + -webkit-text-shadow: 0px 1px #FFFFFF; + -o-text-shadow: 0px 1px #FFFFFF; + text-shadow: 0px 1px #FFFFFF; +} + +.vpc-network-chart .tier-placeholder:hover span { + color: #535353; +} + +.vpc-network-chart .tier-placeholder span { + color: #AFAFAF; + font-size: 24px; + font-weight: 200; +} + +.vpc-network-chart .tier-item.router { + width: 258px; + height: 218px; + background: #BDBDBD; + border: 1px solid #808080; + float: left; + /*+placement:shift 10px 176px;*/ + position: relative; + left: 10px; + top: 176px; +} + +.vpc-network-chart .tier-item.router .header { + padding: 15px 0 14px; + border-bottom: 1px solid #808080; + background: #C3C6C9; +/*Old browsers*/ + background: -moz-linear-gradient(top, #c3c6c9 0%, #909497 100%); +/*FF3.6+*/ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#c3c6c9), color-stop(100%,#909497)); +/*Chrome,Safari4+*/ + background: -webkit-linear-gradient(top, #c3c6c9 0%,#909497 100%); +/*Chrome10+,Safari5.1+*/ + background: -o-linear-gradient(top, #c3c6c9 0%,#909497 100%); +/*Opera 11.10+*/ + background: -ms-linear-gradient(top, #c3c6c9 0%,#909497 100%); +/*IE10+*/ + background: linear-gradient(to bottom, #c3c6c9 0%,#909497 100%); +/*W3C*/ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#c3c6c9', endColorstr='#909497',GradientType=0 ); +/*IE6-8*/ +} + +.vpc-network-chart .tier-item.router .header .title { + width: 212px; + margin-top: 3px; +} + +.vpc-network-chart .tier-item.router .header .title span { + padding: 0 0 0 50px; +} + +.vpc-network-chart .tier-item.router .header span.icon { + background: url(../../images/sprites.png) -589px -1175px; + padding: 10px 10px 10px 20px; + float: left; + position: absolute; + top: 7px; + left: 10px; +} + +.vpc-network-chart .tier-item.router .dashboard-item { + width: 100px; + /*[empty]margin:;*/ + padding: 0px 2px 0px 6px; + height: 73px; + background: #A7A7A7; +} + +.vpc-network-chart .tier-item.router .dashboard-item span { + color: #FFFFFF; + /*+text-shadow:0px 1px #000000;*/ + -moz-text-shadow: 0px 1px #000000; + -webkit-text-shadow: 0px 1px #000000; + -o-text-shadow: 0px 1px #000000; + text-shadow: 0px 1px #000000; +} + +.vpc-network-chart .tier-item.router .dashboard-item:hover { + background-color: #818181; +} + diff --git a/ui/modules/vpc/vpc.js b/ui/modules/vpc/vpc.js new file mode 100644 index 00000000000..a6037c00fb7 --- /dev/null +++ b/ui/modules/vpc/vpc.js @@ -0,0 +1,327 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +(function($, cloudStack) { + var addTierDialog = function(args) { + var $placeholder = args.$placeholder; + var context = args.context; + var addAction = cloudStack.vpc.tiers.actions.add; + + cloudStack.dialog.createForm({ + context: context, + form: addAction.createForm, + after: function(args) { + var $loading = $('
').addClass('loading-overlay') + .prependTo($placeholder); + + addAction.action({ + context: context, + data: args.data, + response: { + success: function(args) { + cloudStack.ui.notifications.add( + // Notification + { + desc: addAction.label + }, + + // Success + function(args) { + $loading.remove(); + $placeholder.closest('.vpc-network-chart').trigger('reload'); + }, + + {}, + + // Error + function(args) { + $loading.remove(); + } + ); + }, + error: function(errorMsg) { + cloudStack.dialog.notice({ message: _s(errorMsg) }); + $loading.remove(); + } + } + }); + } + }); + }; + + var elems = { + tier: function(args) { + var tier = args.tier; + var context = $.extend(true, {}, args.context, { + networks: [tier] + }); + var dashboardItems = args.dashboardItems; + var $tier = $('
').addClass('tier-item'); + var $header = $('
').addClass('header'); + var $title = $('
').addClass('title').append($('')); + var $content = $('
').addClass('content'); + var $browser = $('#browser .container'); + var $dashboard = elems.dashboard({ + context: context, + dashboardItems: dashboardItems + }); + var $detailLink = $('
').addClass('detail-link'); + var $info = $('
').addClass('info'); + var $cidrLabel = $('').addClass('cidr-label'); + var $cidr = $('').addClass('cidr'); + + $detailLink.click(function() { + $browser.cloudBrowser('addPanel', { + title: tier.displayname ? tier.displayname : tier.name, + complete: function($panel) { + var $detailView = $('
').detailView( + $.extend(true, {}, cloudStack.vpc.tiers.detailView, { + $browser: $browser, + context: context, + onActionComplete: function() { + $tier.closest('.vpc-network-chart').trigger('reload'); + } + }) + ); + + $detailView.appendTo($panel); + } + }); + }); + + $cidrLabel.html('CIDR: '); + $cidr.html(tier.cidr); + $title.find('span').html(tier.displayname ? tier.displayname : tier.name); + $header.append($title, $detailLink); + $info.append($cidrLabel, $cidr); + $content.append($dashboard, $info); + $tier.append($header, $content); + + return $tier; + }, + + router: function(args) { + var $router = elems.tier({ + context: args.context, + tier: { + name: 'Router', + }, + dashboardItems: args.dashboardItems + }).addClass('router'); + + $router.find('.info, .detail-link').remove(); + $router.find('.header').prepend($('').addClass('icon').html(' ')); + + return $router; + }, + + tierPlaceholder: function(args) { + var context = args.context; + var $placeholder = $('
').addClass('tier-placeholder'); + + $placeholder.append($('').append('Create network')); + $placeholder.click(function() { + addTierDialog({ + context: context, + $placeholder: $placeholder + }); + }); + + return $placeholder; + }, + + dashboard: function(args) { + var $dashboard = $('
').addClass('dashboard'); + var context = args.context; + var tier = context.networks[0]; + + $(args.dashboardItems).map(function(index, dashboardItem) { + var $dashboardItem = $('
').addClass('dashboard-item'); + var $name = $('
').addClass('name').append($('')); + var $total = $('
').addClass('total').append($('')); + var id = dashboardItem.id; + + $name.find('span').html(dashboardItem.name); + + + if (dashboardItem.totalMultiLine) { + $total.find('span').html(dashboardItem.totalMultiLine); + $total.addClass('multiline'); + } else { + $total.find('span').html(dashboardItem.total ? dashboardItem.total : 0); + } + + $dashboardItem.append($total, $name); + $dashboardItem.appendTo($dashboard); + + $dashboardItem.click(function() { + var section = cloudStack.vpc.sections[id]; + var $section = $('
'); + var $loading = $('
').addClass('loading-overlay'); + + if ($.isFunction(section)) { + section = cloudStack.vpc.sections[id](); + } + + var before = section.before; + var load = function() { + $('#browser .container').cloudBrowser('addPanel', { + title: tier.name + ' - ' + dashboardItem.name, + maximizeIfSelected: true, + complete: function($panel) { + if (section.listView) { + $section.listView($.extend(true, {}, section, { + onActionComplete: function() { + $dashboardItem.closest('.vpc-network-chart').trigger('reload'); + }, + context: context + })); + } + + $section.appendTo($panel); + } + }); + }; + + if (before) { + before.check({ + context: context, + response: { + success: function(result) { + // true means content exists + if (result) { + load(); + } else { + cloudStack.dialog.confirm({ + message: before.messages.confirm, + action: function() { + $loading.appendTo($dashboardItem.closest('.vpc-network-chart')); + before.action({ + context: context, + response: { + success: function() { + $loading.remove(); + $dashboardItem.closest('.vpc-network-chart').trigger('reload'); + load(); + } + } + }); + } + }) + } + } + } + }); + } else { + load(); + } + }); + }); + + return $dashboard; + } + }; + + cloudStack.modules.vpc = function(module) { + var vpc = cloudStack.vpc; + var vpcSection = cloudStack.sections.network.sections.vpc; + var listConfigureAction = vpcSection.listView.actions.configureVpc.action; + var detailsConfigureAction = vpcSection.listView.detailView.actions.configureVpc.action; + + var vpcChart = function(args) { + var context = args.context; + var vpcItem = context.vpc[0]; + + var chart = function(args) { + args = args ? args : {}; + + var $chart = $('
').addClass('vpc-network-chart'); + var $tiers = $('
').addClass('tiers'); + var $toolbar = $('
').addClass('toolbar'); + + $toolbar.appendTo($chart); + $tiers.appendTo($chart); + + // Get tiers + var $loading = $('
').addClass('loading-overlay').prependTo($chart); + vpc.tiers.dataProvider({ + context: context, + response: { + success: function(data) { + var tiers = data.tiers; + var $placeholder = elems.tierPlaceholder({ + context: context + }); + + $(tiers).map(function(index, tier) { + var $tier = elems.tier({ + context: context, + tier: tier, + dashboardItems: tier._dashboardItems + }); + $tier.appendTo($tiers); + }); + + // Add placeholder tier + $tiers.append($placeholder); + $loading.remove(); + + if (!tiers.length) { + addTierDialog({ + context: context, + $placeholder: $placeholder + }); + } + + if (args.complete) { + args.complete($chart); + } + + // Router + elems.router({ + context: context, + dashboardItems: data.routerDashboard + }).appendTo($chart); + } + } + }); + + $chart.bind('reload', function() { + chart({ + complete: function($newChart) { + $chart.replaceWith($newChart); + } + }); + }); + + return $chart; + }; + + $('#browser .container').cloudBrowser('addPanel', { + title: vpcItem.displaytext ? vpcItem.displaytext : vpcItem.name, + maximizeIfSelected: true, + complete: function($panel) { + var $chart = chart(); + + $chart.appendTo($panel); + } + }); + }; + + listConfigureAction.custom = vpcChart; + detailsConfigureAction.custom = vpcChart; + }; +}(jQuery, cloudStack)); diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js index 808b34289d7..211d7b786b7 100644 --- a/ui/scripts/configuration.js +++ b/ui/scripts/configuration.js @@ -171,7 +171,7 @@ var items=[]; items.push({id:'',description:''}); items.push({id:'Strict', description:'Strict'}); - items.push({id:'Preffered', description:'Preffered'}); + items.push({id:'Preferred', description:'Preferred'}); args.response.success({data:items}); } }, @@ -1919,26 +1919,22 @@ inputData['isPersistent'] = false; } else if (inputData['guestIpType'] == "Isolated") { //specifyVlan checkbox is shown - if (inputData['specifyVlan'] == 'on') { //specifyVlan checkbox is checked + inputData['specifyIpRanges'] = false; + + if (inputData['specifyVlan'] == 'on') { //specifyVlan checkbox is checked inputData['specifyVlan'] = true; - inputData['specifyIpRanges'] = true; - - - - } else { //specifyVlan checkbox is unchecked inputData['specifyVlan'] = false; - inputData['specifyIpRanges'] = false; + } - if(inputData['isPersistent'] == 'on') { //It is a persistent network - inputData['isPersistent'] = true; - } - else { //Isolated Network with Non-persistent network - inputData['isPersistent'] = false; - } - + if(inputData['isPersistent'] == 'on') { //It is a persistent network + inputData['isPersistent'] = true; + } + else { //Isolated Network with Non-persistent network + inputData['isPersistent'] = false; + } } diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js index c76d843ed6e..31237a8855b 100644 --- a/ui/scripts/instances.js +++ b/ui/scripts/instances.js @@ -204,6 +204,14 @@ affinitygroupid: args.context.affinityGroups[0].id }); } + + if("vpc" in args.context && + "networks" in args.context) { + $.extend(data, { + vpcid: args.context.vpc[0].id, + networkid: args.context.networks[0].id + }); + } $.ajax({ url: createURL('listVirtualMachines'), diff --git a/ui/scripts/network.js b/ui/scripts/network.js index 6b310ce0e83..d66ec839dd6 100755 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -50,7 +50,7 @@ nicId: nic.id }, success: function(json) { - var nic = json.listnics.nic[0]; + var nic = json.listnicsresponse.nic[0]; var ips = nic.secondaryip ? nic.secondaryip : []; var ipSelection = []; @@ -321,7 +321,7 @@ listView: { actions: { add: { //add Isolated guest network (can't add Shared guest network here) - label: 'label.add.guest.network', + label: 'Add Isolated Guest Network', preFilter: function(args) { //Isolated networks is only supported in Advanced (SG-disabled) zone if(args.context.zoneType != 'Basic') @@ -331,8 +331,8 @@ }, createForm: { - title: 'label.add.guest.network', - desc: 'message.add.guest.network', + title: 'Add Isolated Guest Network', + desc: 'Add Isolated Guest Network with SourceNat', fields: { name: { label: 'label.name', validation: { required: true }, docID: 'helpGuestNetworkName' }, displayText: { label: 'label.display.text', validation: { required: true }, docID: 'helpGuestNetworkDisplayText'}, @@ -497,7 +497,7 @@ }); }, messages: { - notification: function() { return 'label.add.guest.network'; } + notification: function() { return 'Add Isolated Guest Network'; } } } }, @@ -1755,18 +1755,36 @@ } }, messages: { + /* confirm: function(args) { if(args.context.vpc) return 'message.acquire.new.ip.vpc'; else return 'message.acquire.new.ip'; }, + */ notification: function(args) { return 'label.acquire.new.ip'; } - }, + }, + createForm: { + title: 'label.acquire.new.ip', + fields: { + isportable: { + label: 'label.cross.zones', + select: function(args) { + var items = []; + items.push({ id: "false", description: _l('label.no') }); + items.push({ id: "true", description: _l('label.yes') }); + args.response.success({data: items}); + } + } + } + }, action: function(args) { - var dataObj = {}; + var dataObj = { + isportable: args.data.isportable + }; if('vpc' in args.context) { //from VPC section $.extend(dataObj, { vpcid: args.context.vpc[0].id @@ -2299,6 +2317,12 @@ ipaddress: { label: 'label.ip' } }, { + isportable: { + label: 'label.cross.zones', + converter: function(data) { + return data ? _l('label.yes') : _l('label.no'); + } + }, id: { label: 'label.id' }, associatednetworkid: { label: 'label.associated.network.id' }, networkname: { label: 'label.associated.network' }, diff --git a/ui/scripts/regions.js b/ui/scripts/regions.js index 2bbbbeea672..4be600f8b69 100644 --- a/ui/scripts/regions.js +++ b/ui/scripts/regions.js @@ -116,7 +116,22 @@ }, detailView: { name: 'Region details', - viewAll: { path: 'regions.GSLB', label: 'GSLB' }, + viewAll: [ + { + path: 'regions.GSLB', + label: 'GSLB' + }, + { + path: 'regions.portableIpRanges', + label: 'Portable IP', + preFilter: function(args) { + if (isAdmin()) + return true; + + return false; + } + } + ], actions: { edit: { label: 'label.edit.region', @@ -451,8 +466,202 @@ } } }, - - lbUnderGSLB: { + + portableIpRanges: { + id: 'portableIpRanges', + type: 'select', + title: 'Portable IP Ranges', + listView: { + id: 'portableIpRanges', + label: 'Portable IP Ranges', + fields: { + startip: { label: 'label.start.IP' }, + endip: { label: 'label.end.IP' }, + gateway: { label: 'label.gateway' }, + netmask: { label: 'label.netmask' }, + vlan: { label: 'label.vlan' } + }, + dataProvider: function(args) { + $.ajax({ + url: createURL('listPortableIpRanges'), + data: { + regionid: args.context.regions[0].id + }, + success: function(json) { + var items = json.listportableipresponse.portableiprange; + args.response.success({ + data: items + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + }, + actions: { + add: { + label: 'Add Portable IP Range', + messages: { + notification: function(args) { + return 'Add Portable IP Range'; + } + }, + createForm: { + title: 'Add Portable IP Range', + fields: { + startip: { + label: 'label.start.IP', + validation: { required: true } + }, + endip: { + label: 'label.end.IP', + validation: { required: true } + }, + gateway: { + label: 'label.gateway', + validation: { required: true } + }, + netmask: { + label: 'label.netmask', + validation: { required: true } + }, + vlan: { + label: 'label.vlan', + validation: { required: false } + } + } + }, + action: function(args) { + var data = { + regionid: args.context.regions[0].id, + startip: args.data.startip, + endip: args.data.endip, + gateway: args.data.gateway, + netmask: args.data.netmask + }; + if(args.data.vlan != null && args.data.vlan.length > 0) { + $.extend(data, { + vlan: args.data.vlan + }) + } + $.ajax({ + url: createURL('createPortableIpRange'), + data: data, + success: function(json) { + var jid = json.createportableiprangeresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.portableiprange; + } + } + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + + detailView: { + name: 'Portable IP Range details', + actions: { + remove: { + label: 'Delete Portable IP Range', + messages: { + confirm: function(args) { + return 'Please confirm you want to delete Portable IP Range'; + }, + notification: function(args) { + return 'Delete Portable IP Range'; + } + }, + action: function(args) { + var data = { + id: args.context.portableIpRanges[0].id + }; + $.ajax({ + url: createURL('deletePortableIpRange'), + data: data, + async: true, + success: function(json) { + var jid = json.deleteportablepublicipresponse.jobid; + args.response.success({ + _custom: { + jobId: jid + } + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + tabs: { + details: { + title: 'label.details', + fields: [ + { + id: { label: 'label.id' } + }, + { + startip: { label: 'label.start.IP' }, + endip: { label: 'label.end.IP' }, + gateway: { label: 'label.gateway' }, + netmask: { label: 'label.netmask' }, + vlan: { label: 'label.vlan' }, + portableipaddress: { + label: 'Portable IPs', + converter: function(args) { + var text1 = ''; + if(args != null) { + for(var i = 0; i < args.length; i++) { + if(i > 0) { + text1 += ', '; + } + text1 += args[i].ipaddress; + } + } + return text1; + } + } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL('listPortableIpRanges'), + data: { + id: args.context.portableIpRanges[0].id + }, + success: function(json) { + var item = json.listportableipresponse.portableiprange[0]; + args.response.success({ + data: item + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + } + } + } + } + } + }, + + lbUnderGSLB: { id: 'lbUnderGSLB', type: 'select', title: 'assigned load balancing', diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index 035299059c2..d87f0dcb0ae 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -276,7 +276,7 @@ cloudStack.actionFilter = { guestNetwork: function(args) { var jsonObj = args.context.item; var allowedActions = []; - + allowedActions.push('replaceacllist'); if(jsonObj.type == 'Isolated') { allowedActions.push('edit'); //only Isolated network is allowed to upgrade to a different network offering (Shared network is not allowed to) allowedActions.push('restart'); diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 2e23fc40202..8b9a81fe7c7 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -1085,10 +1085,13 @@ tabFilter: function(args) { var hiddenTabs = []; - if (selectedZoneObj.networktype == 'Basic') + if (selectedZoneObj.networktype == 'Basic') { hiddenTabs.push("network"); - else //selectedZoneObj.networktype == 'Advanced' + hiddenTabs.push("dedicatedGuestVlanRanges"); + } + else { //selectedZoneObj.networktype == 'Advanced' hiddenTabs.push("ipAddresses"); + } return hiddenTabs; }, @@ -2115,7 +2118,169 @@ } } } - } + }, + + dedicatedGuestVlanRanges : { + title: 'Dedicated VLAN Ranges', + listView: { + section: 'dedicatedGuestVlanRanges', + id: 'dedicatedGuestVlanRanges', + fields: { + guestvlanrange: { label: 'VLAN Range(s)' }, + domain: { label: 'label.domain' }, + account: { label: 'label.account' } + }, + dataProvider: function(args) { + $.ajax({ + url: createURL('listDedicatedGuestVlanRanges'), + data: { + physicalnetworkid: args.context.physicalNetworks[0].id + }, + success: function(json) { + var items = json.listdedicatedguestvlanrangesresponse.dedicatedguestvlanrange; + args.response.success({ data: items }) + } + }); + }, + actions: { + add: { + label: 'Dedicate VLAN Range', + messages: { + notification: function(args) { + return 'Dedicate VLAN Range'; + } + }, + createForm: { + title: 'Dedicate VLAN Range', + fields: { + vlanrange: { + label: 'VLAN Range', + select: function(args) { + var items = []; + if(args.context.physicalNetworks[0].vlan != null && args.context.physicalNetworks[0].vlan.length > 0) { + var vlanranges = args.context.physicalNetworks[0].vlan.split(";"); + for(var i = 0; i < vlanranges.length ; i++) { + items.push({id: vlanranges[i], description: vlanranges[i]}); + } + } + args.response.success({data: items}); + }, + validation: { required: true } + }, + account: { label: 'label.account', validation: { required: true } }, + domainid: { + label: 'label.domain', + validation: { required: true }, + 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 = { + physicalnetworkid: args.context.physicalNetworks[0].id, + vlanrange: args.data.vlanrange, + domainid: args.data.domainid, + account: args.data.account + }; + $.ajax({ + url: createURL('dedicateGuestVlanRange'), + data: data, + success: function(json) { + var item = json.dedicateguestvlanrangeresponse.dedicatedguestvlanrange; + args.response.success({ data: item }); + } + }); + }, + notification: { + poll: function(args) { + args.complete(); + } + } + } + }, + + detailView: { + name: 'VLAN Range details', + actions: { + remove: { + label: 'Release dedicated VLAN range', + messages: { + confirm: function(args) { + return 'Please confirm you want to release dedicated VLAN range'; + }, + notification: function(args) { + return 'Release dedicated VLAN range'; + } + }, + action: function(args) { + var data = { + id: args.context.dedicatedGuestVlanRanges[0].id + }; + $.ajax({ + url: createURL('releaseDedicatedGuestVlanRange'), + data: data, + async: true, + success: function(json) { + var jid = json.releasededicatedguestvlanrangeresponse.jobid; + args.response.success( + { + _custom: { jobId: jid } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + + tabs: { + details: { + title: 'label.details', + fields: [ + { + guestvlanrange: { label: 'VLAN Range(s)' }, + }, + { + domain: { label: 'label.domain' }, + account: { label: 'label.account' }, + id: { label: 'label.id' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL('listDedicatedGuestVlanRanges'), + data: { + id: args.context.dedicatedGuestVlanRanges[0].id + }, + success: function(json) { + var item = json.listdedicatedguestvlanrangesresponse.dedicatedguestvlanrange[0]; + args.response.success({ data: item }) + } + }); + } + } + } + } + } + } } } } @@ -12554,7 +12719,7 @@ nspHardcodingArray.push( { id: 'InternalLbVm', - name: 'InternalLbVm', + name: 'Internal LB VM', state: nspMap.InternalLbVm ? nspMap.InternalLbVm.state : 'Disabled' } ); diff --git a/ui/scripts/ui-custom/installWizard.js b/ui/scripts/ui-custom/installWizard.js index 86919f9fa41..9f1f4c761e5 100644 --- a/ui/scripts/ui-custom/installWizard.js +++ b/ui/scripts/ui-custom/installWizard.js @@ -298,6 +298,17 @@ * Layout/behavior for each step in wizard */ var steps = { + start: function(args) { + if (cloudStack.preInstall) { + return cloudStack.preInstall({ + complete: function() { + goTo('intro'); + } + }); + } + + return steps.intro(args); + }, intro: function(args) { var $intro = $('
').addClass('intro what-is-cloudstack'); var $title = $('
').addClass('title').html(_l('label.what.is.cloudstack')); @@ -775,7 +786,7 @@ } }; - var initialStep = steps.intro().addClass('step'); + var initialStep = steps.start().addClass('step'); showDiagram(''); diff --git a/ui/scripts/ui/dialog.js b/ui/scripts/ui/dialog.js index bb372fbf3d6..45f928e38a9 100644 --- a/ui/scripts/ui/dialog.js +++ b/ui/scripts/ui/dialog.js @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. -(function($, cloudStack) { +(function($, cloudStack, _l) { cloudStack.dialog = { /** * Error message form @@ -506,6 +506,94 @@ } }, + // Dialog with list view selector + listView: function(args) { + var listView = args.listView; + var after = args.after; + var context = args.context; + var $listView = $('
'); + + listView.actions = { + select: { + label: _l('label.select.instance'), + type: listView.type, + action: { + uiCustom: function(args) { + var $item = args.$item; + var $input = $item.find('td.actions input:visible'); + + if ($input.attr('type') == 'checkbox') { + if ($input.is(':checked')) + $item.addClass('multi-edit-selected'); + else + $item.removeClass('multi-edit-selected'); + } else { + $item.siblings().removeClass('multi-edit-selected'); + $item.addClass('multi-edit-selected'); + } + } + } + } + }; + + // Init list view + $listView = $('
').listView({ + context: context, + uiCustom: true, + listView: listView + }); + + // Change action label + $listView.find('th.actions').html(_l('label.select')); + + $listView.dialog({ + dialogClass: 'multi-edit-add-list panel', + width: 825, + title: _l('Select VM'), + buttons: [ + { + text: _l('label.apply'), + 'class': 'ok', + click: function() { + if (!$listView.find( + 'input[type=radio]:checked, input[type=checkbox]:checked' + ).size()) { + cloudStack.dialog.notice({ message: _l('message.select.instance')}); + + return false; + } + + after({ + context: $.extend(true, {}, context, { + instances: $listView.find('tr.multi-edit-selected').map(function(index, row) { + var $row = $(row); + + return $row.data('json-obj'); + }) + }) + }); + + $listView.remove(); + + $('div.overlay').remove(); + } + }, + { + text: _l('label.cancel'), + 'class': 'cancel', + click: function() { + $listView.fadeOut(function() { + $listView.remove(); + }); + $('div.overlay').fadeOut(function() { + $('div.overlay').remove(); + }); + } + } + ] + }).parent('.ui-dialog').overlay(); + }, + /** * to change a property(e.g. validation) of a createForm field after a createForm is rendered */ @@ -612,4 +700,4 @@ return false; } }; -})(window.jQuery, window.cloudStack); +})(window.jQuery, window.cloudStack, _l); diff --git a/ui/scripts/ui/widgets/detailView.js b/ui/scripts/ui/widgets/detailView.js index a721a44ec05..11e82b35f1c 100644 --- a/ui/scripts/ui/widgets/detailView.js +++ b/ui/scripts/ui/widgets/detailView.js @@ -70,7 +70,8 @@ action.notification : {}; var messages = action.messages; var id = args.id; - var context = args.context ? args.context : $detailView.data('view-args').context; + var context = $.extend(true, {}, + args.context ? args.context : $detailView.data('view-args').context); var _custom = $detailView.data('_custom'); var customAction = action.action.custom; var noAdd = action.noAdd; @@ -273,7 +274,7 @@ notification.desc = messages.notification(messageArgs); notification.section = 'instances'; - if (!action.createForm) { + if (!action.createForm && !action.listView) { if (messages && messages.confirm) { cloudStack.dialog.confirm({ message: messages.confirm(messageArgs), @@ -286,7 +287,7 @@ } else { performAction({ id: id }); } - } else { + } else if (action.createForm) { cloudStack.dialog.createForm({ form: action.createForm, after: function(args) { @@ -301,6 +302,15 @@ }, context: context }); + } else if (action.listView) { + cloudStack.dialog.listView({ + context: context, + listView: action.listView, + after: function(args) { + context = args.context; + performAction(); + } + }); } } }, diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js index 0d5ef6fc751..d68f91fac7c 100644 --- a/ui/scripts/ui/widgets/listView.js +++ b/ui/scripts/ui/widgets/listView.js @@ -104,6 +104,10 @@ cloudStack.ui.notifications.add( notification, function(args) { + if (listViewArgs.onActionComplete) { + listViewArgs.onActionComplete(); + } + if ($item.is(':visible') && !isHeader) { replaceItem( $item, @@ -175,6 +179,10 @@ if (additional && additional.success) additional.success(args); + if (listViewArgs.onActionComplete == true) { + listViewArgs.onActionComplete(); + } + cloudStack.ui.notifications.add( notification, @@ -213,6 +221,10 @@ if (options.complete) { options.complete(args); } + + if (listViewArgs.onActionComplete) { + listViewArgs.onActionComplete(); + } }, {}, @@ -1187,6 +1199,10 @@ $quickViewTooltip.hide(); }, onActionComplete: function() { + if (listViewArgs.onActionComplete) { + listViewArgs.onActionComplete(); + } + $tr.removeClass('loading').find('td:last .loading').remove(); $quickViewTooltip.remove(); } @@ -1798,6 +1814,8 @@ }); } + detailViewArgs.data.onActionComplete = listViewArgs.onActionComplete; + createDetailView( detailViewArgs, function($detailView) { //complete(), callback funcion @@ -1873,7 +1891,7 @@ if (!options) options = {}; var viewArgs = listView.data('view-args'); - var listViewArgs = viewArgs.listView ? viewArgs.listView : viewArgs; + var listViewArgs = $.isPlainObject(viewArgs.listView) ? viewArgs.listView : viewArgs; var targetArgs = listViewArgs.activeSection ? listViewArgs.sections[ listViewArgs.activeSection ].listView : listViewArgs; @@ -1903,7 +1921,7 @@ var $newRow; var $listView = $row.closest('.list-view'); var viewArgs = $listView.data('view-args'); - var listViewArgs = viewArgs.listView ? viewArgs.listView : viewArgs; + var listViewArgs = $.isPlainObject(viewArgs.listView) ? viewArgs.listView : viewArgs; var targetArgs = listViewArgs.activeSection ? listViewArgs.sections[ listViewArgs.activeSection ].listView : listViewArgs; diff --git a/ui/scripts/ui/widgets/multiEdit.js b/ui/scripts/ui/widgets/multiEdit.js index a1272fda31c..936c20c48a0 100755 --- a/ui/scripts/ui/widgets/multiEdit.js +++ b/ui/scripts/ui/widgets/multiEdit.js @@ -30,347 +30,363 @@ var $tr; var $item = $('
').addClass('data-item'); var multiRule = data; + var reorder = options.reorder; $item.append($('').append($(''))); $tr = $('').appendTo($item.find('tbody')); + $item.data('json-obj', multiRule); if (itemData) { $tr.data('multi-edit-data', itemData); } - // Setup columns - $.each(fields, function(fieldName, field) { - if (options.ignoreEmptyFields && !data[fieldName]) { - return true; - } + // Add reorder actions + if (reorder) { + $(''); + var itemName = multiRule._itemName ? item[multiRule._itemName] : item.name; + var $itemName = $('').html(_s(itemName)); - // Show list view of selected VMs - $browser.cloudBrowser('addPanel', { - title: _l('label.item.listing'), - data: '', - noSelectPanel: true, - maximizeIfSelected: true, - complete: function($newPanel) { - return $newPanel.listView(listViewArgs); + $tr.append($(''); - var itemName = multiRule._itemName ? item[multiRule._itemName] : item.name; - var $itemName = $('').html(_s(itemName)); - - $tr.append($('').appendTo($('
').addClass('actions reorder').appendTo($tr).append(function() { + var $td = $(this); - var $td = $('').addClass(fieldName).appendTo($tr); - var $input, val; - var $addButton = $multi.find('form .button.add-vm:not(.custom-action)').clone(); - var newItemRows = []; - var addItemAction = function(data) { - var $loading = $('
').addClass('loading-overlay'); - var complete = function(args) { - var $tbody = $item.find('.expandable-listing tbody'); + $.each(reorder, function(actionName, action) { + var fnLabel = { + moveTop: _l('label.move.to.top'), + moveBottom: _l('label.move.to.bottom'), + moveUp: _l('label.move.up.row'), + moveDown: _l('label.move.down.row'), + moveDrag: _l('label.drag.new.position') + }; - $loading.remove(); - $(data).each(function() { - var item = this; - var $itemRow = _medit.multiItem.itemRow(item, options.itemActions, multiRule, $tbody); + $('
') + .addClass('action reorder') + .addClass(actionName) + .append( + $('').addClass('icon').html(' ') + ) + .attr({ + title: _l(fnLabel[actionName]) + }) + .appendTo($td) + .click(function() { + if (actionName == 'moveDrag') return false; - $itemRow.appendTo($tbody); - newItemRows.push($itemRow); + rowActions[actionName]($tr); + $tr.closest('.data-body').find('.data-item').each(function() { + sort($(this), action); + }); - cloudStack.evenOdd($tbody, 'tr:visible', { - even: function($elem) { - $elem.removeClass('odd'); - $elem.addClass('even'); - }, - odd: function($elem) { - $elem.removeClass('even'); - $elem.addClass('odd'); - } + return false; }); - }); - }; - var error = function() { - $(newItemRows).each(function() { - var $itemRow = this; + }); + }); + } - $itemRow.remove(); - }); - $loading.remove(); - }; - $loading.prependTo($item); - options.itemActions.add.action({ - context: options.context, - data: data, - multiRule: multiRule, - response: { - success: function(args) { - var notificationError = function(args) { - error(); - }; + // Setup columns + $.each(fields, function(fieldName, field) { + if (!field || (options.ignoreEmptyFields && !data[fieldName])) { + return true; + } - cloudStack.ui.notifications.add(args.notification, - complete, {}, - notificationError, {}); + var $td = $('
').addClass(fieldName).appendTo($tr); + var $input, val; + var $addButton = $multi.find('form .button.add-vm:not(.custom-action)').clone(); + var newItemRows = []; + var addItemAction = function(data) { + var $loading = $('
').addClass('loading-overlay'); + var complete = function(args) { + var $tbody = $item.find('.expandable-listing tbody'); + + $loading.remove(); + $(data).each(function() { + var item = this; + var $itemRow = _medit.multiItem.itemRow(item, options.itemActions, multiRule, $tbody); + + $itemRow.appendTo($tbody); + newItemRows.push($itemRow); + + cloudStack.evenOdd($tbody, 'tr:visible', { + even: function($elem) { + $elem.removeClass('odd'); + $elem.addClass('even'); }, - error: error - } + odd: function($elem) { + $elem.removeClass('even'); + $elem.addClass('odd'); + } + }); }); }; + var error = function() { + $(newItemRows).each(function() { + var $itemRow = this; - if (!itemData) itemData = [{}]; + $itemRow.remove(); + }); + $loading.remove(); + }; - if (!options.noSelect && - $multi.find('th,td').filter(function() { - return $(this).attr('rel') == fieldName; - }).is(':hidden')) { - return true; - } + $loading.prependTo($item); + options.itemActions.add.action({ + context: options.context, + data: data, + multiRule: multiRule, + response: { + success: function(args) { + var notificationError = function(args) { + error(); + }; - if (!field.isPassword) { - if (field.edit) { - // Edit fields append value of data - if (field.range) { - var start = _s(data[field.range[0]]); - var end = _s(data[field.range[1]]); + cloudStack.ui.notifications.add(args.notification, + complete, {}, + notificationError, {}); + }, + error: error + } + }); + }; - $td.append($('').html(start + ' - ' + end)); + if (!itemData) itemData = [{}]; + + if (!options.noSelect && + $multi.find('th,td').filter(function() { + return $(this).attr('rel') == fieldName; + }).is(':hidden')) { + return true; + } + + if (!field.isPassword) { + if (field.edit) { + // Edit fields append value of data + if (field.range) { + var start = _s(data[field.range[0]]); + var end = _s(data[field.range[1]]); + + $td.append($('').html(start + ' - ' + end)); + } else { + var maxLengths = data['_maxLength']; + + if (maxLengths && + maxLengths[fieldName] && + data[fieldName].length >= maxLengths[fieldName]) { + $td.append($('').html(_s(data[fieldName].toString().substr(0, maxLengths[fieldName] - 3).concat('...')))); } else { - var maxLengths = data['_maxLength']; - - if (maxLengths && - maxLengths[fieldName] && - data[fieldName].length >= maxLengths[fieldName]) { - $td.append($('').html(_s(data[fieldName].toString().substr(0, maxLengths[fieldName] - 3).concat('...')))); - } else { - $td.append($('').html(_s(data[fieldName]))); - } - $td.attr('title', data[fieldName]); + $td.append($('').html(_s(data[fieldName]))); } - } else if (field.select) { - // Get matching option text - var $matchingSelect = $multi.find('select') - .filter(function() { - return $(this).attr('name') == fieldName; - }); - var $matchingOption = $matchingSelect.find('option') - .filter(function() { - return $(this).val() == data[fieldName]; - }); + $td.attr('title', data[fieldName]); + } + } else if (field.select) { + // Get matching option text + var $matchingSelect = $multi.find('select') + .filter(function() { + return $(this).attr('name') == fieldName; + }); + var $matchingOption = $matchingSelect.find('option') + .filter(function() { + return $(this).val() == data[fieldName]; + }); - var matchingValue = $matchingOption.size() ? - $matchingOption.html() : data[fieldName]; - - $td.append($('').html(_s(matchingValue))); - } else if (field.addButton && !options.noSelect) { - if (options.multipleAdd) { - $addButton.click(function() { - if ($td.hasClass('disabled')) return false; - - _medit.vmList($multi, - options.listView, - options.context, - options.multipleAdd, _l('label.add.vms'), - addItemAction, - { - multiRule: multiRule - }); - - return true; - }); - $td.append($addButton); - } else { - // Show VM data - var itemName = data._itemName ? itemData[0][data._itemName] : itemData[0].name; - $td.html(options.multipleAdd ? - itemData.length + ' VMs' : itemName); - $td.click(function() { - var $browser = $(this).closest('.detail-view').data('view-args').$browser; - - if (options.multipleAdd) { - _medit.multiItem.details(itemData, $browser); - } else { - _medit.details(itemData[0], $browser, { - context: options.context, itemName: itemName - }); - } - }); - } - } else if (field.custom) { - var $button = $('
').addClass('button add-vm custom-action'); - - $td.data('multi-custom-data', data[fieldName]); - $button.html(data && data[fieldName] && data[fieldName]['_buttonLabel'] ? - _l(data[fieldName]['_buttonLabel']) : _l(field.custom.buttonLabel)); - $button.click(function() { + var matchingValue = $matchingOption.size() ? + $matchingOption.html() : data[fieldName]; + + $td.append($('').html(_s(matchingValue))); + } else if (field.addButton && !options.noSelect) { + if (options.multipleAdd) { + $addButton.click(function() { if ($td.hasClass('disabled')) return false; - var $button = $(this); - var context = $.extend(true, {}, - options.context ? - options.context : cloudStack.context, { - multiRules: [data] - }); - - field.custom.action({ - context: context, - data: $td.data('multi-custom-data'), - $item: $td, - response: { - success: function(args) { - if (args.data['_buttonLabel']) { - $button.html(_l(args.data['_buttonLabel'])); - } - $td.data('multi-custom-data', args.data); - } - } - }); + _medit.vmList($multi, + options.listView, + options.context, + options.multipleAdd, _l('label.add.vms'), + addItemAction, + { + multiRule: multiRule + }); return true; }); - $button.appendTo($td); - } - } + $td.append($addButton); + } else { + // Show VM data + var itemName = data._itemName ? itemData[0][data._itemName] : itemData[0].name; + $td.html(options.multipleAdd ? + itemData.length + ' VMs' : itemName); + $td.click(function() { + var $browser = $(this).closest('.detail-view').data('view-args').$browser; - // Add blank styling for empty fields - if ($td.html() == '') { - $td.addClass('blank'); - } - - // Align width to main header - _medit.refreshItemWidths($multi); - - if (data._hideFields && - $.inArray(fieldName, data._hideFields) > -1) { - $td.addClass('disabled'); - } - - return true; - }); - - // Actions column - var $actions = $('
').addClass('multi-actions').appendTo($item.find('tr')); - - // Align action column width - $actions.width($multi.find('th.multi-actions').width() + 4); - - // 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; }) - }) - }) : null; - - // Append actions - $.each(actions, function(actionID, action) { - if (allowedActions && $.inArray(actionID, allowedActions) == -1) return true; - - $actions.append( - $('
').addClass('action') - .addClass(actionID) - .append($('').addClass('icon')) - .attr({ title: _l(action.label) }) - .click(function() { - var performAction = function(actionOptions) { - if (!actionOptions) actionOptions = {}; - - action.action({ - context: $.extend(true, {}, options.context, { - multiRule: [data] - }), - data: actionOptions.data, - response: { - success: function(args) { - var notification = args ? args.notification : null; - var _custom = args ? args._custom : null; - if (notification) { - $('.notifications').notifications('add', { - section: 'network', - desc: notification.label, - interval: 3000, - _custom: _custom, - poll: function(args) { - var complete = args.complete; - var error = args.error; - - notification.poll({ - _custom: args._custom, - complete: function(args) { - if (isDestroy) { - $loading.remove(); - $dataItem.remove(); - } else { - $multi.trigger('refresh'); - } - - complete(); - - if (actionOptions.complete) actionOptions.complete(); - }, - error: function(args) { - error(args); - $loading.remove(); - $dataItem.show(); - - return cloudStack.dialog.error; - } - }); - } - }); - } else { - $loading.remove(); - if (isDestroy) { - $dataItem.remove(); - } - } - }, - error: function(message) { - cloudStack.dialog.notice({ message: message }); - $item.show(); - $loading.remove(); - } - } + if (options.multipleAdd) { + _medit.multiItem.details(itemData, $browser); + } else { + _medit.details(itemData[0], $browser, { + context: options.context, itemName: itemName }); - }; + } + }); + } + } else if (field.custom) { + var $button = $('
').addClass('button add-vm custom-action'); - var $target = $(this); - var $dataItem = $target.closest('.data-item'); - var $expandable = $dataItem.find('.expandable-listing'); - var isDestroy = $target.hasClass('destroy'); - var isEdit = $target.hasClass('edit'); - var createForm = action.createForm; + $td.data('multi-custom-data', data[fieldName]); + $button.html(data && data[fieldName] && data[fieldName]['_buttonLabel'] ? + _l(data[fieldName]['_buttonLabel']) : _l(field.custom.buttonLabel)); + $button.click(function() { + if ($td.hasClass('disabled')) return false; + + var $button = $(this); + var context = $.extend(true, {}, + options.context ? + options.context : cloudStack.context, { + multiRules: [data] + }); - if (isDestroy) { - var $loading = _medit.loadingItem($multi, _l('label.removing') + '...'); - - if ($expandable.is(':visible')) { - $expandable.slideToggle(function() { - $dataItem.hide(); - $dataItem.after($loading); - }); - } else { - // Loading appearance - $dataItem.hide(); - $dataItem.after($loading); + field.custom.action({ + context: context, + data: $td.data('multi-custom-data'), + $item: $td, + response: { + success: function(args) { + if (args.data['_buttonLabel']) { + $button.html(_l(args.data['_buttonLabel'])); + } + $td.data('multi-custom-data', args.data); } } + }); - if (!isEdit) { - 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'); - } }); + return true; + }); + $button.appendTo($td); + } + } + + // Add blank styling for empty fields + if ($td.html() == '') { + $td.addClass('blank'); + } + + // Align width to main header + _medit.refreshItemWidths($multi); + + if (data._hideFields && + $.inArray(fieldName, data._hideFields) > -1) { + $td.addClass('disabled'); + } + + return true; + }); + + // Actions column + var $actions = $('
').addClass('multi-actions').appendTo($item.find('tr')); + + // Align action column width + $actions.width($multi.find('th.multi-actions').width() + 4); + + // 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; }) + }) + }) : null; + + // Append actions + $.each(actions, function(actionID, action) { + if (allowedActions && $.inArray(actionID, allowedActions) == -1) return true; + + $actions.append( + $('
').addClass('action') + .addClass(actionID) + .append($('').addClass('icon')) + .attr({ title: _l(action.label) }) + .click(function() { + var performAction = function(actionOptions) { + if (!actionOptions) actionOptions = {}; + + action.action({ + context: $.extend(true, {}, options.context, { + multiRule: [data] + }), + data: actionOptions.data, + response: { + success: function(args) { + var notification = args ? args.notification : null; + var _custom = args ? args._custom : null; + if (notification) { + $('.notifications').notifications('add', { + section: 'network', + desc: notification.label, + interval: 3000, + _custom: _custom, + poll: function(args) { + var complete = args.complete; + var error = args.error; + + notification.poll({ + _custom: args._custom, + complete: function(args) { + if (isDestroy) { + $loading.remove(); + $dataItem.remove(); + } else { + $multi.trigger('refresh'); + } + + complete(); + + if (actionOptions.complete) actionOptions.complete(); + }, + error: function(args) { + error(args); + $loading.remove(); + $dataItem.show(); + + return cloudStack.dialog.error; + } + }); + } + }); + } else { + $loading.remove(); + if (isDestroy) { + $dataItem.remove(); + } } - }); - } else { - performAction(); - } - } else { - // Get editable fields - var editableFields = {}; - - $.each(fields, function(key, field) { - if (field.isEditable) editableFields[key] = $.extend(true, {}, field, { - defaultValue: data[key] - }); - }); - - cloudStack.dialog.createForm({ - form: { - title: 'Edit rule', - desc: '', - fields: editableFields }, + error: function(message) { + cloudStack.dialog.notice({ message: message }); + $item.show(); + $loading.remove(); + } + } + }); + }; + + var $target = $(this); + var $dataItem = $target.closest('.data-item'); + var $expandable = $dataItem.find('.expandable-listing'); + var isDestroy = $target.hasClass('destroy'); + var isEdit = $target.hasClass('edit'); + var createForm = action.createForm; + var reorder = options.reorder; + + if (isDestroy) { + var $loading = _medit.loadingItem($multi, _l('label.removing') + '...'); + + if ($expandable.is(':visible')) { + $expandable.slideToggle(function() { + $dataItem.hide(); + $dataItem.after($loading); + }); + } else { + // Loading appearance + $dataItem.hide(); + $dataItem.after($loading); + } + } + + if (!isEdit) { + if (createForm) { + cloudStack.dialog.createForm({ + form: createForm, after: function(args) { var $loading = $('
').addClass('loading-overlay').prependTo($dataItem); performAction({ data: args.data, complete: function() { @@ -378,324 +394,336 @@ } }); } }); + } else { + performAction(); } - }) - ); - }); + } else { + // Get editable fields + var editableFields = {}; - // Add tagger action - if (options.tags) { - $actions.prepend( - $('
') - .addClass('action editTags') - .attr('title', _l('label.edit.tags')) - .append($('').addClass('icon')) - .click(function() { - $('
') - .dialog({ - dialogClass: 'editTags', - title: _l('label.edit.tags'), - width: 400, - buttons: [ - { - text: _l('label.done'), - 'class': 'ok', - click: function() { - $(this).dialog('destroy'); - $('div.overlay:last').remove(); + $.each(fields, function(key, field) { + if (field && field.isEditable) editableFields[key] = $.extend(true, {}, field, { + defaultValue: data[key] + }); + }); - return true; - } + cloudStack.dialog.createForm({ + form: { + title: 'Edit rule', + desc: '', + fields: editableFields + }, + after: function(args) { + var $loading = $('
').addClass('loading-overlay').prependTo($dataItem); + performAction({ data: args.data, complete: function() { + $multi.trigger('refresh'); + } }); + } + }); + } + }) + ); + }); + + // Add tagger action + if (options.tags) { + $actions.prepend( + $('
') + .addClass('action editTags') + .attr('title', _l('label.edit.tags')) + .append($('').addClass('icon')) + .click(function() { + $('
') + .dialog({ + dialogClass: 'editTags', + title: _l('label.edit.tags'), + width: 400, + buttons: [ + { + text: _l('label.done'), + 'class': 'ok', + click: function() { + $(this).dialog('destroy'); + $('div.overlay:last').remove(); + + return true; } - ] - }) - .append( - $('
').addClass('multi-edit-tags').tagger($.extend(true, {}, options.tags, { - context: $.extend(true, {}, options.context, { - multiRule: [multiRule] - }) - })) - ) - .closest('.ui-dialog').overlay(); + } + ] + }) + .append( + $('
').addClass('multi-edit-tags').tagger($.extend(true, {}, options.tags, { + context: $.extend(true, {}, options.context, { + multiRule: [multiRule] + }) + })) + ) + .closest('.ui-dialog').overlay(); + + return false; + }) + ) + } + + // Add expandable listing, for multiple-item + if (options.multipleAdd) { + // Create expandable box + _medit.multiItem.expandable($item.find('tr').data('multi-edit-data'), + options.itemActions, + multiRule).appendTo($item); + + // Expandable icon/action + $item.find('td:first').prepend( + $('
').addClass('expand').click(function() { + $item.closest('.data-item').find('.expandable-listing').slideToggle(); + })); + } + + return $item; + }, + + vmList: function($multi, listView, context, isMultipleAdd, label, complete, options) { + if (!options) options = {}; + + // Create a listing of instances, based on limited information + // from main instances list view + var $listView; + var instances = $.extend(true, {}, listView, { + context: $.extend(true, {}, context, { + multiData: getMultiData($multi), + multiRule: options.multiRule ? [options.multiRule] : null + }), + uiCustom: true + }); + + instances.listView.actions = { + select: { + label: 'Select instance', + type: isMultipleAdd ? 'checkbox' : 'radio', + action: { + uiCustom: function(args) { + var $item = args.$item; + var $input = $item.find('td.actions input:visible'); + + if ($input.attr('type') == 'checkbox') { + if ($input.is(':checked')) + $item.addClass('multi-edit-selected'); + else + $item.removeClass('multi-edit-selected'); + } else { + $item.siblings().removeClass('multi-edit-selected'); + $item.addClass('multi-edit-selected'); + } + } + } + } + }; + + $listView = $('
').listView(instances); + + // Change action label + $listView.find('th.actions').html(_l('Select')); + + var $dataList = $listView.addClass('multi-edit-add-list').dialog({ + dialogClass: 'multi-edit-add-list panel', + width: 825, + title: label, + buttons: [ + { + text: _l('label.apply'), + 'class': 'ok', + click: function() { + if (!$listView.find('input[type=radio]:checked, input[type=checkbox]:checked').size()) { + cloudStack.dialog.notice({ message: _l('message.select.item')}); return false; - }) - ) - } - - // Add expandable listing, for multiple-item - if (options.multipleAdd) { - // Create expandable box - _medit.multiItem.expandable($item.find('tr').data('multi-edit-data'), - options.itemActions, - multiRule).appendTo($item); - - // Expandable icon/action - $item.find('td:first').prepend( - $('
').addClass('expand').click(function() { - $item.closest('.data-item').find('.expandable-listing').slideToggle(); - })); - } - - return $item; - }, - - vmList: function($multi, listView, context, isMultipleAdd, label, complete, options) { - if (!options) options = {}; - - // Create a listing of instances, based on limited information - // from main instances list view - var $listView; - var instances = $.extend(true, {}, listView, { - context: $.extend(true, {}, context, { - multiData: getMultiData($multi), - multiRule: options.multiRule ? [options.multiRule] : null - }), - uiCustom: true - }); - - instances.listView.actions = { - select: { - label: 'Select instance', - type: isMultipleAdd ? 'checkbox' : 'radio', - action: { - uiCustom: function(args) { - var $item = args.$item; - var $input = $item.find('td.actions input:visible'); - - if ($input.attr('type') == 'checkbox') { - if ($input.is(':checked')) - $item.addClass('multi-edit-selected'); - else - $item.removeClass('multi-edit-selected'); - } else { - $item.siblings().removeClass('multi-edit-selected'); - $item.addClass('multi-edit-selected'); - } } + + $dataList.fadeOut(function() { + complete($.map( + $listView.find('tr.multi-edit-selected'), + + // Attach VM data to row + function(elem) { + var itemData = $(elem).data('json-obj'); + var $subselect = $(elem).find('.subselect select'); + + // Include subselect data + if ($subselect && $subselect.val()) { + return $.extend(itemData, { + _subselect: $subselect.val() + }); + } + + return itemData; + } + )); + $dataList.remove(); + }); + + $('div.overlay').fadeOut(function() { + $('div.overlay').remove(); + }); + + return true; + } + }, + { + text: _l('label.cancel'), + 'class': 'cancel', + click: function() { + $dataList.fadeOut(function() { + $dataList.remove(); + }); + $('div.overlay').fadeOut(function() { + $('div.overlay').remove(); + }); } } - }; + ] + }).parent('.ui-dialog').overlay(); + }, - $listView = $('
').listView(instances); + /** + * Align width of each data row to main header + */ + refreshItemWidths: function($multi) { + $multi.find('.data-body').width( + $multi.find('form > table.multi-edit').width() + ); - // Change action label - $listView.find('th.actions').html(_l('Select')); + $multi.find('.data tr').filter(function() { + return !$(this).closest('.expandable-listing').size(); + }).each(function() { + var $tr = $(this); - var $dataList = $listView.addClass('multi-edit-add-list').dialog({ - dialogClass: 'multi-edit-add-list panel', - width: 825, - title: label, - buttons: [ - { - text: _l('label.apply'), - 'class': 'ok', - click: function() { - if (!$listView.find('input[type=radio]:checked, input[type=checkbox]:checked').size()) { - cloudStack.dialog.notice({ message: _l('message.select.item')}); + $tr.find('td').each(function() { + var $td = $(this); - return false; - } - - $dataList.fadeOut(function() { - complete($.map( - $listView.find('tr.multi-edit-selected'), - - // Attach VM data to row - function(elem) { - var itemData = $(elem).data('json-obj'); - var $subselect = $(elem).find('.subselect select'); - - // Include subselect data - if ($subselect && $subselect.val()) { - return $.extend(itemData, { - _subselect: $subselect.val() - }); - } - - return itemData; - } - )); - $dataList.remove(); - }); - - $('div.overlay').fadeOut(function() { - $('div.overlay').remove(); - }); - - return true; - } - }, - { - text: _l('label.cancel'), - 'class': 'cancel', - click: function() { - $dataList.fadeOut(function() { - $dataList.remove(); - }); - $('div.overlay').fadeOut(function() { - $('div.overlay').remove(); - }); - } - } - ] - }).parent('.ui-dialog').overlay(); - }, - - /** - * Align width of each data row to main header - */ - refreshItemWidths: function($multi) { - $multi.find('.data-body').width( - $multi.find('form > table.multi-edit').width() - ); - - $multi.find('.data tr').filter(function() { - return !$(this).closest('.expandable-listing').size(); - }).each(function() { - var $tr = $(this); - - $tr.find('td').each(function() { - var $td = $(this); - - $td.width($($multi.find('th:visible')[$td.index()]).width() + 5); - }); + $td.width($($multi.find('th:visible')[$td.index()]).width() + 5); }); - }, + }); + }, - /** - * Create a fake 'loading' item box - */ - loadingItem: function($multi, label) { - var $loading = $('
').addClass('data-item loading'); + /** + * Create a fake 'loading' item box + */ + loadingItem: function($multi, label) { + var $loading = $('
').addClass('data-item loading'); - // Align height with existing items - var $row = $multi.find('.data-item:first'); + // Align height with existing items + var $row = $multi.find('.data-item:first'); - // Set label - if (label) { - $loading.append( - $('
').addClass('label').append( - $('').html(_l(label)) - ) - ); + // Set label + if (label) { + $loading.append( + $('
').addClass('label').append( + $('').html(_l(label)) + ) + ); + } + + return $loading; + }, + details: function(data, $browser, options) { + if (!options) options = {}; + + var detailViewArgs, $detailView; + + detailViewArgs = $.extend(true, {}, cloudStack.sections.instances.listView.detailView); + detailViewArgs.actions = null; + detailViewArgs.$browser = $browser; + detailViewArgs.id = data.id; + detailViewArgs.jsonObj = data; + detailViewArgs.context = options.context; + + $browser.cloudBrowser('addPanel', { + title: options.itemName ? options.itemName : data.name, + maximizeIfSelected: true, + complete: function($newPanel) { + $newPanel.detailView(detailViewArgs); } + }); + }, + multiItem: { + /** + * Show listing of load balanced VMs + */ + details: function(data, $browser) { + var listViewArgs, $listView; - return $loading; - }, - details: function(data, $browser, options) { - if (!options) options = {}; - - var detailViewArgs, $detailView; - - detailViewArgs = $.extend(true, {}, cloudStack.sections.instances.listView.detailView); - detailViewArgs.actions = null; - detailViewArgs.$browser = $browser; - detailViewArgs.id = data.id; - detailViewArgs.jsonObj = data; - detailViewArgs.context = options.context; + // Setup list view + listViewArgs = $.extend(true, {}, cloudStack.sections.instances); + listViewArgs.listView.actions = null; + listViewArgs.listView.filters = null; + listViewArgs.$browser = $browser; + listViewArgs.listView.detailView.actions = null; + listViewArgs.listView.dataProvider = function(args) { + setTimeout(function() { + args.response.success({ + data: data + }); + }, 50); + }; + $listView = $('
').listView(listViewArgs); + // Show list view of selected VMs $browser.cloudBrowser('addPanel', { - title: options.itemName ? options.itemName : data.name, + title: _l('label.item.listing'), + data: '', + noSelectPanel: true, maximizeIfSelected: true, complete: function($newPanel) { - $newPanel.detailView(detailViewArgs); + return $newPanel.listView(listViewArgs); } }); }, - multiItem: { - /** - * Show listing of load balanced VMs - */ - details: function(data, $browser) { - var listViewArgs, $listView; - // Setup list view - listViewArgs = $.extend(true, {}, cloudStack.sections.instances); - listViewArgs.listView.actions = null; - listViewArgs.listView.filters = null; - listViewArgs.$browser = $browser; - listViewArgs.listView.detailView.actions = null; - listViewArgs.listView.dataProvider = function(args) { - setTimeout(function() { - args.response.success({ - data: data - }); - }, 50); - }; - $listView = $('
').listView(listViewArgs); + itemRow: function(item, itemActions, multiRule, $tbody) { + var $tr = $('
').addClass('name').appendTo($tr).append($itemName)); + + $itemName.click(function() { + _medit.details(item, $('#browser .container'), { + itemName: itemName, + context: { + instances: [item] } }); - }, + }); - itemRow: function(item, itemActions, multiRule, $tbody) { - var $tr = $('
').addClass('name').appendTo($tr).append($itemName)); - - $itemName.click(function() { - _medit.details(item, $('#browser .container'), { - itemName: itemName, - context: { - instances: [item] - } - }); - }); - - var itemState=multiRule._itemState ? item[multiRule._itemState] :item.state; - var $itemState = $('').html(_s(itemState)); - $tr.append($('').addClass('state').appendTo($tr).append("Application State - ").append($itemState)); + var itemState=multiRule._itemState ? item[multiRule._itemState] :item.state; + var $itemState = $('').html(_s(itemState)); + $tr.append($('').addClass('state').appendTo($tr).append("Application State - ").append($itemState)); - if (itemActions) { - var $itemActions = $('').addClass('actions item-actions'); + if (itemActions) { + var $itemActions = $('').addClass('actions item-actions'); - $.each(itemActions, function(itemActionID, itemAction) { - if (itemActionID == 'add') - return true; - - if(item._hideActions != null && $.inArray(itemActionID, item._hideActions) > -1) - return true; + $.each(itemActions, function(itemActionID, itemAction) { + if (itemActionID == 'add') + return true; + + if(item._hideActions != null && $.inArray(itemActionID, item._hideActions) > -1) + return true; - var $itemAction = $('
').addClass('action').addClass(itemActionID); + var $itemAction = $('
').addClass('action').addClass(itemActionID); - $itemAction.click(function() { - itemAction.action({ - item: item, - multiRule: multiRule, - response: { - success: function(args) { - if (itemActionID == 'destroy') { - var notification = args.notification; - var success = function(args) { $tr.remove(); }; - var successArgs = {}; - var error = function(args) { - $tr.show(); - cloudStack.evenOdd($tbody, 'tr:visible', { - even: function($elem) { - $elem.removeClass('odd'); - $elem.addClass('even'); - }, - odd: function($elem) { - $elem.removeClass('even'); - $elem.addClass('odd'); - } - }); - }; - var errorArgs = {}; - - $tr.hide(); + $itemAction.click(function() { + itemAction.action({ + item: item, + multiRule: multiRule, + response: { + success: function(args) { + if (itemActionID == 'destroy') { + var notification = args.notification; + var success = function(args) { $tr.remove(); }; + var successArgs = {}; + var error = function(args) { + $tr.show(); cloudStack.evenOdd($tbody, 'tr:visible', { even: function($elem) { $elem.removeClass('odd'); @@ -706,83 +734,124 @@ $elem.addClass('odd'); } }); - cloudStack.ui.notifications.add(notification, - success, successArgs, - error, errorArgs); - } - }, - error: function(message) { - if (message) { - cloudStack.dialog.notice({ message: message }); - } + }; + var errorArgs = {}; + + $tr.hide(); + cloudStack.evenOdd($tbody, 'tr:visible', { + even: function($elem) { + $elem.removeClass('odd'); + $elem.addClass('even'); + }, + odd: function($elem) { + $elem.removeClass('even'); + $elem.addClass('odd'); + } + }); + cloudStack.ui.notifications.add(notification, + success, successArgs, + error, errorArgs); + } + }, + error: function(message) { + if (message) { + cloudStack.dialog.notice({ message: message }); } } - }); + } }); - $itemAction.append($('').addClass('icon')); - $itemAction.appendTo($itemActions); - - return true; }); + $itemAction.append($('').addClass('icon')); + $itemAction.appendTo($itemActions); - $itemActions.appendTo($tr); - } - - return $tr; - }, - - expandable: function(data, itemActions, multiRule) { - var $expandable = $('
').addClass('expandable-listing'); - var $tbody = $('
').appendTo($expandable)); - - $(data).each(function() { - var field = this; - var $tr = _medit.multiItem.itemRow(field, itemActions, multiRule, $tbody).appendTo($tbody); - - cloudStack.evenOdd($tbody, 'tr', { - even: function($elem) { - $elem.addClass('even'); - }, - odd: function($elem) { - $elem.addClass('odd'); - } - }); + return true; }); - return $expandable.hide(); + $itemActions.appendTo($tr); } + + return $tr; + }, + + expandable: function(data, itemActions, multiRule) { + var $expandable = $('
').addClass('expandable-listing'); + var $tbody = $('
').appendTo($('
').appendTo($expandable)); + + $(data).each(function() { + var field = this; + var $tr = _medit.multiItem.itemRow(field, itemActions, multiRule, $tbody).appendTo($tbody); + + cloudStack.evenOdd($tbody, 'tr', { + even: function($elem) { + $elem.addClass('even'); + }, + odd: function($elem) { + $elem.addClass('odd'); + } + }); + }); + + return $expandable.hide(); } - }; + } +}; - $.fn.multiEdit = function(args) { - var dataProvider = args.dataProvider; - var multipleAdd = args.multipleAdd; - var tags = args.tags; - var $multi = $('
').addClass('multi-edit').appendTo(this); - var $multiForm = $('
').appendTo($multi); - var $inputTable = $('
').addClass('multi-edit').appendTo($multiForm); - var $dataTable = $('
').addClass('data').appendTo($multi); - var $addVM; - var fields = args.fields; - var actions = args.actions; - var itemActions = multipleAdd ? args.itemActions : null; - var noSelect = args.noSelect; - var context = args.context; - var ignoreEmptyFields = args.ignoreEmptyFields; - var actionPreFilter = args.actionPreFilter; - var readOnlyCheck = args.readOnlyCheck; +$.fn.multiEdit = function(args) { + var dataProvider = args.dataProvider; + var multipleAdd = args.multipleAdd; + var tags = args.tags; + var $multi = $('
').addClass('multi-edit').appendTo(this); + var $multiForm = $('').appendTo($multi); + var $inputTable = $('
').addClass('multi-edit').appendTo($multiForm); + var $dataTable = $('
').addClass('data').appendTo($multi); + var $addVM; + var fields = args.fields; + var actions = args.actions; + var itemActions = multipleAdd ? args.itemActions : null; + var noSelect = args.noSelect; + var context = args.context; + var ignoreEmptyFields = args.ignoreEmptyFields; + var actionPreFilter = args.actionPreFilter; + var readOnlyCheck = args.readOnlyCheck; + var reorder = args.reorder; - var $thead = $('
').appendTo( - $('').appendTo($inputTable) - ); - var $inputForm = $('').appendTo( - $('').appendTo($inputTable) - ); - var $dataBody = $('
').addClass('data-body').appendTo($dataTable); + var $thead = $('
').appendTo( + $('').appendTo($inputTable) + ); + var $inputForm = $('').appendTo( + $('').appendTo($inputTable) + ); + var $dataBody = $('
').addClass('data-body').appendTo($dataTable); - // Setup input table headers - $.each(args.fields, function(fieldName, field) { - var $th = $('
').addClass(fieldName).html(_l(field.label.toString())); + // Setup input table headers + + if (reorder) { + $('').addClass('reorder').appendTo($thead); + $('').addClass('reorder').appendTo($inputForm); + $multi.find('.data-body').sortable({ + handle: '.action.moveDrag', + + update: function(event, ui) { + reorder.moveDrag.action({ + context: $.extend(true, {}, context, { + // Passes all rules, so that each index can be updated + multiRule: $multi.find('.data-item').map(function(index, item) { + return $(item).data('json-obj'); + }) + }), + response: { + success: function(args) { + } + } + }); + } + }); + } + + $.each(args.fields, function(fieldName, field) { + if (!field) return true; + + var $th = $('').addClass(fieldName).html(_l(field.label.toString())); $th.attr('rel', fieldName); $th.appendTo($thead); var $td = $('').addClass(fieldName); @@ -1055,7 +1124,8 @@ ignoreEmptyFields: ignoreEmptyFields, preFilter: actionPreFilter, listView: listView, - tags: tags + tags: tags, + reorder: reorder } ).appendTo($dataBody); }); diff --git a/ui/scripts/vpc.js b/ui/scripts/vpc.js index 4890dcc6ee9..3581b88ea34 100644 --- a/ui/scripts/vpc.js +++ b/ui/scripts/vpc.js @@ -26,9 +26,49 @@ } return hiddenFields; // Returns fields to be hidden + }, + reorder: { + moveDrag: { + action: function(args) { + $(args.context.multiRule.toArray().reverse()).map(function(index, rule) { + $.ajax({ + url: createURL('updateNetworkACLItem'), + data: { + id: rule.id, + number: index + 1 + }, + success: function(json) { + var pollTimer = setInterval(function() { + pollAsyncJobResult({ + _custom: { jobId: json.createnetworkaclresponse.jobid }, + complete: function() { + clearInterval(pollTimer); + }, + error: function(errorMsg) { + clearInterval(pollTimer); + cloudStack.dialog.notice(errorMsg); + } + }); + }, 1000); + } + }); + }); + } + } }, fields: { 'cidrlist': { edit: true, label: 'label.cidr' }, + action: { + label: 'Action', + select: function(args) { + args.response.success({ + data: [ + { name: 'Allow', description: 'Allow' }, + { name: 'Deny', description: 'Deny' } + ] + }); + } + }, 'protocol': { label: 'label.protocol', select: function(args) { @@ -45,28 +85,27 @@ var $otherFields = $inputs.filter(function() { var name = $(this).attr('name'); - return name != 'icmptype' && name != 'icmpcode' && name != 'cidrlist'; + return name != 'protocolnumber' && + name != 'icmptype' && + name != 'icmpcode' && + name != 'cidrlist'; }); - var $protocolinput = args.$form.find('th,td'); + var $protocolinput = args.$form.find('td input'); var $protocolFields = $protocolinput.filter(function(){ - var name = $(this).attr('rel'); + var name = $(this).attr('name'); return $.inArray(name,['protocolnumber']) > -1; }); - if($(this).val() == 'protocolnumber' ){ - - $protocolFields.show(); - } - else{ - $protocolFields.hide(); - } - - - if ($(this).val() == 'icmp') { + if ($(this).val() == 'protocolnumber' ){ + $icmpFields.hide(); + $otherFields.hide(); + $protocolFields.show().addClass('required'); + } else if ($(this).val() == 'icmp') { $icmpFields.show(); $icmpFields.attr('disabled', false); + $protocolFields.hide().removeClass('required'); $otherFields.attr('disabled', 'disabled'); $otherFields.hide(); $otherFields.parent().find('label.error').hide(); @@ -77,6 +116,7 @@ $icmpFields.attr('disabled', 'disabled'); $icmpFields.hide(); $icmpFields.parent().find('label.error').hide(); + $protocolFields.hide().removeClass('required'); } }); @@ -90,12 +130,14 @@ ] }); + + setTimeout(function() { args.$select.trigger('change'); }, 100); } }, - 'protocolnumber': {label:'Protocol Number',isDisabled:true,isHidden:true,edit:true}, - 'startport': { edit: true, label: 'label.start.port' , isOptional:true }, - 'endport': { edit: true, label: 'label.end.port' , isOptional:true}, + 'protocolnumber': {label:'Protocol Number',edit:true}, + 'startport': { edit: true, label: 'label.start.port', isOptional: true }, + 'endport': { edit: true, label: 'label.end.port', isOptional: true }, 'networkid': { label: 'Select Tier', select: function(args) { @@ -180,8 +222,7 @@ $.ajax({ url: createURL('createNetworkACL'), data: $.extend(args.data, { - networkid: args.context.networks ? - args.context.networks[0].id : args.data.networkid + aclid: args.context.aclLists[0].id }), dataType: 'json', success: function(data) { @@ -189,14 +230,6 @@ _custom: { jobId: data.createnetworkaclresponse.jobid, getUpdatedItem: function(json) { - var networkName = $multi.find('select[name=networkid] option[value=' + args.data.networkid + ']').html(); - var data = $.extend(json.queryasyncjobresultresponse.jobresult.networkacl, { - networkid: networkName - }); - var aclRules = $multi.data('acl-rules'); - - aclRules.push(data); - $multi.data('acl-rules', aclRules); $(window).trigger('cloudStack.fullRefresh'); return data; @@ -231,7 +264,7 @@ args.response.success({ _custom: { jobId: jobID, - getUpdatedItem: function() { + getUpdateIdtem: function() { $(window).trigger('cloudStack.fullRefresh'); } }, @@ -289,6 +322,531 @@ }; cloudStack.vpc = { + // nTier sections + sections: { + tierVMs: function() { + var list = $.extend(true, {}, cloudStack.sections.instances); + + list.listView.actions.add.action.custom = cloudStack.uiCustom.instanceWizard( + $.extend(true, {}, cloudStack.instanceWizard, { + pluginForm: { name: 'vpcTierInstanceWizard' } + }) + ); + + return list; + }, + + tierPortForwarders: function() { + return cloudStack.vpc.ipAddresses.listView(); + }, + + tierStaticNATs: function() { + return cloudStack.vpc.staticNatIpAddresses.listView(); + }, + + // Internal load balancers + internalLoadBalancers: { + title: 'Internal LB', + listView: { + id: 'internalLoadBalancers', + fields: { + name: { label: 'label.name' }, + sourceipaddress: { label: 'Source IP Address' } + }, + dataProvider: function(args) { + $.ajax({ + url: createURL('listLoadBalancers'), + data: { + networkid: args.context.networks[0].id + }, + success: function(json) { + var items = json.listloadbalancerssresponse.loadbalancer; + args.response.success({ data: items }); + + } + }); + }, + actions: { + add: { + label: 'Add Internal LB', + createForm: { + title: 'Add Internal LB', + fields: { + name: { label: 'label.name', validation: { required: true } }, + description: { label: 'label.description', validation: { required: false } }, + sourceipaddress: { label: 'Source IP Address', validation: { required: false } }, + sourceport: { label: 'sourceport', validation: { required: true } }, + instanceport: { label: 'instanceport', validation: { required: true } }, + algorithm: { + label: 'label.algorithm', + validation: { required: true }, + select: function(args) { + args.response.success({ + data: [ + { id: 'source', description: 'source' }, + { id: 'roundrobin', description: 'roundrobin' }, + { id: 'leastconn', description: 'leastconn' } + ] + }); + } + } + } + }, + messages: { + notification: function(args) { + return 'Add Internal LB'; + } + }, + action: function(args) { + var data = { + name: args.data.name, + sourceport: args.data.sourceport, + instanceport: args.data.instanceport, + algorithm: args.data.algorithm, + networkid: args.context.networks[0].id, + sourceipaddressnetworkid: args.context.networks[0].id, + scheme: 'Internal' + }; + if(args.data.description != null && args.data.description.length > 0){ + $.extend(data, { + description: args.data.description + }); + } + if(args.data.sourceipaddress != null && args.data.sourceipaddress.length > 0){ + $.extend(data, { + sourceipaddress: args.data.sourceipaddress + }); + } + $.ajax({ + url: createURL('createLoadBalancer'), + data: data, + success: function(json){ + var jid = json.createloadbalancerresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.loadbalancer; + } + } + } + ); + } + }); + + args.response.success(); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + + detailView: { + name: 'Internal Lb details', + actions: { + assignVm: { + label: 'Assign VMs to LB', + messages: { + notification: function(args) { return 'Assign VM to internal LB rule'; } + }, + listView: $.extend(true, {}, cloudStack.sections.instances.listView, { + type: 'checkbox', + filters: false, + dataProvider: function(args) { + $.ajax({ + url: createURL('listVirtualMachines'), + data: { + networkid: args.context.networks[0].id, + listAll: true + }, + success: function(json) { + var instances = json.listvirtualmachinesresponse.virtualmachine; + + // Pre-select existing instances in LB rule + $(instances).map(function(index, instance) { + instance._isSelected = $.grep( + args.context.internalLoadBalancers[0].loadbalancerinstance, + + function(lbInstance) { + return lbInstance.id == instance.id; + } + ).length ? true : false; + }); + + args.response.success({ + data: instances + }); + } + }); + } + }), + action: function(args) { + var vms = args.context.instances; + var array1 = []; + for(var i = 0; i < vms.length; i++) { + array1.push(vms[i].id); + } + var virtualmachineids = array1.join(','); + + $.ajax({ + url: createURL('assignToLoadBalancerRule'), + data: { + id: args.context.internalLoadBalancers[0].id, + virtualmachineids: virtualmachineids + }, + dataType: 'json', + async: true, + success: function(data) { + var jid = data.assigntoloadbalancerruleresponse.jobid; + args.response.success({ + _custom: { jobId: jid } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + tabs: { + details: { + title: 'label.details', + fields: [ + { + name: { label: 'label.name' } + }, + { + id: { label: 'label.id' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL('listLoadBalancers'), + data: { + id: args.context.internalLoadBalancers[0].id + }, + success: function(json) { + var item = json.listloadbalancerssresponse.loadbalancer[0]; + args.response.success({ data: item }); + } + }); + } + }, + rules: { + title: 'label.rules', + multiple: true, + fields: [ + { + sourceport: { label: 'Source Port' }, + instanceport: { label: 'Instance Port' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL('listLoadBalancers'), + data: { + id: args.context.internalLoadBalancers[0].id + }, + success: function(json) { + var item = json.listloadbalancerssresponse.loadbalancer[0]; + args.response.success({ data: item.loadbalancerrule }); + } + }); + } + } , + assignedVms: { + title: 'Assigned VMs', + multiple: true, + fields: [ + { + name: { label: 'label.name' }, + ipaddress: { label: 'label.ip.address' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL('listLoadBalancers'), + data: { + id: args.context.internalLoadBalancers[0].id + }, + success: function(json) { + var item = json.listloadbalancerssresponse.loadbalancer[0]; + args.response.success({ data: item.loadbalancerinstance }); + } + }); + } + } + } + } + } + }, + publicLbIps: { + title: 'Public LB', + listView: { + id: 'publicLbIps', + fields: { + ipaddress: { + label: 'label.ips', + converter: function(text, item) { + if (item.issourcenat) { + return text + ' [' + _l('label.source.nat') + ']'; + } + + return text; + } + }, + zonename: { label: 'label.zone' }, + virtualmachinedisplayname: { label: 'label.vm.name' }, + state: { + converter: function(str) { + // For localization + return str; + }, + label: 'label.state', indicator: { 'Allocated': 'on', 'Released': 'off' } + } + }, + dataProvider: function(args) { + $.ajax({ + url: createURL('listPublicIpAddresses'), + async: false, + data: { networkid: args.context.networks[0].id, forloadbalancing: true }, + success: function(json) { + var items = json.listpublicipaddressesresponse; + args.response.success({ data: items }); + } + }); + } + } + }, + + // Private gateways + privateGateways: function() { + return cloudStack.vpc.gateways.listView() + }, + + // Public IP Addresses + publicIPs: function() { + return cloudStack.vpc.ipAddresses.listView() + }, + + // Network ACL lists + networkACLLists: { + listView: { + id: 'aclLists', + fields: { + name: { label: 'label.name' }, + description: {label:'Description'}, + id: { label: 'id' } + }, + dataProvider: function(args) { + $.ajax({ + url:createURL('listNetworkACLLists&vpc_id=' + args.context.vpc[0].id), + success:function(json){ + var items = json.listnetworkacllistsresponse.networkacllist; + + args.response.success({ + data:items + }); + } + }); + }, + + actions:{ + add:{ + label:'Add ACL List', + createForm:{ + label: 'Add ACL List', + fields:{ + name:{label:'ACL List Name',validation:{required:true}}, + description:{label:'Description',validation:{required:true}} + } + }, + messages: { + notification: function(args) { + return 'Add Network ACL List'; + } + }, + action:function(args){ + var data = { + name:args.data.name, + description:args.data.description + + }; + + $.ajax({ + url:createURL('createNetworkACLList&vpcid='+ args.context.vpc[0].id), + data:data, + success:function(json){ + var items = json.createnetworkacllistresponse; + args.response.success({ + data:items + }); + } + }); + } + } + }, + + detailView: { + isMaximized: true, + actions:{ + remove: { + label:'Delete ACL List', + messages: { + confirm: function(args) { + return 'Are you sure you want to delete this ACL list ?'; + }, + notification: function(args) { + return 'Delete ACL list'; + } + }, + action:function(args){ + $.ajax({ + url:createURL('deleteNetworkACLList&id=' + args.context.aclLists[0].id), + success:function(json){ + var jid = json.deletenetworkacllistresponse.jobid; + args.response.success( + {_custom: + { jobId: jid + } + } + ); + }, + error:function(json){ + args.response.error(parseXMLHttpResponse(json)); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + + tabs: { + details: { + title: 'label.details', + fields: [ + { + name: { label: 'label.name', isEditable: true }, + description: {label:'Description'}, + id:{label:'id'} + } + ], + dataProvider: function(args) { + var items = args.context.aclLists[0]; + setTimeout(function() { + args.response.success({ + data: items, + actionFilter: function(args) { + var allowedActions = []; + if(isAdmin()) { + allowedActions.push("remove"); + + } + return allowedActions; + } + }); + }); + } + }, + + aclRules: { + title: 'ACL List Rules', + custom: function(args) { + return $('
').multiEdit($.extend(true, {}, aclMultiEdit, { + context: args.context, + fields: { + networkid: false + }, + dataProvider: function(args) { + $.ajax({ + url:createURL('listNetworkACLs&aclid=' + args.context.aclLists[0].id), + success:function(json){ + var items = json.listnetworkaclsresponse.networkacl; + + args.response.success({ + data:items + /* { + cidrlist: '10.1.1.0/24', + protocol: 'TCP', + startport: 22, endport: 22, + networkid: 0, + traffictype: 'Egress' + }, + { + cidrlist: '10.2.1.0/24', + protocol: 'UDP', + startport: 56, endport: 72, + networkid: 0, + trafficType: 'Ingress' + } + ]*/ + }); + } + }); + } + })); + } + } + } + } + } + }, + siteToSiteVPNs: function() { + return $.extend(true, {}, cloudStack.vpc.siteToSiteVPN, { + // siteToSiteVPN is multi-section so doesn't have an explicit + // 'listView' block + // + // -- use this as a flag for VPC chart to render as a list view + listView: true, + before: { + messages: { + confirm: 'Please confirm that you would like to create a site-to-site VPN gateway for this VPC.', + notification: 'Create site-to-site VPN gateway' + }, + check: function(args) { + var items; + + $.ajax({ + url: createURL('listVpnGateways&listAll=true'), + data: { + vpcid: args.context.vpc[0].id + }, + success: function(json) { + var items = json.listvpngatewaysresponse.vpngateway; + + args.response.success(items && items.length); + } + }); + }, + action: function(args) { + $.ajax({ + url: createURL("createVpnGateway"), + data: { + vpcid: args.context.vpc[0].id + }, + success: function(json) { + var jid = json.createvpngatewayresponse.jobid; + var pollTimer = setInterval(function() { + pollAsyncJobResult({ + _custom: { jobId: jid }, + complete: function() { + clearInterval(pollTimer); + args.response.success(); + } + }); + }, g_queryAsyncJobResultInterval); + } + }); + } + } + }); + } + }, + routerDetailView: function() { return { title: 'VPC router details', @@ -594,7 +1152,7 @@ ipAddresses: { listView: function() { var listView = $.extend(true, {}, cloudStack.sections.network.sections.ipAddresses); - + listView.listView.fields = { ipaddress: listView.listView.fields.ipaddress, zonename: listView.listView.fields.zonename, @@ -605,6 +1163,35 @@ return listView; } }, + staticNatIpAddresses: { + listView: function() { + var listView = $.extend(true, {}, cloudStack.sections.network.sections.ipAddresses); + + listView.listView.fields = { + ipaddress: listView.listView.fields.ipaddress, + zonename: listView.listView.fields.zonename, + associatednetworkname: { label: 'label.network.name' }, + state: listView.listView.fields.state + }; + + listView.listView.dataProvider = function(args) { + $.ajax({ + url: createURL('listPublicIpAddresses'), + data: { networkid: args.context.networks[0].id, isstaticnat: true }, + success: function(json) { + args.response.success({ + data: json.listpublicipaddressesresponse.publicipaddress + }); + }, + error: function(json) { + args.response.error(parseXMLHttpResponse(json)); + } + }); + }; + + return listView; + } + }, acl: { multiEdit: aclMultiEdit, @@ -1451,7 +2038,7 @@ listAll: true }, success: function(json) { - var items = json.listvpncustomergatewaysresponse.vpncustomergateway; + var items = json.listvpncustomergatewaysresponse.vpncustomergateway ? json.listvpncustomergatewaysresponse.vpncustomergateway: []; args.response.success({ data: $.map(items, function(item) { return { @@ -1651,6 +2238,9 @@ path: 'network.ipAddresses', label: 'label.menu.ipaddresses', preFilter: function(args) { + return false; + + /// Disabled if (args.context.networks[0].state == 'Destroyed') return false; @@ -1895,7 +2485,76 @@ notification: { poll: pollAsyncJobResult } - } + }, + + replaceacllist:{ + + label:'Replace ACL List', + createForm:{ + title:'Replace ACL List', + label:'Replace ACL List', + fields:{ + aclid:{ + label:'ACL', + select:function(args){ + $.ajax({ + url: createURL('listNetworkACLLists'), + dataType: 'json', + async: true, + success: function(json) { + var objs = json.listnetworkacllistsresponse.networkacllist; + var items = []; + $(objs).each(function() { + + items.push({id: this.id, description: this.name}); + }); + args.response.success({data: items}); + } + }); + } + } + } + }, + action: function(args) { + $.ajax({ + url: createURL("replaceNetworkACLList&networkid=" + args.context.networks[0].id + "&aclid=" + args.data.aclid ), + dataType: "json", + success: function(json) { + var jid = json.replacenetworkacllistresponse.jobid; + args.response.success( + + {_custom: + { + jobId: jid, + getUpdatedItem: function(json) { + var item = json.queryasyncjobresultresponse.jobresult.aclid; + return {data:item}; + } + } + } + + ) + }, + + error:function(json){ + + args.response.error(parseXMLHttpResponse(json)); + } + }); + }, + notification: { + poll: pollAsyncJobResult + }, + + messages: { + confirm: function(args) { + return 'Do you want to replace the ACL with a new one ?'; + }, + notification: function(args) { + return 'ACL replaced'; + } + } + } }, tabFilter: function(args) { @@ -1921,7 +2580,7 @@ } }); - var hiddenTabs = ['ipAddresses']; // Disable IP address tab; it is redundant with 'view all' button + var hiddenTabs = ['ipAddresses', 'acl']; // Disable IP address tab; it is redundant with 'view all' button if(networkOfferingHavingELB == false) hiddenTabs.push("addloadBalancer"); @@ -2057,6 +2716,8 @@ isEditable: true }, + aclid:{label:'ACL id'}, + domain: { label: 'label.domain' }, account: { label: 'label.account' } } @@ -2506,23 +3167,169 @@ async: true, success: function(json) { var networks = json.listnetworksresponse.network; - if(networks != null && networks.length > 0) { - for(var i = 0; i < networks.length; i++) { + var networkACLLists, publicIpAddresses, privateGateways, vpnGateways; + var error = false; + + // Get network ACL lists + $.ajax({ + url: createURL('listNetworkACLLists'), + data: { 'vpc_id': args.context.vpc[0].id }, + async: false, + success: function(json) { + networkACLLists = json.listnetworkacllistsresponse; + }, + error: function(json) { + error = true; + } + }); + + // Get public IPs + $.ajax({ + url: createURL('listPublicIpAddresses'), + async: false, + data: { 'vpcid': args.context.vpc[0].id }, + success: function(json) { + publicIpAddresses = json.listpublicipaddressesresponse; + }, + error: function(json) { + error = true; + } + }); + + // Get private gateways + $.ajax({ + url: createURL('listPrivateGateways'), + async: false, + data: { 'vpcid': args.context.vpc[0].id }, + success: function(json) { + privateGateways = json.listprivategatewaysresponse; + }, + error: function(json) { + error = true; + } + }); + + // Get VPN gateways + $.ajax({ + url: createURL('listVpnGateways'), + async: false, + data: { 'vpcid': args.context.vpc[0].id }, + success: function(json) { + vpnGateways = json.listvpngatewaysresponse; + }, + error: function(json) { + error = true; + } + }); + + args.response.success({ + routerDashboard: [ + { + id: 'privateGateways', + name: 'Private gateways', + total: privateGateways.count + }, + { + id: 'publicIPs', + name: 'Public IP addresses', + total: publicIpAddresses.count + }, + { + id: 'siteToSiteVPNs', + name: 'Site-to-site VPNs', + total: vpnGateways.count + }, + { + id: 'networkACLLists', + name: 'Network ACL lists', + total: networkACLLists.count + } + ], + tiers: $(networks).map(function(index, tier) { + var internalLoadBalancers, publicLbIps, virtualMachines, staticNatIps; + + // Get internal load balancers $.ajax({ - url: createURL("listVirtualMachines"), - dataType: "json", - data: { - networkid: networks[i].id, - listAll: true - }, + url: createURL('listLoadBalancers'), async: false, + data: { networkid: tier.id }, success: function(json) { - networks[i].virtualMachines = json.listvirtualmachinesresponse.virtualmachine; + internalLoadBalancers = json.listloadbalancerssresponse; + }, + error: function(json) { + error = true; } }); - } + + // Get Public LB IPs + $.ajax({ + url: createURL('listPublicIpAddresses'), + async: false, + data: { networkid: tier.id, forloadbalancing: true }, + success: function(json) { + publicLbIps = json.listpublicipaddressesresponse; + }, + error: function(json) { + error = true; + } + }); + + // Get static NAT IPs + $.ajax({ + url: createURL('listPublicIpAddresses'), + async: false, + data: { networkid: tier.id, isstaticnat: true }, + success: function(json) { + staticNatIps = json.listpublicipaddressesresponse; + }, + error: function(json) { + error = true; + } + }); + + // Get VMs + $.ajax({ + url: createURL('listVirtualMachines'), + async: false, + data: { networkid: tier.id }, + success: function(json) { + virtualMachines = json.listvirtualmachinesresponse; + }, + error: function(json) { + error = true; + } + }); + + return $.extend(tier, { + _dashboardItems: [ + { + id: 'internalLoadBalancers', + name: 'Internal LB', + total: internalLoadBalancers.count + }, + { + id: 'publicLbIps', + name: 'Public LB IP', + total: publicLbIps.count + }, + { + id: 'tierStaticNATs', + name: 'Static NATs', + total: staticNatIps.count + }, + { + id: 'tierVMs', + name: 'Virtual Machines', + total: virtualMachines.count + } + ] + }); + }) + }); + + if (error) { + cloudStack.dialog.notice({ message: 'Error loading dashboard data.' }); } - args.response.success({ tiers: networks }); } }); } diff --git a/ui/scripts/zoneWizard.js b/ui/scripts/zoneWizard.js index 5a89cb38ee8..a2998b4a9a5 100755 --- a/ui/scripts/zoneWizard.js +++ b/ui/scripts/zoneWizard.js @@ -401,7 +401,6 @@ var nonSupportedHypervisors = {}; if(args.context.zones[0]['network-model'] == "Advanced" && args.context.zones[0]['zone-advanced-sg-enabled'] == "on") { firstOption = "KVM"; - nonSupportedHypervisors["XenServer"] = 1; //to developers: comment this line if you need to test Advanced SG-enabled zone with XenServer hypervisor nonSupportedHypervisors["VMware"] = 1; nonSupportedHypervisors["BareMetal"] = 1; nonSupportedHypervisors["Ovm"] = 1; diff --git a/usage/src/com/cloud/usage/UsageManagerImpl.java b/usage/src/com/cloud/usage/UsageManagerImpl.java index 16fe67bcbec..0c2ad6ef339 100644 --- a/usage/src/com/cloud/usage/UsageManagerImpl.java +++ b/usage/src/com/cloud/usage/UsageManagerImpl.java @@ -18,6 +18,7 @@ package com.cloud.usage; import java.net.InetAddress; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; @@ -119,6 +120,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna int m_pid = 0; TimeZone m_usageTimezone = TimeZone.getTimeZone("GMT");; private final GlobalLock m_heartbeatLock = GlobalLock.getInternLock("usage.job.heartbeat.check"); + private List usageNetworks = new ArrayList(); private final ScheduledExecutorService m_executor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Usage-Job")); private final ScheduledExecutorService m_heartbeatExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Usage-HB")); @@ -547,16 +549,18 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna // loop over the user stats, create delta entries in the usage_network helper table int numAcctsProcessed = 0; + usageNetworks.clear(); for (String key : aggregatedStats.keySet()) { UsageNetworkVO currentNetworkStats = null; if (networkStats != null) { currentNetworkStats = networkStats.get(key); } - + createNetworkHelperEntry(aggregatedStats.get(key), currentNetworkStats, endDateMillis); numAcctsProcessed++; - } - + } + m_usageNetworkDao.saveUsageNetworks(usageNetworks); + if (s_logger.isDebugEnabled()) { s_logger.debug("created network stats helper entries for " + numAcctsProcessed + " accts"); } @@ -999,7 +1003,7 @@ public class UsageManagerImpl extends ManagerBase implements UsageManager, Runna s_logger.debug("creating networkHelperEntry... accountId: " + userStat.getAccountId() + " in zone: " + userStat.getDataCenterId() + "; abr: " + userStat.getAggBytesReceived() + "; abs: " + userStat.getAggBytesSent() + "; curABS: " + currentAccountedBytesSent + "; curABR: " + currentAccountedBytesReceived + "; ubs: " + bytesSent + "; ubr: " + bytesReceived); } - m_usageNetworkDao.persist(usageNetworkVO); + usageNetworks.add(usageNetworkVO); } private void createIPHelperEvent(UsageEventVO event) { diff --git a/utils/src/com/cloud/utils/exception/CloudRuntimeException.java b/utils/src/com/cloud/utils/exception/CloudRuntimeException.java index 30d55b41a82..0d722977694 100755 --- a/utils/src/com/cloud/utils/exception/CloudRuntimeException.java +++ b/utils/src/com/cloud/utils/exception/CloudRuntimeException.java @@ -19,7 +19,6 @@ package com.cloud.utils.exception; import java.util.ArrayList; import java.util.List; -import com.cloud.utils.AnnotationHelper; import com.cloud.utils.Pair; import com.cloud.utils.SerialVersionUID; @@ -30,8 +29,8 @@ public class CloudRuntimeException extends RuntimeException implements ErrorCont private static final long serialVersionUID = SerialVersionUID.CloudRuntimeException; - // This holds a list of uuids and their names. Add uuid:fieldname pairs - protected ArrayList idList = new ArrayList(); + // This holds a list of uuids and their descriptive names. + protected ArrayList idList = new ArrayList(); protected ArrayList, String>> uuidList = new ArrayList, String>>(); @@ -53,18 +52,17 @@ public class CloudRuntimeException extends RuntimeException implements ErrorCont setCSErrorCode(CSExceptionErrorCode.getCSErrCode(this.getClass().getName())); } - public void addProxyObject(String uuid) { - idList.add(uuid); - return; + public void addProxyObject(ExceptionProxyObject obj){ + idList.add(obj); } - public void addProxyObject(Object voObj, Long id, String idFieldName) { - // Get the VO object's table name. - String tablename = AnnotationHelper.getTableName(voObj); - if (tablename != null) { - addProxyObject(tablename, id, idFieldName); + public void addProxyObject(String uuid) { + idList.add(new ExceptionProxyObject(uuid, null)); } - return; + + public void addProxyObject(String voObjUuid, String description) { + ExceptionProxyObject proxy = new ExceptionProxyObject(voObjUuid, description); + idList.add(proxy); } @Override @@ -73,7 +71,7 @@ public class CloudRuntimeException extends RuntimeException implements ErrorCont return this; } - public ArrayList getIdProxyList() { + public ArrayList getIdProxyList() { return idList; } diff --git a/utils/src/com/cloud/utils/exception/ExceptionProxyObject.java b/utils/src/com/cloud/utils/exception/ExceptionProxyObject.java new file mode 100644 index 00000000000..01cbd632c14 --- /dev/null +++ b/utils/src/com/cloud/utils/exception/ExceptionProxyObject.java @@ -0,0 +1,50 @@ +// 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 +// 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.utils.exception; + + +public class ExceptionProxyObject { + private String uuid; + private String description; + + public ExceptionProxyObject(){ + + } + + public ExceptionProxyObject(String uuid, String desc){ + this.uuid = uuid; + this.description = desc; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + +} diff --git a/utils/src/com/cloud/utils/net/NetUtils.java b/utils/src/com/cloud/utils/net/NetUtils.java index 37dcef382aa..8c094c85088 100755 --- a/utils/src/com/cloud/utils/net/NetUtils.java +++ b/utils/src/com/cloud/utils/net/NetUtils.java @@ -61,6 +61,8 @@ public class NetUtils { public final static String ALL_PROTO = "all"; public final static String ALL_CIDRS = "0.0.0.0/0"; + public final static int PORT_RANGE_MIN = 0; + public final static int PORT_RANGE_MAX = 65535; public final static int DEFAULT_AUTOSCALE_VM_DESTROY_TIME = 2 * 60; // Grace period before Vm is destroyed public final static int DEFAULT_AUTOSCALE_POLICY_INTERVAL_TIME = 30; diff --git a/utils/src/com/cloud/utils/ssh/SshHelper.java b/utils/src/com/cloud/utils/ssh/SshHelper.java index 6ee87ad722c..fb81e506ee5 100755 --- a/utils/src/com/cloud/utils/ssh/SshHelper.java +++ b/utils/src/com/cloud/utils/ssh/SshHelper.java @@ -146,10 +146,6 @@ public class SshHelper { } sess = conn.openSession(); - // There is a bug in Trilead library, wait a second before - // starting a shell and executing commands, from http://spci.st.ewi.tudelft.nl/chiron/xref/nl/tudelft/swerl/util/SSHConnection.html - Thread.sleep(1000); - sess.execCommand(command); InputStream stdout = sess.getStdout();