diff --git a/CHANGES b/CHANGES index a1edfdac527..054e7b06615 100644 --- a/CHANGES +++ b/CHANGES @@ -1,7 +1,387 @@ -Apache CloudStack (Incubating) CHANGES +Apache CloudStack CHANGES ====================================== -Full release notes for each release are located in the project's documentation website: http://cloudstack.apache.org/docs +Full release notes for each release are located in the project's documentation website: +http://cloudstack.apache.org/docs + +Version 4.2.0 +------------------------ + +In progress + + + + +Version 4.1.0 +------------------------ + +This is the second major release of CloudStack from within the Apache Software Foundation, and the +first major release as a Top-Level Project (TLP). + +Build Tool Changes: + + * The project now uses Maven 3 exclusively to build. + +New Features: +* CLOUDSTACK-101: OVS support in KVM +* CLOUDSTACK-132: Mash up marvin into an interactive auto-completing API shell for CloudStack +* CLOUDSTACK-241: AWS Style Regions +* CLOUDSTACK-297: Reset SSH Key to access VM (similar to reset password) +* CLOUDSTACK-299: Egress firewall rules for guest network +* CLOUDSTACK-306: Support SRX & F5 inline mode +* CLOUDSTACK-618: API request throttling to avoid malicious attacks on MS per account through frequent API request. +* CLOUDSTACK-637: AutoScale +* CLOUDSTACK-644: Resize volumes feature +* CLOUDSTACK-706: Persistent Networks without running a VM +* CLOUDSTACK-726: Implement L3 Router functionality in Nicira Nvp Plugin +* CLOUDSTACK-780: Additional VMX Settings +* CLOUDSTACK-926: ApiDiscoverService: Implement a plugin mechanism that exposes the list of APIs through a discovery service on the management server + +Bug Fixes: + +* CLOUDSTACK-1600 Typo in dpkg-buildpackage command +* CLOUDSTACK-1574 updateResourceCount API is failed saying to specify valida resource type even after parsing the valid resource type +* CLOUDSTACK-1562 Replace the short-cut solution of supportting @DB with the formal one +* CLOUDSTACK-1541 NPE while deleting snapshot :Unexpected exception while executing org.apache.cloudstack.api.command.user.snapshot.DeleteSnapshotCmd +* CLOUDSTACK-1521 Redundant router: Services are not stopped when switch to BACKUP state +* CLOUDSTACK-1509 Failed to implement network elements and resources while provisioning for persistent network(createVlanIpRange to an account] +* CLOUDSTACK-1496 List API Performance: listAccounts failing with OOME for high values of pagesize (>1000 ) +* CLOUDSTACK-1487 cloudstack-setup-agent fails to set private.network.device on KVM host add +* CLOUDSTACK-1485 Add Baremetal Provider back to 4.1 branch +* CLOUDSTACK-1484 "API Throttling : api.throttling.enabled, Global setting missing" +* CLOUDSTACK-1473 deleteDomain is failing with NPE +* CLOUDSTACK-1470 unhandled exception executing api command: deployVirtualMachine +* CLOUDSTACK-1469 kvm agent: agent service fails to start up +* CLOUDSTACK-1465 List Zones returns null under create instance when logged is as user +* CLOUDSTACK-1449 listAccounts and listProjectAccounts API lists all the users not account-specific users for each account returned +* CLOUDSTACK-1447 [UI]Persistent Status is not displayed for VPC Tiers +* CLOUDSTACK-1436 4.1 management server fails to start from RPM build artifacts +* CLOUDSTACK-1429 single account is unable to use same vnet across multiple physical networks +* CLOUDSTACK-1425 unhandled exception executing api command: migrateVirtualMachine & recoverVirtualMachine +* CLOUDSTACK-1420 Ensure trademarks are properly attributed in publican brand. +* CLOUDSTACK-1419 Apache-ify and apply trademark logos in the UI +* CLOUDSTACK-1418 "As regular user , we are not allowed to deploy VM on a shared network." +* CLOUDSTACK-1417 "When invalid values are passed to createNetwork() , error message does not indicate the parameter name that has invalid values." +* CLOUDSTACK-1414 Redundant router: BACKUP switch cancelled due to lock timeout after a glitch in network +* CLOUDSTACK-1403 Storage and console-proxy related error +* CLOUDSTACK-1402 listRouters API response doesn't return linklocal IP and public IP details +* CLOUDSTACK-1399 Unhandled exception executing api command: stopVirtualMachine +* CLOUDSTACK-1397 Static Nat configuration is failing with NPE +* CLOUDSTACK-1391 EventBus is not getting injected after javelin merge +* CLOUDSTACK-1383 Deploying basic zone on 4.1 fails in NPE +* CLOUDSTACK-1382 "vm deploy fails with Error ""cannot find DeployPlannerSelector for vm""" +* CLOUDSTACK-1375 deploydb failing with acs master +* CLOUDSTACK-1369 "Ipv6 - In dual Stack network , guest VM does not have the Ipv6 address of the router programmed in /etc/resolv.conf for DNS resolution." +* CLOUDSTACK-1367 NPE noticed in logs while AgentMonitor is monitoring the host ping interval +* CLOUDSTACK-1357 "Autoscale: Provisioned VMs from Netscaler not being added to lb vserver, provserver fails with provserver_err_asynctaskpoll" +* CLOUDSTACK-1350 Management server Stop and start causes previously downloaded ISOs and templates to redownload & reinstall +* CLOUDSTACK-1347 "Not able to delete network. Error - ""Unable to insert queue item into database, DB is full?""" +* CLOUDSTACK-1346 "Check to see if external devices are used in the network, is hardcoded for specific devices" +* CLOUDSTACK-1345 BigSwitch plugin introduces 'VNS' isolation in UI without backend implementation +* CLOUDSTACK-1344 Typo in use.external.dns setting description +* CLOUDSTACK-1343 Porting Baremetal related UI changes to ACS +* CLOUDSTACK-1341 URL for the KEYs file is wrong in the installation guide +* CLOUDSTACK-1339 ASF 4.1: Management server becomes unresponsive +* CLOUDSTACK-1338 Deploy VM failed using ISO +* CLOUDSTACK-1334 vmware.root.disk.controller doesn't work. +* CLOUDSTACK-1332 IPV6 - Router and guest Vms should be able to use an IPV6 address for external DNS entry. +* CLOUDSTACK-1331 Upgrade fails for a 2.2.14 Zone having multiple guest networks using network_tags and Public Vlan +* CLOUDSTACK-1330 ec2-run-instances - When -n option is used to deploy multiple Vms API returns error even though few of the Vms have been deployed successfully. +* CLOUDSTACK-1320 Routers naming convention is changed to hostname +* CLOUDSTACK-1319 createCustomerVpnGateway response gives TypeError: json.createvpncustomergatewayresponse is undefined +* CLOUDSTACK-1315 [F5-SRX-InlineMode] Network implement failed with Run time Exception during network upgrade from VR to SRX-F5 +* CLOUDSTACK-1313 Working with Volumes Section Is Missing +* CLOUDSTACK-1312 "Fix rolling upgrades from 4.0 to 4.1 in 4.1 release, fix db schemas to be same as 4.0" +* CLOUDSTACK-1307 Noticed NPE when we put host in maintenance mode in clustered management setup +* CLOUDSTACK-1303 Ipv6 - java.lang.NullPointerException when executing listnetworks() and deployVirtualMachine() after extending the Ipv4 range of a dual stack network. +* CLOUDSTACK-1300 section in wrong order in installation guide +* CLOUDSTACK-1299 Errors in 4.5.5 section of installation guide +* CLOUDSTACK-1295 NPE in usage parsers due to missing @Component inject +* CLOUDSTACK-1289 [F5-SRX-InlineMode] Usage stats are not generated for Juniper SRX Firewall in inlinemode +* CLOUDSTACK-1288 [F5-SRX-InlineMode] classCastException during network restart with cleanup option true +* CLOUDSTACK-1277 ApiResponseHelper.createUserVmResponse failed to populate password field set from UserVm object +* CLOUDSTACK-1272 Autoscale: createAutoScaleVmProfile fails due to unable to retrieve Service Offering id +* CLOUDSTACK-1267 KVM's cloudstack-agent service doesn't log (log4j) +* CLOUDSTACK-1265 logrotate dnsmasq configuration is wrong +* CLOUDSTACK-1262 "Failed to Prepare Secondary Storage in VMware," +* CLOUDSTACK-1251 Baremetal zone doesn't need primary/secondary storage in UI wizard +* CLOUDSTACK-1243 Failed to cleanup account :java.lang.NullPointerException +* CLOUDSTACK-1242 [F5-SRX-InlineMode] Failed to create LB rule with F5-SRX inlinemode deployement +* CLOUDSTACK-1241 Network apply rules logic is broken +* CLOUDSTACK-1237 "Register Template fails with ""Cannot find template adapter for XenServer""" +* CLOUDSTACK-1234 Unable to start KVM agent with 4.1 build +* CLOUDSTACK-1233 Veewee configuration files are inappropriately identified as ASLv2 licensed files +* CLOUDSTACK-1232 "Ipv6 - Guest Vms are not able to get Ipaddress when executing dhclient command when using ""/96"" network." +* CLOUDSTACK-1226 Error while running Cloudstack-setup-databases +* CLOUDSTACK-1223 Exception while starting jetty server: org.springframework.beans.factory.BeanCreationException Error creating bean with name 'apiServer': +* CLOUDSTACK-1222 API rate limit configs: removed double quote in upgrade script +* CLOUDSTACK-1220 Ipv6 - Better error message when deploy Vm fails to get a free Ip address. +* CLOUDSTACK-1219 Ipv6 - Provide better error messages when deploying a Vm with Ip an address that is outside the network's ip range / if the ip address already is assigned to another Vm. +* CLOUDSTACK-1216 UUID is null for admin and failed to register user key with 4.1 +* CLOUDSTACK-1210 Make all pluggable services return list of api cmd classes +* CLOUDSTACK-1206 Failure in Copy of System templates +* CLOUDSTACK-1205 Ipv6 - Ubuntu 12.10 guest Vms looses default route (after it expiration time ~ 30 mts) when ipv6.autoconfig parameters are disabled except for net.ipv6.conf.lo.autoconf which is enabled. +* CLOUDSTACK-1204 Fail to create advance zone due to fail to add host +* CLOUDSTACK-1201 "Failed to create ssh key for user ""cloud"" /var/lib/cloud/management/.ssh/id_rsa and failed to start management server" +* CLOUDSTACK-1190 Make APIChecker interface throw a single sensible exception +* CLOUDSTACK-1181 mvn deploy db failing with NPE +* CLOUDSTACK-1176 Issue with snapshots(create/list) +* CLOUDSTACK-1174 Snapshots related SQL error +* CLOUDSTACK-1173 ConsoleProxyResource instantiation exception +* CLOUDSTACK-1168 Create firewall rule broken +* CLOUDSTACK-1163 Failed with NPE while creating firewall rule +* CLOUDSTACK-1161 Differences between 4.1 and master in ongoing-config-of-external-firewalls-lb.xml +* CLOUDSTACK-1154 Account/Users related API failed due to RegionService inject exception +* CLOUDSTACK-1153 "Ipv6 - Vm deployment fails with ""n must be positive"" error." +* CLOUDSTACK-1152 Missing tag in host-add.xml +* CLOUDSTACK-1141 "Ipv6 - After network restart (and reboot router) , we do not see the existing vms dnsentries not being programmed in the router." +* CLOUDSTACK-1138 "Providing invalid values for gateway, netmask etc in the zoneWizard blocks the VLAN container to load , throwing an error" +* CLOUDSTACK-1123 ListStoragePools API broken by refactor +* CLOUDSTACK-1113 "Ipv6 - Not able to deploy a new VM in this network because of ""Unable to allocate Unique Ipv6 address""" +* CLOUDSTACK-1112 "Errors in ""Prepare the System VM Template""" +* CLOUDSTACK-1111 Ipv6 - listRouters() does not return guestipaddress/ +* CLOUDSTACK-1109 "Ipv6 - Unable to expunge User Vms that are ""Destroyed""." +* CLOUDSTACK-1108 Ipv6 - Not able to restart Networks. +* CLOUDSTACK-1107 Ipv6 - Unable to extend Ip range for a Ipv6 network using craeteVlanIpRange() command - Error code 530 returned. +* CLOUDSTACK-1105 "IpV6 - listVirtualMachines() does not return netmask ,gateway,ipaddress." +* CLOUDSTACK-1104 Ipv6 - listVlanIpRanges() returns error 530. +* CLOUDSTACK-1103 "IpV6 - listNetwork() command does not retrun gateway,netmask,cidr" +* CLOUDSTACK-1095 Ipv6 - dhclient command needs to be run manually on the Vms to get the Ipv6 address. +* CLOUDSTACK-1088 EnableStaticNat error will clear the data in database +* CLOUDSTACK-1087 Update the Developer Guide for ASFCS 4.1 Release +* CLOUDSTACK-1083 listUsageRecords api: removed project results in NPE +* CLOUDSTACK-1082 UI doesn't throw any error message when trying to delete ip range from a network that is in use +* CLOUDSTACK-1079 Deploying AWSAPI with mvn -pl :cloud-awsapi jetty:run fails +* CLOUDSTACK-1070 javelin: NPE on executing registerIso API +* CLOUDSTACK-1064 A type error occurs when trying to add account/register template.... +* CLOUDSTACK-1063 "SG Enabled Advanced Zone - ""Add Guest Networks"" - When user tries to add a guest Network with scope as ""Account"" , he should NOT be presented with ""Offering for shared security group enabled""" +* CLOUDSTACK-1057 regression of changeServiceForVirtualMachine API - fails to find service offering by serviceOfferingId parameter +* CLOUDSTACK-1056 S3 secondary storage fails to upload systemvm template due to KVMHA directory +* CLOUDSTACK-1055 "The overlay still exists when the ""Recurring Snapshots"" dialog is canceled by pressing esc key." +* CLOUDSTACK-1051 API dispatcher unable to find objectVO corresponding to DeleteTemplatecmd +* CLOUDSTACK-1050 No Documentation on Adding a Load Balancer Rule +* CLOUDSTACK-1037 "Make cloudmonkey awesome-er: Online help docs and api discovery, better colored output, parameter value autocompletion" +* CLOUDSTACK-1029 Enter the token to specified project is malfunctioned +* CLOUDSTACK-1027 """Update SSL certificate"" button should properly reflect it's functionality" +* CLOUDSTACK-1024 Regression: Unable to add Xenserver host with latest build +* CLOUDSTACK-1021 the vlan is not creat to right nic. when i creat multi guest network. +* CLOUDSTACK-1016 Not able to deploy VM. +* CLOUDSTACK-1014 Merge ManagementServer and ManagementServerExt +* CLOUDSTACK-1013 running cloudstack overwrites default public/private ssh keys +* CLOUDSTACK-1011 KVM host getting disconnected in cluster environment +* CLOUDSTACK-1010 Host count and Secondary storage count always shows 1 in UI +* CLOUDSTACK-1002 Not able to start VM. +* CLOUDSTACK-995 Not able to add the KVM host. +* CLOUDSTACK-993 """admin"" user is not getting created when management server is started." +* CLOUDSTACK-987 Sections missing in Working With Snapshots +* CLOUDSTACK-985 Different MAC address for RvR caused issue in short term network outrage +* CLOUDSTACK-978 TypeError: instance.displayname is undefined while adding VM's to the LB rule. +* CLOUDSTACK-968 marvin: vlan should be an attribute of the physical_network and not the zone +* CLOUDSTACK-959 Missing sub-sections in document section System Service Offerings +* CLOUDSTACK-938 s2s VPN trouble +* CLOUDSTACK-928 [Simulator] Latency for Agent Commands - change unit of wait from seconds to milliseconds +* CLOUDSTACK-863 Non-printable characters (ASCII control character) such as %00 or %0025 are getting stored in raw/non encoded form in the database. +* CLOUDSTACK-819 Create Account/User API logging password in access logs +* CLOUDSTACK-799 [Load Test] Check router statistics falls behind in gathering stats by more than 2 times the set value +* CLOUDSTACK-798 Move usage related cmd classes from cloud-server to cloud-api +* CLOUDSTACK-736 Integration smoke tests: Fix check for vm name for the deployvm smoke test +* CLOUDSTACK-734 api_refactoring: CreateAccountCmd fails to send response due to NPE in service layer +* CLOUDSTACK-725 UI: Error when the Egress rules tab is selected for a network +* CLOUDSTACK-721 Bytes sent/received in user statistics is empty (CloudStack 4.0) +* CLOUDSTACK-720 Fail to load a png image when accessing the web console +* CLOUDSTACK-717 cloudmonkey fails to parse/print response +* CLOUDSTACK-693 Adding a VPC virtual router to a NiciraNVP enabled network fails +* CLOUDSTACK-691 A warning dialog box shows after reloading the welcome page +* CLOUDSTACK-689 RVR: Stop pending flag is not cleared when user start the disconnected router from another host +* CLOUDSTACK-683 Image Is Missing in the Accessing VM Section +* CLOUDSTACK-660 Network Traffic Labels are not functional in Marvin +* CLOUDSTACK-648 The normal users could change their own login password +* CLOUDSTACK-639 API Refactoring: Adapters for ACL +* CLOUDSTACK-617 Unable to edit a Sub domain +* CLOUDSTACK-614 "ListTemplates API is not returning ""Enable SSH Key"" attribute for any given template" +* CLOUDSTACK-606 Starting VM fails with 'ConcurrentOperationException' in a clustered MS scenario +* CLOUDSTACK-605 Host physical CPU is incorrectly calculated for Vmware hosts +* CLOUDSTACK-599 DhcpEntryCommand fails on Router VM on CS4.0 and vSphere5 with Advanced Network Zone +* CLOUDSTACK-596 DeployVM command takes a lot of time to return job id +* CLOUDSTACK-584 "typos in ""Apache_CloudStack-4.0.0-incubating-CloudStack_Nicira_NVP_Guide-en-US""" +* CLOUDSTACK-573 "NPE at ""com.cloud.network.NetworkManagerImpl.networkOfferingIsConfiguredForExternalNetworking(NetworkManagerImpl.java:4345)"" when create network from the network offering having NULL provider for the service" +* CLOUDSTACK-572 SG Enabled Advanced Zone - Not able to deploy a VM in an account specific shared network. +* CLOUDSTACK-560 Usage server doesn't work in 4.0.0 due to missing db changes +* CLOUDSTACK-556 Erratic window behavior in Quick View tooltip +* CLOUDSTACK-553 "SRX - When adding SRX device make ""Public Network"" - default to ""untrusted"" and ""Private Network"" - default to ""trusted"" as un-editable fields." +* CLOUDSTACK-552 ]Quick view details for a volume displays scroll bar in place of name of the volume when the name of the volume has more no of characters +* CLOUDSTACK-539 Cropped Text in UI under Quick View +* CLOUDSTACK-536 remove citrix cloudpatform from 4.0 build - CloudStack is ASF project +* CLOUDSTACK-527 List API performance optimization by using DB views and removing UUID conversion. +* CLOUDSTACK-522 Log requests in cloudmonkey's log file +* CLOUDSTACK-520 Dependency jar names mismatch with install-non-oss.sh +* CLOUDSTACK-518 API refactoring -- change @Parameter annotation and remove the @IdentityMapper annotation +* CLOUDSTACK-514 Marvin and Cloudmonkey don't work when an API target uses https or an alternate path +* CLOUDSTACK-510 Add button not visible when adding public IPs to physical network +* CLOUDSTACK-508 CLVM copies template to primary storage unnecessarily +* CLOUDSTACK-507 fix api docs for listSSHKeyPairs +* CLOUDSTACK-504 Duplicate guest password scripts in codebase +* CLOUDSTACK-501 Apidocs and marvin does not know how to handle Autoscaling docs +* CLOUDSTACK-500 Passwd-server iptables rules are dropped on domr on fresh start or on reboot +* CLOUDSTACK-499 cloudmonkey CLI can't accept complex parameters +* CLOUDSTACK-493 2.2.x-3.0 DB upgrade support for Advance SG enabled networks +* CLOUDSTACK-481 Installation Guide Doc Error +* CLOUDSTACK-467 Developer's Guide points to cloud.com for API reference +* CLOUDSTACK-465 French language file quotes are dropping javascript syntax errors +* CLOUDSTACK-464 "Regression in AWSAPI docs, entire sections removed" +* CLOUDSTACK-462 A few corrections to make to the 4.0.0 installation guide +* CLOUDSTACK-459 [Optional Public IP assignment for EIP with Basic Zone] Associate IP Checkbox in Create Network Offering Dialog is Displayed When Elastic LB is Selected +* CLOUDSTACK-456 License tag in SPEC isn't what RPM is expecting +* CLOUDSTACK-448 SSVM bootstrap failure on XenServer hosts with E3 CPU +* CLOUDSTACK-446 "Host going to alert state, if you are adding already added host" +* CLOUDSTACK-441 Running mgmt server using jetty fails to start api server +* CLOUDSTACK-435 Vmware network labels are ignored when creating a Zone using basic networking +* CLOUDSTACK-427 Change hardcoded step number references to dynamic links +* CLOUDSTACK-424 Updated userdata not propagating to the VR. +* CLOUDSTACK-417 Handle password server securely to run on port 8080 on VR +* CLOUDSTACK-416 XCP 1.6beta2 (61002c) - can't add a host +* CLOUDSTACK-404 Update docs on the usage of cloud-setup-databases +* CLOUDSTACK-398 Install Guide: Section 11.17.3 (Using VPN with Mac OSX): Not complete? +* CLOUDSTACK-397 Install Guide: Section 11.1 (Guest Traffic): Diagram is the wrong diagram +* CLOUDSTACK-390 Install Guide: Section 4.5.7 (Prepare the System VM Template): Links go to cloud.com +* CLOUDSTACK-378 mavenize marvin on master +* CLOUDSTACK-377 provide deployment config access to marvin's testcase +* CLOUDSTACK-373 "static NAT and Firewall is not working on external firewall device SRX, it needs to be implemented" +* CLOUDSTACK-369 ASF 4.0 - unable to support XenServer 6.1 host +* CLOUDSTACK-364 Docs point to download.cloud.com for AWS API script +* CLOUDSTACK-361 Wrong creation of guest networks on a KVM host in Multiple Physical Networks with guest traffic +* CLOUDSTACK-359 PropagateResourceEventCommand failes in cluster configuration +* CLOUDSTACK-357 "ISOs can be deleted while still attached to a running VM, and they subsequently cannot be detached from a running VM" +* CLOUDSTACK-355 "Fix ""count"" in a bunch of API commands" +* CLOUDSTACK-348 deleteNetwork does not clean up network resource count correctly +* CLOUDSTACK-347 listNetworks API: return vlan information only when the caller is ROOT admin +* CLOUDSTACK-346 Cannot add Vmware cluster with class loader conflict exception +* CLOUDSTACK-335 KVM VPC load balancer not working +* CLOUDSTACK-333 When Datacenter name in VCenter has spaces Primary Storage (VMFS) discovery will fail +* CLOUDSTACK-332 """count"" property in list* API response should be equal to how many entries in database, not how many objects in API response" +* CLOUDSTACK-318 Adding XenServer Host Fails - 6.0.2 fails with 4.0.0 +* CLOUDSTACK-304 Add synchronization for createSnapshot command per host basis +* CLOUDSTACK-293 "We do awful, hacky things in our spec file for client" +* CLOUDSTACK-290 3.0.0 template also needed for 2.2.14 to 3.0.5 direct upgrade. +* CLOUDSTACK-284 listVirtualMachines does not return deleted machines when zone is specified +* CLOUDSTACK-279 deleteProject fails when executed by the regular user (works fine for root/domain admin) +* CLOUDSTACK-274 Two error codes mapped to same value in API +* CLOUDSTACK-271 updatePhysicalNetwork dies with an NPE when the vlan range is empty +* CLOUDSTACK-256 "vpn:As an admin user , not able to delete VPN user which is present in a regular user's network." +* CLOUDSTACK-250 Incorrect description of maintenance mode in admin guide +* CLOUDSTACK-249 Add host id to failed VM deploy alerts +* CLOUDSTACK-235 Network rate can be set in 2 places. Clarify docs on how this works. +* CLOUDSTACK-232 Zone infrastructure chart -- disable resource total display +* CLOUDSTACK-228 UI provides an option to reconnect a disconnected host - ServerApiException is thrown on an attempt +* CLOUDSTACK-227 ReconnectHostCmd: NullPointerException: Unable to get host Information for XenServer 6.0.2 host - on intentionally changing the traffic labels on the physical network +* CLOUDSTACK-226 UpdatePhysicalNetworkcommand failed due to java.sql.BatchUpdateException ; Tried to extend the existing Guest VLAN Range of one physical network into the Guest VLAN range of the other physical network +* CLOUDSTACK-225 API Docs: Request params repeated with different descriptions +* CLOUDSTACK-222 Admin UI prompts to restart Management server with cancel edit operation +* CLOUDSTACK-178 Expose name parameter of VM in list Vm view. +* CLOUDSTACK-130 Clarify docs on tags parameter in API reference +* CLOUDSTACK-119 Move Agent-Simulator in to the hypervisor plugin model +* CLOUDSTACK-118 "Status of host resorce stuck in ""ErrorInMaintenance""" +* CLOUDSTACK-95 IP address allocation not working when a user tries to allocate IP addresses in a Project. +* CLOUDSTACK-70 Improve Network Restart Behaviour for Basic Zone: Restarting Network Fails +* CLOUDSTACK-46 Remnants of mycloud remain + +Security Fixes: + + * CVE-2012-4501: Apache CloudStack configuration vulnerability + + +Version 4.0.2 +------------------------ + +This is a maintenance release for the Apache CloudStack 4.0.x series, with no new features. + +Issues fixed in this release: + +* CLOUDSTACK-354: Display of storage statistics is wrong. +* CLOUDSTACK-397: Install Guide: Section 11.1 (Guest Traffic): Diagram is the wrong diagram +* CLOUDSTACK-398: Install Guide: Section 11.17.3 (Using VPN with Mac OSX): Not complete? +* CLOUDSTACK-462: A few corrections to make to the 4.0.0 installation guide +* CLOUDSTACK-524: http proxy used by ssvm (secstorage.proxy) NOT working +* CLOUDSTACK-587: MEMORY_CONSTRAINT_VIOLATIONMemory limits must satisfy: +* CLOUDSTACK-803: HA gets triggered even when the host investigator is unable to determine the state of the host +* CLOUDSTACK-810: Make DirectAgent thread pool size configurable +* CLOUDSTACK-976: unable to start cloudstack (error: "java.lang.NoSuchMethodError: org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString([B)Ljava/lang/String;") +* CLOUDSTACK-988: HV version must be updated in hypervisor_version column of host table +* CLOUDSTACK-990: Documentation issue with libvirtd.conf tcp_port configuration +* CLOUDSTACK-1088: EnableStaticNat error will clear the data in database +* CLOUDSTACK-1106: Missing documentation for cloud-setup-databases +* CLOUDSTACK-1110: Documentation missing "Management Server Load Balancing" +* CLOUDSTACK-1112: Errors in "Prepare the System VM Template" +* CLOUDSTACK-1137: Force reconnect of a disconnected state complains about the state of the host. +* CLOUDSTACK-1150: Documentation for libvirt on Ubuntu 12.04 +* CLOUDSTACK-1151: vmware systemVm template upgrade is missing in 4.0 upgrade +* CLOUDSTACK-1211: Network operations are Blocked for the Read-only file system of Virtual Router +* CLOUDSTACK-1265: logrotate dnsmasq configuration is wrong +* CLOUDSTACK-1291: duplicate arguments in commands.xml prevents cloudapis.py to run to completion +* CLOUDSTACK-1298: typo in deb package setup +* CLOUDSTACK-1299: Errors in 4.5.5 section of installation guide +* CLOUDSTACK-1300: section in wrong order in installation guide +* CLOUDSTACK-1341: URL for the KEYs file is wrong in the installation guide +* CLOUDSTACK-1419: Apache-ify and apply trademark logos in the UI +* CLOUDSTACK-1420: Ensure trademarks are properly attributed in publican brand. +* CLOUDSTACK-1589: Ubuntu 4.0 packages depend on non-existent chkconfig +* CLOUDSTACK-1629: Need to move location or conflict with antlr +* CLOUDSTACK-1642: Add support CentOS 6.4 +* CLOUDSTACK-1648: Unable to add KVM host +* CLOUDSTACK-1652: /etc/hosts error in virtual router when deploy instance with the name same to previous instances +* CLOUDSTACK-1666: KVM VPC NetworkUsage doesnot work +* CLOUDSTACK-1668: IP conflict in VPC tier +* CLOUDSTACK-1761: Available local storage disk capacity incorrectly reported in KVM to manager. +* CLOUDSTACK-1845: KVM - storage migration often fails +* CLOUDSTACK-1846: KVM - storage pools can silently fail to be unregistered, leading to failure to register later +* CLOUDSTACK-2003: Deleting domain while deleted account is cleaning up leaves VMs expunging forever due to 'Failed to update resource count' +* CLOUDSTACK-2090: Upgrade from version 4.0.1 to version 4.0.2 triggers the 4.0.0 to 4.0.1. +* CLOUDSTACK-2091: Error in API documentation for 4.0.x. + + +Version 4.0.1-incubating +------------------------ + +This is a bugfix release for Apache CloudStack 4.0.0-incubating, with no new features. + +Security Fixes: + +* CVE-2012-5616: Local Information Disclosure Vulnerability (See CLOUDSTACK-505) + +Bugs fixed in this release: + +* CLOUDSTACK-359: PropagateResourceEventCommand fails in cluster configuration +* CLOUDSTACK-374: When running cloud-setup-databases, it auto chooses the highest priority nic (lowest number ie: eth0) +* CLOUDSTACK-389: Install Guide: Section 4.5.5 (Prepare NFS Shares): Confusing statement about iSCSI +* CLOUDSTACK-395: Primary Storage and Secondary Storage sections missing sub-sections +* CLOUDSTACK-411: Add another step during kvm agent installation on Ubuntu machine +* CLOUDSTACK-415: restartNetwork call causes VM to be unreachable when Nicira based SDN is used. +* CLOUDSTACK-422: XSL files missing license header. +* CLOUDSTACK-426: SetVPCStaticNatRules unimplemented for KVM. +* CLOUDSTACK-448: SSVM bootstrap failure on XenServer hosts with E3 CPU. +* CLOUDSTACK-465: French language file quotes are dropping javascript syntax errors. +* CLOUDSTACK-473: API Doc for uploadCustomCertificate doesn't explain how to use the optional parameters well. +* CLOUDSTACK-480: Installation Documentation error: Section 4.5.5.2 needs to mention nfs-kernel-server. +* CLOUDSTACK-481: Installation Guide Doc Error +* CLOUDSTACK-498: Missing dependency in RPM of KVM Agent. +* CLOUDSTACK-502: VPC router needs to resolve its hostname. +* CLOUDSTACK-505: cloudstack logs the private key in plaintext. +* CLOUDSTACK-507: fix api docs for listSSHKeyPairs. +* CLOUDSTACK-515: NVP installation. +* CLOUDSTACK-536: remove citrix cloudpatform from 4.0 build - CloudStack is ASF project. +* CLOUDSTACK-560: Usage server doesn't work in 4.0.0 due to missing db changes. +* CLOUDSTACK-580: Packages are named with 4.0 with 4.0.1 build. +* CLOUDSTACK-591: Wrong vnet in iptables on KVM hypervisors after VM reboot. +* CLOUDSTACK-595: Recreate root volume scenarios doesn't work in VMware +* CLOUDSTACK-603: Upgrade from 4.0 to 4.0.1 is not enabled. +* CLOUDSTACK-605: Host physical CPU is incorrectly calculated for VMware host +* CLOUDSTACK-622: In the add primary storage dialog in the ui the RBD fields don't disappear when changing from RBD to another protocol. +* CLOUDSTACK-683: Image is missing in the Accessing VM Section +* CLOUDSTACK-685: CloudStack 4.0 Network Usage is ZERO +* CLOUDSTACK-938: s2s VPN trouble +* CLOUDSTACK-961: Installation docs don't detail dependencies for building RPMs +* CLOUDSTACK-995: Not able to add the KVM host + Version 4.0.0-incubating ------------------------ @@ -34,4 +414,3 @@ New Features: Security Fixes: * CVE-2012-4501: Apache CloudStack configuration vulnerability - diff --git a/README.md b/README.md index 7fb9b57c53f..fda0b894e35 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -Apache CloudStack (Incubating) Version 4.0.0 +Apache CloudStack Version 4.2.0 -# About Apache CloudStack (Incubating) +# About Apache CloudStack -Apache CloudStack (Incubating) is software designed to deploy +Apache CloudStack is software designed to deploy and manage large networks of virtual machines, as a highly available, highly scalable Infrastructure as a Service (IaaS) cloud computing platform. CloudStack is used by a number of diff --git a/api/src/com/cloud/agent/api/DeleteSnapshotBackupCommand.java b/api/src/com/cloud/agent/api/DeleteSnapshotBackupCommand.java index 6114148954f..128df84c729 100644 --- a/api/src/com/cloud/agent/api/DeleteSnapshotBackupCommand.java +++ b/api/src/com/cloud/agent/api/DeleteSnapshotBackupCommand.java @@ -19,6 +19,7 @@ package com.cloud.agent.api; import com.cloud.agent.api.LogLevel.Log4jLevel; import com.cloud.agent.api.to.S3TO; import com.cloud.agent.api.to.SwiftTO; +import com.cloud.storage.StoragePool; /** * This command encapsulates a primitive operation which enables coalescing the backed up VHD snapshots on the secondary server @@ -78,7 +79,8 @@ public class DeleteSnapshotBackupCommand extends SnapshotCommand { * @param backupUUID The VHD which has to be deleted * @param childUUID The child VHD file of the backup whose parent is reset to its grandparent. */ - public DeleteSnapshotBackupCommand(SwiftTO swift, + public DeleteSnapshotBackupCommand(StoragePool pool, + SwiftTO swift, S3TO s3, String secondaryStoragePoolURL, Long dcId, @@ -86,7 +88,7 @@ public class DeleteSnapshotBackupCommand extends SnapshotCommand { Long volumeId, String backupUUID, Boolean all) { - super(null, secondaryStoragePoolURL, backupUUID, null, dcId, accountId, volumeId); + super(pool, secondaryStoragePoolURL, backupUUID, null, dcId, accountId, volumeId); setSwift(swift); this.s3 = s3; setAll(all); diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageAnswer.java b/api/src/com/cloud/agent/api/MigrateWithStorageAnswer.java new file mode 100644 index 00000000000..06aff323bdc --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageAnswer.java @@ -0,0 +1,39 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.api; + +import java.util.List; +import com.cloud.agent.api.to.VolumeTO; + +public class MigrateWithStorageAnswer extends Answer { + + List volumeTos; + + public MigrateWithStorageAnswer(MigrateWithStorageCommand cmd, Exception ex) { + super(cmd, ex); + volumeTos = null; + } + + public MigrateWithStorageAnswer(MigrateWithStorageCommand cmd, List volumeTos) { + super(cmd, true, null); + this.volumeTos = volumeTos; + } + + public List getVolumeTos() { + return volumeTos; + } +} diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageCommand.java b/api/src/com/cloud/agent/api/MigrateWithStorageCommand.java new file mode 100644 index 00000000000..058aa15338e --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageCommand.java @@ -0,0 +1,45 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.api; + +import java.util.Map; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.agent.api.to.StorageFilerTO; + +public class MigrateWithStorageCommand extends Command { + VirtualMachineTO vm; + Map volumeToFiler; + + public MigrateWithStorageCommand(VirtualMachineTO vm, Map volumeToFiler) { + this.vm = vm; + this.volumeToFiler = volumeToFiler; + } + + public VirtualMachineTO getVirtualMachine() { + return vm; + } + + public Map getVolumeToFiler() { + return volumeToFiler; + } + + @Override + public boolean executeInSequence() { + return true; + } +} diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageCompleteAnswer.java b/api/src/com/cloud/agent/api/MigrateWithStorageCompleteAnswer.java new file mode 100644 index 00000000000..920cf48ca49 --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageCompleteAnswer.java @@ -0,0 +1,38 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.api; + +import java.util.List; +import com.cloud.agent.api.to.VolumeTO; + +public class MigrateWithStorageCompleteAnswer extends Answer { + List volumeTos; + + public MigrateWithStorageCompleteAnswer(MigrateWithStorageCompleteCommand cmd, Exception ex) { + super(cmd, ex); + volumeTos = null; + } + + public MigrateWithStorageCompleteAnswer(MigrateWithStorageCompleteCommand cmd, List volumeTos) { + super(cmd, true, null); + this.volumeTos = volumeTos; + } + + public List getVolumeTos() { + return volumeTos; + } +} diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageCompleteCommand.java b/api/src/com/cloud/agent/api/MigrateWithStorageCompleteCommand.java new file mode 100644 index 00000000000..1303c07c56f --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageCompleteCommand.java @@ -0,0 +1,36 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.api; + +import com.cloud.agent.api.to.VirtualMachineTO; + +public class MigrateWithStorageCompleteCommand extends Command { + VirtualMachineTO vm; + + public MigrateWithStorageCompleteCommand(VirtualMachineTO vm) { + this.vm = vm; + } + + public VirtualMachineTO getVirtualMachine() { + return vm; + } + + @Override + public boolean executeInSequence() { + return false; + } +} diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageReceiveAnswer.java b/api/src/com/cloud/agent/api/MigrateWithStorageReceiveAnswer.java new file mode 100644 index 00000000000..3bf521ce535 --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageReceiveAnswer.java @@ -0,0 +1,55 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.api; + +import java.util.Map; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.agent.api.to.NicTO; + +public class MigrateWithStorageReceiveAnswer extends Answer { + + Map volumeToSr; + Map nicToNetwork; + Map token; + + public MigrateWithStorageReceiveAnswer(MigrateWithStorageReceiveCommand cmd, Exception ex) { + super(cmd, ex); + volumeToSr = null; + nicToNetwork = null; + token = null; + } + + public MigrateWithStorageReceiveAnswer(MigrateWithStorageReceiveCommand cmd, Map volumeToSr, + Map nicToNetwork, Map token) { + super(cmd, true, null); + this.volumeToSr = volumeToSr; + this.nicToNetwork = nicToNetwork; + this.token = token; + } + + public Map getVolumeToSr() { + return volumeToSr; + } + + public Map getNicToNetwork() { + return nicToNetwork; + } + + public Map getToken() { + return token; + } +} diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageReceiveCommand.java b/api/src/com/cloud/agent/api/MigrateWithStorageReceiveCommand.java new file mode 100644 index 00000000000..df6740574a7 --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageReceiveCommand.java @@ -0,0 +1,45 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.api; + +import java.util.Map; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.agent.api.to.StorageFilerTO; + +public class MigrateWithStorageReceiveCommand extends Command { + VirtualMachineTO vm; + Map volumeToFiler; + + public MigrateWithStorageReceiveCommand(VirtualMachineTO vm, Map volumeToFiler) { + this.vm = vm; + this.volumeToFiler = volumeToFiler; + } + + public VirtualMachineTO getVirtualMachine() { + return vm; + } + + public Map getVolumeToFiler() { + return volumeToFiler; + } + + @Override + public boolean executeInSequence() { + return true; + } +} diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageSendAnswer.java b/api/src/com/cloud/agent/api/MigrateWithStorageSendAnswer.java new file mode 100644 index 00000000000..7cf641f7845 --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageSendAnswer.java @@ -0,0 +1,39 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.api; + +import java.util.Set; +import com.cloud.agent.api.to.VolumeTO; + +public class MigrateWithStorageSendAnswer extends Answer { + + Set volumeToSet; + + public MigrateWithStorageSendAnswer(MigrateWithStorageSendCommand cmd, Exception ex) { + super(cmd, ex); + volumeToSet = null; + } + + public MigrateWithStorageSendAnswer(MigrateWithStorageSendCommand cmd, Set volumeToSet) { + super(cmd, true, null); + this.volumeToSet = volumeToSet; + } + + public Set getVolumeToSet() { + return volumeToSet; + } +} diff --git a/api/src/com/cloud/agent/api/MigrateWithStorageSendCommand.java b/api/src/com/cloud/agent/api/MigrateWithStorageSendCommand.java new file mode 100644 index 00000000000..d10db30effa --- /dev/null +++ b/api/src/com/cloud/agent/api/MigrateWithStorageSendCommand.java @@ -0,0 +1,58 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.api; + +import java.util.Map; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.agent.api.to.NicTO; + +public class MigrateWithStorageSendCommand extends Command { + VirtualMachineTO vm; + Map volumeToSr; + Map nicToNetwork; + Map token; + + public MigrateWithStorageSendCommand(VirtualMachineTO vm, Map volumeToSr, + Map nicToNetwork, Map token) { + this.vm = vm; + this.volumeToSr = volumeToSr; + this.nicToNetwork = nicToNetwork; + this.token = token; + } + + public VirtualMachineTO getVirtualMachine() { + return vm; + } + + public Map getVolumeToSr() { + return volumeToSr; + } + + public Map getNicToNetwork() { + return nicToNetwork; + } + + public Map getToken() { + return token; + } + + @Override + public boolean executeInSequence() { + return true; + } +} diff --git a/api/src/com/cloud/agent/api/storage/MigrateVolumeAnswer.java b/api/src/com/cloud/agent/api/storage/MigrateVolumeAnswer.java new file mode 100644 index 00000000000..d5efa9527b5 --- /dev/null +++ b/api/src/com/cloud/agent/api/storage/MigrateVolumeAnswer.java @@ -0,0 +1,38 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.api.storage; + +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; + +public class MigrateVolumeAnswer extends Answer { + private String volumePath; + + public MigrateVolumeAnswer(Command command, boolean success, String details, String volumePath) { + super(command, success, details); + this.volumePath = volumePath; + } + + public MigrateVolumeAnswer(Command command) { + super(command); + this.volumePath = null; + } + + public String getVolumePath() { + return volumePath; + } +} \ No newline at end of file diff --git a/api/src/com/cloud/agent/api/storage/MigrateVolumeCommand.java b/api/src/com/cloud/agent/api/storage/MigrateVolumeCommand.java new file mode 100644 index 00000000000..b82d8481f2c --- /dev/null +++ b/api/src/com/cloud/agent/api/storage/MigrateVolumeCommand.java @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.agent.api.storage; + +import com.cloud.agent.api.Command; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.storage.StoragePool; + +public class MigrateVolumeCommand extends Command { + + long volumeId; + String volumePath; + StorageFilerTO pool; + + public MigrateVolumeCommand(long volumeId, String volumePath, StoragePool pool) { + this.volumeId = volumeId; + this.volumePath = volumePath; + this.pool = new StorageFilerTO(pool); + } + + @Override + public boolean executeInSequence() { + return true; + } + + public String getVolumePath() { + return volumePath; + } + + public long getVolumeId() { + return volumeId; + } + + public StorageFilerTO getPool() { + return pool; + } +} \ No newline at end of file diff --git a/api/src/com/cloud/hypervisor/HypervisorCapabilities.java b/api/src/com/cloud/hypervisor/HypervisorCapabilities.java index aff81b0018d..c954750a12a 100644 --- a/api/src/com/cloud/hypervisor/HypervisorCapabilities.java +++ b/api/src/com/cloud/hypervisor/HypervisorCapabilities.java @@ -52,4 +52,6 @@ public interface HypervisorCapabilities extends Identity, InternalIdentity{ */ Integer getMaxHostsPerCluster(); + boolean isStorageMotionSupported(); + } diff --git a/api/src/com/cloud/network/IpAddress.java b/api/src/com/cloud/network/IpAddress.java index fce8f38c2f2..71c9b4e0bf3 100644 --- a/api/src/com/cloud/network/IpAddress.java +++ b/api/src/com/cloud/network/IpAddress.java @@ -78,16 +78,7 @@ public interface IpAddress extends ControlledEntity, Identity, InternalIdentity boolean getSystem(); - /** - * @return - */ Long getVpcId(); - /** - * @param vpcId - */ - void setVpcId(Long vpcId); String getVmIp(); - void setVmIp(String vmIp); - } diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index ffe70d19dc0..4472dbacc53 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -16,24 +16,11 @@ // under the License. package com.cloud.network; -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -import org.apache.cloudstack.acl.ControlledEntity; -import org.apache.cloudstack.api.Identity; -import org.apache.cloudstack.api.InternalIdentity; - -import com.cloud.network.Networks.BroadcastDomainType; -import com.cloud.network.Networks.Mode; -import com.cloud.network.Networks.TrafficType; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; import com.cloud.utils.fsm.StateMachine2; import com.cloud.utils.fsm.StateObject; - import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; @@ -183,6 +170,7 @@ public interface Network extends ControlledEntity, StateObject, I public static final Capability AllowDnsSuffixModification = new Capability("AllowDnsSuffixModification"); public static final Capability RedundantRouter = new Capability("RedundantRouter"); public static final Capability ElasticIp = new Capability("ElasticIp"); + public static final Capability AssociatePublicIP = new Capability("AssociatePublicIP"); public static final Capability ElasticLb = new Capability("ElasticLb"); public static final Capability AutoScaleCounters = new Capability("AutoScaleCounters"); public static final Capability InlineMode = new Capability("InlineMode"); diff --git a/api/src/com/cloud/network/NetworkService.java b/api/src/com/cloud/network/NetworkService.java index 066009b8b75..5a6054da23b 100755 --- a/api/src/com/cloud/network/NetworkService.java +++ b/api/src/com/cloud/network/NetworkService.java @@ -79,7 +79,7 @@ public interface NetworkService { Long startIndex, Long pageSize, String name); PhysicalNetwork updatePhysicalNetwork(Long id, String networkSpeed, List tags, - String newVnetRangeString, String state); + String newVnetRangeString, String state, String removeVlan); boolean deletePhysicalNetwork(Long id); diff --git a/api/src/com/cloud/network/PhysicalNetwork.java b/api/src/com/cloud/network/PhysicalNetwork.java index a2044a61047..c521dc4f888 100644 --- a/api/src/com/cloud/network/PhysicalNetwork.java +++ b/api/src/com/cloud/network/PhysicalNetwork.java @@ -18,6 +18,7 @@ package com.cloud.network; import java.util.List; +import com.cloud.utils.Pair; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; @@ -59,7 +60,9 @@ public interface PhysicalNetwork extends Identity, InternalIdentity { Long getDomainId(); - String getVnet(); + List> getVnet(); + + String getVnetString(); String getSpeed(); diff --git a/api/src/com/cloud/network/PublicIpAddress.java b/api/src/com/cloud/network/PublicIpAddress.java index d81e9c1ee6c..916d43428e9 100644 --- a/api/src/com/cloud/network/PublicIpAddress.java +++ b/api/src/com/cloud/network/PublicIpAddress.java @@ -30,7 +30,4 @@ public interface PublicIpAddress extends ControlledEntity, IpAddress, Vlan, Inte public String getNetmask(); public String getGateway(); - - @Override - public String getVlanTag(); } diff --git a/api/src/com/cloud/network/element/IpDeployer.java b/api/src/com/cloud/network/element/IpDeployer.java index c92d3e3cf2d..d356c3b7d01 100644 --- a/api/src/com/cloud/network/element/IpDeployer.java +++ b/api/src/com/cloud/network/element/IpDeployer.java @@ -28,7 +28,11 @@ import com.cloud.utils.component.Adapter; public interface IpDeployer extends Adapter{ /** - * Apply ip addresses to this network + * Modify ip addresses on this network + * Depending on the State of the ip addresses the element should take + * appropriate action. + * If state is Releasing the ip address should be de-allocated + * If state is Allocating or Allocated the ip address should be provisioned * @param network * @param ipAddress * @return diff --git a/api/src/com/cloud/offering/NetworkOffering.java b/api/src/com/cloud/offering/NetworkOffering.java index bd14acd4718..6f0b9937854 100644 --- a/api/src/com/cloud/offering/NetworkOffering.java +++ b/api/src/com/cloud/offering/NetworkOffering.java @@ -107,6 +107,8 @@ public interface NetworkOffering extends InfrastructureEntity, InternalIdentity, boolean getElasticIp(); + boolean getAssociatePublicIP(); + boolean getElasticLb(); boolean getSpecifyIpRanges(); diff --git a/api/src/com/cloud/server/ManagementService.java b/api/src/com/cloud/server/ManagementService.java index 6e6dbc36f0c..22494072648 100755 --- a/api/src/com/cloud/server/ManagementService.java +++ b/api/src/com/cloud/server/ManagementService.java @@ -75,9 +75,11 @@ import com.cloud.network.IpAddress; import com.cloud.org.Cluster; import com.cloud.storage.GuestOS; import com.cloud.storage.GuestOsCategory; +import com.cloud.storage.StoragePool; import com.cloud.template.VirtualMachineTemplate; import com.cloud.user.SSHKeyPair; import com.cloud.utils.Pair; +import com.cloud.utils.Ternary; import com.cloud.vm.InstanceGroup; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachine.Type; @@ -388,10 +390,21 @@ public interface ManagementService { * @param Long * vmId * Id of The VM to migrate - * @return Pair, List> List of all Hosts in VM's cluster and list of Hosts with - * enough capacity + * @return Ternary, List, Map> List of all Hosts to which a VM + * can be migrated, list of Hosts with enough capacity and hosts requiring storage motion for migration. */ - Pair, Integer>, List> listHostsForMigrationOfVM(Long vmId, Long startIndex, Long pageSize); + Ternary, Integer>, List, Map> listHostsForMigrationOfVM( + Long vmId, Long startIndex, Long pageSize); + + /** + * List storage pools for live migrating of a volume. The API returns list of all pools in the cluster to which the + * volume can be migrated. Current pool is not included in the list. + * + * @param Long volumeId + * @return Pair, List> List of storage pools in cluster and list + * of pools with enough capacity. + */ + Pair, List> listStoragePoolsForMigrationOfVolume(Long volumeId); String[] listEventTypes(); @@ -407,6 +420,4 @@ public interface ManagementService { */ List listTopConsumedResources(ListCapacityCmd cmd); - List listDeploymentPlanners(); - } diff --git a/api/src/com/cloud/user/Account.java b/api/src/com/cloud/user/Account.java index 5d32fb23253..940a0eb2667 100755 --- a/api/src/com/cloud/user/Account.java +++ b/api/src/com/cloud/user/Account.java @@ -22,6 +22,7 @@ import org.apache.cloudstack.acl.ControlledEntity; import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; + public interface Account extends ControlledEntity, InternalIdentity, Identity { public enum Type { Normal, @@ -64,4 +65,7 @@ public interface Account extends ControlledEntity, InternalIdentity, Identity { public Long getDefaultZoneId(); public String getUuid(); + + boolean isDefault(); + } diff --git a/api/src/com/cloud/user/User.java b/api/src/com/cloud/user/User.java index 3742c7bf3e2..dcf27a0de69 100644 --- a/api/src/com/cloud/user/User.java +++ b/api/src/com/cloud/user/User.java @@ -72,5 +72,7 @@ public interface User extends OwnedBy, InternalIdentity { String getRegistrationToken(); boolean isRegistered(); + + boolean isDefault(); } diff --git a/api/src/com/cloud/vm/UserVmService.java b/api/src/com/cloud/vm/UserVmService.java index d963b74b080..aa2113617bd 100755 --- a/api/src/com/cloud/vm/UserVmService.java +++ b/api/src/com/cloud/vm/UserVmService.java @@ -405,6 +405,33 @@ public interface UserVmService { */ VirtualMachine migrateVirtualMachine(Long vmId, Host destinationHost) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException; + /** + * Migrate the given VM with its volumes to the destination host. The API returns the migrated VM if it succeeds. + * Only root admin can migrate a VM. + * + * @param destinationStorage + * TODO + * @param Long + * vmId of The VM to migrate + * @param Host + * destinationHost to migrate the VM + * @param Map + * A map of volume to which pool it should be migrated + * + * @return VirtualMachine migrated VM + * @throws ManagementServerException + * in case we get error finding the VM or host or access errors or other internal errors. + * @throws ConcurrentOperationException + * if there are multiple users working on the same VM. + * @throws ResourceUnavailableException + * if the destination host to migrate the VM is not currently available. + * @throws VirtualMachineMigrationException + * if the VM to be migrated is not in Running state + */ + VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinationHost, Map volumeToPool) + throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, + VirtualMachineMigrationException; + UserVm moveVMToUser(AssignVMCmd moveUserVMCmd) throws ResourceAllocationException, ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException; VirtualMachine vmStorageMigration(Long vmId, StoragePool destPool); diff --git a/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java b/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java index afd33da84b7..b6d4ff64b31 100644 --- a/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java +++ b/api/src/org/apache/cloudstack/affinity/AffinityGroupResponse.java @@ -64,7 +64,6 @@ public class AffinityGroupResponse extends BaseResponse implements ControlledVie private List vmIdList; public AffinityGroupResponse() { - this.vmIdList = new ArrayList(); } @Override @@ -149,6 +148,10 @@ public class AffinityGroupResponse extends BaseResponse implements ControlledVie } public void addVMId(String vmId) { + if (this.vmIdList == null) { + this.vmIdList = new ArrayList(); + } + this.vmIdList.add(vmId); } diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index 37cb59f3758..e774ecc94b6 100755 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -221,6 +221,7 @@ public class ApiConstants { public static final String VIRTUAL_MACHINE_ID = "virtualmachineid"; public static final String VIRTUAL_MACHINE_IDS = "virtualmachineids"; public static final String VLAN = "vlan"; + public static final String REMOVE_VLAN="removevlan"; public static final String VLAN_ID = "vlanid"; public static final String VM_AVAILABLE = "vmavailable"; public static final String VM_LIMIT = "vmlimit"; @@ -230,6 +231,7 @@ public class ApiConstants { public static final String VOLUME_ID = "volumeid"; public static final String ZONE_ID = "zoneid"; public static final String ZONE_NAME = "zonename"; + public static final String ZONE_TYPE = "zonetype"; public static final String NETWORK_TYPE = "networktype"; public static final String PAGE = "page"; public static final String PAGE_SIZE = "pagesize"; @@ -364,6 +366,8 @@ public class ApiConstants { public static final String HA_HOST = "hahost"; public static final String CUSTOM_DISK_OFF_MAX_SIZE = "customdiskofferingmaxsize"; public static final String DEFAULT_ZONE_ID = "defaultzoneid"; + public static final String LIVE_MIGRATE = "livemigrate"; + public static final String MIGRATE_TO = "migrateto"; public static final String GUID = "guid"; public static final String VSWITCH_TYPE_GUEST_TRAFFIC = "guestvswitchtype"; public static final String VSWITCH_TYPE_PUBLIC_TRAFFIC = "publicvswitchtype"; @@ -475,8 +479,8 @@ public class ApiConstants { public static final String HEALTHCHECK_PINGPATH = "pingpath"; public static final String AFFINITY_GROUP_IDS = "affinitygroupids"; public static final String AFFINITY_GROUP_NAMES = "affinitygroupnames"; - public static final String DEPLOYMENT_PLANNER = "deploymentplanner"; public static final String ASA_INSIDE_PORT_PROFILE = "insideportprofile"; + public static final String AFFINITY_GROUP_ID = "affinitygroupid"; public enum HostDetails { all, capacity, events, stats, min; diff --git a/api/src/org/apache/cloudstack/api/ResponseGenerator.java b/api/src/org/apache/cloudstack/api/ResponseGenerator.java index c0dd57e15bd..a3aa9de0e3e 100644 --- a/api/src/org/apache/cloudstack/api/ResponseGenerator.java +++ b/api/src/org/apache/cloudstack/api/ResponseGenerator.java @@ -189,6 +189,10 @@ public interface ResponseGenerator { HostResponse createHostResponse(Host host); + HostForMigrationResponse createHostForMigrationResponse(Host host); + + HostForMigrationResponse createHostForMigrationResponse(Host host, EnumSet details); + VlanIpRangeResponse createVlanIpRangeResponse(Vlan vlan); IPAddressResponse createIPAddressResponse(IpAddress ipAddress); @@ -216,6 +220,8 @@ public interface ResponseGenerator { StoragePoolResponse createStoragePoolResponse(StoragePool pool); + StoragePoolForMigrationResponse createStoragePoolForMigrationResponse(StoragePool pool); + ClusterResponse createClusterResponse(Cluster cluster, Boolean showCapacities); FirewallRuleResponse createPortForwardingRuleResponse(PortForwardingRule fwRule); diff --git a/api/src/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java b/api/src/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java index aabfd4a620d..9f34405ffbd 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/config/ListCfgsByCmd.java @@ -23,8 +23,7 @@ import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseListCmd; import org.apache.cloudstack.api.Parameter; -import org.apache.cloudstack.api.response.ConfigurationResponse; -import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.*; import org.apache.log4j.Logger; import com.cloud.configuration.Configuration; @@ -46,6 +45,13 @@ public class ListCfgsByCmd extends BaseListCmd { @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, description = "lists configuration by name") private String configName; + @Parameter(name=ApiConstants.SCOPE, type = CommandType.STRING, description = "scope(zone/cluster/pool/account) of the parameter that needs to be updated") + private String scope; + + @Parameter(name=ApiConstants.ID, type = CommandType.UUID, entityType = {ZoneResponse.class, ClusterResponse.class, StoragePoolResponse.class, AccountResponse.class}, description = "corresponding ID of the scope") + private Long id; + + // /////////////////////////////////////////////////// // ///////////////// Accessors /////////////////////// // /////////////////////////////////////////////////// @@ -58,6 +64,15 @@ public class ListCfgsByCmd extends BaseListCmd { return configName; } + public String getScope() { + return scope; + } + + public Long getId() { + return id; + } + + @Override public Long getPageSizeVal() { Long pageSizeVal = 500L; @@ -85,6 +100,11 @@ public class ListCfgsByCmd extends BaseListCmd { for (Configuration cfg : result.first()) { ConfigurationResponse cfgResponse = _responseGenerator.createConfigurationResponse(cfg); cfgResponse.setObjectName("configuration"); + if (scope != null) { + cfgResponse.setScope(scope); + } else { + cfgResponse.setScope("global"); + } configResponses.add(cfgResponse); } diff --git a/api/src/org/apache/cloudstack/api/command/admin/config/ListDeploymentPlannersCmd.java b/api/src/org/apache/cloudstack/api/command/admin/config/ListDeploymentPlannersCmd.java deleted file mode 100644 index 69004de2a6b..00000000000 --- a/api/src/org/apache/cloudstack/api/command/admin/config/ListDeploymentPlannersCmd.java +++ /dev/null @@ -1,71 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -package org.apache.cloudstack.api.command.admin.config; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.cloudstack.api.APICommand; -import org.apache.cloudstack.api.BaseListCmd; -import org.apache.cloudstack.api.response.DeploymentPlannersResponse; -import org.apache.cloudstack.api.response.ListResponse; -import org.apache.log4j.Logger; - -@APICommand(name = "listDeploymentPlanners", description = "Lists all DeploymentPlanners available.", responseObject = DeploymentPlannersResponse.class) -public class ListDeploymentPlannersCmd extends BaseListCmd { - public static final Logger s_logger = Logger.getLogger(ListDeploymentPlannersCmd.class.getName()); - - private static final String s_name = "listdeploymentplannersresponse"; - - ///////////////////////////////////////////////////// - //////////////// API parameters ///////////////////// - ///////////////////////////////////////////////////// - - - ///////////////////////////////////////////////////// - /////////////////// Accessors /////////////////////// - ///////////////////////////////////////////////////// - - - ///////////////////////////////////////////////////// - /////////////// API Implementation/////////////////// - ///////////////////////////////////////////////////// - - @Override - public String getCommandName() { - return s_name; - } - - @Override - public void execute(){ - List planners = _mgr.listDeploymentPlanners(); - ListResponse response = new ListResponse(); - List plannerResponses = new ArrayList(); - - for (String planner : planners) { - DeploymentPlannersResponse plannerResponse = new DeploymentPlannersResponse(); - plannerResponse.setName(planner); - plannerResponse.setObjectName("deploymentPlanner"); - plannerResponses.add(plannerResponse); - } - - response.setResponses(plannerResponses); - response.setResponseName(getCommandName()); - this.setResponseObject(response); - - } -} diff --git a/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java b/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java index ffeb58621b9..074c5a3b028 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/config/UpdateCfgCmd.java @@ -22,7 +22,7 @@ import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.BaseCmd; import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.ServerApiException; -import org.apache.cloudstack.api.response.ConfigurationResponse; +import org.apache.cloudstack.api.response.*; import org.apache.log4j.Logger; import com.cloud.configuration.Configuration; @@ -43,6 +43,12 @@ public class UpdateCfgCmd extends BaseCmd { @Parameter(name=ApiConstants.VALUE, type=CommandType.STRING, description="the value of the configuration", length=4095) private String value; + @Parameter(name=ApiConstants.SCOPE, type = CommandType.STRING, description = "scope(zone/cluster/pool/account) of the parameter that needs to be updated") + private String scope; + + @Parameter(name=ApiConstants.ID, type = CommandType.UUID, entityType = {ZoneResponse.class, ClusterResponse.class, StoragePoolResponse.class, AccountResponse.class}, description = "corresponding ID of the scope") + private Long id; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -55,6 +61,14 @@ public class UpdateCfgCmd extends BaseCmd { return value; } + public String getScope() { + return scope; + } + + public Long getId() { + return id; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -75,6 +89,12 @@ public class UpdateCfgCmd extends BaseCmd { if (cfg != null) { ConfigurationResponse response = _responseGenerator.createConfigurationResponse(cfg); response.setResponseName(getCommandName()); + if (scope != null) { + response.setScope(scope); + response.setValue(value); + } else { + response.setScope("global"); + } this.setResponseObject(response); } else { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update config"); diff --git a/api/src/org/apache/cloudstack/api/command/admin/host/FindHostsForMigrationCmd.java b/api/src/org/apache/cloudstack/api/command/admin/host/FindHostsForMigrationCmd.java new file mode 100644 index 00000000000..e6e45cc7246 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/host/FindHostsForMigrationCmd.java @@ -0,0 +1,107 @@ +// 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.api.command.admin.host; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.apache.cloudstack.api.APICommand; +import org.apache.log4j.Logger; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.HostForMigrationResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import com.cloud.host.Host; +import com.cloud.utils.Pair; +import com.cloud.utils.Ternary; + +@APICommand(name = "findHostsForMigration", description="Find hosts suitable for migrating a virtual machine.", + responseObject=HostForMigrationResponse.class) +public class FindHostsForMigrationCmd extends BaseListCmd { + public static final Logger s_logger = Logger.getLogger(FindHostsForMigrationCmd.class.getName()); + + private static final String s_name = "findhostsformigrationresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType = UserVmResponse.class, + required=false, description="find hosts to which this VM can be migrated and flag the hosts with enough " + + "CPU/RAM to host the VM") + private Long virtualMachineId; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getVirtualMachineId() { + return virtualMachineId; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public void execute() { + ListResponse response = null; + Pair,Integer> result; + List hostsWithCapacity = new ArrayList(); + Map hostsRequiringStorageMotion; + + Ternary,Integer>, List, Map> hostsForMigration = + _mgr.listHostsForMigrationOfVM(getVirtualMachineId(), this.getStartIndex(), this.getPageSizeVal()); + result = hostsForMigration.first(); + hostsWithCapacity = hostsForMigration.second(); + hostsRequiringStorageMotion = hostsForMigration.third(); + + response = new ListResponse(); + List hostResponses = new ArrayList(); + for (Host host : result.first()) { + HostForMigrationResponse hostResponse = _responseGenerator.createHostForMigrationResponse(host); + Boolean suitableForMigration = false; + if (hostsWithCapacity.contains(host)) { + suitableForMigration = true; + } + hostResponse.setSuitableForMigration(suitableForMigration); + + Boolean requiresStorageMotion = hostsRequiringStorageMotion.get(host); + if (requiresStorageMotion != null && requiresStorageMotion) { + hostResponse.setRequiresStorageMotion(true); + } else { + hostResponse.setRequiresStorageMotion(false); + } + + hostResponse.setObjectName("host"); + hostResponses.add(hostResponse); + } + + response.setResponses(hostResponses, result.second()); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java b/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java index 29844c31113..5ec7cf3e10b 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java @@ -19,6 +19,7 @@ package org.apache.cloudstack.api.command.admin.host; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; +import java.util.Map; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -37,6 +38,7 @@ import com.cloud.async.AsyncJob; import com.cloud.exception.InvalidParameterValueException; import com.cloud.host.Host; import com.cloud.utils.Pair; +import com.cloud.utils.Ternary; @APICommand(name = "listHosts", description="Lists hosts.", responseObject=HostResponse.class) public class ListHostsCmd extends BaseListCmd { @@ -170,8 +172,8 @@ public class ListHostsCmd extends BaseListCmd { } else { Pair,Integer> result; List hostsWithCapacity = new ArrayList(); - - Pair,Integer>, List> hostsForMigration = _mgr.listHostsForMigrationOfVM(getVirtualMachineId(), this.getStartIndex(), this.getPageSizeVal()); + Ternary,Integer>, List, Map> hostsForMigration = + _mgr.listHostsForMigrationOfVM(getVirtualMachineId(), this.getStartIndex(), this.getPageSizeVal()); result = hostsForMigration.first(); hostsWithCapacity = hostsForMigration.second(); @@ -192,6 +194,5 @@ public class ListHostsCmd extends BaseListCmd { } response.setResponseName(getCommandName()); this.setResponseObject(response); - } } diff --git a/api/src/org/apache/cloudstack/api/command/admin/network/UpdatePhysicalNetworkCmd.java b/api/src/org/apache/cloudstack/api/command/admin/network/UpdatePhysicalNetworkCmd.java index 06cf38dba3f..6d37dd8a49b 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/network/UpdatePhysicalNetworkCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/network/UpdatePhysicalNetworkCmd.java @@ -54,6 +54,8 @@ public class UpdatePhysicalNetworkCmd extends BaseAsyncCmd { @Parameter(name=ApiConstants.VLAN, type=CommandType.STRING, description="the VLAN for the physical network") private String vlan; + @Parameter(name=ApiConstants.REMOVE_VLAN, type = CommandType.STRING, description ="The vlan range we want to remove") + private String removevlan; ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// @@ -79,6 +81,10 @@ public class UpdatePhysicalNetworkCmd extends BaseAsyncCmd { return vlan; } + public String getRemoveVlan(){ + return removevlan; + } + ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// @@ -95,7 +101,7 @@ public class UpdatePhysicalNetworkCmd extends BaseAsyncCmd { @Override public void execute(){ - PhysicalNetwork result = _networkService.updatePhysicalNetwork(getId(),getNetworkSpeed(), getTags(), getVlan(), getState()); + PhysicalNetwork result = _networkService.updatePhysicalNetwork(getId(),getNetworkSpeed(), getTags(), getVlan(), getState(), getRemoveVlan()); PhysicalNetworkResponse response = _responseGenerator.createPhysicalNetworkResponse(result); response.setResponseName(getCommandName()); this.setResponseObject(response); diff --git a/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java b/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java index 74392cd4299..0e35276d914 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/offering/CreateServiceOfferingCmd.java @@ -84,9 +84,6 @@ public class CreateServiceOfferingCmd extends BaseCmd { @Parameter(name=ApiConstants.NETWORKRATE, type=CommandType.INTEGER, description="data transfer rate in megabits per second allowed. Supported only for non-System offering and system offerings having \"domainrouter\" systemvmtype") private Integer networkRate; - @Parameter(name = ApiConstants.DEPLOYMENT_PLANNER, type = CommandType.STRING, description = "The deployment planner heuristics used to deploy a VM of this offering, default \"FirstFitPlanner\".") - private String deploymentPlanner; - ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -151,9 +148,6 @@ public class CreateServiceOfferingCmd extends BaseCmd { return networkRate; } - public String getDeploymentPlanner() { - return deploymentPlanner; - } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// diff --git a/api/src/org/apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCmd.java b/api/src/org/apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCmd.java new file mode 100644 index 00000000000..37d007c0376 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/storage/FindStoragePoolsForMigrationCmd.java @@ -0,0 +1,98 @@ +// 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.api.command.admin.storage; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.cloudstack.api.APICommand; +import org.apache.log4j.Logger; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.ListResponse; +import org.apache.cloudstack.api.response.StoragePoolForMigrationResponse; +import org.apache.cloudstack.api.response.VolumeResponse; +import com.cloud.async.AsyncJob; +import com.cloud.storage.StoragePool; +import com.cloud.utils.Pair; + +@APICommand(name = "findStoragePoolsForMigration", description="Lists storage pools available for migration of a volume.", + responseObject=StoragePoolForMigrationResponse.class) +public class FindStoragePoolsForMigrationCmd extends BaseListCmd { + public static final Logger s_logger = Logger.getLogger(FindStoragePoolsForMigrationCmd.class.getName()); + + private static final String s_name = "findstoragepoolsformigrationresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType = VolumeResponse.class, required=true, + description="the ID of the volume") + private Long id; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getId() { + return id; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + public AsyncJob.Type getInstanceType() { + return AsyncJob.Type.StoragePool; + } + + @Override + public void execute() { + Pair, List> pools = + _mgr.listStoragePoolsForMigrationOfVolume(getId()); + ListResponse response = new ListResponse(); + List poolResponses = new ArrayList(); + + List allPools = pools.first(); + List suitablePoolList = pools.second(); + for (StoragePool pool : allPools) { + StoragePoolForMigrationResponse poolResponse = _responseGenerator.createStoragePoolForMigrationResponse(pool); + Boolean suitableForMigration = false; + for (StoragePool suitablePool : suitablePoolList) { + if (suitablePool.getId() == pool.getId()) { + suitableForMigration = true; + break; + } + } + poolResponse.setSuitableForMigration(suitableForMigration); + poolResponse.setObjectName("storagepool"); + poolResponses.add(poolResponse); + } + + response.setResponses(poolResponses); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java new file mode 100644 index 00000000000..b1eaf11a251 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/vm/MigrateVirtualMachineWithVolumeCmd.java @@ -0,0 +1,160 @@ +// 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.api.command.admin.vm; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.apache.cloudstack.api.*; +import org.apache.log4j.Logger; + +import org.apache.cloudstack.api.APICommand; + +import org.apache.cloudstack.api.BaseCmd.CommandType; +import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.UserVmResponse; +import com.cloud.event.EventTypes; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.ManagementServerException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.VirtualMachineMigrationException; +import com.cloud.host.Host; +import com.cloud.storage.StoragePool; +import com.cloud.user.Account; +import com.cloud.user.UserContext; +import com.cloud.uservm.UserVm; +import com.cloud.vm.VirtualMachine; + +@APICommand(name = "migrateVirtualMachineWithVolume", description="Attempts Migration of a VM with its volumes to a different host", responseObject=UserVmResponse.class) +public class MigrateVirtualMachineWithVolumeCmd extends BaseAsyncCmd { + public static final Logger s_logger = Logger.getLogger(MigrateVMCmd.class.getName()); + + private static final String s_name = "migratevirtualmachinewithvolumeresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name=ApiConstants.HOST_ID, type=CommandType.UUID, entityType=HostResponse.class, + required=true, description="Destination Host ID to migrate VM to.") + private Long hostId; + + @Parameter(name=ApiConstants.VIRTUAL_MACHINE_ID, type=CommandType.UUID, entityType=UserVmResponse.class, + required=true, description="the ID of the virtual machine") + private Long virtualMachineId; + + @Parameter(name = ApiConstants.MIGRATE_TO, type = CommandType.MAP, required=false, + description = "Map of pool to which each volume should be migrated (volume/pool pair)") + private Map migrateVolumeTo; + + ///////////////////////////////////////////////////// + /////////////////// Accessors /////////////////////// + ///////////////////////////////////////////////////// + + public Long getHostId() { + return hostId; + } + + public Long getVirtualMachineId() { + return virtualMachineId; + } + + public Map getVolumeToPool() { + Map volumeToPoolMap = new HashMap(); + if (migrateVolumeTo != null && !migrateVolumeTo.isEmpty()) { + Collection allValues = migrateVolumeTo.values(); + Iterator iter = allValues.iterator(); + while (iter.hasNext()) { + HashMap volumeToPool = (HashMap) iter.next(); + String volume = volumeToPool.get("volume"); + String pool = volumeToPool.get("pool"); + volumeToPoolMap.put(volume, pool); + } + } + return volumeToPoolMap; + } + + ///////////////////////////////////////////////////// + /////////////// API Implementation/////////////////// + ///////////////////////////////////////////////////// + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + UserVm userVm = _entityMgr.findById(UserVm.class, getVirtualMachineId()); + if (userVm != null) { + return userVm.getAccountId(); + } + + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public String getEventType() { + return EventTypes.EVENT_VM_MIGRATE; + } + + @Override + public String getEventDescription() { + return "Attempting to migrate VM Id: " + getVirtualMachineId() + " to host Id: "+ getHostId(); + } + + @Override + public void execute(){ + UserVm userVm = _userVmService.getUserVm(getVirtualMachineId()); + if (userVm == null) { + throw new InvalidParameterValueException("Unable to find the VM by id=" + getVirtualMachineId()); + } + + Host destinationHost = _resourceService.getHost(getHostId()); + if (destinationHost == null) { + throw new InvalidParameterValueException("Unable to find the host to migrate the VM, host id =" + getHostId()); + } + + try{ + VirtualMachine migratedVm = _userVmService.migrateVirtualMachineWithVolume(getVirtualMachineId(), + destinationHost, getVolumeToPool()); + if (migratedVm != null) { + UserVmResponse response = _responseGenerator.createUserVmResponse("virtualmachine", (UserVm)migratedVm).get(0); + response.setResponseName(getCommandName()); + this.setResponseObject(response); + } else { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to migrate vm"); + } + } catch (ResourceUnavailableException ex) { + s_logger.warn("Exception: ", ex); + throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage()); + } catch (ConcurrentOperationException e) { + s_logger.warn("Exception: ", e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); + } catch (ManagementServerException e) { + s_logger.warn("Exception: ", e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); + } catch (VirtualMachineMigrationException e) { + s_logger.warn("Exception: ", e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, e.getMessage()); + } + } +} diff --git a/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java b/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java index 63e2788b77c..a01bac39a4b 100644 --- a/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/tag/CreateTagsCmd.java @@ -35,7 +35,7 @@ import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.server.ResourceTag; import com.cloud.server.ResourceTag.TaggedResourceType; -@APICommand(name = "createTags", description = "Creates resource tag(s)", responseObject = SuccessResponse.class, since = "Burbank") +@APICommand(name = "createTags", description = "Creates resource tag(s)", responseObject = SuccessResponse.class, since = "4.0.0") public class CreateTagsCmd extends BaseAsyncCmd{ public static final Logger s_logger = Logger.getLogger(CreateTagsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java b/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java index 084a5142aa1..a6ba0da82b7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/tag/DeleteTagsCmd.java @@ -34,7 +34,7 @@ import org.apache.log4j.Logger; import com.cloud.event.EventTypes; import com.cloud.server.ResourceTag.TaggedResourceType; -@APICommand(name = "deleteTags", description = "Deleting resource tag(s)", responseObject = SuccessResponse.class, since = "Burbank") +@APICommand(name = "deleteTags", description = "Deleting resource tag(s)", responseObject = SuccessResponse.class, since = "4.0.0") public class DeleteTagsCmd extends BaseAsyncCmd{ public static final Logger s_logger = Logger.getLogger(DeleteTagsCmd.class.getName()); diff --git a/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java b/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java index e3dc108a757..f80da204cce 100644 --- a/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/tag/ListTagsCmd.java @@ -24,7 +24,7 @@ import org.apache.cloudstack.api.Parameter; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.ResourceTagResponse; -@APICommand(name = "listTags", description = "List resource tag(s)", responseObject = ResourceTagResponse.class, since = "Burbank") +@APICommand(name = "listTags", description = "List resource tag(s)", responseObject = ResourceTagResponse.class, since = "4.0.0") public class ListTagsCmd extends BaseListProjectAndAccountResourcesCmd{ private static final String s_name = "listtagsresponse"; diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java index 77ba9fed59e..70c0159dffe 100755 --- a/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/DeployVMCmd.java @@ -230,7 +230,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd { for (String groupName : securityGroupNameList) { Long groupId = _responseGenerator.getSecurityGroupId(groupName, getEntityOwnerId()); if (groupId == null) { - throw new InvalidParameterValueException("Unable to find group by name " + groupName + " for account " + getEntityOwnerId()); + throw new InvalidParameterValueException("Unable to find group by name " + groupName); } else { securityGroupIds.add(groupId); } @@ -344,8 +344,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd { for (String groupName : affinityGroupNameList) { Long groupId = _responseGenerator.getAffinityGroupId(groupName, getEntityOwnerId()); if (groupId == null) { - throw new InvalidParameterValueException("Unable to find group by name " + groupName - + " for account " + getEntityOwnerId()); + throw new InvalidParameterValueException("Unable to find affinity group by name " + groupName); } else { affinityGroupIds.add(groupId); } diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java index 30f03b88995..dae9df311cd 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.EnumSet; import java.util.List; +import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiConstants.VMDetails; @@ -95,7 +96,7 @@ public class ListVMsCmd extends BaseListTaggedResourcesCmd { @Parameter(name=ApiConstants.DETAILS, type=CommandType.LIST, collectionType=CommandType.STRING, description="comma separated list of host details requested, " + - "value can be a list of [all, group, nics, stats, secgrp, tmpl, servoff, iso, volume, min]." + + "value can be a list of [all, group, nics, stats, secgrp, tmpl, servoff, iso, volume, min, affgrp]." + " If no parameter is passed in, the details will be defaulted to all" ) private List viewDetails; @@ -110,6 +111,10 @@ public class ListVMsCmd extends BaseListTaggedResourcesCmd { @Parameter(name=ApiConstants.VPC_ID, type=CommandType.UUID, entityType=VpcResponse.class, description="list vms by vpc") private Long vpcId; + + @Parameter(name = ApiConstants.AFFINITY_GROUP_ID, type = CommandType.UUID, entityType = AffinityGroupResponse.class, description = "list vms by affinity group") + private Long affinityGroupId; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -174,6 +179,10 @@ public class ListVMsCmd extends BaseListTaggedResourcesCmd { return vpcId; } + public Long getAffinityGroupId() { + return affinityGroupId; + } + public EnumSet getDetails() throws InvalidParameterValueException { EnumSet dv; if (viewDetails==null || viewDetails.size() <=0){ diff --git a/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java b/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java index 287241a8d90..ce40f0d2979 100644 --- a/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/volume/MigrateVolumeCmd.java @@ -47,6 +47,10 @@ public class MigrateVolumeCmd extends BaseAsyncCmd { required=true, description="destination storage pool ID to migrate the volume to") private Long storageId; + @Parameter(name=ApiConstants.LIVE_MIGRATE, type=CommandType.BOOLEAN, required=false, + description="if the volume should be live migrated when it is attached to a running vm") + private Boolean liveMigrate; + ///////////////////////////////////////////////////// /////////////////// Accessors /////////////////////// ///////////////////////////////////////////////////// @@ -58,6 +62,10 @@ public class MigrateVolumeCmd extends BaseAsyncCmd { public Long getStoragePoolId() { return storageId; } + + public boolean isLiveMigrate() { + return (liveMigrate != null) ? liveMigrate : false; + } ///////////////////////////////////////////////////// /////////////// API Implementation/////////////////// ///////////////////////////////////////////////////// diff --git a/api/src/org/apache/cloudstack/api/response/AccountResponse.java b/api/src/org/apache/cloudstack/api/response/AccountResponse.java index c109a6325c8..1e59822180f 100644 --- a/api/src/org/apache/cloudstack/api/response/AccountResponse.java +++ b/api/src/org/apache/cloudstack/api/response/AccountResponse.java @@ -183,6 +183,9 @@ public class AccountResponse extends BaseResponse { @SerializedName(ApiConstants.ACCOUNT_DETAILS) @Param(description="details for the account") private Map details; + + @SerializedName(ApiConstants.IS_DEFAULT) @Param(description="true if account is default, false otherwise", since="4.2.0") + private Boolean isDefault; @Override @@ -381,4 +384,8 @@ public class AccountResponse extends BaseResponse { public void setDefaultZone(String defaultZoneId) { this.defaultZoneId = defaultZoneId; } + + public void setIsDefault(Boolean isDefault) { + this.isDefault = isDefault; + } } diff --git a/api/src/org/apache/cloudstack/api/response/ConfigurationResponse.java b/api/src/org/apache/cloudstack/api/response/ConfigurationResponse.java index 95b8af2f4c5..176c47aff8b 100644 --- a/api/src/org/apache/cloudstack/api/response/ConfigurationResponse.java +++ b/api/src/org/apache/cloudstack/api/response/ConfigurationResponse.java @@ -32,9 +32,13 @@ public class ConfigurationResponse extends BaseResponse { @SerializedName(ApiConstants.VALUE) @Param(description="the value of the configuration") private String value; + @SerializedName(ApiConstants.SCOPE) @Param(description="scope(zone/cluster/pool/account) of the parameter that needs to be updated") + private String scope; + @SerializedName(ApiConstants.DESCRIPTION) @Param(description="the description of the configuration") private String description; + public String getCategory() { return category; } @@ -66,4 +70,12 @@ public class ConfigurationResponse extends BaseResponse { public void setDescription(String description) { this.description = description; } + + public String getScope() { + return scope; + } + + public void setScope(String scope) { + this.scope = scope; + } } diff --git a/api/src/org/apache/cloudstack/api/response/HostForMigrationResponse.java b/api/src/org/apache/cloudstack/api/response/HostForMigrationResponse.java new file mode 100644 index 00000000000..fde2440a8e2 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/HostForMigrationResponse.java @@ -0,0 +1,365 @@ +// 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.api.response; + +import java.util.Date; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import com.cloud.host.Host; +import com.cloud.host.Status; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.serializer.Param; +import com.google.gson.annotations.SerializedName; + +@EntityReference(value=Host.class) +public class HostForMigrationResponse extends BaseResponse { + @SerializedName(ApiConstants.ID) @Param(description="the ID of the host") + private String id; + + @SerializedName(ApiConstants.NAME) @Param(description="the name of the host") + private String name; + + @SerializedName(ApiConstants.STATE) @Param(description="the state of the host") + private Status state; + + @SerializedName("disconnected") @Param(description="true if the host is disconnected. False otherwise.") + private Date disconnectedOn; + + @SerializedName(ApiConstants.TYPE) @Param(description="the host type") + private Host.Type hostType; + + @SerializedName("oscategoryid") @Param(description="the OS category ID of the host") + private String osCategoryId; + + @SerializedName("oscategoryname") @Param(description="the OS category name of the host") + private String osCategoryName; + + @SerializedName(ApiConstants.IP_ADDRESS) @Param(description="the IP address of the host") + private String ipAddress; + + @SerializedName(ApiConstants.ZONE_ID) @Param(description="the Zone ID of the host") + private String zoneId; + + @SerializedName(ApiConstants.ZONE_NAME) @Param(description="the Zone name of the host") + private String zoneName; + + @SerializedName(ApiConstants.POD_ID) @Param(description="the Pod ID of the host") + private String podId; + + @SerializedName("podname") @Param(description="the Pod name of the host") + private String podName; + + @SerializedName("version") @Param(description="the host version") + private String version; + + @SerializedName(ApiConstants.HYPERVISOR) @Param(description="the host hypervisor") + private HypervisorType hypervisor; + + @SerializedName("cpunumber") @Param(description="the CPU number of the host") + private Integer cpuNumber; + + @SerializedName("cpuspeed") @Param(description="the CPU speed of the host") + private Long cpuSpeed; + + @SerializedName("cpuallocated") @Param(description="the amount of the host's CPU currently allocated") + private String cpuAllocated; + + @SerializedName("cpuused") @Param(description="the amount of the host's CPU currently used") + private String cpuUsed; + + @SerializedName("cpuwithoverprovisioning") @Param(description="the amount of the host's CPU after applying the cpu.overprovisioning.factor ") + private String cpuWithOverprovisioning; + + @SerializedName("averageload") @Param(description="the cpu average load on the host") + private Long averageLoad; + + @SerializedName("networkkbsread") @Param(description="the incoming network traffic on the host") + private Long networkKbsRead; + + @SerializedName("networkkbswrite") @Param(description="the outgoing network traffic on the host") + private Long networkKbsWrite; + + @SerializedName("memorytotal") @Param(description="the memory total of the host") + private Long memoryTotal; + + @SerializedName("memoryallocated") @Param(description="the amount of the host's memory currently allocated") + private Long memoryAllocated; + + @SerializedName("memoryused") @Param(description="the amount of the host's memory currently used") + private Long memoryUsed; + + @SerializedName("disksizetotal") @Param(description="the total disk size of the host") + private Long diskSizeTotal; + + @SerializedName("disksizeallocated") @Param(description="the host's currently allocated disk size") + private Long diskSizeAllocated; + + @SerializedName("capabilities") @Param(description="capabilities of the host") + private String capabilities; + + @SerializedName("lastpinged") @Param(description="the date and time the host was last pinged") + private Date lastPinged; + + @SerializedName("managementserverid") @Param(description="the management server ID of the host") + private Long managementServerId; + + @SerializedName("clusterid") @Param(description="the cluster ID of the host") + private String clusterId; + + @SerializedName("clustername") @Param(description="the cluster name of the host") + private String clusterName; + + @SerializedName("clustertype") @Param(description="the cluster type of the cluster that host belongs to") + private String clusterType; + + @SerializedName("islocalstorageactive") @Param(description="true if local storage is active, false otherwise") + private Boolean localStorageActive; + + @SerializedName(ApiConstants.CREATED) @Param(description="the date and time the host was created") + private Date created; + + @SerializedName("removed") @Param(description="the date and time the host was removed") + private Date removed; + + @SerializedName("events") @Param(description="events available for the host") + private String events; + + @SerializedName("hosttags") @Param(description="comma-separated list of tags for the host") + private String hostTags; + + @SerializedName("hasenoughcapacity") @Param(description="true if this host has enough CPU and RAM capacity to migrate a VM to it, false otherwise") + private Boolean hasEnoughCapacity; + + @SerializedName("suitableformigration") @Param(description="true if this host is suitable(has enough capacity and satisfies all conditions like hosttags, max guests vm limit etc) to migrate a VM to it , false otherwise") + private Boolean suitableForMigration; + + @SerializedName("requiresStorageMotion") @Param(description="true if migrating a vm to this host requires storage motion, false otherwise") + private Boolean requiresStorageMotion; + + @SerializedName("resourcestate") @Param(description="the resource state of the host") + private String resourceState; + + @SerializedName(ApiConstants.HYPERVISOR_VERSION) @Param(description="the hypervisor version") + private String hypervisorVersion; + + @SerializedName(ApiConstants.HA_HOST) @Param(description="true if the host is Ha host (dedicated to vms started by HA process; false otherwise") + private Boolean haHost; + + @Override + public String getObjectId() { + return this.getId(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public void setState(Status state) { + this.state = state; + } + + public void setDisconnectedOn(Date disconnectedOn) { + this.disconnectedOn = disconnectedOn; + } + + public void setHostType(Host.Type hostType) { + this.hostType = hostType; + } + + public void setOsCategoryId(String osCategoryId) { + this.osCategoryId = osCategoryId; + } + + public void setOsCategoryName(String osCategoryName) { + this.osCategoryName = osCategoryName; + } + + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + + public void setZoneId(String zoneId) { + this.zoneId = zoneId; + } + + public void setZoneName(String zoneName) { + this.zoneName = zoneName; + } + + public void setPodId(String podId) { + this.podId = podId; + } + + public void setPodName(String podName) { + this.podName = podName; + } + + public void setVersion(String version) { + this.version = version; + } + + public void setHypervisor(HypervisorType hypervisor) { + this.hypervisor = hypervisor; + } + + public void setCpuNumber(Integer cpuNumber) { + this.cpuNumber = cpuNumber; + } + + public void setCpuSpeed(Long cpuSpeed) { + this.cpuSpeed = cpuSpeed; + } + + public String getCpuAllocated() { + return cpuAllocated; + } + + public void setCpuAllocated(String cpuAllocated) { + this.cpuAllocated = cpuAllocated; + } + + public void setCpuUsed(String cpuUsed) { + this.cpuUsed = cpuUsed; + } + + public void setAverageLoad(Long averageLoad) { + this.averageLoad = averageLoad; + } + + public void setNetworkKbsRead(Long networkKbsRead) { + this.networkKbsRead = networkKbsRead; + } + + public void setNetworkKbsWrite(Long networkKbsWrite) { + this.networkKbsWrite = networkKbsWrite; + } + + public void setMemoryTotal(Long memoryTotal) { + this.memoryTotal = memoryTotal; + } + + public void setMemoryAllocated(Long memoryAllocated) { + this.memoryAllocated = memoryAllocated; + } + + public void setMemoryUsed(Long memoryUsed) { + this.memoryUsed = memoryUsed; + } + + public void setDiskSizeTotal(Long diskSizeTotal) { + this.diskSizeTotal = diskSizeTotal; + } + + public void setDiskSizeAllocated(Long diskSizeAllocated) { + this.diskSizeAllocated = diskSizeAllocated; + } + + public void setCapabilities(String capabilities) { + this.capabilities = capabilities; + } + + public void setLastPinged(Date lastPinged) { + this.lastPinged = lastPinged; + } + + public void setManagementServerId(Long managementServerId) { + this.managementServerId = managementServerId; + } + + public void setClusterId(String clusterId) { + this.clusterId = clusterId; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public void setClusterType(String clusterType) { + this.clusterType = clusterType; + } + + public void setLocalStorageActive(Boolean localStorageActive) { + this.localStorageActive = localStorageActive; + } + + public void setCreated(Date created) { + this.created = created; + } + + public void setRemoved(Date removed) { + this.removed = removed; + } + + public void setEvents(String events) { + this.events = events; + } + + public String getHostTags() { + return hostTags; + } + + public void setHostTags(String hostTags) { + this.hostTags = hostTags; + } + + public void setHasEnoughCapacity(Boolean hasEnoughCapacity) { + this.hasEnoughCapacity = hasEnoughCapacity; + } + + public void setSuitableForMigration(Boolean suitableForMigration) { + this.suitableForMigration = suitableForMigration; + } + + public void setRequiresStorageMotion(Boolean requiresStorageMotion) { + this.requiresStorageMotion = requiresStorageMotion; + } + + public String getResourceState() { + return resourceState; + } + + public void setResourceState(String resourceState) { + this.resourceState = resourceState; + } + + public String getCpuWithOverprovisioning() { + return cpuWithOverprovisioning; + } + + public void setCpuWithOverprovisioning(String cpuWithOverprovisioning) { + this.cpuWithOverprovisioning = cpuWithOverprovisioning; + } + + public void setHypervisorVersion(String hypervisorVersion) { + this.hypervisorVersion = hypervisorVersion; + } + + public void setHaHost(Boolean haHost) { + this.haHost = haHost; + } +} diff --git a/api/src/org/apache/cloudstack/api/response/HostResponse.java b/api/src/org/apache/cloudstack/api/response/HostResponse.java index f5aa8f90a17..687687d37fc 100644 --- a/api/src/org/apache/cloudstack/api/response/HostResponse.java +++ b/api/src/org/apache/cloudstack/api/response/HostResponse.java @@ -330,7 +330,6 @@ public class HostResponse extends BaseResponse { this.hasEnoughCapacity = hasEnoughCapacity; } - public void setSuitableForMigration(Boolean suitableForMigration) { this.suitableForMigration = suitableForMigration; } diff --git a/api/src/org/apache/cloudstack/api/response/StoragePoolForMigrationResponse.java b/api/src/org/apache/cloudstack/api/response/StoragePoolForMigrationResponse.java new file mode 100644 index 00000000000..f0bbcb19136 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/StoragePoolForMigrationResponse.java @@ -0,0 +1,248 @@ +// 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.api.response; + +import java.util.Date; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.BaseResponse; +import org.apache.cloudstack.api.EntityReference; + +import com.cloud.serializer.Param; +import com.cloud.storage.StoragePool; +import com.cloud.storage.StoragePoolStatus; +import com.google.gson.annotations.SerializedName; + +@EntityReference(value=StoragePool.class) +public class StoragePoolForMigrationResponse extends BaseResponse { + @SerializedName("id") @Param(description="the ID of the storage pool") + private String id; + + @SerializedName("zoneid") @Param(description="the Zone ID of the storage pool") + private String zoneId; + + @SerializedName(ApiConstants.ZONE_NAME) @Param(description="the Zone name of the storage pool") + private String zoneName; + + @SerializedName("podid") @Param(description="the Pod ID of the storage pool") + private String podId; + + @SerializedName("podname") @Param(description="the Pod name of the storage pool") + private String podName; + + @SerializedName("name") @Param(description="the name of the storage pool") + private String name; + + @SerializedName("ipaddress") @Param(description="the IP address of the storage pool") + private String ipAddress; + + @SerializedName("path") @Param(description="the storage pool path") + private String path; + + @SerializedName("created") @Param(description="the date and time the storage pool was created") + private Date created; + + @SerializedName("type") @Param(description="the storage pool type") + private String type; + + @SerializedName("clusterid") @Param(description="the ID of the cluster for the storage pool") + private String clusterId; + + @SerializedName("clustername") @Param(description="the name of the cluster for the storage pool") + private String clusterName; + + @SerializedName("disksizetotal") @Param(description="the total disk size of the storage pool") + private Long diskSizeTotal; + + @SerializedName("disksizeallocated") @Param(description="the host's currently allocated disk size") + private Long diskSizeAllocated; + + @SerializedName("disksizeused") @Param(description="the host's currently used disk size") + private Long diskSizeUsed; + + @SerializedName("tags") @Param(description="the tags for the storage pool") + private String tags; + + @SerializedName(ApiConstants.STATE) @Param(description="the state of the storage pool") + private StoragePoolStatus state; + + @SerializedName(ApiConstants.SCOPE) @Param(description="the scope of the storage pool") + private String scope; + + @SerializedName("suitableformigration") @Param(description="true if this pool is suitable to migrate a volume," + + " false otherwise") + private Boolean suitableForMigration; + + /** + * @return the scope + */ + public String getScope() { + return scope; + } + + /** + * @param scope the scope to set + */ + public void setScope(String scope) { + this.scope = scope; + } + + @Override + public String getObjectId() { + return this.getId(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getZoneId() { + return zoneId; + } + + public void setZoneId(String zoneId) { + this.zoneId = zoneId; + } + + public String getZoneName() { + return zoneName; + } + + public void setZoneName(String zoneName) { + this.zoneName = zoneName; + } + + public String getPodId() { + return podId; + } + + public void setPodId(String podId) { + this.podId = podId; + } + + public String getPodName() { + return podName; + } + + public void setPodName(String podName) { + this.podName = podName; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getIpAddress() { + return ipAddress; + } + + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + + public Date getCreated() { + return created; + } + + public void setCreated(Date created) { + this.created = created; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getClusterId() { + return clusterId; + } + + public void setClusterId(String clusterId) { + this.clusterId = clusterId; + } + + public String getClusterName() { + return clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public Long getDiskSizeTotal() { + return diskSizeTotal; + } + + public void setDiskSizeTotal(Long diskSizeTotal) { + this.diskSizeTotal = diskSizeTotal; + } + + public Long getDiskSizeAllocated() { + return diskSizeAllocated; + } + + public void setDiskSizeAllocated(Long diskSizeAllocated) { + this.diskSizeAllocated = diskSizeAllocated; + } + + public Long getDiskSizeUsed() { + return diskSizeUsed; + } + + public void setDiskSizeUsed(Long diskSizeUsed) { + this.diskSizeUsed = diskSizeUsed; + } + + public String getTags() { + return tags; + } + + public void setTags(String tags) { + this.tags = tags; + } + + public StoragePoolStatus getState() { + return state; + } + + public void setState(StoragePoolStatus state) { + this.state = state; + } + + public void setSuitableForMigration(Boolean suitableForMigration) { + this.suitableForMigration = suitableForMigration; + } +} diff --git a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java index 0b1622640d0..e034b17e8ea 100644 --- a/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java +++ b/api/src/org/apache/cloudstack/api/response/StoragePoolResponse.java @@ -83,8 +83,6 @@ public class StoragePoolResponse extends BaseResponse { @SerializedName(ApiConstants.SCOPE) @Param(description="the scope of the storage pool") private String scope; - - /** * @return the scope */ @@ -239,5 +237,4 @@ public class StoragePoolResponse extends BaseResponse { public void setState(StoragePoolStatus state) { this.state = state; } - } diff --git a/api/src/org/apache/cloudstack/api/response/UserResponse.java b/api/src/org/apache/cloudstack/api/response/UserResponse.java index 9cd25cb7ad6..e70a310bf06 100644 --- a/api/src/org/apache/cloudstack/api/response/UserResponse.java +++ b/api/src/org/apache/cloudstack/api/response/UserResponse.java @@ -18,6 +18,7 @@ package org.apache.cloudstack.api.response; import java.util.Date; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import org.apache.cloudstack.api.EntityReference; @@ -74,6 +75,9 @@ public class UserResponse extends BaseResponse { @SerializedName("iscallerchilddomain") @Param(description="the boolean value representing if the updating target is in caller's child domain") private boolean isCallerChildDomain; + + @SerializedName(ApiConstants.IS_DEFAULT) @Param(description="true if user is default, false otherwise", since="4.2.0") + private Boolean isDefault; @Override public String getObjectId() { @@ -206,4 +210,8 @@ public class UserResponse extends BaseResponse { public void setIsCallerChildDomain(boolean isCallerChildDomain) { this.isCallerChildDomain = isCallerChildDomain; } + + public void setIsDefault(Boolean isDefault) { + this.isDefault = isDefault; + } } diff --git a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java index 212601ce20c..da08c94074c 100644 --- a/api/src/org/apache/cloudstack/api/response/UserVmResponse.java +++ b/api/src/org/apache/cloudstack/api/response/UserVmResponse.java @@ -80,6 +80,9 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp @SerializedName(ApiConstants.ZONE_NAME) @Param(description="the name of the availability zone for the virtual machine") private String zoneName; + @SerializedName(ApiConstants.ZONE_TYPE) @Param(description="the network type of the availability zone for the virtual machine") + private String zoneType; + @SerializedName(ApiConstants.HOST_ID) @Param(description="the ID of the host for the virtual machine") private String hostId; @@ -249,6 +252,10 @@ public class UserVmResponse extends BaseResponse implements ControlledEntityResp this.zoneName = zoneName; } + public void setZoneType(String zoneType) { + this.zoneType = zoneType; + } + public void setHostId(String hostId) { this.hostId = hostId; } diff --git a/api/test/org/apache/cloudstack/api/command/test/ListCfgCmdTest.java b/api/test/org/apache/cloudstack/api/command/test/ListCfgCmdTest.java new file mode 100644 index 00000000000..7c05eaf5a8d --- /dev/null +++ b/api/test/org/apache/cloudstack/api/command/test/ListCfgCmdTest.java @@ -0,0 +1,89 @@ +// 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.api.command.test; + +import com.cloud.configuration.Configuration; +import com.cloud.configuration.ConfigurationService; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.resource.ResourceService; +import com.cloud.server.ManagementService; +import com.cloud.utils.Pair; +import junit.framework.Assert; +import junit.framework.TestCase; +import org.apache.cloudstack.api.ResponseGenerator; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.admin.config.ListCfgsByCmd; +import org.apache.cloudstack.api.response.ConfigurationResponse; +import org.apache.cloudstack.api.response.ListResponse; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mockito; + +import java.util.ArrayList; +import java.util.List; + +public class ListCfgCmdTest extends TestCase{ + + private ListCfgsByCmd listCfgsByCmd; + private ManagementService mgr; + private ResponseGenerator responseGenerator; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Before + public void setUp() { + responseGenerator = Mockito.mock(ResponseGenerator.class); + mgr = Mockito.mock(ManagementService.class); + listCfgsByCmd = new ListCfgsByCmd(); + } + + @Test + public void testCreateSuccess() { + + Configuration cfg = Mockito.mock(Configuration.class); + listCfgsByCmd._mgr = mgr; + listCfgsByCmd._responseGenerator = responseGenerator; + + + + List configList = new ArrayList(); + configList.add(cfg); + + Pair, Integer> result = new Pair, Integer>(configList, 1); + + try { + Mockito.when( + mgr.searchForConfigurations(listCfgsByCmd)) + .thenReturn(result); + }catch (Exception e){ + Assert.fail("Received exception when success expected " + e.getMessage()); + } + ConfigurationResponse cfgResponse = new ConfigurationResponse(); + cfgResponse.setName("Test case"); + Mockito.when(responseGenerator.createConfigurationResponse(cfg)).thenReturn(cfgResponse); + + listCfgsByCmd.execute(); + Mockito.verify(responseGenerator).createConfigurationResponse(cfg); + + ListResponse actualResponse = (ListResponse) listCfgsByCmd.getResponseObject(); + Assert.assertEquals(cfgResponse, actualResponse.getResponses().get(0)); + } + +} diff --git a/api/test/org/apache/cloudstack/api/command/test/UpdateCfgCmdTest.java b/api/test/org/apache/cloudstack/api/command/test/UpdateCfgCmdTest.java new file mode 100644 index 00000000000..27000cf1770 --- /dev/null +++ b/api/test/org/apache/cloudstack/api/command/test/UpdateCfgCmdTest.java @@ -0,0 +1,116 @@ +// 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.api.command.test; + +import com.cloud.configuration.Configuration; +import com.cloud.configuration.ConfigurationService; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.resource.ResourceService; +import junit.framework.Assert; +import junit.framework.TestCase; +import org.apache.cloudstack.api.ResponseGenerator; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; +import org.apache.cloudstack.api.response.ConfigurationResponse; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mockito; + +public class UpdateCfgCmdTest extends TestCase{ + + private UpdateCfgCmd updateCfgCmd; + private ConfigurationService configService; + private ResponseGenerator responseGenerator; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Before + public void setUp() { + responseGenerator = Mockito.mock(ResponseGenerator.class); + configService = Mockito.mock(ConfigurationService.class); + updateCfgCmd = new UpdateCfgCmd(); + } + + @Test + public void testExecuteForEmptyResult() { + updateCfgCmd._configService = configService; + + try { + updateCfgCmd.execute(); + } catch (ServerApiException exception) { + Assert.assertEquals("Failed to update config", + exception.getDescription()); + } + + } + + @Test + public void testExecuteForNullResult() { + + updateCfgCmd._configService = configService; + + try { + Mockito.when( + configService.updateConfiguration(updateCfgCmd)) + .thenReturn(null); + } catch (InvalidParameterValueException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalArgumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + try { + updateCfgCmd.execute(); + } catch (ServerApiException exception) { + Assert.assertEquals("Failed to update config", + exception.getDescription()); + } + + } + + + @Test + public void testCreateSuccess() { + + Configuration cfg = Mockito.mock(Configuration.class); + updateCfgCmd._configService = configService; + updateCfgCmd._responseGenerator = responseGenerator; + + try { + Mockito.when( + configService.updateConfiguration(updateCfgCmd)) + .thenReturn(cfg); + }catch (Exception e){ + Assert.fail("Received exception when success expected " + e.getMessage()); + } + + ConfigurationResponse response = new ConfigurationResponse(); + response.setName("Test case"); + Mockito.when(responseGenerator.createConfigurationResponse(cfg)).thenReturn(response); + + updateCfgCmd.execute(); + Mockito.verify(responseGenerator).createConfigurationResponse(cfg); + ConfigurationResponse actualResponse = (ConfigurationResponse) updateCfgCmd.getResponseObject(); + Assert.assertEquals(response, actualResponse); + Assert.assertEquals("updateconfigurationresponse", response.getResponseName()); + } + +} diff --git a/build/replace.properties b/build/replace.properties index c9a93c2831c..265f3358724 100644 --- a/build/replace.properties +++ b/build/replace.properties @@ -27,3 +27,4 @@ MSMNTDIR=/mnt COMPONENTS-SPEC=components.xml AWSAPILOG=awsapi.log REMOTEHOST=localhost +COMMONLIBDIR=C:\Users\htrippaers\eclipse_workspace\cloudstack\client\target\cloud-client-ui-4.2.0-SNAPSHOT\WEB-INF\classes diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties index 349ca2e6693..461cc11074a 100644 --- a/client/WEB-INF/classes/resources/messages.properties +++ b/client/WEB-INF/classes/resources/messages.properties @@ -14,9 +14,6 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. - - -#new labels (begin) ********************************************************************************************** label.add.affinity.group=Add new affinity group message.delete.affinity.group=Please confirm that you would like to remove this affinity group. label.delete.affinity.group=Delete Affinity Group @@ -27,902 +24,141 @@ label.affinity.groups=Affinity Groups label.anti.affinity.groups=Anti-affinity Groups label.affinity.group=Affinity Group label.anti.affinity.group=Anti-affinity Group -message.redirecting.region=Redirecting to region... -label.use.vm.ip=Use VM IP: -label.cpu.limits=CPU limits -label.memory.limits=Memory limits (MiB) -label.primary.storage.limits=Primary Storage limits (GiB) -label.secondary.storage.limits=Secondary Storage limits (GiB) -label.max.cpus=Max. CPU cores -label.max.memory=Max. memory (MiB) -label.max.primary.storage=Max. primary (GiB) -label.max.secondary.storage=Max. secondary (GiB) -label.menu.regions=Regions -label.region=Region -label.add.region=Add Region -label.remove.region=Remove Region -message.remove.region=Are you sure you want to remove this region from this management server? -message.add.region=Please specify the required information to add a new region. -label.endpoint=Endpoint -label.plugins=Plugins -label.plugin.details=Plugin details -label.author.name=Author name -label.author.email=Author e-mail -label.external.link=External link -label.egress.rules=Egress rules -message.acquire.new.ip.vpc=Please confirm that you would like to acquire a new IP for this VPC. -label.zoneWizard.trafficType.management=Management: Traffic between CloudStack\'s internal resources, including any components that communicate with the Management Server, such as hosts and CloudStack system VMs -label.zoneWizard.trafficType.public=Public: Traffic between the internet and virtual machines in the cloud. -label.zoneWizard.trafficType.guest=Guest: Traffic between end-user virtual machines -label.zoneWizard.trafficType.storage=Storage: Traffic between primary and secondary storage servers, such as VM templates and snapshots -label.quickview=Quickview -label.migrate.to.host=Migrate to host -label.migrate.to.storage=Migrate to storage -label.stop=Stop -label.reboot=Reboot -label.destroy=Destroy -label.restore=Restore -label.isolation.uri=Isolation URI -label.broadcast.uri=Broadcast URI -label.enable.s3=Enable S3-backed Secondary Storage -confirm.enable.s3=Please fill in the following information to enable support for S3-backed Secondary Storage -message.after.enable.s3=S3-backed Secondary Storage configured. Note: When you leave this page, you will not be able to re-configure S3 again. -label.s3.access_key=Access Key -label.s3.secret_key=Secret Key -label.s3.bucket=Bucket -label.s3.endpoint=Endpoint -label.s3.use_https=Use HTTPS -label.s3.connection_timeout=Connection Timeout -label.s3.max_error_retry=Max Error Retry -label.s3.socket_timeout=Socket Timeout -#new labels (end) ************************************************************************************************ - - -#modified labels (begin) ***************************************************************************************** -label.site.to.site.VPN=Site-to-site VPN -message.zoneWizard.enable.local.storage=WARNING: If you enable local storage for this zone, you must do the following, depending on where you would like your system VMs to launch:

1. If system VMs need to be launched in primary storage, primary storage needs to be added to the zone after creation. You must also start the zone in a disabled state.

2. If system VMs need to be launched in local storage, system.vm.use.local.storage needs to be set to true before you enable the zone.


Would you like to continue? -#modified labels (end) ******************************************************************************************* - -label.configure.network.ACLs=Configure Network ACLs -label.network.ACLs=Network ACLs -label.add.network.ACL=Add network ACL -label.private.Gateway=Private Gateway -label.VPC.router.details=VPC router details -label.VMs.in.tier=VMs in tier -label.local.storage.enabled=Local storage enabled -label.tier.details=Tier details -label.edit.tags=Edit tags -label.action.enable.physical.network=Enable physical network -label.action.disable.physical.network=Disable physical network -message.action.enable.physical.network=Please confirm that you want to enable this physical network. -message.action.disable.physical.network=Please confirm that you want to disable this physical network. - -label.select.tier=Select Tier -label.add.ACL=Add ACL -label.remove.ACL=Remove ACL -label.tier=Tier -label.network.ACL=Network ACL -label.network.ACL.total=Network ACL Total -label.add.new.gateway=Add new gateway -message.add.new.gateway.to.vpc=Please specify the information to add a new gateway to this VPC. -label.delete.gateway=delete gateway -message.delete.gateway=Please confirm you want to delete the gateway -label.CIDR.of.destination.network=CIDR of destination network -label.add.route=Add route -label.add.static.route=Add static route -label.remove.static.route=Remove static route -label.add.VPN.gateway=Add VPN Gateway -message.add.VPN.gateway=Please confirm that you want to add a VPN Gateway -label.VPN.gateway=VPN Gateway -label.delete.VPN.gateway=delete VPN Gateway -message.delete.VPN.gateway=Please confirm that you want to delete this VPN Gateway -label.VPN.connection=VPN Connection -label.IPsec.preshared.key=IPsec Preshared-Key -label.IKE.policy=IKE policy -label.ESP.policy=ESP policy -label.create.VPN.connection=Create VPN Connection -label.VPN.customer.gateway=VPN Customer Gateway -label.CIDR.list=CIDR list -label.IKE.lifetime=IKE Lifetime (second) -label.ESP.lifetime=ESP Lifetime(second) -label.dead.peer.detection=Dead Peer Detection -label.reset.VPN.connection=Reset VPN connection -message.reset.VPN.connection=Please confirm that you want to reset VPN connection -label.delete.VPN.connection=delete VPN connection -message.delete.VPN.connection=Please confirm that you want to delete VPN connection -label.add.new.tier=Add new tier -label.add.VM.to.tier=Add VM to tier -label.remove.tier=Remove tier - -label.local.storage.enabled=Local Storage Enabled -label.associated.network=Associated Network -label.add.port.forwarding.rule=Add port forwarding rule -label.dns=DNS - -label.vpc=VPC -label.vpc.id=VPC ID -label.tier=Tier -label.add.vpc=Add VPC -label.super.cidr.for.guest.networks=Super CIDR for Guest Networks -label.DNS.domain.for.guest.networks=DNS domain for Guest Networks -label.configure.vpc=Configure VPC -label.edit.vpc=Edit VPC -label.restart.vpc=restart VPC -message.restart.vpc=Please confirm that you want to restart the VPC -label.remove.vpc=remove VPC -message.remove.vpc=Please confirm that you want to remove the VPC -label.vpn.customer.gateway=VPN Customer Gateway -label.add.vpn.customer.gateway=Add VPN Customer Gateway -label.IKE.encryption=IKE Encryption -label.IKE.hash=IKE Hash -label.IKE.DH=IKE DH -label.ESP.encryption=ESP Encryption -label.ESP.hash=ESP Hash -label.perfect.forward.secrecy=Perfect Forward Secrecy -label.IKE.lifetime=IKE lifetime (second) -label.ESP.lifetime=ESP Lifetime (second) -label.dead.peer.detection=Dead Peer Detection -label.delete.VPN.customer.gateway=delete VPN Customer Gateway -message.delete.VPN.customer.gateway=Please confirm that you want to delete this VPN Customer Gateway - -label.network.domain.text=Network domain -label.memory.mb=Memory (in MB) -label.cpu.mhz=CPU (in MHz) - -message.action.remove.host=Please confirm that you want to remove this host. - -message.action.reboot.router=All services provided by this virtual router will be interrupted. Please confirm that you want to reboot this router. -message.action.stop.router=All services provided by this virtual router will be interrupted. Please confirm that you want to stop this router. -message.restart.network=All services provided by this network will be interrupted. Please confirm that you want to restart this network. - - -label.ipaddress=IP Address -label.vcdcname=vCenter DC name -label.vcipaddress=vCenter IP Address -label.vsmctrlvlanid=Control VLAN ID -label.vsmpktvlanid=Packet VLAN ID -label.vsmstoragevlanid=Storage VLAN ID -label.nexusVswitch=Nexus 1000v -label.action.delete.nexusVswitch=Delete Nexus 1000v -label.action.enable.nexusVswitch=Enable Nexus 1000v -label.action.disable.nexusVswitch=Disable Nexus 1000v -label.action.list.nexusVswitch=List Nexus 1000v -message.action.delete.nexusVswitch=Please confirm that you want to delete this nexus 1000v -message.action.enable.nexusVswitch=Please confirm that you want to enable this nexus 1000v -message.action.disable.nexusVswitch=Please confirm that you want to disable this nexus 1000v -message.specify.url=Please specify URL -label.select.instance.to.attach.volume.to=Select instance to attach volume to -label.upload=Upload -label.upload.volume=Upload volume -label.virtual.routers=Virtual Routers -label.primary.storage.count=Primary Storage Pools -label.secondary.storage.count=Secondary Storage Pools -label.number.of.system.vms=Number of System VMs -label.number.of.virtual.routers=Number of Virtual Routers -label.action.register.iso=Register ISO -label.isolation.method=Isolation method -label.action.register.template=Register template -label.checksum=MD5 checksum -label.vpn=VPN -label.vlan=VLAN - - -label.management.ips=Management IP Addresses -label.devices=Devices -label.rules=Rules -label.traffic.label=Traffic label -label.vm.state=VM state -message.setup.physical.network.during.zone.creation.basic=When adding a basic zone, you can set up one physical network, which corresponds to a NIC on the hypervisor. The network carries several types of traffic.

You may also drag and drop other traffic types onto the physical network. -label.domain.router=Domain router -label.console.proxy=Console proxy -label.secondary.storage.vm=Secondary storage VM -label.add.netScaler.device=Add Netscaler device -label.add.F5.device=Add F5 device -label.add.SRX.device=Add SRX device -label.account.and.security.group=Account, Security group -label.fetch.latest=Fetch latest -label.system.offering=System Offering -message.validate.instance.name=Instance name can not be longer than 63 characters. Only ASCII letters a~z, A~Z, digits 0~9, hyphen are allowed. Must start with a letter and end with a letter or a digit. - - -label.isolated.networks=Isolated networks -label.latest.events=Latest events -state.Enabled=Enabled -label.system.wide.capacity=System-wide capacity -label.network.service.providers=Network Service Providers -message.launch.zone=Zone is ready to launch; please proceed to the next step. -error.unable.to.reach.management.server=Unable to reach Management Server -label.internal.name=Internal name -message.configure.all.traffic.types=You have multiple physical networks; please configure labels for each traffic type by clicking on the Edit button. -message.edit.traffic.type=Please specify the traffic label you want associated with this traffic type. -label.edit.traffic.type=Edit traffic type -label.label=Label -label.max.networks=Max. networks -error.invalid.username.password=Invalid username or password -message.enabling.security.group.provider=Enabling Security Group provider -message.adding.Netscaler.provider=Adding Netscaler provider -message.creating.guest.network=Creating guest network -label.action.delete.physical.network=Delete physical network -message.action.delete.physical.network=Please confirm that you want to delete this physical network -message.installWizard.copy.whatIsAHost=A host is a single computer. Hosts provide the computing resources that run the guest virtual machines. Each host has hypervisor software installed on it to manage the guest VMs (except for bare metal hosts, which are a special case discussed in the Advanced Installation Guide). For example, a Linux KVM-enabled server, a Citrix XenServer server, and an ESXi server are hosts. In a Basic Installation, we use a single host running XenServer or KVM.

The host is the smallest organizational unit within a CloudStack™ deployment. Hosts are contained within clusters, clusters are contained within pods, and pods are contained within zones. - - -label.add.compute.offering=Add compute offering -label.compute.offering=Compute offering -label.compute.offerings=Compute offerings -label.select.offering=Select offering -label.menu.infrastructure=Infrastructure -label.sticky.tablesize=Table size -label.sticky.expire=Expires -label.sticky.cookie-name=Cookie name -label.sticky.mode=Mode -label.sticky.length=Length -label.sticky.holdtime=Hold time -label.sticky.request-learn=Request learn -label.sticky.prefix=Prefix -label.sticky.nocache=No cache -label.sticky.indirect=Indirect -label.sticky.postonly=Post only -label.sticky.domain=Domain -state.Allocating=Allocating -state.Migrating=Migrating -error.please.specify.physical.network.tags=Network offerings is not available until you specify tags for this physical network. - - -state.Stopping=Stopping -message.add.load.balancer.under.ip=The load balancer rule has been added under IP: -message.select.instance=Please select an instance. -label.select=Select -label.select.vm.for.static.nat=Select VM for static NAT -label.select.instance=Select instance -label.nat.port.range=NAT Port Range -label.static.nat.vm.details=Static NAT VM Details -label.edit.lb.rule=Edit LB rule -message.migrate.instance.to.host=Please confirm that you want to migrate instance to another host. -label.migrate.instance.to.host=Migrate instance to another host -message.migrate.instance.to.ps=Please confirm that you want to migrate instance to another primary storage. -label.migrate.instance.to.ps=Migrate instance to another primary storage -label.corrections.saved=Corrections saved -message.installWizard.copy.whatIsSecondaryStorage=Secondary storage is associated with a zone, and it stores the following:
  • Templates - OS images that can be used to boot VMs and can include additional configuration information, such as installed applications
  • ISO images - OS images that can be bootable or non-bootable
  • Disk volume snapshots - saved copies of VM data which can be used for data recovery or to create new templates
-message.installWizard.copy.whatIsPrimaryStorage=A CloudStack™ cloud infrastructure makes use of two types of storage: primary storage and secondary storage. Both of these can be iSCSI or NFS servers, or localdisk.

Primary storage is associated with a cluster, and it stores the disk volumes of each guest VM for all the VMs running on hosts in that cluster. The primary storage server is typically located close to the hosts. -message.installWizard.copy.whatIsACluster=A cluster provides a way to group hosts. The hosts in a cluster all have identical hardware, run the same hypervisor, are on the same subnet, and access the same shared storage. Virtual machine instances (VMs) can be live-migrated from one host to another within the same cluster, without interrupting service to the user. A cluster is the third-largest organizational unit within a CloudStack™ deployment. Clusters are contained within pods, and pods are contained within zones.

CloudStack™ allows multiple clusters in a cloud deployment, but for a Basic Installation, we only need one cluster. -message.installWizard.copy.whatIsAPod=A pod often represents a single rack. Hosts in the same pod are in the same subnet.

A pod is the second-largest organizational unit within a CloudStack™ deployment. Pods are contained within zones. Each zone can contain one or more pods; in the Basic Installation, you will have just one pod in your zone. -message.installWizard.copy.whatIsAZone=A zone is the largest organizational unit within a CloudStack™ deployment. A zone typically corresponds to a single datacenter, although it is permissible to have multiple zones in a datacenter. The benefit of organizing infrastructure into zones is to provide physical isolation and redundancy. For example, each zone can have its own power supply and network uplink, and the zones can be widely separated geographically (though this is not required). -message.installWizard.copy.whatIsCloudStack=CloudStack™ is a software platform that pools computing resources to build public, private, and hybrid Infrastructure as a Service (IaaS) clouds. CloudStack™ manages the network, storage, and compute nodes that make up a cloud infrastructure. Use CloudStack™ to deploy, manage, and configure cloud computing environments.

Extending beyond individual virtual machine images running on commodity hardware, CloudStack™ provides a turnkey cloud infrastructure software stack for delivering virtual datacenters as a service - delivering all of the essential components to build, deploy, and manage multi-tier and multi-tenant cloud applications. Both open-source and Premium versions are available, with the open-source version offering nearly identical features. -message.installWizard.tooltip.addSecondaryStorage.path=The exported path, located on the server you specified above -message.installWizard.tooltip.addSecondaryStorage.nfsServer=The IP address of the NFS server hosting the secondary storage -message.installWizard.tooltip.addPrimaryStorage.path=(for NFS) In NFS this is the exported path from the server. Path (for SharedMountPoint). With KVM this is the path on each host that is where this primary storage is mounted. For example, "/mnt/primary". -message.installWizard.tooltip.addPrimaryStorage.server=(for NFS, iSCSI, or PreSetup) The IP address or DNS name of the storage device. -message.installWizard.tooltip.addPrimaryStorage.name=The name for the storage device. -message.installWizard.tooltip.addHost.password=This is the password for the user named above (from your XenServer install). -message.installWizard.tooltip.addHost.username=Usually root. -message.installWizard.tooltip.addHost.hostname=The DNS name or IP address of the host. -message.installWizard.tooltip.addCluster.name=A name for the cluster. This can be text of your choosing and is not used by CloudStack. -message.installWizard.tooltip.addPod.reservedSystemEndIp=This is the IP range in the private network that the CloudStack uses to manage Secondary Storage VMs and Console Proxy VMs. These IP addresses are taken from the same subnet as computing servers. -message.installWizard.tooltip.addPod.reservedSystemStartIp=This is the IP range in the private network that the CloudStack uses to manage Secondary Storage VMs and Console Proxy VMs. These IP addresses are taken from the same subnet as computing servers. -message.installWizard.tooltip.addPod.reservedSystemNetmask=The netmask in use on the subnet the guests will use. -message.installWizard.tooltip.addPod.reservedSystemGateway=The gateway for the hosts in that pod. -message.installWizard.tooltip.addPod.name=A name for the pod -message.installWizard.tooltip.configureGuestTraffic.guestEndIp=The range of IP addresses that will be available for allocation to guests in this zone. If one NIC is used, these IPs should be in the same CIDR as the pod CIDR. -message.installWizard.tooltip.configureGuestTraffic.guestStartIp=The range of IP addresses that will be available for allocation to guests in this zone. If one NIC is used, these IPs should be in the same CIDR as the pod CIDR. -message.installWizard.tooltip.configureGuestTraffic.guestNetmask=The netmask in use on the subnet that the guests should use -message.installWizard.tooltip.configureGuestTraffic.guestGateway=The gateway that the guests should use -message.installWizard.tooltip.configureGuestTraffic.description=A description for your network -message.installWizard.tooltip.configureGuestTraffic.name=A name for your network -message.installWizard.tooltip.addZone.internaldns2=These are DNS servers for use by system VMs in the zone. These DNS servers will be accessed via the private network interface of the System VMs. The private IP address you provide for the pods must have a route to the DNS server named here. -message.installWizard.tooltip.addZone.internaldns1=These are DNS servers for use by system VMs in the zone. These DNS servers will be accessed via the private network interface of the System VMs. The private IP address you provide for the pods must have a route to the DNS server named here. -message.installWizard.tooltip.addZone.dns2=These are DNS servers for use by guest VMs in the zone. These DNS servers will be accessed via the public network you will add later. The public IP addresses for the zone must have a route to the DNS server named here. -message.installWizard.tooltip.addZone.name=A name for the zone -message.installWizard.tooltip.addZone.dns1=These are DNS servers for use by guest VMs in the zone. These DNS servers will be accessed via the public network you will add later. The public IP addresses for the zone must have a route to the DNS server named here. -message.setup.successful=Cloud setup successful! -label.may.continue=You may now continue. -error.installWizard.message=Something went wrong; you may go back and correct any errors -message.installWizard.now.building=Now building your cloud... -message.installWizard.click.retry=Click the button to retry launch. -label.launch=Launch -label.installWizard.click.launch=Click the launch button. -label.congratulations=Congratulations! -label.installWizard.addSecondaryStorageIntro.subtitle=What is secondary storage? -label.installWizard.addSecondaryStorageIntro.title=Let’s add secondary storage -label.installWizard.addPrimaryStorageIntro.subtitle=What is primary storage? -label.installWizard.addPrimaryStorageIntro.title=Let’s add primary storage -label.installWizard.addHostIntro.subtitle=What is a host? -label.installWizard.addHostIntro.title=Let’s add a host -label.installWizard.addClusterIntro.subtitle=What is a cluster? -label.installWizard.addClusterIntro.title=Let’s add a cluster -label.installWizard.addPodIntro.subtitle=What is a pod? -label.installWizard.addPodIntro.title=Let’s add a pod -label.installWizard.addZone.title=Add zone -label.installWizard.addZoneIntro.subtitle=What is a zone? -label.installWizard.addZoneIntro.title=Let’s add a zone -error.password.not.match=The password fields do not match -label.confirm.password=Confirm password -message.change.password=Please change your password. -label.save.and.continue=Save and continue -label.skip.guide=I have used CloudStack before, skip this guide -label.continue.basic.install=Continue with basic installation -label.introduction.to.cloudstack=Introduction to CloudStack™ -label.what.is.cloudstack=What is CloudStack™? -label.hints=Hints -label.installWizard.subtitle=This tour will aid you in setting up your CloudStack™ installation -label.continue=Continue -label.installWizard.title=Hello and Welcome to CloudStack™ -label.agree=Agree -label.manage.resources=Manage Resources -label.port.forwarding.policies=Port forwarding policies -label.load.balancing.policies=Load balancing policies -label.networking.and.security=Networking and security -label.bandwidth=Bandwidth -label.virtual.machines=Virtual machines -label.compute.and.storage=Compute and Storage -label.task.completed=Task completed -label.update.project.resources=Update project resources -label.remove.project.account=Remove project account -label.item.listing=Item listing -message.select.item=Please select an item. -label.removing=Removing -label.invite=Invite -label.add.by=Add by -label.max.vms=Max. user VMs -label.max.public.ips=Max. public IPs -label.max.volumes=Max. volumes -label.max.snapshots=Max. snapshots -label.max.templates=Max. templates -label.max.vpcs=Max. VPCs -label.project.dashboard=Project dashboard -label.remind.later=Remind me later -label.invited.accounts=Invited accounts -label.invite.to=Invite to -label.add.accounts.to=Add accounts to -label.add.accounts=Add accounts -label.project.name=Project name -label.create.project=Create project -label.networks=Networks -label.launch.vm=Launch VM -label.new.vm=New VM -label.previous=Previous -label.add.to.group=Add to group -message.vm.review.launch=Please review the following information and confirm that your virtual instance is correct before launch. -message.select.security.groups=Please select security group(s) for your new VM -label.new=New -message.please.select.networks=Please select networks for your virtual machine. -message.please.proceed=Please proceed to the next step. -message.zone.no.network.selection=The zone you selected does not have any choices for network selection. -label.no.thanks=No thanks -label.my.templates=My templates -message.select.template=Please select a template for your new virtual instance. -message.select.iso=Please select an ISO for your new virtual instance. -message.template.desc=OS image that can be used to boot VMs -message.iso.desc=Disc image containing data or bootable media for OS -label.select.iso.or.template=Select ISO or template -message.select.a.zone=A zone typically corresponds to a single datacenter. Multiple zones help make the cloud more reliable by providing physical isolation and redundancy. -label.select.a.zone=Select a zone -label.review=Review -label.select.a.template=Select a template -label.setup=Setup -state.Allocated=Allocated changed.item.properties=Changed item properties -label.apply=Apply -label.default=Default -label.viewing=Viewing -label.move.to.top=Move to top -label.move.up.row=Move up one row -label.move.down.row=Move down one row -label.move.to.bottom=Move to bottom -label.drag.new.position=Drag to new position -label.order=Order -label.no.data=No data to show -label.change.value=Change value -label.clear.list=Clear list -label.full.path=Full path -message.add.domain=Please specify the subdomain you want to create under this domain -message.delete.user=Please confirm that you would like to delete this user. -message.enable.user=Please confirm that you would like to enable this user. -message.disable.user=Please confirm that you would like to disable this user. -message.generate.keys=Please confirm that you would like to generate new keys for this user. -message.update.resource.count=Please confirm that you want to update resource counts for this account. -message.edit.account=Edit ("-1" indicates no limit to the amount of resources create) -label.total.of.vm=Total of VM -label.total.of.ip=Total of IP Address -state.enabled=Enabled -message.action.download.iso=Please confirm that you want to download this ISO. -message.action.download.template=Please confirm that you want to download this template. -label.destination.zone=Destination Zone -label.keyboard.type=Keyboard type -label.nic.adapter.type=NIC adapter type -label.root.disk.controller=Root disk controller -label.community=Community -label.remove.egress.rule=Remove egress rule -label.add.egress.rule=Add egress rule -label.egress.rule=Egress rule -label.remove.ingress.rule=Remove ingress rule -label.delete.vpn.user=Delete VPN user -label.add.vpn.user=Add VPN user -label.remove.pf=Remove port forwarding rule -label.remove.vm.from.lb=Remove VM from load balancer rule -label.add.vms.to.lb=Add VM(s) to load balancer rule -label.add.vm=Add VM -label.remove.static.nat.rule=Remove static NAT rule -label.remove.rule=Remove rule -label.add.static.nat.rule=Add static NAT rule -label.add.rule=Add rule -label.configuration=Configuration -message.disable.vpn=Are you sure you want to disable VPN? -label.disable.vpn=Disable VPN -message.enable.vpn=Please confirm that you want VPN access enabled for this IP address. -label.enable.vpn=Enable VPN -message.acquire.new.ip=Please confirm that you would like to acquire a new IP for this network. -label.elastic=Elastic -label.my.network=My network -label.add.vms=Add VMs -label.configure=Configure -label.stickiness=Stickiness -label.source=Source -label.least.connections=Least connections -label.round.robin=Round-robin -label.restart.required=Restart required -label.clean.up=Clean up -label.restart.network=Restart network -label.edit.network.details=Edit network details -label.add.guest.network=Add guest network -label.guest.networks=Guest networks -message.ip.address.changed=Your IP addresses may have changed; would you like to refresh the listing? Note that in this case the details pane will close. -state.BackingUp=Backing Up -state.BackedUp=Backed Up -label.done=Done -label.vm.name=VM name -message.migrate.volume=Please confirm that you want to migrate volume to another primary storage. -label.migrate.volume=Migrate volume to another primary storage -message.create.template=Are you sure you want to create template? -label.create.template=Create template -message.download.volume.confirm=Please confirm that you want to download this volume -message.detach.disk=Are you sure you want to detach this disk? -state.ready=Ready -state.Ready=Ready -label.vm.display.name=VM display name -label.select-view=Select view -label.local.storage=Local Storage -label.direct.ips=Shared Network IPs -label.view.all=View all -label.zone.details=Zone details -message.alert.state.detected=Alert state detected -state.Starting=Starting -state.Expunging=Expunging -state.Creating=Creating -message.decline.invitation=Are you sure you want to decline this project invitation? -label.decline.invitation=Decline invitation -message.confirm.join.project=Please confirm you wish to join this project. -message.join.project=You have now joined a project. Please switch to Project view to see the project. -label.accept.project.invitation=Accept project invitation -label.token=Token -label.project.id=Project ID -message.enter.token=Please enter the token that you were given in your invite e-mail. -label.enter.token=Enter token -state.Accepted=Accepted -state.Pending=Pending -state.Completed=Completed -state.Declined=Declined -label.project=Project -label.invitations=Invitations -label.delete.project=Delete project -message.delete.project=Are you sure you want to delete this project? -message.activate.project=Are you sure you want to activate this project? -label.activate.project=Activate Project -label.suspend.project=Suspend Project -message.suspend.project=Are you sure you want to suspend this project? -state.Suspended=Suspended -label.edit.project.details=Edit project details -label.new.project=New Project -state.Active=Active -state.Disabled=Disabled -label.projects=Projects -label.make.project.owner=Make account project owner -label.remove.project.account=Remove account from project -message.project.invite.sent=Invite sent to user; they will be added to the project once they accept the invitation -label.add.account.to.project=Add account to project -label.revoke.project.invite=Revoke invitation -label.project.invite=Invite to project -label.select.project=Select Project -message.no.projects=You do not have any projects.
Please create a new one from the projects section. -message.no.projects.adminOnly=You do not have any projects.
Please ask your administrator to create a new project. -message.pending.projects.1=You have pending project invitations: -message.pending.projects.2=To view, please go to the projects section, then select invitations from the drop-down. -message.instanceWizard.noTemplates=You do not have any templates available; please add a compatible template, and re-launch the instance wizard. -label.view=View -instances.actions.reboot.label=Reboot instance -label.filterBy=Filter by -label.ok=OK -notification.reboot.instance=Reboot instance -notification.start.instance=Start instance -notification.stop.instance=Stop instance -label.display.name=Display name -label.zone.name=Zone name -ui.listView.filters.all=All -ui.listView.filters.mine=Mine -state.Running=Running -state.Stopped=Stopped -state.Destroyed=Destroyed -state.Error=Error -message.reset.password.warning.notPasswordEnabled=The template of this instance was created without password enabled -message.reset.password.warning.notStopped=Your instance must be stopped before attempting to change its current password -label.notifications=Notifications -label.default.view=Default View -label.project.view=Project View - -message.add.system.service.offering=Please fill in the following data to add a new system service offering. -message.action.delete.system.service.offering=Please confirm that you want to delete this system service offering. -label.action.delete.system.service.offering=Delete System Service Offering -label.hypervisor.capabilities=Hypervisor capabilities -label.hypervisor.version=Hypervisor version -label.max.guest.limit=Max guest limit -label.add.network.offering=Add network offering -label.supported.services=Supported Services -label.service.capabilities=Service Capabilities -label.guest.type=Guest Type -label.specify.IP.ranges=Specify IP ranges -label.conserve.mode=Conserve mode -label.created.by.system=Created by system -label.menu.system.service.offerings=System Offerings -label.add.system.service.offering=Add System Service Offering -label.redundant.router.capability=Redundant router capability -label.supported.source.NAT.type=Supported Source NAT type -label.elastic.LB=Elastic LB -label.LB.isolation=LB isolation -label.elastic.IP=Elastic IP -label.network.label.display.for.blank.value=Use default gateway -label.xen.traffic.label=XenServer traffic label -label.kvm.traffic.label=KVM traffic label -label.vmware.traffic.label=VMware traffic label -label.start.IP=Start IP -label.end.IP=End IP -label.remove.ip.range=Remove IP range -label.ip.ranges=IP Ranges -label.start.vlan=Start Vlan -label.end.vlan=End Vlan -label.broadcast.domain.range=Broadcast domain range -label.compute=Compute -message.add.guest.network=Please confirm that you would like to add a guest network -label.subdomain.access=Subdomain Access -label.guest.start.ip=Guest start IP -label.guest.end.ip=Guest end IP -label.virtual.router=Virtual Router -label.physical.network.ID=Physical network ID -label.destination.physical.network.id=Destination physical network ID -label.dhcp=DHCP -label.destroy.router=Destroy router -message.confirm.destroy.router=Please confirm that you would like to destroy this router -label.change.service.offering=Change service offering -label.view.console=View console -label.redundant.state=Redundant state -label.enable.provider=Enable provider -message.confirm.enable.provider=Please confirm that you would like to enable this provider -label.disable.provider=Disable provider -message.confirm.disable.provider=Please confirm that you would like to disable this provider -label.shutdown.provider=Shutdown provider -message.confirm.shutdown.provider=Please confirm that you would like to shutdown this provider -label.netScaler=NetScaler -label.add.new.NetScaler=Add new NetScaler -label.capacity=Capacity -label.dedicated=Dedicated -label.f5=F5 -label.add.new.F5=Add new F5 -label.srx=SRX -label.providers=Providers -label.add.new.SRX=Add new SRX -label.timeout=Timeout -label.public.network=Public network -label.private.network=Private network -label.enable.swift=Enable Swift +confirm.enable.s3=Please fill in the following information to enable support for S3-backed Secondary Storage confirm.enable.swift=Please fill in the following information to enable support for Swift -message.after.enable.swift=Swift configured. Note: When you leave this page, you will not be able to re-configure Swift again. -label.key=Key -label.delete.NetScaler=Delete NetScaler -message.confirm.delete.NetScaler=Please confirm that you would like to delete NetScaler -label.delete.F5=Delete F5 -message.confirm.delete.F5=Please confirm that you would like to delete F5 -label.delete.SRX=Delete SRX -message.confirm.delete.SRX=Please confirm that you would like to delete SRX -label.pods=Pods -label.pod.name=Pod name -label.reserved.system.gateway=Reserved system gateway -label.reserved.system.netmask=Reserved system netmask -label.start.reserved.system.IP=Start Reserved system IP -label.end.reserved.system.IP=End Reserved system IP -label.clusters=Clusters -label.cluster.name=Cluster Name -label.host.MAC=Host MAC -label.agent.username=Agent Username -label.agent.password=Agent Password -message.confirm.action.force.reconnect=Please confirm that you want to force reconnect this host. -label.resource.state=Resource state -label.LUN.number=LUN # -message.confirm.remove.IP.range=Please confirm that you would like to remove this IP range. -message.tooltip.zone.name=A name for the zone. -message.tooltip.dns.1=Name of a DNS server for use by VMs in the zone. The public IP addresses for the zone must have a route to this server. -message.tooltip.dns.2=A second DNS server name for use by VMs in the zone. The public IP addresses for the zone must have a route to this server. -message.tooltip.internal.dns.1=Name of a DNS server for use by CloudStack internal system VMs in the zone. The private IP address for the pods must have a route to this server. -message.tooltip.internal.dns.2=Name of a DNS server for use by CloudStack internal system VMs in the zone. The private IP address for the pods must have a route to this server. -message.tooltip.network.domain=A DNS suffix that will create a custom domain name for the network that is accessed by guest VMs. -message.tooltip.pod.name=A name for this pod. -message.tooltip.reserved.system.gateway=The gateway for the hosts in the pod. -message.tooltip.reserved.system.netmask=The network prefix that defines the pod subnet. Uses CIDR notation. -message.creating.zone=Creating zone -message.creating.physical.networks=Creating physical networks -message.configuring.physical.networks=Configuring physical networks -message.adding.Netscaler.device=Adding Netscaler device -message.creating.pod=Creating pod -message.configuring.public.traffic=Configuring public traffic -message.configuring.storage.traffic=Configuring storage traffic -message.configuring.guest.traffic=Configuring guest traffic -message.creating.cluster=Creating cluster -message.adding.host=Adding host -message.creating.primary.storage=Creating primary storage -message.creating.secondary.storage=Creating secondary storage -message.Zone.creation.complete=Zone creation complete -message.enabling.zone=Enabling zone -error.something.went.wrong.please.correct.the.following=Something went wrong; please correct the following error.could.not.enable.zone=Could not enable zone -message.zone.creation.complete.would.you.like.to.enable.this.zone=Zone creation complete. Would you like to enable this zone? -message.please.add.at.lease.one.traffic.range=Please add at least one traffic range. -message.you.must.have.at.least.one.physical.network=You must have at least one physical network -message.please.select.a.different.public.and.management.network.before.removing=Please select a different public and management network before removing - -label.zone.type=Zone Type -label.setup.zone=Setup Zone -label.setup.network=Setup Network -label.add.resources=Add Resources -label.launch=Launch -label.set.up.zone.type=Set up zone type -message.please.select.a.configuration.for.your.zone=Please select a configuration for your zone. -message.desc.basic.zone=Provide a single network where each VM instance is assigned an IP directly from the network. Guest isolation can be provided through layer-3 means such as security groups (IP address source filtering). -label.basic=Basic -message.desc.advanced.zone=For more sophisticated network topologies. This network model provides the most flexibility in defining guest networks and providing custom network offerings such as firewall, VPN, or load balancer support. -label.advanced=Advanced -message.desc.zone=A zone is the largest organizational unit in CloudStack, and it typically corresponds to a single datacenter. Zones provide physical isolation and redundancy. A zone consists of one or more pods (each of which contains hosts and primary storage servers) and a secondary storage server which is shared by all pods in the zone. -label.physical.network=Physical Network -label.public.traffic=Public traffic -label.guest.traffic=Guest Traffic -label.storage.traffic=Storage Traffic -message.setup.physical.network.during.zone.creation=When adding an advanced zone, you need to set up one or more physical networks. Each network corresponds to a NIC on the hypervisor. Each physical network can carry one or more types of traffic, with certain restrictions on how they may be combined.

Drag and drop one or more traffic types onto each physical network. -label.add.physical.network=Add physical network -label.traffic.types=Traffic Types -label.management=Management -label.guest=Guest -label.please.specify.netscaler.info=Please specify Netscaler info -message.public.traffic.in.advanced.zone=Public traffic is generated when VMs in the cloud access the internet. Publicly-accessible IPs must be allocated for this purpose. End users can use the CloudStack UI to acquire these IPs to implement NAT between their guest network and their public network.

Provide at least one range of IP addresses for internet traffic. -message.public.traffic.in.basic.zone=Public traffic is generated when VMs in the cloud access the Internet or provide services to clients over the Internet. Publicly accessible IPs must be allocated for this purpose. When a instance is created, an IP from this set of Public IPs will be allocated to the instance in addition to the guest IP address. Static 1-1 NAT will be set up automatically between the public IP and the guest IP. End users can also use the CloudStack UI to acquire additional IPs to implement static NAT between their instances and the public IP. -message.add.pod.during.zone.creation=Each zone must contain in one or more pods, and we will add the first pod now. A pod contains hosts and primary storage servers, which you will add in a later step. First, configure a range of reserved IP addresses for CloudStack's internal management traffic. The reserved IP range must be unique for each zone in the cloud. -message.guest.traffic.in.advanced.zone=Guest network traffic is communication between end-user virtual machines. Specify a range of VLAN IDs to carry guest traffic for each physical network. -message.guest.traffic.in.basic.zone=Guest network traffic is communication between end-user virtual machines. Specify a range of IP addresses that CloudStack can assign to guest VMs. Make sure this range does not overlap the reserved system IP range. -message.storage.traffic=Traffic between CloudStack's internal resources, including any components that communicate with the Management Server, such as hosts and CloudStack system VMs. Please configure storage traffic here. -message.desc.cluster=Each pod must contain one or more clusters, and we will add the first cluster now. A cluster provides a way to group hosts. The hosts in a cluster all have identical hardware, run the same hypervisor, are on the same subnet, and access the same shared storage. Each cluster consists of one or more hosts and one or more primary storage servers. -message.desc.host=Each cluster must contain at least one host (computer) for guest VMs to run on, and we will add the first host now. For a host to function in CloudStack, you must install hypervisor software on the host, assign an IP address to the host, and ensure the host is connected to the CloudStack management server.

Give the host's DNS or IP address, the user name (usually root) and password, and any labels you use to categorize hosts. -message.desc.primary.storage=Each cluster must contain one or more primary storage servers, and we will add the first one now. Primary storage contains the disk volumes for all the VMs running on hosts in the cluster. Use any standards-compliant protocol that is supported by the underlying hypervisor. -message.desc.secondary.storage=Each zone must have at least one NFS or secondary storage server, and we will add the first one now. Secondary storage stores VM templates, ISO images, and VM disk volume snapshots. This server must be available to all hosts in the zone.

Provide the IP address and exported path. -label.launch.zone=Launch zone -message.please.wait.while.zone.is.being.created=Please wait while your zone is being created; this may take a while... - -label.load.balancing=Load Balancing -label.static.nat.enabled=Static NAT Enabled -label.zones=Zones -label.view.more=View more -label.number.of.zones=Number of Zones -label.number.of.pods=Number of Pods -label.number.of.clusters=Number of Clusters -label.number.of.hosts=Number of Hosts -label.total.hosts=Total Hosts -label.total.CPU=Total CPU -label.total.memory=Total Memory -label.total.storage=Total Storage -label.purpose=Purpose - - - - -label.action.migrate.router=Migrate Router -label.action.migrate.router.processing=Migrating Router.... -message.migrate.router.confirm=Please confirm the host you wish to migrate the router to: -label.migrate.router.to=Migrate Router to - -label.action.migrate.systemvm=Migrate System VM -label.action.migrate.systemvm.processing=Migrating System VM.... -message.migrate.systemvm.confirm=Please confirm the host you wish to migrate the system VM to: -label.migrate.systemvm.to=Migrate System VM to - - -mode=Mode -side.by.side=Side by Side -inline=Inline - +error.installWizard.message=Something went wrong; you may go back and correct any errors +error.invalid.username.password=Invalid username or password +error.login=Your username/password does not match our records. +error.menu.select=Unable to perform action due to no items being selected. +error.mgmt.server.inaccessible=The Management Server is unaccessible. Please try again later. +error.password.not.match=The password fields do not match +error.please.specify.physical.network.tags=Network offerings is not available until you specify tags for this physical network. +error.session.expired=Your session has expired. +error.something.went.wrong.please.correct.the.following=Something went wrong; please correct the following +error.unable.to.reach.management.server=Unable to reach Management Server +error.unresolved.internet.name=Your internet name cannot be resolved. extractable=Extractable - -label.ocfs2=OCFS2 - -label.action.edit.host=Edit Host - -network.rate=Network Rate - -ICMP.type=ICMP Type -ICMP.code=ICMP Code - -image.directory=Image Directory - -label.action.create.template.from.vm=Create Template from VM -label.action.create.template.from.volume=Create Template from Volume - -message.vm.create.template.confirm=Create Template will reboot the VM automatically. - -label.action.manage.cluster=Manage Cluster -message.action.manage.cluster=Please confirm that you want to manage the cluster. -label.action.manage.cluster.processing=Managing Cluster.... - -label.action.unmanage.cluster=Unmanage Cluster -message.action.unmanage.cluster=Please confirm that you want to unmanage the cluster. -label.action.unmanage.cluster.processing=Unmanaging Cluster.... - -label.allocation.state=Allocation State -managed.state=Managed State - -label.default.use=Default Use -label.host.tags=Host Tags - -label.cidr=CIDR -label.cidr.list=Source CIDR - -label.storage.tags=Storage Tags - -label.redundant.router=Redundant Router -label.is.redundant.router=Redundant - -force.delete=Force Delete force.delete.domain.warning=Warning: Choosing this option will cause the deletion of all child domains and all associated accounts and their resources. - +force.delete=Force Delete force.remove=Force Remove force.remove.host.warning=Warning: Choosing this option will cause CloudStack to forcefully stop all running virtual machines before removing this host from the cluster. - force.stop=Force Stop force.stop.instance.warning=Warning: Forcing a stop on this instance should be your last option. It can lead to data loss as well as inconsistent behavior of the virtual machine state. - -label.PreSetup=PreSetup -label.SR.name = SR Name-Label -label.SharedMountPoint=SharedMountPoint -label.clvm=CLVM -label.volgroup=Volume Group -label.VMFS.datastore=VMFS datastore - -label.network.device=Network Device -label.add.network.device=Add Network Device -label.network.device.type=Network Device Type -label.DHCP.server.type=DHCP Server Type -label.Pxe.server.type=Pxe Server Type -label.PING.storage.IP=PING storage IP -label.PING.dir=PING Directory -label.TFTP.dir=TFTP Directory -label.PING.CIFS.username=PING CIFS username -label.PING.CIFS.password=PING CIFS password -label.CPU.cap=CPU Cap - - -label.action.enable.zone=Enable Zone -label.action.enable.zone.processing=Enabling Zone.... -message.action.enable.zone=Please confirm that you want to enable this zone. -label.action.disable.zone=Disable Zone -label.action.disable.zone.processing=Disabling Zone.... -message.action.disable.zone=Please confirm that you want to disable this zone. - -label.action.enable.pod=Enable Pod -label.action.enable.pod.processing=Enabling Pod.... -message.action.enable.pod=Please confirm that you want to enable this pod. -label.action.disable.pod=Disable Pod -label.action.disable.pod.processing=Disabling Pod.... -message.action.disable.pod=Please confirm that you want to disable this pod. - -label.action.enable.cluster=Enable Cluster -label.action.enable.cluster.processing=Enabling Cluster.... -message.action.enable.cluster=Please confirm that you want to enable this cluster. -label.action.disable.cluster=Disable Cluster -label.action.disable.cluster.processing=Disabling Cluster.... -message.action.disable.cluster=Please confirm that you want to disable this cluster. - +ICMP.code=ICMP Code +ICMP.type=ICMP Type +image.directory=Image Directory +inline=Inline +instances.actions.reboot.label=Reboot instance +label.accept.project.invitation=Accept project invitation +label.account=Account +label.account.and.security.group=Account, Security group label.account.id=Account ID label.account.name=Account Name -label.account.specific=Account-Specific -label.account=Account label.accounts=Accounts +label.account.specific=Account-Specific label.acquire.new.ip=Acquire New IP -label.show.ingress.rule=Show Ingress Rule -label.hide.ingress.rule=Hide Ingress Rule -label.action.attach.disk.processing=Attaching Disk.... label.action.attach.disk=Attach Disk -label.action.attach.iso.processing=Attaching ISO.... +label.action.attach.disk.processing=Attaching Disk.... label.action.attach.iso=Attach ISO -label.action.cancel.maintenance.mode.processing=Cancelling Maintenance Mode.... +label.action.attach.iso.processing=Attaching ISO.... label.action.cancel.maintenance.mode=Cancel Maintenance Mode +label.action.cancel.maintenance.mode.processing=Cancelling Maintenance Mode.... label.action.change.password=Change Password -label.action.change.service.processing=Changing Service.... label.action.change.service=Change Service -label.action.copy.ISO.processing=Coping ISO.... +label.action.change.service.processing=Changing Service.... label.action.copy.ISO=Copy ISO -label.action.copy.template.processing=Coping Template.... +label.action.copy.ISO.processing=Coping ISO.... label.action.copy.template=Copy Template -label.action.create.template.processing=Creating Template.... +label.action.copy.template.processing=Coping Template.... label.action.create.template=Create Template -label.action.create.vm.processing=Creating VM.... +label.action.create.template.from.vm=Create Template from VM +label.action.create.template.from.volume=Create Template from Volume +label.action.create.template.processing=Creating Template.... label.action.create.vm=Create VM -label.action.create.volume.processing=Creating Volume.... +label.action.create.vm.processing=Creating VM.... label.action.create.volume=Create Volume -label.action.delete.IP.range.processing=Deleting IP Range.... -label.action.delete.IP.range=Delete IP Range -label.action.delete.ISO.processing=Deleting ISO.... -label.action.delete.ISO=Delete ISO -label.action.delete.account.processing=Deleting account.... +label.action.create.volume.processing=Creating Volume.... label.action.delete.account=Delete account -label.action.delete.cluster.processing=Deleting Cluster.... +label.action.delete.account.processing=Deleting account.... label.action.delete.cluster=Delete Cluster -label.action.delete.disk.offering.processing=Deleting Disk Offering.... +label.action.delete.cluster.processing=Deleting Cluster.... label.action.delete.disk.offering=Delete Disk Offering - -label.action.update.resource.count=Update Resource Count -label.action.update.resource.count.processing=Updating Resource Count.... - +label.action.delete.disk.offering.processing=Deleting Disk Offering.... label.action.delete.domain=Delete Domain label.action.delete.domain.processing=Deleting Domain.... - -label.action.delete.firewall.processing=Deleting Firewall.... label.action.delete.firewall=Delete firewall rule -label.action.delete.ingress.rule.processing=Deleting Ingress Rule.... +label.action.delete.firewall.processing=Deleting Firewall.... label.action.delete.ingress.rule=Delete Ingress Rule -label.action.delete.load.balancer.processing=Deleting Load Balancer.... +label.action.delete.ingress.rule.processing=Deleting Ingress Rule.... +label.action.delete.IP.range=Delete IP Range +label.action.delete.IP.range.processing=Deleting IP Range.... +label.action.delete.ISO=Delete ISO +label.action.delete.ISO.processing=Deleting ISO.... label.action.delete.load.balancer=Delete load balancer rule -label.action.edit.network.processing=Editing Network.... -label.action.edit.network=Edit Network -label.action.delete.network.processing=Deleting Network.... +label.action.delete.load.balancer.processing=Deleting Load Balancer.... label.action.delete.network=Delete Network -label.action.delete.pod.processing=Deleting Pod.... +label.action.delete.network.processing=Deleting Network.... +label.action.delete.nexusVswitch=Delete Nexus 1000v +label.action.delete.physical.network=Delete physical network label.action.delete.pod=Delete Pod -label.action.delete.primary.storage.processing=Deleting Primary Storage.... +label.action.delete.pod.processing=Deleting Pod.... label.action.delete.primary.storage=Delete Primary Storage -label.action.delete.secondary.storage.processing=Deleting Secondary Storage.... +label.action.delete.primary.storage.processing=Deleting Primary Storage.... label.action.delete.secondary.storage=Delete Secondary Storage -label.action.delete.security.group.processing=Deleting Security Group.... +label.action.delete.secondary.storage.processing=Deleting Secondary Storage.... label.action.delete.security.group=Delete Security Group -label.action.delete.service.offering.processing=Deleting Service Offering.... +label.action.delete.security.group.processing=Deleting Security Group.... label.action.delete.service.offering=Delete Service Offering -label.action.delete.snapshot.processing=Deleting Snapshot.... +label.action.delete.service.offering.processing=Deleting Service Offering.... label.action.delete.snapshot=Delete Snapshot -label.action.delete.template.processing=Deleting Template.... +label.action.delete.snapshot.processing=Deleting Snapshot.... +label.action.delete.system.service.offering=Delete System Service Offering label.action.delete.template=Delete Template -label.action.delete.user.processing=Deleting User.... +label.action.delete.template.processing=Deleting Template.... label.action.delete.user=Delete User -label.action.delete.volume.processing=Deleting Volume.... +label.action.delete.user.processing=Deleting User.... label.action.delete.volume=Delete Volume -label.action.delete.zone.processing=Deleting Zone.... +label.action.delete.volume.processing=Deleting Volume.... label.action.delete.zone=Delete Zone -label.action.destroy.instance.processing=Destroying Instance.... +label.action.delete.zone.processing=Deleting Zone.... label.action.destroy.instance=Destroy Instance -label.action.destroy.systemvm.processing=Destroying System VM.... +label.action.destroy.instance.processing=Destroying Instance.... label.action.destroy.systemvm=Destroy System VM -label.action.detach.disk.processing=Detaching Disk.... +label.action.destroy.systemvm.processing=Destroying System VM.... label.action.detach.disk=Detach Disk -label.action.detach.iso.processing=Detaching ISO.... +label.action.detach.disk.processing=Detaching Disk.... label.action.detach.iso=Detach ISO -label.action.disable.account.processing=Disabling account.... +label.action.detach.iso.processing=Detaching ISO.... label.action.disable.account=Disable account -label.action.disable.static.NAT.processing=Disabling Static NAT.... +label.action.disable.account.processing=Disabling account.... +label.action.disable.cluster=Disable Cluster +label.action.disable.cluster.processing=Disabling Cluster.... +label.action.disable.nexusVswitch=Disable Nexus 1000v +label.action.disable.physical.network=Disable physical network +label.action.disable.pod=Disable Pod +label.action.disable.pod.processing=Disabling Pod.... label.action.disable.static.NAT=Disable Static NAT -label.action.disable.user.processing=Disabling User.... +label.action.disable.static.NAT.processing=Disabling Static NAT.... label.action.disable.user=Disable User +label.action.disable.user.processing=Disabling User.... +label.action.disable.zone=Disable Zone +label.action.disable.zone.processing=Disabling Zone.... label.action.download.ISO=Download ISO label.action.download.template=Download Template -label.action.download.volume.processing=Downloading Volume.... label.action.download.volume=Download Volume -label.action.edit.ISO=Edit ISO +label.action.download.volume.processing=Downloading Volume.... label.action.edit.account=Edit account label.action.edit.disk.offering=Edit Disk Offering label.action.edit.domain=Edit Domain label.action.edit.global.setting=Edit Global Setting +label.action.edit.host=Edit Host label.action.edit.instance=Edit Instance +label.action.edit.ISO=Edit ISO +label.action.edit.network=Edit Network label.action.edit.network.offering=Edit Network Offering +label.action.edit.network.processing=Editing Network.... label.action.edit.pod=Edit Pod label.action.edit.primary.storage=Edit Primary Storage label.action.edit.resource.limits=Edit Resource Limits @@ -930,22 +166,37 @@ label.action.edit.service.offering=Edit Service Offering label.action.edit.template=Edit Template label.action.edit.user=Edit User label.action.edit.zone=Edit Zone -label.action.enable.account.processing=Enabling account.... label.action.enable.account=Enable account -label.action.enable.maintenance.mode.processing=Enabling Maintenance Mode.... +label.action.enable.account.processing=Enabling account.... +label.action.enable.cluster=Enable Cluster +label.action.enable.cluster.processing=Enabling Cluster.... label.action.enable.maintenance.mode=Enable Maintenance Mode -label.action.enable.static.NAT.processing=Enabling Static NAT.... +label.action.enable.maintenance.mode.processing=Enabling Maintenance Mode.... +label.action.enable.nexusVswitch=Enable Nexus 1000v +label.action.enable.physical.network=Enable physical network +label.action.enable.pod=Enable Pod +label.action.enable.pod.processing=Enabling Pod.... label.action.enable.static.NAT=Enable Static NAT -label.action.enable.user.processing=Enabling User.... +label.action.enable.static.NAT.processing=Enabling Static NAT.... label.action.enable.user=Enable User -label.action.force.reconnect.processing=Reconnecting.... +label.action.enable.user.processing=Enabling User.... +label.action.enable.zone=Enable Zone +label.action.enable.zone.processing=Enabling Zone.... label.action.force.reconnect=Force Reconnect -label.action.generate.keys.processing=Generate Keys.... +label.action.force.reconnect.processing=Reconnecting.... label.action.generate.keys=Generate Keys -label.action.lock.account.processing=Locking account.... +label.action.generate.keys.processing=Generate Keys.... +label.action.list.nexusVswitch=List Nexus 1000v label.action.lock.account=Lock account +label.action.lock.account.processing=Locking account.... +label.action.manage.cluster=Manage Cluster +label.action.manage.cluster.processing=Managing Cluster.... label.action.migrate.instance=Migrate Instance label.action.migrate.instance.processing=Migrating Instance.... +label.action.migrate.router=Migrate Router +label.action.migrate.router.processing=Migrating Router.... +label.action.migrate.systemvm=Migrate System VM +label.action.migrate.systemvm.processing=Migrating System VM.... label.action.reboot.instance.processing=Rebooting Instance.... label.action.reboot.instance=Reboot Instance label.action.reboot.router.processing=Rebooting Router.... @@ -953,15 +204,20 @@ label.action.reboot.router=Reboot Router label.action.reboot.systemvm.processing=Rebooting System VM.... label.action.reboot.systemvm=Reboot System VM label.action.recurring.snapshot=Recurring Snapshots +label.action.register.iso=Register ISO +label.action.register.template=Register template label.action.release.ip.processing=Releasing IP.... label.action.release.ip=Release IP label.action.remove.host.processing=Removing Host.... label.action.remove.host=Remove Host label.action.reset.password.processing=Resetting Password.... label.action.reset.password=Reset Password +label.action.resize.volume.processing=Resizing Volume.... +label.action.resize.volume=Resize Volume label.action.resource.limits=Resource limits label.action.restore.instance.processing=Restoring Instance.... label.action.restore.instance=Restore Instance +label.actions=Actions label.action.start.instance.processing=Starting Instance.... label.action.start.instance=Start Instance label.action.start.router.processing=Starting Router.... @@ -976,65 +232,124 @@ label.action.stop.systemvm.processing=Stopping System VM.... label.action.stop.systemvm=Stop System VM label.action.take.snapshot.processing=Taking Snapshot.... label.action.take.snapshot=Take Snapshot +label.action.unmanage.cluster.processing=Unmanaging Cluster.... +label.action.unmanage.cluster=Unmanage Cluster label.action.update.OS.preference.processing=Updating OS Preference.... label.action.update.OS.preference=Update OS Preference -label.actions=Actions +label.action.update.resource.count.processing=Updating Resource Count.... +label.action.update.resource.count=Update Resource Count +label.action.vmsnapshot.create=Take VM Snapshot +label.action.vmsnapshot.delete=Delete VM snapshot +label.action.vmsnapshot.revert=Revert to VM snapshot +label.activate.project=Activate Project label.active.sessions=Active Sessions label.add.account=Add Account +label.add.accounts=Add accounts +label.add.accounts.to=Add accounts to +label.add.account.to.project=Add account to project +label.add.ACL=Add ACL +label.add=Add +label.add.BigSwitchVns.device=Add BigSwitch Vns Controller +label.add.by=Add by label.add.by.cidr=Add By CIDR label.add.by.group=Add By Group label.add.cluster=Add Cluster +label.add.compute.offering=Add compute offering label.add.direct.iprange=Add Direct Ip Range label.add.disk.offering=Add Disk Offering label.add.domain=Add Domain +label.add.egress.rule=Add egress rule +label.add.F5.device=Add F5 device label.add.firewall=Add firewall rule +label.add.guest.network=Add guest network label.add.host=Add Host -label.add.ingress.rule=Add Ingress Rule -label.add.ip.range=Add IP Range -label.add.load.balancer=Add Load Balancer -label.add.more=Add More -label.add.network=Add Network -label.add.pod=Add Pod -label.add.primary.storage=Add Primary Storage -label.add.secondary.storage=Add Secondary Storage -label.add.security.group=Add Security Group -label.add.service.offering=Add Service Offering -label.add.template=Add Template -label.add.user=Add User -label.add.vlan=Add VLAN -label.add.volume=Add Volume -label.add.zone=Add Zone -label.add=Add +label.adding=Adding label.adding.cluster=Adding Cluster label.adding.failed=Adding Failed label.adding.pod=Adding Pod label.adding.processing=Adding.... +label.add.ingress.rule=Add Ingress Rule label.adding.succeeded=Adding Succeeded label.adding.user=Adding User label.adding.zone=Adding Zone -label.adding=Adding +label.add.ip.range=Add IP Range label.additional.networks=Additional Networks +label.add.load.balancer=Add Load Balancer +label.add.more=Add More +label.add.netScaler.device=Add Netscaler device +label.add.network.ACL=Add network ACL +label.add.network=Add Network +label.add.network.device=Add Network Device +label.add.network.offering=Add network offering +label.add.new.F5=Add new F5 +label.add.new.gateway=Add new gateway +label.add.new.NetScaler=Add new NetScaler +label.add.new.SRX=Add new SRX +label.add.new.tier=Add new tier +label.add.NiciraNvp.device=Add Nvp Controller +label.add.physical.network=Add physical network +label.add.pod=Add Pod +label.add.port.forwarding.rule=Add port forwarding rule +label.add.primary.storage=Add Primary Storage +label.add.region=Add Region +label.add.resources=Add Resources +label.add.route=Add route +label.add.rule=Add rule +label.add.secondary.storage=Add Secondary Storage +label.add.security.group=Add Security Group +label.add.service.offering=Add Service Offering +label.add.SRX.device=Add SRX device +label.add.static.nat.rule=Add static NAT rule +label.add.static.route=Add static route +label.add.system.service.offering=Add System Service Offering +label.add.template=Add Template +label.add.to.group=Add to group +label.add.user=Add User +label.add.vlan=Add VLAN +label.add.vm=Add VM +label.add.vms=Add VMs +label.add.vms.to.lb=Add VM(s) to load balancer rule +label.add.VM.to.tier=Add VM to tier +label.add.volume=Add Volume +label.add.vpc=Add VPC +label.add.vpn.customer.gateway=Add VPN Customer Gateway +label.add.VPN.gateway=Add VPN Gateway +label.add.vpn.user=Add VPN user +label.add.zone=Add Zone label.admin.accounts=Admin Accounts label.admin=Admin +label.advanced=Advanced label.advanced.mode=Advanced Mode label.advanced.search=Advance Search -label.advanced=Advanced +label.agent.password=Agent Password +label.agent.username=Agent Username +label.agree=Agree label.alert=Alert label.algorithm=Algorithm label.allocated=Allocated +label.allocation.state=Allocation State label.api.key=API Key -label.assign.to.load.balancer=Assigning instance to load balancer +label.apply=Apply label.assign=Assign +label.assign.to.load.balancer=Assigning instance to load balancer +label.associated.network=Associated Network label.associated.network.id=Associated Network ID label.attached.iso=Attached ISO -label.availability.zone=Availability Zone +label.author.email=Author e-mail +label.author.name=Author name label.availability=Availability -label.available.public.ips=Available Public IP Addresses +label.availability.zone=Availability Zone label.available=Available +label.available.public.ips=Available Public IP Addresses label.back=Back +label.bandwidth=Bandwidth +label.basic=Basic label.basic.mode=Basic Mode +label.bigswitch.controller.address=BigSwitch Vns Controller Address label.bootable=Bootable +label.broadcast.domain.range=Broadcast domain range label.broadcast.domain.type=Broadcast Domain Type +label.broadcast.uri=Broadcast URI label.by.account=By Account label.by.availability=By Availability label.by.domain=By Domain @@ -1044,30 +359,64 @@ label.by.pod=By Pod label.by.role=By Role label.by.start.date=By Start Date label.by.state=By State -label.by.traffic.type=By Traffic Type -label.by.type.id=By Type ID -label.by.type=By Type -label.by.zone=By Zone label.bytes.received=Bytes Received label.bytes.sent=Bytes Sent +label.by.traffic.type=By Traffic Type +label.by.type=By Type +label.by.type.id=By Type ID +label.by.zone=By Zone label.cancel=Cancel +label.capacity=Capacity label.certificate=Certificate -label.privatekey=PKCS#8 Private Key -label.domain.suffix=DNS Domain Suffix (i.e., xyz.com) +label.change.service.offering=Change service offering +label.change.value=Change value label.character=Character +label.checksum=MD5 checksum label.cidr.account=CIDR or Account/Security Group +label.cidr=CIDR +label.CIDR.list=CIDR list +label.cidr.list=Source CIDR +label.CIDR.of.destination.network=CIDR of destination network +label.clean.up=Clean up +label.clear.list=Clear list label.close=Close label.cloud.console=Cloud Management Console label.cloud.managed=Cloud.com Managed -label.cluster.type=Cluster Type label.cluster=Cluster +label.cluster.name=Cluster Name +label.clusters=Clusters +label.cluster.type=Cluster Type +label.clvm=CLVM label.code=Code +label.community=Community +label.compute.and.storage=Compute and Storage +label.compute=Compute +label.compute.offering=Compute offering +label.compute.offerings=Compute offerings +label.configuration=Configuration +label.configure=Configure +label.configure.network.ACLs=Configure Network ACLs +label.configure.vpc=Configure VPC label.confirmation=Confirmation -label.cpu.allocated.for.VMs=CPU Allocated for VMs +label.confirm.password=Confirm password +label.congratulations=Congratulations! +label.conserve.mode=Conserve mode +label.console.proxy=Console proxy +label.continue.basic.install=Continue with basic installation +label.continue=Continue +label.corrections.saved=Corrections saved label.cpu.allocated=CPU Allocated -label.cpu.utilized=CPU Utilized +label.cpu.allocated.for.VMs=CPU Allocated for VMs +label.CPU.cap=CPU Cap label.cpu=CPU +label.cpu.limits=CPU limits +label.cpu.mhz=CPU (in MHz) +label.cpu.utilized=CPU Utilized +label.created.by.system=Created by system label.created=Created +label.create.project=Create project +label.create.template=Create template +label.create.VPN.connection=Create VPN Connection label.cross.zones=Cross Zones label.custom.disk.size=Custom Disk Size label.daily=Daily @@ -1075,47 +424,111 @@ label.data.disk.offering=Data Disk Offering label.date=Date label.day.of.month=Day of Month label.day.of.week=Day of Week +label.dead.peer.detection=Dead Peer Detection +label.decline.invitation=Decline invitation +label.dedicated=Dedicated +label.default=Default +label.default.use=Default Use +label.default.view=Default View +label.delete.BigSwitchVns=Remove BigSwitch Vns Controller label.delete=Delete +label.delete.F5=Delete F5 +label.delete.gateway=delete gateway +label.delete.NetScaler=Delete NetScaler +label.delete.NiciraNvp=Remove Nvp Controller +label.delete.project=Delete project +label.delete.SRX=Delete SRX +label.delete.VPN.connection=delete VPN connection +label.delete.VPN.customer.gateway=delete VPN Customer Gateway +label.delete.VPN.gateway=delete VPN Gateway +label.delete.vpn.user=Delete VPN user label.deleting.failed=Deleting Failed label.deleting.processing=Deleting.... label.description=Description +label.destination.physical.network.id=Destination physical network ID +label.destination.zone=Destination Zone +label.destroy=Destroy +label.destroy.router=Destroy router label.detaching.disk=Detaching Disk label.details=Details label.device.id=Device ID +label.devices=Devices +label.dhcp=DHCP +label.DHCP.server.type=DHCP Server Type +label.direct.ips=Shared Network IPs label.disabled=Disabled +label.disable.provider=Disable provider +label.disable.vpn=Disable VPN label.disabling.vpn.access=Disabling VPN Access label.disk.allocated=Disk Allocated label.disk.offering=Disk Offering -label.disk.size.gb=Disk Size (in GB) label.disk.size=Disk Size +label.disk.size.gb=Disk Size (in GB) label.disk.total=Disk Total label.disk.volume=Disk Volume +label.display.name=Display name label.display.text=Display Text label.dns.1=DNS 1 label.dns.2=DNS 2 +label.dns=DNS +label.DNS.domain.for.guest.networks=DNS domain for Guest Networks label.domain.admin=Domain Admin +label.domain=Domain label.domain.id=Domain ID label.domain.name=Domain Name -label.domain=Domain +label.domain.router=Domain router +label.domain.suffix=DNS Domain Suffix (i.e., xyz.com) +label.done=Done label.double.quotes.are.not.allowed=Double quotes are not allowed label.download.progress=Download Progress +label.drag.new.position=Drag to new position label.edit=Edit +label.edit.lb.rule=Edit LB rule +label.edit.network.details=Edit network details +label.edit.project.details=Edit project details +label.edit.tags=Edit tags +label.edit.traffic.type=Edit traffic type +label.edit.vpc=Edit VPC +label.egress.rule=Egress rule +label.egress.rules=Egress rules +label.elastic=Elastic +label.elastic.IP=Elastic IP +label.elastic.LB=Elastic LB label.email=Email +label.enable.provider=Enable provider +label.enable.s3=Enable S3-backed Secondary Storage +label.enable.swift=Enable Swift +label.enable.vpn=Enable VPN label.enabling.vpn.access=Enabling VPN Access label.enabling.vpn=Enabling VPN -label.end.port=End Port +label.end.IP=End IP +label.endpoint=Endpoint label.endpoint.or.operation=Endpoint or Operation +label.end.port=End Port +label.end.reserved.system.IP=End Reserved system IP +label.end.vlan=End Vlan +label.enter.token=Enter token label.error.code=Error Code label.error=Error +label.ESP.encryption=ESP Encryption +label.ESP.hash=ESP Hash +label.ESP.lifetime=ESP Lifetime (second) +label.ESP.lifetime=ESP Lifetime(second) +label.ESP.policy=ESP policy label.esx.host=ESX/ESXi Host label.example=Example +label.external.link=External link +label.f5=F5 label.failed=Failed label.featured=Featured +label.fetch.latest=Fetch latest +label.filterBy=Filter by label.firewall=Firewall label.first.name=First Name label.format=Format label.friday=Friday label.full=Full +label.full.path=Full path label.gateway=Gateway label.general.alerts=General Alerts label.generating.url=Generating URL @@ -1123,75 +536,157 @@ label.go.step.2=Go to Step 2 label.go.step.3=Go to Step 3 label.go.step.4=Go to Step 4 label.go.step.5=Go to Step 5 -label.group.optional=Group (Optional) label.group=Group +label.group.optional=Group (Optional) label.guest.cidr=Guest CIDR +label.guest.end.ip=Guest end IP label.guest.gateway=Guest Gateway -label.guest.ip.range=Guest IP Range +label.guest=Guest label.guest.ip=Guest IP Address +label.guest.ip.range=Guest IP Range label.guest.netmask=Guest Netmask +label.guest.networks=Guest networks +label.guest.start.ip=Guest start IP +label.guest.traffic=Guest Traffic +label.guest.type=Guest Type label.ha.enabled=HA Enabled label.help=Help +label.hide.ingress.rule=Hide Ingress Rule +label.hints=Hints label.host.alerts=Host Alerts -label.host.name=Host Name label.host=Host +label.host.MAC=Host MAC +label.host.name=Host Name label.hosts=Hosts +label.host.tags=Host Tags label.hourly=Hourly -label.hypervisor.type=Hypervisor Type +label.hypervisor.capabilities=Hypervisor capabilities label.hypervisor=Hypervisor +label.hypervisor.type=Hypervisor Type +label.hypervisor.version=Hypervisor version label.id=ID +label.IKE.DH=IKE DH +label.IKE.encryption=IKE Encryption +label.IKE.hash=IKE Hash +label.IKE.lifetime=IKE lifetime (second) +label.IKE.lifetime=IKE Lifetime (second) +label.IKE.policy=IKE policy label.info=Info label.ingress.rule=Ingress Rule label.initiated.by=Initiated By +label.installWizard.addClusterIntro.subtitle=What is a cluster? +label.installWizard.addClusterIntro.title=Let’s add a cluster +label.installWizard.addHostIntro.subtitle=What is a host? +label.installWizard.addHostIntro.title=Let’s add a host +label.installWizard.addPodIntro.subtitle=What is a pod? +label.installWizard.addPodIntro.title=Let’s add a pod +label.installWizard.addPrimaryStorageIntro.subtitle=What is primary storage? +label.installWizard.addPrimaryStorageIntro.title=Let’s add primary storage +label.installWizard.addSecondaryStorageIntro.subtitle=What is secondary storage? +label.installWizard.addSecondaryStorageIntro.title=Let’s add secondary storage +label.installWizard.addZoneIntro.subtitle=What is a zone? +label.installWizard.addZoneIntro.title=Let’s add a zone +label.installWizard.addZone.title=Add zone +label.installWizard.click.launch=Click the launch button. +label.installWizard.subtitle=This tour will aid you in setting up your CloudStack™ installation +label.installWizard.title=Hello and Welcome to CloudStack™ +label.instance=Instance label.instance.limits=Instance Limits label.instance.name=Instance Name -label.instance=Instance label.instances=Instances label.internal.dns.1=Internal DNS 1 label.internal.dns.2=Internal DNS 2 +label.internal.name=Internal name label.interval.type=Interval Type +label.introduction.to.cloudstack=Introduction to CloudStack™ label.invalid.integer=Invalid Integer label.invalid.number=Invalid Number +label.invitations=Invitations +label.invited.accounts=Invited accounts +label.invite=Invite +label.invite.to=Invite to label.ip.address=IP Address +label.ipaddress=IP Address label.ip.allocations=IP Allocations +label.ip=IP label.ip.limits=Public IP Limits label.ip.or.fqdn=IP or FQDN label.ip.range=IP Range -label.ip=IP +label.ip.ranges=IP Ranges +label.IPsec.preshared.key=IPsec Preshared-Key label.ips=IPs -label.is.default=Is Default -label.is.shared=Is Shared -label.is.system=Is System label.iscsi=iSCSI +label.is.default=Is Default label.iso.boot=ISO Boot label.iso=ISO +label.isolated.networks=Isolated networks +label.isolation.method=Isolation method label.isolation.mode=Isolation Mode +label.isolation.uri=Isolation URI +label.is.redundant.router=Redundant +label.is.shared=Is Shared +label.is.system=Is System +label.item.listing=Item listing label.keep=Keep +label.keyboard.type=Keyboard type +label.key=Key +label.kvm.traffic.label=KVM traffic label +label.label=Label +label.lang.brportugese=Brazilian Portugese label.lang.chinese=Chinese (Simplified) label.lang.english=English +label.lang.french=French label.lang.japanese=Japanese -label.lang.spanish=Spanish label.lang.korean=Korean label.lang.russian=Russian -label.lang.french=French -label.lang.brportugese=Brazilian Portugese +label.lang.spanish=Spanish label.last.disconnected=Last Disconnected label.last.name=Last Name +label.latest.events=Latest events +label.launch=Launch +label.launch.vm=Launch VM +label.launch.zone=Launch zone +label.LB.isolation=LB isolation +label.least.connections=Least connections label.level=Level label.linklocal.ip=Link Local IP Adddress label.load.balancer=Load Balancer +label.load.balancing=Load Balancing +label.load.balancing.policies=Load balancing policies label.loading=Loading label.local=Local +label.local.storage.enabled=Local storage enabled label.local.storage.enabled=Local Storage Enabled +label.local.storage=Local Storage label.login=Login label.logout=Logout label.lun=LUN +label.LUN.number=LUN # +label.make.project.owner=Make account project owner label.manage=Manage +label.management.ips=Management IP Addresses +label.management=Management +label.manage.resources=Manage Resources +label.max.cpus=Max. CPU cores +label.max.guest.limit=Max guest limit label.maximum=Maximum +label.max.memory=Max. memory (MiB) +label.max.networks=Max. networks +label.max.primary.storage=Max. primary (GiB) +label.max.public.ips=Max. public IPs +label.max.secondary.storage=Max. secondary (GiB) +label.max.snapshots=Max. snapshots +label.max.templates=Max. templates +label.max.vms=Max. user VMs +label.max.volumes=Max. volumes +label.max.vpcs=Max. VPCs +label.may.continue=You may now continue. label.memory.allocated=Memory Allocated +label.memory.limits=Memory limits (MiB) +label.memory.mb=Memory (in MB) +label.memory=Memory label.memory.total=Memory Total label.memory.used=Memory Used -label.memory=Memory label.menu.accounts=Accounts label.menu.alerts=Alerts label.menu.all.accounts=All Accounts @@ -1207,6 +702,7 @@ label.menu.events=Events label.menu.featured.isos=Featured ISOs label.menu.featured.templates=Featured Templates label.menu.global.settings=Global Settings +label.menu.infrastructure=Infrastructure label.menu.instances=Instances label.menu.ipaddresses=IP Addresses label.menu.isos=ISOs @@ -1214,65 +710,112 @@ label.menu.my.accounts=My Accounts label.menu.my.instances=My Instances label.menu.my.isos=My ISOs label.menu.my.templates=My Templates -label.menu.network.offerings=Network Offerings label.menu.network=Network +label.menu.network.offerings=Network Offerings label.menu.physical.resources=Physical Resources +label.menu.regions=Regions label.menu.running.instances=Running Instances label.menu.security.groups=Security Groups label.menu.service.offerings=Service Offerings label.menu.snapshots=Snapshots label.menu.stopped.instances=Stopped Instances label.menu.storage=Storage -label.menu.system.vms=System VMs +label.menu.system.service.offerings=System Offerings label.menu.system=System +label.menu.system.vms=System VMs label.menu.templates=Templates label.menu.virtual.appliances=Virtual Appliances label.menu.virtual.resources=Virtual Resources label.menu.volumes=Volumes +label.migrate.instance.to.host=Migrate instance to another host label.migrate.instance.to=Migrate instance to +label.migrate.instance.to.ps=Migrate instance to another primary storage +label.migrate.router.to=Migrate Router to +label.migrate.systemvm.to=Migrate System VM to +label.migrate.to.host=Migrate to host +label.migrate.to.storage=Migrate to storage +label.migrate.volume=Migrate volume to another primary storage label.minimum=Minimum label.minute.past.hour=minute(s) Past the Hour label.monday=Monday label.monthly=Monthly label.more.templates=More Templates +label.move.down.row=Move down one row +label.move.to.bottom=Move to bottom +label.move.to.top=Move to top +label.move.up.row=Move up one row label.my.account=My Account -label.name.optional=Name (Optional) +label.my.network=My network +label.my.templates=My templates label.name=Name +label.name.optional=Name (Optional) +label.nat.port.range=NAT Port Range label.netmask=Netmask +label.netScaler=NetScaler +label.network.ACL=Network ACL +label.network.ACLs=Network ACLs +label.network.ACL.total=Network ACL Total label.network.desc=Network Desc +label.network.device=Network Device +label.network.device.type=Network Device Type label.network.domain=Network Domain +label.network.domain.text=Network domain label.network.id=Network ID +label.networking.and.security=Networking and security +label.network.label.display.for.blank.value=Use default gateway label.network.name=Network Name +label.network=Network label.network.offering.display.text=Network Offering Display Text label.network.offering.id=Network Offering ID label.network.offering.name=Network Offering Name label.network.offering=Network Offering -label.network.rate=Network Rate label.network.rate.megabytes=Network Rate (Mb/s) +label.network.rate=Network Rate label.network.read=Network Read +label.network.service.providers=Network Service Providers +label.networks=Networks label.network.type=Network Type label.network.write=Network Write -label.network=Network +label.new=New label.new.password=New Password +label.new.project=New Project +label.new.vm=New VM label.next=Next +label.nexusVswitch=Nexus 1000v +label.nfs=NFS label.nfs.server=NFS Server label.nfs.storage=NFS Storage -label.nfs=NFS +label.nic.adapter.type=NIC adapter type +label.nicira.controller.address=Controller Address +label.nicira.l3gatewayserviceuuid=L3 Gateway Service Uuid +label.nicira.transportzoneuuid=Transport Zone Uuid label.nics=NICs label.no.actions=No Available Actions label.no.alerts=No Recent Alerts +label.no.data=No data to show label.no.errors=No Recent Errors label.no.isos=No available ISOs label.no.items=No Available Items -label.no.security.groups=No Available Security Groups -label.no.thanks=No Thanks -label.no=No label.none=None +label.no=No +label.no.security.groups=No Available Security Groups label.not.found=Not Found +label.no.thanks=No thanks +label.no.thanks=No Thanks +label.notifications=Notifications +label.number.of.clusters=Number of Clusters +label.number.of.hosts=Number of Hosts +label.number.of.pods=Number of Pods +label.number.of.system.vms=Number of System VMs +label.number.of.virtual.routers=Number of Virtual Routers +label.number.of.zones=Number of Zones label.num.cpu.cores=# of CPU Cores label.numretries=Number of Retries +label.ocfs2=OCFS2 label.offer.ha=Offer HA +label.ok=OK label.optional=Optional +label.order=Order label.os.preference=OS Preference label.os.type=OS Type label.owned.public.ips=Owned Public IP Addresses @@ -1282,110 +825,259 @@ label.parent.domain=Parent Domain label.password.enabled=Password Enabled label.password=Password label.path=Path +label.perfect.forward.secrecy=Perfect Forward Secrecy +label.physical.network.ID=Physical network ID +label.physical.network=Physical Network +label.PING.CIFS.password=PING CIFS password +label.PING.CIFS.username=PING CIFS username +label.PING.dir=PING Directory +label.PING.storage.IP=PING storage IP +label.please.specify.netscaler.info=Please specify Netscaler info label.please.wait=Please Wait +label.plugin.details=Plugin details +label.plugins=Plugins +label.pod.name=Pod name label.pod=Pod +label.pods=Pods +label.port.forwarding.policies=Port forwarding policies label.port.forwarding=Port Forwarding label.port.range=Port Range +label.PreSetup=PreSetup +label.previous=Previous label.prev=Prev label.primary.allocated=Primary Storage Allocated label.primary.network=Primary Network +label.primary.storage.count=Primary Storage Pools +label.primary.storage.limits=Primary Storage limits (GiB) label.primary.storage=Primary Storage label.primary.used=Primary Storage Used +label.private.Gateway=Private Gateway label.private.interface=Private Interface -label.private.ip.range=Private IP Range label.private.ip=Private IP Address +label.private.ip.range=Private IP Range label.private.ips=Private IP Addresses +label.privatekey=PKCS#8 Private Key +label.private.network=Private network label.private.port=Private Port label.private.zone=Private Zone +label.project.dashboard=Project dashboard +label.project.id=Project ID +label.project.invite=Invite to project +label.project.name=Project name +label.project=Project +label.projects=Projects +label.project.view=Project View label.protocol=Protocol +label.providers=Providers label.public.interface=Public Interface label.public.ip=Public IP Address label.public.ips=Public IP Addresses +label.public.network=Public network label.public.port=Public Port -label.public.zone=Public Zone label.public=Public +label.public.traffic=Public traffic +label.public.zone=Public Zone +label.purpose=Purpose +label.Pxe.server.type=Pxe Server Type +label.quickview=Quickview +label.reboot=Reboot label.recent.errors=Recent Errors +label.redundant.router.capability=Redundant router capability +label.redundant.router=Redundant Router +label.redundant.state=Redundant state label.refresh=Refresh +label.region=Region label.related=Related +label.remind.later=Remind me later +label.remove.ACL=Remove ACL +label.remove.egress.rule=Remove egress rule label.remove.from.load.balancer=Removing instance from load balancer +label.remove.ingress.rule=Remove ingress rule +label.remove.ip.range=Remove IP range +label.remove.pf=Remove port forwarding rule +label.remove.project.account=Remove account from project +label.remove.project.account=Remove project account +label.remove.region=Remove Region +label.remove.rule=Remove rule +label.remove.static.nat.rule=Remove static NAT rule +label.remove.static.route=Remove static route +label.remove.tier=Remove tier +label.remove.vm.from.lb=Remove VM from load balancer rule +label.remove.vpc=remove VPC +label.removing=Removing label.removing.user=Removing User label.required=Required +label.reserved.system.gateway=Reserved system gateway label.reserved.system.ip=Reserved System IP +label.reserved.system.netmask=Reserved system netmask +label.reset.VPN.connection=Reset VPN connection +label.resize.new.offering.id=New Offering +label.resize.new.size=New Size(GB) +label.resize.shrink.ok=Shrink OK label.resource.limits=Resource Limits label.resource=Resource label.resources=Resources +label.resource.state=Resource state +label.restart.network=Restart network +label.restart.required=Restart required +label.restart.vpc=restart VPC +label.restore=Restore +label.review=Review +label.revoke.project.invite=Revoke invitation label.role=Role +label.root.disk.controller=Root disk controller label.root.disk.offering=Root Disk Offering +label.round.robin=Round-robin +label.rules=Rules label.running.vms=Running VMs +label.s3.access_key=Access Key +label.s3.bucket=Bucket +label.s3.connection_timeout=Connection Timeout +label.s3.endpoint=Endpoint +label.s3.max_error_retry=Max Error Retry +label.s3.secret_key=Secret Key +label.s3.socket_timeout=Socket Timeout +label.s3.use_https=Use HTTPS label.saturday=Saturday +label.save.and.continue=Save and continue label.save=Save label.saving.processing=Saving.... label.scope=Scope label.search=Search +label.secondary.storage.count=Secondary Storage Pools +label.secondary.storage.limits=Secondary Storage limits (GiB) label.secondary.storage=Secondary Storage +label.secondary.storage.vm=Secondary storage VM label.secondary.used=Secondary Storage Used label.secret.key=Secret Key label.security.group.name=Security Group Name label.security.group=Security Group label.security.groups.enabled=Security Groups Enabled label.security.groups=Security Groups +label.select.a.template=Select a template +label.select.a.zone=Select a zone +label.select.instance=Select instance +label.select.instance.to.attach.volume.to=Select instance to attach volume to +label.select.iso.or.template=Select ISO or template +label.select.offering=Select offering +label.select.project=Select Project +label.select=Select +label.select.tier=Select Tier +label.select-view=Select view +label.select.vm.for.static.nat=Select VM for static NAT label.sent=Sent label.server=Server +label.service.capabilities=Service Capabilities label.service.offering=Service Offering -label.system.service.offering=System Service Offering label.session.expired=Session Expired +label.setup.network=Setup Network +label.setup=Setup +label.setup.zone=Setup Zone +label.set.up.zone.type=Set up zone type +label.SharedMountPoint=SharedMountPoint label.shared=Shared +label.show.ingress.rule=Show Ingress Rule +label.shutdown.provider=Shutdown provider +label.site.to.site.VPN=Site-to-site VPN label.size=Size +label.skip.guide=I have used CloudStack before, skip this guide label.snapshot.limits=Snapshot Limits label.snapshot.name=Snapshot Name -label.snapshot.s=Snapshot (s) label.snapshot.schedule=Setup Recurring Snapshot label.snapshot=Snapshot +label.snapshot.s=Snapshot (s) label.snapshots=Snapshots label.source.nat=Source NAT +label.source=Source +label.specify.IP.ranges=Specify IP ranges label.specify.vlan=Specify VLAN +label.SR.name = SR Name-Label +label.srx=SRX +label.start.IP=Start IP label.start.port=Start Port +label.start.reserved.system.IP=Start Reserved system IP +label.start.vlan=Start Vlan label.state=State -label.static.nat.to=Static NAT to +label.static.nat.enabled=Static NAT Enabled label.static.nat=Static NAT +label.static.nat.to=Static NAT to +label.static.nat.vm.details=Static NAT VM Details label.statistics=Statistics label.status=Status -label.step.1.title=Step 1: Select a Template label.step.1=Step 1 -label.step.2.title=Step 2: Service Offering +label.step.1.title=Step 1: Select a Template label.step.2=Step 2 -label.step.3.title=Step 3: Select a Disk Offering +label.step.2.title=Step 2: Service Offering label.step.3=Step 3 -label.step.4.title=Step 4: Network +label.step.3.title=Step 3: Select a Disk Offering label.step.4=Step 4 -label.step.5.title=Step 5: Review +label.step.4.title=Step 4: Network label.step.5=Step 5 +label.step.5.title=Step 5: Review +label.stickiness=Stickiness +label.sticky.cookie-name=Cookie name +label.sticky.domain=Domain +label.sticky.expire=Expires +label.sticky.holdtime=Hold time +label.sticky.indirect=Indirect +label.sticky.length=Length +label.sticky.mode=Mode +label.sticky.nocache=No cache +label.sticky.postonly=Post only +label.sticky.prefix=Prefix +label.sticky.request-learn=Request learn +label.sticky.tablesize=Table size label.stopped.vms=Stopped VMs -label.storage.type=Storage Type +label.stop=Stop label.storage=Storage +label.storage.tags=Storage Tags +label.storage.traffic=Storage Traffic +label.storage.type=Storage Type +label.subdomain.access=Subdomain Access label.submit=Submit label.submitted.by=[Submitted by: ] label.succeeded=Succeeded label.sunday=Sunday +label.super.cidr.for.guest.networks=Super CIDR for Guest Networks +label.supported.services=Supported Services +label.supported.source.NAT.type=Supported Source NAT type +label.suspend.project=Suspend Project label.system.capacity=System Capacity -label.system.vm.type=System VM Type -label.system.vm=System VM +label.system.offering=System Offering +label.system.service.offering=System Service Offering label.system.vms=System VMs +label.system.vm=System VM +label.system.vm.type=System VM Type +label.system.wide.capacity=System-wide capacity label.tagged=Tagged label.tags=Tags label.target.iqn=Target IQN +label.task.completed=Task completed label.template.limits=Template Limits label.template=Template +label.TFTP.dir=TFTP Directory label.theme.default=Default Theme label.theme.grey=Custom - Grey label.theme.lightblue=Custom - Light Blue label.thursday=Thursday -label.time.zone=Timezone -label.time=Time +label.tier.details=Tier details +label.tier=Tier label.timeout.in.second = Timeout(seconds) +label.timeout=Timeout +label.time=Time +label.time.zone=Timezone label.timezone=Timezone +label.token=Token label.total.cpu=Total CPU +label.total.CPU=Total CPU +label.total.hosts=Total Hosts +label.total.memory=Total Memory +label.total.of.ip=Total of IP Address +label.total.of.vm=Total of VM +label.total.storage=Total Storage label.total.vms=Total VMs +label.traffic.label=Traffic label +label.traffic.types=Traffic Types label.traffic.type=Traffic Type label.tuesday=Tuesday label.type.id=Type ID @@ -1393,39 +1085,77 @@ label.type=Type label.unavailable=Unavailable label.unlimited=Unlimited label.untagged=Untagged +label.update.project.resources=Update project resources label.update.ssl.cert= SSL Certificate label.update.ssl= SSL Certificate label.updating=Updating +label.upload=Upload +label.upload.volume=Upload volume label.url=URL label.usage.interface=Usage Interface label.used=Used -label.user=User label.username=Username label.users=Users +label.user=User +label.use.vm.ip=Use VM IP: label.value=Value +label.vcdcname=vCenter DC name label.vcenter.cluster=vCenter Cluster label.vcenter.datacenter=vCenter Datacenter label.vcenter.datastore=vCenter Datastore label.vcenter.host=vCenter Host label.vcenter.password=vCenter Password label.vcenter.username=vCenter Username +label.vcipaddress=vCenter IP Address label.version=Version -label.virtual.appliance=Virtual Appliance +label.view.all=View all +label.view.console=View console +label.viewing=Viewing +label.view.more=View more +label.view=View label.virtual.appliances=Virtual Appliances +label.virtual.appliance=Virtual Appliance +label.virtual.machines=Virtual machines label.virtual.network=Virtual Network +label.virtual.routers=Virtual Routers +label.virtual.router=Virtual Router label.vlan.id=VLAN ID label.vlan.range=VLAN Range +label.vlan=VLAN label.vm.add=Add Instance label.vm.destroy=Destroy -label.vm.reboot=Reboot -label.vm.start=Start -label.vm.stop=Stop +label.vm.display.name=VM display name +label.VMFS.datastore=VMFS datastore label.vmfs=VMFS +label.vm.name=VM name +label.vm.reboot=Reboot +label.VMs.in.tier=VMs in tier +label.vmsnapshot.current=isCurrent +label.vmsnapshot.memory=Snapshot memory +label.vmsnapshot.parentname=Parent +label.vmsnapshot.type=Type +label.vmsnapshot=VM Snapshots +label.vm.start=Start +label.vm.state=VM state +label.vm.stop=Stop label.vms=VMs +label.vmware.traffic.label=VMware traffic label +label.volgroup=Volume Group label.volume.limits=Volume Limits label.volume.name=Volume Name -label.volume=Volume label.volumes=Volumes +label.volume=Volume +label.vpc.id=VPC ID +label.VPC.router.details=VPC router details +label.vpc=VPC +label.VPN.connection=VPN Connection +label.vpn.customer.gateway=VPN Customer Gateway +label.VPN.customer.gateway=VPN Customer Gateway +label.VPN.gateway=VPN Gateway +label.vpn=VPN +label.vsmctrlvlanid=Control VLAN ID +label.vsmpktvlanid=Packet VLAN ID +label.vsmstoragevlanid=Storage VLAN ID label.vsphere.managed=vSphere Managed label.waiting=Waiting label.warn=Warn @@ -1433,130 +1163,297 @@ label.wednesday=Wednesday label.weekly=Weekly label.welcome.cloud.console=Welcome to Management Console label.welcome=Welcome +label.what.is.cloudstack=What is CloudStack™? +label.xen.traffic.label=XenServer traffic label label.yes=Yes +label.zone.details=Zone details label.zone.id=Zone ID +label.zone.name=Zone name label.zone.step.1.title=Step 1: Select a Network label.zone.step.2.title=Step 2: Add a Zone label.zone.step.3.title=Step 3: Add a Pod label.zone.step.4.title=Step 4: Add an IP range +label.zones=Zones +label.zone.type=Zone Type label.zone.wide=Zone-Wide +label.zoneWizard.trafficType.guest=Guest: Traffic between end-user virtual machines +label.zoneWizard.trafficType.management=Management: Traffic between CloudStack\'s internal resources, including any components that communicate with the Management Server, such as hosts and CloudStack system VMs +label.zoneWizard.trafficType.public=Public: Traffic between the internet and virtual machines in the cloud. +label.zoneWizard.trafficType.storage=Storage: Traffic between primary and secondary storage servers, such as VM templates and snapshots label.zone=Zone - -#VM snapshot label -label.vmsnapshot=VM Snapshots -label.vmsnapshot.type=Type -label.vmsnapshot.parentname=Parent -label.vmsnapshot.current=isCurrent -label.vmsnapshot.memory=Snapshot memory -message.action.vmsnapshot.delete=Please confirm that you want to delete this VM snapshot. -label.action.vmsnapshot.delete=Delete VM snapshot -label.action.vmsnapshot.revert=Revert to VM snapshot -message.action.vmsnapshot.revert=Revert VM snapshot -label.action.vmsnapshot.create=Take VM Snapshot - - - -#Messages +managed.state=Managed State +message.acquire.new.ip=Please confirm that you would like to acquire a new IP for this network. +message.acquire.new.ip.vpc=Please confirm that you would like to acquire a new IP for this VPC. message.acquire.public.ip=Please select a zone from which you want to acquire your new IP from. message.action.cancel.maintenance.mode=Please confirm that you want to cancel this maintenance. message.action.cancel.maintenance=Your host has been successfully canceled for maintenance. This process can take up to several minutes. -message.action.delete.ISO.for.all.zones=The ISO is used by all zones. Please confirm that you want to delete it from all zones. -message.action.delete.ISO=Please confirm that you want to delete this ISO. +message.action.change.service.warning.for.instance=Your instance must be stopped before attempting to change its current service offering. +message.action.change.service.warning.for.router=Your router must be stopped before attempting to change its current service offering. message.action.delete.cluster=Please confirm that you want to delete this cluster. message.action.delete.disk.offering=Please confirm that you want to delete this disk offering. message.action.delete.domain=Please confirm that you want to delete this domain. message.action.delete.external.firewall=Please confirm that you would like to remove this external firewall. Warning: If you are planning to add back the same external firewall, you must reset usage data on the device. message.action.delete.external.load.balancer=Please confirm that you would like to remove this external load balancer. Warning: If you are planning to add back the same external load balancer, you must reset usage data on the device. message.action.delete.ingress.rule=Please confirm that you want to delete this ingress rule. +message.action.delete.ISO.for.all.zones=The ISO is used by all zones. Please confirm that you want to delete it from all zones. +message.action.delete.ISO=Please confirm that you want to delete this ISO. message.action.delete.network=Please confirm that you want to delete this network. +message.action.delete.nexusVswitch=Please confirm that you want to delete this nexus 1000v +message.action.delete.physical.network=Please confirm that you want to delete this physical network message.action.delete.pod=Please confirm that you want to delete this pod. message.action.delete.primary.storage=Please confirm that you want to delete this primary storage. message.action.delete.secondary.storage=Please confirm that you want to delete this secondary storage. message.action.delete.security.group=Please confirm that you want to delete this security group. message.action.delete.service.offering=Please confirm that you want to delete this service offering. message.action.delete.snapshot=Please confirm that you want to delete this snapshot. +message.action.delete.system.service.offering=Please confirm that you want to delete this system service offering. message.action.delete.template.for.all.zones=The template is used by all zones. Please confirm that you want to delete it from all zones. message.action.delete.template=Please confirm that you want to delete this template. message.action.delete.volume=Please confirm that you want to delete this volume. message.action.delete.zone=Please confirm that you want to delete this zone. message.action.destroy.instance=Please confirm that you want to destroy this instance. message.action.destroy.systemvm=Please confirm that you want to destroy this System VM. +message.action.disable.cluster=Please confirm that you want to disable this cluster. +message.action.disable.nexusVswitch=Please confirm that you want to disable this nexus 1000v +message.action.disable.physical.network=Please confirm that you want to disable this physical network. +message.action.disable.pod=Please confirm that you want to disable this pod. message.action.disable.static.NAT=Please confirm that you want to disable static NAT. +message.action.disable.zone=Please confirm that you want to disable this zone. +message.action.download.iso=Please confirm that you want to download this ISO. +message.action.download.template=Please confirm that you want to download this template. +message.action.enable.cluster=Please confirm that you want to enable this cluster. message.action.enable.maintenance=Your host has been successfully prepared for maintenance. This process can take up to several minutes or longer depending on how many VMs are currently on this host. +message.action.enable.nexusVswitch=Please confirm that you want to enable this nexus 1000v +message.action.enable.physical.network=Please confirm that you want to enable this physical network. +message.action.enable.pod=Please confirm that you want to enable this pod. +message.action.enable.zone=Please confirm that you want to enable this zone. message.action.force.reconnect=Your host has been successfully forced to reconnect. This process can take up to several minutes. message.action.host.enable.maintenance.mode=Enabling maintenance mode will cause a live migration of all running instances on this host to any available host. message.action.instance.reset.password=Please confirm that you want to change the ROOT password for this virtual machine. +message.action.manage.cluster=Please confirm that you want to manage the cluster. message.action.primarystorage.enable.maintenance.mode=Warning: placing the primary storage into maintenance mode will cause all VMs using volumes from it to be stopped. Do you want to continue? message.action.reboot.instance=Please confirm that you want to reboot this instance. +message.action.reboot.router=All services provided by this virtual router will be interrupted. Please confirm that you want to reboot this router. message.action.reboot.systemvm=Please confirm that you want to reboot this system VM. message.action.release.ip=Please confirm that you want to release this IP. +message.action.remove.host=Please confirm that you want to remove this host. message.action.remove.host=Removing last/only host in cluster and reinstalling the host will destroy working environment/database on the host and render the VM Guests unuseable. +message.action.reset.password.off=Your instance currently does not support this feature. +message.action.reset.password.warning=Your instance must be stopped before attempting to change its current password. message.action.restore.instance=Please confirm that you want to restore this instance. message.action.start.instance=Please confirm that you want to start this instance. message.action.start.router=Please confirm that you want to start this router. message.action.start.systemvm=Please confirm that you want to start this system VM. message.action.stop.instance=Please confirm that you want to stop this instance. +message.action.stop.router=All services provided by this virtual router will be interrupted. Please confirm that you want to stop this router. message.action.stop.systemvm=Please confirm that you want to stop this system VM. message.action.take.snapshot=Please confirm that you want to take a snapshot of this volume. -message.add.cluster.zone=Add a hypervisor managed cluster for zone +message.action.unmanage.cluster=Please confirm that you want to unmanage the cluster. +message.action.vmsnapshot.delete=Please confirm that you want to delete this VM snapshot. +message.action.vmsnapshot.revert=Revert VM snapshot +message.activate.project=Are you sure you want to activate this project? message.add.cluster=Add a hypervisor managed cluster for zone , pod +message.add.cluster.zone=Add a hypervisor managed cluster for zone message.add.disk.offering=Please specify the following parameters to add a new disk offering +message.add.domain=Please specify the subdomain you want to create under this domain message.add.firewall=Add a firewall to zone +message.add.guest.network=Please confirm that you would like to add a guest network message.add.host=Please specify the following parameters to add a new host +message.adding.host=Adding host +message.adding.Netscaler.device=Adding Netscaler device +message.adding.Netscaler.provider=Adding Netscaler provider +message.add.ip.range=Add an IP range to public network in zone message.add.ip.range.direct.network=Add an IP range to direct network in zone message.add.ip.range.to.pod=

Add an IP range to pod:

-message.add.ip.range=Add an IP range to public network in zone +message.additional.networks.desc=Please select additional network(s) that your virtual instance will be connected to. message.add.load.balancer=Add a load balancer to zone +message.add.load.balancer.under.ip=The load balancer rule has been added under IP: message.add.network=Add a new network for zone: +message.add.new.gateway.to.vpc=Please specify the information to add a new gateway to this VPC. message.add.pod=Add a new pod for zone -message.add.primary.storage=Add a new Primary Storage for zone , pod +message.add.pod.during.zone.creation=Each zone must contain in one or more pods, and we will add the first pod now. A pod contains hosts and primary storage servers, which you will add in a later step. First, configure a range of reserved IP addresses for CloudStack's internal management traffic. The reserved IP range must be unique for each zone in the cloud. message.add.primary=Please specify the following parameters to add a new primary storage +message.add.primary.storage=Add a new Primary Storage for zone , pod +message.add.region=Please specify the required information to add a new region. message.add.secondary.storage=Add a new storage for zone message.add.service.offering=Please fill in the following data to add a new compute offering. +message.add.system.service.offering=Please fill in the following data to add a new system service offering. message.add.template=Please enter the following data to create your new template message.add.volume=Please fill in the following data to add a new volume. -message.additional.networks.desc=Please select additional network(s) that your virtual instance will be connected to. +message.add.VPN.gateway=Please confirm that you want to add a VPN Gateway message.advanced.mode.desc=Choose this network model if you wish to enable VLAN support. This network model provides the most flexibility in allowing administrators to provide custom network offerings such as providing firewall, vpn, or load balancer support as well as enabling direct vs virtual networking. message.advanced.security.group=Choose this if you wish to use security groups to provide guest VM isolation. message.advanced.virtual=Choose this if you wish to use zone-wide VLANs to provide guest VM isolation. +message.after.enable.s3=S3-backed Secondary Storage configured. Note: When you leave this page, you will not be able to re-configure S3 again. +message.after.enable.swift=Swift configured. Note: When you leave this page, you will not be able to re-configure Swift again. +message.alert.state.detected=Alert state detected message.allow.vpn.access=Please enter a username and password of the user that you want to allow VPN access. +message.apply.snapshot.policy=You have successfully updated your current snapshot policy. message.attach.iso.confirm=Please confirm that you want to attach the ISO to this virtual instance. message.attach.volume=Please fill in the following data to attach a new volume. If you are attaching a disk volume to a Windows based virtual machine, you will need to reboot the instance to see the attached disk. message.basic.mode.desc=Choose this network model if you do *not* want to enable any VLAN support. All virtual instances created under this network model will be assigned an IP directly from the network and security groups are used to provide security and segregation. message.change.offering.confirm=Please confirm that you wish to change the service offering of this virtual instance. +message.change.password=Please change your password. +message.configure.all.traffic.types=You have multiple physical networks; please configure labels for each traffic type by clicking on the Edit button. +message.configuring.guest.traffic=Configuring guest traffic +message.configuring.physical.networks=Configuring physical networks +message.configuring.public.traffic=Configuring public traffic +message.configuring.storage.traffic=Configuring storage traffic +message.confirm.action.force.reconnect=Please confirm that you want to force reconnect this host. +message.confirm.delete.F5=Please confirm that you would like to delete F5 +message.confirm.delete.NetScaler=Please confirm that you would like to delete NetScaler +message.confirm.delete.SRX=Please confirm that you would like to delete SRX +message.confirm.destroy.router=Please confirm that you would like to destroy this router +message.confirm.disable.provider=Please confirm that you would like to disable this provider +message.confirm.enable.provider=Please confirm that you would like to enable this provider +message.confirm.join.project=Please confirm you wish to join this project. +message.confirm.remove.IP.range=Please confirm that you would like to remove this IP range. +message.confirm.shutdown.provider=Please confirm that you would like to shutdown this provider message.copy.iso.confirm=Please confirm that you wish to copy your ISO to message.copy.template=Copy template XXX from zone to +message.create.template=Are you sure you want to create template? message.create.template.vm=Create VM from template message.create.template.volume=Please specify the following information before creating a template of your disk volume: . Creation of the template can range from several minutes to longer depending on the size of the volume. +message.creating.cluster=Creating cluster +message.creating.guest.network=Creating guest network +message.creating.physical.networks=Creating physical networks +message.creating.pod=Creating pod +message.creating.primary.storage=Creating primary storage +message.creating.secondary.storage=Creating secondary storage +message.creating.zone=Creating zone +message.decline.invitation=Are you sure you want to decline this project invitation? message.delete.account=Please confirm that you want to delete this account. +message.delete.gateway=Please confirm you want to delete the gateway +message.delete.project=Are you sure you want to delete this project? +message.delete.user=Please confirm that you would like to delete this user. +message.delete.VPN.connection=Please confirm that you want to delete VPN connection +message.delete.VPN.customer.gateway=Please confirm that you want to delete this VPN Customer Gateway +message.delete.VPN.gateway=Please confirm that you want to delete this VPN Gateway +message.desc.advanced.zone=For more sophisticated network topologies. This network model provides the most flexibility in defining guest networks and providing custom network offerings such as firewall, VPN, or load balancer support. +message.desc.basic.zone=Provide a single network where each VM instance is assigned an IP directly from the network. Guest isolation can be provided through layer-3 means such as security groups (IP address source filtering). +message.desc.cluster=Each pod must contain one or more clusters, and we will add the first cluster now. A cluster provides a way to group hosts. The hosts in a cluster all have identical hardware, run the same hypervisor, are on the same subnet, and access the same shared storage. Each cluster consists of one or more hosts and one or more primary storage servers. +message.desc.host=Each cluster must contain at least one host (computer) for guest VMs to run on, and we will add the first host now. For a host to function in CloudStack, you must install hypervisor software on the host, assign an IP address to the host, and ensure the host is connected to the CloudStack management server.

Give the host's DNS or IP address, the user name (usually root) and password, and any labels you use to categorize hosts. +message.desc.primary.storage=Each cluster must contain one or more primary storage servers, and we will add the first one now. Primary storage contains the disk volumes for all the VMs running on hosts in the cluster. Use any standards-compliant protocol that is supported by the underlying hypervisor. +message.desc.secondary.storage=Each zone must have at least one NFS or secondary storage server, and we will add the first one now. Secondary storage stores VM templates, ISO images, and VM disk volume snapshots. This server must be available to all hosts in the zone.

Provide the IP address and exported path. +message.desc.zone=A zone is the largest organizational unit in CloudStack, and it typically corresponds to a single datacenter. Zones provide physical isolation and redundancy. A zone consists of one or more pods (each of which contains hosts and primary storage servers) and a secondary storage server which is shared by all pods in the zone. +message.detach.disk=Are you sure you want to detach this disk? message.detach.iso.confirm=Please confirm that you want to detach the ISO from this virtual instance. message.disable.account=Please confirm that you want to disable this account. By disabling the account, all users for this account will no longer have access to their cloud resources. All running virtual machines will be immediately shut down. +message.disable.snapshot.policy=You have successfully disabled your current snapshot policy. +message.disable.user=Please confirm that you would like to disable this user. message.disable.vpn.access=Please confirm that you want to disable VPN Access. +message.disable.vpn=Are you sure you want to disable VPN? message.download.ISO=Please click 00000 to download ISO message.download.template=Please click 00000 to download template +message.download.volume.confirm=Please confirm that you want to download this volume message.download.volume=Please click 00000 to download volume +message.edit.account=Edit ("-1" indicates no limit to the amount of resources create) message.edit.confirm=Please confirm that your changes before clicking "Save". message.edit.limits=Please specify limits to the following resources. A "-1" indicates no limit to the amount of resources create. +message.edit.traffic.type=Please specify the traffic label you want associated with this traffic type. message.enable.account=Please confirm that you want to enable this account. -message.enable.vpn.access=VPN is currently disabled for this IP Address. Would you like to enable VPN access? message.enabled.vpn.ip.sec=Your IPSec pre-shared key is message.enabled.vpn=Your VPN access is currently enabled and can be accessed via the IP +message.enable.user=Please confirm that you would like to enable this user. +message.enable.vpn.access=VPN is currently disabled for this IP Address. Would you like to enable VPN access? +message.enable.vpn=Please confirm that you want VPN access enabled for this IP address. +message.enabling.security.group.provider=Enabling Security Group provider +message.enabling.zone=Enabling zone +message.enter.token=Please enter the token that you were given in your invite e-mail. +message.generate.keys=Please confirm that you would like to generate new keys for this user. +message.guest.traffic.in.advanced.zone=Guest network traffic is communication between end-user virtual machines. Specify a range of VLAN IDs to carry guest traffic for each physical network. +message.guest.traffic.in.basic.zone=Guest network traffic is communication between end-user virtual machines. Specify a range of IP addresses that CloudStack can assign to guest VMs. Make sure this range does not overlap the reserved system IP range. +message.installWizard.click.retry=Click the button to retry launch. +message.installWizard.copy.whatIsACluster=A cluster provides a way to group hosts. The hosts in a cluster all have identical hardware, run the same hypervisor, are on the same subnet, and access the same shared storage. Virtual machine instances (VMs) can be live-migrated from one host to another within the same cluster, without interrupting service to the user. A cluster is the third-largest organizational unit within a CloudStack™ deployment. Clusters are contained within pods, and pods are contained within zones.

CloudStack™ allows multiple clusters in a cloud deployment, but for a Basic Installation, we only need one cluster. +message.installWizard.copy.whatIsAHost=A host is a single computer. Hosts provide the computing resources that run the guest virtual machines. Each host has hypervisor software installed on it to manage the guest VMs (except for bare metal hosts, which are a special case discussed in the Advanced Installation Guide). For example, a Linux KVM-enabled server, a Citrix XenServer server, and an ESXi server are hosts. In a Basic Installation, we use a single host running XenServer or KVM.

The host is the smallest organizational unit within a CloudStack™ deployment. Hosts are contained within clusters, clusters are contained within pods, and pods are contained within zones. +message.installWizard.copy.whatIsAPod=A pod often represents a single rack. Hosts in the same pod are in the same subnet.

A pod is the second-largest organizational unit within a CloudStack™ deployment. Pods are contained within zones. Each zone can contain one or more pods; in the Basic Installation, you will have just one pod in your zone. +message.installWizard.copy.whatIsAZone=A zone is the largest organizational unit within a CloudStack™ deployment. A zone typically corresponds to a single datacenter, although it is permissible to have multiple zones in a datacenter. The benefit of organizing infrastructure into zones is to provide physical isolation and redundancy. For example, each zone can have its own power supply and network uplink, and the zones can be widely separated geographically (though this is not required). +message.installWizard.copy.whatIsCloudStack=CloudStack™ is a software platform that pools computing resources to build public, private, and hybrid Infrastructure as a Service (IaaS) clouds. CloudStack™ manages the network, storage, and compute nodes that make up a cloud infrastructure. Use CloudStack™ to deploy, manage, and configure cloud computing environments.

Extending beyond individual virtual machine images running on commodity hardware, CloudStack™ provides a turnkey cloud infrastructure software stack for delivering virtual datacenters as a service - delivering all of the essential components to build, deploy, and manage multi-tier and multi-tenant cloud applications. Both open-source and Premium versions are available, with the open-source version offering nearly identical features. +message.installWizard.copy.whatIsPrimaryStorage=A CloudStack™ cloud infrastructure makes use of two types of storage: primary storage and secondary storage. Both of these can be iSCSI or NFS servers, or localdisk.

Primary storage is associated with a cluster, and it stores the disk volumes of each guest VM for all the VMs running on hosts in that cluster. The primary storage server is typically located close to the hosts. +message.installWizard.copy.whatIsSecondaryStorage=Secondary storage is associated with a zone, and it stores the following:
  • Templates - OS images that can be used to boot VMs and can include additional configuration information, such as installed applications
  • ISO images - OS images that can be bootable or non-bootable
  • Disk volume snapshots - saved copies of VM data which can be used for data recovery or to create new templates
+message.installWizard.now.building=Now building your cloud... +message.installWizard.tooltip.addCluster.name=A name for the cluster. This can be text of your choosing and is not used by CloudStack. +message.installWizard.tooltip.addHost.hostname=The DNS name or IP address of the host. +message.installWizard.tooltip.addHost.password=This is the password for the user named above (from your XenServer install). +message.installWizard.tooltip.addHost.username=Usually root. +message.installWizard.tooltip.addPod.name=A name for the pod +message.installWizard.tooltip.addPod.reservedSystemEndIp=This is the IP range in the private network that the CloudStack uses to manage Secondary Storage VMs and Console Proxy VMs. These IP addresses are taken from the same subnet as computing servers. +message.installWizard.tooltip.addPod.reservedSystemGateway=The gateway for the hosts in that pod. +message.installWizard.tooltip.addPod.reservedSystemNetmask=The netmask in use on the subnet the guests will use. +message.installWizard.tooltip.addPod.reservedSystemStartIp=This is the IP range in the private network that the CloudStack uses to manage Secondary Storage VMs and Console Proxy VMs. These IP addresses are taken from the same subnet as computing servers. +message.installWizard.tooltip.addPrimaryStorage.name=The name for the storage device. +message.installWizard.tooltip.addPrimaryStorage.path=(for NFS) In NFS this is the exported path from the server. Path (for SharedMountPoint). With KVM this is the path on each host that is where this primary storage is mounted. For example, "/mnt/primary". +message.installWizard.tooltip.addPrimaryStorage.server=(for NFS, iSCSI, or PreSetup) The IP address or DNS name of the storage device. +message.installWizard.tooltip.addSecondaryStorage.nfsServer=The IP address of the NFS server hosting the secondary storage +message.installWizard.tooltip.addSecondaryStorage.path=The exported path, located on the server you specified above +message.installWizard.tooltip.addZone.dns1=These are DNS servers for use by guest VMs in the zone. These DNS servers will be accessed via the public network you will add later. The public IP addresses for the zone must have a route to the DNS server named here. +message.installWizard.tooltip.addZone.dns2=These are DNS servers for use by guest VMs in the zone. These DNS servers will be accessed via the public network you will add later. The public IP addresses for the zone must have a route to the DNS server named here. +message.installWizard.tooltip.addZone.internaldns1=These are DNS servers for use by system VMs in the zone. These DNS servers will be accessed via the private network interface of the System VMs. The private IP address you provide for the pods must have a route to the DNS server named here. +message.installWizard.tooltip.addZone.internaldns2=These are DNS servers for use by system VMs in the zone. These DNS servers will be accessed via the private network interface of the System VMs. The private IP address you provide for the pods must have a route to the DNS server named here. +message.installWizard.tooltip.addZone.name=A name for the zone +message.installWizard.tooltip.configureGuestTraffic.description=A description for your network +message.installWizard.tooltip.configureGuestTraffic.guestEndIp=The range of IP addresses that will be available for allocation to guests in this zone. If one NIC is used, these IPs should be in the same CIDR as the pod CIDR. +message.installWizard.tooltip.configureGuestTraffic.guestGateway=The gateway that the guests should use +message.installWizard.tooltip.configureGuestTraffic.guestNetmask=The netmask in use on the subnet that the guests should use +message.installWizard.tooltip.configureGuestTraffic.guestStartIp=The range of IP addresses that will be available for allocation to guests in this zone. If one NIC is used, these IPs should be in the same CIDR as the pod CIDR. +message.installWizard.tooltip.configureGuestTraffic.name=A name for your network +message.instanceWizard.noTemplates=You do not have any templates available; please add a compatible template, and re-launch the instance wizard. +message.ip.address.changed=Your IP addresses may have changed; would you like to refresh the listing? Note that in this case the details pane will close. +message.iso.desc=Disc image containing data or bootable media for OS +message.join.project=You have now joined a project. Please switch to Project view to see the project. message.launch.vm.on.private.network=Do you wish to launch your instance on your own private dedicated network? +message.launch.zone=Zone is ready to launch; please proceed to the next step. message.lock.account=Please confirm that you want to lock this account. By locking the account, all users for this account will no longer be able to manage their cloud resources. Existing resources can still be accessed. message.migrate.instance.confirm=Please confirm the host you wish to migrate the virtual instance to. +message.migrate.instance.to.host=Please confirm that you want to migrate instance to another host. +message.migrate.instance.to.ps=Please confirm that you want to migrate instance to another primary storage. +message.migrate.router.confirm=Please confirm the host you wish to migrate the router to: +message.migrate.systemvm.confirm=Please confirm the host you wish to migrate the system VM to: +message.migrate.volume=Please confirm that you want to migrate volume to another primary storage. message.new.user=Specify the following to add a new user to the account message.no.network.support.configuration.not.true=You do not have any zone that has security group enabled. Thus, no additional network features. Please continue to step 5. message.no.network.support=Your selected hypervisor, vSphere, does not have any additional network features. Please continue to step 5. +message.no.projects.adminOnly=You do not have any projects.
Please ask your administrator to create a new project. +message.no.projects=You do not have any projects.
Please create a new one from the projects section. message.number.clusters=

# of Clusters

message.number.hosts=

# of Hosts

message.number.pods=

# of Pods

message.number.storage=

# of Primary Storage Volumes

message.number.zones=

# of Zones

+message.pending.projects.1=You have pending project invitations: +message.pending.projects.2=To view, please go to the projects section, then select invitations from the drop-down. +message.please.add.at.lease.one.traffic.range=Please add at least one traffic range. +message.please.proceed=Please proceed to the next step. +message.please.select.a.configuration.for.your.zone=Please select a configuration for your zone. +message.please.select.a.different.public.and.management.network.before.removing=Please select a different public and management network before removing +message.please.select.networks=Please select networks for your virtual machine. +message.please.wait.while.zone.is.being.created=Please wait while your zone is being created; this may take a while... +message.project.invite.sent=Invite sent to user; they will be added to the project once they accept the invitation +message.public.traffic.in.advanced.zone=Public traffic is generated when VMs in the cloud access the internet. Publicly-accessible IPs must be allocated for this purpose. End users can use the CloudStack UI to acquire these IPs to implement NAT between their guest network and their public network.

Provide at least one range of IP addresses for internet traffic. +message.public.traffic.in.basic.zone=Public traffic is generated when VMs in the cloud access the Internet or provide services to clients over the Internet. Publicly accessible IPs must be allocated for this purpose. When a instance is created, an IP from this set of Public IPs will be allocated to the instance in addition to the guest IP address. Static 1-1 NAT will be set up automatically between the public IP and the guest IP. End users can also use the CloudStack UI to acquire additional IPs to implement static NAT between their instances and the public IP. +message.redirecting.region=Redirecting to region... +message.remove.region=Are you sure you want to remove this region from this management server? +message.remove.vpc=Please confirm that you want to remove the VPC message.remove.vpn.access=Please confirm that you want to remove VPN access from the following user. +message.reset.password.warning.notPasswordEnabled=The template of this instance was created without password enabled +message.reset.password.warning.notStopped=Your instance must be stopped before attempting to change its current password +message.reset.VPN.connection=Please confirm that you want to reset VPN connection message.restart.mgmt.server=Please restart your management server(s) for your new settings to take effect. message.restart.mgmt.usage.server=Please restart your management server(s) and usage server(s) for your new settings to take effect. +message.restart.network=All services provided by this network will be interrupted. Please confirm that you want to restart this network. +message.restart.vpc=Please confirm that you want to restart the VPC message.security.group.usage=(Use Ctrl-click to select all applicable security groups) +message.select.a.zone=A zone typically corresponds to a single datacenter. Multiple zones help make the cloud more reliable by providing physical isolation and redundancy. +message.select.instance=Please select an instance. +message.select.iso=Please select an ISO for your new virtual instance. +message.select.item=Please select an item. +message.select.security.groups=Please select security group(s) for your new VM +message.select.template=Please select a template for your new virtual instance. +message.setup.physical.network.during.zone.creation.basic=When adding a basic zone, you can set up one physical network, which corresponds to a NIC on the hypervisor. The network carries several types of traffic.

You may also drag and drop other traffic types onto the physical network. +message.setup.physical.network.during.zone.creation=When adding an advanced zone, you need to set up one or more physical networks. Each network corresponds to a NIC on the hypervisor. Each physical network can carry one or more types of traffic, with certain restrictions on how they may be combined.

Drag and drop one or more traffic types onto each physical network. +message.setup.successful=Cloud setup successful! message.snapshot.schedule=You can setup recurring snapshot schedules by selecting from the available options below and applying your policy preference +message.specify.url=Please specify URL message.step.1.continue=Please select a template or ISO to continue message.step.1.desc=Please select a template for your new virtual instance. You can also choose to select a blank template from which an ISO image can be installed onto. message.step.2.continue=Please select a service offering to continue @@ -1565,40 +1462,63 @@ message.step.3.continue=Please select a disk offering to continue message.step.3.desc= message.step.4.continue=Please select at least one network to continue message.step.4.desc=Please select the primary network that your virtual instance will be connected to. +message.storage.traffic=Traffic between CloudStack's internal resources, including any components that communicate with the Management Server, such as hosts and CloudStack system VMs. Please configure storage traffic here. +message.suspend.project=Are you sure you want to suspend this project? +message.template.desc=OS image that can be used to boot VMs +message.tooltip.dns.1=Name of a DNS server for use by VMs in the zone. The public IP addresses for the zone must have a route to this server. +message.tooltip.dns.2=A second DNS server name for use by VMs in the zone. The public IP addresses for the zone must have a route to this server. +message.tooltip.internal.dns.1=Name of a DNS server for use by CloudStack internal system VMs in the zone. The private IP address for the pods must have a route to this server. +message.tooltip.internal.dns.2=Name of a DNS server for use by CloudStack internal system VMs in the zone. The private IP address for the pods must have a route to this server. +message.tooltip.network.domain=A DNS suffix that will create a custom domain name for the network that is accessed by guest VMs. +message.tooltip.pod.name=A name for this pod. +message.tooltip.reserved.system.gateway=The gateway for the hosts in the pod. +message.tooltip.reserved.system.netmask=The network prefix that defines the pod subnet. Uses CIDR notation. +message.tooltip.zone.name=A name for the zone. message.update.os.preference=Please choose a OS preference for this host. All virtual instances with similar preferences will be first allocated to this host before choosing another. +message.update.resource.count=Please confirm that you want to update resource counts for this account. message.update.ssl=Please submit a new X.509 compliant SSL certificate to be updated to each console proxy virtual instance: +message.validate.instance.name=Instance name can not be longer than 63 characters. Only ASCII letters a~z, A~Z, digits 0~9, hyphen are allowed. Must start with a letter and end with a letter or a digit. message.virtual.network.desc=A dedicated virtualized network for your account. The broadcast domain is contained within a VLAN and all public network access is routed out by a virtual router. +message.vm.create.template.confirm=Create Template will reboot the VM automatically. +message.vm.review.launch=Please review the following information and confirm that your virtual instance is correct before launch. message.volume.create.template.confirm=Please confirm that you wish to create a template for this disk volume. Creation of the template can range from several minutes to longer depending on the size of the volume. +message.you.must.have.at.least.one.physical.network=You must have at least one physical network +message.zone.creation.complete.would.you.like.to.enable.this.zone=Zone creation complete. Would you like to enable this zone? +message.Zone.creation.complete=Zone creation complete +message.zone.no.network.selection=The zone you selected does not have any choices for network selection. message.zone.step.1.desc=Please select a network model for your zone. message.zone.step.2.desc=Please enter the following info to add a new zone message.zone.step.3.desc=Please enter the following info to add a new pod -message.apply.snapshot.policy=You have successfully updated your current snapshot policy. -message.disable.snapshot.policy=You have successfully disabled your current snapshot policy. -message.action.change.service.warning.for.instance=Your instance must be stopped before attempting to change its current service offering. -message.action.change.service.warning.for.router=Your router must be stopped before attempting to change its current service offering. -message.action.reset.password.warning=Your instance must be stopped before attempting to change its current password. -message.action.reset.password.off=Your instance currently does not support this feature. - -#Errors -error.login=Your username/password does not match our records. -error.menu.select=Unable to perform action due to no items being selected. -error.mgmt.server.inaccessible=The Management Server is unaccessible. Please try again later. -error.session.expired=Your session has expired. -error.unresolved.internet.name=Your internet name cannot be resolved. - -label.add.NiciraNvp.device=Add Nvp Controller -label.delete.NiciraNvp=Remove Nvp Controller -label.nicira.controller.address=Controller Address -label.nicira.transportzoneuuid=Transport Zone Uuid -label.nicira.l3gatewayserviceuuid=L3 Gateway Service Uuid - -label.add.BigSwitchVns.device=Add BigSwitch Vns Controller -label.delete.BigSwitchVns=Remove BigSwitch Vns Controller -label.bigswitch.controller.address=BigSwitch Vns Controller Address - -#resizeVolumes -label.resize.new.size=New Size(GB) -label.action.resize.volume=Resize Volume -label.action.resize.volume.processing=Resizing Volume.... -label.resize.new.offering.id=New Offering -label.resize.shrink.ok=Shrink OK +message.zoneWizard.enable.local.storage=WARNING: If you enable local storage for this zone, you must do the following, depending on where you would like your system VMs to launch:

1. If system VMs need to be launched in primary storage, primary storage needs to be added to the zone after creation. You must also start the zone in a disabled state.

2. If system VMs need to be launched in local storage, system.vm.use.local.storage needs to be set to true before you enable the zone.


Would you like to continue? +mode=Mode +network.rate=Network Rate +notification.reboot.instance=Reboot instance +notification.start.instance=Start instance +notification.stop.instance=Stop instance +side.by.side=Side by Side +state.Accepted=Accepted +state.Active=Active +state.Allocated=Allocated +state.Allocating=Allocating +state.BackedUp=Backed Up +state.BackingUp=Backing Up +state.Completed=Completed +state.Creating=Creating +state.Declined=Declined +state.Destroyed=Destroyed +state.Disabled=Disabled +state.enabled=Enabled +state.Enabled=Enabled +state.Error=Error +state.Expunging=Expunging +state.Migrating=Migrating +state.Pending=Pending +state.ready=Ready +state.Ready=Ready +state.Running=Running +state.Starting=Starting +state.Stopped=Stopped +state.Stopping=Stopping +state.Suspended=Suspended +ui.listView.filters.all=All +ui.listView.filters.mine=Mine diff --git a/client/WEB-INF/classes/resources/messages_fr_FR.properties b/client/WEB-INF/classes/resources/messages_fr_FR.properties index 267baec0270..6a7cc9a9d55 100644 --- a/client/WEB-INF/classes/resources/messages_fr_FR.properties +++ b/client/WEB-INF/classes/resources/messages_fr_FR.properties @@ -128,8 +128,8 @@ label.action.delete.nexusVswitch=Supprimer le Nexus 1000v label.action.delete.physical.network=Supprimer le r\u00E9seau physique label.action.delete.pod=Supprimer le Pod label.action.delete.pod.processing=Suppression du pod... -label.action.delete.primary.storage=Supprimer le stockage primaire -label.action.delete.primary.storage.processing=Suppression du stockage primaire... +label.action.delete.primary.storage=Supprimer le stockage principal +label.action.delete.primary.storage.processing=Suppression du stockage principal... label.action.delete.secondary.storage=Supprimer le stockage secondaire label.action.delete.secondary.storage.processing=Suppression du stockage secondaire... label.action.delete.security.group=Supprimer le groupe de s\u00E9curit\u00E9 @@ -184,7 +184,7 @@ label.action.edit.network=Modifier le r\u00E9seau label.action.edit.network.offering=Modifier l\\'offre de service r\u00E9seau label.action.edit.network.processing=Modification du R\u00E9seau... label.action.edit.pod=Modifier le pod -label.action.edit.primary.storage=Modifier le stockage primaire +label.action.edit.primary.storage=Modifier le stockage principal label.action.edit.resource.limits=Modifier les limites de ressources label.action.edit.service.offering=Modifier l\\'offre de service label.action.edit.template=Modifier le mod\u00E8le @@ -236,6 +236,8 @@ label.action.remove.host=Supprimer l\\'h\u00F4te label.action.remove.host.processing=Suppression de l\\'h\u00F4te... label.action.reset.password=R\u00E9-initialiser le mot de passe label.action.reset.password.processing=R\u00E9-initialisation du mot de passe... +label.action.resize.volume=Redimensionner Volume +label.action.resize.volume.processing=Redimensionnement en cours... label.action.resource.limits=Limites de ressources label.action.restore.instance=Restaurer l\\'instance label.action.restore.instance.processing=Restauration de l\\'instance... @@ -263,7 +265,7 @@ label.actions=Actions label.activate.project=Activer projet label.active.sessions=Sessions actives label.add=Ajouter -label.add.ACL=Ajouter une r\u00E8gle ACL +label.add.ACL=Ajouter r\u00E8gle ACL label.add.F5.device=Ajouter un F5 label.add.NiciraNvp.device=Ajouter un contr\u00F4leur Nvp label.add.SRX.device=Ajouter un SRX @@ -302,10 +304,10 @@ label.add.new.tier=Ajouter un nouveau tiers label.add.physical.network=Ajouter un r\u00E9seau physique label.add.pod=Ajouter un pod label.add.port.forwarding.rule=Ajouter une r\u00E8gle de transfert de port -label.add.primary.storage=Ajouter un stockage primaire -label.add.resources=Ajouter des ressources -label.add.route=Ajouter une route -label.add.rule=Ajouter une r\u00E8gle +label.add.primary.storage=Ajouter un stockage principal +label.add.resources=Ajouter ressources +label.add.route=Ajouter route +label.add.rule=Ajouter r\u00E8gle label.add.secondary.storage=Ajouter un stockage secondaire label.add.security.group=Ajouter un groupe de s\u00E9curit\u00E9 label.add.service.offering=Ajouter une offre de service @@ -344,7 +346,7 @@ label.agree=Accepter label.alert=Alerte label.algorithm=Algorithme label.allocated=Allou\u00E9 -label.allocation.state=\u00C9tat de l\\'allocation +label.allocation.state=\u00C9tat label.api.key=Cl\u00E9 d\\'API label.apply=Appliquer label.assign=Assigner @@ -402,7 +404,7 @@ label.clvm=CLVM label.code=Code label.community=Communaut\u00E9 label.compute=Processeur -label.compute.and.storage=Processeur et Stockage +label.compute.and.storage=Calcul et Stockage label.compute.offering=Offre de calcul label.compute.offerings=Offres de calcul label.configuration=Configuration @@ -474,7 +476,7 @@ label.disk.size=Taille du disque label.disk.size.gb=Taille du disque (en Go) label.disk.total=Espace disque total label.disk.volume=Volume disque -label.display.name=Nom d\\'affichage +label.display.name=Nom commun label.display.text=Texte affich\u00E9 label.dns=DNS label.dns.1=DNS 1 @@ -508,7 +510,7 @@ label.enable.swift=Activer Swift label.enable.vpn=Activer VPN label.enabling.vpn=Activation du VPN label.enabling.vpn.access=Activation de l\\'acc\u00E8s VPN -label.end.IP=R\u00E9silier l\\'IP +label.end.IP=Fin de plage IP label.end.port=Port de fin label.end.reserved.system.IP=Adresse IP de fin r\u00E9serv\u00E9e Syst\u00E8me label.end.vlan=VLAN de fin @@ -522,7 +524,7 @@ label.f5=F5 label.failed=\u00C9chou\u00E9 label.featured=Sponsoris\u00E9 label.fetch.latest=Rafra\u00EEchir -label.filterBy=Filtrer par +label.filterBy=Filtre label.firewall=Pare-feu label.first.name=Pr\u00E9nom label.format=Format @@ -574,8 +576,8 @@ label.installWizard.addHostIntro.subtitle=Qu\\'est ce qu\\'un h\u00F4te ? label.installWizard.addHostIntro.title=Ajoutons un h\u00F4te label.installWizard.addPodIntro.subtitle=Qu\\'est ce qu\\'un pod ? label.installWizard.addPodIntro.title=Ajoutons un pod -label.installWizard.addPrimaryStorageIntro.subtitle=Qu\\'est ce que le stockage primaire ? -label.installWizard.addPrimaryStorageIntro.title=Ajoutons du stockage primaire +label.installWizard.addPrimaryStorageIntro.subtitle=Qu\\'est ce que le stockage principal ? +label.installWizard.addPrimaryStorageIntro.title=Ajoutons du stockage principal label.installWizard.addSecondaryStorageIntro.subtitle=Qu\\'est ce que le stockage secondaire ? label.installWizard.addSecondaryStorageIntro.title=Ajoutons du stockage secondaire label.installWizard.addZone.title=Ajouter une zone @@ -626,10 +628,15 @@ label.keyboard.type=Type de clavier label.kvm.traffic.label=Libell\u00E9 pour le trafic KVM label.label=Libell\u00E9 label.lang.brportugese=Portuguais Br\u00E9sil +label.lang.catalan=Catalan label.lang.chinese=Chinois (simplifi\u00E9) label.lang.english=Anglais label.lang.french=Fran\u00E7ais +label.lang.german=Allemand +label.lang.italian=Italien label.lang.japanese=Japonais +label.lang.korean=Cor\u00E9en +label.lang.norwegian=Norv\u00E9gien label.lang.russian=Russe label.lang.spanish=Espagnol label.last.disconnected=Derni\u00E8re D\u00E9connexion @@ -712,12 +719,12 @@ label.menu.virtual.resources=Ressources Virtuelles label.menu.volumes=Volumes label.migrate.instance.to=Migrer l\\'instance vers label.migrate.instance.to.host=Migration de l\\'instance sur un autre h\u00F4te -label.migrate.instance.to.ps=Migration de l\\'instance sur un autre stockage primaire +label.migrate.instance.to.ps=Migration de l\\'instance sur un autre stockage principal label.migrate.router.to=Migrer le routeur vers label.migrate.systemvm.to=Migrer la VM syst\u00E8me vers label.migrate.to.host=Migrer vers un h\u00F4te label.migrate.to.storage=Migrer vers un stockage -label.migrate.volume=Migration du volume vers un autre stockage primaire +label.migrate.volume=Migration du volume vers un autre stockage principal label.minimum=Minimum label.minute.past.hour=minute(s) label.monday=Lundi @@ -785,7 +792,7 @@ label.no.thanks=Non merci label.none=Aucun label.not.found=Introuvable label.notifications=Messages -label.num.cpu.cores=Nombre de coeurs de processeur +label.num.cpu.cores=Nombre de c\u0153urs label.number.of.clusters=Nombre de clusters label.number.of.hosts=Nombre d\\'H\u00F4tes label.number.of.pods=Nombre de Pods @@ -798,11 +805,11 @@ label.offer.ha=Offrir la haute disponibilit\u00E9 label.ok=OK label.optional=Facultatif label.order=Ordre -label.os.preference=Pr\u00E9f\u00E9rence du OS +label.os.preference=Pr\u00E9f\u00E9rence OS label.os.type=Type du OS label.owned.public.ips=Adresses IP Publiques d\u00E9tenues -label.owner.account=Propri\u00E9taire du compte -label.owner.domain=Propri\u00E9taire du domaine +label.owner.account=Propri\u00E9taire +label.owner.domain=Propri\u00E9taire label.parent.domain=Parent du Domaine label.password=Mot de passe label.password.enabled=Mot de passe activ\u00E9 @@ -820,11 +827,11 @@ label.port.forwarding.policies=R\u00E8gles de transfert de port label.port.range=Plage de ports label.prev=Pr\u00E9c\u00E9dent label.previous=Retour -label.primary.allocated=Stockage primaire allou\u00E9 -label.primary.network=R\u00E9seau primaire +label.primary.allocated=Stockage principal allou\u00E9 +label.primary.network=R\u00E9seau principal label.primary.storage=Premier stockage -label.primary.storage.count=Groupes de stockage primaire -label.primary.used=Stockage primaire utilis\u00E9 +label.primary.storage.count=Groupes de stockage principal +label.primary.used=Stockage principal utilis\u00E9 label.private.Gateway=Passerelle priv\u00E9e label.private.interface=Interface priv\u00E9e label.private.ip=Adresse IP Priv\u00E9e @@ -881,6 +888,9 @@ label.reserved.system.gateway=Passerelle r\u00E9serv\u00E9e Syst\u00E8me label.reserved.system.ip=Adresse IP Syst\u00E8me r\u00E9serv\u00E9e label.reserved.system.netmask=Masque de sous-r\u00E9seau r\u00E9serv\u00E9 Syst\u00E8me label.reset.VPN.connection=R\u00E9-initialiser la connexion VPN +label.resize.new.offering.id=Nouvelle Offre +label.resize.new.size=Nouvelle Taille (Go) +label.resize.shrink.ok=R\u00E9duction OK label.resource=Ressource label.resource.limits=Limite des ressources label.resource.state=\u00C9tat des ressources @@ -921,7 +931,7 @@ label.security.group.name=Nom du groupe de s\u00E9curit\u00E9 label.security.groups=Groupes de s\u00E9curit\u00E9 label.security.groups.enabled=Groupes de s\u00E9curit\u00E9 Activ\u00E9s label.select=S\u00E9lectionner -label.select-view=S\u00E9lectionner la vue +label.select-view=S\u00E9lectionner la vue label.select.a.template=S\u00E9lectionner un mod\u00E8le label.select.a.zone=S\u00E9lectionner une zone label.select.instance=S\u00E9lectionner une instance @@ -947,8 +957,8 @@ label.site.to.site.VPN=VPN Site-\u00E0-Site label.size=Taille label.skip.guide=J\\'ai d\u00E9j\u00E0 utilis\u00E9 CloudStack avant, passer ce tutoriel label.snapshot=Instantan\u00E9 -label.snapshot.limits=Limites d\\'instantan\u00E9 -label.snapshot.name=Nom de l\\'instantan\u00E9 +label.snapshot.limits=Limites d\\'instantan\u00E9s +label.snapshot.name=Nom Instantan\u00E9 label.snapshot.s=Instantan\u00E9(s) label.snapshot.schedule=Configurer un instantan\u00E9 r\u00E9current label.snapshots=Instantan\u00E9s @@ -957,7 +967,7 @@ label.source.nat=NAT Source label.specify.IP.ranges=Sp\u00E9cifier des plages IP label.specify.vlan=Pr\u00E9ciser le VLAN label.srx=SRX -label.start.IP=D\u00E9marrer l\\'IP +label.start.IP=Plage de d\u00E9but IP label.start.port=Port de d\u00E9but label.start.reserved.system.IP=Adresse IP de d\u00E9but r\u00E9serv\u00E9e Syst\u00E8me label.start.vlan=VLAN de d\u00E9part @@ -1086,7 +1096,7 @@ label.vlan.id=ID du VLAN label.vlan.range=Plage du VLAN label.vm.add=Ajouter une instance label.vm.destroy=D\u00E9truire -label.vm.display.name=Nom d\\'affichage de la VM +label.vm.display.name=Nom commun VM label.vm.name=Nom de la VM label.vm.reboot=Red\u00E9marrer label.vm.start=D\u00E9marrer @@ -1120,7 +1130,7 @@ label.yes=Oui label.zone=Zone label.zone.details=D\u00E9tails de la zone label.zone.id=ID de la zone -label.zone.name=Nom de la zone +label.zone.name=Nom de zone label.zone.step.1.title=\u00C9tape 1 \: S\u00E9lectionnez un r\u00E9seau label.zone.step.2.title=\u00C9tape 2 \: Ajoutez une zone label.zone.step.3.title=\u00C9tape 3 \: Ajoutez un Pod @@ -1130,7 +1140,7 @@ label.zone.wide=Transverse \u00E0 la zone label.zoneWizard.trafficType.guest=Invit\u00E9 \: Trafic entre les machines virtuelles utilisateurs label.zoneWizard.trafficType.management=Administration \: Trafic entre les ressources internes de CloudStack, incluant tous les composants qui communiquent avec le serveur d\\'administration, tels que les h\u00F4tes and les machines virtuelles Syst\u00E8mes CloudStack label.zoneWizard.trafficType.public=Public \: Trafic entre Internet et les machines virtuelles dans le nuage -label.zoneWizard.trafficType.storage=Stockage \: Trafic entre les serveurs de stockages primaires et secondaires, tel que le transfert de machines virtuelles mod\u00E8les et des instantan\u00E9s de disques +label.zoneWizard.trafficType.storage=Stockage \: Trafic entre les serveurs de stockages principaux et secondaires, tel que le transfert de machines virtuelles mod\u00E8les et des instantan\u00E9s de disques label.zones=Zones managed.state=\u00C9tat de la gestion message.Zone.creation.complete=Cr\u00E9ation de la zone termin\u00E9e @@ -1141,63 +1151,63 @@ message.action.cancel.maintenance=Votre h\u00F4te a quitt\u00E9 la maintenance. message.action.cancel.maintenance.mode=Confirmer l\\'annulation de cette maintenance. message.action.change.service.warning.for.instance=Votre instance doit \u00EAtre arr\u00EAt\u00E9e avant d\\'essayer de changer son offre de service. message.action.change.service.warning.for.router=Votre routeur doit \u00EAtre arr\u00EAt\u00E9 avant d\\'essayer de changer son offre de service. -message.action.delete.ISO=Confirmer que vous souhaitez supprimer cette ISO. +message.action.delete.ISO=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer cette ISO. message.action.delete.ISO.for.all.zones=L\\'ISO est utilis\u00E9 par toutes les zones. S\\'il vous pla\u00EEt confirmer que vous voulez le supprimer de toutes les zones. -message.action.delete.cluster=Confirmer que vous voulez supprimer ce cluster. -message.action.delete.disk.offering=Confirmer que vous souhaitez supprimer cette offre de disque. -message.action.delete.domain=Confirmer que vous voulez supprimer ce domaine. -message.action.delete.external.firewall=Confirmer que vous souhaitez supprimer ce pare-feu externe. Attention \: Si vous pr\u00E9voyez de rajouter le m\u00EAme pare-feu externe de nouveau, vous devez r\u00E9-initialiser les donn\u00E9es d\\'utilisation sur l\\'appareil. -message.action.delete.external.load.balancer=Confirmez que vous souhaitez supprimer ce r\u00E9partiteur de charge externe. Attention \: Si vous pensez ajouter le m\u00EAme r\u00E9partiteur de charge plus tard, vous devez remettre \u00E0 z\u00E9ro les statistiques d\\'utilisation de cet \u00E9quipement. -message.action.delete.ingress.rule=Confirmez que vous souhaitez supprimer cette r\u00E8gle d\\'entr\u00E9e. -message.action.delete.network=Confirmer que vous voulez supprimer ce r\u00E9seau. +message.action.delete.cluster=\u00CAtes-vous s\u00FBr que vous voulez supprimer ce cluster. +message.action.delete.disk.offering=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer cette offre de disque. +message.action.delete.domain=\u00CAtes-vous s\u00FBr que vous voulez supprimer ce domaine. +message.action.delete.external.firewall=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer ce pare-feu externe. Attention \: Si vous pr\u00E9voyez de rajouter le m\u00EAme pare-feu externe de nouveau, vous devez r\u00E9-initialiser les donn\u00E9es d\\'utilisation sur l\\'appareil. +message.action.delete.external.load.balancer=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer ce r\u00E9partiteur de charge externe. Attention \: Si vous pensez ajouter le m\u00EAme r\u00E9partiteur de charge plus tard, vous devez remettre \u00E0 z\u00E9ro les statistiques d\\'utilisation de cet \u00E9quipement. +message.action.delete.ingress.rule=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer cette r\u00E8gle d\\'entr\u00E9e. +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.physical.network=Confirmer la suppression du r\u00E9seau physique -message.action.delete.pod=Confirmez que vous souhaitez supprimer ce pod. -message.action.delete.primary.storage=Confirmer que vous voulez supprimer ce stockage primaire. -message.action.delete.secondary.storage=Confirmez que vous souhaitez supprimer ce stockage secondaire. -message.action.delete.security.group=Confirmez que vous souhaitez supprimer ce groupe de s\u00E9curit\u00E9. -message.action.delete.service.offering=Confirmez que vous souhaitez supprimer cette offre de service. -message.action.delete.snapshot=Confirmez que vous souhaitez supprimer cet instantan\u00E9 -message.action.delete.system.service.offering=Confirmer la suppression de l\\'offre syst\u00E8me. -message.action.delete.template=Confirmez que vous souhaitez supprimer ce mod\u00E8le. -message.action.delete.template.for.all.zones=Ce mod\u00E8le est utilis\u00E9 par toutes les zones. Confirmez que vous souhaitez le supprimer de toutes les zones. -message.action.delete.volume=Confirmez que vous souhaitez supprimer ce volume. -message.action.delete.zone=Confirmez que vous souhaitez supprimer cette zone. -message.action.destroy.instance=Confirmez que vous souhaitez supprimer cette instance. -message.action.destroy.systemvm=Confirmez que vous souhaitez supprimer cette VM Syst\u00E8me. -message.action.disable.cluster=Confirmez que vous souhaitez d\u00E9sactiver ce cluster +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. +message.action.delete.secondary.storage=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer ce stockage secondaire. +message.action.delete.security.group=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer ce groupe de s\u00E9curit\u00E9. +message.action.delete.service.offering=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer cette offre de service. +message.action.delete.snapshot=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer cet instantan\u00E9 +message.action.delete.system.service.offering=\u00CAtes-vous s\u00FBr que vous voulez supprimer l\\'offre syst\u00E8me. +message.action.delete.template=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer ce mod\u00E8le. +message.action.delete.template.for.all.zones=Ce mod\u00E8le est utilis\u00E9 par toutes les zones. \u00CAtes-vous s\u00FBr que vous souhaitez le supprimer de toutes les zones. +message.action.delete.volume=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer ce volume. +message.action.delete.zone=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer cette zone. +message.action.destroy.instance=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer cette instance. +message.action.destroy.systemvm=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer cette VM Syst\u00E8me. +message.action.disable.cluster=\u00CAtes-vous s\u00FBr que vous souhaitez d\u00E9sactiver ce cluster message.action.disable.nexusVswitch=Confirmer la d\u00E9sactivation de ce Nexus 1000v message.action.disable.physical.network=Confirmer l\\'activation de ce r\u00E9seau physique. -message.action.disable.pod=Confirmez que vous voulez d\u00E9sactiver ce Pod -message.action.disable.static.NAT=Confirmez que vous souhaitez d\u00E9sactiver le NAT statique. -message.action.disable.zone=Confirmez que vous voulez d\u00E9sactiver cette zone +message.action.disable.pod=\u00CAtes-vous s\u00FBr que vous souhaitez d\u00E9sactiver ce Pod +message.action.disable.static.NAT=\u00CAtes-vous s\u00FBr que vous souhaitez d\u00E9sactiver le NAT statique. +message.action.disable.zone=\u00CAtes-vous s\u00FBr que vous souhaitez d\u00E9sactiver cette zone message.action.download.iso=Confirmer le t\u00E9l\u00E9chargement de cet ISO message.action.download.template=Confirmer le t\u00E9l\u00E9chargement de ce mod\u00E8le -message.action.enable.cluster=Confirmez que vous souhaitez activer ce cluster +message.action.enable.cluster=\u00CAtes-vous s\u00FBr que vous souhaitez activer ce cluster message.action.enable.maintenance=Votre h\u00F4te a \u00E9t\u00E9 mis en mode maintenance avec succ\u00E8s. Ce processus peut durer plusieurs minutes ou plus, suivant le nombre de VMs actives sur cet h\u00F4te. message.action.enable.nexusVswitch=Confirmer l\\'activation de ce Nexus 1000v message.action.enable.physical.network=Confirmer l\\'activation de ce r\u00E9seau physique. -message.action.enable.pod=Confirmez que vous souhaitez activer ce Pod -message.action.enable.zone=Confirmez que vous voulez activer cette zone +message.action.enable.pod=\u00CAtes-vous s\u00FBr que vous souhaitez activer ce Pod +message.action.enable.zone=\u00CAtes-vous s\u00FBr que vous souhaitez activer cette zone message.action.force.reconnect=Votre h\u00F4te a \u00E9t\u00E9 forc\u00E9e \u00E0 se reconnecter avec succ\u00E8s. Ce processus peut prendre jusqu\\'\u00E0 plusieurs minutes. message.action.host.enable.maintenance.mode=Activer le mode maintenance va causer la migration \u00E0 chaud de l\\'ensemble des instances de cet h\u00F4te sur les autres h\u00F4tes disponibles. message.action.instance.reset.password=Confirmer le changement du mot de passe ROOT pour cette machine virtuelle. -message.action.manage.cluster=Confirmez que vous voulez g\u00E9rer le cluster -message.action.primarystorage.enable.maintenance.mode=Attention \: placer ce stockage primaire en mode maintenance va provoquer l\\'arr\u00EAt de l\\'ensemble des VMs utilisant des volumes sur ce stockage. Souhaitez-vous continuer ? -message.action.reboot.instance=Confirmez que vous souhaitez red\u00E9marrer cette instance. +message.action.manage.cluster=\u00CAtes-vous s\u00FBr que vous souhaitez g\u00E9rer le cluster +message.action.primarystorage.enable.maintenance.mode=Attention \: placer ce stockage principal en mode maintenance va provoquer l\\'arr\u00EAt de l\\'ensemble des VMs utilisant des volumes sur ce stockage. Souhaitez-vous continuer ? +message.action.reboot.instance=\u00CAtes-vous s\u00FBr que vous souhaitez red\u00E9marrer cette instance. message.action.reboot.router=Tous les services fournit par ce routeur virtuel vont \u00EAtre interrompus. Confirmer le r\u00E9-amor\u00E7age de ce routeur. -message.action.reboot.systemvm=Confirmez que vous souhaitez red\u00E9marrer cette VM Syst\u00E8me -message.action.release.ip=Confirmez que vous souhaitez lib\u00E9rer cette IP. -message.action.remove.host=Confirmer la suppression de cet h\u00F4te. +message.action.reboot.systemvm=\u00CAtes-vous s\u00FBr que vous souhaitez red\u00E9marrer cette VM Syst\u00E8me +message.action.release.ip=\u00CAtes-vous s\u00FBr que vous souhaitez lib\u00E9rer cette IP. +message.action.remove.host=\u00CAtes-vous s\u00FBr que vous voulez supprimer cet h\u00F4te. message.action.reset.password.off=Votre instance ne supporte pas pour le moment cette fonctionnalit\u00E9. message.action.reset.password.warning=Votre instance doit \u00EAtre arr\u00EAt\u00E9e avant d\\'essayer de changer son mot de passe. -message.action.restore.instance=Confirmez que vous souhaitez restaurer cette instance. -message.action.start.instance=Confirmez que vous souhaitez d\u00E9marrer cette instance. -message.action.start.router=Confirmez que vous souhaitez d\u00E9marrer ce routeur. -message.action.start.systemvm=Confirmez que vous souhaitez red\u00E9marrer cette VM syst\u00E8me. -message.action.stop.instance=Confirmez que vous souhaitez arr\u00EAter cette instance. +message.action.restore.instance=\u00CAtes-vous s\u00FBr que vous souhaitez restaurer cette instance. +message.action.start.instance=\u00CAtes-vous s\u00FBr que vous souhaitez d\u00E9marrer cette instance. +message.action.start.router=\u00CAtes-vous s\u00FBr que vous souhaitez d\u00E9marrer ce routeur. +message.action.start.systemvm=\u00CAtes-vous s\u00FBr que vous souhaitez red\u00E9marrer cette VM syst\u00E8me. +message.action.stop.instance=\u00CAtes-vous s\u00FBr que vous souhaitez arr\u00EAter cette instance. message.action.stop.router=Tous les services fournit par ce routeur virtuel vont \u00EAtre interrompus. Confirmer l\\'arr\u00EAt de ce routeur. -message.action.stop.systemvm=Confirmez que vous souhaitez arr\u00EAter cette VM. +message.action.stop.systemvm=\u00CAtes-vous s\u00FBr que vous souhaitez arr\u00EAter cette VM. message.action.take.snapshot=Confirmer la prise d\\'un instantan\u00E9 pour ce volume. message.action.unmanage.cluster=Confirmez que vous ne voulez plus g\u00E9rer le cluster message.activate.project=\u00CAtes-vous s\u00FBr de vouloir activer ce projet ? @@ -1217,9 +1227,9 @@ message.add.load.balancer.under.ip=La r\u00E8gle de r\u00E9partition de charge \ message.add.network=Ajouter un nouveau r\u00E9seau \u00E0 la zone\: message.add.new.gateway.to.vpc=Renseigner les informations suivantes pour ajouter une nouvelle passerelle pour ce VPC message.add.pod=Ajouter un nouveau pod \u00E0 la zone -message.add.pod.during.zone.creation=Chaque zone doit contenir un ou plusieurs pods, et le premier pod sera ajout\u00E9 maintenant. Une pod contient les h\u00F4tes et les serveurs de stockage primaire, qui seront ajout\u00E9s dans une \u00E9tape ult\u00E9rieure. Configurer une plage d\\'adresses IP r\u00E9serv\u00E9es pour le trafic de gestion interne de CloudStack. La plage d\\'IP r\u00E9serv\u00E9e doit \u00EAtre unique pour chaque zone dans le nuage. -message.add.primary=Renseignez les param\u00E8tres suivants pour ajouter un stockage primaire -message.add.primary.storage=Ajouter un nouveau stockage primaire \u00E0 la zone , pod +message.add.pod.during.zone.creation=Chaque zone doit contenir un ou plusieurs pods, et le premier pod sera ajout\u00E9 maintenant. Une pod contient les h\u00F4tes et les serveurs de stockage principal, qui seront ajout\u00E9s dans une \u00E9tape ult\u00E9rieure. Configurer une plage d\\'adresses IP r\u00E9serv\u00E9es pour le trafic de gestion interne de CloudStack. La plage d\\'IP r\u00E9serv\u00E9e doit \u00EAtre unique pour chaque zone dans le nuage. +message.add.primary=Renseignez les param\u00E8tres suivants pour ajouter un stockage principal +message.add.primary.storage=Ajouter un nouveau stockage principal \u00E0 la zone , pod message.add.secondary.storage=Ajouter un nouveau stockage pour la zone message.add.service.offering=Renseigner les informations suivantes pour ajouter une nouvelle offre de service de calcul. message.add.system.service.offering=Ajouter les informations suivantes pour cr\u00E9er une nouvelle offre syst\u00E8me. @@ -1237,10 +1247,10 @@ message.after.enable.swift=Swift configur\u00E9. Remarque \: une fois que vous q message.alert.state.detected=\u00C9tat d\\'alerte d\u00E9tect\u00E9 message.allow.vpn.access=Entrez un nom d\\'utilisateur et un mot de passe pour l\\'utilisateur que vous souhaitez autoriser \u00E0 utiliser l\\'acc\u00E8s VPN. message.apply.snapshot.policy=Vous avez mis \u00E0 jour votre politique d\\'instantan\u00E9s avec succ\u00E8s. -message.attach.iso.confirm=Confirmez que vous souhaitez attacher l\\'image ISO \u00E0 cette instance. +message.attach.iso.confirm=\u00CAtes-vous s\u00FBr que vous souhaitez attacher l\\'image ISO \u00E0 cette instance. message.attach.volume=Renseignez les donn\u00E9es suivantes pour attacher un nouveau volume. Si vous attachez un volume disque \u00E0 une machine virtuelle sous Windows, vous aurez besoin de red\u00E9marrer l\\'instance pour voir le nouveau disque. message.basic.mode.desc=Choisissez ce mod\u00E8le de r\u00E9seau si vous *ne voulez pas* activer le support des VLANs. Toutes les instances cr\u00E9\u00E9es avec ce mod\u00E8le de r\u00E9seau se verront assigner une adresse IP et les groupes de s\u00E9curit\u00E9 seront utilis\u00E9s pour fournir l\\'isolation entre les VMs. -message.change.offering.confirm=Confirmez que vous souhaitez changer l\\'offre de service de cette instance. +message.change.offering.confirm=\u00CAtes-vous s\u00FBr que vous souhaitez changer l\\'offre de service de cette instance. message.change.password=Merci de modifier votre mot de passe. message.configure.all.traffic.types=Vous avez de multiples r\u00E9seaux physiques ; veuillez configurer les libell\u00E9s pour chaque type de trafic en cliquant sur le bouton Modifier. message.configuring.guest.traffic=Configuration du r\u00E9seau VM @@ -1251,13 +1261,13 @@ message.confirm.action.force.reconnect=Confirmer la re-connexion forc\u00E9e de message.confirm.delete.F5=Confirmer la suppression du F5 message.confirm.delete.NetScaler=Confirmer la suppression du Netscaler message.confirm.delete.SRX=Confirmer la suppression du SRX -message.confirm.destroy.router=Confirmer la suppression de ce routeur +message.confirm.destroy.router=\u00CAtes-vous s\u00FBr que vous voulez supprimer ce routeur message.confirm.disable.provider=Confirmer la d\u00E9sactivation de ce fournisseur message.confirm.enable.provider=Confirmer l\\'activation de ce fournisseur -message.confirm.join.project=Confirmer que vous souhaitez rejoindre ce projet. -message.confirm.remove.IP.range=Confirmer la suppression de cette plage d\\'adresses IP +message.confirm.join.project=\u00CAtes-vous s\u00FBr que vous souhaitez rejoindre ce projet. +message.confirm.remove.IP.range=\u00CAtes-vous s\u00FBr que vous voulez supprimer cette plage d\\'adresses IP message.confirm.shutdown.provider=Confirmer l\\'arr\u00EAt de ce fournisseur -message.copy.iso.confirm=Confirmez que vous souhaitez copier votre image ISO vers +message.copy.iso.confirm=\u00CAtes-vous s\u00FBr que vous souhaitez copier votre image ISO vers message.copy.template=Copier le mod\u00E8le XXX de la zone vers message.create.template=Voulez vous cr\u00E9er un mod\u00E8le ? message.create.template.vm=Cr\u00E9er la VM depuis le mod\u00E8le @@ -1266,31 +1276,31 @@ message.creating.cluster=Cr\u00E9ation du cluster message.creating.guest.network=Cr\u00E9ation du r\u00E9seau pour les invit\u00E9s message.creating.physical.networks=Cr\u00E9ation des r\u00E9seaux physiques message.creating.pod=Cr\u00E9ation d\\'un pod -message.creating.primary.storage=Cr\u00E9ation du stockage primaire +message.creating.primary.storage=Cr\u00E9ation du stockage principal message.creating.secondary.storage=Cr\u00E9ation du stockage secondaire message.creating.zone=Cr\u00E9ation de la zone message.decline.invitation=Voulez-vous refuser cette invitation au projet ? -message.delete.VPN.connection=Confirmer la suppression de la connexion VPN -message.delete.VPN.customer.gateway=Confirmer la suppression de cette passerelle VPN client -message.delete.VPN.gateway=Confirmer la suppression de cette passerelle VPN -message.delete.account=Confirmez que vous souhaitez supprimer ce compte. -message.delete.gateway=Confirmer la suppression de cette passerelle +message.delete.VPN.connection=\u00CAtes-vous s\u00FBr que vous voulez supprimer la connexion VPN +message.delete.VPN.customer.gateway=\u00CAtes-vous s\u00FBr que vous voulez supprimer cette passerelle VPN client +message.delete.VPN.gateway=\u00CAtes-vous s\u00FBr que vous voulez supprimer cette passerelle VPN +message.delete.account=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer ce compte. +message.delete.gateway=\u00CAtes-vous s\u00FBr que vous voulez supprimer cette passerelle message.delete.project=\u00CAtes-vous s\u00FBr de vouloir supprimer ce projet ? -message.delete.user=Confirmer la suppression de cet utilisateur. +message.delete.user=\u00CAtes-vous s\u00FBr que vous voulez supprimer cet utilisateur. message.desc.advanced.zone=Pour des topologies de r\u00E9seau plus sophistiqu\u00E9es. Ce mod\u00E8le de r\u00E9seau permet plus de flexibilit\u00E9 dans la d\u00E9finition des r\u00E9seaux d\\'invit\u00E9s et propose des offres personnalis\u00E9es telles que le support de pare-feu, VPN ou d\\'\u00E9quilibrage de charge. message.desc.basic.zone=Fournit un r\u00E9seau unique o\u00F9 chaque instance de machine virtuelle se voit attribuer une adresse IP directement depuis le r\u00E9seau. L\\'isolation des invit\u00E9s peut \u00EAtre assur\u00E9 au niveau de la couche r\u00E9seau-3 tels que les groupes de s\u00E9curit\u00E9 (filtrage d\\'adresse IP source). -message.desc.cluster=Chaque pod doit contenir un ou plusieurs clusters, et le premier cluster sera ajout\u00E9 tout de suite. Un cluster est un regroupement pour h\u00F4tes. Les h\u00F4tes d\\'un cluster ont tous un mat\u00E9riel identique, ex\u00E9cutent le m\u00EAme hyperviseur, sont dans le m\u00EAme sous-r\u00E9seau, et acc\u00E8dent au m\u00EAme stockage partag\u00E9. Chaque cluster comprend une ou plusieurs h\u00F4tes et un ou plusieurs serveurs de stockage primaire. +message.desc.cluster=Chaque pod doit contenir un ou plusieurs clusters, et le premier cluster sera ajout\u00E9 tout de suite. Un cluster est un regroupement pour h\u00F4tes. Les h\u00F4tes d\\'un cluster ont tous un mat\u00E9riel identique, ex\u00E9cutent le m\u00EAme hyperviseur, sont dans le m\u00EAme sous-r\u00E9seau, et acc\u00E8dent au m\u00EAme stockage partag\u00E9. Chaque cluster comprend une ou plusieurs h\u00F4tes et un ou plusieurs serveurs de stockage principal. message.desc.host=Chaque cluster doit contenir au moins un h\u00F4te (machine) pour ex\u00E9cuter des machines virtuelles invit\u00E9es, et le premier h\u00F4te sera ajout\u00E9 tout de suite. Pour un h\u00F4te fonctionnant dans CloudStack, vous devez installer un logiciel hyperviseur sur l\\'h\u00F4te, attribuer une adresse IP \u00E0 l\\'h\u00F4te, et s\\'assurer que l\\'h\u00F4te est connect\u00E9 au serveur d\\'administration CloudStack.

Indiquer le nom de l\\'h\u00F4te ou son adresse IP, l\\'identifiant de connexion (g\u00E9n\u00E9ralement root) et le mot de passe ainsi que toutes les \u00E9tiquettes permettant de classer les h\u00F4tes. -message.desc.primary.storage=Chaque cluster doit contenir un ou plusieurs serveurs de stockage primaire, et le premier sera ajout\u00E9 tout de suite. Le stockage principal contient les volumes de disque pour les machines virtuelles s\\'ex\u00E9cutant sur les h\u00F4tes dans le cluster. Utiliser les protocoles standards pris en charge par l\\'hyperviseur sous-jacent. +message.desc.primary.storage=Chaque cluster doit contenir un ou plusieurs serveurs de stockage principal, et le premier sera ajout\u00E9 tout de suite. Le stockage principal contient les volumes de disque pour les machines virtuelles s\\'ex\u00E9cutant sur les h\u00F4tes dans le cluster. Utiliser les protocoles standards pris en charge par l\\'hyperviseur sous-jacent. message.desc.secondary.storage=Chaque zone doit avoir au moins un serveur NFS ou un serveur de stockage secondaire, et sera ajout\u00E9 en premier tout de suite. Le stockage secondaire entrepose les mod\u00E8les de machines virtuelles, les images ISO et les images disques des volumes des machines virtuelles. Ce serveur doit \u00EAtre accessible pour toutes les machines h\u00F4tes dans la zone.

Saisir l\\'adresse IP et le chemin d\\'export. -message.desc.zone=Une zone est la plus grande unit\u00E9 organisationnelle dans CloudStack, et correspond typiquement \u00E0 un centre de donn\u00E9es. Les zones fournissent un isolement physique et de la redondance. Une zone est constitu\u00E9e d\\'un ou plusieurs pods (dont chacun contient les h\u00F4tes et les serveurs de stockage primaire) et un serveur de stockage secondaire qui est partag\u00E9e par tous les pods dans la zone. +message.desc.zone=Une zone est la plus grande unit\u00E9 organisationnelle dans CloudStack, et correspond typiquement \u00E0 un centre de donn\u00E9es. Les zones fournissent un isolement physique et de la redondance. Une zone est constitu\u00E9e d\\'un ou plusieurs pods (dont chacun contient les h\u00F4tes et les serveurs de stockage principal) et un serveur de stockage secondaire qui est partag\u00E9e par tous les pods dans la zone. message.detach.disk=Voulez-vous d\u00E9tacher ce disque ? -message.detach.iso.confirm=Confirmez que vous souhaitez d\u00E9tacher l\\'image ISO de cette instance. +message.detach.iso.confirm=\u00CAtes-vous s\u00FBr que vous souhaitez d\u00E9tacher l\\'image ISO de cette instance. message.disable.account=Veuillez confirmer que vous voulez d\u00E9sactiver ce compte. En d\u00E9sactivant le compte, tous les utilisateurs pour ce compte n\\'auront plus acc\u00E8s \u00E0 leurs ressources sur le cloud. Toutes les machines virtuelles vont \u00EAtre arr\u00EAt\u00E9es imm\u00E9diatement. message.disable.snapshot.policy=Vous avez d\u00E9sactiv\u00E9 votre politique d\\'instantan\u00E9 avec succ\u00E8s. message.disable.user=Confirmer la d\u00E9sactivation de cet utilisateur. message.disable.vpn=\u00CAtes-vous s\u00FBr de vouloir d\u00E9sactiver le VPN ? -message.disable.vpn.access=Confirmez que vous souhaitez d\u00E9sactiver l\\'acc\u00E8s VPN. +message.disable.vpn.access=\u00CAtes-vous s\u00FBr que vous souhaitez d\u00E9sactiver l\\'acc\u00E8s VPN. message.download.ISO=Cliquer 00000 pour t\u00E9l\u00E9charger une image ISO message.download.template=Cliquer sur 00000 pour t\u00E9l\u00E9charger le mod\u00E8le message.download.volume=Cliquer sur 00000 pour t\u00E9l\u00E9charger le volume @@ -1299,7 +1309,7 @@ message.edit.account=Modifier ("-1" signifie pas de limite de ressources) message.edit.confirm=Confirmer les changements avant de cliquer sur "Enregistrer". message.edit.limits=Renseignez les limites pour les ressources suivantes. "-1" indique qu\\'il n\\'y a pas de limites pour la cr\u00E9ation de ressources. message.edit.traffic.type=Sp\u00E9cifier le libell\u00E9 de trafic associ\u00E9 avec ce type de trafic. -message.enable.account=Confirmez que vous souhaitez activer ce compte. +message.enable.account=\u00CAtes-vous s\u00FBr que vous souhaitez activer ce compte. message.enable.user=Confirmer l\\'activation de cet utilisateur. message.enable.vpn=Confirmer l\\'activation de l\\'acc\u00E8s VPN pour cette adresse IP. message.enable.vpn.access=Le VPN est d\u00E9sactiv\u00E9 pour cette adresse IP. Voulez vous activer l\\'acc\u00E8s VPN ? @@ -1317,7 +1327,7 @@ message.installWizard.copy.whatIsAHost=Un h\u00F4te est une machine. Les h\u00F4 message.installWizard.copy.whatIsAPod=Un pod repr\u00E9sente souvent un seul rack. Les h\u00F4tes dans le m\u00EAme pod sont dans le m\u00EAme sous-r\u00E9seau.
Un pod est la deuxi\u00E8me plus grande unit\u00E9 organisationnelle au sein d\\'un d\u00E9ploiement CloudStack&\#8482;. Les pods sont contenus dans les zones. Chaque zone peut contenir un ou plusieurs pods ; dans l\\'Installation Basique, vous aurez juste un pod dans votre zone. message.installWizard.copy.whatIsAZone=Une zone est la plus grande unit\u00E9 organisationnelle au sein d\\'un d\u00E9ploiement CloudStack&\#8482;. Une zone correspond typiquement \u00E0 un centre de donn\u00E9es, mais il est permis d\\'avoir plusieurs zones dans un centre de donn\u00E9es. L\\'avantage d\\'organiser une infrastructure en zones est de fournir une isolation physique et de la redondance. Par exemple, chaque zone peut avoir sa propre alimentation et de liaison avec le r\u00E9seau, et les zones peuvent \u00EAtre tr\u00E8s \u00E9loign\u00E9es g\u00E9ographiquement (m\u00EAme si ce n\\'est pas une obligation). message.installWizard.copy.whatIsCloudStack=CloudStack&\#8482; est une plate-forme logicielle de pools de ressources informatiques pour construire des infrastructures publiques, priv\u00E9es et hybrides en tant que services (IaaS) dans les nuages. CloudStack&\#8482; g\u00E8re le r\u00E9seau, le stockage et les noeuds de calcul qui composent une infrastructure dans les nuages. Utilisez CloudStack&\#8482; pour d\u00E9ployer, g\u00E9rer et configurer les environnements d\\'informatiques dans les nuages.

S\\'\u00E9tendant au-del\u00E0 des machines virtuelles individuelles fonctionnant sur du mat\u00E9riel standard, CloudStack&\#8482; offre une solution d\\'informatique en nuage cl\u00E9 en main pour fournir des centres de donn\u00E9es virtuels comme service - fournissant tous les composants essentiels pour construire, d\u00E9ployer et g\u00E9rer des applications \\'cloud\\' multi-niveaux et multi-locataire. Les versions libre et Premium sont disponibles, la version Libre offrant des caract\u00E9ristiques presque identiques. -message.installWizard.copy.whatIsPrimaryStorage=Une infrastructure CloudStack&\#8482; utilise deux types de stockage \: stockage primaire et stockage secondaire. Les deux peuvent \u00EAtre des serveurs iSCSI ou NFS, ou sur disque local.

Le stockage primaire est associ\u00E9 \u00E0 un cluster, et stocke les volumes disques de chaque machine virtuelle pour toutes les VMs s\\'ex\u00E9cutant sur les h\u00F4tes dans le cluster. Le serveur de stockage primaire est typiquement proche des h\u00F4tes. +message.installWizard.copy.whatIsPrimaryStorage=Une infrastructure CloudStack&\#8482; utilise deux types de stockage \: stockage principal et stockage secondaire. Les deux peuvent \u00EAtre des serveurs iSCSI ou NFS, ou sur disque local.

Le stockage principal est associ\u00E9 \u00E0 un cluster, et stocke les volumes disques de chaque machine virtuelle pour toutes les VMs s\\'ex\u00E9cutant sur les h\u00F4tes dans le cluster. Le serveur de stockage principal est typiquement proche des h\u00F4tes. message.installWizard.copy.whatIsSecondaryStorage=Le stockage secondaire est associ\u00E9 \u00E0 une zone, et il stocke les \u00E9l\u00E9ments suivants\:
  • Mod\u00E8les - images de syst\u00E8mes d\\'exploitation qui peuvent \u00EAtre utilis\u00E9es pour d\u00E9marrer les machines virtuelles et peuvent inclure des informations de configuration suppl\u00E9mentaires, telles que les applications pr\u00E9-install\u00E9es
  • Images ISO - images de syst\u00E8me d\\'exploitation ou d\\'installation d\\'OS qui peuvent \u00EAtre amor\u00E7able ou non-amor\u00E7able
  • Images de volume disque - capture des donn\u00E9es de machines virtuelles qui peuvent \u00EAtre utilis\u00E9es pour la r\u00E9cup\u00E9ration des donn\u00E9es ou cr\u00E9er des mod\u00E8les
message.installWizard.now.building=Construction de votre Cloud en cours message.installWizard.tooltip.addCluster.name=Un nom pour le cluster. Ce choix est libre et n\\'est pas utilis\u00E9 par CloudStack. @@ -1330,7 +1340,7 @@ message.installWizard.tooltip.addPod.reservedSystemGateway=Passerelle pour les s message.installWizard.tooltip.addPod.reservedSystemNetmask=Le masque r\u00E9seau que les instances utiliseront sur le r\u00E9seau message.installWizard.tooltip.addPod.reservedSystemStartIp=Ceci est la plage d\\'adresses IP dans le r\u00E9seau priv\u00E9 que CloudStack utilise la gestion des VMs du stockage secondaire et les VMs Console Proxy. Ces adresses IP sont prises dans le m\u00EAme sous-r\u00E9seau que les serveurs h\u00F4tes. message.installWizard.tooltip.addPrimaryStorage.name=Nom pour ce stockage -message.installWizard.tooltip.addPrimaryStorage.path=(pour NFS) Dans NFS, ceci est le chemin d\\'export depuis le serveur. (pour SharedMountPoint) Le chemin. Avec KVM, c\\'est le chemin sur chaque h\u00F4te o\u00F9 ce stockage primaire est mont\u00E9. Par exemple, "/mnt/primary". +message.installWizard.tooltip.addPrimaryStorage.path=(pour NFS) Dans NFS, ceci est le chemin d\\'export depuis le serveur. (pour SharedMountPoint) Le chemin. Avec KVM, c\\'est le chemin sur chaque h\u00F4te o\u00F9 ce stockage principal est mont\u00E9. Par exemple, "/mnt/primary". message.installWizard.tooltip.addPrimaryStorage.server=(pour NFS, iSCSI ou PreSetup) Adresse IP ou nom DNS du stockage message.installWizard.tooltip.addSecondaryStorage.nfsServer=Adresse IP du serveur NFS supportant le stockage secondaire message.installWizard.tooltip.addSecondaryStorage.path=Le chemin export\u00E9, situ\u00E9 sur le serveur sp\u00E9cifi\u00E9 pr\u00E9c\u00E9demment @@ -1351,13 +1361,13 @@ message.iso.desc=Image disque contenant des donn\u00E9es ou un support amor\u00E message.join.project=Vous avez rejoint un projet. S\u00E9lectionnez la vue Projet pour le voir. message.launch.vm.on.private.network=Souhaitez vous d\u00E9marrer cette instance sur votre propre r\u00E9seau priv\u00E9 ? message.launch.zone=La zone est pr\u00EAte \u00E0 d\u00E9marrer ; passer \u00E0 l\\'\u00E9tape suivante. -message.lock.account=Confirmez que vous souhaitez verrouiller ce compte. En le verrouillant, les utilisateurs de ce compte ne seront plus capables de g\u00E9rer leurs ressources. Les ressources existantes resteront toutefois accessibles. +message.lock.account=\u00CAtes-vous s\u00FBr que vous souhaitez verrouiller ce compte. En le verrouillant, les utilisateurs de ce compte ne seront plus capables de g\u00E9rer leurs ressources. Les ressources existantes resteront toutefois accessibles. message.migrate.instance.confirm=Confirmez l\\'h\u00F4te vers lequel vous souhaitez migrer cette instance message.migrate.instance.to.host=Confirmer la migration de l\\'instance vers un autre h\u00F4te -message.migrate.instance.to.ps=Confirmer la migration de l\\'instance vers un autre stockage primaire +message.migrate.instance.to.ps=Confirmer la migration de l\\'instance vers un autre stockage principal 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 primaire. +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.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.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. @@ -1366,7 +1376,7 @@ message.no.projects.adminOnly=Vous n\\'avez pas de projet.
Contacter votre a message.number.clusters=

\# de Clusters

message.number.hosts=

\# d\\' H\u00F4tes

message.number.pods=

\# de Pods

-message.number.storage=

\# de Volumes de Stockage Primaire

+message.number.storage=

\# de Volumes de Stockage Principal

message.number.zones=

\# de Zones

message.pending.projects.1=Vous avez des invitations projet en attente \: message.pending.projects.2=Pour les visualiser, aller dans la section projets, puis s\u00E9lectionner invitation dans la liste d\u00E9roulante. @@ -1380,7 +1390,7 @@ message.project.invite.sent=Invitation envoy\u00E9e ; les utilisateurs seront aj message.public.traffic.in.advanced.zone=Le trafic public est g\u00E9n\u00E9r\u00E9 lorsque les machines virtuelles dans le nuage acc\u00E8dent \u00E0 Internet. Des adresses IP publiquement accessibles doivent \u00EAtre pr\u00E9vues \u00E0 cet effet. Les utilisateurs peuvent utiliser l\\'interface d\\'administration de CloudStack pour acqu\u00E9rir ces adresses IP qui impl\u00E9menteront une translation d\\'adresse NAT entre le r\u00E9seau d\\'invit\u00E9 et le r\u00E9seau public.

Fournir au moins une plage d\\'adresses IP pour le trafic Internet. message.public.traffic.in.basic.zone=Le trafic public est g\u00E9n\u00E9r\u00E9 lorsque les machines virtuelles dans le nuage acc\u00E8dent \u00E0 Internet ou fournissent des services \u00E0 des utilisateurs sur Internet. Des adresses IP publiquement accessibles doivent \u00EAtre pr\u00E9vus \u00E0 cet effet. Quand une instance est cr\u00E9\u00E9e, une adresse IP publique depuis un ensemble d\\'adresses IP publiques sera allou\u00E9e \u00E0 l\\'instance, en plus de l\\'adresse IP de l\\'invit\u00E9. La translation d\\'adresses statique NAT 1-1 sera mises en place automatiquement entre l\\'adresse IP publique et l\\'adresse IP de l\\'invit\u00E9. Les utilisateurs peuvent \u00E9galement utiliser l\\'interface d\\'administration CloudStack pour acqu\u00E9rir des adresses IP suppl\u00E9mentaires pour ajouter une translation d\\'adresse statique NAT entre leurs instances et le r\u00E9seau d\\'adresses IP publiques. message.remove.vpc=Confirmer la suppression du VPC -message.remove.vpn.access=Confirmez que vous souhaitez supprimer l\\'acc\u00E8s VPN \u00E0 l\\'utilisateur suivant. +message.remove.vpn.access=\u00CAtes-vous s\u00FBr que vous souhaitez supprimer l\\'acc\u00E8s VPN \u00E0 l\\'utilisateur suivant. message.reset.VPN.connection=Confirmer le r\u00E9-initialisation de la connexion VPN message.reset.password.warning.notPasswordEnabled=Le mod\u00E8le de cette instance a \u00E9t\u00E9 cr\u00E9\u00E9 sans la gestion de mot de passe message.reset.password.warning.notStopped=Votre instance doit \u00EAtre arr\u00EAt\u00E9e avant de changer son mot de passe @@ -1425,14 +1435,14 @@ message.validate.instance.name=Le nom de l\\'instance ne peut d\u00E9passer 63 c message.virtual.network.desc=Un r\u00E9seau virtuel d\u00E9di\u00E9 pour votre compte. Ce domaine de multi-diffusion est contenu dans un VLAN et l\\'ensemble des r\u00E9seaux d\\'acc\u00E8s publique sont rout\u00E9s par un routeur virtuel. message.vm.create.template.confirm=Cr\u00E9er un mod\u00E8le va red\u00E9marrer la VM automatiquement message.vm.review.launch=Merci de v\u00E9rifier les informations suivantes et de confirmer que votre instance virtuelle est correcte avant de la d\u00E9marrer. -message.volume.create.template.confirm=Confirmez que vous souhaitez cr\u00E9er un mod\u00E8le pour ce disque. La cr\u00E9ation peut prendre plusieurs minutes, voire plus, selon la taille du volume. +message.volume.create.template.confirm=\u00CAtes-vous s\u00FBr que vous souhaitez cr\u00E9er un mod\u00E8le pour ce disque. La cr\u00E9ation peut prendre plusieurs minutes, voire plus, selon la taille du volume. message.you.must.have.at.least.one.physical.network=Vous devez avoir au moins un r\u00E9seau physique message.zone.creation.complete.would.you.like.to.enable.this.zone=Cr\u00E9ation de la zone termin\u00E9e. Voulez-vous l\\'activer ? message.zone.no.network.selection=La zone s\u00E9lectionn\u00E9e ne propose pas le r\u00E9seau choisi message.zone.step.1.desc=S\u00E9lectionnez un mod\u00E8le de r\u00E9seau pour votre zone. message.zone.step.2.desc=Renseigner les informations suivantes pour ajouter une nouvelle zone message.zone.step.3.desc=Renseigner les informations suivantes pour ajouter un nouveau pod -message.zoneWizard.enable.local.storage=ATTENTION \: si vous activez le stockage local pour cette zone, vous devez effectuer les op\u00E9rations suivantes, selon l\\'endroit o\u00F9 vous souhaitez lancer vos machines virtuelles Syst\u00E8mes \:

1. Si les machines virtuelles Syst\u00E8mes doivent \u00EAtre lanc\u00E9es depuis le stockage primaire, ce dernier doit \u00EAtre ajout\u00E9 \u00E0 la zone apr\u00E8s la cr\u00E9ation. Vous devez \u00E9galement d\u00E9marrer la zone dans un \u00E9tat d\u00E9sactiv\u00E9.

2. Si les machines virtuelles Syst\u00E8mes doivent \u00EAtre lanc\u00E9es depuis le stockage local, le param\u00E8tre system.vm.use.local.storage doit \u00EAtre d\u00E9fini \u00E0 \\'true\\' avant d\\'activer la zone.


Voulez-vous continuer ? +message.zoneWizard.enable.local.storage=ATTENTION \: si vous activez le stockage local pour cette zone, vous devez effectuer les op\u00E9rations suivantes, selon l\\'endroit o\u00F9 vous souhaitez lancer vos machines virtuelles Syst\u00E8mes \:

1. Si les machines virtuelles Syst\u00E8mes doivent \u00EAtre lanc\u00E9es depuis le stockage principal, ce dernier doit \u00EAtre ajout\u00E9 \u00E0 la zone apr\u00E8s la cr\u00E9ation. Vous devez \u00E9galement d\u00E9marrer la zone dans un \u00E9tat d\u00E9sactiv\u00E9.

2. Si les machines virtuelles Syst\u00E8mes doivent \u00EAtre lanc\u00E9es depuis le stockage local, le param\u00E8tre system.vm.use.local.storage doit \u00EAtre d\u00E9fini \u00E0 \\'true\\' avant d\\'activer la zone.


Voulez-vous continuer ? mode=Mode network.rate=D\u00E9bit R\u00E9seau notification.reboot.instance=Red\u00E9marrer l\\'instance diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in index 15cd6fe0f13..d2ea380ddab 100644 --- a/client/tomcatconf/applicationContext.xml.in +++ b/client/tomcatconf/applicationContext.xml.in @@ -609,8 +609,9 @@ + - + @@ -713,6 +714,7 @@ + @@ -838,7 +840,10 @@ --> - + + + + diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 10fcfe3f687..b49e1fbf5ff 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -69,6 +69,7 @@ changeServiceForVirtualMachine=15 scaleVirtualMachine=15 assignVirtualMachine=1 migrateVirtualMachine=1 +migrateVirtualMachineWithVolume=1 recoverVirtualMachine=7 #### snapshot commands @@ -254,6 +255,7 @@ deleteHost=3 prepareHostForMaintenance=1 cancelHostMaintenance=1 listHosts=3 +findHostsForMigration=1 addSecondaryStorage=1 updateHostPassword=1 @@ -288,6 +290,7 @@ deleteStoragePool=1 listClusters=3 enableStorageMaintenance=1 cancelStorageMaintenance=1 +findStoragePoolsForMigration=1 #### security group commands createSecurityGroup=15 diff --git a/client/tomcatconf/componentContext.xml.in b/client/tomcatconf/componentContext.xml.in index 23284abc094..7a469816f82 100644 --- a/client/tomcatconf/componentContext.xml.in +++ b/client/tomcatconf/componentContext.xml.in @@ -253,9 +253,17 @@ - - - - + + + + + + + + + + + + diff --git a/client/tomcatconf/nonossComponentContext.xml.in b/client/tomcatconf/nonossComponentContext.xml.in index a2182d183b0..2359ba80699 100644 --- a/client/tomcatconf/nonossComponentContext.xml.in +++ b/client/tomcatconf/nonossComponentContext.xml.in @@ -355,9 +355,17 @@ - - - - + + + + + + + + + + + + diff --git a/client/tomcatconf/simulatorComponentContext.xml.in b/client/tomcatconf/simulatorComponentContext.xml.in index 435b9e2fc62..9d8c6c0ce93 100644 --- a/client/tomcatconf/simulatorComponentContext.xml.in +++ b/client/tomcatconf/simulatorComponentContext.xml.in @@ -218,12 +218,19 @@ class="org.apache.cloudstack.region.gslb.GlobalLoadBalancingRulesServiceImpl"/> + + + + + + + diff --git a/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java b/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java index fafc0a33af0..66890668387 100644 --- a/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java +++ b/core/src/com/cloud/hypervisor/HypervisorCapabilitiesVO.java @@ -64,16 +64,21 @@ public class HypervisorCapabilitiesVO implements HypervisorCapabilities { @Column(name="vm_snapshot_enabled") private Boolean vmSnapshotEnabled; - + + @Column(name="storage_motion_supported") + private boolean storageMotionSupported; + protected HypervisorCapabilitiesVO() { this.uuid = UUID.randomUUID().toString(); } - public HypervisorCapabilitiesVO(HypervisorType hypervisorType, String hypervisorVersion, Long maxGuestsLimit, boolean securityGroupEnabled) { + public HypervisorCapabilitiesVO(HypervisorType hypervisorType, String hypervisorVersion, Long maxGuestsLimit, + boolean securityGroupEnabled, boolean storageMotionSupported) { this.hypervisorType = hypervisorType; this.hypervisorVersion = hypervisorVersion; this.maxGuestsLimit = maxGuestsLimit; this.securityGroupEnabled = securityGroupEnabled; + this.storageMotionSupported = storageMotionSupported; this.uuid = UUID.randomUUID().toString(); } @@ -135,6 +140,21 @@ public class HypervisorCapabilitiesVO implements HypervisorCapabilities { return maxGuestsLimit; } + /** + * @param storageMotionSupported + */ + public void setStorageMotionSupported(boolean storageMotionSupported) { + this.storageMotionSupported = storageMotionSupported; + } + + /** + * @return if storage motion is supported + */ + @Override + public boolean isStorageMotionSupported() { + return storageMotionSupported; + } + public long getId() { return id; diff --git a/core/src/com/cloud/user/AccountVO.java b/core/src/com/cloud/user/AccountVO.java index 5e939c52173..77110aedb95 100644 --- a/core/src/com/cloud/user/AccountVO.java +++ b/core/src/com/cloud/user/AccountVO.java @@ -65,6 +65,9 @@ public class AccountVO implements Account { @Column(name="default_zone_id") private Long defaultZoneId = null; + + @Column(name = "default") + boolean isDefault; public AccountVO() { this.uuid = UUID.randomUUID().toString(); @@ -179,4 +182,8 @@ public class AccountVO implements Account { this.uuid = uuid; } + @Override + public boolean isDefault() { + return isDefault; + } } diff --git a/core/src/com/cloud/user/UserVO.java b/core/src/com/cloud/user/UserVO.java index 8b7c4e3f1e1..2a857580506 100644 --- a/core/src/com/cloud/user/UserVO.java +++ b/core/src/com/cloud/user/UserVO.java @@ -29,10 +29,11 @@ import javax.persistence.Id; import javax.persistence.Table; import org.apache.cloudstack.api.Identity; +import org.apache.cloudstack.api.InternalIdentity; + import com.cloud.user.Account.State; import com.cloud.utils.db.Encrypt; import com.cloud.utils.db.GenericDao; -import org.apache.cloudstack.api.InternalIdentity; /** * A bean representing a user @@ -92,6 +93,9 @@ public class UserVO implements User, Identity, InternalIdentity { @Column(name="uuid") private String uuid; + + @Column(name = "default") + boolean isDefault; public UserVO() { this.uuid = UUID.randomUUID().toString(); @@ -262,4 +266,9 @@ public class UserVO implements User, Identity, InternalIdentity { this.uuid = uuid; } + @Override + public boolean isDefault() { + return isDefault; + } + } diff --git a/docs/en-US/Admin_Guide.xml b/docs/en-US/Admin_Guide.xml index 07f5e889fc8..d3b9706f84e 100644 --- a/docs/en-US/Admin_Guide.xml +++ b/docs/en-US/Admin_Guide.xml @@ -26,7 +26,7 @@ &PRODUCT; Administrator's Guide Apache CloudStack - 4.0.0-incubating + 4.2.0 1 diff --git a/docs/en-US/Book_Info.xml b/docs/en-US/Book_Info.xml index 0ab84c40d9b..327668dfc9d 100644 --- a/docs/en-US/Book_Info.xml +++ b/docs/en-US/Book_Info.xml @@ -27,7 +27,7 @@ &PRODUCT; Guide Revised August 9, 2012 10:48 pm Pacific Apache CloudStack - 4.0.0 + 4.2.0 1 diff --git a/docs/en-US/CloudStack_Nicira_NVP_Guide.xml b/docs/en-US/CloudStack_Nicira_NVP_Guide.xml index a4c367c26f7..7f156d5dc09 100644 --- a/docs/en-US/CloudStack_Nicira_NVP_Guide.xml +++ b/docs/en-US/CloudStack_Nicira_NVP_Guide.xml @@ -28,7 +28,7 @@ &PRODUCT; Plugin Guide for the Nicira NVP Plugin Apache CloudStack - 4.0.0-incubating + 4.2.0 1 diff --git a/docs/en-US/Common_Content/feedback.xml b/docs/en-US/Common_Content/feedback.xml new file mode 100644 index 00000000000..4b06c9f3898 --- /dev/null +++ b/docs/en-US/Common_Content/feedback.xml @@ -0,0 +1,24 @@ + + +%BOOK_ENTITIES; +]> + +
+ Feedback + to-do +
diff --git a/docs/en-US/Developers_Guide.xml b/docs/en-US/Developers_Guide.xml index c86208b3271..87dc8a6675a 100644 --- a/docs/en-US/Developers_Guide.xml +++ b/docs/en-US/Developers_Guide.xml @@ -26,7 +26,7 @@ &PRODUCT; Developer's Guide Apache CloudStack - 4.1.0-incubating + 4.2.0 diff --git a/docs/en-US/Installation_Guide.xml b/docs/en-US/Installation_Guide.xml index 6ce5527e86c..e6a80318611 100644 --- a/docs/en-US/Installation_Guide.xml +++ b/docs/en-US/Installation_Guide.xml @@ -25,7 +25,7 @@ &PRODUCT; Installation Guide Apache CloudStack - 4.0.0 + 4.2.0 1 diff --git a/docs/en-US/Preface.xml b/docs/en-US/Preface.xml index 3f5cdc6bfcb..e046410234d 100644 --- a/docs/en-US/Preface.xml +++ b/docs/en-US/Preface.xml @@ -25,7 +25,7 @@ Preface - + diff --git a/docs/en-US/Release_Notes.xml b/docs/en-US/Release_Notes.xml index 718f38e7df9..cda8d724e9f 100644 --- a/docs/en-US/Release_Notes.xml +++ b/docs/en-US/Release_Notes.xml @@ -19,5043 +19,5805 @@ specific language governing permissions and limitations under the License. --> - - - - Welcome to &PRODUCT; 4.1 - Welcome to the 4.1.0 release of &PRODUCT;, the first major release from the Apache CloudStack project since its graduation from the Apache Incubator. - This document contains information specific to this release of &PRODUCT;, including upgrade instructions from prior releases, new features added to &PRODUCT;, API changes, and issues fixed in the release. For installation instructions, please see the Installation Guide. For usage and administration instructions, please see the &PRODUCT; Administrator's Guide. Developers and users who wish to work with the API will find instruction in the &PRODUCT; API Developer's Guide - If you find any errors or problems in this guide, please see . We hope you enjoy working with &PRODUCT;! - - - Version 4.1.0 -
- What’s New in 4.1 - Apache CloudStack 4.1.0 includes many new features. This section covers the most prominent new features and changes. -
- Localization - The 4.1.0 release adds partial User Interface (UI) support for Catalan, Chinese, French, German, Italian, Japanese, Korean, Norwegian, Portuguese, Russian, and Spanish. Not all languages are complete. - The 4.1.0 release also adds documentation translations for Chinese, Chinese (Taiwan), Italian, Japanese, Korean, and Portuguese. -
-
- Added Region Support - CLOUDSTACK-241: This feature adds a "region" construct that spans several management servers. The objective of this feature is to add AWS EC2 like Regions implementation into CloudStack. Regions are dispersed and located in separate geographic areas. Availability Zones (or Zones in CloudStack) are distinct locations within a Region that are engineered to be isolated from failures in other Zones and provide inexpensive, low latency network connectivity to other Zones in the same Region. - Regions are expected to add the following benefits - - Higher availability of the services: users can deploy services across AZs and even if one of the AZ goes down the services are still available to the end-user through VMs deployed in other zones. - Higher availability of the Management Server (MS): Since each MS Cluster only manages a single Region, if that MS Cluster goes down, only that particular Region is impacted. Admin should be able to access all the other Regions. - Scalability: The scalability limit of CloudStack dramatically improves, as the scalability limit of MS Cluster is limited to a single Region. - Object Store: With Regions construct, CloudStack would also allow users to define Object Store (Secondary Storage) across AZs. This helps users easily deploy VMs in different AZs using the same template, offerings. - Geographical Grouping: Regions allow admins to group AZs (that have low latency and are geographically located nearby) into a broader region construct. - - Currently the Region feature is exposed in the API, but does not have a UI component. -
-
- Support for EC2 Query API - CLOUDSTACK-197: This introduces a query API for the AWS APIs that are currently only supported by SOAP. The AWS Java SDK and AWS PHP SDK should now be supported by the AWSAPI in CloudStack. - Supported Query APIs in 4.1.0: - - AllocateAddress - AssociateAddress - AttachVolume - AuthorizeSecurityGroupIngress - CreateImage - CreateKeyPair - CreateSecurityGroup - CreateSnapshot - CreateTags - CreateVolume - DeleteKeyPair - DeleteSecurityGroup - DeleteSnapshot - DeleteTags - DeleteVolume - DeregisterImage - DescribeAddresses - DescribeAvailabilityZones - DescribeImageAttribute - DescribeImages - DescribeInstanceAttribute - DescribeInstances - DescribeKeyPairs - DescribeSecurityGroups - DescribeSnapshots - DescribeTags - DescribeVolumes - DetachVolume - DisassociateAddress - GetPasswordData - ImportkeyPair - ModifyImageAttribute - RebootInstances - RegisterImage - ReleaseAddress - ResetImageAttribute - RevokeSecurityGroupIngress - RunInstances - StartInstances - StopInstances - TerminateInstances - - See the Feature Specification for more information on the Query API support. -
-
- Auto-Completing Shell for CloudStack (CloudMonkey) - CLOUDSTACK-132: Adds a auto-completing shell and command-line tool for &PRODUCT; written in Python, called CloudMonkey. - CloudMonkey includes the following features: - - Usable as a command line tool and interactive shell. - All commands are lowercase unlike API. - Api Discovery using sync feature, with build time api precaching for failsafe sync. - Raw api execution support. - Auto-completion via double tab. - Reverse search using Ctrl+R - Emacs compatible key bindings. - Output that's "pipeable" to other *nix programs. - Unix shell execution. - Support to handle asynchronous jobs using user defined blocking or non-blocking way. - Tabular or JSON output with filtering of table columns. - Colored output. - API parameter value completion (based on predication, fuzzy results may fail sometimes). - - CloudMonkey has a few requirements above and beyond CloudStack, and does not need to be run on the same machine as a management server. If you wish to run CloudMonkey you'll need Python 2.5 or later, readline, Pygments, and prettytable. CloudMonkey can be installed with pip: - $ pip install cloudmonkey - See the Developer's Guide and the CloudStack wiki for the latest information on CloudMonkey installation and use. -
-
- API Discovery Service - CLOUDSTACK-926: CloudStack has more than 300 APIs and more are added in each major release. CloudStack admins can enable or disable APIs, or add plugins which provide more APIs. The API Discovery Service is a plugin which will help users discover the APIs available to them on a CloudStack Management Server. - The discovery service implements a method called listApis which will return information about APIs for a user. It currently accepts an apiName to list api information of that particular API. The method ensures that user can only list APIs they are entitled to. - All CloudStack APIs are implemented by annotated command class and PluggableService is a contract implemented by all the components such as the Management Server and all the plugins which provide an API. During load time, API discovery service asks all the pluggable services to return list of API cmd classes from whose fields and annotations it gathers information about each API, the information consists of name, description, parameter name, parameter description, etc. - For more information on the implementation of the API Discovery Service for 4.1.0, see the CloudStack wiki. -
-
- Events Framework - CLOUDSTACK-820: The Events Framework provides a mechanism to publish and subscribe to events in &PRODUCT;. -
-
- Additional VMX Settings - ### -
-
- L3 Router Functionality in Nicira Nvp Plugin - ### -
-
- Persistent Networks without Running VM - ### -
-
- Add/Remove Network on VM - ### -
-
- Resize Volumes Feature - ### -
-
- Autoscale - ### -
-
- API Request Throttling - ### -
-
- Ceph RDB Setup - ### -
-
- S3 Backed Secondary Storage - ### -
-
- User and Domain Admin Can Create API Key and Secret - CLOUDSTACK-437: This feature adds the ability for domain admins and users to create their own API Key and Secret. Domain admins can create keys for themselves, subdomain admins, and for regular users, but not for other domain admins. -
-
- Support Inline Mode for F5 and SRX - CLOUDSTACK-306: ### -
-
- Egress Firewall Rules for Guest Networks - CLOUDSTACK-299: ### -
-
- Reset SSH Key to Access VM - CLOUDSTACK-297: ### -
-
-
- Issues Fixed in 4.1.0 - Apache CloudStack uses Jira - to track its issues. All new features and bugs for 4.1.0 have been tracked in Jira, and have - a standard naming convention of "CLOUDSTACK-NNNN" where "NNNN" is the issue number. - This section includes a summary of known issues against 4.0.0 that were fixed in 4.1.0. Approximately 470 bugs were resolved or closed in the 4.1.0 cycle. - - - - - - - - Defect - - - Description - - - - - - - CLOUDSTACK-46 - - - Remnants of mycloud remain. - - - - - CLOUDSTACK-70 - - - Improve Network Restart Behaviour for Basic Zone: Restarting Network Fail - - - - - CLOUDSTACK-94 - - - "API command, listIsos documentation clarity - - - - - CLOUDSTACK-95 - - - IP address allocation not working when a user tries to allocate IP addresses in a Project - - - - - CLOUDSTACK-97 - - - Vmware network labels are ignored when creating a Zone using basic networkin - - - - - CLOUDSTACK-108 - - - VM should not be allowed to be deployed on two Isolated Networks of an Account that were created from DefaultNetworkOfferingwithSourceNATService - - - - - CLOUDSTACK-118 - - - "Status of host resorce stuck in ""ErrorInMaintenance"" - - - - - CLOUDSTACK-119 - - - Move Agent-Simulator in to the hypervisor plugin mode - - - - - CLOUDSTACK-130 - - - Clarify docs on tags parameter in API referenc - - - - - CLOUDSTACK-152 - - - Routes on the User VM are programmed incorrectly on a VM present on both Isolated and Shared Guest Network - - - - - CLOUDSTACK-178 - - - Expose name parameter of VM in list Vm view - - - - - CLOUDSTACK-198 - - - vpn:failto add VPN Users deletes all the existing Vpn use - - - - - CLOUDSTACK-222 - - - Admin UI prompts to restart Management server with cancel edit operatio - - - - - CLOUDSTACK-225 - - - API Docs: Request params repeated with different description - - - - - CLOUDSTACK-226 - - - UpdatePhysicalNetworkcommand failed due to java.sql.BatchUpdateException ; Tried to extend the existing Guest VLAN Range of one physical network into the Guest VLAN range of the other physical networ - - - - - CLOUDSTACK-227 - - - ReconnectHostCmd: NullPointerException: Unable to get host Information for XenServer 6.0.2 host - on intentionally changing the traffic labels on the physical networ - - - - - CLOUDSTACK-228 - - - UI provides an option to reconnect a disconnected host - ServerApiException is thrown on an attemp - - - - - CLOUDSTACK-232 - - - Zone infrastructure chart -- disable resource total displa - - - - - CLOUDSTACK-235 - - - Network rate can be set in 2 places. Clarify docs on how this works - - - - - CLOUDSTACK-249 - - - Add host id to failed VM deploy alert - - - - - CLOUDSTACK-250 - - - Incorrect description of maintenance mode in admin guid - - - - - CLOUDSTACK-256 - - - "vpn:As an admin user, not able to delete VPN user which is present in a regular user's network. - - - - - CLOUDSTACK-271 - - - updatePhysicalNetwork dies with an NPE when the vlan range is empt - - - - - CLOUDSTACK-274 - - - Two error codes mapped to same value in AP - - - - - CLOUDSTACK-275 - - - hostid not always a UUI - - - - - CLOUDSTACK-277 - - - Message during CloudStack management server Installation: cannot access /usr/share/cloud/bridge/lib: No such file or director - - - - - CLOUDSTACK-279 - - - deleteProject fails when executed by the regular user (works fine for root/domain admin - - - - - CLOUDSTACK-284 - - - listVirtualMachines does not return deleted machines when zone is specifie - - - - - CLOUDSTACK-290 - - - 3.0.0 template also needed for 2.2.14 to 3.0.5 direct upgrade - - - - - CLOUDSTACK-293 - - - "We do awful, hacky things in our spec file for client - - - - - CLOUDSTACK-304 - - - Add synchronization for createSnapshot command per host basi - - - - - CLOUDSTACK-309 - - - iptables rules being deleted from wrong VM after a migratio - - - - - CLOUDSTACK-318 - - - Adding XenServer Host Fails - 6.0.2 fails with 4.0. - - - - - CLOUDSTACK-320 - - - "sessionKey query parameter should be case-insensitive, now only sessionkey is accepted - - - - - CLOUDSTACK-322 - - - During upgrade displays error - a foreign key constraint fails (`cloud/#sql-f34_6e`.. - - - - - CLOUDSTACK-332 - - - """count"" property in list* API response should be equal to how many entries in database, not how many objects in API response - - - - - CLOUDSTACK-333 - - - When Datacenter name in VCenter has spaces Primary Storage (VMFS) discovery will fai - - - - - CLOUDSTACK-335 - - - KVM VPC load balancer not workin - - - - - CLOUDSTACK-336 - - - listZones doesn't honour pagin - - - - - CLOUDSTACK-343 - - - "Document what tools and packages are required to build, package and install CloudStack 4.0 - - - - - CLOUDSTACK-346 - - - Cannot add Vmware cluster with class loader conflict exceptio - - - - - CLOUDSTACK-347 - - - listNetworks API: return vlan information only when the caller is ROOT admi - - - - - CLOUDSTACK-348 - - - deleteNetwork does not clean up network resource count correctl - - - - - CLOUDSTACK-354 - - - Display of storage statistics is wrong - - - - - CLOUDSTACK-355 - - - "Fix ""count"" in a bunch of API commands - - - - - CLOUDSTACK-357 - - - "ISOs can be deleted while still attached to a running VM, and they subsequently cannot be detached from a running VM - - - - - CLOUDSTACK-359 - - - PropagateResourceEventCommand failes in cluster configuratio - - - - - CLOUDSTACK-361 - - - Wrong creation of guest networks on a KVM host in Multiple Physical Networks with guest traffi - - - - - CLOUDSTACK-364 - - - Docs point to download.cloud.com for AWS API scrip - - - - - CLOUDSTACK-368 - - - OVM - cannot create guest V - - - - - CLOUDSTACK-369 - - - ASF 4.0 - unable to support XenServer 6.1 hos - - - - - CLOUDSTACK-373 - - - "static NAT and Firewall is not working on external firewall device SRX, it needs to be implemented - - - - - CLOUDSTACK-377 - - - provide deployment config access to marvin's testcas - - - - - CLOUDSTACK-378 - - - mavenize marvin on maste - - - - - CLOUDSTACK-390 - - - Install Guide: Section 4.5.7 (Prepare the System VM Template): Links go to cloud.co - - - - - CLOUDSTACK-397 - - - Install Guide: Section 11.1 (Guest Traffic): Diagram is the wrong diagra - - - - - CLOUDSTACK-398 - - - Install Guide: Section 11.17.3 (Using VPN with Mac OSX): Not complete - - - - - CLOUDSTACK-404 - - - Update docs on the usage of cloud-setup-database - - - - - CLOUDSTACK-412 - - - Data truncation: Out of range value for column 'ram' at row - - - - - CLOUDSTACK-415 - - - restartNetwork call causes VM to be unreachable when Nicira based SDN is used - - - - - CLOUDSTACK-416 - - - XCP 1.6beta2 (61002c) - can't add a hos - - - - - CLOUDSTACK-417 - - - Handle password server securely to run on port 8080 on V - - - - - CLOUDSTACK-424 - - - Updated userdata not propagating to the VR - - - - - CLOUDSTACK-427 - - - Change hardcoded step number references to dynamic link - - - - - CLOUDSTACK-428 - - - Storage capacity shown in UI is incorrec - - - - - CLOUDSTACK-435 - - - Vmware network labels are ignored when creating a Zone using basic networkin - - - - - CLOUDSTACK-441 - - - Running mgmt server using jetty fails to start api serve - - - - - CLOUDSTACK-446 - - - "Host going to alert state, if you are adding already added host - - - - - CLOUDSTACK-448 - - - SSVM bootstrap failure on XenServer hosts with E3 CP - - - - - CLOUDSTACK-456 - - - License tag in SPEC isn't what RPM is expectin - - - - - CLOUDSTACK-459 - - - [Optional Public IP assignment for EIP with Basic Zone] Associate IP Checkbox in Create Network Offering Dialog is Displayed When Elastic LB is Selecte - - - - - CLOUDSTACK-462 - - - A few corrections to make to the 4.0.0 installation guid - - - - - CLOUDSTACK-464 - - - "Regression in AWSAPI docs, entire sections removed - - - - - CLOUDSTACK-465 - - - French language file quotes are dropping javascript syntax error - - - - - CLOUDSTACK-467 - - - Developer's Guide points to cloud.com for API referenc - - - - - CLOUDSTACK-479 - - - UpdateVirtualMachine api fails to propagate userdata to dom - - - - - CLOUDSTACK-481 - - - Installation Guide Doc Erro - - - - - CLOUDSTACK-493 - - - 2.2.x-3.0 DB upgrade support for Advance SG enabled network - - - - - CLOUDSTACK-499 - - - cloudmonkey CLI can't accept complex parameter - - - - - CLOUDSTACK-500 - - - Passwd-server iptables rules are dropped on domr on fresh start or on reboot. - - - - - CLOUDSTACK-501 - - - Apidocs and marvin does not know how to handle Autoscaling docs. - - - - - CLOUDSTACK-504 - - - Duplicate guest password scripts in codebase. - - - - - CLOUDSTACK-507 - - - fix api docs for listSSHKeyPair - - - - - CLOUDSTACK-508 - - - CLVM copies template to primary storage unnecessarily. - - - - - CLOUDSTACK-510 - - - Add button not visible when adding public IPs to physical network. - - - - - CLOUDSTACK-514 - - - Marvin and Cloudmonkey don't work when an API target uses https or an alternate path. - - - - - CLOUDSTACK-518 - - - API refactoring -- change @Parameter annotation and remove the @IdentityMapper annotation. - - - - - CLOUDSTACK-520 - - - Dependency jar names mismatch with install-non-oss.s - - - - - CLOUDSTACK-521 - - - Build will hung up when doing test for TestAgentShel - - - - - CLOUDSTACK-522 - - - Log requests in cloudmonkey's log file. - - - - - CLOUDSTACK-527 - - - List API performance optimization by using DB views and removing UUID conversion - - - - - CLOUDSTACK-534 - - - Failed to add hos - - - - - CLOUDSTACK-536 - - - remove citrix cloudpatform from 4.0 build - CloudStack is ASF project. - - - - - CLOUDSTACK-539 - - - Cropped Text in UI under Quick View. - - - - - CLOUDSTACK-552 - - - ]Quick view details for a volume displays scroll bar in place of name of the volume when the name of the volume has more no of characters. - - - - - CLOUDSTACK-553 - - - "SRX - When adding SRX device make "Public Network" - default to "untrusted" and "Private Network" - default to "trusted" as un-editable fields. - - - - - CLOUDSTACK-556 - - - Erratic window behavior in Quick View tooltip. - - - - - CLOUDSTACK-559 - - - source code import problem - - - - - CLOUDSTACK-560 - - - Usage server doesn't work in 4.0.0 due to missing db changes - - - - - CLOUDSTACK-572 - - - SG Enabled Advanced Zone - Not able to deploy a VM in an account specific shared network - - - - - CLOUDSTACK-573 - - - "NPE at ""com.cloud.network.NetworkManagerImpl.networkOfferingIsConfiguredForExternalNetworking(NetworkManagerImpl.java:4345)"" when create network from the network offering having NULL provider for the service - - - - - CLOUDSTACK-578 - - - The already deleted same hostname is not deleted from /etc/hosts of vRouter - - - - - CLOUDSTACK-584 - - - "typos in ""Apache_CloudStack-4.0.0-incubating-CloudStack_Nicira_NVP_Guide-en-US"" - - - - - CLOUDSTACK-590 - - - Incorrect Network Gateways Assigned to System VM - - - - - CLOUDSTACK-592 - - - "API bloat, unknown apis cmd classes - - - - - CLOUDSTACK-593 - - - "2 guest network, auto create vlan error - - - - - CLOUDSTACK-596 - - - DeployVM command takes a lot of time to return job id. - - - - - CLOUDSTACK-599 - - - DhcpEntryCommand fails on Router VM on CS4.0 and vSphere5 with Advanced Network Zone. - - - - - CLOUDSTACK-600 - - - When rebooting KVM local storage VM host, libvirt definitions deleted - - - - - CLOUDSTACK-605 - - - Host physical CPU is incorrectly calculated for Vmware host - - - - - CLOUDSTACK-606 - - - Starting VM fails with 'ConcurrentOperationException' in a clustered MS scenari - - - - - CLOUDSTACK-614 - - - "ListTemplates API is not returning ""Enable SSH Key"" attribute for any given template - - - - - CLOUDSTACK-617 - - - Unable to edit a Sub domai - - - - - CLOUDSTACK-639 - - - API Refactoring: Adapters for AC - - - - - CLOUDSTACK-648 - - - The normal users could change their own login password. - - - - - CLOUDSTACK-660 - - - Network Traffic Labels are not functional in Marvin - - - - - CLOUDSTACK-683 - - - Image Is Missing in the Accessing VM Section - - - - - CLOUDSTACK-689 - - - RVR: Stop pending flag is not cleared when user start the disconnected router from another hos - - - - - CLOUDSTACK-691 - - - A warning dialog box shows after reloading the welcome page. - - - - - CLOUDSTACK-693 - - - Adding a VPC virtual router to a NiciraNVP enabled network fails. - - - - - CLOUDSTACK-694 - - - "Create a new VPC network offering with "connectivity" option needed for SDN networking) is not allowed / VPC support for SDN networks - - - - - CLOUDSTACK-717 - - - cloudmonkey fails to parse/print response. - - - - - CLOUDSTACK-720 - - - Fail to load a png image when accessing the web console. - - - - - CLOUDSTACK-721 - - - Bytes sent/received in user statistics is empty (CloudStack 4.0) - - - - - CLOUDSTACK-725 - - - UI: Error when the Egress rules tab is selected for a network. - - - - - CLOUDSTACK-734 - - - api_refactoring: CreateAccountCmd fails to send response due to NPE in service layer - - - - - CLOUDSTACK-735 - - - Integration smoke tests: Fix expunge vm test on api_refactoring - - - - - CLOUDSTACK-736 - - - Integration smoke tests: Fix check for vm name for the deployvm smoke test. - - - - - CLOUDSTACK-793 - - - "Create cloudmonkey-helper, a plugin that helps autodiscover and sync api info via an api over some endpoint - - - - - CLOUDSTACK-798 - - - Move usage related cmd classes from cloud-server to cloud-api - - - - - CLOUDSTACK-799 - - - [Load Test] Check router statistics falls behind in gathering stats by more than 2 times the set value - - - - - CLOUDSTACK-819 - - - Create Account/User API logging password in access log - - - - - CLOUDSTACK-863 - - - Non-printable characters (ASCII control character) such as %00 or %0025 are getting stored in raw/non encoded form in the database - - - - - CLOUDSTACK-870 - - - Client UI: Wrong character encoding for some language - - - - - CLOUDSTACK-928 - - - [Simulator] Latency for Agent Commands - change unit of wait from seconds to millisecond - - - - - CLOUDSTACK-938 - - - s2s VPN trouble - - - - - CLOUDSTACK-959 - - - Missing sub-sections in document section System Service Offering - - - - - CLOUDSTACK-968 - - - marvin: vlan should be an attribute of the physical_network and not the zon - - - - - CLOUDSTACK-977 - - - Document how to use openvswitch with KVM hypervisor - - - - - CLOUDSTACK-978 - - - TypeError: instance.displayname is undefined while adding VM's to the LB rule - - - - - CLOUDSTACK-985 - - - Different MAC address for RvR caused issue in short term network outrag - - - - - CLOUDSTACK-987 - - - Sections missing in Working With Snapshot - - - - - CLOUDSTACK-993 - - - "admin"" user is not getting created when management server is started. - - - - - CLOUDSTACK-995 - - - Not able to add the KVM host - - - - - CLOUDSTACK-1002 - - - Not able to start VM - - - - - CLOUDSTACK-1006 - - - need to disable service libvirt-guests in CentOS packaging RPMs, or in installation docs - - - - - CLOUDSTACK-1008 - - - "Egress"" tab should not be presented in the UI for Shared Networks - - - - - CLOUDSTACK-1010 - - - Host count and Secondary storage count always shows 1 in UI - - - - - CLOUDSTACK-1011 - - - KVM host getting disconnected in cluster environment - - - - - CLOUDSTACK-1013 - - - running cloudstack overwrites default public/private ssh key - - - - - CLOUDSTACK-1014 - - - Merge ManagementServer and ManagementServerEx - - - - - CLOUDSTACK-1016 - - - Not able to deploy VM - - - - - CLOUDSTACK-1021 - - - the vlan is not creat to right nic. when i creat multi guest network - - - - - CLOUDSTACK-1024 - - - Regression: Unable to add Xenserver host with latest build. - - - - - CLOUDSTACK-1027 - - - "Update SSL certificate" button should properly reflect its functionality - - - - - CLOUDSTACK-1029 - - - Enter the token to specified project is malfunctioned - - - - - CLOUDSTACK-1037 - - - "Make cloudmonkey awesome-er: Online help docs and api discovery, better colored output, parameter value autocompletion - - - - - CLOUDSTACK-1050 - - - No Documentation on Adding a Load Balancer Rule - - - - - CLOUDSTACK-1051 - - - API dispatcher unable to find objectVO corresponding to DeleteTemplatecm - - - - - CLOUDSTACK-1055 - - - "The overlay still exists when the ""Recurring Snapshots"" dialog is canceled by pressing esc key. - - - - - CLOUDSTACK-1056 - - - S3 secondary storage fails to upload systemvm template due to KVMHA director - - - - - CLOUDSTACK-1057 - - - regression of changeServiceForVirtualMachine API - fails to find service offering by serviceOfferingId parameter - - - - - CLOUDSTACK-1063 - - - "SG Enabled Advanced Zone - "Add Guest Networks" - When user tries to add a guest Network with scope as "Account" he should NOT be presented with ""Offering for shared security group enabled"" - - - - - CLOUDSTACK-1064 - - - A type error occurs when trying to add account/register template... - - - - - CLOUDSTACK-1068 - - - Names in VR list is useles - - - - - CLOUDSTACK-1070 - - - javelin: NPE on executing registerIso AP - - - - - CLOUDSTACK-1071 - - - Netscaler element is not getting loaded as part of LoadBalancing Service Providers - - - - - CLOUDSTACK-1078 - - - Not able to start System Vms on Rhel 6.3 KVM hos - - - - - CLOUDSTACK-1079 - - - Deploying AWSAPI with mvn -pl :cloud-awsapi jetty:run fail - - - - - CLOUDSTACK-1082 - - - UI doesn't throw any error message when trying to delete ip range from a network that is in use. - - - - - CLOUDSTACK-1083 - - - listUsageRecords api: removed project results in NP - - - - - CLOUDSTACK-1087 - - - Update the Developer Guide for ASFCS 4.1 Releas - - - - - CLOUDSTACK-1088 - - - EnableStaticNat error will clear the data in databas - - - - - CLOUDSTACK-1094 - - - Ipv6 - hostname/hostname --fqdn does not return the name of the VM. But i am able to reach the Vm using their names - - - - - CLOUDSTACK-1095 - - - Ipv6 - dhclient command needs to be run manually on the Vms to get the Ipv6 address - - - - - CLOUDSTACK-1100 - - - Expunge thread is not kicked off based on global configuration if the global setting is less than 60 second - - - - - CLOUDSTACK-1103 - - - "IpV6 - listNetwork() command does not retrun gateway,netmask,cidr - - - - - CLOUDSTACK-1104 - - - Ipv6 - listVlanIpRanges() returns error 530 - - - - - CLOUDSTACK-1105 - - - "IpV6 - listVirtualMachines() does not return netmask, gateway,ipaddress. - - - - - CLOUDSTACK-1107 - - - Ipv6 - Unable to extend Ip range for a Ipv6 network using craeteVlanIpRange() command - Error code 530 returned - - - - - CLOUDSTACK-1108 - - - Ipv6 - Not able to restart Networks - - - - - CLOUDSTACK-1109 - - - "Ipv6 - Unable to expunge User Vms that are ""Destroyed"". - - - - - CLOUDSTACK-1111 - - - Ipv6 - listRouters() does not return guestipaddress - - - - - CLOUDSTACK-1112 - - - "Errors in ""Prepare the System VM Template"" - - - - - CLOUDSTACK-1113 - - - "Ipv6 - Not able to deploy a new VM in this network because of ""Unable to allocate Unique Ipv6 address"" - - - - - CLOUDSTACK-1114 - - - unable to execute listegressfirewallrules API due invalid value i - - - - - CLOUDSTACK-1115 - - - In multiple shared network unable to login with default nic - KV - - - - - CLOUDSTACK-1123 - - - ListStoragePools API broken by refacto - - - - - CLOUDSTACK-1138 - - - "Providing invalid values for gateway, netmask etc in the zoneWizard blocks the VLAN container to load, throwing an error - - - - - CLOUDSTACK-1139 - - - "After the Vm is "Expunged" we see the entry still being present in the router in /etc/dhcphosts.txt - - - - - CLOUDSTACK-1141 - - - "Ipv6 - After network restart (and reboot router), we do not see the existing vms dnsentries not being programmed in the router. - - - - - CLOUDSTACK-1152 - - - Missing tag in host-add.xm - - - - - CLOUDSTACK-1153 - - - "Ipv6 - Vm deployment fails with "n must be positive" error. - - - - - CLOUDSTACK-1154 - - - Account/Users related API failed due to RegionService inject exception. - - - - - CLOUDSTACK-1157 - - - No API Documentation on Listing Custom User Templates Using CS4 API - - - - - CLOUDSTACK-1160 - - - References to version=3.0.3|4|5|6 in API classes needs to be removed. - - - - - CLOUDSTACK-1161 - - - Differences between 4.1 and master in ongoing-config-of-external-firewalls-lb.xml - - - - - CLOUDSTACK-1163 - - - Failed with NPE while creating firewall rule - - - - - CLOUDSTACK-1168 - - - Create firewall rule broke - - - - - CLOUDSTACK-1173 - - - ConsoleProxyResource instantiation exception. - - - - - CLOUDSTACK-1174 - - - Snapshots related SQL error. - - - - - CLOUDSTACK-1176 - - - Issue with snapshots(create/list - - - - - CLOUDSTACK-1181 - - - mvn deploy db failing with NP - - - - - CLOUDSTACK-1190 - - - Make APIChecker interface throw a single sensible exception. - - - - - CLOUDSTACK-1200 - - - "Unknown column 'vm_instance.disk_offering_id' in table vm_instance, db exception shown in MS log - - - - - CLOUDSTACK-1201 - - - "Failed to create ssh key for user "cloud" /var/lib/cloud/management/.ssh/id_rsa and failed to start management server - - - - - CLOUDSTACK-1202 - - - Fail to install KVM cloud-agent. - - - - - CLOUDSTACK-1203 - - - Fail to create advance zone with SG enabled when UI allows SG enabled option. - - - - - CLOUDSTACK-1204 - - - Fail to create advance zone due to fail to add host - - - - - CLOUDSTACK-1205 - - - Ipv6 - Ubuntu 12.10 guest Vms loses default route (after it expiration time ~ 30 mts) when ipv6.autoconfig parameters are disabled except for net.ipv6.conf.lo.autoconf which is enabled. - - - - - CLOUDSTACK-1206 - - - Failure in Copy of System template - - - - - CLOUDSTACK-1210 - - - Make all pluggable services return list of api cmd classes - - - - - CLOUDSTACK-1216 - - - UUID is null for admin and failed to register user key with 4.0 - - - - - CLOUDSTACK-1218 - - - "IPv6: Shared Network - After network restart with clean option, router is assigned a different address. Name resolution for the existing guest Vms in the network fails. - - - - - CLOUDSTACK-1219 - - - Ipv6 - Provide better error messages when deploying a Vm with Ip an address that is outside the network's ip range / if the ip address already is assigned to another Vm - - - - - CLOUDSTACK-1220 - - - Ipv6 - Better error message when deploy Vm fails to get a free Ip address - - - - - CLOUDSTACK-1222 - - - API rate limit configs: removed double quote in upgrade script - - - - - CLOUDSTACK-1223 - - - Exception while starting jetty server: org.springframework.beans.factory.BeanCreationException Error creating bean with name 'apiServer' - - - - - CLOUDSTACK-1224 - - - Volume snapshot creation failing - - - - - CLOUDSTACK-1226 - - - Error while running Cloudstack-setup-database - - - - - CLOUDSTACK-1228 - - - Unable to Create System Vm's in the VMware Hypervisor setup - - - - - CLOUDSTACK-1229 - - - Incorrect SQL syntax to insert api limit related configuration items in upgrade path script. - - - - - CLOUDSTACK-1231 - - - cloud-install-sys-tmplt failed due to missing path - - - - - CLOUDSTACK-1232 - - - "Ipv6 - Guest Vms are not able to get Ipaddress when executing dhclient command when using ""/96"" network. - - - - - CLOUDSTACK-1233 - - - Veewee configuration files are inappropriately identified as ASLv2 licensed file - - - - - CLOUDSTACK-1234 - - - Unable to start KVM agent with 4.1 build. - - - - - CLOUDSTACK-1237 - - - "Register Template fails with ""Cannot find template adapter for XenServer"" - - - - - CLOUDSTACK-1239 - - - Unable to registerISO :unhandled exception executing api command: registerIs - - - - - CLOUDSTACK-1240 - - - Unable to registerTemplate : Cannot find template adapter for XenServer. - - - - - CLOUDSTACK-1241 - - - Network apply rules logic is broken. - - - - - CLOUDSTACK-1242 - - - [F5-SRX-InlineMode] Failed to create LB rule with F5-SRX inlinemode deployemen - - - - - CLOUDSTACK-1243 - - - Failed to cleanup account :java.lang.NullPointerException - - - - - CLOUDSTACK-1244 - - - fail to push sysmvm.iso onto xen host - - - - - CLOUDSTACK-1246 - - - "[ ALU beta CS 4.1 build2] ""Guest network"" missing in Add Zone wizard ( step 3, Setup Network \ Physical Network) - - - - - CLOUDSTACK-1251 - - - Baremetal zone doesn't need primary/secondary storage in UI wizard. - - - - - CLOUDSTACK-1252 - - - Failed to download default template in VMware. - - - - - CLOUDSTACK-1260 - - - Failed to register template: Unable to find template adapter - - - - - CLOUDSTACK-1261 - - - Cannot find template adapter for XenServer. - - - - - CLOUDSTACK-1262 - - - "Failed to Prepare Secondary Storage in VMware, - - - - - CLOUDSTACK-1265 - - - logrotate dnsmasq configuration is wrong - - - - - CLOUDSTACK-1267 - - - KVM's cloudstack-agent service doesn't log (log4j) - - - - - CLOUDSTACK-1269 - - - Failed to start CPVM java.lang.NullPointerException Unable to start SSVM - - - - - CLOUDSTACK-1272 - - - Autoscale: createAutoScaleVmProfile fails due to unable to retrieve Service Offering ip - - - - - CLOUDSTACK-1274 - - - UpdateNetworkCmd throws NP - - - - - CLOUDSTACK-1276 - - - Remove autoscanning for 4.1 - - - - - CLOUDSTACK-1277 - - - ApiResponseHelper.createUserVmResponse failed to populate password field set from UserVm object - - - - - CLOUDSTACK-1278 - - - Improper permissions on injectkeys.s - - - - - CLOUDSTACK-1288 - - - [F5-SRX-InlineMode] classCastException during network restart with cleanup option true - - - - - CLOUDSTACK-1289 - - - [F5-SRX-InlineMode] Usage stats are not generated for Juniper SRX Firewall in inlinemod - - - - - CLOUDSTACK-1290 - - - listNetoworks API takes too long to respond - - - - - CLOUDSTACK-1292 - - - "[F5-SRX-InlineMode] Update network from SRX,F5 as service provideds to VR as service provider does not delete firewall rules from SRX - - - - - CLOUDSTACK-1295 - - - NPE in usage parsers due to missing @Component inject - - - - - CLOUDSTACK-1299 - - - Errors in 4.5.5 section of installation guide - - - - - CLOUDSTACK-1300 - - - section in wrong order in installation guide - - - - - CLOUDSTACK-1303 - - - Ipv6 - java.lang.NullPointerException when executing listnetworks() and deployVirtualMachine() after extending the Ipv4 range of a dual stack network - - - - - CLOUDSTACK-1307 - - - Noticed NPE when we put host in maintenance mode in clustered management setup - - - - - CLOUDSTACK-1310 - - - ASF-build-master-nonoss-rhel63 - create advance zone FAIL - CreatePhysicalNetworkCmd FAIL - MySQLIntegrityConstraintViolationException: Duplicate entry '200-Public' for key 'physical_network_id - - - - - CLOUDSTACK-1312 - - - "Fix rolling upgrades from 4.0 to 4.1 in 4.1 release, fix db schemas to be same as 4.0 - - - - - CLOUDSTACK-1313 - - - Working with Volumes Section Is Missing - - - - - CLOUDSTACK-1315 - - - [F5-SRX-InlineMode] Network implement failed with Run time Exception during network upgrade from VR to SRX-F - - - - - CLOUDSTACK-1319 - - - createCustomerVpnGateway response gives TypeError: json.createvpncustomergatewayresponse is undefined - - - - - CLOUDSTACK-1320 - - - Routers naming convention is changed to hostname. - - - - - CLOUDSTACK-1321 - - - [Site-to-Site VPN] No events are generated in case of status change in site to site vpn connection - - - - - CLOUDSTACK-1326 - - - KVM - Failed to start cloud agent from SSVM - - - - - CLOUDSTACK-1328 - - - console view unable to connect - CPVM SSVM guest VM - - - - - CLOUDSTACK-1329 - - - "API listRouters response returns hostname instead of Virtual Routers, UI displays host entry for each VR - - - - - CLOUDSTACK-1330 - - - ec2-run-instances - When -n option is used to deploy multiple Vms API returns error even though few of the Vms have been deployed successfully - - - - - CLOUDSTACK-1331 - - - Upgrade fails for a 2.2.14 Zone having multiple guest networks using network_tags and Public Vlan - - - - - CLOUDSTACK-1332 - - - IPV6 - Router and guest Vms should be able to use an IPV6 address for external DNS entry - - - - - CLOUDSTACK-1334 - - - vmware.root.disk.controller doesn't work - - - - - CLOUDSTACK-1337 - - - Zone to zone template/ISO copy fails and template/ISO download also fail - - - - - CLOUDSTACK-1338 - - - Deploy VM failed using IS - - - - - CLOUDSTACK-1339 - - - ASF 4.1: Management server becomes unresponsive - - - - - CLOUDSTACK-1341 - - - URL for the KEYs file is wrong in the installation guide - - - - - CLOUDSTACK-1342 - - - Document installation and usage of cloudmonkey for 4.1 docs - - - - - CLOUDSTACK-1343 - - - Porting Baremetal related UI changes to ACS - - - - - CLOUDSTACK-1344 - - - Typo in use.external.dns setting description - - - - - CLOUDSTACK-1345 - - - BigSwitch plugin introduces 'VNS' isolation in UI without backend implementation - - - - - CLOUDSTACK-1346 - - - "Check to see if external devices are used in the network, is hardcoded for specific devices - - - - - CLOUDSTACK-1347 - - - "Not able to delete network. Error - ""Unable to insert queue item into database, DB is full?"" - - - - - CLOUDSTACK-1348 - - - API/UI: zoneObj is undefined. - - - - - CLOUDSTACK-1349 - - - "VPC network Adding Network ACls, PF rules - Unable to insert queue item into database, DB is full? PF rules and NW Acls in Add state in DB - - - - - CLOUDSTACK-1350 - - - Management server Stop and start causes previously downloaded ISOs and templates to redownload & reinstall. - - - - - CLOUDSTACK-1353 - - - KVM 6.3 snapshot Scheduling snapshot failed due to java.lang.NullPointerExceptio - - - - - CLOUDSTACK-1357 - - - "Autoscale: Provisioned VMs from Netscaler not being added to lb vserver, provserver fails with provserver_err_asynctaskpoll - - - - - CLOUDSTACK-1360 - - - The clusterid field of the createStoragePool API command should be documented as required. - - - - - CLOUDSTACK-1367 - - - NPE noticed in logs while AgentMonitor is monitoring the host ping interval - - - - - CLOUDSTACK-1368 - - - Shared network - Not able to delete network because of java.lang.NullPointerException - - - - - CLOUDSTACK-1369 - - - "Ipv6 - In dual Stack network, guest VM does not have the Ipv6 address of the router programmed in /etc/resolv.conf for DNS resolution. - - - - - CLOUDSTACK-1370 - - - DeployVM Fail - VPC or non-VPC network - - - - - CLOUDSTACK-1375 - - - deploydb failing with acs master - - - - - CLOUDSTACK-1376 - - - Unable to migrate VM due to internal error process exited while connecting to monitor - - - - - CLOUDSTACK-1377 - - - HA fail - when host is shutdown, VMs and SSVMs are not failover to second host in cluster. - - - - - CLOUDSTACK-1382 - - - vm deploy fails with Error "cannot find DeployPlannerSelector for vm" - - - - - CLOUDSTACK-1383 - - - Deploying basic zone on 4.1 fails in NP - - - - - CLOUDSTACK-1386 - - - BASIC zone SSVM fail to start due to exception - - - - - CLOUDSTACK-1388 - - - UI - ListUsers doesnt display any User except the Default Root Admin User - - - - - CLOUDSTACK-1391 - - - EventBus is not getting injected after javelin merge - - - - - CLOUDSTACK-1394 - - - [F5-SRX-InlineMode] Failure in static nat configuration on SRX does not result in LB configuration error in CS during LB rule configuratio - - - - - CLOUDSTACK-1397 - - - Static Nat configuration is failing with NP - - - - - CLOUDSTACK-1399 - - - Unhandled exception executing api command: stopVirtualMachine - - - - - CLOUDSTACK-1402 - - - listRouters API response doesn't return linklocal IP and public IP detail - - - - - CLOUDSTACK-1403 - - - Storage and console-proxy related error - - - - - CLOUDSTACK-1411 - - - Issues with VMWare Hypervisor host_ids not updated when ESX(i) crashes in instance table - - - - - CLOUDSTACK-1414 - - - Redundant router: BACKUP switch cancelled due to lock timeout after a glitch in network. - - - - - CLOUDSTACK-1417 - - - When invalid values are passed to createNetwork(), error message does not indicate the parameter name that has invalid values. - - - - - CLOUDSTACK-1418 - - - As regular user, we are not allowed to deploy VM on a shared network. - - - - - CLOUDSTACK-1419 - - - Apache-ify and apply trademark logos in the UI - - - - - CLOUDSTACK-1420 - - - Ensure trademarks are properly attributed in publican brand - - - - - CLOUDSTACK-1423 - - - Unable to launch UI [HTTP Status 404]. - - - - - CLOUDSTACK-1425 - - - unhandled exception executing api command: migrateVirtualMachine & recoverVirtualMachine - - - - - CLOUDSTACK-1427 - - - Failed to delete Guestnetwork which has LB with Netscaler - - - - - CLOUDSTACK-1428 - - - [UI] Instance which are created without display name are not visible when added to LB - - - - - CLOUDSTACK-1429 - - - single account is unable to use same vnet across multiple physical network - - - - - CLOUDSTACK-1436 - - - 4.1 management server fails to start from RPM build artifact - - - - - CLOUDSTACK-1443 - - - As domain admin we are allowed to create shared network - - - - - CLOUDSTACK-1446 - - - [UI]VPC Router type should be of type vpc and not syste - - - - - CLOUDSTACK-1447 - - - [UI]Persistent Status is not displayed for VPC Tier - - - - - CLOUDSTACK-1449 - - - listAccounts and listProjectAccounts API lists all the users not account-specific users for each account returne - - - - - CLOUDSTACK-1451 - - - Getting EntityExistsException while creating more than one project in CS 4. - - - - - CLOUDSTACK-1452 - - - Public IP's are assigned to private interface with VPC Restart [PF/LB rules are not functional - - - - - CLOUDSTACK-1461 - - - "Ipv6 - From a Vm that that is part of 2 networks, non default network router's details should not get programmed in the DNS entries of the guest VM. - - - - - CLOUDSTACK-1463 - - - IPV6 - Ubuntu 12.10 - Multiple Nic - IPV6 address is assigned automatically for 1 nic only. Need to do a manual dhclient request to get the ipv6 for other nic - - - - - CLOUDSTACK-1464 - - - "IPV6 - Multi nic - Ubuntu 1210 -When Vm is stopped and started/ rebooted, i get multiple global IPV6 addresses being allocated for one of the nics. - - - - - CLOUDSTACK-1465 - - - List Zones returns null under create instance when logged is as use - - - - - CLOUDSTACK-1467 - - - Failed to create Volume for the System Vm's - - - - - CLOUDSTACK-1469 - - - kvm agent: agent service fails to start u - - - - - CLOUDSTACK-1470 - - - unhandled exception executing api command: deployVirtualMachin - - - - - CLOUDSTACK-1472 - - - AssignVirtualMachine API with wrong Virtual Instance ID failed with NP - - - - - CLOUDSTACK-1473 - - - deleteDomain is failing with NP - - - - - CLOUDSTACK-1481 - - - "IPV6 - When Vm is part of 1 dual network and 1 ipv6 network, name resolution using fqdn fails for the ipv6 network. - - - - - CLOUDSTACK-1482 - - - IPV6 - We are not allowed to create a shared IPV6 network with a VLAN which already is associated with a IPV4 network - - - - - CLOUDSTACK-1484 - - - "API Throttling : api.throttling.enabled, Global setting missing - - - - - CLOUDSTACK-1485 - - - Add Baremetal Provider back to 4.1 branc - - - - - CLOUDSTACK-1487 - - - cloudstack-setup-agent fails to set private.network.device on KVM host ad - - - - - CLOUDSTACK-1488 - - - "Ipv6 - When Vm is deployed as part of multiple networks, one of the IPV6 address assigned to guest VM is lost. - - - - - CLOUDSTACK-1490 - - - 4.1 deb management fails to start due to tomcat dep problem - - - - - CLOUDSTACK-1496 - - - List API Performance: listAccounts failing with OOME for high values of pagesize (>1000 - - - - - CLOUDSTACK-1499 - - - ListAPI Performance for few APIs not as good as it was before API optimizatio - - - - - CLOUDSTACK-1503 - - - listHypervisor API not getting fired when logged in as Use - - - - - CLOUDSTACK-1505 - - - Unknown column 'domain.region_id' in 'field list - - - - - CLOUDSTACK-1509 - - - Failed to implement network elements and resources while provisioning for persistent network(createVlanIpRange to an account - - - - - CLOUDSTACK-1511 - - - [UI] Instances NIC details does not have Network Nam - - - - - CLOUDSTACK-1512 - - - [UI] Wrong message[message.configure.all.traffic.types] when trying to create zone with mulitple physical networks without providing the traffic labe - - - - - CLOUDSTACK-1515 - - - None of the cloudstack packges are marked for upgrade when tried to upgrade from.4.0/4.0.1 to 4. - - - - - CLOUDSTACK-1516 - - - Create documentation in languages that have translations availabl - - - - - CLOUDSTACK-1517 - - - Check UI in languages availabl - - - - - CLOUDSTACK-1521 - - - Redundant router: Services are not stopped when switch to BACKUP stat - - - - - CLOUDSTACK-1526 - - - Template registration fails in the VMware Setup - - - - - CLOUDSTACK-1531 - - - vmware create volume from snapshot will missing dat - - - - - CLOUDSTACK-1537 - - - Restart network with clean up set to true causes Autoscaled LB rule to get mangled and unusabl - - - - - CLOUDSTACK-1541 - - - NPE while deleting snapshot :Unexpected exception while executing org.apache.cloudstack.api.command.user.snapshot.DeleteSnapshotCm - - - - - CLOUDSTACK-1542 - - - unhandled exception while creating projec - - - - - CLOUDSTACK-1544 - - - The description and the response format for the deleteUser command are incorrec - - - - - CLOUDSTACK-1550 - - - createaccountresponse returns more than the user you requested for creation - - - - - CLOUDSTACK-1553 - - - AWS Regions-Not able to list accounts from the 2nd region after user/account/domain details have been manually synced up from first region - - - - - CLOUDSTACK-1555 - - - "AWS Regions - userapikey and usersecretkey parameters are not returned in the response of addRegion, updateRegion listRegion api calls.. - - - - - CLOUDSTACK-1557 - - - EC2 REST API : cloudbridge database is missing on the CloudStack Installatio - - - - - CLOUDSTACK-1562 - - - Replace the short-cut solution of supportting @DB with the formal on - - - - - CLOUDSTACK-1565 - - - "Used Master Branch System VM Template: Default Route on the System VMs (SSVM,CPVM and VR) is missing - - - - - CLOUDSTACK-1566 - - - Baremetal API addBaremetalPxePingServer fail to add PXE PING server to deployment causing create instance with PING style image to fai - - - - - CLOUDSTACK-1569 - - - "AWS Regions - Not able to Edit domain/account/user from a region that is not the owner region.""The content of elements must consist of well-formed character data or markup."" - error message presented to the user. - - - - - CLOUDSTACK-1571 - - - "AWS Regions - When deleting domain/account/user from a region that is not the owner, the request is not being forwarded to the owner region. - - - - - CLOUDSTACK-1574 - - - updateResourceCount API is failed saying to specify valida resource type even after parsing the valid resource typ - - - - - CLOUDSTACK-1583 - - - AWS Regions - RabbitMQ Server did not recieve any event notification during account creation - - - - - CLOUDSTACK-1587 - - - "Basic zone - CPVM fail to go to running state, Exception while trying to start secondary storage vm - - - - - CLOUDSTACK-1588 - - - "AWS Regions - When registerUserKeys() is called for a user from a region that is not the owner, it is handled by this region. - - - - - CLOUDSTACK-1600 - - - Typo in dpkg-buildpackage comman - - - - - CLOUDSTACK-1604 - - - "deploy VM failed when global setting ""vm.allocation.algorithm"" is set to ""userdispersing"" - - - - - CLOUDSTACK-1615 - - - "VMware Cluster discovery fails with if ESXi version is 5.0 Update 1, build 721882 - - - - - CLOUDSTACK-1620 - - - Cannot provision CentOS 6 VMs on XenServer 6. - - - - - CLOUDSTACK-1621 - - - listProjectInvitations fails with NPE for valid request - - - - - CLOUDSTACK-1624 - - - API is not returning response in details:UI is also not returning any outpu - - - - - CLOUDSTACK-1625 - - - NPE with updateResourceCount when && is passed thru AP - - - - - CLOUDSTACK-1630 - - - 4.0.x cloud-aws-api not properly obsoleted - - - - - CLOUDSTACK-1631 - - - 4.1 RPM packaging broke - - - - - CLOUDSTACK-1636 - - - AWS Regions - Remove the concept of having an owner region for domain/account/user objects - - - - - CLOUDSTACK-1642 - - - Add support CentOS 6. - - - - - CLOUDSTACK-1648 - - - Unable to add KVM hos - - - - - CLOUDSTACK-1649 - - - vmware vm os type erro - - - - - CLOUDSTACK-1651 - - - agent scripts still pointing to /var/log/cloud - - - - - CLOUDSTACK-1656 - - - NicResponses in a UserVmResponse are not preseving the natural order - - - - - CLOUDSTACK-1663 - - - AWS Regions - Events - There are no events being generated when a new domain is added/edited - - - - - CLOUDSTACK-1664 - - - Action Events are not logged due to spring change - - - - - CLOUDSTACK-1665 - - - AWS Regions - Events - There are no events being generated when a new user is added/edited/enabled/deleted/password changes/api & secret keys are generated - - - - - CLOUDSTACK-1666 - - - KVM VPC NetworkUsage doesnot wor - - - - - CLOUDSTACK-1668 - - - IP conflict in VPC tie - - - - - CLOUDSTACK-1671 - - - AWS Regions - Events - Domain Delete event does not include the UUID of the domain that was deleted - - - - - CLOUDSTACK-1674 - - - AWS Regions - Events - Account Deletion event does not include the UUID of the account deleted - - - - - CLOUDSTACK-1681 - - - Upgrade instructions mention incorrect name and description of systemvm-vmware template in registering template section - - - - - CLOUDSTACK-1684 - - - "api.throttling.enabled configuration setting should be set to ""false"" in Config.java - - - - - CLOUDSTACK-1688 - - - AWS Regions - Domain admin user is not able to use getUser() command to fetch user details - - - - - CLOUDSTACK-1690 - - - NPE from API server when starting mgmt serve - - - - - CLOUDSTACK-1694 - - - Issues to start/access Management Server after upgrade from 4.0 to 4. - - - - - CLOUDSTACK-1697 - - - Six DB tables are not available with upgraded setup(4.0 to 4.1) when compare to 4.1 newly installatio - - - - - CLOUDSTACK-1706 - - - "Failed to deploy VM with error ""cannot find DeployPlannerSelector"" - - - - - CLOUDSTACK-1709 - - - "AWS Regions - As part of adding a new region, project related entries should not be synced from accounts table. - - - - - CLOUDSTACK-1710 - - - "AWS Regions - As part of adding a new region,default_zone_id column for the account entries should not be synced. - - - - - CLOUDSTACK-1711 - - - AWS Regions - Include all the details of the API call made in the Events payload when changes in Admin/Account/User objects are made. - - - - - CLOUDSTACK-1713 - - - EC2 REST API: AWS API Installation Problem - - - - - CLOUDSTACK-1714 - - - Doc section has wrong title: Setting Zone VLAN and Running VM Maximum - - - - - CLOUDSTACK-1715 - - - "Missing ""host"" config setting in docs on management server load balancing - - - - - CLOUDSTACK-1716 - - - "AWS Regions - listRegions(),removeRegions(),updateRegions() should accept UUID value instead of id. - - - - - CLOUDSTACK-1718 - - - AWS Regions - removeRegion() response returns updateregionresponse - - - - - CLOUDSTACK-1719 - - - EC2 REST API: AWS APIs are not getting translated on the CloudStack Management Serve - - - - - CLOUDSTACK-1720 - - - Have an upgrade path from 4.0.x to 4.1 and 4.0.x to 4.2. - - - - - CLOUDSTACK-1729 - - - Ensure adapter execution order in runtim - - - - - CLOUDSTACK-1733 - - - [ACS41][UI] Add guest network is missing ip range fields and missing network offering - - - - - CLOUDSTACK-1736 - - - Ubuntu 12.04 cloud-setup-management Failed to configure CloudStack Management Serve - - - - - CLOUDSTACK-1738 - - - StatsCollector is not runnin - - - - - CLOUDSTACK-1740 - - - Failed to view consol - - - - - CLOUDSTACK-1746 - - - Cloudstack Usage Server won't star - - - - - CLOUDSTACK-1747 - - - "mvn deploydb only creates 4.0 DB, not 4.1 - - - - - CLOUDSTACK-1750 - - - injectkeys script fails on OSX because cp does not have a -b option (backup of destination file - - - - - CLOUDSTACK-1761 - - - Available local storage disk capacity incorrectly reported in KVM to manager - - - - - CLOUDSTACK-1764 - - - ListTemplateCommand failed with java.lang.NumberFormatException and failed to create default template. - - - - - CLOUDSTACK-1772 - - - the change in vnc listening port will cause live migration doesn't work. - - - - - CLOUDSTACK-1773 - - - Disable baremetal functionality - - - - - CLOUDSTACK-1776 - - - NPE on listSecondaryStorageHostsInAllZones in Upgraded setup from 4.0 to 4.1.0 - - - - - CLOUDSTACK-1785 - - - Redundant Router test cases failing during automation run. - - - - - CLOUDSTACK-1789 - - - Unable to download templates to Primary Storage if a host is in maintenance. - - - - - CLOUDSTACK-1791 - - - Volumes with storage tags can't be attached. - - - - - CLOUDSTACK-1792 - - - "AWS Regions - RuntimeException while executing listAccounts(), when the encryption keys are set to different values between regions. - - - - - CLOUDSTACK-1793 - - - L10n docs don't build in chinese, portuguese and japanese - - - - - CLOUDSTACK-1795 - - - Customize AOP to fully support legacy CloudStack @DB and @ActionEvent semantics. - - - - - CLOUDSTACK-1796 - - - Japanese docs don't build. - - - - - CLOUDSTACK-1802 - - - Upgrade 4.0 -> 4.1 - Not able to start management server becasue of missing /etc/cloudstack/management/tomcat6.conf file - - - - - CLOUDSTACK-1804 - - - Upgrade 4.0 -> 4.1 - DB upgrade fails - - - - - CLOUDSTACK-1805 - - - com.mysql.jdbc.exceptions.jdbc4.CommunicationsException seen after long time of inactivity resulting in not being able to log in to the management server - - - - - CLOUDSTACK-1810 - - - listTemplate API with templatefilter=featured|community is not returning any lists - - - - - CLOUDSTACK-1811 - - - "Upgrade 4.0->4.1 - When upgrade scripts fail, component loading continues and management server starts. - - - - - CLOUDSTACK-1812 - - - create physical network fails while creating basic zon - - - - - CLOUDSTACK-1825 - - - EC2 REST API: AWS APIs fail to execute due to BeanCreationException: Error creating bean with name 'SAclDaoImpl - - - - - CLOUDSTACK-1826 - - - "Storage migration not working, seemingly due to uuid vs id - - - - - CLOUDSTACK-1827 - - - Redundant router - When VR Master was stopped failover to VR Backup did not occur. - - - - - CLOUDSTACK-1834 - - - "Events are not generated for registerUserKeys(), Enabling account and Editing account. - - - - - CLOUDSTACK-1836 - - - License header failures for ja-JP .po translation file - - - - - CLOUDSTACK-1839 - - - Upgrade 4.0 -> 4.1 - Upgraded DB has lot more keys and indexes for many tables compare to the fresh installed 4.1 DB - - - - - CLOUDSTACK-1841 - - - ASF 4.0 to 4.1 Upgrade: Missing Few Global Configuration parameters on the Upgraded Setup. - - - - - CLOUDSTACK-1842 - - - ASF 4.0 to 4.1 Upgrade: Missing Ubuntu 12.04 Guest OS Types on the Upgraded Setup. - - - - - CLOUDSTACK-1844 - - - Upgrade 4.0 -> 4.1 - KVM host agent.properties is not restored as part of upgrading the binaries from 4.0 to 4.1. - - - - - CLOUDSTACK-1845 - - - KVM - storage migration often fail. - - - - - CLOUDSTACK-1846 - - - "KVM - storage pools can silently fail to be unregistered, leading to failure to register later. - - - - - CLOUDSTACK-1848 - - - Cloudstack Packages are not got updated with scenario 4.0 to 4.1 upgrade where MS is on Ubuntu 12.04. - - - - - CLOUDSTACK-1856 - - - Upgrade 4.0 -> 4.1 - Fresh install of 4.1 has 3 parameters missing in db.properties compared to an upgraded 4.0 set up - - - - - CLOUDSTACK-1873 - - - "Installation : JasyptPBEStringDecryptionCLI missing, failed to decrypt db password - - - - - CLOUDSTACK-1874 - - - AWS Regions - Account table in cloud_usage DB has region_id - - - - - CLOUDSTACK-1876 - - - External Devices - network offering for external devices is not returned in API listNetworkOfferings when creating instances. - - - - - CLOUDSTACK-1877 - - - Failed to connect to DB while starting Ubuntu management server after upgrading the packages from 4.0 to 4.1.0 - - - - - CLOUDSTACK-1882 - - - “HTTP Status 404 。 The requested resource () is not available. - - - - - CLOUDSTACK-1890 - - - listProjects is not listing state in the respons - - - - - CLOUDSTACK-1900 - - - "Upgrade 4.0 -> 4.1, We do not have a copy of db.properties that comes from a 4.1 installation saved anywhere. - - - - - CLOUDSTACK-1929 - - - ASF 4.1 cloudstack agent fail to install in KVM host CENTOS 6.3 OS: qemu-kvm-0.12.1.2-3.295.el6.10.x86_64 requires libusbredirparser.so. - - - - - CLOUDSTACK-1934 - - - NPE with listSupportedNetworkServices after upgrade from 4.0 to 4.1 (Ubuntu MS - - - - - CLOUDSTACK-1935 - - - Cloud utilities are not renamed to Cloudstack after upgrade from 4.0 to 4.1 [Ubutnu MS - - - - - CLOUDSTACK-1936 - - - On CentOS, after a upgrade from 4.0.1 to 4.1 on a cloud node (cloud-agent), the new cloustack-agent isn't add as a service (chkconfig) - - - - - CLOUDSTACK-1951 - - - centos packaging: cloud-install-sys-tmplt can't find jasypt jar. - - - - - CLOUDSTACK-1971 - - - VM deployed to incorrect primary storage. - - - - - CLOUDSTACK-1972 - - - VM deployed to incorrect primary storage. - - - - - CLOUDSTACK-1978 - - - openvswitch - unable to start console session for SSVM CPVM user VM - - - - - CLOUDSTACK-1980 - - - "[4.1]cloudstack-setup-bridge, cloudstack-setup-encryption & cloudstack-sysvmadm utilities are not available in Ubuntu 12.04 Management Server. - - - - - CLOUDSTACK-1987 - - - Deleted service offerings owned by a domain show up to domain user. - - - - - CLOUDSTACK-1988 - - - AWS API using SOAP client - User Registeration fails - - - - - CLOUDSTACK-1989 - - - "Query service offering by ID returns no result, but querying all returns service offering - - - - - CLOUDSTACK-2003 - - - Deleting domain while deleted account is cleaning up leaves VMs expunging forever due to 'Failed to update resource count - - - - - CLOUDSTACK-2007 - - - Release Notes failing to build on jenkins.cs. - - - - CS-16135 - Creating volumes after upgrading from snapshot taken in 2.2.14 no longer deletes the snapshot physically from the secondary storage. - - - - -
-
- Known Issues in 4.1.0 - - - - - - - - Issue ID - - - Description - - - - - - CLOUDSTACK-1747 - mvn deploydb only creates 4.0 DB, not 4.1 - Due to tooling changes between 4.1 and 4.2, CloudStack's database is created using the 4.0 schema and updated to the 4.1 schema when the management server starts for the first time. It's OK to see the same schema if the management server has not started yet. - - - - CLOUDSTACK-1824 - Service CloudStack-Management is being displayed as cloud-management service - Many scripts and text entries have references to cloud-management rather than cloudstack-management due to the changeover between 4.0 and 4.1 to rename services. This is a minor issue and should be corrected by 4.2. - - - - - CLOUDSTACK-1824 - Service CloudStack-Management is being displayed as cloud-management service - - - - - CLOUDSTACK-1510 - - - NPE when primary storage is added with wrong path - - - - - CLOUDSTACK-1428 - - - [UI] Instance which are created without display name are not visible when added to LB - - - - - CLOUDSTACK-1306 - - - Better Error message when trying to deploy Vm by passing static Ipv4 addresses that are assigned to another VM/IP4 address is outside the iprange. - - - - - CLOUDSTACK-1236 - - - Warning while adding Xen 6.1 host [Unable to create local link network] - - - - - CLOUDSTACK-969 - - - api: zone response lists vlan in it as "vlan range of zone" but the vlan belongs to physical network - - - - - CLOUDSTACK-963 - - - [cloud.utils.AnnotationHelper] class java.lang.Stringdoes not have a Table annotation - - - - - CLOUDSTACK-458 - - - xen:snapshots:Storage gc fail to clean the failed snapshot images from secondarystorage - - - - - CLOUDSTACK-315 - - - Infrastructure view does not show capacity values - - - - - CLOUDSTACK-300 - - - Creation of compute offering allow combination of local storage + HA - - - - - CLOUDSTACK-282 - - - Virtual Routers do not properly resolve DNS SRV Records - - - - - CLOUDSTACK-276 - - - SSVM ID is exposed in the Error Message thrown by AddTrafficType API - - - - - CLOUDSTACK-270 - - - Ui should not ask for a vlan range if the physical network isolation type is not VLAN - - - - - CLOUDSTACK-245 - - - VPC ACLs are not stored and programmed consistently - - - - - CLOUDSTACK-231 - - - Tag creation using special charecters - - - - - CLOUDSTACK-124 - - - NetworkGarbageCollector not cleaning up networks - - - - - CLOUDSTACK-62 - - - console proxy does not support any keymaps besides us, jp - - - - - -
-
- - Upgrade Instructions - This section contains upgrade instructions from prior versions of CloudStack to Apache CloudStack 4.1.0. We include instructions on upgrading to Apache CloudStack from pre-Apache versions of Citrix CloudStack (last version prior to Apache is 3.0.2) and from the releases made while CloudStack was in the Apache Incubator. - If you run into any issues during upgrades, please feel free to ask questions on users@apache.cloudstack.org or dev@apache.cloudstack.org. -
- Upgrade from 4.0.x to 4.1.0 - This section will guide you from Apache CloudStack 4.0.x versions to &PRODUCT; 4.1.0. - Any steps that are hypervisor-specific will be called out with a note. - Package Structure Changes - The package structure for &PRODUCT; has changed significantly since the 4.0.x releases. If you've compiled your own packages, you'll notice that the package names and the number of packages has changed. This is not a bug. - However, this does mean that the procedure is not as simple as an apt-get upgrade or yum update, so please follow this section carefully. - - We recommend reading through this section once or twice before beginning your upgrade procedure, and working through it on a test system before working on a production system. - - - Most users of &PRODUCT; manage the installation and upgrades of &PRODUCT; with one of Linux's predominant package systems, RPM or APT. This guide assumes you'll be using RPM and Yum (for Red Hat Enterprise Linux or CentOS), or APT and Debian packages (for Ubuntu). - Create RPM or Debian packages (as appropriate) and a repository from the 4.1.0 source, or check the Apache CloudStack downloads page at http://cloudstack.apache.org/downloads.html for package repositories supplied by community members. You will need them for step or step . - Instructions for creating packages from the &PRODUCT; source are in the Installation Guide. - - - For VMware Only - This step is only required if you are using VMware. You can safely skip this step if you are using KVM and/or Xen only. - - In each zone that includes VMware hosts, you need to add a new system VM template. - - - While running the existing 3.0.2 system, log in to the UI as root administrator. - - - In the left navigation bar, click Templates. - - - In Select view, click Templates. - - - Click Register template. - The Register template dialog box is displayed. - - - In the Register template dialog box, specify the following values (do not change these): - - - - - - - Field - Value - - - - - Name - systemvm-vmware-4.1 - - - Description - systemvm-vmware-4.1 - - - URL - http://download.cloud.com/templates/burbank/burbank-systemvm-08012012.ova - - - Zone - Choose the zone where this hypervisor is used - - - Hypervisor - VMware - - - Format - OVA - - - OS Type - Debian GNU/Linux 5.0 (32-bit) - - - Extractable - no - - - Password Enabled - no - - - Public - no - - - Featured - no - - - - - - - Watch the screen to be sure that the template downloads successfully and enters - the READY state. Do not proceed until this is successful. - - - - - Stop your management server or servers. Run this on all management server hosts: - # service cloud-management stop - - - If you are running a usage server or usage servers, stop those as well: - # service cloud-usage stop - - - Make a backup of your MySQL database. If you run into any issues or need to roll back the upgrade, this will assist in debugging or restoring your existing environment. You'll be prompted for your password. - # mysqldump -u root -p cloud > cloudstack-backup.sql - - - Whether you're upgrading a Red Hat/CentOS based system or Ubuntu based system, you're going to need to stop the CloudStack management server before proceeding. - # service cloud-management stop - - - If you have made changes to /etc/cloud/management/components.xml, you'll need to carry these over manually to the new file, /etc/cloudstack/management/componentContext.xml. This is not done automatically. (If you're unsure, we recommend making a backup of the original components.xml to be on the safe side. - - - If you are using Ubuntu, follow this procedure to upgrade your packages. If not, skip to step . - Community Packages - This section assumes you're using the community supplied packages for &PRODUCT;. If you've created your own packages and APT repository, substitute your own URL for the ones used in these examples. - - - - The first order of business will be to change the sources list for each system with &PRODUCT; packages. This means all management servers, and any hosts that have the KVM agent. (No changes should be necessary for hosts that are running VMware or Xen.) - Start by opening /etc/apt/sources.list.d/cloudstack.list on any systems that have &PRODUCT; packages installed. - This file should have one line, which contains: - deb http://cloudstack.apt-get.eu/ubuntu precise 4.0 - We'll change it to point to the new package repository: - deb http://cloudstack.apt-get.eu/ubuntu precise 4.1 - If you're using your own package repository, change this line to read as appropriate for your 4.1.0 repository. - - - Now update your apt package list: - $ sudo apt-get update - - - Now that you have the repository configured, it's time to install the cloudstack-management package. This will pull in any other dependencies you need. - $ sudo apt-get install cloudstack-management - - - You will need to manually install the cloudstack-agent package: - $ sudo apt-get install cloudstack-agent - During the installation of cloudstack-agent, APT will copy your agent.properties, log4j-cloud.xml, and environment.properties from /etc/cloud/agent to /etc/cloudstack/agent. - When prompted whether you wish to keep your configuration, say Yes. - - - Verify that the file /etc/cloudstack/agent/environment.properties has a line that reads: - paths.script=/usr/share/cloudstack-common - If not, add the line. - - - Restart the agent: - - service cloud-agent stop - killall jsvc - service cloudstack-agent start + + + + Welcome to &PRODUCT; 4.1 + Welcome to the 4.1.0 release of &PRODUCT;, the first major release from the Apache + CloudStack project since its graduation from the Apache Incubator. + This document contains information specific to this release of &PRODUCT;, including + upgrade instructions from prior releases, new features added to &PRODUCT;, API changes, and + issues fixed in the release. For installation instructions, please see the Installation Guide. For usage and administration instructions, please see the + &PRODUCT; Administrator's Guide. Developers and users who wish to work with the API + will find instruction in the &PRODUCT; API Developer's Guide + If you find any errors or problems in this guide, please see . We hope you enjoy + working with &PRODUCT;! + + + Version 4.1.0 +
+ What’s New in 4.1 + Apache CloudStack 4.1.0 includes many new features. This section covers the most + prominent new features and changes. +
+ Localization + The 4.1.0 release adds partial User Interface (UI) support for Catalan, Chinese, + French, German, Italian, Japanese, Korean, Norwegian, Portuguese, Russian, and Spanish. + Not all languages are complete. + The 4.1.0 release also adds documentation translations for Chinese, Chinese (Taiwan), + Italian, Japanese, Korean, and Portuguese. +
+
+ Added Region Support + CLOUDSTACK-241: This feature adds a "region" construct that spans several + management servers. The objective of this feature is to add AWS EC2 like Regions + implementation into CloudStack. Regions are dispersed and located in separate geographic + areas. Availability Zones (or Zones in CloudStack) are distinct locations within a Region + that are engineered to be isolated from failures in other Zones and provide inexpensive, + low latency network connectivity to other Zones in the same Region. + Regions are expected to add the following benefits + + + Higher availability of the services: users can deploy services across AZs and even + if one of the AZ goes down the services are still available to the end-user through + VMs deployed in other zones. + + + Higher availability of the Management Server (MS): Since each MS Cluster only + manages a single Region, if that MS Cluster goes down, only that particular Region is + impacted. Admin should be able to access all the other Regions. + + + Scalability: The scalability limit of CloudStack dramatically improves, as the + scalability limit of MS Cluster is limited to a single Region. + + + Object Store: With Regions construct, CloudStack would also allow users to define + Object Store (Secondary Storage) across AZs. This helps users easily deploy VMs in + different AZs using the same template, offerings. + + + Geographical Grouping: Regions allow admins to group AZs (that have low latency + and are geographically located nearby) into a broader region construct. + + + Currently the Region feature is exposed in the API, but does not have a UI + component. +
+
+ Support for EC2 Query API + CLOUDSTACK-197: This introduces a query API for the AWS APIs that are currently + only supported by SOAP. The AWS Java SDK and AWS PHP SDK should now be supported by the + AWSAPI in CloudStack. + Supported Query APIs in 4.1.0: + + + AllocateAddress + + + AssociateAddress + + + AttachVolume + + + AuthorizeSecurityGroupIngress + + + CreateImage + + + CreateKeyPair + + + CreateSecurityGroup + + + CreateSnapshot + + + CreateTags + + + CreateVolume + + + DeleteKeyPair + + + DeleteSecurityGroup + + + DeleteSnapshot + + + DeleteTags + + + DeleteVolume + + + DeregisterImage + + + DescribeAddresses + + + DescribeAvailabilityZones + + + DescribeImageAttribute + + + DescribeImages + + + DescribeInstanceAttribute + + + DescribeInstances + + + DescribeKeyPairs + + + DescribeSecurityGroups + + + DescribeSnapshots + + + DescribeTags + + + DescribeVolumes + + + DetachVolume + + + DisassociateAddress + + + GetPasswordData + + + ImportkeyPair + + + ModifyImageAttribute + + + RebootInstances + + + RegisterImage + + + ReleaseAddress + + + ResetImageAttribute + + + RevokeSecurityGroupIngress + + + RunInstances + + + StartInstances + + + StopInstances + + + TerminateInstances + + + See the Feature Specification for more information on the Query API support. +
+
+ Auto-Completing Shell for CloudStack (CloudMonkey) + CLOUDSTACK-132: Adds a auto-completing shell and command-line tool for + &PRODUCT; written in Python, called CloudMonkey. + CloudMonkey includes the following features: + + + Usable as a command line tool and interactive shell. + + + All commands are lowercase unlike API. + + + Api Discovery using sync feature, with build time api precaching for failsafe + sync. + + + Raw api execution support. + + + Auto-completion via double tab. + + + Reverse search using Ctrl+R + + + Emacs compatible key bindings. + + + Output that's "pipeable" to other *nix programs. + + + Unix shell execution. + + + Support to handle asynchronous jobs using user defined blocking or non-blocking + way. + + + Tabular or JSON output with filtering of table columns. + + + Colored output. + + + API parameter value completion (based on predication, fuzzy results may fail + sometimes). + + + CloudMonkey has a few requirements above and beyond CloudStack, and does not need to + be run on the same machine as a management server. If you wish to run + CloudMonkey you'll need Python 2.5 or later, + readline, Pygments, and + prettytable. CloudMonkey can be installed with + pip: + $ pip install cloudmonkey + See the Developer's Guide and the CloudStack + wiki for the latest information on CloudMonkey + installation and use. +
+
+ API Discovery Service + CLOUDSTACK-926: CloudStack has more than 300 APIs and more are added in each + major release. CloudStack admins can enable or disable APIs, or add plugins which provide + more APIs. The API Discovery Service is a plugin which will help users discover the APIs + available to them on a CloudStack Management Server. + The discovery service implements a method called listApis which + will return information about APIs for a user. It currently accepts an apiName to list api + information of that particular API. The method ensures that user can only list APIs they + are entitled to. + All CloudStack APIs are implemented by annotated command class and PluggableService is + a contract implemented by all the components such as the Management Server and all the + plugins which provide an API. During load time, API discovery service asks all the + pluggable services to return list of API cmd classes from whose fields and annotations it + gathers information about each API, the information consists of name, description, + parameter name, parameter description, etc. + For more information on the implementation of the API Discovery Service for 4.1.0, see + the CloudStack + wiki. +
+
+ Events Framework + CLOUDSTACK-820: The Events Framework provides a mechanism to publish and + subscribe to events in &PRODUCT;. +
+
+ Additional VMX Settings + ### +
+
+ L3 Router Functionality in Nicira Nvp Plugin + ### +
+
+ Persistent Networks without Running VM + ### +
+
+ Add/Remove Network on VM + ### +
+
+ Resize Volumes Feature + ### +
+
+ Autoscale + ### +
+
+ API Request Throttling + CLOUDSTACK-618: Limits the number of API requests per second that can be placed + against a management server to avoid DoS attacks via API requests. + The throttling is controlled by the api.throttling.enabled, + api.throttling.interval, and api.throttling.max + configuration settings. Note that api.throttling.enabled is set to + false by default. +
+
+ S3 Backed Secondary Storage + CLOUDSTACK-509: This enhancement backs NFS secondary storage with an + S3-compatible object store. Periodically, a reaper thread synchronizes the templates, + ISOs, and snapshots stored on a NFS secondary storage mount with a configured S3 object + store. In addition to permitting the use of commodity or IaaS storage solutions for static + assets, it provides a means of automatically synchronizing template and ISO assets across + multiple zones. + See the &PRODUCT; + wiki for more information on this feature, currently the documentation is + incomplete. +
+
+ User and Domain Admin Can Create API Key and Secret + CLOUDSTACK-437: This feature adds the ability for domain admins and users to + create their own API Key and Secret. Domain admins can create keys for themselves, + subdomain admins, and for regular users, but not for other domain admins. +
+
+ Support Inline Mode for F5 and SRX + CLOUDSTACK-306: For &PRODUCT; deployments using the Juniper SRX (firewall) and + F5 Big IP (load balancer), &PRODUCT; 4.1.0 supports putting the firewall in front of the + load balancer, making the firewall device the gateway and putting the load balancer behind + the public network. +
+
+ Egress Firewall Rules for Guest Networks + CLOUDSTACK-299: This feature allows users to create egress (exit) traffic rules + from private networks to public networks (e.g. from your internal + network to the public Internet). By default all traffic is blocked from internal networks + to the public networks, this allows you to open ports as necessary. + Egress traffic rules are suppored only on virtual routers at this time, physical + devices are not supported. +
+
+ Reset SSH Key to Access VM + CLOUDSTACK-297: &PRODUCT; 4.1.0 introduces a new API + resetSSHKeyForVirtualMachine, that can allow them to set or reset the + SSH keypair assigned to a virtual machine. +
+
+
+ Issues Fixed in 4.1.0 + Apache CloudStack uses Jira to track its issues. All new features and bugs for 4.1.0 have been tracked + in Jira, and have a standard naming convention of "CLOUDSTACK-NNNN" where "NNNN" is the + issue number. + This section includes a summary of known issues against 4.0.0 that were fixed in 4.1.0. + Approximately 470 bugs were resolved or closed in the 4.1.0 cycle. + + + + + + + + Defect + + + Description + + + + + + + CLOUDSTACK-46 + + + Remnants of mycloud remain. + + + + + CLOUDSTACK-70 + + + Improve Network Restart Behaviour for Basic Zone: Restarting Network + Fail + + + + + CLOUDSTACK-94 + + + "API command, listIsos documentation clarity + + + + + CLOUDSTACK-95 + + + IP address allocation not working when a user tries to allocate IP addresses + in a Project + + + + + CLOUDSTACK-97 + + + Vmware network labels are ignored when creating a Zone using basic + networking + + + + + CLOUDSTACK-108 + + + VM should not be allowed to be deployed on two Isolated Networks of an Account + that were created from DefaultNetworkOfferingwithSourceNATService + + + + + CLOUDSTACK-118 + + + Status of host resorce stuck in "ErrorInMaintenance" + + + + + CLOUDSTACK-119 + + + Move Agent-Simulator in to the hypervisor plugin model + + + + + CLOUDSTACK-130 + + + Clarify docs on tags parameter in API reference + + + + + CLOUDSTACK-152 + + + Routes on the User VM are programmed incorrectly on a VM present on both + Isolated and Shared Guest Network + + + + + CLOUDSTACK-178 + + + Expose name parameter of VM in list Vm view. + + + + + CLOUDSTACK-198 + + + vpn:failto add VPN Users deletes all the existing Vpn user + + + + + CLOUDSTACK-222 + + + Admin UI prompts to restart Management server with cancel edit + operation + + + + + CLOUDSTACK-225 + + + API Docs: Request params repeated with different description + + + + + CLOUDSTACK-226 + + + UpdatePhysicalNetworkcommand failed due to java.sql.BatchUpdateException ; + Tried to extend the existing Guest VLAN Range of one physical network into the + Guest VLAN range of the other physical network + + + + + CLOUDSTACK-227 + + + ReconnectHostCmd: NullPointerException: Unable to get host Information for + XenServer 6.0.2 host - on intentionally changing the traffic labels on the + physical network + + + + + CLOUDSTACK-228 + + + UI provides an option to reconnect a disconnected host - ServerApiException is + thrown on an attempt + + + + + CLOUDSTACK-232 + + + Zone infrastructure chart -- disable resource total display + + + + + CLOUDSTACK-235 + + + Network rate can be set in 2 places. Clarify docs on how this works + + + + + CLOUDSTACK-249 + + + Add host id to failed VM deploy alerts + + + + + CLOUDSTACK-250 + + + Incorrect description of maintenance mode in admin guide + + + + + CLOUDSTACK-256 + + + "vpn:As an admin user, not able to delete VPN user which is present in a + regular user's network. + + + + + CLOUDSTACK-271 + + + updatePhysicalNetwork dies with an NPE when the vlan range is empty + + + + + CLOUDSTACK-274 + + + Two error codes mapped to same value in API + + + + + CLOUDSTACK-275 + + + hostid not always a UUID + + + + + CLOUDSTACK-277 + + + Message during CloudStack management server Installation: cannot access + /usr/share/cloud/bridge/lib: No such file or directory + + + + + CLOUDSTACK-279 + + + deleteProject fails when executed by the regular user (works fine for + root/domain admin) + + + + + CLOUDSTACK-284 + + + listVirtualMachines does not return deleted machines when zone is + specified + + + + + CLOUDSTACK-290 + + + 3.0.0 template also needed for 2.2.14 to 3.0.5 direct upgrade. + + + + + CLOUDSTACK-293 + + + "We do awful, hacky things in our spec file for client" + + + + + CLOUDSTACK-304 + + + Add synchronization for createSnapshot command per host basis + + + + + CLOUDSTACK-309 + + + iptables rules being deleted from wrong VM after a migration + + + + + CLOUDSTACK-318 + + + Adding XenServer Host Fails - 6.0.2 fails with 4.0.0 + + + + + CLOUDSTACK-320 + + + "sessionKey query parameter should be case-insensitive, now only sessionkey is + accepted" + + + + + CLOUDSTACK-322 + + + During upgrade displays error - a foreign key constraint fails + (`cloud/#sql-f34_6e`.. + + + + + CLOUDSTACK-332 + + + "count" property in list* API response should be equal to how many entries in + database, not how many objects in API response + + + + + CLOUDSTACK-333 + + + When Datacenter name in VCenter has spaces Primary Storage (VMFS) discovery + will fail + + + + + CLOUDSTACK-335 + + + KVM VPC load balancer not working + + + + + CLOUDSTACK-336 + + + listZones doesn't honour paging + + + + + CLOUDSTACK-343 + + + "Document what tools and packages are required to build, package and install + CloudStack 4.0 + + + + + CLOUDSTACK-346 + + + Cannot add Vmware cluster with class loader conflict exception + + + + + CLOUDSTACK-347 + + + listNetworks API: return vlan information only when the caller is ROOT + admin + + + + + CLOUDSTACK-348 + + + deleteNetwork does not clean up network resource count correctly + + + + + CLOUDSTACK-354 + + + Display of storage statistics is wrong + + + + + CLOUDSTACK-355 + + + "Fix ""count"" in a bunch of API commands + + + + + CLOUDSTACK-357 + + + "ISOs can be deleted while still attached to a running VM, and they + subsequently cannot be detached from a running VM + + + + + CLOUDSTACK-359 + + + PropagateResourceEventCommand failes in cluster configuration + + + + + CLOUDSTACK-361 + + + Wrong creation of guest networks on a KVM host in Multiple Physical Networks + with guest traffic + + + + + CLOUDSTACK-364 + + + Docs point to download.cloud.com for AWS API script + + + + + CLOUDSTACK-368 + + + OVM - cannot create guest VM + + + + + CLOUDSTACK-369 + + + ASF 4.0 - unable to support XenServer 6.1 host + + + + + CLOUDSTACK-373 + + + "static NAT and Firewall is not working on external firewall device SRX, it + needs to be implemented + + + + + CLOUDSTACK-377 + + + provide deployment config access to marvin's testcase + + + + + CLOUDSTACK-378 + + + mavenize marvin on master + + + + + CLOUDSTACK-390 + + + Install Guide: Section 4.5.7 (Prepare the System VM Template): Links go to + cloud.com + + + + + CLOUDSTACK-397 + + + Install Guide: Section 11.1 (Guest Traffic): Diagram is the wrong + diagram + + + + + CLOUDSTACK-398 + + + Install Guide: Section 11.17.3 (Using VPN with Mac OSX): Not complete + + + + + CLOUDSTACK-404 + + + Update docs on the usage of cloud-setup-database + + + + + CLOUDSTACK-412 + + + Data truncation: Out of range value for column 'ram' at row + + + + + CLOUDSTACK-415 + + + restartNetwork call causes VM to be unreachable when Nicira based SDN is + used + + + + + CLOUDSTACK-416 + + + XCP 1.6beta2 (61002c) - can't add a host + + + + + CLOUDSTACK-417 + + + Handle password server securely to run on port 8080 on VR + + + + + CLOUDSTACK-424 + + + Updated userdata not propagating to the VR + + + + + CLOUDSTACK-427 + + + Change hardcoded step number references to dynamic link + + + + + CLOUDSTACK-428 + + + Storage capacity shown in UI is incorrect + + + + + CLOUDSTACK-435 + + + Vmware network labels are ignored when creating a Zone using basic + networking + + + + + CLOUDSTACK-441 + + + Running mgmt server using jetty fails to start api server + + + + + CLOUDSTACK-446 + + + "Host going to alert state, if you are adding already added host + + + + + CLOUDSTACK-448 + + + SSVM bootstrap failure on XenServer hosts with E3 CPU + + + + + CLOUDSTACK-456 + + + License tag in SPEC isn't what RPM is expecting + + + + + CLOUDSTACK-459 + + + [Optional Public IP assignment for EIP with Basic Zone] Associate IP Checkbox + in Create Network Offering Dialog is Displayed When Elastic LB is Selected + + + + + CLOUDSTACK-462 + + + A few corrections to make to the 4.0.0 installation guide + + + + + CLOUDSTACK-464 + + + "Regression in AWSAPI docs, entire sections removed + + + + + CLOUDSTACK-465 + + + French language file quotes are dropping javascript syntax error + + + + + CLOUDSTACK-467 + + + Developer's Guide points to cloud.com for API reference + + + + + CLOUDSTACK-479 + + + UpdateVirtualMachine api fails to propagate userdata to domr + + + + + CLOUDSTACK-481 + + + Installation Guide Doc Error + + + + + CLOUDSTACK-493 + + + 2.2.x-3.0 DB upgrade support for Advance SG enabled network + + + + + CLOUDSTACK-499 + + + cloudmonkey CLI can't accept complex parameter + + + + + CLOUDSTACK-500 + + + Passwd-server iptables rules are dropped on domr on fresh start or on + reboot. + + + + + CLOUDSTACK-501 + + + Apidocs and marvin does not know how to handle Autoscaling docs. + + + + + CLOUDSTACK-504 + + + Duplicate guest password scripts in codebase. + + + + + CLOUDSTACK-507 + + + fix api docs for listSSHKeyPair + + + + + CLOUDSTACK-508 + + + CLVM copies template to primary storage unnecessarily. + + + + + CLOUDSTACK-510 + + + Add button not visible when adding public IPs to physical network. + + + + + CLOUDSTACK-514 + + + Marvin and Cloudmonkey don't work when an API target uses https or an + alternate path. + + + + + CLOUDSTACK-518 + + + API refactoring -- change @Parameter annotation and remove the @IdentityMapper + annotation. + + + + + CLOUDSTACK-520 + + + Dependency jar names mismatch with install-non-oss.sh + + + + + CLOUDSTACK-521 + + + Build will hung up when doing test for TestAgentShell + + + + + CLOUDSTACK-522 + + + Log requests in cloudmonkey's log file. + + + + + CLOUDSTACK-527 + + + List API performance optimization by using DB views and removing UUID + conversion. + + + + + CLOUDSTACK-534 + + + Failed to add host + + + + + CLOUDSTACK-536 + + + remove citrix cloudpatform from 4.0 build - CloudStack is ASF project. + + + + + CLOUDSTACK-539 + + + Cropped Text in UI under Quick View. + + + + + CLOUDSTACK-552 + + + ]Quick view details for a volume displays scroll bar in place of name of the + volume when the name of the volume has more no of characters. + + + + + CLOUDSTACK-553 + + + "SRX - When adding SRX device make "Public Network" - default to "untrusted" + and "Private Network" - default to "trusted" as un-editable fields. + + + + + CLOUDSTACK-556 + + + Erratic window behavior in Quick View tooltip. + + + + + CLOUDSTACK-559 + + + source code import problem + + + + + CLOUDSTACK-560 + + + Usage server doesn't work in 4.0.0 due to missing db changes + + + + + CLOUDSTACK-572 + + + SG Enabled Advanced Zone - Not able to deploy a VM in an account specific + shared network + + + + + CLOUDSTACK-573 + + + "NPE at + ""com.cloud.network.NetworkManagerImpl.networkOfferingIsConfiguredForExternalNetworking(NetworkManagerImpl.java:4345)"" + when create network from the network offering having NULL provider for the + service + + + + + CLOUDSTACK-578 + + + The already deleted same hostname is not deleted from /etc/hosts of + vRouter + + + + + CLOUDSTACK-584 + + + "typos in + ""Apache_CloudStack-4.0.0-incubating-CloudStack_Nicira_NVP_Guide-en-US"" + + + + + CLOUDSTACK-590 + + + Incorrect Network Gateways Assigned to System VM + + + + + CLOUDSTACK-592 + + + "API bloat, unknown apis cmd classes + + + + + CLOUDSTACK-593 + + + "2 guest network, auto create vlan error + + + + + CLOUDSTACK-596 + + + DeployVM command takes a lot of time to return job id. + + + + + CLOUDSTACK-599 + + + DhcpEntryCommand fails on Router VM on CS4.0 and vSphere5 with Advanced + Network Zone. + + + + + CLOUDSTACK-600 + + + When rebooting KVM local storage VM host, libvirt definitions deleted + + + + + CLOUDSTACK-605 + + + Host physical CPU is incorrectly calculated for Vmware host + + + + + CLOUDSTACK-606 + + + Starting VM fails with 'ConcurrentOperationException' in a clustered MS + scenario + + + + + CLOUDSTACK-614 + + + "ListTemplates API is not returning ""Enable SSH Key"" attribute for any given + template + + + + + CLOUDSTACK-617 + + + Unable to edit a Sub domain + + + + + CLOUDSTACK-639 + + + API Refactoring: Adapters for ACL + + + + + CLOUDSTACK-648 + + + The normal users could change their own login password. + + + + + CLOUDSTACK-660 + + + Network Traffic Labels are not functional in Marvin + + + + + CLOUDSTACK-683 + + + Image Is Missing in the Accessing VM Section + + + + + CLOUDSTACK-689 + + + RVR: Stop pending flag is not cleared when user start the disconnected router + from another host + + + + + CLOUDSTACK-691 + + + A warning dialog box shows after reloading the welcome page. + + + + + CLOUDSTACK-693 + + + Adding a VPC virtual router to a NiciraNVP enabled network fails. + + + + + CLOUDSTACK-694 + + + "Create a new VPC network offering with "connectivity" option needed for SDN + networking) is not allowed / VPC support for SDN networks + + + + + CLOUDSTACK-717 + + + cloudmonkey fails to parse/print response. + + + + + CLOUDSTACK-720 + + + Fail to load a png image when accessing the web console. + + + + + CLOUDSTACK-721 + + + Bytes sent/received in user statistics is empty (CloudStack 4.0) + + + + + CLOUDSTACK-725 + + + UI: Error when the Egress rules tab is selected for a network. + + + + + CLOUDSTACK-734 + + + api_refactoring: CreateAccountCmd fails to send response due to NPE in service + layer + + + + + CLOUDSTACK-735 + + + Integration smoke tests: Fix expunge vm test on api_refactoring + + + + + CLOUDSTACK-736 + + + Integration smoke tests: Fix check for vm name for the deployvm smoke + test. + + + + + CLOUDSTACK-793 + + + "Create cloudmonkey-helper, a plugin that helps autodiscover and sync api info + via an api over some endpoint + + + + + CLOUDSTACK-798 + + + Move usage related cmd classes from cloud-server to cloud-api + + + + + CLOUDSTACK-799 + + + [Load Test] Check router statistics falls behind in gathering stats by more + than 2 times the set value + + + + + CLOUDSTACK-819 + + + Create Account/User API logging password in access log + + + + + CLOUDSTACK-863 + + + Non-printable characters (ASCII control character) such as %00 or %0025 are + getting stored in raw/non encoded form in the database + + + + + CLOUDSTACK-870 + + + Client UI: Wrong character encoding for some language + + + + + CLOUDSTACK-928 + + + [Simulator] Latency for Agent Commands - change unit of wait from seconds to + milliseconds + + + + + CLOUDSTACK-938 + + + s2s VPN trouble + + + + + CLOUDSTACK-959 + + + Missing sub-sections in document section System Service Offering + + + + + CLOUDSTACK-968 + + + marvin: vlan should be an attribute of the physical_network and not the + zone + + + + + CLOUDSTACK-977 + + + Document how to use openvswitch with KVM hypervisor + + + + + CLOUDSTACK-978 + + + TypeError: instance.displayname is undefined while adding VM's to the LB + rule + + + + + CLOUDSTACK-985 + + + Different MAC address for RvR caused issue in short term network outage + + + + + CLOUDSTACK-987 + + + Sections missing in Working With Snapshots + + + + + CLOUDSTACK-993 + + + "admin"" user is not getting created when management server is started. + + + + + CLOUDSTACK-995 + + + Not able to add the KVM host + + + + + CLOUDSTACK-1002 + + + Not able to start VM + + + + + CLOUDSTACK-1006 + + + need to disable service libvirt-guests in CentOS packaging RPMs, or in + installation docs + + + + + CLOUDSTACK-1008 + + + "Egress"" tab should not be presented in the UI for Shared Networks + + + + + CLOUDSTACK-1010 + + + Host count and Secondary storage count always shows 1 in UI + + + + + CLOUDSTACK-1011 + + + KVM host getting disconnected in cluster environment + + + + + CLOUDSTACK-1013 + + + running cloudstack overwrites default public/private ssh key + + + + + CLOUDSTACK-1014 + + + Merge ManagementServer and ManagementServerEx + + + + + CLOUDSTACK-1016 + + + Not able to deploy VM + + + + + CLOUDSTACK-1021 + + + the vlan is not creat to right nic. when i creat multi guest network + + + + + CLOUDSTACK-1024 + + + Regression: Unable to add Xenserver host with latest build. + + + + + CLOUDSTACK-1027 + + + "Update SSL certificate" button should properly reflect its + functionality + + + + + CLOUDSTACK-1029 + + + Enter the token to specified project is malfunctioned + + + + + CLOUDSTACK-1037 + + + "Make cloudmonkey awesome-er: Online help docs and api discovery, better + colored output, parameter value autocompletion + + + + + CLOUDSTACK-1050 + + + No Documentation on Adding a Load Balancer Rule + + + + + CLOUDSTACK-1051 + + + API dispatcher unable to find objectVO corresponding to + DeleteTemplatecmd + + + + + CLOUDSTACK-1055 + + + "The overlay still exists when the ""Recurring Snapshots"" dialog is canceled + by pressing esc key. + + + + + CLOUDSTACK-1056 + + + S3 secondary storage fails to upload systemvm template due to KVMHA + directory + + + + + CLOUDSTACK-1057 + + + regression of changeServiceForVirtualMachine API - fails to find service + offering by serviceOfferingId parameter + + + + + CLOUDSTACK-1063 + + + "SG Enabled Advanced Zone - "Add Guest Networks" - When user tries to add a + guest Network with scope as "Account" he should NOT be presented with "Offering + for shared security group enabled" + + + + + CLOUDSTACK-1064 + + + A type error occurs when trying to add account/register template... + + + + + CLOUDSTACK-1068 + + + Names in VR list is useless + + + + + CLOUDSTACK-1070 + + + javelin: NPE on executing registerIso API + + + + + CLOUDSTACK-1071 + + + Netscaler element is not getting loaded as part of LoadBalancing Service + Providers + + + + + CLOUDSTACK-1078 + + + Not able to start System Vms on Rhel 6.3 KVM host + + + + + CLOUDSTACK-1079 + + + Deploying AWSAPI with mvn -pl :cloud-awsapi jetty:run fail + + + + + CLOUDSTACK-1082 + + + UI doesn't throw any error message when trying to delete ip range from a + network that is in use. + + + + + CLOUDSTACK-1083 + + + listUsageRecords api: removed project results in NPE + + + + + CLOUDSTACK-1087 + + + Update the Developer Guide for ASFCS 4.1 Release + + + + + CLOUDSTACK-1088 + + + EnableStaticNat error will clear the data in database + + + + + CLOUDSTACK-1094 + + + Ipv6 - hostname/hostname --fqdn does not return the name of the VM. But i am + able to reach the Vm using their names + + + + + CLOUDSTACK-1095 + + + Ipv6 - dhclient command needs to be run manually on the Vms to get the Ipv6 + address + + + + + CLOUDSTACK-1100 + + + Expunge thread is not kicked off based on global configuration if the global + setting is less than 60 seconds + + + + + CLOUDSTACK-1103 + + + "IpV6 - listNetwork() command does not retrun gateway,netmask,cidr + + + + + CLOUDSTACK-1104 + + + Ipv6 - listVlanIpRanges() returns error 530 + + + + + CLOUDSTACK-1105 + + + "IpV6 - listVirtualMachines() does not return netmask, + gateway,ipaddress. + + + + + CLOUDSTACK-1107 + + + Ipv6 - Unable to extend Ip range for a Ipv6 network using craeteVlanIpRange() + command - Error code 530 returned + + + + + CLOUDSTACK-1108 + + + Ipv6 - Not able to restart Networks + + + + + CLOUDSTACK-1109 + + + "Ipv6 - Unable to expunge User Vms that are "Destroyed". + + + + + CLOUDSTACK-1111 + + + Ipv6 - listRouters() does not return guestipaddress/ + + + + + CLOUDSTACK-1112 + + + "Errors in "Prepare the System VM Template" + + + + + CLOUDSTACK-1113 + + + "Ipv6 - Not able to deploy a new VM in this network because of "Unable to + allocate Unique Ipv6 address" + + + + + CLOUDSTACK-1114 + + + unable to execute listegressfirewallrules API due invalid value id + + + + + CLOUDSTACK-1115 + + + In multiple shared network unable to login with default nic - KVM + + + + + CLOUDSTACK-1123 + + + ListStoragePools API broken by refactor + + + + + CLOUDSTACK-1138 + + + "Providing invalid values for gateway, netmask etc in the zoneWizard blocks + the VLAN container to load, throwing an error + + + + + CLOUDSTACK-1139 + + + "After the Vm is "Expunged" we see the entry still being present in the router + in /etc/dhcphosts.txt + + + + + CLOUDSTACK-1141 + + + "Ipv6 - After network restart (and reboot router), we do not see the existing + vms dnsentries not being programmed in the router. + + + + + CLOUDSTACK-1152 + + + Missing tag in host-add.xml + + + + + CLOUDSTACK-1153 + + + "Ipv6 - Vm deployment fails with "n must be positive" error. + + + + + CLOUDSTACK-1154 + + + Account/Users related API failed due to RegionService inject exception. + + + + + CLOUDSTACK-1157 + + + No API Documentation on Listing Custom User Templates Using CS4 API + + + + + CLOUDSTACK-1160 + + + References to version=3.0.3|4|5|6 in API classes needs to be removed. + + + + + CLOUDSTACK-1161 + + + Differences between 4.1 and master in + ongoing-config-of-external-firewalls-lb.xml + + + + + CLOUDSTACK-1163 + + + Failed with NPE while creating firewall rule + + + + + CLOUDSTACK-1168 + + + Create firewall rule broke + + + + + CLOUDSTACK-1173 + + + ConsoleProxyResource instantiation exception. + + + + + CLOUDSTACK-1174 + + + Snapshots related SQL error. + + + + + CLOUDSTACK-1176 + + + Issue with snapshots(create/list) + + + + + CLOUDSTACK-1181 + + + mvn deploy db failing with NPE + + + + + CLOUDSTACK-1190 + + + Make APIChecker interface throw a single sensible exception. + + + + + CLOUDSTACK-1200 + + + "Unknown column 'vm_instance.disk_offering_id' in table vm_instance, db + exception shown in MS log + + + + + CLOUDSTACK-1201 + + + "Failed to create ssh key for user "cloud" + /var/lib/cloud/management/.ssh/id_rsa and failed to start management server + + + + + CLOUDSTACK-1202 + + + Fail to install KVM cloud-agent. + + + + + CLOUDSTACK-1203 + + + Fail to create advance zone with SG enabled when UI allows SG enabled + option. + + + + + CLOUDSTACK-1204 + + + Fail to create advance zone due to fail to add host + + + + + CLOUDSTACK-1205 + + + Ipv6 - Ubuntu 12.10 guest Vms loses default route (after it expiration time ~ + 30 mts) when ipv6.autoconfig parameters are disabled except for + net.ipv6.conf.lo.autoconf which is enabled. + + + + + CLOUDSTACK-1206 + + + Failure in Copy of System template + + + + + CLOUDSTACK-1210 + + + Make all pluggable services return list of api cmd classes + + + + + CLOUDSTACK-1216 + + + UUID is null for admin and failed to register user key with 4.0 + + + + + CLOUDSTACK-1218 + + + "IPv6: Shared Network - After network restart with clean option, router is + assigned a different address. Name resolution for the existing guest Vms in the + network fails. + + + + + CLOUDSTACK-1219 + + + Ipv6 - Provide better error messages when deploying a Vm with Ip an address + that is outside the network's ip range / if the ip address already is assigned to + another Vm + + + + + CLOUDSTACK-1220 + + + Ipv6 - Better error message when deploy Vm fails to get a free Ip + address + + + + + CLOUDSTACK-1222 + + + API rate limit configs: removed double quote in upgrade script + + + + + CLOUDSTACK-1223 + + + Exception while starting jetty server: + org.springframework.beans.factory.BeanCreationException Error creating bean with + name 'apiServer' + + + + + CLOUDSTACK-1224 + + + Volume snapshot creation failing + + + + + CLOUDSTACK-1226 + + + Error while running Cloudstack-setup-database + + + + + CLOUDSTACK-1228 + + + Unable to Create System Vm's in the VMware Hypervisor setup + + + + + CLOUDSTACK-1229 + + + Incorrect SQL syntax to insert api limit related configuration items in + upgrade path script. + + + + + CLOUDSTACK-1231 + + + cloud-install-sys-tmplt failed due to missing path + + + + + CLOUDSTACK-1232 + + + "Ipv6 - Guest Vms are not able to get Ipaddress when executing dhclient + command when using ""/96"" network. + + + + + CLOUDSTACK-1233 + + + Veewee configuration files are inappropriately identified as ASLv2 licensed + file + + + + + CLOUDSTACK-1234 + + + Unable to start KVM agent with 4.1 build. + + + + + CLOUDSTACK-1237 + + + "Register Template fails with ""Cannot find template adapter for + XenServer"" + + + + + CLOUDSTACK-1239 + + + Unable to registerISO :unhandled exception executing api command: + registerIso + + + + + CLOUDSTACK-1240 + + + Unable to registerTemplate : Cannot find template adapter for + XenServer. + + + + + CLOUDSTACK-1241 + + + Network apply rules logic is broken. + + + + + CLOUDSTACK-1242 + + + [F5-SRX-InlineMode] Failed to create LB rule with F5-SRX inlinemode + deployment + + + + + CLOUDSTACK-1243 + + + Failed to cleanup account :java.lang.NullPointerException + + + + + CLOUDSTACK-1244 + + + fail to push sysmvm.iso onto xen host + + + + + CLOUDSTACK-1246 + + + "[ ALU beta CS 4.1 build2] ""Guest network"" missing in Add Zone wizard ( step + 3, Setup Network \ Physical Network) + + + + + CLOUDSTACK-1251 + + + Baremetal zone doesn't need primary/secondary storage in UI wizard. + + + + + CLOUDSTACK-1252 + + + Failed to download default template in VMware. + + + + + CLOUDSTACK-1260 + + + Failed to register template: Unable to find template adapter + + + + + CLOUDSTACK-1261 + + + Cannot find template adapter for XenServer. + + + + + CLOUDSTACK-1262 + + + "Failed to Prepare Secondary Storage in VMware, + + + + + CLOUDSTACK-1265 + + + logrotate dnsmasq configuration is wrong + + + + + CLOUDSTACK-1267 + + + KVM's cloudstack-agent service doesn't log (log4j) + + + + + CLOUDSTACK-1269 + + + Failed to start CPVM java.lang.NullPointerException Unable to start + SSVM + + + + + CLOUDSTACK-1272 + + + Autoscale: createAutoScaleVmProfile fails due to unable to retrieve Service + Offering ip + + + + + CLOUDSTACK-1274 + + + UpdateNetworkCmd throws NP + + + + + CLOUDSTACK-1276 + + + Remove autoscanning for 4.1 + + + + + CLOUDSTACK-1277 + + + ApiResponseHelper.createUserVmResponse failed to populate password field set + from UserVm object + + + + + CLOUDSTACK-1278 + + + Improper permissions on injectkeys.sh + + + + + CLOUDSTACK-1288 + + + [F5-SRX-InlineMode] classCastException during network restart with cleanup + option true + + + + + CLOUDSTACK-1289 + + + [F5-SRX-InlineMode] Usage stats are not generated for Juniper SRX Firewall in + inlinemode + + + + + CLOUDSTACK-1290 + + + listNetoworks API takes too long to respond + + + + + CLOUDSTACK-1292 + + + "[F5-SRX-InlineMode] Update network from SRX,F5 as service provideds to VR as + service provider does not delete firewall rules from SRX + + + + + CLOUDSTACK-1295 + + + NPE in usage parsers due to missing @Component inject + + + + + CLOUDSTACK-1299 + + + Errors in 4.5.5 section of installation guide + + + + + CLOUDSTACK-1300 + + + section in wrong order in installation guide + + + + + CLOUDSTACK-1303 + + + Ipv6 - java.lang.NullPointerException when executing listnetworks() and + deployVirtualMachine() after extending the Ipv4 range of a dual stack + network + + + + + CLOUDSTACK-1307 + + + Noticed NPE when we put host in maintenance mode in clustered management + setup + + + + + CLOUDSTACK-1310 + + + ASF-build-master-nonoss-rhel63 - create advance zone FAIL - + CreatePhysicalNetworkCmd FAIL - MySQLIntegrityConstraintViolationException: + Duplicate entry '200-Public' for key 'physical_network_id' + + + + + CLOUDSTACK-1312 + + + "Fix rolling upgrades from 4.0 to 4.1 in 4.1 release, fix db schemas to be + same as 4.0 + + + + + CLOUDSTACK-1313 + + + Working with Volumes Section Is Missing + + + + + CLOUDSTACK-1315 + + + [F5-SRX-InlineMode] Network implement failed with Run time Exception during + network upgrade from VR to SRX-F5 + + + + + CLOUDSTACK-1319 + + + createCustomerVpnGateway response gives TypeError: + json.createvpncustomergatewayresponse is undefined + + + + + CLOUDSTACK-1320 + + + Routers naming convention is changed to hostname. + + + + + CLOUDSTACK-1321 + + + [Site-to-Site VPN] No events are generated in case of status change in site to + site vpn connection + + + + + CLOUDSTACK-1326 + + + KVM - Failed to start cloud agent from SSVM + + + + + CLOUDSTACK-1328 + + + console view unable to connect - CPVM SSVM guest VM + + + + + CLOUDSTACK-1329 + + + "API listRouters response returns hostname instead of Virtual Routers, UI + displays host entry for each VR + + + + + CLOUDSTACK-1330 + + + ec2-run-instances - When -n option is used to deploy multiple Vms API returns + error even though few of the Vms have been deployed successfully + + + + + CLOUDSTACK-1331 + + + Upgrade fails for a 2.2.14 Zone having multiple guest networks using + network_tags and Public Vlan + + + + + CLOUDSTACK-1332 + + + IPV6 - Router and guest Vms should be able to use an IPV6 address for external + DNS entry + + + + + CLOUDSTACK-1334 + + + vmware.root.disk.controller doesn't work + + + + + CLOUDSTACK-1337 + + + Zone to zone template/ISO copy fails and template/ISO download also + fail + + + + + CLOUDSTACK-1338 + + + Deploy VM failed using IS + + + + + CLOUDSTACK-1339 + + + ASF 4.1: Management server becomes unresponsive + + + + + CLOUDSTACK-1341 + + + URL for the KEYs file is wrong in the installation guide + + + + + CLOUDSTACK-1342 + + + Document installation and usage of cloudmonkey for 4.1 docs + + + + + CLOUDSTACK-1343 + + + Porting Baremetal related UI changes to ACS + + + + + CLOUDSTACK-1344 + + + Typo in use.external.dns setting description + + + + + CLOUDSTACK-1345 + + + BigSwitch plugin introduces 'VNS' isolation in UI without backend + implementation + + + + + CLOUDSTACK-1346 + + + "Check to see if external devices are used in the network, is hardcoded for + specific devices + + + + + CLOUDSTACK-1347 + + + "Not able to delete network. Error - "Unable to insert queue item into + database, DB is full?" + + + + + CLOUDSTACK-1348 + + + API/UI: zoneObj is undefined. + + + + + CLOUDSTACK-1349 + + + "VPC network Adding Network ACls, PF rules - Unable to insert queue item into + database, DB is full? PF rules and NW Acls in Add state in DB + + + + + CLOUDSTACK-1350 + + + Management server Stop and start causes previously downloaded ISOs and + templates to redownload & reinstall. + + + + + CLOUDSTACK-1353 + + + KVM 6.3 snapshot Scheduling snapshot failed due to + java.lang.NullPointerException + + + + + CLOUDSTACK-1357 + + + "Autoscale: Provisioned VMs from Netscaler not being added to lb vserver, + provserver fails with provserver_err_asynctaskpoll + + + + + CLOUDSTACK-1360 + + + The clusterid field of the createStoragePool API command should be documented + as required. + + + + + CLOUDSTACK-1367 + + + NPE noticed in logs while AgentMonitor is monitoring the host ping + interval + + + + + CLOUDSTACK-1368 + + + Shared network - Not able to delete network because of + java.lang.NullPointerException + + + + + CLOUDSTACK-1369 + + + "Ipv6 - In dual Stack network, guest VM does not have the Ipv6 address of the + router programmed in /etc/resolv.conf for DNS resolution. + + + + + CLOUDSTACK-1370 + + + DeployVM Fail - VPC or non-VPC network + + + + + CLOUDSTACK-1375 + + + deploydb failing with acs master + + + + + CLOUDSTACK-1376 + + + Unable to migrate VM due to internal error process exited while connecting to + monitor + + + + + CLOUDSTACK-1377 + + + HA fail - when host is shutdown, VMs and SSVMs are not failover to second host + in cluster. + + + + + CLOUDSTACK-1382 + + + vm deploy fails with Error "cannot find DeployPlannerSelector for vm" + + + + + CLOUDSTACK-1383 + + + Deploying basic zone on 4.1 fails in NPE + + + + + CLOUDSTACK-1386 + + + BASIC zone SSVM fail to start due to exception + + + + + CLOUDSTACK-1388 + + + UI - ListUsers doesnt display any User except the Default Root Admin + User + + + + + CLOUDSTACK-1391 + + + EventBus is not getting injected after javelin merge + + + + + CLOUDSTACK-1394 + + + [F5-SRX-InlineMode] Failure in static nat configuration on SRX does not result + in LB configuration error in CS during LB rule configuration + + + + + CLOUDSTACK-1397 + + + Static Nat configuration is failing with NPE + + + + + CLOUDSTACK-1399 + + + Unhandled exception executing api command: stopVirtualMachine + + + + + CLOUDSTACK-1402 + + + listRouters API response doesn't return linklocal IP and public IP + details + + + + + CLOUDSTACK-1403 + + + Storage and console-proxy related error + + + + + CLOUDSTACK-1411 + + + Issues with VMWare Hypervisor host_ids not updated when ESX(i) crashes in + instance table + + + + + CLOUDSTACK-1414 + + + Redundant router: BACKUP switch cancelled due to lock timeout after a glitch + in network. + + + + + CLOUDSTACK-1417 + + + When invalid values are passed to createNetwork(), error message does not + indicate the parameter name that has invalid values. + + + + + CLOUDSTACK-1418 + + + As regular user, we are not allowed to deploy VM on a shared network. + + + + + CLOUDSTACK-1419 + + + Apache-ify and apply trademark logos in the UI + + + + + CLOUDSTACK-1420 + + + Ensure trademarks are properly attributed in publican brand + + + + + CLOUDSTACK-1423 + + + Unable to launch UI [HTTP Status 404]. + + + + + CLOUDSTACK-1425 + + + unhandled exception executing api command: migrateVirtualMachine & + recoverVirtualMachine + + + + + CLOUDSTACK-1427 + + + Failed to delete Guestnetwork which has LB with Netscaler + + + + + CLOUDSTACK-1428 + + + [UI] Instance which are created without display name are not visible when + added to LB + + + + + CLOUDSTACK-1429 + + + single account is unable to use same vnet across multiple physical + network + + + + + CLOUDSTACK-1436 + + + 4.1 management server fails to start from RPM build artifact + + + + + CLOUDSTACK-1443 + + + As domain admin we are allowed to create shared network + + + + + CLOUDSTACK-1446 + + + [UI]VPC Router type should be of type vpc and not system + + + + + CLOUDSTACK-1447 + + + [UI]Persistent Status is not displayed for VPC Tier + + + + + CLOUDSTACK-1449 + + + listAccounts and listProjectAccounts API lists all the users not + account-specific users for each account returned + + + + + CLOUDSTACK-1451 + + + Getting EntityExistsException while creating more than one project in CS + 4.1 + + + + + CLOUDSTACK-1452 + + + Public IP's are assigned to private interface with VPC Restart [PF/LB rules + are not functional + + + + + CLOUDSTACK-1461 + + + "Ipv6 - From a Vm that that is part of 2 networks, non default network + router's details should not get programmed in the DNS entries of the guest + VM. + + + + + CLOUDSTACK-1463 + + + IPV6 - Ubuntu 12.10 - Multiple Nic - IPV6 address is assigned automatically + for 1 nic only. Need to do a manual dhclient request to get the ipv6 for other + nic. + + + + + CLOUDSTACK-1464 + + + "IPV6 - Multi nic - Ubuntu 1210 -When Vm is stopped and started/ rebooted, i + get multiple global IPV6 addresses being allocated for one of the nics. + + + + + CLOUDSTACK-1465 + + + List Zones returns null under create instance when logged is as user + + + + + CLOUDSTACK-1467 + + + Failed to create Volume for the System VMs + + + + + CLOUDSTACK-1469 + + + kvm agent: agent service fails to start up + + + + + CLOUDSTACK-1470 + + + unhandled exception executing api command: deployVirtualMachine + + + + + CLOUDSTACK-1472 + + + AssignVirtualMachine API with wrong Virtual Instance ID failed with NPE + + + + + CLOUDSTACK-1473 + + + deleteDomain is failing with NPE + + + + + CLOUDSTACK-1481 + + + "IPV6 - When Vm is part of 1 dual network and 1 ipv6 network, name resolution + using fqdn fails for the ipv6 network. + + + + + CLOUDSTACK-1482 + + + IPV6 - We are not allowed to create a shared IPV6 network with a VLAN which + already is associated with a IPV4 network + + + + + CLOUDSTACK-1484 + + + API Throttling : api.throttling.enabled, Global setting missing + + + + + CLOUDSTACK-1485 + + + Add Baremetal Provider back to 4.1 branch + + + + + CLOUDSTACK-1487 + + + cloudstack-setup-agent fails to set private.network.device on KVM host + add + + + + + CLOUDSTACK-1488 + + + "Ipv6 - When Vm is deployed as part of multiple networks, one of the IPV6 + address assigned to guest VM is lost. + + + + + CLOUDSTACK-1490 + + + 4.1 deb management fails to start due to tomcat dep problem + + + + + CLOUDSTACK-1496 + + + List API Performance: listAccounts failing with OOME for high values of + pagesize (>1000) + + + + + CLOUDSTACK-1499 + + + ListAPI Performance for few APIs not as good as it was before API + optimization + + + + + CLOUDSTACK-1503 + + + listHypervisor API not getting fired when logged in as User + + + + + CLOUDSTACK-1505 + + + Unknown column 'domain.region_id' in 'field list' + + + + + CLOUDSTACK-1509 + + + Failed to implement network elements and resources while provisioning for + persistent network(createVlanIpRange to an account + + + + + CLOUDSTACK-1511 + + + [UI] Instances NIC details does not have Network Name + + + + + CLOUDSTACK-1512 + + + [UI] Wrong message[message.configure.all.traffic.types] when trying to create + zone with mulitple physical networks without providing the traffic label + + + + + CLOUDSTACK-1515 + + + None of the cloudstack packges are marked for upgrade when tried to upgrade + from.4.0/4.0.1 to 4.1 + + + + + CLOUDSTACK-1516 + + + Create documentation in languages that have translations available + + + + + CLOUDSTACK-1517 + + + Check UI in languages available + + + + + CLOUDSTACK-1521 + + + Redundant router: Services are not stopped when switch to BACKUP state + + + + + CLOUDSTACK-1526 + + + Template registration fails in the VMware Setup + + + + + CLOUDSTACK-1531 + + + vmware create volume from snapshot will missing date + + + + + CLOUDSTACK-1537 + + + Restart network with clean up set to true causes Autoscaled LB rule to get + mangled and unusable + + + + + CLOUDSTACK-1541 + + + NPE while deleting snapshot :Unexpected exception while executing + org.apache.cloudstack.api.command.user.snapshot.DeleteSnapshotCmd + + + + + CLOUDSTACK-1542 + + + unhandled exception while creating project + + + + + CLOUDSTACK-1544 + + + The description and the response format for the deleteUser command are + incorrect + + + + + CLOUDSTACK-1550 + + + createaccountresponse returns more than the user you requested for + creation + + + + + CLOUDSTACK-1553 + + + AWS Regions-Not able to list accounts from the 2nd region after + user/account/domain details have been manually synced up from first region + + + + + CLOUDSTACK-1555 + + + "AWS Regions - userapikey and usersecretkey parameters are not returned in the + response of addRegion, updateRegion listRegion api calls.. + + + + + CLOUDSTACK-1557 + + + EC2 REST API : cloudbridge database is missing on the CloudStack + Installation + + + + + CLOUDSTACK-1562 + + + Replace the short-cut solution of supportting @DB with the formal one + + + + + CLOUDSTACK-1565 + + + "Used Master Branch System VM Template: Default Route on the System VMs + (SSVM,CPVM and VR) is missing + + + + + CLOUDSTACK-1566 + + + Baremetal API addBaremetalPxePingServer fail to add PXE PING server to + deployment causing create instance with PING style image to fail + + + + + CLOUDSTACK-1569 + + + "AWS Regions - Not able to Edit domain/account/user from a region that is not + the owner region.""The content of elements must consist of well-formed character + data or markup."" - error message presented to the user. + + + + + CLOUDSTACK-1571 + + + "AWS Regions - When deleting domain/account/user from a region that is not the + owner, the request is not being forwarded to the owner region. + + + + + CLOUDSTACK-1574 + + + updateResourceCount API is failed saying to specify valida resource type even + after parsing the valid resource type + + + + + CLOUDSTACK-1583 + + + AWS Regions - RabbitMQ Server did not recieve any event notification during + account creation + + + + + CLOUDSTACK-1587 + + + Basic zone - CPVM fail to go to running state, Exception while trying to start + secondary storage vm + + + + + CLOUDSTACK-1588 + + + AWS Regions - When registerUserKeys() is called for a user from a region that + is not the owner, it is handled by this region. + + + + + CLOUDSTACK-1600 + + + Typo in dpkg-buildpackage command + + + + + CLOUDSTACK-1604 + + + deploy VM failed when global setting "vm.allocation.algorithm" is set to + "userdispersing + + + + + CLOUDSTACK-1615 + + + "VMware Cluster discovery fails with if ESXi version is 5.0 Update 1, build + 721882 + + + + + CLOUDSTACK-1620 + + + Cannot provision CentOS 6 VMs on XenServer 6.1 + + + + + CLOUDSTACK-1621 + + + listProjectInvitations fails with NPE for valid request + + + + + CLOUDSTACK-1624 + + + API is not returning response in details:UI is also not returning any + output + + + + + CLOUDSTACK-1625 + + + NPE with updateResourceCount when && is passed thru API + + + + + CLOUDSTACK-1630 + + + 4.0.x cloud-aws-api not properly obsoleted + + + + + CLOUDSTACK-1631 + + + 4.1 RPM packaging broken + + + + + CLOUDSTACK-1636 + + + AWS Regions - Remove the concept of having an owner region for + domain/account/user objects + + + + + CLOUDSTACK-1642 + + + Add support CentOS 6.4 + + + + + CLOUDSTACK-1648 + + + Unable to add KVM host. + + + + + CLOUDSTACK-1649 + + + vmware vm os type error + + + + + CLOUDSTACK-1651 + + + agent scripts still pointing to /var/log/cloud + + + + + CLOUDSTACK-1656 + + + NicResponses in a UserVmResponse are not preserving the natural order + + + + + CLOUDSTACK-1663 + + + AWS Regions - Events - There are no events being generated when a new domain + is added/edited + + + + + CLOUDSTACK-1664 + + + Action Events are not logged due to spring change + + + + + CLOUDSTACK-1665 + + + AWS Regions - Events - There are no events being generated when a new user is + added/edited/enabled/deleted/password changes/api & secret keys are + generated + + + + + CLOUDSTACK-1666 + + + KVM VPC NetworkUsage does not work + + + + + CLOUDSTACK-1668 + + + IP conflict in VPC tier + + + + + CLOUDSTACK-1671 + + + AWS Regions - Events - Domain Delete event does not include the UUID of the + domain that was deleted + + + + + CLOUDSTACK-1674 + + + AWS Regions - Events - Account Deletion event does not include the UUID of the + account deleted + + + + + CLOUDSTACK-1681 + + + Upgrade instructions mention incorrect name and description of systemvm-vmware + template in registering template section + + + + + CLOUDSTACK-1684 + + + "api.throttling.enabled configuration setting should be set to ""false"" in + Config.java + + + + + CLOUDSTACK-1688 + + + AWS Regions - Domain admin user is not able to use getUser() command to fetch + user details + + + + + CLOUDSTACK-1690 + + + NPE from API server when starting mgmt server + + + + + CLOUDSTACK-1694 + + + Issues to start/access Management Server after upgrade from 4.0 to 4.1 + + + + + CLOUDSTACK-1697 + + + Six DB tables are not available with upgraded setup(4.0 to 4.1) when compare + to 4.1 newly installation + + + + + CLOUDSTACK-1706 + + + Failed to deploy VM with error "cannot find DeployPlannerSelector" + + + + + CLOUDSTACK-1709 + + + AWS Regions - As part of adding a new region, project related entries should + not be synced from accounts table. + + + + + CLOUDSTACK-1710 + + + AWS Regions - As part of adding a new region,default_zone_id column for the + account entries should not be synced. + + + + + CLOUDSTACK-1711 + + + AWS Regions - Include all the details of the API call made in the Events + payload when changes in Admin/Account/User objects are made. + + + + + CLOUDSTACK-1713 + + + EC2 REST API: AWS API Installation Problem + + + + + CLOUDSTACK-1714 + + + Doc section has wrong title: Setting Zone VLAN and Running VM Maximum + + + + + CLOUDSTACK-1715 + + + "Missing ""host"" config setting in docs on management server load + balancing + + + + + CLOUDSTACK-1716 + + + "AWS Regions - listRegions(),removeRegions(),updateRegions() should accept + UUID value instead of id. + + + + + CLOUDSTACK-1718 + + + AWS Regions - removeRegion() response returns updateregionresponse + + + + + CLOUDSTACK-1719 + + + EC2 REST API: AWS APIs are not getting translated on the CloudStack Management + Server + + + + + CLOUDSTACK-1720 + + + Have an upgrade path from 4.0.x to 4.1 and 4.0.x to 4.2.0 + + + + + CLOUDSTACK-1729 + + + Ensure adapter execution order in runtime + + + + + CLOUDSTACK-1733 + + + [ACS41][UI] Add guest network is missing ip range fields and missing network + offering + + + + + CLOUDSTACK-1736 + + + Ubuntu 12.04 cloud-setup-management Failed to configure CloudStack Management + Server + + + + + CLOUDSTACK-1738 + + + StatsCollector is not running + + + + + CLOUDSTACK-1740 + + + Failed to view console + + + + + CLOUDSTACK-1746 + + + Cloudstack Usage Server won't start + + + + + CLOUDSTACK-1747 + + + "mvn deploydb only creates 4.0 DB, not 4.1 + + + + + CLOUDSTACK-1750 + + + injectkeys script fails on OSX because cp does not have a -b option (backup of + destination file + + + + + CLOUDSTACK-1761 + + + Available local storage disk capacity incorrectly reported in KVM to + manager + + + + + CLOUDSTACK-1764 + + + ListTemplateCommand failed with java.lang.NumberFormatException and failed to + create default template. + + + + + CLOUDSTACK-1772 + + + the change in vnc listening port will cause live migration doesn't + work. + + + + + CLOUDSTACK-1773 + + + Disable baremetal functionality + + + + + CLOUDSTACK-1776 + + + NPE on listSecondaryStorageHostsInAllZones in Upgraded setup from 4.0 to + 4.1.0 + + + + + CLOUDSTACK-1785 + + + Redundant Router test cases failing during automation run. + + + + + CLOUDSTACK-1789 + + + Unable to download templates to Primary Storage if a host is in + maintenance. + + + + + CLOUDSTACK-1791 + + + Volumes with storage tags can't be attached. + + + + + CLOUDSTACK-1792 + + + "AWS Regions - RuntimeException while executing listAccounts(), when the + encryption keys are set to different values between regions. + + + + + CLOUDSTACK-1793 + + + L10n docs don't build in chinese, portuguese and japanese + + + + + CLOUDSTACK-1795 + + + Customize AOP to fully support legacy CloudStack @DB and @ActionEvent + semantics. + + + + + CLOUDSTACK-1796 + + + Japanese docs don't build. + + + + + CLOUDSTACK-1802 + + + Upgrade 4.0 -> 4.1 - Not able to start management server becasue of missing + /etc/cloudstack/management/tomcat6.conf file + + + + + CLOUDSTACK-1804 + + + Upgrade 4.0 -> 4.1 - DB upgrade fails + + + + + CLOUDSTACK-1805 + + + com.mysql.jdbc.exceptions.jdbc4.CommunicationsException seen after long time + of inactivity resulting in not being able to log in to the management + server + + + + + CLOUDSTACK-1810 + + + listTemplate API with templatefilter=featured|community is not returning any + lists + + + + + CLOUDSTACK-1811 + + + "Upgrade 4.0->4.1 - When upgrade scripts fail, component loading continues and + management server starts. + + + + + CLOUDSTACK-1812 + + + create physical network fails while creating basic zone + + + + + CLOUDSTACK-1825 + + + EC2 REST API: AWS APIs fail to execute due to BeanCreationException: Error + creating bean with name 'SAclDaoImpl' + + + + + CLOUDSTACK-1826 + + + "Storage migration not working, seemingly due to uuid vs id + + + + + CLOUDSTACK-1827 + + + Redundant router - When VR Master was stopped failover to VR Backup did not + occur. + + + + + CLOUDSTACK-1834 + + + "Events are not generated for registerUserKeys(), Enabling account and Editing + account. + + + + + CLOUDSTACK-1836 + + + License header failures for ja-JP .po translation file + + + + + CLOUDSTACK-1839 + + + Upgrade 4.0 -> 4.1 - Upgraded DB has lot more keys and indexes for many tables + compare to the fresh installed 4.1 DB + + + + + CLOUDSTACK-1841 + + + ASF 4.0 to 4.1 Upgrade: Missing Few Global Configuration parameters on the + Upgraded Setup. + + + + + CLOUDSTACK-1842 + + + ASF 4.0 to 4.1 Upgrade: Missing Ubuntu 12.04 Guest OS Types on the Upgraded + Setup. + + + + + CLOUDSTACK-1844 + + + Upgrade 4.0 -> 4.1 - KVM host agent.properties is not restored as part of + upgrading the binaries from 4.0 to 4.1. + + + + + CLOUDSTACK-1845 + + + KVM - storage migration often fails + + + + + CLOUDSTACK-1846 + + + "KVM - storage pools can silently fail to be unregistered, leading to failure + to register later. + + + + + CLOUDSTACK-1848 + + + Cloudstack Packages are not got updated with scenario 4.0 to 4.1 upgrade where + MS is on Ubuntu 12.04. + + + + + CLOUDSTACK-1856 + + + Upgrade 4.0 -> 4.1 - Fresh install of 4.1 has 3 parameters missing in + db.properties compared to an upgraded 4.0 setup + + + + + CLOUDSTACK-1873 + + + "Installation : JasyptPBEStringDecryptionCLI missing, failed to decrypt db + password + + + + + CLOUDSTACK-1874 + + + AWS Regions - Account table in cloud_usage DB has region_id + + + + + CLOUDSTACK-1876 + + + External Devices - network offering for external devices is not returned in + API listNetworkOfferings when creating instances. + + + + + CLOUDSTACK-1877 + + + Failed to connect to DB while starting Ubuntu management server after + upgrading the packages from 4.0 to 4.1.0 + + + + + CLOUDSTACK-1882 + + + “HTTP Status 404 。 The requested resource () is not available. + + + + + CLOUDSTACK-1890 + + + listProjects is not listing state in the response + + + + + CLOUDSTACK-1900 + + + "Upgrade 4.0 -> 4.1, We do not have a copy of db.properties that comes from a + 4.1 installation saved anywhere. + + + + + CLOUDSTACK-1929 + + + ASF 4.1 cloudstack agent fail to install in KVM host CENTOS 6.3 OS: + qemu-kvm-0.12.1.2-3.295.el6.10.x86_64 requires libusbredirparser.so.0 + + + + + CLOUDSTACK-1934 + + + NPE with listSupportedNetworkServices after upgrade from 4.0 to 4.1 (Ubuntu + MS) + + + + + CLOUDSTACK-1935 + + + Cloud utilities are not renamed to Cloudstack after upgrade from 4.0 to 4.1 + [Ubutnu MS] + + + + + CLOUDSTACK-1936 + + + On CentOS, after a upgrade from 4.0.1 to 4.1 on a cloud node (cloud-agent), + the new cloustack-agent isn't add as a service (chkconfig) + + + + + CLOUDSTACK-1951 + + + centos packaging: cloud-install-sys-tmplt can't find jasypt jar. + + + + + CLOUDSTACK-1971 + + + VM deployed to incorrect primary storage. + + + + + CLOUDSTACK-1972 + + + VM deployed to incorrect primary storage. + + + + + CLOUDSTACK-1978 + + + openvswitch - unable to start console session for SSVM CPVM user VM + + + + + CLOUDSTACK-1980 + + + "[4.1]cloudstack-setup-bridge, cloudstack-setup-encryption & + cloudstack-sysvmadm utilities are not available in Ubuntu 12.04 Management + Server. + + + + + CLOUDSTACK-1987 + + + Deleted service offerings owned by a domain show up to domain user. + + + + + CLOUDSTACK-1988 + + + AWS API using SOAP client - User Registration fails + + + + + CLOUDSTACK-1989 + + + "Query service offering by ID returns no result, but querying all returns + service offering + + + + + CLOUDSTACK-2003 + + + Deleting domain while deleted account is cleaning up leaves VMs expunging + forever due to 'Failed to update resource count + + + + + CLOUDSTACK-2007 + + + Release Notes failing to build on jenkins.cs. + + + + + +
+
+ Known Issues in 4.1.0 + + + + + + + + Issue ID + + + Description + + + + + + CLOUDSTACK-1747 + mvn deploydb only creates 4.0 DB, not 4.1 + Due to tooling changes between 4.1 and 4.2, CloudStack's database is created + using the 4.0 schema and updated to the 4.1 schema when the management server + starts for the first time. It's OK to see the same schema if the management server + has not started yet. + + + + CLOUDSTACK-1824 + Service CloudStack-Management is being displayed as cloud-management + service + Many scripts and text entries have references to cloud-management rather than + cloudstack-management due to the changeover between 4.0 and 4.1 to rename + services. This is a minor issue and should be corrected by 4.2. + + + + + CLOUDSTACK-1824 + Service CloudStack-Management is being displayed as cloud-management + service + + + + + CLOUDSTACK-1510 + + + NPE when primary storage is added with wrong path + + + + + CLOUDSTACK-1428 + + + [UI] Instance which are created without display name are not visible when + added to LB + + + + + CLOUDSTACK-1306 + + + Better Error message when trying to deploy Vm by passing static Ipv4 addresses + that are assigned to another VM/IP4 address is outside the iprange. + + + + + CLOUDSTACK-1236 + + + Warning while adding Xen 6.1 host [Unable to create local link network] + + + + + CLOUDSTACK-969 + + + api: zone response lists vlan in it as "vlan range of zone" but the + vlan belongs to physical network + + + + + CLOUDSTACK-963 + + + [cloud.utils.AnnotationHelper] class java.lang.Stringdoes not have a Table + annotation + + + + + CLOUDSTACK-458 + + + xen:snapshots:Storage gc fail to clean the failed snapshot images from + secondarystorage + + + + + CLOUDSTACK-315 + + + Infrastructure view does not show capacity values + + + + + CLOUDSTACK-300 + + + Creation of compute offering allow combination of local storage + HA + + + + + CLOUDSTACK-282 + + + Virtual Routers do not properly resolve DNS SRV Records + + + + + CLOUDSTACK-276 + + + SSVM ID is exposed in the Error Message thrown by AddTrafficType API + + + + + CLOUDSTACK-270 + + + Ui should not ask for a vlan range if the physical network isolation type is + not VLAN + + + + + CLOUDSTACK-245 + + + VPC ACLs are not stored and programmed consistently + + + + + CLOUDSTACK-231 + + + Tag creation using special charecters + + + + + CLOUDSTACK-124 + + + NetworkGarbageCollector not cleaning up networks + + + + + CLOUDSTACK-62 + + + console proxy does not support any keymaps besides us, jp + + + + + +
+
+ + Upgrade Instructions + This section contains upgrade instructions from prior versions of CloudStack to Apache + CloudStack 4.1.0. We include instructions on upgrading to Apache CloudStack from pre-Apache + versions of Citrix CloudStack (last version prior to Apache is 3.0.2) and from the releases + made while CloudStack was in the Apache Incubator. + If you run into any issues during upgrades, please feel free to ask questions on + users@apache.cloudstack.org or dev@apache.cloudstack.org. +
+ Upgrade from 4.0.x to 4.1.0 + This section will guide you from &PRODUCT; 4.0.x versions to &PRODUCT; 4.1.0. + Any steps that are hypervisor-specific will be called out with a note. + + Package Structure Changes + The package structure for &PRODUCT; has changed significantly since the 4.0.x + releases. If you've compiled your own packages, you'll notice that the package names and + the number of packages has changed. This is not a bug. + However, this does mean that the procedure is not as simple as an + apt-get upgrade or yum update, so please follow + this section carefully. + + We recommend reading through this section once or twice before beginning your upgrade + procedure, and working through it on a test system before working on a production + system. + + + Most users of &PRODUCT; manage the installation and upgrades of &PRODUCT; with one + of Linux's predominant package systems, RPM or APT. This guide assumes you'll be using + RPM and Yum (for Red Hat Enterprise Linux or CentOS), or APT and Debian packages (for + Ubuntu). + Create RPM or Debian packages (as appropriate) and a repository from the 4.1.0 + source, or check the Apache CloudStack downloads page at http://cloudstack.apache.org/downloads.html for package repositories supplied + by community members. You will need them for step + or step . + Instructions for creating packages from the &PRODUCT; source are in the Installation + Guide. + + + Stop your management server or servers. Run this on all management server + hosts: + # service cloud-management stop + + + If you are running a usage server or usage servers, stop those as well: + # service cloud-usage stop + + + Make a backup of your MySQL database. If you run into any issues or need to roll + back the upgrade, this will assist in debugging or restoring your existing environment. + You'll be prompted for your password. + # mysqldump -u root -p cloud > cloudstack-backup.sql + + + Whether you're upgrading a Red Hat/CentOS based system or Ubuntu based system, + you're going to need to stop the CloudStack management server before proceeding. + # service cloud-management stop + + + If you have made changes to + /etc/cloud/management/components.xml, you'll need to carry these + over manually to the new file, + /etc/cloudstack/management/componentContext.xml. This is not done + automatically. (If you're unsure, we recommend making a backup of the original + components.xml to be on the safe side. + + + If you are using Ubuntu, follow this procedure to upgrade your packages. If not, + skip to step . + + Community Packages + This section assumes you're using the community supplied packages for &PRODUCT;. + If you've created your own packages and APT repository, substitute your own URL for + the ones used in these examples. + + + + The first order of business will be to change the sources list for each system + with &PRODUCT; packages. This means all management servers, and any hosts that have + the KVM agent. (No changes should be necessary for hosts that are running VMware or + Xen.) + Start by opening /etc/apt/sources.list.d/cloudstack.list on + any systems that have &PRODUCT; packages installed. + This file should have one line, which contains: + deb http://cloudstack.apt-get.eu/ubuntu precise 4.0 + We'll change it to point to the new package repository: + deb http://cloudstack.apt-get.eu/ubuntu precise 4.1 + If you're using your own package repository, change this line to read as + appropriate for your 4.1.0 repository. + + + Now update your apt package list: + $ sudo apt-get update + + + Now that you have the repository configured, it's time to install the + cloudstack-management package. This will pull in any other + dependencies you need. + $ sudo apt-get install cloudstack-management + + + You will need to manually install the cloudstack-agent + package: + $ sudo apt-get install cloudstack-agent + During the installation of cloudstack-agent, APT will copy + your agent.properties, log4j-cloud.xml, + and environment.properties from + /etc/cloud/agent to + /etc/cloudstack/agent. + When prompted whether you wish to keep your configuration, say Yes. + + + Verify that the file + /etc/cloudstack/agent/environment.properties has a line that + reads: + paths.script=/usr/share/cloudstack-common + If not, add the line. + + + Restart the agent: + +service cloud-agent stop +killall jsvc +service cloudstack-agent start - - - During the upgrade, log4j-cloud.xml was simply copied over, so the logs will continue to be added to /var/log/cloud/agent/agent.log. There's nothing wrong with this, but if you prefer to be consistent, you can change this by copying over the sample configuration file: - - cd /etc/cloudstack/agent - mv log4j-cloud.xml.dpkg-dist log4j-cloud.xml - service cloudstack-agent restart + + + During the upgrade, log4j-cloud.xml was simply copied over, + so the logs will continue to be added to + /var/log/cloud/agent/agent.log. There's nothing + wrong with this, but if you prefer to be consistent, you can + change this by copying over the sample configuration file: + +cd /etc/cloudstack/agent +mv log4j-cloud.xml.dpkg-dist log4j-cloud.xml +service cloudstack-agent restart - - - Once the agent is running, you can uninstall the old cloud-* packages from your system: - sudo dpkg --purge cloud-agent - - - - - The package names have changed between 4.0 and 4.1, so upgrading the packages won't happen automatically with a yum update - - - Once you've upgraded the packages on your management servers, you'll need to restart the system VMs. Make sure port 8096 is open to do this. - There is a script that will do this for you, all you need to do is run the script and supply the IP address for your MySQL instance and your MySQL credentials: - # nohup cloudstack-sysvmadm -d IP address -u cloud -p -a > sysvm.log 2>&1 & - You can monitor the log for progress. The process of restarting the system VMs can take an hour or more. - # tail -f sysvm.log - The output to sysvm.log will look something like this: - - Stopping and starting 1 secondary storage vm(s)... - Done stopping and starting secondary storage vm(s) - Stopping and starting 1 console proxy vm(s)... - Done stopping and starting console proxy vm(s). - Stopping and starting 4 running routing vm(s)... - Done restarting router(s). + + + Once the agent is running, you can uninstall the old cloud-* packages from your + system: + sudo dpkg --purge cloud-agent + + + + + If you are using CentOS or RHEL, follow this procedure to upgrade your packages. If + not, skip to step . + + Community Packages + This section assumes you're using the community supplied packages for &PRODUCT;. + If you've created your own packages and yum repository, substitute your own URL for + the ones used in these examples. + + + + The first order of business will be to change the yum repository for each system + with &PRODUCT; packages. This means all management servers, and any hosts that have + the KVM agent. (No changes should be necessary for hosts that are running VMware or + Xen.) + Start by opening /etc/yum.repos.d/cloudstack.repo on any + systems that have &PRODUCT; packages installed. + This file should have content similar to the following: + +[apache-cloudstack] +name=Apache CloudStack +baseurl=http://cloudstack.apt-get.eu/rhel/4.0/ +enabled=1 +gpgcheck=0 + + If you are using the community provided package repository, change the baseurl + to http://cloudstack.apt-get.eu/rhel/4.1/ + If you're using your own package repository, change this line to read as + appropriate for your 4.1.0 repository. + + + Now that you have the repository configured, it's time to install the + cloudstack-management package by upgrading the older + cloud-client package. + $ sudo yum upgrade cloud-client + + + For KVM hosts, you will need to upgrade the cloud-agent + package, similarly installing the new version as + cloudstack-agent. + $ sudo yum upgrade cloud-agent + During the installation of cloudstack-agent, the RPM will + copy your agent.properties, + log4j-cloud.xml, and + environment.properties from + /etc/cloud/agent to + /etc/cloudstack/agent. + + + Verify that the file + /etc/cloudstack/agent/environment.properties has a line that + reads: + paths.script=/usr/share/cloudstack-common + If not, add the line. + + + Restart the agent: + +service cloud-agent stop +killall jsvc +service cloudstack-agent start + + + + + + Once you've upgraded the packages on your management servers, you'll need to restart + the system VMs. Make sure port 8096 is open in your local host firewall to do + this. + There is a script that will do this for you, all you need to do is run the script + and supply the IP address for your MySQL instance and your MySQL credentials: + # nohup cloudstack-sysvmadm -d IP address -u cloud -p -a > sysvm.log 2>&1 & + You can monitor the log for progress. The process of restarting the system VMs can + take an hour or more. + # tail -f sysvm.log + The output to sysvm.log will look something like this: + +Stopping and starting 1 secondary storage vm(s)... +Done stopping and starting secondary storage vm(s) +Stopping and starting 1 console proxy vm(s)... +Done stopping and starting console proxy vm(s). +Stopping and starting 4 running routing vm(s)... +Done restarting router(s). - - - For Xen Hosts: Copy vhd-utils - This step is only for CloudStack installs that are using Xen hosts. - - Copy the file vhd-utils to /usr/share/cloudstack-common/scripts/vm/hypervisor/xenserver. - - -
-
- Upgrade from 3.0.2 to 4.1.0 - This section will guide you from Citrix CloudStack 3.0.2 to Apache CloudStack 4.1.0. Sections that are hypervisor-specific will be called out with a note. - - - Ensure that you query your IP address usage records and process them or make a - backup. During the upgrade you will lose the old IP address usage records. - Starting in 3.0.2, the usage record format for IP addresses is the same as the rest - of the usage types. Instead of a single record with the assignment and release dates, - separate records are generated per aggregation period with start and end dates. After - upgrading, any existing IP address usage records in the old format will no longer be - available. - - - - The following upgrade instructions apply only if you're using VMware hosts. If - you're not using VMware hosts, skip this step and move on to . - - In each zone that includes VMware hosts, you need to add a new system VM template. - - - While running the existing 3.0.2 system, log in to the UI as root administrator. - - - In the left navigation bar, click Templates. - - - In Select view, click Templates. - - - Click Register template. - The Register template dialog box is displayed. - - - In the Register template dialog box, specify the following values (do not change these): - - - - - - - Field - Value - - - - - Name - systemvm-vmware-4.1 - - - Description - systemvm-vmware-4.1 - - - URL - http://download.cloud.com/templates/burbank/burbank-systemvm-08012012.ova - - - Zone - Choose the zone where this hypervisor is used - - - Hypervisor - VMware - - - Format - OVA - - - OS Type - Debian GNU/Linux 5.0 (32-bit) - - - Extractable - no - - - Password Enabled - no - - - Public - no - - - Featured - no - - - - - - - Watch the screen to be sure that the template downloads successfully and enters - the READY state. Do not proceed until this is successful. - - - - - Stop all Usage Servers if running. Run this on all Usage Server hosts. - # service cloud-usage stop - - - Stop the Management Servers. Run this on all Management Server hosts. - # service cloud-management stop - - - On the MySQL master, take a backup of the MySQL databases. We recommend performing - this step even in test upgrades. If there is an issue, this will assist with - debugging. - In the following commands, it is assumed that you have set the root password on the - database, which is a CloudStack recommended best practice. Substitute your own MySQL - root password. - # mysqldump -u root -pmysql_password cloud > cloud-backup.dmp + + + + For Xen Hosts: Copy vhd-utils + This step is only for CloudStack installs that are using Xen hosts. + + Copy the file vhd-utils to + /usr/share/cloudstack-common/scripts/vm/hypervisor/xenserver. + + +
+
+ Upgrade from 3.0.2 to 4.1.0 + This section will guide you from Citrix CloudStack 3.0.2 to Apache CloudStack 4.1.0. + Sections that are hypervisor-specific will be called out with a note. + + + + The following upgrade instructions apply only if you're using VMware hosts. If + you're not using VMware hosts, skip this step and move on to . + + In each zone that includes VMware hosts, you need to add a new system VM template. + + + While running the existing 3.0.2 system, log in to the UI as root + administrator. + + + In the left navigation bar, click Templates. + + + In Select view, click Templates. + + + Click Register template. + The Register template dialog box is displayed. + + + In the Register template dialog box, specify the following values (do not change + these): + + + + + + + Field + Value + + + + + Name + systemvm-vmware-4.1 + + + Description + systemvm-vmware-4.1 + + + URL + http://download.cloud.com/templates/burbank/burbank-systemvm-08012012.ova + + + Zone + Choose the zone where this hypervisor is used + + + Hypervisor + VMware + + + Format + OVA + + + OS Type + Debian GNU/Linux 5.0 (32-bit) + + + Extractable + no + + + Password Enabled + no + + + Public + no + + + Featured + no + + + + + + + Watch the screen to be sure that the template downloads successfully and enters + the READY state. Do not proceed until this is successful. + + + + + Stop all Usage Servers if running. Run this on all Usage Server hosts. + # service cloud-usage stop + + + Stop the Management Servers. Run this on all Management Server hosts. + # service cloud-management stop + + + On the MySQL master, take a backup of the MySQL databases. We recommend performing + this step even in test upgrades. If there is an issue, this will assist with + debugging. + In the following commands, it is assumed that you have set the root password on the + database, which is a CloudStack recommended best practice. Substitute your own MySQL + root password. + # mysqldump -u root -pmysql_password cloud > cloud-backup.dmp # mysqldump -u root -pmysql_password cloud_usage > cloud-usage-backup.dmp + + + Either build RPM/DEB packages as detailed in the Installation Guide, or use one of + the community provided yum/apt repositories to gain access to the &PRODUCT; + binaries. + + + If you are using Ubuntu, follow this procedure to upgrade your packages. If not, + skip to step . + + Community Packages + This section assumes you're using the community supplied packages for &PRODUCT;. + If you've created your own packages and APT repository, substitute your own URL for + the ones used in these examples. + + + + The first order of business will be to change the sources list for each system + with &PRODUCT; packages. This means all management servers, and any hosts that have + the KVM agent. (No changes should be necessary for hosts that are running VMware or + Xen.) + Start by opening /etc/apt/sources.list.d/cloudstack.list on + any systems that have &PRODUCT; packages installed. + This file should have one line, which contains: + deb http://cloudstack.apt-get.eu/ubuntu precise 4.0 + We'll change it to point to the new package repository: + deb http://cloudstack.apt-get.eu/ubuntu precise 4.1 + If you're using your own package repository, change this line to read as + appropriate for your 4.1.0 repository. + + + Now update your apt package list: + $ sudo apt-get update + + + Now that you have the repository configured, it's time to install the + cloudstack-management package. This will pull in any other + dependencies you need. + $ sudo apt-get install cloudstack-management + + + You will need to manually install the cloudstack-agent + package: + $ sudo apt-get install cloudstack-agent + During the installation of cloudstack-agent, APT will copy + your agent.properties, log4j-cloud.xml, + and environment.properties from + /etc/cloud/agent to + /etc/cloudstack/agent. + When prompted whether you wish to keep your configuration, say Yes. + + + Verify that the file + /etc/cloudstack/agent/environment.properties has a line that + reads: + paths.script=/usr/share/cloudstack-common + If not, add the line. + + + Restart the agent: + +service cloud-agent stop +killall jsvc +service cloudstack-agent start + + + + During the upgrade, log4j-cloud.xml was simply copied over, + so the logs will continue to be added to + /var/log/cloud/agent/agent.log. There's nothing + wrong with this, but if you prefer to be consistent, you can + change this by copying over the sample configuration file: + +cd /etc/cloudstack/agent +mv log4j-cloud.xml.dpkg-dist log4j-cloud.xml +service cloudstack-agent restart + + + + Once the agent is running, you can uninstall the old cloud-* packages from your + system: + sudo dpkg --purge cloud-agent + + + + + If you are using CentOS or RHEL, follow this procedure to upgrade your packages. If + not, skip to step . + + Community Packages + This section assumes you're using the community supplied packages for &PRODUCT;. + If you've created your own packages and yum repository, substitute your own URL for + the ones used in these examples. + + + + The first order of business will be to change the yum repository for each system + with &PRODUCT; packages. This means all management servers, and any hosts that have + the KVM agent. (No changes should be necessary for hosts that are running VMware or + Xen.) + Start by opening /etc/yum.repos.d/cloudstack.repo on any + systems that have &PRODUCT; packages installed. + This file should have content similar to the following: + +[apache-cloudstack] +name=Apache CloudStack +baseurl=http://cloudstack.apt-get.eu/rhel/4.0/ +enabled=1 +gpgcheck=0 + + If you are using the community provided package repository, change the baseurl + to http://cloudstack.apt-get.eu/rhel/4.1/ + If you're using your own package repository, change this line to read as + appropriate for your 4.1.0 repository. + + + Now that you have the repository configured, it's time to install the + cloudstack-management package by upgrading the older + cloud-client package. + $ sudo yum upgrade cloud-client + + + For KVM hosts, you will need to upgrade the cloud-agent + package, similarly installing the new version as + cloudstack-agent. + $ sudo yum upgrade cloud-agent + During the installation of cloudstack-agent, the RPM will + copy your agent.properties, + log4j-cloud.xml, and + environment.properties from + /etc/cloud/agent to + /etc/cloudstack/agent. + + + Verify that the file + /etc/cloudstack/agent/environment.properties has a line that + reads: + paths.script=/usr/share/cloudstack-common + If not, add the line. + + + Restart the agent: + +service cloud-agent stop +killall jsvc +service cloudstack-agent start + + + + + + If you have made changes to your copy of + /etc/cloud/management/components.xml the changes will be + preserved in the upgrade. However, you need to do the following steps to place these + changes in a new version of the file which is compatible with version 4.1.0. + + + Make a backup copy of /etc/cloud/management/components.xml. + For example: + # mv /etc/cloud/management/components.xml /etc/cloud/management/components.xml-backup + + + Copy /etc/cloud/management/components.xml.rpmnew to create + a new /etc/cloud/management/components.xml: + # cp -ap /etc/cloud/management/components.xml.rpmnew /etc/cloud/management/components.xml + + + Merge your changes from the backup file into the new + components.xml. + # vi /etc/cloud/management/components.xml + + + + If you have more than one management server node, repeat the upgrade steps on each + node. + + + + Start the first Management Server. Do not start any other Management Server nodes + yet. + # service cloud-management start + Wait until the databases are upgraded. Ensure that the database upgrade is complete. + After confirmation, start the other Management Servers one at a time by running the same + command on each node. + + Failing to restart the Management Server indicates a problem in the upgrade. + Having the Management Server restarted without any issues indicates that the upgrade + is successfully completed. + + + + Start all Usage Servers (if they were running on your previous version). Perform + this on each Usage Server host. + # service cloud-usage start + + + + Additional steps are required for each KVM host. These steps will not affect + running guests in the cloud. These steps are required only for clouds using KVM as + hosts and only on the KVM hosts. + + + + Configure a yum or apt respository containing the &PRODUCT; packages as outlined + in the Installation Guide. + + + Stop the running agent. + # service cloud-agent stop + + + Update the agent software with one of the following command sets as appropriate + for your environment. + # yum update cloud-* + # apt-get update + # apt-get upgrade cloud-* + + + Start the agent. + # service cloud-agent start + + + Edit /etc/cloud/agent/agent.properties to change the + resource parameter from + "com.cloud.agent.resource.computing.LibvirtComputingResource" to + "com.cloud.hypervisor.kvm.resource.LibvirtComputingResource". + + + Start the cloud agent and cloud management services. + + + When the Management Server is up and running, log in to the CloudStack UI and + restart the virtual router for proper functioning of all the features. + + + + + Log in to the CloudStack UI as administrator, and check the status of the hosts. All + hosts should come to Up state (except those that you know to be offline). You may need + to wait 20 or 30 minutes, depending on the number of hosts. + + Troubleshooting: If login fails, clear your browser cache and reload the + page. + + + Do not proceed to the next step until the hosts show in Up state. + + + If you are upgrading from 3.0.2, perform the following: + + + Ensure that the admin port is set to 8096 by using the "integration.api.port" + global parameter. + This port is used by the cloud-sysvmadm script at the end of the upgrade + procedure. For information about how to set this parameter, see "Setting Global + Configuration Parameters" in the Installation Guide. + + + Restart the Management Server. + + If you don't want the admin port to remain open, you can set it to null after + the upgrade is done and restart the management server. + + + + + + Run the cloud-sysvmadm script to stop, then start, all Secondary + Storage VMs, Console Proxy VMs, and virtual routers. Run the script once on each + management server. Substitute your own IP address of the MySQL instance, the MySQL user + to connect as, and the password to use for that user. In addition to those parameters, + provide the -c and -r arguments. For + example: + # nohup cloud-sysvmadm -d 192.168.1.5 -u cloud -p password -c -r > + sysvm.log 2>&1 & + # tail -f sysvm.log + This might take up to an hour or more to run, depending on the number of accounts in + the system. + + + If needed, upgrade all Citrix XenServer hypervisor hosts in your cloud to a version + supported by CloudStack 4.1.0. The supported versions are XenServer 5.6 SP2 and 6.0.2. + Instructions for upgrade can be found in the CloudStack 4.1.0 Installation Guide under + "Upgrading XenServer Versions." + + + Now apply the XenServer hotfix XS602E003 (and any other needed hotfixes) to + XenServer v6.0.2 hypervisor hosts. + + + Disconnect the XenServer cluster from CloudStack. + In the left navigation bar of the CloudStack UI, select Infrastructure. Under + Clusters, click View All. Select the XenServer cluster and click Actions - + Unmanage. + This may fail if there are hosts not in one of the states Up, Down, + Disconnected, or Alert. You may need to fix that before unmanaging this + cluster. + Wait until the status of the cluster has reached Unmanaged. Use the CloudStack + UI to check on the status. When the cluster is in the unmanaged state, there is no + connection to the hosts in the cluster. + + + To clean up the VLAN, log in to one XenServer host and run: + /opt/xensource/bin/cloud-clean-vlan.sh + + + Now prepare the upgrade by running the following on one XenServer host: + /opt/xensource/bin/cloud-prepare-upgrade.sh + If you see a message like "can't eject CD", log in to the VM and unmount the CD, + then run this script again. + + + Upload the hotfix to the XenServer hosts. Always start with the Xen pool master, + then the slaves. Using your favorite file copy utility (e.g. WinSCP), copy the + hotfixes to the host. Place them in a temporary folder such as /tmp. + On the Xen pool master, upload the hotfix with this command: + xe patch-upload file-name=XS602E003.xsupdate + Make a note of the output from this command, which is a UUID for the hotfix + file. You'll need it in another step later. + + (Optional) If you are applying other hotfixes as well, you can repeat the + commands in this section with the appropriate hotfix number. For example, + XS602E004.xsupdate. + + + + Manually live migrate all VMs on this host to another host. First, get a list of + the VMs on this host: + # xe vm-list + Then use this command to migrate each VM. Replace the example host name and VM + name with your own: + # xe vm-migrate live=true host=host-name + vm=VM-name + + Troubleshooting + If you see a message like "You attempted an operation on a VM which requires + PV drivers to be installed but the drivers were not detected," run: + /opt/xensource/bin/make_migratable.sh + b6cf79c8-02ee-050b-922f-49583d9f1a14. + + + + Apply the hotfix. First, get the UUID of this host: + # xe host-list + Then use the following command to apply the hotfix. Replace the example host + UUID with the current host ID, and replace the hotfix UUID with the output from the + patch-upload command you ran on this machine earlier. You can also get the hotfix + UUID by running xe patch-list. + xe patch-apply host-uuid=host-uuid uuid=hotfix-uuid + + + Copy the following files from the CloudStack Management Server to the + host. + + + + + + + Copy from here... + ...to here + + + + + /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/xenserver60/NFSSR.py + /opt/xensource/sm/NFSSR.py + + + /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/setupxenserver.sh + /opt/xensource/bin/setupxenserver.sh + + + /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/make_migratable.sh + /opt/xensource/bin/make_migratable.sh + + + + + + + (Only for hotfixes XS602E005 and XS602E007) You need to apply a new Cloud + Support Pack. + + + Download the CSP software onto the XenServer host from one of the following + links: + For hotfix XS602E005: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E005/56710/xe-phase-2/xenserver-cloud-supp.tgz + For hotfix XS602E007: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E007/57824/xe-phase-2/xenserver-cloud-supp.tgz - Either build RPM/DEB packages as detailed in the Installation Guide, or use one of - the community provided yum/apt repositories to gain access to the &PRODUCT; - binaries. + Extract the file: + # tar xf xenserver-cloud-supp.tgz - After you have configured an appropriate yum or apt repository, you may execute the - one of the following commands as appropriate for your environment in order to upgrade - &PRODUCT;: # yum update cloud-* - # apt-get update - # apt-get upgrade cloud-* - - You will, of course, have to agree to the changes suggested by Yum or APT. - - If the upgrade output includes a message similar to the following, then some - custom content was found in your old components.xml, and you need to merge the two - files: - warning: /etc/cloud/management/components.xml created as /etc/cloud/management/components.xml.rpmnew - Instructions follow in the next step. - + Run the following script: + # xe-install-supplemental-pack xenserver-cloud-supp.iso - If you have made changes to your copy of - /etc/cloud/management/components.xml the changes will be - preserved in the upgrade. However, you need to do the following steps to place these - changes in a new version of the file which is compatible with version - 4.1.0. - - - Make a backup copy of /etc/cloud/management/components.xml. - For example: - # mv /etc/cloud/management/components.xml /etc/cloud/management/components.xml-backup - - - Copy /etc/cloud/management/components.xml.rpmnew to create - a new /etc/cloud/management/components.xml: - # cp -ap /etc/cloud/management/components.xml.rpmnew /etc/cloud/management/components.xml - - - Merge your changes from the backup file into the new - components.xml. - # vi /etc/cloud/management/components.xml - - - - If you have more than one management server node, repeat the upgrade steps on each - node. - + If the XenServer host is part of a zone that uses basic networking, disable + Open vSwitch (OVS): + # xe-switch-network-backend bridge - - Start the first Management Server. Do not start any other Management Server nodes - yet. - # service cloud-management start - Wait until the databases are upgraded. Ensure that the database upgrade is complete. - After confirmation, start the other Management Servers one at a time by running the same - command on each node. - - Failing to restart the Management Server indicates a problem in the upgrade. - Having the Management Server restarted without any issues indicates that the upgrade - is successfully completed. - - - - Start all Usage Servers (if they were running on your previous version). Perform - this on each Usage Server host. - # service cloud-usage start - - - - Additional steps are required for each KVM host. These steps will not affect - running guests in the cloud. These steps are required only for clouds using KVM as - hosts and only on the KVM hosts. - - - - Configure a yum or apt respository containing the &PRODUCT; packages as outlined - in the Installation Guide. - - - Stop the running agent. - # service cloud-agent stop - - - Update the agent software with one of the following command sets as appropriate - for your environment. - # yum update cloud-* - # apt-get update - # apt-get upgrade cloud-* - - - Start the agent. - # service cloud-agent start - - - Edit /etc/cloud/agent/agent.properties to change the - resource parameter from - "com.cloud.agent.resource.computing.LibvirtComputingResource" to - "com.cloud.hypervisor.kvm.resource.LibvirtComputingResource". - - - Start the cloud agent and cloud management services. - - - When the Management Server is up and running, log in to the CloudStack UI and - restart the virtual router for proper functioning of all the features. - - - - - Log in to the CloudStack UI as administrator, and check the status of the hosts. All - hosts should come to Up state (except those that you know to be offline). You may need - to wait 20 or 30 minutes, depending on the number of hosts. - - Troubleshooting: If login fails, clear your browser cache and reload the - page. - - - Do not proceed to the next step until the hosts show in Up state. - - - If you are upgrading from 3.0.2, perform the following: - - - Ensure that the admin port is set to 8096 by using the "integration.api.port" - global parameter. - This port is used by the cloud-sysvmadm script at the end of the upgrade - procedure. For information about how to set this parameter, see "Setting Global - Configuration Parameters" in the Installation Guide. - - - Restart the Management Server. - - If you don't want the admin port to remain open, you can set it to null after - the upgrade is done and restart the management server. - - - - - - Run the cloud-sysvmadm script to stop, then start, all Secondary - Storage VMs, Console Proxy VMs, and virtual routers. Run the script once on each - management server. Substitute your own IP address of the MySQL instance, the MySQL user - to connect as, and the password to use for that user. In addition to those parameters, - provide the -c and -r arguments. For - example: - # nohup cloud-sysvmadm -d 192.168.1.5 -u cloud -p password -c -r > - sysvm.log 2>&1 & - # tail -f sysvm.log - This might take up to an hour or more to run, depending on the number of accounts in - the system. - - - If needed, upgrade all Citrix XenServer hypervisor hosts in your cloud to a version - supported by CloudStack 4.1.0. The supported versions are XenServer 5.6 SP2 - and 6.0.2. Instructions for upgrade can be found in the CloudStack 4.1.0 - Installation Guide under "Upgrading XenServer Versions." - - - Now apply the XenServer hotfix XS602E003 (and any other needed hotfixes) to - XenServer v6.0.2 hypervisor hosts. - - - Disconnect the XenServer cluster from CloudStack. - In the left navigation bar of the CloudStack UI, select Infrastructure. Under - Clusters, click View All. Select the XenServer cluster and click Actions - - Unmanage. - This may fail if there are hosts not in one of the states Up, Down, - Disconnected, or Alert. You may need to fix that before unmanaging this - cluster. - Wait until the status of the cluster has reached Unmanaged. Use the CloudStack - UI to check on the status. When the cluster is in the unmanaged state, there is no - connection to the hosts in the cluster. - - - To clean up the VLAN, log in to one XenServer host and run: - /opt/xensource/bin/cloud-clean-vlan.sh - - - Now prepare the upgrade by running the following on one XenServer host: - /opt/xensource/bin/cloud-prepare-upgrade.sh - If you see a message like "can't eject CD", log in to the VM and unmount the CD, - then run this script again. - - - Upload the hotfix to the XenServer hosts. Always start with the Xen pool master, - then the slaves. Using your favorite file copy utility (e.g. WinSCP), copy the - hotfixes to the host. Place them in a temporary folder such as /tmp. - On the Xen pool master, upload the hotfix with this command: - xe patch-upload file-name=XS602E003.xsupdate - Make a note of the output from this command, which is a UUID for the hotfix - file. You'll need it in another step later. - - (Optional) If you are applying other hotfixes as well, you can repeat the - commands in this section with the appropriate hotfix number. For example, - XS602E004.xsupdate. - - - - Manually live migrate all VMs on this host to another host. First, get a list of - the VMs on this host: - # xe vm-list - Then use this command to migrate each VM. Replace the example host name and VM - name with your own: - # xe vm-migrate live=true host=host-name - vm=VM-name - - Troubleshooting - If you see a message like "You attempted an operation on a VM which requires - PV drivers to be installed but the drivers were not detected," run: - /opt/xensource/bin/make_migratable.sh - b6cf79c8-02ee-050b-922f-49583d9f1a14. - - - - Apply the hotfix. First, get the UUID of this host: - # xe host-list - Then use the following command to apply the hotfix. Replace the example host - UUID with the current host ID, and replace the hotfix UUID with the output from the - patch-upload command you ran on this machine earlier. You can also get the hotfix - UUID by running xe patch-list. - xe patch-apply host-uuid=host-uuid uuid=hotfix-uuid - - - Copy the following files from the CloudStack Management Server to the - host. - - - - - - - Copy from here... - ...to here - - - - - /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/xenserver60/NFSSR.py - /opt/xensource/sm/NFSSR.py - - - /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/setupxenserver.sh - /opt/xensource/bin/setupxenserver.sh - - - /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/make_migratable.sh - /opt/xensource/bin/make_migratable.sh - - - - - - - (Only for hotfixes XS602E005 and XS602E007) You need to apply a new Cloud - Support Pack. - - - Download the CSP software onto the XenServer host from one of the following - links: - For hotfix XS602E005: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E005/56710/xe-phase-2/xenserver-cloud-supp.tgz - For hotfix XS602E007: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E007/57824/xe-phase-2/xenserver-cloud-supp.tgz - - - Extract the file: - # tar xf xenserver-cloud-supp.tgz - - - Run the following script: - # xe-install-supplemental-pack xenserver-cloud-supp.iso - - - If the XenServer host is part of a zone that uses basic networking, disable - Open vSwitch (OVS): - # xe-switch-network-backend bridge - - - - - Reboot this XenServer host. - - - Run the following: - /opt/xensource/bin/setupxenserver.sh - - If the message "mv: cannot stat `/etc/cron.daily/logrotate': No such file or - directory" appears, you can safely ignore it. - - - - Run the following: - for pbd in `xe pbd-list currently-attached=false| grep ^uuid | awk '{print $NF}'`; do xe pbd-plug uuid=$pbd ; - - - On each slave host in the Xen pool, repeat these steps, starting from "manually - live migrate VMs." - - - - - - Troubleshooting Tip - If passwords which you know to be valid appear not to work after upgrade, or other UI - issues are seen, try clearing your browser cache and reloading the UI page. - -
-
- Upgrade from 2.2.14 to 4.1.0 - - - Ensure that you query your IPaddress usage records and process them; for example, - issue invoices for any usage that you have not yet billed users for. - Starting in 3.0.2, the usage record format for IP addresses is the same as the rest - of the usage types. Instead of a single record with the assignment and release dates, - separate records are generated per aggregation period with start and end dates. After - upgrading to 4.1.0, any existing IP address usage records in the old format - will no longer be available. - - - If you are using version 2.2.0 - 2.2.13, first upgrade to 2.2.14 by using the - instructions in the 2.2.14 Release Notes. - - KVM Hosts - If KVM hypervisor is used in your cloud, be sure you completed the step to insert - a valid username and password into the host_details table on each KVM node as - described in the 2.2.14 Release Notes. This step is critical, as the database will be - encrypted after the upgrade to 4.1.0. - - - - While running the 2.2.14 system, log in to the UI as root administrator. - - - Using the UI, add a new System VM template for each hypervisor type that is used in - your cloud. In each zone, add a system VM template for each hypervisor used in that - zone - - - In the left navigation bar, click Templates. - - - In Select view, click Templates. - - - Click Register template. - The Register template dialog box is displayed. - - - In the Register template dialog box, specify the following values depending on - the hypervisor type (do not change these): - - - - - - - Hypervisor - Description - - - - - XenServer - Name: systemvm-xenserver-4.1.0 - Description: systemvm-xenserver-4.1.0 - URL: - http://download.cloud.com/templates/acton/acton-systemvm-02062012.vhd.bz2 - Zone: Choose the zone where this hypervisor is used - Hypervisor: XenServer - Format: VHD - OS Type: Debian GNU/Linux 5.0 (32-bit) - Extractable: no - Password Enabled: no - Public: no - Featured: no - - - - KVM - Name: systemvm-kvm-4.1.0 - Description: systemvm-kvm-4.1.0 - URL: - http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2 - Zone: Choose the zone where this hypervisor is used - Hypervisor: KVM - Format: QCOW2 - OS Type: Debian GNU/Linux 5.0 (32-bit) - Extractable: no - Password Enabled: no - Public: no - Featured: no - - - - VMware - Name: systemvm-vmware-4.1.0 - Description: systemvm-vmware-4.1.0 - URL: - http://download.cloud.com/templates/burbank/burbank-systemvm-08012012.ova - Zone: Choose the zone where this hypervisor is used - Hypervisor: VMware - Format: OVA - OS Type: Debian GNU/Linux 5.0 (32-bit) - Extractable: no - Password Enabled: no - Public: no - Featured: no - - - - - - - - - - Watch the screen to be sure that the template downloads successfully and enters the - READY state. Do not proceed until this is successful - - - WARNING: If you use more than one type of - hypervisor in your cloud, be sure you have repeated these steps to download the system - VM template for each hypervisor type. Otherwise, the upgrade will fail. - - - Stop all Usage Servers if running. Run this on all Usage Server hosts. - # service cloud-usage stop - - - Stop the Management Servers. Run this on all Management Server hosts. - # service cloud-management stop - - - On the MySQL master, take a backup of the MySQL databases. We recommend performing - this step even in test upgrades. If there is an issue, this will assist with - debugging. - In the following commands, it is assumed that you have set the root password on the - database, which is a CloudStack recommended best practice. Substitute your own MySQL - root password. - # mysqldump -u root -pmysql_password cloud > cloud-backup.dmp + + + + Reboot this XenServer host. + + + Run the following: + /opt/xensource/bin/setupxenserver.sh + + If the message "mv: cannot stat `/etc/cron.daily/logrotate': No such file or + directory" appears, you can safely ignore it. + + + + Run the following: + for pbd in `xe pbd-list currently-attached=false| grep ^uuid | awk '{print $NF}'`; do xe pbd-plug uuid=$pbd ; + + + On each slave host in the Xen pool, repeat these steps, starting from "manually + live migrate VMs." + + + + + + Troubleshooting Tip + If passwords which you know to be valid appear not to work after upgrade, or other UI + issues are seen, try clearing your browser cache and reloading the UI page. + +
+
+ Upgrade from 2.2.14 to 4.1.0 + + + Ensure that you query your IPaddress usage records and process them; for example, + issue invoices for any usage that you have not yet billed users for. + Starting in 3.0.2, the usage record format for IP addresses is the same as the rest + of the usage types. Instead of a single record with the assignment and release dates, + separate records are generated per aggregation period with start and end dates. After + upgrading to 4.1.0, any existing IP address usage records in the old format will no + longer be available. + + + If you are using version 2.2.0 - 2.2.13, first upgrade to 2.2.14 by using the + instructions in the 2.2.14 + Release Notes. + + KVM Hosts + If KVM hypervisor is used in your cloud, be sure you completed the step to insert + a valid username and password into the host_details table on each KVM node as + described in the 2.2.14 Release Notes. This step is critical, as the database will be + encrypted after the upgrade to 4.1.0. + + + + While running the 2.2.14 system, log in to the UI as root administrator. + + + Using the UI, add a new System VM template for each hypervisor type that is used in + your cloud. In each zone, add a system VM template for each hypervisor used in that + zone + + + In the left navigation bar, click Templates. + + + In Select view, click Templates. + + + Click Register template. + The Register template dialog box is displayed. + + + In the Register template dialog box, specify the following values depending on + the hypervisor type (do not change these): + + + + + + + Hypervisor + Description + + + + + XenServer + Name: systemvm-xenserver-4.1.0 + Description: systemvm-xenserver-4.1.0 + URL: + http://download.cloud.com/templates/acton/acton-systemvm-02062012.vhd.bz2 + Zone: Choose the zone where this hypervisor is used + Hypervisor: XenServer + Format: VHD + OS Type: Debian GNU/Linux 5.0 (32-bit) + Extractable: no + Password Enabled: no + Public: no + Featured: no + + + + KVM + Name: systemvm-kvm-4.1.0 + Description: systemvm-kvm-4.1.0 + URL: + http://download.cloud.com/templates/acton/acton-systemvm-02062012.qcow2.bz2 + Zone: Choose the zone where this hypervisor is used + Hypervisor: KVM + Format: QCOW2 + OS Type: Debian GNU/Linux 5.0 (32-bit) + Extractable: no + Password Enabled: no + Public: no + Featured: no + + + + VMware + Name: systemvm-vmware-4.1.0 + Description: systemvm-vmware-4.1.0 + URL: + http://download.cloud.com/templates/burbank/burbank-systemvm-08012012.ova + Zone: Choose the zone where this hypervisor is used + Hypervisor: VMware + Format: OVA + OS Type: Debian GNU/Linux 5.0 (32-bit) + Extractable: no + Password Enabled: no + Public: no + Featured: no + + + + + + + + + + Watch the screen to be sure that the template downloads successfully and enters the + READY state. Do not proceed until this is successful + + + WARNING: If you use more than one type of + hypervisor in your cloud, be sure you have repeated these steps to download the system + VM template for each hypervisor type. Otherwise, the upgrade will fail. + + + Stop all Usage Servers if running. Run this on all Usage Server hosts. + # service cloud-usage stop + + + Stop the Management Servers. Run this on all Management Server hosts. + # service cloud-management stop + + + On the MySQL master, take a backup of the MySQL databases. We recommend performing + this step even in test upgrades. If there is an issue, this will assist with + debugging. + In the following commands, it is assumed that you have set the root password on the + database, which is a CloudStack recommended best practice. Substitute your own MySQL + root password. + # mysqldump -u root -pmysql_password cloud > cloud-backup.dmp # mysqldump -u root -pmysql_password cloud_usage > cloud-usage-backup.dmp - - - Either build RPM/DEB packages as detailed in the Installation Guide, or use one of - the community provided yum/apt repositories to gain access to the &PRODUCT; binaries. - - - - After you have configured an appropriate yum or apt repository, you may execute the - one of the following commands as appropriate for your environment in order to upgrade - &PRODUCT;: # yum update cloud-* - # apt-get update - # apt-get upgrade cloud-* - - You will, of course, have to agree to the changes suggested by Yum or APT. - - - If you have made changes to your existing copy of the file components.xml in your - previous-version CloudStack installation, the changes will be preserved in the upgrade. - However, you need to do the following steps to place these changes in a new version of - the file which is compatible with version 4.0.0-incubating. - - How will you know whether you need to do this? If the upgrade output in the - previous step included a message like the following, then some custom content was - found in your old components.xml, and you need to merge the two files: - - warning: /etc/cloud/management/components.xml created as /etc/cloud/management/components.xml.rpmnew - - - Make a backup copy of your - /etc/cloud/management/components.xml file. For - example: - # mv /etc/cloud/management/components.xml /etc/cloud/management/components.xml-backup - - - Copy /etc/cloud/management/components.xml.rpmnew to create - a new /etc/cloud/management/components.xml: - # cp -ap /etc/cloud/management/components.xml.rpmnew /etc/cloud/management/components.xml - - - Merge your changes from the backup file into the new components.xml file. - # vi /etc/cloud/management/components.xml + + + Either build RPM/DEB packages as detailed in the Installation Guide, or use one of + the community provided yum/apt repositories to gain access to the &PRODUCT; binaries. + + + + If you are using Ubuntu, follow this procedure to upgrade your packages. If not, + skip to step . + + Community Packages + This section assumes you're using the community supplied packages for &PRODUCT;. + If you've created your own packages and APT repository, substitute your own URL for + the ones used in these examples. + + + + The first order of business will be to change the sources list for each system + with &PRODUCT; packages. This means all management servers, and any hosts that have + the KVM agent. (No changes should be necessary for hosts that are running VMware or + Xen.) + Start by opening /etc/apt/sources.list.d/cloudstack.list on + any systems that have &PRODUCT; packages installed. + This file should have one line, which contains: + deb http://cloudstack.apt-get.eu/ubuntu precise 4.0 + We'll change it to point to the new package repository: + deb http://cloudstack.apt-get.eu/ubuntu precise 4.1 + If you're using your own package repository, change this line to read as + appropriate for your 4.1.0 repository. + + + Now update your apt package list: + $ sudo apt-get update + + + Now that you have the repository configured, it's time to install the + cloudstack-management package. This will pull in any other + dependencies you need. + $ sudo apt-get install cloudstack-management + + + You will need to manually install the cloudstack-agent + package: + $ sudo apt-get install cloudstack-agent + During the installation of cloudstack-agent, APT will copy + your agent.properties, log4j-cloud.xml, + and environment.properties from + /etc/cloud/agent to + /etc/cloudstack/agent. + When prompted whether you wish to keep your configuration, say Yes. + + + Verify that the file + /etc/cloudstack/agent/environment.properties has a line that + reads: + paths.script=/usr/share/cloudstack-common + If not, add the line. + + + Restart the agent: + +service cloud-agent stop +killall jsvc +service cloudstack-agent start - - - - - If you have made changes to your existing copy of the - /etc/cloud/management/db.properties file in your previous-version - CloudStack installation, the changes will be preserved in the upgrade. However, you need - to do the following steps to place these changes in a new version of the file which is - compatible with version 4.0.0-incubating. - - - Make a backup copy of your file - /etc/cloud/management/db.properties. For example: - # mv /etc/cloud/management/db.properties /etc/cloud/management/db.properties-backup - - - Copy /etc/cloud/management/db.properties.rpmnew to create a - new /etc/cloud/management/db.properties: - # cp -ap /etc/cloud/management/db.properties.rpmnew etc/cloud/management/db.properties - - - Merge your changes from the backup file into the new db.properties file. - # vi /etc/cloud/management/db.properties - - - - - On the management server node, run the following command. It is recommended that you - use the command-line flags to provide your own encryption keys. See Password and Key - Encryption in the Installation Guide. - # cloud-setup-encryption -e encryption_type -m management_server_key -k database_key - When used without arguments, as in the following example, the default encryption - type and keys will be used: - - - (Optional) For encryption_type, use file or web to indicate the technique used - to pass in the database encryption password. Default: file. - - - (Optional) For management_server_key, substitute the default key that is used to - encrypt confidential parameters in the properties file. Default: password. It is - highly recommended that you replace this with a more secure value - - - (Optional) For database_key, substitute the default key that is used to encrypt - confidential parameters in the CloudStack database. Default: password. It is highly - recommended that you replace this with a more secure value. - - - - - Repeat steps 10 - 14 on every management server node. If you provided your own - encryption key in step 14, use the same key on all other management servers. - - - Start the first Management Server. Do not start any other Management Server nodes - yet. - # service cloud-management start - Wait until the databases are upgraded. Ensure that the database upgrade is complete. - You should see a message like "Complete! Done." After confirmation, start the other - Management Servers one at a time by running the same command on each node. - - - Start all Usage Servers (if they were running on your previous version). Perform - this on each Usage Server host. - # service cloud-usage start - - - (KVM only) Additional steps are required for each KVM host. These steps will not - affect running guests in the cloud. These steps are required only for clouds using KVM - as hosts and only on the KVM hosts. - - - Configure your CloudStack package repositories as outlined in the Installation - Guide - - - Stop the running agent. - # service cloud-agent stop - - - Update the agent software with one of the following command sets as - appropriate. - # yum update cloud-* - + + + During the upgrade, log4j-cloud.xml was simply copied over, + so the logs will continue to be added to + /var/log/cloud/agent/agent.log. There's nothing + wrong with this, but if you prefer to be consistent, you can + change this by copying over the sample configuration file: + +cd /etc/cloudstack/agent +mv log4j-cloud.xml.dpkg-dist log4j-cloud.xml +service cloudstack-agent restart + + + + Once the agent is running, you can uninstall the old cloud-* packages from your + system: + sudo dpkg --purge cloud-agent + + + + + If you are using CentOS or RHEL, follow this procedure to upgrade your packages. If + not, skip to step . + + Community Packages + This section assumes you're using the community supplied packages for &PRODUCT;. + If you've created your own packages and yum repository, substitute your own URL for + the ones used in these examples. + + + + The first order of business will be to change the yum repository for each system + with &PRODUCT; packages. This means all management servers, and any hosts that have + the KVM agent. (No changes should be necessary for hosts that are running VMware or + Xen.) + Start by opening /etc/yum.repos.d/cloudstack.repo on any + systems that have &PRODUCT; packages installed. + This file should have content similar to the following: + +[apache-cloudstack] +name=Apache CloudStack +baseurl=http://cloudstack.apt-get.eu/rhel/4.0/ +enabled=1 +gpgcheck=0 + + If you are using the community provided package repository, change the baseurl + to http://cloudstack.apt-get.eu/rhel/4.1/ + If you're using your own package repository, change this line to read as + appropriate for your 4.1.0 repository. + + + Now that you have the repository configured, it's time to install the + cloudstack-management package by upgrading the older + cloud-client package. + $ sudo yum upgrade cloud-client + + + For KVM hosts, you will need to upgrade the cloud-agent + package, similarly installing the new version as + cloudstack-agent. + $ sudo yum upgrade cloud-agent + During the installation of cloudstack-agent, the RPM will + copy your agent.properties, + log4j-cloud.xml, and + environment.properties from + /etc/cloud/agent to + /etc/cloudstack/agent. + + + Verify that the file + /etc/cloudstack/agent/environment.properties has a line that + reads: + paths.script=/usr/share/cloudstack-common + If not, add the line. + + + Restart the agent: + +service cloud-agent stop +killall jsvc +service cloudstack-agent start + + + + + + If you have made changes to your existing copy of the file components.xml in your + previous-version CloudStack installation, the changes will be preserved in the upgrade. + However, you need to do the following steps to place these changes in a new version of + the file which is compatible with version 4.0.0-incubating. + + How will you know whether you need to do this? If the upgrade output in the + previous step included a message like the following, then some custom content was + found in your old components.xml, and you need to merge the two files: + + warning: /etc/cloud/management/components.xml created as /etc/cloud/management/components.xml.rpmnew + + + Make a backup copy of your + /etc/cloud/management/components.xml file. For + example: + # mv /etc/cloud/management/components.xml /etc/cloud/management/components.xml-backup + + + Copy /etc/cloud/management/components.xml.rpmnew to create + a new /etc/cloud/management/components.xml: + # cp -ap /etc/cloud/management/components.xml.rpmnew /etc/cloud/management/components.xml + + + Merge your changes from the backup file into the new components.xml file. + # vi /etc/cloud/management/components.xml + + + + + + If you have made changes to your existing copy of the + /etc/cloud/management/db.properties file in your previous-version + CloudStack installation, the changes will be preserved in the upgrade. However, you need + to do the following steps to place these changes in a new version of the file which is + compatible with version 4.0.0-incubating. + + + Make a backup copy of your file + /etc/cloud/management/db.properties. For example: + # mv /etc/cloud/management/db.properties /etc/cloud/management/db.properties-backup + + + Copy /etc/cloud/management/db.properties.rpmnew to create a + new /etc/cloud/management/db.properties: + # cp -ap /etc/cloud/management/db.properties.rpmnew etc/cloud/management/db.properties + + + Merge your changes from the backup file into the new db.properties file. + # vi /etc/cloud/management/db.properties + + + + + On the management server node, run the following command. It is recommended that you + use the command-line flags to provide your own encryption keys. See Password and Key + Encryption in the Installation Guide. + # cloud-setup-encryption -e encryption_type -m management_server_key -k database_key + When used without arguments, as in the following example, the default encryption + type and keys will be used: + + + (Optional) For encryption_type, use file or web to indicate the technique used + to pass in the database encryption password. Default: file. + + + (Optional) For management_server_key, substitute the default key that is used to + encrypt confidential parameters in the properties file. Default: password. It is + highly recommended that you replace this with a more secure value + + + (Optional) For database_key, substitute the default key that is used to encrypt + confidential parameters in the CloudStack database. Default: password. It is highly + recommended that you replace this with a more secure value. + + + + + Repeat steps 10 - 14 on every management server node. If you provided your own + encryption key in step 14, use the same key on all other management servers. + + + Start the first Management Server. Do not start any other Management Server nodes + yet. + # service cloud-management start + Wait until the databases are upgraded. Ensure that the database upgrade is complete. + You should see a message like "Complete! Done." After confirmation, start the other + Management Servers one at a time by running the same command on each node. + + + Start all Usage Servers (if they were running on your previous version). Perform + this on each Usage Server host. + # service cloud-usage start + + + (KVM only) Additional steps are required for each KVM host. These steps will not + affect running guests in the cloud. These steps are required only for clouds using KVM + as hosts and only on the KVM hosts. + + + Configure your CloudStack package repositories as outlined in the Installation + Guide + + + Stop the running agent. + # service cloud-agent stop + + + Update the agent software with one of the following command sets as + appropriate. + # yum update cloud-* + # apt-get update # apt-get upgrade cloud-* - - - Start the agent. - # service cloud-agent start - - - Copy the contents of the agent.properties file to the new - agent.properties file by using the following command - sed -i 's/com.cloud.agent.resource.computing.LibvirtComputingResource/com.cloud.hypervisor.kvm.resource.LibvirtComputingResource/g' /etc/cloud/agent/agent.properties - - - Start the cloud agent and cloud management services. - - - When the Management Server is up and running, log in to the CloudStack UI and - restart the virtual router for proper functioning of all the features. - - - - - Log in to the CloudStack UI as admin, and check the status of the hosts. All hosts - should come to Up state (except those that you know to be offline). You may need to wait - 20 or 30 minutes, depending on the number of hosts. - Do not proceed to the next step until the hosts show in the Up state. If the hosts - do not come to the Up state, contact support. - - - Run the following script to stop, then start, all Secondary Storage VMs, Console - Proxy VMs, and virtual routers. - - - Run the command once on one management server. Substitute your own IP address of - the MySQL instance, the MySQL user to connect as, and the password to use for that - user. In addition to those parameters, provide the "-c" and "-r" arguments. For - example: - # nohup cloud-sysvmadm -d 192.168.1.5 -u cloud -p password -c -r > sysvm.log 2>&1 & + + + Start the agent. + # service cloud-agent start + + + Copy the contents of the agent.properties file to the new + agent.properties file by using the following command + sed -i 's/com.cloud.agent.resource.computing.LibvirtComputingResource/com.cloud.hypervisor.kvm.resource.LibvirtComputingResource/g' /etc/cloud/agent/agent.properties + + + Start the cloud agent and cloud management services. + + + When the Management Server is up and running, log in to the CloudStack UI and + restart the virtual router for proper functioning of all the features. + + + + + Log in to the CloudStack UI as admin, and check the status of the hosts. All hosts + should come to Up state (except those that you know to be offline). You may need to wait + 20 or 30 minutes, depending on the number of hosts. + Do not proceed to the next step until the hosts show in the Up state. If the hosts + do not come to the Up state, contact support. + + + Run the following script to stop, then start, all Secondary Storage VMs, Console + Proxy VMs, and virtual routers. + + + Run the command once on one management server. Substitute your own IP address of + the MySQL instance, the MySQL user to connect as, and the password to use for that + user. In addition to those parameters, provide the "-c" and "-r" arguments. For + example: + # nohup cloud-sysvmadm -d 192.168.1.5 -u cloud -p password -c -r > sysvm.log 2>&1 & # tail -f sysvm.log - This might take up to an hour or more to run, depending on the number of - accounts in the system. - - - After the script terminates, check the log to verify correct execution: - # tail -f sysvm.log - The content should be like the following: - + This might take up to an hour or more to run, depending on the number of + accounts in the system. + + + After the script terminates, check the log to verify correct execution: + # tail -f sysvm.log + The content should be like the following: + Stopping and starting 1 secondary storage vm(s)... Done stopping and starting secondary storage vm(s) Stopping and starting 1 console proxy vm(s)... @@ -5063,197 +5825,197 @@ under the License. Stopping and starting 4 running routing vm(s)... Done restarting router(s). - - - - - If you would like additional confirmation that the new system VM templates were - correctly applied when these system VMs were rebooted, SSH into the System VM and check - the version. - Use one of the following techniques, depending on the hypervisor. - - XenServer or KVM: - SSH in by using the link local IP address of the system VM. For example, in the - command below, substitute your own path to the private key used to log in to the - system VM and your own link local IP. - - Run the following commands on the XenServer or KVM host on which the system VM is - present: - # ssh -i private-key-path link-local-ip -p 3922 + + + + + If you would like additional confirmation that the new system VM templates were + correctly applied when these system VMs were rebooted, SSH into the System VM and check + the version. + Use one of the following techniques, depending on the hypervisor. + + XenServer or KVM: + SSH in by using the link local IP address of the system VM. For example, in the + command below, substitute your own path to the private key used to log in to the + system VM and your own link local IP. + + Run the following commands on the XenServer or KVM host on which the system VM is + present: + # ssh -i private-key-path link-local-ip -p 3922 # cat /etc/cloudstack-release - The output should be like the following: - Cloudstack Release 4.0.0-incubating Mon Oct 9 15:10:04 PST 2012 - - ESXi - SSH in using the private IP address of the system VM. For example, in the command - below, substitute your own path to the private key used to log in to the system VM and - your own private IP. - - Run the following commands on the Management Server: - # ssh -i private-key-path private-ip -p 3922 + The output should be like the following: + Cloudstack Release 4.0.0-incubating Mon Oct 9 15:10:04 PST 2012 + + ESXi + SSH in using the private IP address of the system VM. For example, in the command + below, substitute your own path to the private key used to log in to the system VM and + your own private IP. + + Run the following commands on the Management Server: + # ssh -i private-key-path private-ip -p 3922 # cat /etc/cloudstack-release - The output should be like the following: - Cloudstack Release 4.0.0-incubating Mon Oct 9 15:10:04 PST 2012 + The output should be like the following: + Cloudstack Release 4.0.0-incubating Mon Oct 9 15:10:04 PST 2012 + + + If needed, upgrade all Citrix XenServer hypervisor hosts in your cloud to a version + supported by CloudStack 4.0.0-incubating. The supported versions are XenServer 5.6 SP2 + and 6.0.2. Instructions for upgrade can be found in the CloudStack 4.0.0-incubating + Installation Guide. + + + Apply the XenServer hotfix XS602E003 (and any other needed hotfixes) to XenServer + v6.0.2 hypervisor hosts. + + + Disconnect the XenServer cluster from CloudStack. + In the left navigation bar of the CloudStack UI, select Infrastructure. Under + Clusters, click View All. Select the XenServer cluster and click Actions - + Unmanage. + This may fail if there are hosts not in one of the states Up, Down, + Disconnected, or Alert. You may need to fix that before unmanaging this + cluster. + Wait until the status of the cluster has reached Unmanaged. Use the CloudStack + UI to check on the status. When the cluster is in the unmanaged state, there is no + connection to the hosts in the cluster. + + + To clean up the VLAN, log in to one XenServer host and run: + /opt/xensource/bin/cloud-clean-vlan.sh + + + Prepare the upgrade by running the following on one XenServer host: + /opt/xensource/bin/cloud-prepare-upgrade.sh + If you see a message like "can't eject CD", log in to the VM and umount the CD, + then run this script again. + + + Upload the hotfix to the XenServer hosts. Always start with the Xen pool master, + then the slaves. Using your favorite file copy utility (e.g. WinSCP), copy the + hotfixes to the host. Place them in a temporary folder such as /root or /tmp. + On the Xen pool master, upload the hotfix with this command: + xe patch-upload file-name=XS602E003.xsupdate + Make a note of the output from this command, which is a UUID for the hotfix + file. You'll need it in another step later. + + (Optional) If you are applying other hotfixes as well, you can repeat the + commands in this section with the appropriate hotfix number. For example, + XS602E004.xsupdate. + + + + Manually live migrate all VMs on this host to another host. First, get a list of + the VMs on this host: + # xe vm-list + Then use this command to migrate each VM. Replace the example host name and VM + name with your own: + # xe vm-migrate live=true host=host-name vm=VM-name + + Troubleshooting + If you see a message like "You attempted an operation on a VM which requires + PV drivers to be installed but the drivers were not detected," run: + /opt/xensource/bin/make_migratable.sh + b6cf79c8-02ee-050b-922f-49583d9f1a14. + + + + Apply the hotfix. First, get the UUID of this host: + # xe host-list + Then use the following command to apply the hotfix. Replace the example host + UUID with the current host ID, and replace the hotfix UUID with the output from the + patch-upload command you ran on this machine earlier. You can also get the hotfix + UUID by running xe patch-list. + xe patch-apply host-uuid=host-uuid + uuid=hotfix-uuid + + + Copy the following files from the CloudStack Management Server to the + host. + + + + + + + Copy from here... + ...to here + + + + + /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/xenserver60/NFSSR.py + /opt/xensource/sm/NFSSR.py + + + /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/setupxenserver.sh + /opt/xensource/bin/setupxenserver.sh + + + /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/make_migratable.sh + /opt/xensource/bin/make_migratable.sh + + + + + + + (Only for hotfixes XS602E005 and XS602E007) You need to apply a new Cloud + Support Pack. + + + Download the CSP software onto the XenServer host from one of the following + links: + For hotfix XS602E005: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E005/56710/xe-phase-2/xenserver-cloud-supp.tgz + For hotfix XS602E007: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E007/57824/xe-phase-2/xenserver-cloud-supp.tgz - If needed, upgrade all Citrix XenServer hypervisor hosts in your cloud to a version - supported by CloudStack 4.0.0-incubating. The supported versions are XenServer 5.6 SP2 - and 6.0.2. Instructions for upgrade can be found in the CloudStack 4.0.0-incubating - Installation Guide. + Extract the file: + # tar xf xenserver-cloud-supp.tgz - Apply the XenServer hotfix XS602E003 (and any other needed hotfixes) to XenServer - v6.0.2 hypervisor hosts. - - - Disconnect the XenServer cluster from CloudStack. - In the left navigation bar of the CloudStack UI, select Infrastructure. Under - Clusters, click View All. Select the XenServer cluster and click Actions - - Unmanage. - This may fail if there are hosts not in one of the states Up, Down, - Disconnected, or Alert. You may need to fix that before unmanaging this - cluster. - Wait until the status of the cluster has reached Unmanaged. Use the CloudStack - UI to check on the status. When the cluster is in the unmanaged state, there is no - connection to the hosts in the cluster. - - - To clean up the VLAN, log in to one XenServer host and run: - /opt/xensource/bin/cloud-clean-vlan.sh - - - Prepare the upgrade by running the following on one XenServer host: - /opt/xensource/bin/cloud-prepare-upgrade.sh - If you see a message like "can't eject CD", log in to the VM and umount the CD, - then run this script again. - - - Upload the hotfix to the XenServer hosts. Always start with the Xen pool master, - then the slaves. Using your favorite file copy utility (e.g. WinSCP), copy the - hotfixes to the host. Place them in a temporary folder such as /root or /tmp. - On the Xen pool master, upload the hotfix with this command: - xe patch-upload file-name=XS602E003.xsupdate - Make a note of the output from this command, which is a UUID for the hotfix - file. You'll need it in another step later. - - (Optional) If you are applying other hotfixes as well, you can repeat the - commands in this section with the appropriate hotfix number. For example, - XS602E004.xsupdate. - - - - Manually live migrate all VMs on this host to another host. First, get a list of - the VMs on this host: - # xe vm-list - Then use this command to migrate each VM. Replace the example host name and VM - name with your own: - # xe vm-migrate live=true host=host-name vm=VM-name - - Troubleshooting - If you see a message like "You attempted an operation on a VM which requires - PV drivers to be installed but the drivers were not detected," run: - /opt/xensource/bin/make_migratable.sh - b6cf79c8-02ee-050b-922f-49583d9f1a14. - - - - Apply the hotfix. First, get the UUID of this host: - # xe host-list - Then use the following command to apply the hotfix. Replace the example host - UUID with the current host ID, and replace the hotfix UUID with the output from the - patch-upload command you ran on this machine earlier. You can also get the hotfix - UUID by running xe patch-list. - xe patch-apply host-uuid=host-uuid - uuid=hotfix-uuid - - - Copy the following files from the CloudStack Management Server to the - host. - - - - - - - Copy from here... - ...to here - - - - - /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/xenserver60/NFSSR.py - /opt/xensource/sm/NFSSR.py - - - /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/setupxenserver.sh - /opt/xensource/bin/setupxenserver.sh - - - /usr/lib64/cloud/common/scripts/vm/hypervisor/xenserver/make_migratable.sh - /opt/xensource/bin/make_migratable.sh - - - - - - - (Only for hotfixes XS602E005 and XS602E007) You need to apply a new Cloud - Support Pack. - - - Download the CSP software onto the XenServer host from one of the following - links: - For hotfix XS602E005: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E005/56710/xe-phase-2/xenserver-cloud-supp.tgz - For hotfix XS602E007: http://coltrane.eng.hq.xensource.com/release/XenServer-6.x/XS-6.0.2/hotfixes/XS602E007/57824/xe-phase-2/xenserver-cloud-supp.tgz - - - Extract the file: - # tar xf xenserver-cloud-supp.tgz - - - Run the following script: - # xe-install-supplemental-pack - xenserver-cloud-supp.iso - - - If the XenServer host is part of a zone that uses basic networking, disable - Open vSwitch (OVS): - # xe-switch-network-backend bridge - - - - - Reboot this XenServer host. - - - Run the following: - /opt/xensource/bin/setupxenserver.sh - - If the message "mv: cannot stat `/etc/cron.daily/logrotate': No such file or - directory" appears, you can safely ignore it. - - - - Run the following: - for pbd in `xe pbd-list currently-attached=false| grep ^uuid | awk - '{print $NF}'`; do xe pbd-plug uuid=$pbd ; - - - - On each slave host in the Xen pool, repeat these steps, starting from "manually - live migrate VMs." - - + Run the following script: + # xe-install-supplemental-pack + xenserver-cloud-supp.iso - -
-
- diff --git a/docs/en-US/advanced-zone-configuration.xml b/docs/en-US/advanced-zone-configuration.xml index 03a082f21ac..43b9391516e 100644 --- a/docs/en-US/advanced-zone-configuration.xml +++ b/docs/en-US/advanced-zone-configuration.xml @@ -362,7 +362,7 @@ Secondary Storage : - NFS Server. The IP address of the server. + NFS Server. The IP address of the server or fully qualified domain name of the server. Path. The exported path from the server. diff --git a/docs/en-US/advanced-zone-network-traffic-types.xml b/docs/en-US/advanced-zone-network-traffic-types.xml index d8035929374..4d1f46592e0 100644 --- a/docs/en-US/advanced-zone-network-traffic-types.xml +++ b/docs/en-US/advanced-zone-network-traffic-types.xml @@ -28,7 +28,7 @@ Guest. When end users run VMs, they generate guest traffic. The guest VMs communicate with each other over a network that can be referred to as the guest network. This network can be isolated or shared. In an isolated guest network, the administrator needs to reserve VLAN ranges to provide isolation for each &PRODUCT; account’s network (potentially a large number of VLANs). In a shared guest network, all guest VMs share a single network. Management. When &PRODUCT;’s internal resources communicate with each other, they generate management traffic. This includes communication between hosts, system VMs (VMs used by &PRODUCT; to perform various tasks in the cloud), and any other component that communicates directly with the &PRODUCT; Management Server. You must configure the IP range for the system VMs to use. Public. Public traffic is generated when VMs in the cloud access the Internet. Publicly accessible IPs must be allocated for this purpose. End users can use the &PRODUCT; UI to acquire these IPs to implement NAT between their guest network and the public network, as described in “Acquiring a New IP Address” in the Administration Guide. - Storage. Traffic such as VM templates and snapshots, which is sent between the secondary storage VM and secondary storage servers. &PRODUCT; uses a separate Network Interface Controller (NIC) named storage NIC for storage network traffic. Use of a storage NIC that always operates on a high bandwidth network allows fast template and snapshot copying. You must configure the IP range to use for the storage network. + Storage. While labeled "storage" this is specifically about secondary storage, and doesn't affect traffic for primary storage. This includes traffic such as VM templates and snapshots, which is sent between the secondary storage VM and secondary storage servers. &PRODUCT; uses a separate Network Interface Controller (NIC) named storage NIC for storage network traffic. Use of a storage NIC that always operates on a high bandwidth network allows fast template and snapshot copying. You must configure the IP range to use for the storage network. These traffic types can each be on a separate physical network, or they can be combined with certain restrictions. When you use the Add Zone wizard in the UI to create a new zone, you are guided into making only valid choices.
diff --git a/docs/en-US/basic-zone-network-traffic-types.xml b/docs/en-US/basic-zone-network-traffic-types.xml index 70789d0fa1a..850373658b4 100644 --- a/docs/en-US/basic-zone-network-traffic-types.xml +++ b/docs/en-US/basic-zone-network-traffic-types.xml @@ -26,10 +26,10 @@ When basic networking is used, there can be only one physical network in the zone. That physical network carries the following traffic types: Guest. When end users run VMs, they generate guest traffic. The guest VMs communicate with each other over a network that can be referred to as the guest network. Each pod in a basic zone is a broadcast domain, and therefore each pod has a different IP range for the guest network. The administrator must configure the IP range for each pod. - Management. When &PRODUCT;’s internal resources communicate with each other, they generate management traffic. This includes communication between hosts, system VMs (VMs used by &PRODUCT; to perform various tasks in the cloud), and any other component that communicates directly with the &PRODUCT; Management Server. You must configure the IP range for the system VMs to use. + Management. When &PRODUCT;'s internal resources communicate with each other, they generate management traffic. This includes communication between hosts, system VMs (VMs used by &PRODUCT; to perform various tasks in the cloud), and any other component that communicates directly with the &PRODUCT; Management Server. You must configure the IP range for the system VMs to use. We strongly recommend the use of separate NICs for management traffic and guest traffic. Public. Public traffic is generated when VMs in the cloud access the Internet. Publicly accessible IPs must be allocated for this purpose. End users can use the &PRODUCT; UI to acquire these IPs to implement NAT between their guest network and the public network, as described in Acquiring a New IP Address. - Storage. Traffic such as VM templates and snapshots, which is sent between the secondary storage VM and secondary storage servers. &PRODUCT; uses a separate Network Interface Controller (NIC) named storage NIC for storage network traffic. Use of a storage NIC that always operates on a high bandwidth network allows fast template and snapshot copying. You must configure the IP range to use for the storage network. + Storage. While labeled "storage" this is specifically about secondary storage, and doesn't affect traffic for primary storage. This includes traffic such as VM templates and snapshots, which is sent between the secondary storage VM and secondary storage servers. &PRODUCT; uses a separate Network Interface Controller (NIC) named storage NIC for storage network traffic. Use of a storage NIC that always operates on a high bandwidth network allows fast template and snapshot copying. You must configure the IP range to use for the storage network. In a basic network, configuring the physical network is fairly straightforward. In most cases, you only need to configure one guest network to carry traffic that is generated by guest VMs. If you use a NetScaler load balancer and enable its elastic IP and elastic load balancing (EIP and ELB) features, you must also configure a network to carry public traffic. &PRODUCT; takes care of presenting the necessary network configuration steps to you in the UI when you add a new zone. diff --git a/docs/en-US/build-nonoss.xml b/docs/en-US/build-nonoss.xml new file mode 100644 index 00000000000..fceca6071c2 --- /dev/null +++ b/docs/en-US/build-nonoss.xml @@ -0,0 +1,49 @@ + + +%BOOK_ENTITIES; +]> + + + +
+ Building Non-OSS + If you need support for the VMware, NetApp, F5, NetScaler, SRX, or any other non-Open Source Software (nonoss) plugins, you'll need to download a few components on your own and follow a slightly different procedure to build from source. + Why Non-OSS? + Some of the plugins supported by &PRODUCT; cannot be distributed with &PRODUCT; for licensing reasons. In some cases, some of the required libraries/JARs are under a proprietary license. In other cases, the required libraries may be under a license that's not compatible with Apache's licensing guidelines for third-party products. + + + + To build the Non-OSS plugins, you'll need to have the requisite JARs installed under the deps directory. + Because these modules require dependencies that can't be distributed with &PRODUCT; you'll need to download them yourself. Links to the most recent dependencies are listed on the How to build on master branch page on the wiki. + + You may also need to download vhd-util, which was removed due to licensing issues. You'll copy vhd-util to the scripts/vm/hypervisor/xenserver/ directory. + + + Once you have all the dependencies copied over, you'll be able to build &PRODUCT; with the nonoss option: + + $ mvn clean + $ mvn install -Dnonoss + + + + Once you've built &PRODUCT; with the nonoss profile, you can package it using the or instructions. + + +
diff --git a/docs/en-US/changed-API-commands-4.2.xml b/docs/en-US/changed-API-commands-4.2.xml new file mode 100644 index 00000000000..cbaa2e3fa92 --- /dev/null +++ b/docs/en-US/changed-API-commands-4.2.xml @@ -0,0 +1,107 @@ + + +%BOOK_ENTITIES; +]> + +
+ Changed API Commands in 4.2 + + + + + Parameter Name + Description + + + + + updateResourceLimit + + Added the following resource types to the resourcetype + request parameter to set the limits: + + + CPU + + + RAM + + + primary storage + + + secondary storage + + + network rate + + + + + + updateResourceCount + + Added the following resource types to the resourcetype + request parameter to set the limits: + + + CPU + + + RAM + + + primary storage + + + secondary storage + + + network rate + + + + + + listResourceLimits + + Added the following resource types to the resourcetype + request parameter: + + + CPU + + + RAM + + + primary storage + + + secondary storage + + + network rate + + + + + + + +
diff --git a/docs/en-US/feedback.xml b/docs/en-US/feedback.xml new file mode 100644 index 00000000000..4b06c9f3898 --- /dev/null +++ b/docs/en-US/feedback.xml @@ -0,0 +1,24 @@ + + +%BOOK_ENTITIES; +]> + +
+ Feedback + to-do +
diff --git a/docs/en-US/hypervisor-kvm-install-flow.xml b/docs/en-US/hypervisor-kvm-install-flow.xml index 7dfd47d2e52..aa19e47be77 100644 --- a/docs/en-US/hypervisor-kvm-install-flow.xml +++ b/docs/en-US/hypervisor-kvm-install-flow.xml @@ -34,5 +34,5 @@ - + diff --git a/docs/en-US/hypervisor-support-for-primarystorage.xml b/docs/en-US/hypervisor-support-for-primarystorage.xml index 7c2596eac29..fdef1f2b6e0 100644 --- a/docs/en-US/hypervisor-support-for-primarystorage.xml +++ b/docs/en-US/hypervisor-support-for-primarystorage.xml @@ -22,71 +22,83 @@ under the License. -->
- Hypervisor Support for Primary Storage - The following table shows storage options and parameters for different hypervisors. - - - - - - - - - - - VMware vSphere - Citrix XenServer - KVM - - - - - Format for Disks, Templates, and - Snapshots - VMDK - VHD - QCOW2 - - - iSCSI support - VMFS - Clustered LVM - Yes, via Shared Mountpoint - - - Fiber Channel support - VMFS - Yes, via Existing SR - Yes, via Shared Mountpoint - - - NFS support - Y - Y - Y - - - - Local storage support - Y - Y - Y - - - - Storage over-provisioning - NFS and iSCSI - NFS - NFS - - - - - - XenServer uses a clustered LVM system to store VM images on iSCSI and Fiber Channel volumes and does not support over-provisioning in the hypervisor. The storage server itself, however, can support thin-provisioning. As a result the &PRODUCT; can still support storage over-provisioning by running on thin-provisioned storage volumes. - KVM supports "Shared Mountpoint" storage. A shared mountpoint is a file system path local to each server in a given cluster. The path must be the same across all Hosts in the cluster, for example /mnt/primary1. This shared mountpoint is assumed to be a clustered filesystem such as OCFS2. In this case the &PRODUCT; does not attempt to mount or unmount the storage as is done with NFS. The &PRODUCT; requires that the administrator insure that the storage is available - - With NFS storage, &PRODUCT; manages the overprovisioning. In this case the global configuration parameter storage.overprovisioning.factor controls the degree of overprovisioning. This is independent of hypervisor type. - Local storage is an option for primary storage for vSphere, XenServer, and KVM. When the local disk option is enabled, a local disk storage pool is automatically created on each host. To use local storage for the System Virtual Machines (such as the Virtual Router), set system.vm.use.local.storage to true in global configuration. - &PRODUCT; supports multiple primary storage pools in a Cluster. For example, you could provision 2 NFS servers in primary storage. Or you could provision 1 iSCSI LUN initially and then add a second iSCSI LUN when the first approaches capacity. -
+ Hypervisor Support for Primary Storage + The following table shows storage options and parameters for different hypervisors. + + + + + + + + + + + VMware vSphere + Citrix XenServer + KVM + + + + + Format for Disks, Templates, and + Snapshots + VMDK + VHD + QCOW2 + + + iSCSI support + VMFS + Clustered LVM + Yes, via Shared Mountpoint + + + Fiber Channel support + VMFS + Yes, via Existing SR + Yes, via Shared Mountpoint + + + NFS support + Y + Y + Y + + + Local storage support + Y + Y + Y + + + Storage over-provisioning + NFS and iSCSI + NFS + NFS + + + + + XenServer uses a clustered LVM system to store VM images on iSCSI and Fiber Channel volumes + and does not support over-provisioning in the hypervisor. The storage server itself, however, + can support thin-provisioning. As a result the &PRODUCT; can still support storage + over-provisioning by running on thin-provisioned storage volumes. + KVM supports "Shared Mountpoint" storage. A shared mountpoint is a file system path local to + each server in a given cluster. The path must be the same across all Hosts in the cluster, for + example /mnt/primary1. This shared mountpoint is assumed to be a clustered filesystem such as + OCFS2. In this case the &PRODUCT; does not attempt to mount or unmount the storage as is done + with NFS. The &PRODUCT; requires that the administrator insure that the storage is + available + + With NFS storage, &PRODUCT; manages the overprovisioning. In this case the global + configuration parameter storage.overprovisioning.factor controls the degree of overprovisioning. + This is independent of hypervisor type. + Local storage is an option for primary storage for vSphere, XenServer, and KVM. When the + local disk option is enabled, a local disk storage pool is automatically created on each host. + To use local storage for the System Virtual Machines (such as the Virtual Router), set + system.vm.use.local.storage to true in global configuration. + &PRODUCT; supports multiple primary storage pools in a Cluster. For example, you could + provision 2 NFS servers in primary storage. Or you could provision 1 iSCSI LUN initially and + then add a second iSCSI LUN when the first approaches capacity. + diff --git a/docs/en-US/images/VMSnapshotButton.png b/docs/en-US/images/VMSnapshotButton.png new file mode 100644 index 00000000000..52177402198 Binary files /dev/null and b/docs/en-US/images/VMSnapshotButton.png differ diff --git a/docs/en-US/images/revert-vm.png b/docs/en-US/images/revert-vm.png new file mode 100644 index 00000000000..04655dc37ad Binary files /dev/null and b/docs/en-US/images/revert-vm.png differ diff --git a/docs/en-US/limit-accounts-domains.xml b/docs/en-US/limit-accounts-domains.xml new file mode 100644 index 00000000000..a864ee27ef3 --- /dev/null +++ b/docs/en-US/limit-accounts-domains.xml @@ -0,0 +1,371 @@ + + +%BOOK_ENTITIES; +]> + + +
+ Limiting Resource Usage + &PRODUCT; allows you to control resource usage based on the types of resources, such as CPU, + RAM, Primary storage, and Secondary storage. A new set of resource types has been added to the + existing pool of resources to support the new customization model—need-basis usage, such + as large VM or small VM. The new resource types are now broadly classified as CPU, RAM, Primary + storage, and Secondary storage. The root administrator is able to impose resource usage limit by + the following resource types for Domain, Project, and Accounts. + + + CPUs + + + Memory (RAM) + + + Primary Storage (Volumes) + + + Secondary Storage (Snapshots, Templates, ISOs) + + + To control the behaviour of this feature, the following configuration parameters have been + added: + + + + + Parameter Name + Description + + + + + max.account.cpus + Maximum number of CPU cores that can be used for an account. + Default is 40. + + + max.account.ram (MB) + Maximum RAM that can be used for an account. + Default is 40960. + + + max.account.primary.storage (GB) + Maximum primary storage space that can be used for an account. + Default is 200. + + + + max.account.secondary.storage (GB) + Maximum secondary storage space that can be used for an account. + Default is 400. + + + max.project.cpus + + Maximum number of CPU cores that can be used for an account. + Default is 40. + + + + max.project.ram (MB) + + Maximum RAM that can be used for an account. + Default is 40960. + + + + max.project.primary.storage (GB) + + Maximum primary storage space that can be used for an account. + Default is 200. + + + + max.project.secondary.storage (GB) + + Maximum secondary storage space that can be used for an account. + Default is 400. + + + + + +
+ User Permission + The root administrator, domain administrators and users are able to list resources. Ensure + that proper logs are maintained in the vmops.log and + api.log files. + + + The root admin will have the privilege to list and update resource limits. + + + The domain administrators are allowed to list and change these resource limits only + for the sub-domains and accounts under their own domain or the sub-domains. + + + The end users will the privilege to list resource limits. Use the listResourceLimits + API. + + +
+
+ Limit Usage Considerations + + + Primary or Secondary storage space refers to the stated size of the volume and not the + physical size— the actual consumed size on disk in case of thin provisioning. + + + If the admin reduces the resource limit for an account and set it to less than the + resources that are currently being consumed, the existing VMs/templates/volumes are not + destroyed. Limits are imposed only if the user under that account tries to execute a new + operation using any of these resources. For example, the existing behavior in the case of + a VM are: + + + migrateVirtualMachine: The users under that account will be able to migrate the + running VM into any other host without facing any limit issue. + + + recoverVirtualMachine: Destroyed VMs cannot be recovered. + + + + + For any resource type, if a domain has limit X, sub-domains or accounts under that + domain can have there own limits. However, the sum of resource allocated to a sub-domain + or accounts under the domain at any point of time should not exceed the value X. + For example, if a domain has the CPU limit of 40 and the sub-domain D1 and account A1 + can have limits of 30 each, but at any point of time the resource allocated to D1 and A1 + should not exceed the limit of 40. + + + If any operation needs to pass through two of more resource limit check, then the + lower of 2 limits will be enforced, For example: if an account has the VM limit of 10 and + CPU limit of 20, and a user under that account requests 5 VMs of 4 CPUs each. The user + can deploy 5 more VMs because VM limit is 10. However, the user cannot deploy any more + instances because the CPU limit has been exhausted. + + +
+
+ Per-Domain Limits + &PRODUCT; allows the configuration of limits on a domain basis. With a domain limit in + place, all users still have their account limits. They are additionally limited, as a group, + to not exceed the resource limits set on their domain. Domain limits aggregate the usage of + all accounts in the domain as well as all the accounts in all the sub-domains of that domain. + Limits set at the root domain level apply to the sum of resource usage by the accounts in all + the domains and sub-domains below that root domain. + To set a domain limit: + + + Log in to the &PRODUCT; UI. + + + In the left navigation tree, click Domains. + + + Select the domain you want to modify. The current domain limits are displayed. + A value of -1 shows that there is no limit in place. + + + Click the Edit button + + + + + editbutton.png: edits the settings. + + + + + Edit the following as per your requirement: + + + + + Parameter Name + Description + + + + + Instance Limits + The number of instances that can be used in a domain. + + + Public IP Limits + + The number of public IP addresses that can be used in a + domain. + + + Volume Limits + The number of disk volumes that can be created in a domain. + + + + Snapshot Limits + The number of snapshots that can be created in a domain. + + + Template Limits + The number of templates that can be registered in a + domain. + + + VPC limits + The number of VPCs that can be created in a domain. + + + CPU limits + + The number of CPU cores that can be used for a domain. + + + + Memory limits (MB) + + The number of RAM that can be used for a domain. + + + + Primary Storage limits (GB) + + The primary storage space that can be used for a domain. + + + + Secondary Storage limits (GB) + + The secondary storage space that can be used for a domain. + + + + + + + + Click Apply. + + +
+
+ Default Account Resource Limits + You can limit resource use by accounts. The default limits are set by using Global + configuration parameters, and they affect all accounts within a cloud. The relevant parameters + are those beginning with max.account, for example: max.account.snapshots. + To override a default limit for a particular account, set a per-account resource + limit. + + + Log in to the &PRODUCT; UI. + + + In the left navigation tree, click Accounts. + + + Select the account you want to modify. The current limits are displayed. + A value of -1 shows that there is no limit in place. + + + Click the Edit button. + + + + + editbutton.png: edits the settings + + + + + Edit the following as per your requirement: + + + + + Parameter Name + Description + + + + + Instance Limits + The number of instances that can be used in an account. + The default is 20. + + + Public IP Limits + + The number of public IP addresses that can be used in an account. + The default is 20. + + + Volume Limits + The number of disk volumes that can be created in an account. + The default is 20. + + + Snapshot Limits + The number of snapshots that can be created in an account. + The default is 20. + + + Template Limits + The number of templates that can be registered in an account. + The default is 20. + + + VPC limits + The number of VPCs that can be created in an account. + The default is 20. + + + CPU limits + + The number of CPU cores that can be used for an account. + The default is 40. + + + Memory limits (MB) + + The number of RAM that can be used for an account. + The default is 40960. + + + Primary Storage limits (GB) + + The primary storage space that can be used for an account. + The default is 200. + + + Secondary Storage limits (GB) + + The secondary storage space that can be used for an account. + The default is 400. + + + + + + + Click Apply. + + +
+
diff --git a/docs/en-US/source-build.xml b/docs/en-US/source-build.xml index 33218962174..8504385ee29 100644 --- a/docs/en-US/source-build.xml +++ b/docs/en-US/source-build.xml @@ -25,11 +25,11 @@
Building &PRODUCT; from Source - Prior to the 4.0.0 incubating release, Ant was used to build &PRODUCT;. Starting with 4.0.0 a migration to Maven is underway. + Prior to the 4.0.0 incubating release, Ant was used to build &PRODUCT;. A migration to Maven started in the 4.0.0 cycle, and has completed in 4.1.0. The website and the wiki contain up to date information on the build procedure at: https://cwiki.apache.org/CLOUDSTACK/building-with-maven.html - http://incubator.apache.org/cloudstack/develop/environment.html + https://cwiki.apache.org/CLOUDSTACK/setting-up-cloudstack-development-environment.html The overarching steps to build &PRODUCT; are:. diff --git a/docs/en-US/source.xml b/docs/en-US/source.xml index 5d911c23050..ea30000c6a9 100644 --- a/docs/en-US/source.xml +++ b/docs/en-US/source.xml @@ -34,4 +34,5 @@ + diff --git a/docs/en-US/troubleshooting-working-with-server-logs.xml b/docs/en-US/troubleshooting-working-with-server-logs.xml index 1017bf57252..fa0f78cae3d 100644 --- a/docs/en-US/troubleshooting-working-with-server-logs.xml +++ b/docs/en-US/troubleshooting-working-with-server-logs.xml @@ -24,10 +24,10 @@
Working with Server Logs - The &PRODUCT; Management Server logs all web site, middle tier, and database activities for diagnostics purposes in /var/log/cloud/management/. The &PRODUCT; logs a variety of error messages. We recommend this command to find the problematic output in the Management Server log:. + The &PRODUCT; Management Server logs all web site, middle tier, and database activities for diagnostics purposes in /var/log/cloudstack/management/. The &PRODUCT; logs a variety of error messages. We recommend this command to find the problematic output in the Management Server log:. When copying and pasting a command, be sure the command has pasted as a single line before executing. Some document viewers may introduce unwanted line breaks in copied text. - grep -i -E 'exception|unable|fail|invalid|leak|warn|error' /var/log/cloud/management/management-server.log + grep -i -E 'exception|unable|fail|invalid|leak|warn|error' /var/log/cloudstack/management/management-server.log The &PRODUCT; processes requests with a Job ID. If you find an error in the logs and you are interested in debugging the issue you can grep for this job ID in the management server log. For example, suppose that you find the following ERROR message: @@ -37,5 +37,5 @@ grep "job-1076)" management-server.log - The &PRODUCT; Agent Server logs its activities in /var/log/cloud/agent/. + The &PRODUCT; Agent Server logs its activities in /var/log/cloudstack/agent/.
diff --git a/docs/en-US/virtual-machines.xml b/docs/en-US/virtual-machines.xml index 7c74932b649..20018da8dfb 100644 --- a/docs/en-US/virtual-machines.xml +++ b/docs/en-US/virtual-machines.xml @@ -26,6 +26,7 @@ + diff --git a/docs/en-US/vm-snapshots.xml b/docs/en-US/vm-snapshots.xml new file mode 100644 index 00000000000..8d4bcf9bca1 --- /dev/null +++ b/docs/en-US/vm-snapshots.xml @@ -0,0 +1,146 @@ + + +%BOOK_ENTITIES; +]> + + +
+ Virtual Machine Snapshots for VMware + (VMware hosts only) + In addition to the existing &PRODUCT; ability to snapshot VM volumes, + you can now take a VM snapshot to preserve all of the VM's state and data. + This is useful for quick restore of a VM. + For example, you can snapshot a VM, then make changes such as software upgrades. + If anything goes wrong, simply restore the VM to its previous state using the previously saved VM snapshot. + + The snapshot is created using the VMware native snapshot facility. The VM snapshot + includes not only the data volumes, but optionally also whether the VM is running or + turned off (CPU state) and the memory contents. The snapshot is stored in &PRODUCT;'s + primary storage. + VM snapshots can have a parent/child relationship. + Each successive snapshot of the same VM is the child of the snapshot that came before it. + Each time you take an additional snapshot of the same VM, it saves only the differences + between the current state of the VM and the state stored in the most recent previous snapshot. + The previous snapshot becomes a parent, and the new snapshot is its child. + It is possible to create a long chain of these parent/child snapshots, + which amount to a "redo" record leading from the current state of the VM back to the + original. + If you need more information about VM snapshots, check out the VMware documentation + and the VMware Knowledge Base, especially + Understanding virtual machine snapshots. +
+ Limitations on VM Snapshots + + If a VM has some stored snapshots, you can't attach new volume to the VM + or delete any existing volumes. + If you change the volumes on the VM, it would become impossible to restore the VM snapshot + which was created with the previous volume structure. + VM snapshots which include both data volumes and memory can't be kept if you change the VM's + service offering. Any existing VM snapshots of this type will be discarded. + + You can't make a VM snapshot at the same time as you are taking a volume + snapshot. + + + The "quiesce" option is not supported. This option is provided by the underlying + VMware snapshot facility so that you can choose whether to quiesce the file system + on a running virtual machine before taking the snapshot. In &PRODUCT;, the quiesce option is always + set to false; the file system is not quiesced before taking a snapshot of a running VM. + + + You should use only &PRODUCT; to create VM snapshots on VMware hosts managed by &PRODUCT;. + Any snapshots that you make directly on vSphere will not be tracked in &PRODUCT;. + +
+
+ Configuring VM Snapshots + The cloud administrator can use global configuration variables to control the behavior of VM snapshots. + To set these variables, go through the Global Settings are of the UI. + + + + + Configuration Setting Name + Description + + + + + vmsnapshots.max + The maximum number of VM snapshots that can be saved for any given virtual machine in the cloud. + The total possible number of VM snapshots in the cloud is (number of VMs) * vmsnapshots.max. + If the number of snapshots for any VM ever hits the maximum, the older ones are removed + by the snapshot expunge job. + + + + vmsnapshot.create.wait + Number of seconds to wait for a snapshot job to succeed before declaring failure and issuing an error. + + + + +
+
+ Using VM Snapshots + To create a VM snapshot using the &PRODUCT; UI: + + Log in to the &PRODUCT; UI as a user or administrator. + Click Instances. + Click the name of the VM you want to snapshot. + Click the Take VM Snapshot button. + + + + + + If a snapshot is already in progress, then clicking this button will have no effect. + + Provide a name and description. These will be displayed in the VM Snapshots list. + (For running VMs only) If you want to include the VM's memory in the snapshot, click the + Memory checkbox. This saves the CPU and memory state of the virtual machine. If you + don't check this box, then only the current state of the VM disk is saved. Checking + this box makes the snapshot take longer. + Click OK. + + To delete a snapshot or restore a VM to the state saved in a particular snapshot: + + Navigate to the VM as described in the earlier steps. + Click View VM Snapshots. + In the list of snapshots, click the name of the snapshot you want to work with. + Depending on what you want to do: + To delete the snapshot, click the Delete button. + + + + + + To revert to the snapshot, click the Revert button. + + + + + + + + VM snapshots are deleted automatically when a VM is destroyed. + You don't have to manually delete the snapshots in this case. +
+
diff --git a/docs/en-US/work-with-usage.xml b/docs/en-US/work-with-usage.xml index 00a7fb5df81..00172934644 100644 --- a/docs/en-US/work-with-usage.xml +++ b/docs/en-US/work-with-usage.xml @@ -1,5 +1,5 @@ - %BOOK_ENTITIES; ]> @@ -21,16 +21,18 @@ specific language governing permissions and limitations under the License. --> - - Working with Usage - The Usage Server is an optional, separately-installed part of &PRODUCT; that provides aggregated usage records which you can use to create billing integration for &PRODUCT;. The Usage Server works by taking data from the events log and creating summary usage records that you can access using the listUsageRecords API call. - The usage records show the amount of resources, such as VM run time or template storage - space, consumed by guest instances. - The Usage Server runs at least once per day. It can be configured to run multiple times per day. - - - - - + Working with Usage + The Usage Server is an optional, separately-installed part of &PRODUCT; that provides + aggregated usage records which you can use to create billing integration for &PRODUCT;. The + Usage Server works by taking data from the events log and creating summary usage records that + you can access using the listUsageRecords API call. + The usage records show the amount of resources, such as VM run time or template storage + space, consumed by guest instances. + The Usage Server runs at least once per day. It can be configured to run multiple times per + day. + + + + diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java index f619ef4e976..94ae800ab8e 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ObjectInDataStoreStateMachine.java @@ -28,6 +28,7 @@ public interface ObjectInDataStoreStateMachine extends StateObject createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, TemplateInfo template); AsyncCallFuture copyVolume(VolumeInfo srcVolume, DataStore destStore); + AsyncCallFuture migrateVolume(VolumeInfo srcVolume, DataStore destStore); + AsyncCallFuture migrateVolumes(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost); boolean destroyVolume(long volumeId) throws ConcurrentOperationException; diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolDetailsDao.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolDetailsDao.java index be71670e992..237f235704d 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolDetailsDao.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/StoragePoolDetailsDao.java @@ -25,4 +25,5 @@ public interface StoragePoolDetailsDao extends GenericDao details); Map getDetails(long poolId); + StoragePoolDetailVO findDetail(long poolId, String name); } diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManager.java b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManager.java index 82c580fd506..ca0a77742a9 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManager.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManager.java @@ -37,7 +37,7 @@ public interface VMEntityManager { String reserveVirtualMachine(VMEntityVO vmEntityVO, String plannerToUse, DeploymentPlan plan, ExcludeList exclude) throws InsufficientCapacityException, ResourceUnavailableException; - void deployVirtualMachine(String reservationId, String caller, Map params) throws InsufficientCapacityException, ResourceUnavailableException; + void deployVirtualMachine(String reservationId, VMEntityVO vmEntityVO, String caller, Map params) throws InsufficientCapacityException, ResourceUnavailableException; boolean stopvirtualmachine(VMEntityVO vmEntityVO, String caller) throws ResourceUnavailableException; diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java index ec813b2e998..25e742301cf 100755 --- a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VMEntityManagerImpl.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import javax.inject.Inject; @@ -136,6 +137,7 @@ public class VMEntityManagerImpl implements VMEntityManager { plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), planToDeploy.getPoolId(), planToDeploy.getPhysicalNetworkId()); } + boolean planChangedByReadyVolume = false; List vols = _volsDao.findReadyRootVolumesByInstance(vm.getId()); if(!vols.isEmpty()){ VolumeVO vol = vols.get(0); @@ -158,7 +160,7 @@ public class VMEntityManagerImpl implements VMEntityManager { plan = new DataCenterDeployment(planToDeploy.getDataCenterId(), planToDeploy.getPodId(), planToDeploy.getClusterId(), planToDeploy.getHostId(), vol.getPoolId(), null, null); }else{ plan = new DataCenterDeployment(rootVolDcId, rootVolPodId, rootVolClusterId, null, vol.getPoolId(), null, null); - + planChangedByReadyVolume = true; } } @@ -187,6 +189,10 @@ public class VMEntityManagerImpl implements VMEntityManager { _vmEntityDao.persist(vmEntityVO); return vmReservation.getUuid(); + } else if (planChangedByReadyVolume) { + // we could not reserve in the Volume's cluster - let the deploy + // call retry it. + return UUID.randomUUID().toString(); }else{ throw new InsufficientServerCapacityException("Unable to create a deployment for " + vmProfile, DataCenter.class, plan.getDataCenterId()); } @@ -194,31 +200,36 @@ public class VMEntityManagerImpl implements VMEntityManager { } @Override - public void deployVirtualMachine(String reservationId, String caller, Map params) throws InsufficientCapacityException, ResourceUnavailableException{ + public void deployVirtualMachine(String reservationId, VMEntityVO vmEntityVO, String caller, Map params) throws InsufficientCapacityException, ResourceUnavailableException{ //grab the VM Id and destination using the reservationId. + VMInstanceVO vm = _vmDao.findByUuid(vmEntityVO.getUuid()); + VMReservationVO vmReservation = _reservationDao.findByReservationId(reservationId); - long vmId = vmReservation.getVmId(); - - VMInstanceVO vm = _vmDao.findById(vmId); - //Pass it down - Long poolId = null; - Map storage = vmReservation.getVolumeReservation(); - if(storage != null){ - List volIdList = new ArrayList(storage.keySet()); - if(volIdList !=null && !volIdList.isEmpty()){ - poolId = storage.get(volIdList.get(0)); + if(vmReservation != null){ + // Pass it down + Long poolId = null; + Map storage = vmReservation.getVolumeReservation(); + if (storage != null) { + List volIdList = new ArrayList(storage.keySet()); + if (volIdList != null && !volIdList.isEmpty()) { + poolId = storage.get(volIdList.get(0)); + } } - } - DataCenterDeployment reservedPlan = new DataCenterDeployment(vm.getDataCenterId(), vmReservation.getPodId(), vmReservation.getClusterId(), - vmReservation.getHostId(), null , null); - try{ - VMInstanceVO vmDeployed = _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), reservedPlan); - }catch(Exception ex){ - //Retry the deployment without using the reservation plan - DataCenterDeployment plan = new DataCenterDeployment(vm.getDataCenterId(), null, null,null, null , null); - _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), plan); + DataCenterDeployment reservedPlan = new DataCenterDeployment(vm.getDataCenterId(), + vmReservation.getPodId(), vmReservation.getClusterId(), vmReservation.getHostId(), null, null); + try { + VMInstanceVO vmDeployed = _itMgr.start(vm, params, _userDao.findById(new Long(caller)), + _accountDao.findById(vm.getAccountId()), reservedPlan); + } catch (Exception ex) { + // Retry the deployment without using the reservation plan + _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), + null); + } + } else { + // no reservation found. Let VirtualMachineManager retry + _itMgr.start(vm, params, _userDao.findById(new Long(caller)), _accountDao.findById(vm.getAccountId()), null); } } diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VirtualMachineEntityImpl.java b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VirtualMachineEntityImpl.java index c2ca729c909..dd57f9a03f4 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VirtualMachineEntityImpl.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/cloud/entity/api/VirtualMachineEntityImpl.java @@ -206,7 +206,7 @@ public class VirtualMachineEntityImpl implements VirtualMachineEntity { @Override public void deploy(String reservationId, String caller, Map params) throws InsufficientCapacityException, ResourceUnavailableException{ - manager.deployVirtualMachine(reservationId, caller, params); + manager.deployVirtualMachine(reservationId, this.vmEntityVO, caller, params); } @Override diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageServiceImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageServiceImpl.java index 5898b1b0794..99b1013f964 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageServiceImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/ImageServiceImpl.java @@ -21,11 +21,13 @@ package org.apache.cloudstack.storage.image; import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.ImageService; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; @@ -37,6 +39,7 @@ import org.apache.cloudstack.framework.async.AsyncRpcConext; import org.apache.cloudstack.storage.datastore.DataObjectManager; import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; import org.apache.cloudstack.storage.image.store.TemplateObject; +import org.apache.cloudstack.storage.motion.DataMotionService; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -49,6 +52,8 @@ public class ImageServiceImpl implements ImageService { ObjectInDataStoreManager objectInDataStoreMgr; @Inject DataObjectManager dataObjectMgr; + @Inject + DataMotionService motionSrv; class CreateTemplateContext extends AsyncRpcConext { final TemplateInfo srcTemplate; @@ -140,17 +145,91 @@ public class ImageServiceImpl implements ImageService { return null; } + private class CopyTemplateContext extends AsyncRpcConext { + final AsyncCallFuture future; + final DataObject object; + /** + * @param callback + */ + public CopyTemplateContext(AsyncCompletionCallback callback, AsyncCallFuture future, DataObject object) { + super(callback); + this.future = future; + this.object = object; + } + + } @Override public AsyncCallFuture createTemplateFromSnapshotAsync( SnapshotInfo snapshot, TemplateInfo template, DataStore store) { - // TODO Auto-generated method stub + AsyncCallFuture future = new AsyncCallFuture(); + DataObject templateOnStore = null; + try { + templateOnStore = store.create(template); + templateOnStore.processEvent(Event.CreateOnlyRequested); + + CopyTemplateContext context = new CopyTemplateContext(null, future, templateOnStore); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().copyTemplateAsyncCallback(null, null)) + .setContext(context); + this.motionSrv.copyAsync(snapshot, templateOnStore, caller); + } catch (Exception e) { + s_logger.debug("Failed to create template: " + template.getId() + "from snapshot: " + snapshot.getId() + ", due to " + e.toString()); + if (templateOnStore != null) { + try { + templateOnStore.processEvent(Event.OperationFailed); + } catch (Exception e1) { + + } + } + CommandResult result = new CommandResult(); + result.setResult(e.toString()); + future.complete(result); + } + return future; + } + + protected Void copyTemplateAsyncCallback(AsyncCallbackDispatcher callback, CopyTemplateContext context) { + CopyCommandResult result = callback.getResult(); + AsyncCallFuture future = context.future; + DataObject object = context.object; + CommandResult res = new CommandResult(); + if (result.isFailed()) { + res.setResult(result.getResult()); + object.processEvent(Event.OperationFailed); + } else { + object.processEvent(Event.OperationSuccessed); + } + future.complete(res); return null; } @Override public AsyncCallFuture createTemplateFromVolumeAsync( VolumeInfo volume, TemplateInfo template, DataStore store) { - // TODO Auto-generated method stub - return null; + AsyncCallFuture future = new AsyncCallFuture(); + DataObject templateOnStore = null; + try { + templateOnStore = store.create(template); + templateOnStore.processEvent(Event.CreateOnlyRequested); + + CopyTemplateContext context = new CopyTemplateContext(null, future, templateOnStore); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().copyTemplateAsyncCallback(null, null)) + .setContext(context); + this.motionSrv.copyAsync(volume, templateOnStore, caller); + } catch (Exception e) { + s_logger.debug("Failed to create template: " + template.getId() + "from volume: " + volume.getId() + ", due to " + e.toString()); + if (templateOnStore != null) { + try { + templateOnStore.processEvent(Event.OperationFailed); + } catch (Exception e1) { + + } + } + CommandResult result = new CommandResult(); + result.setResult(e.toString()); + future.complete(result); + } + return future; } } diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java index 97ea6c48c79..4c16f2fe4b1 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/driver/AncientImageDataStoreDriverImpl.java @@ -33,6 +33,8 @@ import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncRpcConext; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.image.ImageDataStoreDriver; import org.apache.log4j.Logger; @@ -45,8 +47,8 @@ import com.cloud.agent.api.to.SwiftTO; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.storage.RegisterVolumePayload; -import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.SnapshotVO; +import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateZoneVO; @@ -80,6 +82,7 @@ public class AncientImageDataStoreDriverImpl implements ImageDataStoreDriver { @Inject SnapshotDao snapshotDao; @Inject AgentManager agentMgr; @Inject SnapshotManager snapshotMgr; + @Inject PrimaryDataStoreDao primaryDataStoreDao; @Inject private SwiftManager _swiftMgr; @Inject @@ -196,9 +199,10 @@ public class AncientImageDataStoreDriverImpl implements ImageDataStoreDriver { } SwiftTO swift = _swiftMgr.getSwiftTO(snapshot.getSwiftId()); S3TO s3 = _s3Mgr.getS3TO(); - + VolumeVO volume = volumeDao.findById(volumeId); + StoragePoolVO pool = primaryDataStoreDao.findById(volume.getPoolId()); DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand( - swift, s3, secondaryStoragePoolUrl, dcId, accountId, volumeId, + pool, swift, s3, secondaryStoragePoolUrl, dcId, accountId, volumeId, backupOfSnapshot, false); Answer answer = agentMgr.sendToSSVM(dcId, cmd); diff --git a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java b/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java index a70fd8ab227..1c21496871f 100644 --- a/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java +++ b/engine/storage/imagemotion/src/org/apache/cloudstack/storage/image/motion/DefaultImageMotionStrategy.java @@ -18,12 +18,15 @@ */ package org.apache.cloudstack.storage.image.motion; +import java.util.Map; + import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncRpcConext; @@ -33,6 +36,8 @@ import org.apache.cloudstack.storage.endpoint.EndPointSelector; import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreInfo; import com.cloud.agent.api.Answer; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.host.Host; //At least one of datastore is coming from image store or image cache store @@ -95,6 +100,11 @@ public class DefaultImageMotionStrategy implements ImageMotionStrategy { return false; } + @Override + public boolean canHandle(Map volumeMap, Host srcHost, Host destHost) { + return false; + } + @Override public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback) { @@ -137,4 +147,12 @@ public class DefaultImageMotionStrategy implements ImageMotionStrategy { } + @Override + public Void copyAsync(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, + AsyncCompletionCallback callback) { + CopyCommandResult result = new CopyCommandResult("", null); + result.setResult("not implemented"); + callback.complete(result); + return null; + } } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java index b619ee9240f..a84f3087d59 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockStorageMotionStrategy.java @@ -18,11 +18,18 @@ */ package org.apache.cloudstack.storage.test; +import java.util.Map; + import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.storage.motion.DataMotionStrategy; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.host.Host; + public class MockStorageMotionStrategy implements DataMotionStrategy { @Override @@ -31,6 +38,11 @@ public class MockStorageMotionStrategy implements DataMotionStrategy { return true; } + @Override + public boolean canHandle(Map volumeMap, Host srcHost, Host destHost) { + return true; + } + @Override public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback) { @@ -39,4 +51,11 @@ public class MockStorageMotionStrategy implements DataMotionStrategy { return null; } + @Override + public Void copyAsync(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, + AsyncCompletionCallback callback) { + CopyCommandResult result = new CopyCommandResult("something", null); + callback.complete(result); + return null; + } } diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java index d10dc778092..37238b72121 100644 --- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java +++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java @@ -106,7 +106,7 @@ public class SnapshotObject implements SnapshotInfo { @Override public Long getSize() { - return this.getSize(); + return this.snapshot.getSize(); } @Override diff --git a/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java b/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java index 3602bb16baf..a6880c3f548 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java +++ b/engine/storage/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java @@ -20,12 +20,14 @@ package org.apache.cloudstack.storage.motion; import java.util.Date; import java.util.List; +import java.util.Map; import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; @@ -36,6 +38,7 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.BackupSnapshotAnswer; import com.cloud.agent.api.BackupSnapshotCommand; @@ -47,15 +50,21 @@ import com.cloud.agent.api.CreateVolumeFromSnapshotCommand; import com.cloud.agent.api.UpgradeSnapshotCommand; import com.cloud.agent.api.storage.CopyVolumeAnswer; import com.cloud.agent.api.storage.CopyVolumeCommand; +import com.cloud.agent.api.storage.MigrateVolumeAnswer; +import com.cloud.agent.api.storage.MigrateVolumeCommand; import com.cloud.agent.api.storage.CreateAnswer; import com.cloud.agent.api.storage.CreateCommand; import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer; import com.cloud.agent.api.to.S3TO; import com.cloud.agent.api.to.StorageFilerTO; import com.cloud.agent.api.to.SwiftTO; +import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.OperationTimedoutException; import com.cloud.exception.StorageUnavailableException; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.storage.DiskOfferingVO; @@ -86,6 +95,8 @@ import com.cloud.utils.db.DB; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.DiskProfile; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.dao.VMInstanceDao; @Component public class AncientDataMotionStrategy implements DataMotionStrategy { @@ -102,8 +113,12 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { @Inject StorageManager storageMgr; @Inject + AgentManager agentMgr; + @Inject VolumeDao volDao; @Inject + VMInstanceDao instanceDao; + @Inject VMTemplateDao templateDao; @Inject SnapshotManager snapshotMgr; @@ -130,6 +145,11 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { return true; } + @Override + public boolean canHandle(Map volumeMap, Host srcHost, Host destHost) { + return false; + } + @DB protected Answer copyVolumeFromImage(DataObject srcData, DataObject destData) { String value = configDao.getValue(Config.RecreateSystemVmEnabled.key()); @@ -393,6 +413,53 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { return cvAnswer; } + protected Answer migrateVolumeToPool(DataObject srcData, DataStore destStore) { + VolumeInfo volume = (VolumeInfo)srcData; + Long instanceId = volume.getInstanceId(); + StoragePool destPool = (StoragePool)this.dataStoreMgr.getDataStore(destStore.getId(), DataStoreRole.Primary); + MigrateVolumeAnswer answer = null; + VMInstanceVO vmInstance = null; + if (instanceId != null) { + vmInstance = instanceDao.findById(instanceId); + } + + Long hostId = null; + if (vmInstance != null) { + hostId = vmInstance.getHostId(); + } + + try { + if (hostId != null) { + MigrateVolumeCommand command = new MigrateVolumeCommand(volume.getId(), volume.getPath(), destPool); + answer = (MigrateVolumeAnswer) this.agentMgr.send(hostId, command); + } + } catch (OperationTimedoutException e) { + s_logger.error("Operation timed out on storage motion for volume " + volume, e); + throw new CloudRuntimeException("Failed to live migrate volume " + volume + " to storage pool " + + destPool, e); + } catch (AgentUnavailableException e) { + s_logger.error("Agent unavailable exception while doing storage motion for volume " + volume, e); + throw new CloudRuntimeException("Failed to live migrate volume " + volume + " to storage pool " + + destPool, e); + } + + if (answer == null || !answer.getResult()) { + throw new CloudRuntimeException("Failed to migrate volume " + volume + " to storage pool " + destPool); + } else { + // Update the volume details after migration. + VolumeVO volumeVo = this.volDao.findById(volume.getId()); + Long oldPoolId = volume.getPoolId(); + volumeVo.setPath(answer.getVolumePath()); + volumeVo.setFolder(destPool.getPath()); + volumeVo.setPodId(destPool.getPodId()); + volumeVo.setPoolId(destPool.getId()); + volumeVo.setLastPoolId(oldPoolId); + this.volDao.update(volume.getId(), volumeVo); + } + + return answer; + } + @Override public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback) { @@ -419,7 +486,12 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { answer = cloneVolume(srcData, destData); } else if (destData.getType() == DataObjectType.VOLUME && srcData.getType() == DataObjectType.VOLUME && srcData.getDataStore().getRole() == DataStoreRole.Primary) { - answer = copyVolumeBetweenPools(srcData, destData); + if (srcData.getId() == destData.getId()) { + // The volume has to be migrated across storage pools. + answer = migrateVolumeToPool(srcData, destData.getDataStore()); + } else { + answer = copyVolumeBetweenPools(srcData, destData); + } } else if (srcData.getType() == DataObjectType.SNAPSHOT && destData.getType() == DataObjectType.SNAPSHOT) { answer = copySnapshot(srcData, destData); @@ -435,6 +507,16 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { return null; } + @Override + public Void copyAsync(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, + AsyncCompletionCallback callback) { + CopyCommandResult result = new CopyCommandResult(null, null); + result.setResult("Unsupported operation requested for copying data."); + callback.complete(result); + + return null; + } + @DB protected Answer createTemplateFromSnashot(DataObject srcData, DataObject destData) { @@ -586,9 +668,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { String checkSum = this.templateMgr .getChecksum(hostId, answer.getPath()); - Transaction txn = Transaction.currentTxn(); - txn.start(); privateTemplate.setChecksum(checkSum); templateDao.update(privateTemplate.getId(), privateTemplate); @@ -603,8 +683,9 @@ public class AncientDataMotionStrategy implements DataMotionStrategy { templateHostVO.setLastUpdated(new Date()); templateHostVO.setSize(answer.getVirtualSize()); templateHostVO.setPhysicalSize(answer.getphysicalSize()); + templateHostDao.persist(templateHostVO); - txn.close(); + return answer; } diff --git a/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionService.java b/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionService.java index db36f6492e8..5ecbcb37afb 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionService.java +++ b/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionService.java @@ -18,11 +18,20 @@ */ package org.apache.cloudstack.storage.motion; +import java.util.Map; + import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.host.Host; + public interface DataMotionService { public void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback); + public void copyAsync(Map volumeMap, VirtualMachineTO vmTo, + Host srcHost, Host destHost, AsyncCompletionCallback callback); } diff --git a/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java b/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java index 343140fb98e..b74e10c460f 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionServiceImpl.java @@ -19,14 +19,19 @@ package org.apache.cloudstack.storage.motion; import java.util.List; +import java.util.Map; import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.springframework.stereotype.Component; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.host.Host; import com.cloud.utils.exception.CloudRuntimeException; @Component @@ -58,4 +63,15 @@ public class DataMotionServiceImpl implements DataMotionService { throw new CloudRuntimeException("can't find strategy to move data"); } + @Override + public void copyAsync(Map volumeMap, VirtualMachineTO vmTo, + Host srcHost, Host destHost, AsyncCompletionCallback callback) { + for (DataMotionStrategy strategy : strategies) { + if (strategy.canHandle(volumeMap, srcHost, destHost)) { + strategy.copyAsync(volumeMap, vmTo, srcHost, destHost, callback); + return; + } + } + throw new CloudRuntimeException("can't find strategy to move data"); + } } diff --git a/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionStrategy.java b/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionStrategy.java index ba40c6dcbce..e3859b4e131 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionStrategy.java +++ b/engine/storage/src/org/apache/cloudstack/storage/motion/DataMotionStrategy.java @@ -18,13 +18,23 @@ */ package org.apache.cloudstack.storage.motion; +import java.util.Map; + import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.host.Host; + public interface DataMotionStrategy { public boolean canHandle(DataObject srcData, DataObject destData); + public boolean canHandle(Map volumeMap, Host srcHost, Host destHost); public Void copyAsync(DataObject srcData, DataObject destData, AsyncCompletionCallback callback); + public Void copyAsync(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, + AsyncCompletionCallback callback); } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java index ceadb253976..ea31be3d6a0 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java @@ -176,6 +176,8 @@ public class VolumeObject implements VolumeInfo { volEvent = Volume.Event.CreateRequested; } else if (event == ObjectInDataStoreStateMachine.Event.CopyingRequested) { volEvent = Volume.Event.CopyRequested; + } else if (event == ObjectInDataStoreStateMachine.Event.MigrationRequested) { + volEvent = Volume.Event.MigrationRequested; } } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index 32e7d274f01..b39502b1924 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -18,6 +18,10 @@ */ package org.apache.cloudstack.storage.volume; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; + import javax.inject.Inject; import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity; @@ -27,6 +31,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult; import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; @@ -40,11 +45,14 @@ import org.apache.cloudstack.storage.datastore.DataObjectManager; import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; import org.apache.cloudstack.storage.datastore.PrimaryDataStore; import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.motion.DataMotionService; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.exception.ConcurrentOperationException; +import com.cloud.host.Host; import com.cloud.storage.StoragePool; import com.cloud.storage.Volume; import com.cloud.storage.Volume.Type; @@ -513,8 +521,8 @@ public class VolumeServiceImpl implements VolumeService { VolumeVO destVol = duplicateVolumeOnAnotherStorage(srcVolume, (StoragePool)destStore); VolumeInfo destVolume = this.volFactory.getVolume(destVol.getId(), destStore); - destVolume.processEvent(Event.CreateOnlyRequested); - srcVolume.processEvent(Event.CopyingRequested); + destVolume.processEvent(Event.MigrationRequested); + srcVolume.processEvent(Event.MigrationRequested); CopyVolumeContext context = new CopyVolumeContext(null, future, srcVolume, destVolume, @@ -542,6 +550,8 @@ public class VolumeServiceImpl implements VolumeService { res.setResult(result.getResult()); destVolume.processEvent(Event.OperationFailed); srcVolume.processEvent(Event.OperationFailed); + destroyVolume(destVolume.getId()); + destVolume = this.volFactory.getVolume(destVolume.getId()); AsyncCallFuture destroyFuture = this.expungeVolumeAsync(destVolume); destroyFuture.get(); future.complete(res); @@ -549,6 +559,8 @@ public class VolumeServiceImpl implements VolumeService { } srcVolume.processEvent(Event.OperationSuccessed); destVolume.processEvent(Event.OperationSuccessed); + destroyVolume(srcVolume.getId()); + srcVolume = this.volFactory.getVolume(srcVolume.getId()); AsyncCallFuture destroyFuture = this.expungeVolumeAsync(srcVolume); destroyFuture.get(); future.complete(res); @@ -561,7 +573,163 @@ public class VolumeServiceImpl implements VolumeService { return null; } - + + private class MigrateVolumeContext extends AsyncRpcConext { + final VolumeInfo srcVolume; + final VolumeInfo destVolume; + final DataStore destStore; + final AsyncCallFuture future; + /** + * @param callback + */ + public MigrateVolumeContext(AsyncCompletionCallback callback, AsyncCallFuture future, + VolumeInfo srcVolume, VolumeInfo destVolume, DataStore destStore) { + super(callback); + this.srcVolume = srcVolume; + this.destVolume = destVolume; + this.destStore = destStore; + this.future = future; + } + } + + @Override + public AsyncCallFuture migrateVolume(VolumeInfo srcVolume, DataStore destStore) { + AsyncCallFuture future = new AsyncCallFuture(); + VolumeApiResult res = new VolumeApiResult(srcVolume); + try { + if (!this.snapshotMgr.canOperateOnVolume(srcVolume)) { + s_logger.debug("Snapshots are being created on this volume. This volume cannot be migrated now."); + res.setResult("Snapshots are being created on this volume. This volume cannot be migrated now."); + future.complete(res); + return future; + } + + VolumeInfo destVolume = this.volFactory.getVolume(srcVolume.getId(), destStore); + srcVolume.processEvent(Event.MigrationRequested); + MigrateVolumeContext context = new MigrateVolumeContext(null, future, + srcVolume, destVolume, destStore); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().migrateVolumeCallBack(null, null)).setContext(context); + this.motionSrv.copyAsync(srcVolume, destVolume, caller); + } catch (Exception e) { + s_logger.debug("Failed to copy volume", e); + res.setResult(e.toString()); + future.complete(res); + } + return future; + } + + protected Void migrateVolumeCallBack(AsyncCallbackDispatcher callback, + MigrateVolumeContext context) { + VolumeInfo srcVolume = context.srcVolume; + VolumeInfo destVolume = context.destVolume; + CopyCommandResult result = callback.getResult(); + AsyncCallFuture future = context.future; + VolumeApiResult res = new VolumeApiResult(srcVolume); + try { + if (result.isFailed()) { + res.setResult(result.getResult()); + srcVolume.processEvent(Event.OperationFailed); + future.complete(res); + } else { + srcVolume.processEvent(Event.OperationSuccessed); + future.complete(res); + } + } catch (Exception e) { + s_logger.error("Failed to process copy volume callback", e); + res.setResult(e.toString()); + future.complete(res); + } + + return null; + } + + private class MigrateVmWithVolumesContext extends AsyncRpcConext { + final Map volumeToPool; + final AsyncCallFuture future; + /** + * @param callback + */ + public MigrateVmWithVolumesContext(AsyncCompletionCallback callback, AsyncCallFuture future, + Map volumeToPool) { + super(callback); + this.volumeToPool = volumeToPool; + this.future = future; + } + } + + @Override + public AsyncCallFuture migrateVolumes(Map volumeMap, VirtualMachineTO vmTo, + Host srcHost, Host destHost) { + AsyncCallFuture future = new AsyncCallFuture(); + CommandResult res = new CommandResult(); + try { + // Check to make sure there are no snapshot operations on a volume and + // put it in the migrating state. + List volumesMigrating = new ArrayList(); + for (Map.Entry entry : volumeMap.entrySet()) { + VolumeInfo volume = entry.getKey(); + if (!this.snapshotMgr.canOperateOnVolume(volume)) { + s_logger.debug("Snapshots are being created on a volume. Volumes cannot be migrated now."); + res.setResult("Snapshots are being created on a volume. Volumes cannot be migrated now."); + future.complete(res); + + // All the volumes that are already in migrating state need to be put back in ready state. + for (VolumeInfo volumeMigrating : volumesMigrating) { + volumeMigrating.processEvent(Event.OperationFailed); + } + return future; + } else { + volume.processEvent(Event.MigrationRequested); + volumesMigrating.add(volume); + } + } + + MigrateVmWithVolumesContext context = new MigrateVmWithVolumesContext(null, + future, volumeMap); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().migrateVmWithVolumesCallBack(null, null)).setContext(context); + this.motionSrv.copyAsync(volumeMap, vmTo, srcHost, destHost, caller); + + } catch (Exception e) { + s_logger.debug("Failed to copy volume", e); + res.setResult(e.toString()); + future.complete(res); + } + + return future; + } + + protected Void migrateVmWithVolumesCallBack(AsyncCallbackDispatcher callback, + MigrateVmWithVolumesContext context) { + Map volumeToPool = context.volumeToPool; + CopyCommandResult result = callback.getResult(); + AsyncCallFuture future = context.future; + CommandResult res = new CommandResult(); + try { + if (result.isFailed()) { + res.setResult(result.getResult()); + for (Map.Entry entry : volumeToPool.entrySet()) { + VolumeInfo volume = entry.getKey(); + volume.processEvent(Event.OperationFailed); + } + future.complete(res); + } else { + for (Map.Entry entry : volumeToPool.entrySet()) { + VolumeInfo volume = entry.getKey(); + volume.processEvent(Event.OperationSuccessed); + } + future.complete(res); + } + } catch (Exception e) { + s_logger.error("Failed to process copy volume callback", e); + res.setResult(e.toString()); + future.complete(res); + } + + return null; + } + @Override public AsyncCallFuture registerVolume(VolumeInfo volume, DataStore store) { diff --git a/packaging/centos63/cloud-usage.rc b/packaging/centos63/cloud-usage.rc index 76f0e06fdfe..a9b60478875 100755 --- a/packaging/centos63/cloud-usage.rc +++ b/packaging/centos63/cloud-usage.rc @@ -58,7 +58,7 @@ export JAVA_HOME SCP="" DCP="" -UCP=`ls /usr/share/cloudstack-usage/cloud-usage-*.jar`":"`ls /usr/share/cloudstack-usage/lib/* | tr '\n' ':'` +UCP=`ls /usr/share/cloudstack-usage/cloud-usage-*.jar`":"`ls /usr/share/cloudstack-usage/lib/*.jar | tr '\n' ':'` JCP="/usr/share/java/commons-daemon.jar" # We need to append the JSVC daemon JAR to the classpath diff --git a/packaging/centos63/cloud.spec b/packaging/centos63/cloud.spec index c2c6fe734cd..a7cc20e8ab8 100644 --- a/packaging/centos63/cloud.spec +++ b/packaging/centos63/cloud.spec @@ -447,13 +447,6 @@ if [ -f "%{_sysconfdir}/%{name}/management/db.properties" ]; then ln -s %{_sysconfdir}/%{name}/management/db.properties %{_sysconfdir}/%{name}/usage/db.properties fi -if [ -f "%{_sysconfdir}/%{name}/management/log4j-cloud.xml" ]; then - echo Replacing log4j-cloud.xml with management server log4j-cloud.xml - rm -f %{_sysconfdir}/%{name}/usage/log4j-cloud.xml - ln -s %{_sysconfdir}/%{name}/management/log4j-cloud.xml %{_sysconfdir}/%{name}/usage/log4j-cloud.xml -fi - - #%post awsapi #if [ -d "%{_datadir}/%{name}-management" ] ; then # ln -s %{_datadir}/%{name}-bridge/webapps %{_datadir}/%{name}-management/webapps7080 @@ -548,7 +541,7 @@ fi %attr(0755,root,root) %{_sysconfdir}/init.d/%{name}-usage %attr(0644,root,root) %{_datadir}/%{name}-usage/*.jar %attr(0644,root,root) %{_datadir}/%{name}-usage/lib/*.jar -%dir /var/log/%{name}/usage +%dir %attr(0770,root,cloud) %{_localstatedir}/log/%{name}/usage %attr(0644,root,root) %{_sysconfdir}/%{name}/usage/db.properties %attr(0644,root,root) %{_sysconfdir}/%{name}/usage/log4j-cloud.xml %{_defaultdocdir}/%{name}-usage-%{version}/LICENSE diff --git a/packaging/centos63/replace.properties b/packaging/centos63/replace.properties index 211cc95449f..83458549570 100644 --- a/packaging/centos63/replace.properties +++ b/packaging/centos63/replace.properties @@ -56,5 +56,5 @@ SYSCONFDIR=/etc/sysconfig SYSTEMCLASSPATH= SYSTEMJARS= USAGECLASSPATH= -USAGELOG=/var/log/cloudstack/usage +USAGELOG=/var/log/cloudstack/usage/usage.log USAGESYSCONFDIR=/etc/sysconfig diff --git a/packaging/debian/init/cloud-management b/packaging/debian/init/cloud-management index 1e008312e09..8431eec8811 100755 --- a/packaging/debian/init/cloud-management +++ b/packaging/debian/init/cloud-management @@ -125,7 +125,7 @@ fi # Define other required variables CATALINA_PID="/var/run/$NAME.pid" BOOTSTRAP_CLASS=org.apache.catalina.startup.Bootstrap -JSVC_CLASSPATH="/usr/share/java/commons-daemon.jar:$CATALINA_HOME/bin/bootstrap.jar:/etc/cloudstack/management" +JSVC_CLASSPATH="/usr/share/java/commons-daemon.jar:$CATALINA_HOME/bin/bootstrap.jar:/etc/cloudstack/management:/usr/share/cloudstack-management/setup" # Look for Java Secure Sockets Extension (JSSE) JARs if [ -z "${JSSE_HOME}" -a -r "${JAVA_HOME}/jre/lib/jsse.jar" ]; then diff --git a/packaging/debian/replace.properties b/packaging/debian/replace.properties index 8c852060c02..5a0bd58ab67 100644 --- a/packaging/debian/replace.properties +++ b/packaging/debian/replace.properties @@ -57,6 +57,6 @@ SYSCONFDIR=/etc SYSTEMCLASSPATH= SYSTEMJARS= USAGECLASSPATH= -USAGELOG=/var/log/cloudstack/usage +USAGELOG=/var/log/cloudstack/usage/usage.log USAGESYSCONFDIR=/etc/cloudstack/usage PACKAGE=cloudstack 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 3faa1bd0f2e..b8ddaf1bcc3 100755 --- a/patches/systemvm/debian/config/etc/init.d/cloud-early-config +++ b/patches/systemvm/debian/config/etc/init.d/cloud-early-config @@ -27,6 +27,8 @@ # under the License. PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin" +#set -x +#exec 3>&0 4>&1 > /var/log/test.log 2>&1 # Fix haproxy directory issue mkdir -p /var/lib/haproxy @@ -227,7 +229,29 @@ setup_interface() { ifdown $intf if [ "$RROUTER" != "1" -o "$1" != "2" ] then - ifup $intf + ifup $intf + timer=0 + log_it "checking that $intf has IP " + while true + do + ip=$(ifconfig $intf | grep "inet addr:" | awk '{print $2}' | awk -F: '{print $2}') + if [ -z $ip ] + then + sleep 1; + #waiting for the interface to setup with ip + log_it "waiting for $intf interface setup with ip timer=$timer" + else + break + fi + + if [ $timer -gt 15 ] + then + log_it "interface $intf is not set up with ip... exiting"; + break + fi + + timer=`expr $timer + 1` + done fi fi } @@ -392,33 +416,8 @@ setup_common() { gwdev="eth0" fi - timer=0 - #default route add fails if we run before interface configured with ip - log_it "checking that $gwdev has IP before setting default route to $GW" - echo "checking that $gwdev has IP before setting default route to $GW" - while true - do - ip=$(ifconfig $gwdev | grep "inet addr:" | awk '{print $2}' | awk -F: '{print $2}') - if [ -z $ip ] - then - sleep 1; - #waiting for the interface to setup with ip - log_it "waiting for $gwdev interface setup with ip" - echo "waiting for $gwdev interface setup with ip" - else - ip route add default via $GW dev $gwdev - break - fi + ip route add default via $GW dev $gwdev - if [ $timer -gt 15 ] - then - log_it "interface $gwdev is not set up with ip... configuring default route failed"; - echo "interface $gwdev is not set up with ip... configuring default route failed" - break - fi - timer=`expr $timer + 1` - done - fi # a hacking way to activate vSwitch under VMware diff --git a/plugins/host-allocators/random/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java b/plugins/host-allocators/random/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java index a672efdc77e..8243f3a46ad 100755 --- a/plugins/host-allocators/random/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java +++ b/plugins/host-allocators/random/src/com/cloud/agent/manager/allocator/impl/RandomAllocator.java @@ -53,6 +53,62 @@ public class RandomAllocator extends AdapterBase implements HostAllocator { return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true); } + @Override + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, + ExcludeList avoid, List hosts, int returnUpTo, boolean considerReservedCapacity) { + long dcId = plan.getDataCenterId(); + Long podId = plan.getPodId(); + Long clusterId = plan.getClusterId(); + ServiceOffering offering = vmProfile.getServiceOffering(); + List suitableHosts = new ArrayList(); + + if (type == Host.Type.Storage) { + return suitableHosts; + } + + String hostTag = offering.getHostTag(); + if(hostTag != null){ + s_logger.debug("Looking for hosts in dc: " + dcId + " pod:" + podId + " cluster:" + clusterId + + " having host tag:" + hostTag); + }else{ + s_logger.debug("Looking for hosts in dc: " + dcId + " pod:" + podId + " cluster:" + clusterId); + } + + // list all computing hosts, regardless of whether they support routing...it's random after all + if(hostTag != null){ + hosts.retainAll(_hostDao.listByHostTag(type, clusterId, podId, dcId, hostTag)); + }else{ + hosts.retainAll(_resourceMgr.listAllUpAndEnabledHosts(type, clusterId, podId, dcId)); + } + + s_logger.debug("Random Allocator found " + hosts.size() + " hosts"); + if (hosts.size() == 0) { + return suitableHosts; + } + + Collections.shuffle(hosts); + for (Host host : hosts) { + if(suitableHosts.size() == returnUpTo){ + break; + } + + if (!avoid.shouldAvoid(host)) { + suitableHosts.add(host); + } else { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Host name: " + host.getName() + ", hostId: "+ host.getId() +" is in avoid set, " + + "skipping this and trying other available hosts"); + } + } + } + + if (s_logger.isDebugEnabled()) { + s_logger.debug("Random Host Allocator returning "+suitableHosts.size() +" suitable hosts"); + } + + return suitableHosts; + } + @Override public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity) { diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java index c4e121b8ae8..d1470d62519 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/KVMHAMonitor.java @@ -23,6 +23,15 @@ import java.util.concurrent.ConcurrentHashMap; import org.apache.log4j.Logger; import com.cloud.utils.script.Script; +import org.libvirt.Connect; +import org.libvirt.LibvirtException; +import org.libvirt.Secret; +import org.libvirt.StoragePool; +import org.libvirt.StoragePoolInfo; +import org.libvirt.StoragePoolInfo.StoragePoolState; + +import com.cloud.hypervisor.kvm.resource.LibvirtConnection; + public class KVMHAMonitor extends KVMHABase implements Runnable { private static final Logger s_logger = Logger.getLogger(KVMHAMonitor.class); private Map _storagePool = new ConcurrentHashMap(); @@ -45,6 +54,9 @@ public class KVMHAMonitor extends KVMHABase implements Runnable { public void removeStoragePool(String uuid) { synchronized (_storagePool) { + NfsStoragePool pool = this._storagePool.get(uuid); + Script.runSimpleBashScript("umount " + pool._mountDestPath); + s_logger.debug("attempted to umount '" + pool._mountDestPath + "'"); this._storagePool.remove(uuid); } } @@ -60,7 +72,44 @@ public class KVMHAMonitor extends KVMHABase implements Runnable { @Override public void run() { synchronized (_storagePool) { - for (NfsStoragePool primaryStoragePool : _storagePool.values()) { + for (String uuid : _storagePool.keySet()) { + NfsStoragePool primaryStoragePool = _storagePool.get(uuid); + + // check for any that have been deregistered with libvirt and + // skip,remove them + + StoragePool storage = null; + try { + Connect conn = LibvirtConnection.getConnection(); + storage = conn.storagePoolLookupByUUIDString(uuid); + if (storage == null) { + s_logger.debug("Libvirt storage pool " + uuid + +" not found, removing from HA list"); + removeStoragePool(uuid); + continue; + + } else if (storage.getInfo().state != StoragePoolState.VIR_STORAGE_POOL_RUNNING) { + s_logger.debug("Libvirt storage pool " + uuid + +" found, but not running, removing from HA list"); + + removeStoragePool(uuid); + continue; + } + s_logger.debug("Found NFS storage pool " + uuid + " in libvirt, continuing"); + + } catch (LibvirtException e) { + s_logger.debug("Failed to lookup libvirt storage pool " + uuid + + " due to: " + e ); + + // we only want to remove pool if it's not found, not if libvirt + // connection fails + if (e.toString().contains("pool not found")) { + s_logger.debug("removing pool from HA monitor since it was deleted"); + removeStoragePool(uuid); + continue; + } + } + String result = null; for (int i = 0; i < 5; i++) { Script cmd = new Script(_heartBeatPath, 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 362e0a53e53..0064edf6a68 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 @@ -1077,8 +1077,7 @@ ServerResource { */ conn.domainCreateXML(domainXML, 0); } catch (final LibvirtException e) { - s_logger.warn("Failed to start domain " + vmName + ": " - + e.getMessage(), e); + throw e; } return null; } @@ -1270,7 +1269,7 @@ ServerResource { secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI( secondaryStorageUrl); secondaryStoragePool.createFolder(volumeDestPath); - secondaryStoragePool.delete(); + _storagePoolMgr.deleteStoragePool(secondaryStoragePool.getType(),secondaryStoragePool.getUuid()); secondaryStoragePool = _storagePoolMgr.getStoragePoolByURI( secondaryStorageUrl + volumeDestPath); @@ -1292,7 +1291,7 @@ ServerResource { return new CopyVolumeAnswer(cmd, false, e.toString(), null, null); } finally { if (secondaryStoragePool != null) { - secondaryStoragePool.delete(); + _storagePoolMgr.deleteStoragePool(secondaryStoragePool.getType(),secondaryStoragePool.getUuid()); } } } @@ -1415,7 +1414,7 @@ ServerResource { return null; } finally { if (secondaryPool != null) { - secondaryPool.delete(); + _storagePoolMgr.deleteStoragePool(secondaryPool.getType(),secondaryPool.getUuid()); } } } @@ -2008,7 +2007,7 @@ ServerResource { true); } finally { if (secondaryStoragePool != null) { - secondaryStoragePool.delete(); + _storagePoolMgr.deleteStoragePool(secondaryStoragePool.getType(),secondaryStoragePool.getUuid()); } } return new BackupSnapshotAnswer(cmd, true, null, snapshotRelPath @@ -2040,7 +2039,7 @@ ServerResource { return new DeleteSnapshotBackupAnswer(cmd, false, e.toString()); } finally { if (secondaryStoragePool != null) { - secondaryStoragePool.delete(); + _storagePoolMgr.deleteStoragePool(secondaryStoragePool.getType(),secondaryStoragePool.getUuid()); } } return new DeleteSnapshotBackupAnswer(cmd, true, null); @@ -2069,7 +2068,7 @@ ServerResource { return new Answer(cmd, false, e.toString()); } finally { if (secondaryStoragePool != null) { - secondaryStoragePool.delete(); + _storagePoolMgr.deleteStoragePool(secondaryStoragePool.getType(),secondaryStoragePool.getUuid()); } } @@ -2167,10 +2166,10 @@ ServerResource { return new CreatePrivateTemplateAnswer(cmd, false, e.getMessage()); } finally { if (secondaryPool != null) { - secondaryPool.delete(); + _storagePoolMgr.deleteStoragePool(secondaryPool.getType(), secondaryPool.getUuid()); } if (snapshotPool != null) { - snapshotPool.delete(); + _storagePoolMgr.deleteStoragePool(snapshotPool.getType(), snapshotPool.getUuid()); } } } @@ -2304,7 +2303,7 @@ ServerResource { return new CreatePrivateTemplateAnswer(cmd, false, e.toString()); } finally { if (secondaryStorage != null) { - secondaryStorage.delete(); + _storagePoolMgr.deleteStoragePool(secondaryStorage.getType(), secondaryStorage.getUuid()); } } } @@ -2362,7 +2361,7 @@ ServerResource { return new PrimaryStorageDownloadAnswer(e.toString()); } finally { if (secondaryPool != null) { - secondaryPool.delete(); + _storagePoolMgr.deleteStoragePool(secondaryPool.getType(),secondaryPool.getUuid()); } } } @@ -3454,7 +3453,7 @@ ServerResource { KVMStoragePool pool = _storagePoolMgr.getStoragePool( StoragePoolType.Filesystem, poolUuid); if (pool != null) { - pool.delete(); + _storagePoolMgr.deleteStoragePool(pool.getType(),pool.getUuid()); } return true; } catch (CloudRuntimeException e) { diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 4ef583a5463..46ae35a4a54 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -3358,7 +3358,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe vm.setMemoryLimits(conn, maxMemsize, maxMemsize, minMemsize, maxMemsize); } - private void waitForTask(Connection c, Task task, long pollInterval, long timeout) throws XenAPIException, XmlRpcException { + protected void waitForTask(Connection c, Task task, long pollInterval, long timeout) throws XenAPIException, XmlRpcException { long beginTime = System.currentTimeMillis(); while (task.getStatus(c) == Types.TaskStatusType.PENDING) { try { @@ -3374,7 +3374,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - private void checkForSuccess(Connection c, Task task) throws XenAPIException, XmlRpcException { + protected void checkForSuccess(Connection c, Task task) throws XenAPIException, XmlRpcException { if (task.getStatus(c) == Types.TaskStatusType.SUCCESS) { return; } else { 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 d64e17337a1..96a90a61fff 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 @@ -132,6 +132,7 @@ public class XenServer56FP1Resource extends XenServer56Resource { record.affinity = host; record.otherConfig.remove("disks"); record.otherConfig.remove("default_template"); + record.otherConfig.remove("mac_seed"); record.isATemplate = false; record.nameLabel = vmSpec.getName(); record.actionsAfterCrash = Types.OnCrashBehaviour.DESTROY; diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer610Resource.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer610Resource.java index 8d267b114fa..bb31136f38e 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer610Resource.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServer610Resource.java @@ -20,6 +20,9 @@ package com.cloud.hypervisor.xen.resource; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; import javax.ejb.Local; @@ -28,7 +31,34 @@ import org.apache.log4j.Logger; import com.cloud.resource.ServerResource; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; - +import com.cloud.vm.VirtualMachine.State; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.storage.MigrateVolumeAnswer; +import com.cloud.agent.api.storage.MigrateVolumeCommand; +import com.cloud.agent.api.MigrateWithStorageAnswer; +import com.cloud.agent.api.MigrateWithStorageCommand; +import com.cloud.agent.api.MigrateWithStorageReceiveAnswer; +import com.cloud.agent.api.MigrateWithStorageReceiveCommand; +import com.cloud.agent.api.MigrateWithStorageSendAnswer; +import com.cloud.agent.api.MigrateWithStorageSendCommand; +import com.cloud.agent.api.MigrateWithStorageCompleteAnswer; +import com.cloud.agent.api.MigrateWithStorageCompleteCommand; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.network.Networks.TrafficType; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.agent.api.to.NicTO; +import com.xensource.xenapi.Connection; +import com.xensource.xenapi.Host; +import com.xensource.xenapi.Network; +import com.xensource.xenapi.SR; +import com.xensource.xenapi.Task; +import com.xensource.xenapi.Types; +import com.xensource.xenapi.VBD; +import com.xensource.xenapi.VDI; +import com.xensource.xenapi.VIF; +import com.xensource.xenapi.VM; @Local(value=ServerResource.class) public class XenServer610Resource extends XenServer56FP1Resource { @@ -55,4 +85,331 @@ public class XenServer610Resource extends XenServer56FP1Resource { files.add(file); return files; } + + @Override + public Answer executeRequest(Command cmd) { + if (cmd instanceof MigrateWithStorageCommand) { + return execute((MigrateWithStorageCommand) cmd); + } else if (cmd instanceof MigrateWithStorageReceiveCommand) { + return execute((MigrateWithStorageReceiveCommand) cmd); + } else if (cmd instanceof MigrateWithStorageSendCommand) { + return execute((MigrateWithStorageSendCommand) cmd); + } else if (cmd instanceof MigrateWithStorageCompleteCommand) { + return execute((MigrateWithStorageCompleteCommand) cmd); + } else if (cmd instanceof MigrateVolumeCommand) { + return execute((MigrateVolumeCommand) cmd); + } else { + return super.executeRequest(cmd); + } + } + + private List getUpdatedVolumePathsOfMigratedVm(Connection connection, VM migratedVm, + VolumeTO[] volumes) throws CloudRuntimeException { + List volumeToList = new ArrayList(); + + try { + // Volume paths would have changed. Return that information. + Set vbds = migratedVm.getVBDs(connection); + Map deviceIdToVdiMap = new HashMap(); + // get vdi:vbdr to a map + for (VBD vbd : vbds) { + VBD.Record vbdr = vbd.getRecord(connection); + if (vbdr.type == Types.VbdType.DISK) { + VDI vdi = vbdr.VDI; + deviceIdToVdiMap.put(vbdr.userdevice, vdi); + } + } + + for (VolumeTO volumeTo : volumes) { + Long deviceId = volumeTo.getDeviceId(); + VDI vdi = deviceIdToVdiMap.get(deviceId.toString()); + volumeTo.setPath(vdi.getUuid(connection)); + volumeToList.add(volumeTo); + } + } catch (Exception e) { + s_logger.error("Unable to get the updated VDI paths of the migrated vm " + e.toString(), e); + throw new CloudRuntimeException("Unable to get the updated VDI paths of the migrated vm " + e.toString(), e); + } + + return volumeToList; + } + + protected MigrateWithStorageAnswer execute(MigrateWithStorageCommand cmd) { + Connection connection = getConnection(); + VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + Map volumeToFiler = cmd.getVolumeToFiler(); + final String vmName = vmSpec.getName(); + State state = s_vms.getState(_cluster, vmName); + Task task = null; + + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, vmName, State.Stopping); + } + + try { + prepareISO(connection, vmSpec.getName()); + Map other = new HashMap(); + other.put("live", "true"); + Network networkForSm = getNativeNetworkForTraffic(connection, TrafficType.Storage, null).getNetwork(); + Host host = Host.getByUuid(connection, _host.uuid); + Map token = host.migrateReceive(connection, networkForSm, other); + + // Get the vm to migrate. + Set vms = VM.getByNameLabel(connection, vmSpec.getName()); + VM vmToMigrate = vms.iterator().next(); + + // Create the vif map. The vm stays in the same cluster so we have to pass an empty vif map. + Map vifMap = new HashMap(); + Map vdiMap = new HashMap(); + for (Map.Entry entry : volumeToFiler.entrySet()) { + vdiMap.put(getVDIbyUuid(connection, entry.getKey().getPath()), + getStorageRepository(connection, entry.getValue().getUuid())); + } + + // Check migration with storage is possible. + task = vmToMigrate.assertCanMigrateAsync(connection, token, true, vdiMap, vifMap, other); + try { + // poll every 1 seconds + long timeout = (_migratewait) * 1000L; + waitForTask(connection, task, 1000, timeout); + checkForSuccess(connection, task); + } catch (Types.HandleInvalid e) { + s_logger.error("Error while checking if vm " + vmName + " can be migrated to the destination host " + + host, e); + throw new CloudRuntimeException("Error while checking if vm " + vmName + " can be migrated to the " + + "destination host " + host, e); + } + + // Migrate now. + task = vmToMigrate.migrateSendAsync(connection, token, true, vdiMap, vifMap, other); + try { + // poll every 1 seconds. + long timeout = (_migratewait) * 1000L; + waitForTask(connection, task, 1000, timeout); + checkForSuccess(connection, task); + } catch (Types.HandleInvalid e) { + s_logger.error("Error while migrating vm " + vmName + " to the destination host " + host, e); + throw new CloudRuntimeException("Error while migrating vm " + vmName + " to the destination host " + + host, e); + } + + // Volume paths would have changed. Return that information. + List volumeToList = getUpdatedVolumePathsOfMigratedVm(connection, vmToMigrate, vmSpec.getDisks()); + vmToMigrate.setAffinity(connection, host); + state = State.Stopping; + + return new MigrateWithStorageAnswer(cmd, volumeToList); + } catch (Exception e) { + s_logger.warn("Catch Exception " + e.getClass().getName() + ". Storage motion failed due to " + + e.toString(), e); + return new MigrateWithStorageAnswer(cmd, e); + } finally { + if (task != null) { + try { + task.destroy(connection); + } catch (Exception e) { + s_logger.debug("Unable to destroy task " + task.toString() + " on host " + _host.uuid +" due to " + + e.toString()); + } + } + + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, vmName, state); + } + } + } + + protected MigrateWithStorageReceiveAnswer execute(MigrateWithStorageReceiveCommand cmd) { + Connection connection = getConnection(); + VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + Map volumeToFiler = cmd.getVolumeToFiler(); + + try { + // Get a map of all the SRs to which the vdis will be migrated. + Map volumeToSr = new HashMap(); + for (Map.Entry entry : volumeToFiler.entrySet()) { + SR sr = getStorageRepository(connection, entry.getValue().getUuid()); + volumeToSr.put(entry.getKey(), sr); + } + + // Get the list of networks to which the vifs will attach. + Map nicToNetwork = new HashMap(); + for (NicTO nicTo : vmSpec.getNics()) { + Network network = getNetwork(connection, nicTo); + nicToNetwork.put(nicTo, network); + } + + Map other = new HashMap(); + other.put("live", "true"); + Network network = getNativeNetworkForTraffic(connection, TrafficType.Storage, null).getNetwork(); + Host host = Host.getByUuid(connection, _host.uuid); + Map token = host.migrateReceive(connection, network, other); + + return new MigrateWithStorageReceiveAnswer(cmd, volumeToSr, nicToNetwork, token); + } catch (CloudRuntimeException e) { + s_logger.error("Migration of vm " + vmSpec.getName() + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageReceiveAnswer(cmd, e); + } catch (Exception e) { + s_logger.error("Migration of vm " + vmSpec.getName() + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageReceiveAnswer(cmd, e); + } + } + + protected MigrateWithStorageSendAnswer execute(MigrateWithStorageSendCommand cmd) { + Connection connection = getConnection(); + VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + Map volumeToSr = cmd.getVolumeToSr(); + Map nicToNetwork = cmd.getNicToNetwork(); + Map token = cmd.getToken(); + final String vmName = vmSpec.getName(); + State state = s_vms.getState(_cluster, vmName); + Set volumeToSet = null; + boolean migrated = false; + Task task = null; + + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, vmName, State.Stopping); + } + + try { + Set vms = VM.getByNameLabel(connection, vmSpec.getName()); + VM vmToMigrate = vms.iterator().next(); + Map other = new HashMap(); + other.put("live", "true"); + + // Create the vdi map which tells what volumes of the vm need to go on which sr on the destination. + Map vdiMap = new HashMap(); + for (Map.Entry entry : volumeToSr.entrySet()) { + if (entry.getValue() instanceof SR) { + SR sr = (SR)entry.getValue(); + VDI vdi = getVDIbyUuid(connection, entry.getKey().getPath()); + vdiMap.put(vdi, sr); + } else { + throw new CloudRuntimeException("The object " + entry.getValue() + " passed is not of type SR."); + } + } + + // Create the vif map. + Map vifMap = new HashMap(); + for (Map.Entry entry : nicToNetwork.entrySet()) { + if (entry.getValue() instanceof Network) { + Network network = (Network)entry.getValue(); + VIF vif = getVifByMac(connection, vmToMigrate, entry.getKey().getMac()); + vifMap.put(vif, network); + } else { + throw new CloudRuntimeException("The object " + entry.getValue() + " passed is not of type Network."); + } + } + + // Check migration with storage is possible. + task = vmToMigrate.assertCanMigrateAsync(connection, token, true, vdiMap, vifMap, other); + try { + // poll every 1 seconds. + long timeout = (_migratewait) * 1000L; + waitForTask(connection, task, 1000, timeout); + checkForSuccess(connection, task); + } catch (Types.HandleInvalid e) { + s_logger.error("Error while checking if vm " + vmName + " can be migrated.", e); + throw new CloudRuntimeException("Error while checking if vm " + vmName + " can be migrated.", e); + } + + // Migrate now. + task = vmToMigrate.migrateSendAsync(connection, token, true, vdiMap, vifMap, other); + try { + // poll every 1 seconds. + long timeout = (_migratewait) * 1000L; + waitForTask(connection, task, 1000, timeout); + checkForSuccess(connection, task); + } catch (Types.HandleInvalid e) { + s_logger.error("Error while migrating vm " + vmName, e); + throw new CloudRuntimeException("Error while migrating vm " + vmName, e); + } + + migrated = true; + return new MigrateWithStorageSendAnswer(cmd, volumeToSet); + } catch (CloudRuntimeException e) { + s_logger.error("Migration of vm " + vmName + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageSendAnswer(cmd, e); + } catch (Exception e) { + s_logger.error("Migration of vm " + vmName + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageSendAnswer(cmd, e); + } finally { + if (task != null) { + try { + task.destroy(connection); + } catch (Exception e) { + s_logger.debug("Unable to destroy task " + task.toString() + " on host " + _host.uuid +" due to " + + e.toString()); + } + } + + // Keep cluster/vm sync happy. + synchronized (_cluster.intern()) { + if (migrated) { + s_vms.remove(_cluster, _name, vmName); + } else { + s_vms.put(_cluster, _name, vmName, state); + } + } + } + } + + protected MigrateWithStorageCompleteAnswer execute(MigrateWithStorageCompleteCommand cmd) { + Connection connection = getConnection(); + VirtualMachineTO vmSpec = cmd.getVirtualMachine(); + + try { + Host host = Host.getByUuid(connection, _host.uuid); + Set vms = VM.getByNameLabel(connection, vmSpec.getName()); + VM migratedVm = vms.iterator().next(); + + // Check the vm is present on the new host. + if (migratedVm == null) { + throw new CloudRuntimeException("Couldn't find the migrated vm " + vmSpec.getName() + + " on the destination host."); + } + + // Volume paths would have changed. Return that information. + List volumeToSet = getUpdatedVolumePathsOfMigratedVm(connection, migratedVm, vmSpec.getDisks()); + migratedVm.setAffinity(connection, host); + + synchronized (_cluster.intern()) { + s_vms.put(_cluster, _name, vmSpec.getName(), State.Running); + } + + return new MigrateWithStorageCompleteAnswer(cmd, volumeToSet); + } catch (CloudRuntimeException e) { + s_logger.error("Migration of vm " + vmSpec.getName() + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageCompleteAnswer(cmd, e); + } catch (Exception e) { + s_logger.error("Migration of vm " + vmSpec.getName() + " with storage failed due to " + e.toString(), e); + return new MigrateWithStorageCompleteAnswer(cmd, e); + } + } + + protected MigrateVolumeAnswer execute(MigrateVolumeCommand cmd) { + Connection connection = getConnection(); + String volumeUUID = cmd.getVolumePath(); + StorageFilerTO poolTO = cmd.getPool(); + + try { + SR destinationPool = getStorageRepository(connection, poolTO.getUuid()); + VDI srcVolume = getVDIbyUuid(connection, volumeUUID); + Map other = new HashMap(); + other.put("live", "true"); + + // Live migrate the vdi across pool. + Task task = srcVolume.poolMigrateAsync(connection, destinationPool, other); + long timeout = (_migratewait) * 1000L; + waitForTask(connection, task, 1000, timeout); + checkForSuccess(connection, task); + VDI dvdi = Types.toVDI(task, connection); + + return new MigrateVolumeAnswer(cmd, true, null, dvdi.getUuid(connection)); + } catch (Exception e) { + String msg = "Catch Exception " + e.getClass().getName() + " due to " + e.toString(); + s_logger.error(msg, e); + return new MigrateVolumeAnswer(cmd, false, msg, null); + } + } } diff --git a/plugins/hypervisors/xen/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java b/plugins/hypervisors/xen/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java new file mode 100644 index 00000000000..353f2b58d08 --- /dev/null +++ b/plugins/hypervisors/xen/src/org/apache/cloudstack/storage/motion/XenServerStorageMotionStrategy.java @@ -0,0 +1,239 @@ +/* + * 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.storage.motion; + +import java.util.HashMap; +import java.util.Map; +import java.util.List; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.MigrateWithStorageAnswer; +import com.cloud.agent.api.MigrateWithStorageCommand; +import com.cloud.agent.api.MigrateWithStorageCompleteAnswer; +import com.cloud.agent.api.MigrateWithStorageCompleteCommand; +import com.cloud.agent.api.MigrateWithStorageReceiveAnswer; +import com.cloud.agent.api.MigrateWithStorageReceiveCommand; +import com.cloud.agent.api.MigrateWithStorageSendAnswer; +import com.cloud.agent.api.MigrateWithStorageSendCommand; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.VolumeTO; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.host.Host; +import com.cloud.storage.StoragePool; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.VMInstanceVO; +import com.cloud.vm.dao.VMInstanceDao; + +@Component +public class XenServerStorageMotionStrategy implements DataMotionStrategy { + private static final Logger s_logger = Logger.getLogger(XenServerStorageMotionStrategy.class); + @Inject AgentManager agentMgr; + @Inject VolumeDao volDao; + @Inject VolumeDataFactory volFactory; + @Inject PrimaryDataStoreDao storagePoolDao; + @Inject VMInstanceDao instanceDao; + + @Override + public boolean canHandle(DataObject srcData, DataObject destData) { + return false; + } + + @Override + public boolean canHandle(Map volumeMap, Host srcHost, Host destHost) { + return true; + } + + @Override + public Void copyAsync(DataObject srcData, DataObject destData, + AsyncCompletionCallback callback) { + CopyCommandResult result = new CopyCommandResult(null, null); + result.setResult("Unsupported operation requested for copying data."); + callback.complete(result); + + return null; + } + + @Override + public Void copyAsync(Map volumeMap, VirtualMachineTO vmTo, Host srcHost, Host destHost, + AsyncCompletionCallback callback) { + Answer answer = null; + String errMsg = null; + try { + VMInstanceVO instance = instanceDao.findById(vmTo.getId()); + if (instance != null) { + if (srcHost.getClusterId() == destHost.getClusterId()) { + answer = migrateVmWithVolumesWithinCluster(instance, vmTo, srcHost, destHost, volumeMap); + } else { + answer = migrateVmWithVolumesAcrossCluster(instance, vmTo, srcHost, destHost, volumeMap); + } + } else { + throw new CloudRuntimeException("Unsupported operation requested for moving data."); + } + } catch (Exception e) { + s_logger.error("copy failed", e); + errMsg = e.toString(); + } + + CopyCommandResult result = new CopyCommandResult(null, answer); + result.setResult(errMsg); + callback.complete(result); + return null; + } + + private Answer migrateVmWithVolumesAcrossCluster(VMInstanceVO vm, VirtualMachineTO to, Host srcHost, + Host destHost, Map volumeToPool) throws AgentUnavailableException { + + // Initiate migration of a virtual machine with it's volumes. + try { + Map volumeToFilerto = new HashMap(); + for (Map.Entry entry : volumeToPool.entrySet()) { + VolumeInfo volume = entry.getKey(); + VolumeTO volumeTo = new VolumeTO(volume, storagePoolDao.findById(volume.getPoolId())); + StorageFilerTO filerTo = new StorageFilerTO((StoragePool)entry.getValue()); + volumeToFilerto.put(volumeTo, filerTo); + } + + // Migration across cluster needs to be done in three phases. + // 1. Send a migrate receive command to the destination host so that it is ready to receive a vm. + // 2. Send a migrate send command to the source host. This actually migrates the vm to the destination. + // 3. Complete the process. Update the volume details. + MigrateWithStorageReceiveCommand receiveCmd = new MigrateWithStorageReceiveCommand(to, volumeToFilerto); + MigrateWithStorageReceiveAnswer receiveAnswer = (MigrateWithStorageReceiveAnswer) agentMgr.send( + destHost.getId(), receiveCmd); + if (receiveAnswer == null) { + s_logger.error("Migration with storage of vm " + vm+ " to host " + destHost + " failed."); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost); + } else if (!receiveAnswer.getResult()) { + s_logger.error("Migration with storage of vm " + vm+ " failed. Details: " + receiveAnswer.getDetails()); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost + + ". " + receiveAnswer.getDetails()); + } + + MigrateWithStorageSendCommand sendCmd = new MigrateWithStorageSendCommand(to, receiveAnswer.getVolumeToSr(), + receiveAnswer.getNicToNetwork(), receiveAnswer.getToken()); + MigrateWithStorageSendAnswer sendAnswer = (MigrateWithStorageSendAnswer) agentMgr.send( + srcHost.getId(), sendCmd); + if (sendAnswer == null) { + s_logger.error("Migration with storage of vm " + vm+ " to host " + destHost + " failed."); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost); + } else if (!sendAnswer.getResult()) { + s_logger.error("Migration with storage of vm " + vm+ " failed. Details: " + sendAnswer.getDetails()); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost + + ". " + sendAnswer.getDetails()); + } + + MigrateWithStorageCompleteCommand command = new MigrateWithStorageCompleteCommand(to); + MigrateWithStorageCompleteAnswer answer = (MigrateWithStorageCompleteAnswer) agentMgr.send( + destHost.getId(), command); + if (answer == null) { + s_logger.error("Migration with storage of vm " + vm + " failed."); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost); + } else if (!answer.getResult()) { + s_logger.error("Migration with storage of vm " + vm+ " failed. Details: " + answer.getDetails()); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost + + ". " + answer.getDetails()); + } else { + // Update the volume details after migration. + updateVolumePathsAfterMigration(volumeToPool, answer.getVolumeTos()); + } + + return answer; + } catch (OperationTimedoutException e) { + s_logger.error("Error while migrating vm " + vm + " to host " + destHost, e); + throw new AgentUnavailableException("Operation timed out on storage motion for " + vm, destHost.getId()); + } + } + + private Answer migrateVmWithVolumesWithinCluster(VMInstanceVO vm, VirtualMachineTO to, Host srcHost, + Host destHost, Map volumeToPool) throws AgentUnavailableException { + + // Initiate migration of a virtual machine with it's volumes. + try { + Map volumeToFilerto = new HashMap(); + for (Map.Entry entry : volumeToPool.entrySet()) { + VolumeInfo volume = entry.getKey(); + VolumeTO volumeTo = new VolumeTO(volume, storagePoolDao.findById(volume.getPoolId())); + StorageFilerTO filerTo = new StorageFilerTO((StoragePool)entry.getValue()); + volumeToFilerto.put(volumeTo, filerTo); + } + + MigrateWithStorageCommand command = new MigrateWithStorageCommand(to, volumeToFilerto); + MigrateWithStorageAnswer answer = (MigrateWithStorageAnswer) agentMgr.send(destHost.getId(), command); + if (answer == null) { + s_logger.error("Migration with storage of vm " + vm + " failed."); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost); + } else if (!answer.getResult()) { + s_logger.error("Migration with storage of vm " + vm+ " failed. Details: " + answer.getDetails()); + throw new CloudRuntimeException("Error while migrating the vm " + vm + " to host " + destHost + + ". " + answer.getDetails()); + } else { + // Update the volume details after migration. + updateVolumePathsAfterMigration(volumeToPool, answer.getVolumeTos()); + } + + return answer; + } catch (OperationTimedoutException e) { + s_logger.error("Error while migrating vm " + vm + " to host " + destHost, e); + throw new AgentUnavailableException("Operation timed out on storage motion for " + vm, destHost.getId()); + } + } + + private void updateVolumePathsAfterMigration(Map volumeToPool, List volumeTos) { + for (Map.Entry entry : volumeToPool.entrySet()) { + boolean updated = false; + VolumeInfo volume = entry.getKey(); + StoragePool pool = (StoragePool)entry.getValue(); + for (VolumeTO volumeTo : volumeTos) { + if (volume.getId() == volumeTo.getId()) { + VolumeVO volumeVO = volDao.findById(volume.getId()); + Long oldPoolId = volumeVO.getPoolId(); + volumeVO.setPath(volumeTo.getPath()); + volumeVO.setFolder(pool.getPath()); + volumeVO.setPodId(pool.getPodId()); + volumeVO.setPoolId(pool.getId()); + volumeVO.setLastPoolId(oldPoolId); + volDao.update(volume.getId(), volumeVO); + updated = true; + break; + } + } + + if (!updated) { + s_logger.error("Volume path wasn't updated for volume " + volume + " after it was migrated."); + } + } + } +} diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java index 3ca34473cd7..c22f669796c 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/element/NiciraNvpElement.java @@ -843,6 +843,11 @@ NiciraNvpElementService, ResourceStateAdapter, IpDeployer { List cidrs = new ArrayList(); for (PublicIpAddress ip : ipAddress) { + if (ip.getState() == IpAddress.State.Releasing) { + // If we are releasing we don't need to push this ip to + // the Logical Router + continue; + } cidrs.add(ip.getAddress().addr() + "/" + NetUtils.getCidrSize(ip.getNetmask())); } ConfigurePublicIpsOnLogicalRouterCommand cmd = new ConfigurePublicIpsOnLogicalRouterCommand(routermapping.getLogicalRouterUuid(), diff --git a/plugins/network-elements/nicira-nvp/test/com/cloud/network/element/NiciraNvpElementTest.java b/plugins/network-elements/nicira-nvp/test/com/cloud/network/element/NiciraNvpElementTest.java index 09d50a33a64..40685fa4236 100644 --- a/plugins/network-elements/nicira-nvp/test/com/cloud/network/element/NiciraNvpElementTest.java +++ b/plugins/network-elements/nicira-nvp/test/com/cloud/network/element/NiciraNvpElementTest.java @@ -16,107 +16,197 @@ // under the License. package com.cloud.network.element; +import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import javax.naming.ConfigurationException; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentMatcher; +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Command; +import com.cloud.agent.api.ConfigurePublicIpsOnLogicalRouterAnswer; +import com.cloud.agent.api.ConfigurePublicIpsOnLogicalRouterCommand; import com.cloud.deploy.DeployDestination; import com.cloud.domain.Domain; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.ResourceUnavailableException; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; import com.cloud.network.Network; import com.cloud.network.Network.GuestType; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; +import com.cloud.network.IpAddress; import com.cloud.network.NetworkManager; import com.cloud.network.NetworkModel; import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.TrafficType; +import com.cloud.network.NiciraNvpDeviceVO; +import com.cloud.network.NiciraNvpRouterMappingVO; +import com.cloud.network.PublicIpAddress; import com.cloud.network.dao.NetworkServiceMapDao; +import com.cloud.network.dao.NiciraNvpDao; +import com.cloud.network.dao.NiciraNvpRouterMappingDao; +import com.cloud.network.nicira.NatRule; import com.cloud.offering.NetworkOffering; import com.cloud.resource.ResourceManager; import com.cloud.user.Account; +import com.cloud.utils.net.Ip; import com.cloud.vm.ReservationContext; import static org.junit.Assert.*; +import static org.mockito.Matchers.argThat; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.*; public class NiciraNvpElementTest { - - NiciraNvpElement _element = new NiciraNvpElement(); - NetworkManager _networkManager = mock(NetworkManager.class); - NetworkModel _networkModel = mock(NetworkModel.class); - NetworkServiceMapDao _ntwkSrvcDao = mock (NetworkServiceMapDao.class); - - @Before - public void setUp() throws ConfigurationException { - _element._resourceMgr = mock(ResourceManager.class); - _element._networkManager = _networkManager; - _element._ntwkSrvcDao = _ntwkSrvcDao; - _element._networkModel = _networkModel; - - // Standard responses - when(_networkModel.isProviderForNetwork(Provider.NiciraNvp, 42L)).thenReturn(true); - - _element.configure("NiciraNvpTestElement", Collections. emptyMap()); - } - @Test - public void canHandleTest() { - Network net = mock(Network.class); - when(net.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Lswitch); - when(net.getId()).thenReturn(42L); - - when(_ntwkSrvcDao.canProviderSupportServiceInNetwork(42L, Service.Connectivity, Provider.NiciraNvp)).thenReturn(true); - // Golden path - assertTrue(_element.canHandle(net, Service.Connectivity)); - - when(net.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Vlan); - // Only broadcastdomaintype lswitch is supported - assertFalse(_element.canHandle(net, Service.Connectivity)); - - when(net.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Lswitch); - when(_ntwkSrvcDao.canProviderSupportServiceInNetwork(42L, Service.Connectivity, Provider.NiciraNvp)).thenReturn(false); - // No nvp provider in the network - assertFalse(_element.canHandle(net, Service.Connectivity)); - - when(_networkModel.isProviderForNetwork(Provider.NiciraNvp, 42L)).thenReturn(false); - when(_ntwkSrvcDao.canProviderSupportServiceInNetwork(42L, Service.Connectivity, Provider.NiciraNvp)).thenReturn(true); - // NVP provider does not provide Connectivity for this network - assertFalse(_element.canHandle(net, Service.Connectivity)); - - when(_networkModel.isProviderForNetwork(Provider.NiciraNvp, 42L)).thenReturn(true); - // Only service Connectivity is supported - assertFalse(_element.canHandle(net, Service.Dhcp)); - - } - - @Test - public void implementTest() throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { - Network network = mock(Network.class); - when(network.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Lswitch); - when(network.getId()).thenReturn(42L); - - NetworkOffering offering = mock(NetworkOffering.class); - when(offering.getId()).thenReturn(42L); - when(offering.getTrafficType()).thenReturn(TrafficType.Guest); - when(offering.getGuestType()).thenReturn(GuestType.Isolated); - - DeployDestination dest = mock(DeployDestination.class); - - Domain dom = mock(Domain.class); - when(dom.getName()).thenReturn("domain"); - Account acc = mock(Account.class); - when(acc.getAccountName()).thenReturn("accountname"); - ReservationContext context = mock(ReservationContext.class); - when(context.getDomain()).thenReturn(dom); - when(context.getAccount()).thenReturn(acc); - - //assertTrue(_element.implement(network, offering, dest, context)); - } + NiciraNvpElement _element = new NiciraNvpElement(); + NetworkManager _networkManager = mock(NetworkManager.class); + NetworkModel _networkModel = mock(NetworkModel.class); + NetworkServiceMapDao _ntwkSrvcDao = mock(NetworkServiceMapDao.class); + AgentManager _agentManager = mock(AgentManager.class); + HostDao _hostDao = mock(HostDao.class); + NiciraNvpDao _niciraNvpDao = mock(NiciraNvpDao.class); + NiciraNvpRouterMappingDao _niciraNvpRouterMappingDao = mock(NiciraNvpRouterMappingDao.class); -} + @Before + public void setUp() throws ConfigurationException { + _element._resourceMgr = mock(ResourceManager.class); + _element._networkManager = _networkManager; + _element._ntwkSrvcDao = _ntwkSrvcDao; + _element._networkModel = _networkModel; + _element._agentMgr = _agentManager; + _element._hostDao = _hostDao; + _element._niciraNvpDao = _niciraNvpDao; + _element._niciraNvpRouterMappingDao = _niciraNvpRouterMappingDao; + + // Standard responses + when(_networkModel.isProviderForNetwork(Provider.NiciraNvp, 42L)).thenReturn(true); + + _element.configure("NiciraNvpTestElement", Collections. emptyMap()); + } + + @Test + public void canHandleTest() { + Network net = mock(Network.class); + when(net.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Lswitch); + when(net.getId()).thenReturn(42L); + + when(_ntwkSrvcDao.canProviderSupportServiceInNetwork(42L, Service.Connectivity, Provider.NiciraNvp)).thenReturn(true); + // Golden path + assertTrue(_element.canHandle(net, Service.Connectivity)); + + when(net.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Vlan); + // Only broadcastdomaintype lswitch is supported + assertFalse(_element.canHandle(net, Service.Connectivity)); + + when(net.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Lswitch); + when(_ntwkSrvcDao.canProviderSupportServiceInNetwork(42L, Service.Connectivity, Provider.NiciraNvp)).thenReturn(false); + // No nvp provider in the network + assertFalse(_element.canHandle(net, Service.Connectivity)); + + when(_networkModel.isProviderForNetwork(Provider.NiciraNvp, 42L)).thenReturn(false); + when(_ntwkSrvcDao.canProviderSupportServiceInNetwork(42L, Service.Connectivity, Provider.NiciraNvp)).thenReturn(true); + // NVP provider does not provide Connectivity for this network + assertFalse(_element.canHandle(net, Service.Connectivity)); + + when(_networkModel.isProviderForNetwork(Provider.NiciraNvp, 42L)).thenReturn(true); + // Only service Connectivity is supported + assertFalse(_element.canHandle(net, Service.Dhcp)); + + } + + @Test + public void implementTest() throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + Network network = mock(Network.class); + when(network.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Lswitch); + when(network.getId()).thenReturn(42L); + + NetworkOffering offering = mock(NetworkOffering.class); + when(offering.getId()).thenReturn(42L); + when(offering.getTrafficType()).thenReturn(TrafficType.Guest); + when(offering.getGuestType()).thenReturn(GuestType.Isolated); + + DeployDestination dest = mock(DeployDestination.class); + + Domain dom = mock(Domain.class); + when(dom.getName()).thenReturn("domain"); + Account acc = mock(Account.class); + when(acc.getAccountName()).thenReturn("accountname"); + ReservationContext context = mock(ReservationContext.class); + when(context.getDomain()).thenReturn(dom); + when(context.getAccount()).thenReturn(acc); + + // assertTrue(_element.implement(network, offering, dest, context)); + } + + @Test + public void applyIpTest() throws ResourceUnavailableException { + Network network = mock(Network.class); + when(network.getBroadcastDomainType()).thenReturn(BroadcastDomainType.Lswitch); + when(network.getId()).thenReturn(42L); + when(network.getPhysicalNetworkId()).thenReturn(42L); + + NetworkOffering offering = mock(NetworkOffering.class); + when(offering.getId()).thenReturn(42L); + when(offering.getTrafficType()).thenReturn(TrafficType.Guest); + when(offering.getGuestType()).thenReturn(GuestType.Isolated); + + List ipAddresses = new ArrayList(); + PublicIpAddress pipReleased = mock(PublicIpAddress.class); + PublicIpAddress pipAllocated = mock(PublicIpAddress.class); + Ip ipReleased = new Ip("42.10.10.10"); + Ip ipAllocated = new Ip("10.10.10.10"); + when(pipAllocated.getState()).thenReturn(IpAddress.State.Allocated); + when(pipAllocated.getAddress()).thenReturn(ipAllocated); + when(pipAllocated.getNetmask()).thenReturn("255.255.255.0"); + when(pipReleased.getState()).thenReturn(IpAddress.State.Releasing); + when(pipReleased.getAddress()).thenReturn(ipReleased); + when(pipReleased.getNetmask()).thenReturn("255.255.255.0"); + ipAddresses.add(pipAllocated); + ipAddresses.add(pipReleased); + + Set services = new HashSet(); + services.add(Service.SourceNat); + services.add(Service.StaticNat); + services.add(Service.PortForwarding); + + List deviceList = new ArrayList(); + NiciraNvpDeviceVO nndVO = mock(NiciraNvpDeviceVO.class); + NiciraNvpRouterMappingVO nnrmVO = mock(NiciraNvpRouterMappingVO.class); + when(_niciraNvpRouterMappingDao.findByNetworkId(42L)).thenReturn(nnrmVO); + when(nnrmVO.getLogicalRouterUuid()).thenReturn("abcde"); + when(nndVO.getHostId()).thenReturn(42L); + HostVO hvo = mock(HostVO.class); + when(hvo.getId()).thenReturn(42L); + when(hvo.getDetail("l3gatewayserviceuuid")).thenReturn("abcde"); + when(_hostDao.findById(42L)).thenReturn(hvo); + deviceList.add(nndVO); + when(_niciraNvpDao.listByPhysicalNetwork(42L)).thenReturn(deviceList); + + ConfigurePublicIpsOnLogicalRouterAnswer answer = mock(ConfigurePublicIpsOnLogicalRouterAnswer.class); + when(answer.getResult()).thenReturn(true); + when(_agentManager.easySend(eq(42L), any(ConfigurePublicIpsOnLogicalRouterCommand.class))).thenReturn(answer); + + assertTrue(_element.applyIps(network, ipAddresses, services)); + + verify(_agentManager, atLeast(1)).easySend(eq(42L), + argThat(new ArgumentMatcher() { + @Override + public boolean matches(Object argument) { + ConfigurePublicIpsOnLogicalRouterCommand command = (ConfigurePublicIpsOnLogicalRouterCommand) argument; + if (command.getPublicCidrs().size() == 1) + return true; + return false; + } + })); + } +} \ No newline at end of file diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java index 51ea2126756..a0c991b5ad6 100644 --- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java +++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/lifecycle/CloudStackPrimaryDataStoreLifeCycleImpl.java @@ -532,8 +532,7 @@ public class CloudStackPrimaryDataStoreLifeCycleImpl implements throw new CloudRuntimeException("Failed to delete storage pool on host"); } - this.dataStoreHelper.deletePrimaryDataStore(store); - return false; + return this.dataStoreHelper.deletePrimaryDataStore(store); } @Override diff --git a/pom.xml b/pom.xml index dbc39076f2d..7d5b4c3bdef 100644 --- a/pom.xml +++ b/pom.xml @@ -237,6 +237,22 @@ install + + org.apache.maven.plugins + maven-release-plugin + 2.2.1 + + + default + + perform + + + pom.xml + + + + diff --git a/server/pom.xml b/server/pom.xml index ca56851ec15..8b64335d50f 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -153,11 +153,11 @@ com/cloud/snapshot/* com/cloud/storage/dao/* com/cloud/vm/dao/* - com/cloud/vpc/* com/cloud/api/ListPerfTest.java com/cloud/network/vpn/RemoteAccessVpnTest.java com/cloud/network/security/SecurityGroupManagerImpl2Test.java com/cloud/network/security/SecurityGroupManagerImpl2Test.java + com/cloud/vpc/* diff --git a/server/src/com/cloud/agent/manager/allocator/HostAllocator.java b/server/src/com/cloud/agent/manager/allocator/HostAllocator.java index 60027e7f9e3..6700f2227d9 100755 --- a/server/src/com/cloud/agent/manager/allocator/HostAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/HostAllocator.java @@ -21,6 +21,7 @@ import java.util.List; import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.host.Host; +import com.cloud.host.HostVO; import com.cloud.host.Host.Type; import com.cloud.offering.ServiceOffering; import com.cloud.utils.component.Adapter; @@ -63,8 +64,22 @@ public interface HostAllocator extends Adapter { **/ public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity); - - - public static int RETURN_UPTO_ALL = -1; - + + /** + * Determines which physical hosts are suitable to + * allocate the guest virtual machines on + * + * @param VirtualMachineProfile vmProfile + * @param DeploymentPlan plan + * @param GuestType type + * @param ExcludeList avoid + * @param List hosts + * @param int returnUpTo (use -1 to return all possible hosts) + * @param boolean considerReservedCapacity (default should be true, set to false if host capacity calculation should not look at reserved capacity) + * @return List List of hosts that are suitable for VM allocation + **/ + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, List hosts, int returnUpTo, boolean considerReservedCapacity); + + public static int RETURN_UPTO_ALL = -1; + } diff --git a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java index 0091e43cab8..b54b1c1f527 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/FirstFitAllocator.java @@ -172,6 +172,53 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator { return allocateTo(plan, offering, template, avoid, clusterHosts, returnUpTo, considerReservedCapacity, account); } + @Override + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, + Type type, ExcludeList avoid, List hosts, int returnUpTo, boolean considerReservedCapacity) { + long dcId = plan.getDataCenterId(); + Long podId = plan.getPodId(); + Long clusterId = plan.getClusterId(); + ServiceOffering offering = vmProfile.getServiceOffering(); + VMTemplateVO template = (VMTemplateVO)vmProfile.getTemplate(); + Account account = vmProfile.getOwner(); + List suitableHosts = new ArrayList(); + + if (type == Host.Type.Storage) { + // FirstFitAllocator should be used for user VMs only since it won't care whether the host is capable of + // routing or not. + return suitableHosts; + } + + String hostTagOnOffering = offering.getHostTag(); + String hostTagOnTemplate = template.getTemplateTag(); + boolean hasSvcOfferingTag = hostTagOnOffering != null ? true : false; + boolean hasTemplateTag = hostTagOnTemplate != null ? true : false; + + String haVmTag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.HaTag); + if (haVmTag != null) { + hosts.retainAll(_hostDao.listByHostTag(type, clusterId, podId, dcId, haVmTag)); + } else { + if (hostTagOnOffering == null && hostTagOnTemplate == null){ + hosts.retainAll(_resourceMgr.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, dcId)); + } else { + if (hasSvcOfferingTag) { + hosts.retainAll(_hostDao.listByHostTag(type, clusterId, podId, dcId, hostTagOnOffering)); + } + + if (hasTemplateTag) { + hosts.retainAll(_hostDao.listByHostTag(type, clusterId, podId, dcId, hostTagOnTemplate)); + } + } + } + + if (!hosts.isEmpty()) { + suitableHosts = allocateTo(plan, offering, template, avoid, hosts, returnUpTo, considerReservedCapacity, + account); + } + + return suitableHosts; + } + protected List allocateTo(DeploymentPlan plan, ServiceOffering offering, VMTemplateVO template, ExcludeList avoid, List hosts, int returnUpTo, boolean considerReservedCapacity, Account account) { if (_allocationAlgorithm.equals("random") || _allocationAlgorithm.equals("userconcentratedpod_random")) { // Shuffle this so that we don't check the hosts in the same order. diff --git a/server/src/com/cloud/agent/manager/allocator/impl/TestingAllocator.java b/server/src/com/cloud/agent/manager/allocator/impl/TestingAllocator.java index 90bd95629bf..890c047de50 100755 --- a/server/src/com/cloud/agent/manager/allocator/impl/TestingAllocator.java +++ b/server/src/com/cloud/agent/manager/allocator/impl/TestingAllocator.java @@ -29,6 +29,7 @@ import com.cloud.agent.manager.allocator.HostAllocator; import com.cloud.deploy.DeploymentPlan; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.host.Host; +import com.cloud.host.HostVO; import com.cloud.host.Host.Type; import com.cloud.host.dao.HostDao; import com.cloud.offering.ServiceOffering; @@ -50,6 +51,12 @@ public class TestingAllocator extends AdapterBase implements HostAllocator { return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true); } + @Override + public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, + ExcludeList avoid, List hosts, int returnUpTo, boolean considerReservedCapacity) { + return allocateTo(vmProfile, plan, type, avoid, returnUpTo, considerReservedCapacity); + } + @Override public List allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity) { diff --git a/server/src/com/cloud/api/ApiDBUtils.java b/server/src/com/cloud/api/ApiDBUtils.java index 303f3281d89..c60af279d4f 100755 --- a/server/src/com/cloud/api/ApiDBUtils.java +++ b/server/src/com/cloud/api/ApiDBUtils.java @@ -36,6 +36,7 @@ import org.apache.cloudstack.api.response.DiskOfferingResponse; import org.apache.cloudstack.api.response.DomainRouterResponse; import org.apache.cloudstack.api.response.EventResponse; import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.response.HostForMigrationResponse; import org.apache.cloudstack.api.response.InstanceGroupResponse; import org.apache.cloudstack.api.response.ProjectAccountResponse; import org.apache.cloudstack.api.response.ProjectInvitationResponse; @@ -43,6 +44,7 @@ import org.apache.cloudstack.api.response.ProjectResponse; import org.apache.cloudstack.api.response.ResourceTagResponse; import org.apache.cloudstack.api.response.SecurityGroupResponse; import org.apache.cloudstack.api.response.ServiceOfferingResponse; +import org.apache.cloudstack.api.response.StoragePoolForMigrationResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.api.response.UserVmResponse; @@ -1518,6 +1520,14 @@ public class ApiDBUtils { return _hostJoinDao.setHostResponse(vrData, vr); } + public static HostForMigrationResponse newHostForMigrationResponse(HostJoinVO vr, EnumSet details) { + return _hostJoinDao.newHostForMigrationResponse(vr, details); + } + + public static HostForMigrationResponse fillHostForMigrationDetails(HostForMigrationResponse vrData, HostJoinVO vr) { + return _hostJoinDao.setHostForMigrationResponse(vrData, vr); + } + public static List newHostView(Host vr){ return _hostJoinDao.newHostView(vr); } @@ -1543,6 +1553,15 @@ public class ApiDBUtils { return _poolJoinDao.setStoragePoolResponse(vrData, vr); } + public static StoragePoolForMigrationResponse newStoragePoolForMigrationResponse(StoragePoolJoinVO vr) { + return _poolJoinDao.newStoragePoolForMigrationResponse(vr); + } + + public static StoragePoolForMigrationResponse fillStoragePoolForMigrationDetails(StoragePoolForMigrationResponse + vrData, StoragePoolJoinVO vr){ + return _poolJoinDao.setStoragePoolForMigrationResponse(vrData, vr); + } + public static List newStoragePoolView(StoragePool vr){ return _poolJoinDao.newStoragePoolView(vr); } diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index cfe0e00d8ba..a7d6165e6ae 100755 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -65,6 +65,7 @@ import org.apache.cloudstack.api.response.FirewallRuleResponse; import org.apache.cloudstack.api.response.GlobalLoadBalancerResponse; import org.apache.cloudstack.api.response.GuestOSResponse; import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.response.HostForMigrationResponse; import org.apache.cloudstack.api.response.HypervisorCapabilitiesResponse; import org.apache.cloudstack.api.response.IPAddressResponse; import org.apache.cloudstack.api.response.InstanceGroupResponse; @@ -105,6 +106,7 @@ import org.apache.cloudstack.api.response.SnapshotResponse; import org.apache.cloudstack.api.response.SnapshotScheduleResponse; import org.apache.cloudstack.api.response.StaticRouteResponse; import org.apache.cloudstack.api.response.StorageNetworkIpRangeResponse; +import org.apache.cloudstack.api.response.StoragePoolForMigrationResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.cloudstack.api.response.SwiftResponse; import org.apache.cloudstack.api.response.SystemVmInstanceResponse; @@ -379,7 +381,7 @@ public class ApiResponseHelper implements ResponseGenerator { populateDomain(resourceLimitResponse, accountTemp.getDomainId()); } resourceLimitResponse.setResourceType(Integer.valueOf(limit.getType().getOrdinal()).toString()); - if(limit.getType() == ResourceType.primary_storage || limit.getType() == ResourceType.secondary_storage) { + if((limit.getType() == ResourceType.primary_storage || limit.getType() == ResourceType.secondary_storage) && limit.getMax() >= 0) { resourceLimitResponse.setMax((long) Math.ceil(limit.getMax()/ResourceType.bytesToGiB)); } else { resourceLimitResponse.setMax(limit.getMax()); @@ -510,6 +512,20 @@ public class ApiResponseHelper implements ResponseGenerator { return listHosts.get(0); } + @Override + public HostForMigrationResponse createHostForMigrationResponse(Host host) { + return createHostForMigrationResponse(host, EnumSet.of(HostDetails.all)); + } + + @Override + public HostForMigrationResponse createHostForMigrationResponse(Host host, EnumSet details) { + List viewHosts = ApiDBUtils.newHostView(host); + List listHosts = ViewResponseHelper.createHostForMigrationResponse(details, + viewHosts.toArray(new HostJoinVO[viewHosts.size()])); + assert listHosts != null && listHosts.size() == 1 : "There should be one host returned"; + return listHosts.get(0); + } + @Override public SwiftResponse createSwiftResponse(Swift swift) { SwiftResponse swiftResponse = new SwiftResponse(); @@ -774,6 +790,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setDescription(globalLoadBalancerRule.getDescription()); response.setRegionIdId(globalLoadBalancerRule.getRegion()); response.setId(globalLoadBalancerRule.getUuid()); + populateOwner(response, globalLoadBalancerRule); response.setObjectName("globalloadbalancer"); return response; } @@ -907,16 +924,21 @@ public class ApiResponseHelper implements ResponseGenerator { } - - @Override public StoragePoolResponse createStoragePoolResponse(StoragePool pool) { List viewPools = ApiDBUtils.newStoragePoolView(pool); List listPools = ViewResponseHelper.createStoragePoolResponse(viewPools.toArray(new StoragePoolJoinVO[viewPools.size()])); assert listPools != null && listPools.size() == 1 : "There should be one storage pool returned"; return listPools.get(0); + } - + @Override + public StoragePoolForMigrationResponse createStoragePoolForMigrationResponse(StoragePool pool) { + List viewPools = ApiDBUtils.newStoragePoolView(pool); + List listPools = ViewResponseHelper.createStoragePoolForMigrationResponse( + viewPools.toArray(new StoragePoolJoinVO[viewPools.size()])); + assert listPools != null && listPools.size() == 1 : "There should be one storage pool returned"; + return listPools.get(0); } @Override @@ -2667,7 +2689,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setZoneId(zone.getUuid()); } response.setNetworkSpeed(result.getSpeed()); - response.setVlan(result.getVnet()); + response.setVlan(result.getVnetString()); if (result.getDomainId() != null) { Domain domain = ApiDBUtils.findDomainById(result.getDomainId()); if (domain != null) { @@ -3663,8 +3685,13 @@ public class ApiResponseHelper implements ResponseGenerator { response.setName(group.getName()); response.setType(group.getType()); response.setDescription(group.getDescription()); - // response.setDomainId(account.) + Domain domain = ApiDBUtils.findDomainById(account.getDomainId()); + if (domain != null) { + response.setDomainId(domain.getUuid()); + response.setDomainName(domain.getName()); + } + response.setObjectName("affinitygroup"); return response; } diff --git a/server/src/com/cloud/api/query/QueryManagerImpl.java b/server/src/com/cloud/api/query/QueryManagerImpl.java index 5ffc2db995c..22982525046 100644 --- a/server/src/com/cloud/api/query/QueryManagerImpl.java +++ b/server/src/com/cloud/api/query/QueryManagerImpl.java @@ -25,12 +25,9 @@ import java.util.Set; import javax.ejb.Local; import javax.inject.Inject; -import javax.naming.ConfigurationException; -import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupResponse; import org.apache.cloudstack.affinity.AffinityGroupVMMapVO; -import org.apache.cloudstack.affinity.AffinityGroupVO; import org.apache.cloudstack.affinity.dao.AffinityGroupVMMapDao; import org.apache.cloudstack.api.command.admin.host.ListHostsCmd; import org.apache.cloudstack.api.command.admin.router.ListRoutersCmd; @@ -111,7 +108,6 @@ import com.cloud.api.query.vo.UserAccountJoinVO; import com.cloud.api.query.vo.UserVmJoinVO; import com.cloud.api.query.vo.VolumeJoinVO; import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.dc.DataCenterVO; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; @@ -124,9 +120,9 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.security.SecurityGroupVMMapVO; import com.cloud.network.security.dao.SecurityGroupVMMapDao; import com.cloud.org.Grouping; -import com.cloud.projects.ProjectInvitation; -import com.cloud.projects.Project.ListProjectResourcesCriteria; import com.cloud.projects.Project; +import com.cloud.projects.Project.ListProjectResourcesCriteria; +import com.cloud.projects.ProjectInvitation; import com.cloud.projects.ProjectManager; import com.cloud.projects.dao.ProjectAccountDao; import com.cloud.projects.dao.ProjectDao; @@ -142,10 +138,8 @@ import com.cloud.user.dao.AccountDao; import com.cloud.utils.DateUtil; import com.cloud.utils.Pair; import com.cloud.utils.Ternary; -import com.cloud.utils.component.Manager; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.Filter; -import com.cloud.utils.db.JoinBuilder; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.SearchCriteria.Func; @@ -644,6 +638,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { c.addCriteria(Criteria.TEMPLATE_ID, cmd.getTemplateId()); c.addCriteria(Criteria.ISO_ID, cmd.getIsoId()); c.addCriteria(Criteria.VPC_ID, cmd.getVpcId()); + c.addCriteria(Criteria.AFFINITY_GROUP_ID, cmd.getAffinityGroupId()); if (domainId != null) { c.addCriteria(Criteria.DOMAINID, domainId); @@ -699,6 +694,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { Object templateId = c.getCriteria(Criteria.TEMPLATE_ID); Object isoId = c.getCriteria(Criteria.ISO_ID); Object vpcId = c.getCriteria(Criteria.VPC_ID); + Object affinityGroupId = c.getCriteria(Criteria.AFFINITY_GROUP_ID); sb.and("displayName", sb.entity().getDisplayName(), SearchCriteria.Op.LIKE); sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ); @@ -739,6 +735,10 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sb.and("poolId", sb.entity().getPoolId(), SearchCriteria.Op.EQ); } + if (affinityGroupId != null) { + sb.and("affinityGroupId", sb.entity().getAffinityGroupId(), SearchCriteria.Op.EQ); + } + // populate the search criteria with the values passed in SearchCriteria sc = sb.create(); @@ -836,6 +836,10 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sc.setParameters("poolId", storageId); } + if (affinityGroupId != null) { + sc.setParameters("affinityGroupId", affinityGroupId); + } + // search vm details by ids Pair, Integer> uniqueVmPair = _userVmJoinDao.searchAndCount(sc, searchFilter); Integer count = uniqueVmPair.second(); @@ -1699,6 +1703,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { sb.and("typeNEQ", sb.entity().getType(), SearchCriteria.Op.NEQ); sb.and("idNEQ", sb.entity().getId(), SearchCriteria.Op.NEQ); + if (listForDomain && isRecursive) { sb.and("path", sb.entity().getDomainPath(), SearchCriteria.Op.LIKE); } @@ -1981,14 +1986,14 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { domainRecord = _domainDao.findById(domainRecord.getParent()); domainIds.add(domainRecord.getId()); } - + SearchCriteria spc = _diskOfferingJoinDao.createSearchCriteria(); spc.addOr("domainId", SearchCriteria.Op.IN, domainIds.toArray()); spc.addOr("domainId", SearchCriteria.Op.NULL); // include public offering as where sc.addAnd("domainId", SearchCriteria.Op.SC, spc); sc.addAnd("systemUse", SearchCriteria.Op.EQ, false); // non-root users should not see system offering at all - + } if (keyword != null) { @@ -2006,7 +2011,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { if (name != null) { sc.addAnd("name", SearchCriteria.Op.EQ, name); } - + // FIXME: disk offerings should search back up the hierarchy for // available disk offerings... /* @@ -2086,7 +2091,7 @@ public class QueryManagerImpl extends ManagerBase implements QueryService { // boolean includePublicOfferings = false; if ((caller.getType() == Account.ACCOUNT_TYPE_NORMAL || caller.getType() == Account.ACCOUNT_TYPE_DOMAIN_ADMIN) || caller.getType() == Account.ACCOUNT_TYPE_RESOURCE_DOMAIN_ADMIN) { - // For non-root users. + // For non-root users. if (isSystem) { throw new InvalidParameterValueException("Only root admins can access system's offering"); } diff --git a/server/src/com/cloud/api/query/ViewResponseHelper.java b/server/src/com/cloud/api/query/ViewResponseHelper.java index dc2727e8e0d..827ae7b7a66 100644 --- a/server/src/com/cloud/api/query/ViewResponseHelper.java +++ b/server/src/com/cloud/api/query/ViewResponseHelper.java @@ -30,6 +30,7 @@ import org.apache.cloudstack.api.response.DiskOfferingResponse; import org.apache.cloudstack.api.response.DomainRouterResponse; import org.apache.cloudstack.api.response.EventResponse; import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.response.HostForMigrationResponse; import org.apache.cloudstack.api.response.InstanceGroupResponse; import org.apache.cloudstack.api.response.ProjectAccountResponse; import org.apache.cloudstack.api.response.ProjectInvitationResponse; @@ -38,6 +39,7 @@ import org.apache.cloudstack.api.response.ResourceTagResponse; import org.apache.cloudstack.api.response.SecurityGroupResponse; import org.apache.cloudstack.api.response.ServiceOfferingResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; +import org.apache.cloudstack.api.response.StoragePoolForMigrationResponse; import org.apache.cloudstack.api.response.UserResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.api.response.VolumeResponse; @@ -230,6 +232,24 @@ public class ViewResponseHelper { return new ArrayList(vrDataList.values()); } + public static List createHostForMigrationResponse(EnumSet details, + HostJoinVO... hosts) { + Hashtable vrDataList = new Hashtable(); + // Initialise the vrdatalist with the input data + for (HostJoinVO vr : hosts) { + HostForMigrationResponse vrData = vrDataList.get(vr.getId()); + if ( vrData == null ) { + // first time encountering this vm + vrData = ApiDBUtils.newHostForMigrationResponse(vr, details); + } else { + // update tags + vrData = ApiDBUtils.fillHostForMigrationDetails(vrData, vr); + } + vrDataList.put(vr.getId(), vrData); + } + return new ArrayList(vrDataList.values()); + } + public static List createVolumeResponse(VolumeJoinVO... volumes) { Hashtable vrDataList = new Hashtable(); for (VolumeJoinVO vr : volumes) { @@ -265,6 +285,23 @@ public class ViewResponseHelper { return new ArrayList(vrDataList.values()); } + public static List createStoragePoolForMigrationResponse(StoragePoolJoinVO... pools) { + Hashtable vrDataList = new Hashtable(); + // Initialise the vrdatalist with the input data + for (StoragePoolJoinVO vr : pools) { + StoragePoolForMigrationResponse vrData = vrDataList.get(vr.getId()); + if ( vrData == null ) { + // first time encountering this vm + vrData = ApiDBUtils.newStoragePoolForMigrationResponse(vr); + } else { + // update tags + vrData = ApiDBUtils.fillStoragePoolForMigrationDetails(vrData, vr); + } + vrDataList.put(vr.getId(), vrData); + } + return new ArrayList(vrDataList.values()); + } + public static List createAccountResponse(AccountJoinVO... accounts) { List respList = new ArrayList(); diff --git a/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java index 51ac5e61edb..796ae54d52f 100644 --- a/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/AccountJoinDaoImpl.java @@ -20,17 +20,16 @@ import java.util.List; import javax.ejb.Local; +import org.apache.cloudstack.api.response.AccountResponse; +import org.apache.cloudstack.api.response.UserResponse; import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; import com.cloud.api.ApiDBUtils; import com.cloud.api.query.ViewResponseHelper; import com.cloud.api.query.vo.AccountJoinVO; import com.cloud.api.query.vo.UserAccountJoinVO; import com.cloud.configuration.Resource.ResourceType; -import org.apache.cloudstack.api.response.AccountResponse; -import org.apache.cloudstack.api.response.UserResponse; -import org.springframework.stereotype.Component; - import com.cloud.user.Account; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; @@ -66,6 +65,7 @@ public class AccountJoinDaoImpl extends GenericDaoBase impl accountResponse.setState(account.getState().toString()); accountResponse.setNetworkDomain(account.getNetworkDomain()); accountResponse.setDefaultZone(account.getDataCenterUuid()); + accountResponse.setIsDefault(account.isDefault()); // get network stat accountResponse.setBytesReceived(account.getBytesReceived()); diff --git a/server/src/com/cloud/api/query/dao/AffinityGroupJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/AffinityGroupJoinDaoImpl.java index a17679313d6..8743bcb2028 100644 --- a/server/src/com/cloud/api/query/dao/AffinityGroupJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/AffinityGroupJoinDaoImpl.java @@ -63,6 +63,7 @@ public class AffinityGroupJoinDaoImpl extends GenericDaoBase { HostResponse setHostResponse(HostResponse response, HostJoinVO host); + HostForMigrationResponse newHostForMigrationResponse(HostJoinVO host, EnumSet details); + + HostForMigrationResponse setHostForMigrationResponse(HostForMigrationResponse response, HostJoinVO host); + List newHostView(Host group); List searchByIds(Long... ids); diff --git a/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java index 1adff40d70f..77965290c8f 100644 --- a/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/HostJoinDaoImpl.java @@ -29,6 +29,7 @@ import javax.inject.Inject; import org.apache.cloudstack.api.ApiConstants.HostDetails; import org.apache.cloudstack.api.response.HostResponse; +import org.apache.cloudstack.api.response.HostForMigrationResponse; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -190,10 +191,6 @@ public class HostJoinDaoImpl extends GenericDaoBase implements } - - - - @Override public HostResponse setHostResponse(HostResponse response, HostJoinVO host) { String tag = host.getTag(); @@ -208,7 +205,137 @@ public class HostJoinDaoImpl extends GenericDaoBase implements return response; } + @Override + public HostForMigrationResponse newHostForMigrationResponse(HostJoinVO host, EnumSet details) { + HostForMigrationResponse hostResponse = new HostForMigrationResponse(); + hostResponse.setId(host.getUuid()); + hostResponse.setCapabilities(host.getCapabilities()); + hostResponse.setClusterId(host.getClusterUuid()); + hostResponse.setCpuNumber(host.getCpus()); + hostResponse.setZoneId(host.getZoneUuid()); + hostResponse.setDisconnectedOn(host.getDisconnectedOn()); + hostResponse.setHypervisor(host.getHypervisorType()); + hostResponse.setHostType(host.getType()); + hostResponse.setLastPinged(new Date(host.getLastPinged())); + hostResponse.setManagementServerId(host.getManagementServerId()); + hostResponse.setName(host.getName()); + hostResponse.setPodId(host.getPodUuid()); + hostResponse.setRemoved(host.getRemoved()); + hostResponse.setCpuSpeed(host.getSpeed()); + hostResponse.setState(host.getStatus()); + hostResponse.setIpAddress(host.getPrivateIpAddress()); + hostResponse.setVersion(host.getVersion()); + hostResponse.setCreated(host.getCreated()); + if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity) + || details.contains(HostDetails.stats) || details.contains(HostDetails.events)) { + + hostResponse.setOsCategoryId(host.getOsCategoryUuid()); + hostResponse.setOsCategoryName(host.getOsCategoryName()); + hostResponse.setZoneName(host.getZoneName()); + hostResponse.setPodName(host.getPodName()); + if ( host.getClusterId() > 0) { + hostResponse.setClusterName(host.getClusterName()); + hostResponse.setClusterType(host.getClusterType().toString()); + } + } + + DecimalFormat decimalFormat = new DecimalFormat("#.##"); + if (host.getType() == Host.Type.Routing) { + if (details.contains(HostDetails.all) || details.contains(HostDetails.capacity)) { + // set allocated capacities + Long mem = host.getMemReservedCapacity() + host.getMemUsedCapacity(); + Long cpu = host.getCpuReservedCapacity() + host.getCpuReservedCapacity(); + + hostResponse.setMemoryAllocated(mem); + hostResponse.setMemoryTotal(host.getTotalMemory()); + + String hostTags = host.getTag(); + hostResponse.setHostTags(host.getTag()); + + String haTag = ApiDBUtils.getHaTag(); + if (haTag != null && !haTag.isEmpty() && hostTags != null && !hostTags.isEmpty()) { + if (haTag.equalsIgnoreCase(hostTags)) { + hostResponse.setHaHost(true); + } else { + hostResponse.setHaHost(false); + } + } else { + hostResponse.setHaHost(false); + } + + hostResponse.setHypervisorVersion(host.getHypervisorVersion()); + + String cpuAlloc = decimalFormat.format(((float) cpu / (float) (host.getCpus() * host.getSpeed())) * 100f) + "%"; + hostResponse.setCpuAllocated(cpuAlloc); + String cpuWithOverprovisioning = new Float(host.getCpus() * host.getSpeed() * ApiDBUtils.getCpuOverprovisioningFactor()).toString(); + hostResponse.setCpuWithOverprovisioning(cpuWithOverprovisioning); + } + + if (details.contains(HostDetails.all) || details.contains(HostDetails.stats)) { + // set CPU/RAM/Network stats + String cpuUsed = null; + HostStats hostStats = ApiDBUtils.getHostStatistics(host.getId()); + if (hostStats != null) { + float cpuUtil = (float) hostStats.getCpuUtilization(); + cpuUsed = decimalFormat.format(cpuUtil) + "%"; + hostResponse.setCpuUsed(cpuUsed); + hostResponse.setMemoryUsed((new Double(hostStats.getUsedMemory())).longValue()); + hostResponse.setNetworkKbsRead((new Double(hostStats.getNetworkReadKBs())).longValue()); + hostResponse.setNetworkKbsWrite((new Double(hostStats.getNetworkWriteKBs())).longValue()); + + } + } + + } else if (host.getType() == Host.Type.SecondaryStorage) { + StorageStats secStorageStats = ApiDBUtils.getSecondaryStorageStatistics(host.getId()); + if (secStorageStats != null) { + hostResponse.setDiskSizeTotal(secStorageStats.getCapacityBytes()); + hostResponse.setDiskSizeAllocated(secStorageStats.getByteUsed()); + } + } + + hostResponse.setLocalStorageActive(ApiDBUtils.isLocalStorageActiveOnHost(host.getId())); + + if (details.contains(HostDetails.all) || details.contains(HostDetails.events)) { + Set possibleEvents = host.getStatus().getPossibleEvents(); + if ((possibleEvents != null) && !possibleEvents.isEmpty()) { + String events = ""; + Iterator iter = possibleEvents.iterator(); + while (iter.hasNext()) { + com.cloud.host.Status.Event event = iter.next(); + events += event.toString(); + if (iter.hasNext()) { + events += "; "; + } + } + hostResponse.setEvents(events); + } + } + + hostResponse.setResourceState(host.getResourceState().toString()); + + // set async job + hostResponse.setJobId(host.getJobUuid()); + hostResponse.setJobStatus(host.getJobStatus()); + + hostResponse.setObjectName("host"); + + return hostResponse; + } + + @Override + public HostForMigrationResponse setHostForMigrationResponse(HostForMigrationResponse response, HostJoinVO host) { + String tag = host.getTag(); + if (tag != null) { + if (response.getHostTags() != null && response.getHostTags().length() > 0) { + response.setHostTags(response.getHostTags() + "," + tag); + } else { + response.setHostTags(tag); + } + } + return response; + } @Override public List newHostView(Host host) { diff --git a/server/src/com/cloud/api/query/dao/StoragePoolJoinDao.java b/server/src/com/cloud/api/query/dao/StoragePoolJoinDao.java index bbb02428981..b7e467fd6d3 100644 --- a/server/src/com/cloud/api/query/dao/StoragePoolJoinDao.java +++ b/server/src/com/cloud/api/query/dao/StoragePoolJoinDao.java @@ -18,6 +18,7 @@ package com.cloud.api.query.dao; import java.util.List; +import org.apache.cloudstack.api.response.StoragePoolForMigrationResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import com.cloud.api.query.vo.StoragePoolJoinVO; @@ -30,6 +31,11 @@ public interface StoragePoolJoinDao extends GenericDao StoragePoolResponse setStoragePoolResponse(StoragePoolResponse response, StoragePoolJoinVO host); + StoragePoolForMigrationResponse newStoragePoolForMigrationResponse(StoragePoolJoinVO host); + + StoragePoolForMigrationResponse setStoragePoolForMigrationResponse(StoragePoolForMigrationResponse response, + StoragePoolJoinVO host); + List newStoragePoolView(StoragePool group); List searchByIds(Long... spIds); diff --git a/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java index 58968df2e56..34b88baa897 100644 --- a/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/StoragePoolJoinDaoImpl.java @@ -22,6 +22,7 @@ import java.util.List; import javax.ejb.Local; import javax.inject.Inject; +import org.apache.cloudstack.api.response.StoragePoolForMigrationResponse; import org.apache.cloudstack.api.response.StoragePoolResponse; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -108,10 +109,6 @@ public class StoragePoolJoinDaoImpl extends GenericDaoBase 0){ + response.setTags(response.getTags() + "," + tag); + } else { + response.setTags(tag); + } + } + return response; + } + @Override public List newStoragePoolView(StoragePool host) { SearchCriteria sc = spIdSearch.create(); diff --git a/server/src/com/cloud/api/query/dao/UserAccountJoinDaoImpl.java b/server/src/com/cloud/api/query/dao/UserAccountJoinDaoImpl.java index 7072324080d..43b3a2d0a1f 100644 --- a/server/src/com/cloud/api/query/dao/UserAccountJoinDaoImpl.java +++ b/server/src/com/cloud/api/query/dao/UserAccountJoinDaoImpl.java @@ -80,6 +80,7 @@ public class UserAccountJoinDaoImpl extends GenericDaoBase implem } userVmResponse.setZoneId(userVm.getDataCenterUuid()); userVmResponse.setZoneName(userVm.getDataCenterName()); + userVmResponse.setZoneType(userVm.getDataCenterType()); if ((caller == null) || (caller.getType() == Account.ACCOUNT_TYPE_ADMIN)) { userVmResponse.setInstanceName(userVm.getInstanceName()); userVmResponse.setHostId(userVm.getHostUuid()); diff --git a/server/src/com/cloud/api/query/vo/AccountJoinVO.java b/server/src/com/cloud/api/query/vo/AccountJoinVO.java index 1cb17ef688b..800da7803fd 100644 --- a/server/src/com/cloud/api/query/vo/AccountJoinVO.java +++ b/server/src/com/cloud/api/query/vo/AccountJoinVO.java @@ -184,6 +184,9 @@ public class AccountJoinVO extends BaseViewVO implements InternalIdentity, Ident @Column(name="job_status") private int jobStatus; + + @Column(name = "default") + boolean isDefault; public AccountJoinVO() { } @@ -672,6 +675,13 @@ public class AccountJoinVO extends BaseViewVO implements InternalIdentity, Ident } + public boolean isDefault() { + return isDefault; + } + public void setDefault(boolean isDefault) { + this.isDefault = isDefault; + } + } diff --git a/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java b/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java index e68996c53df..1c0dc2ccde0 100644 --- a/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java +++ b/server/src/com/cloud/api/query/vo/AffinityGroupJoinVO.java @@ -36,6 +36,9 @@ public class AffinityGroupJoinVO extends BaseViewVO implements ControlledViewEnt @Column(name="name") private String name; + @Column(name = "type") + private String type; + @Column(name = "description") private String description; @@ -114,6 +117,14 @@ public class AffinityGroupJoinVO extends BaseViewVO implements ControlledViewEnt this.name = name; } + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + @Override public long getAccountId() { return accountId; diff --git a/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java b/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java index 44637db3400..d85392fb85a 100644 --- a/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java +++ b/server/src/com/cloud/api/query/vo/UserAccountJoinVO.java @@ -23,12 +23,12 @@ import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; -import com.cloud.utils.db.Encrypt; -import com.cloud.utils.db.GenericDao; - import org.apache.cloudstack.api.Identity; import org.apache.cloudstack.api.InternalIdentity; +import com.cloud.utils.db.Encrypt; +import com.cloud.utils.db.GenericDao; + @Entity @Table(name="user_view") public class UserAccountJoinVO extends BaseViewVO implements InternalIdentity, Identity { @@ -116,6 +116,9 @@ public class UserAccountJoinVO extends BaseViewVO implements InternalIdentity, I @Column(name="job_status") private int jobStatus; + + @Column(name = "default") + boolean isDefault; public UserAccountJoinVO() { } @@ -345,6 +348,13 @@ public class UserAccountJoinVO extends BaseViewVO implements InternalIdentity, I this.jobStatus = jobStatus; } + public boolean isDefault() { + return isDefault; + } + public void setDefault(boolean isDefault) { + this.isDefault = isDefault; + } + } diff --git a/server/src/com/cloud/api/query/vo/UserVmJoinVO.java b/server/src/com/cloud/api/query/vo/UserVmJoinVO.java index 8d1314eafae..a50906d9e3d 100644 --- a/server/src/com/cloud/api/query/vo/UserVmJoinVO.java +++ b/server/src/com/cloud/api/query/vo/UserVmJoinVO.java @@ -153,6 +153,9 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity { @Column(name="data_center_name") private String dataCenterName = null; + @Column(name="data_center_type") + private String dataCenterType = null; + @Column(name="security_group_enabled") private boolean securityGroupEnabled; @@ -800,8 +803,18 @@ public class UserVmJoinVO extends BaseViewVO implements ControlledViewEntity { public void setDataCenterName(String zoneName) { this.dataCenterName = zoneName; } + + + public String getDataCenterType() { + return dataCenterType; + } + public void setDataCenterType(String zoneType) { + this.dataCenterType = zoneType; + } + + public boolean isSecurityGroupEnabled() { return securityGroupEnabled; } diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index e3e305350b1..4d1185a973b 100755 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -16,9 +16,7 @@ // under the License. package com.cloud.configuration; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; +import java.util.*; import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; @@ -196,7 +194,7 @@ public enum Config { CPUOverprovisioningFactor("Advanced", ManagementServer.class, String.class, "cpu.overprovisioning.factor", "1", "Used for CPU overprovisioning calculation; available CPU will be (actualCpuCapacity * cpu.overprovisioning.factor)", null), MemOverprovisioningFactor("Advanced", ManagementServer.class, String.class, "mem.overprovisioning.factor", "1", "Used for memory overprovisioning calculation", null), LinkLocalIpNums("Advanced", ManagementServer.class, Integer.class, "linkLocalIp.nums", "10", "The number of link local ip that needed by domR(in power of 2)", null), - HypervisorList("Advanced", ManagementServer.class, String.class, "hypervisor.list", HypervisorType.KVM + "," + HypervisorType.XenServer + "," + HypervisorType.VMware + "," + HypervisorType.BareMetal + "," + HypervisorType.Ovm, "The list of hypervisors that this deployment will use.", "hypervisorList"), + HypervisorList("Advanced", ManagementServer.class, String.class, "hypervisor.list", HypervisorType.KVM + "," + HypervisorType.XenServer + "," + HypervisorType.VMware + "," + HypervisorType.BareMetal + "," + HypervisorType.Ovm + "," + HypervisorType.LXC, "The list of hypervisors that this deployment will use.", "hypervisorList"), ManagementHostIPAdr("Advanced", ManagementServer.class, String.class, "host", "localhost", "The ip address of management server", null), ManagementNetwork("Advanced", ManagementServer.class, String.class, "management.network.cidr", null, "The cidr of management server network", null), EventPurgeDelay("Advanced", ManagementServer.class, Integer.class, "event.purge.delay", "15", "Events older than specified number days will be purged. Set this value to 0 to never delete events", null), @@ -305,6 +303,8 @@ public enum Config { SSOAuthTolerance("Advanced", ManagementServer.class, Long.class, "security.singlesignon.tolerance.millis", "300000", "The allowable clock difference in milliseconds between when an SSO login request is made and when it is received.", null), //NetworkType("Hidden", ManagementServer.class, String.class, "network.type", "vlan", "The type of network that this deployment will use.", "vlan,direct"), HashKey("Hidden", ManagementServer.class, String.class, "security.hash.key", null, "for generic key-ed hash", null), + EncryptionKey("Hidden", ManagementServer.class, String.class, "security.encryption.key", null, "base64 encoded key data", null), + EncryptionIV("Hidden", ManagementServer.class, String.class, "security.encryption.iv", null, "base64 encoded IV data", null), RouterRamSize("Hidden", NetworkManager.class, Integer.class, "router.ram.size", "128", "Default RAM for router VM (in MB).", null), VmOpWaitInterval("Advanced", ManagementServer.class, Integer.class, "vm.op.wait.interval", "120", "Time (in seconds) to wait before checking if a previous operation has succeeded", null), @@ -337,7 +337,7 @@ public enum Config { //disabling lb as cluster sync does not work with distributed cluster AgentLbEnable("Advanced", ManagementServer.class, Boolean.class, "agent.lb.enabled", "false", "If agent load balancing enabled in cluster setup", null), SubDomainNetworkAccess("Advanced", NetworkManager.class, Boolean.class, "allow.subdomain.network.access", "true", "Allow subdomains to use networks dedicated to their parent domain(s)", null), - UseExternalDnsServers("Advanced", NetworkManager.class, Boolean.class, "use.external.dns", "false", "Bypass internal dns, use external dns1 and dns2", null), + UseExternalDnsServers("Advanced", NetworkManager.class, Boolean.class, "use.external.dns", "false", "Bypass internal dns, use external dns1 and dns2", null, ConfigurationParameterScope.zone.toString()), EncodeApiResponse("Advanced", ManagementServer.class, Boolean.class, "encode.api.response", "false", "Do URL encoding for the api response, false by default", null), DnsBasicZoneUpdates("Advanced", NetworkManager.class, String.class, "network.dns.basiczone.updates", "all", "This parameter can take 2 values: all (default) and pod. It defines if DHCP/DNS requests have to be send to all dhcp servers in cloudstack, or only to the one in the same pod", "all,pod"), @@ -410,6 +410,35 @@ public enum Config { private final String _defaultValue; private final String _description; private final String _range; + private final String _scope; // Parameter can be at different levels (Zone/cluster/pool/account), by default every parameter is at global + + public static enum ConfigurationParameterScope { + global, + zone, + cluster, + pool, + account + } + + private static final HashMap> _scopeLevelConfigsMap = new HashMap>(); + static { + _scopeLevelConfigsMap.put(ConfigurationParameterScope.zone.toString(), new ArrayList()); + _scopeLevelConfigsMap.put(ConfigurationParameterScope.cluster.toString(), new ArrayList()); + _scopeLevelConfigsMap.put(ConfigurationParameterScope.pool.toString(), new ArrayList()); + _scopeLevelConfigsMap.put(ConfigurationParameterScope.account.toString(), new ArrayList()); + _scopeLevelConfigsMap.put(ConfigurationParameterScope.global.toString(), new ArrayList()); + + for (Config c : Config.values()) { + //Creating group of parameters per each level (zone/cluster/pool/account) + StringTokenizer tokens = new StringTokenizer(c.getScope(), ","); + while (tokens.hasMoreTokens()) { + String scope = tokens.nextToken().trim(); + List currentConfigs = _scopeLevelConfigsMap.get(scope); + currentConfigs.add(c); + _scopeLevelConfigsMap.put(scope, currentConfigs); + } + } + } private static final HashMap> _configs = new HashMap>(); static { @@ -445,6 +474,17 @@ public enum Config { _defaultValue = defaultValue; _description = description; _range = range; + _scope = ConfigurationParameterScope.global.toString(); + } + private Config(String category, Class componentClass, Class type, String name, String defaultValue, String description, String range, String scope) { + _category = category; + _componentClass = componentClass; + _type = type; + _name = name; + _defaultValue = defaultValue; + _description = description; + _range = range; + _scope = scope; } public String getCategory() { @@ -471,6 +511,10 @@ public enum Config { return _componentClass; } + public String getScope() { + return _scope; + } + public String getComponent() { if (_componentClass == ManagementServer.class) { return "management-server"; @@ -528,4 +572,8 @@ public enum Config { } return categories; } + + public static List getConfigListByScope(String scope) { + return _scopeLevelConfigsMap.get(scope); + } } diff --git a/server/src/com/cloud/configuration/ConfigurationManager.java b/server/src/com/cloud/configuration/ConfigurationManager.java index d7faf19fd28..738c5bab35d 100755 --- a/server/src/com/cloud/configuration/ConfigurationManager.java +++ b/server/src/com/cloud/configuration/ConfigurationManager.java @@ -60,7 +60,7 @@ public interface ConfigurationManager extends ConfigurationService, Manager { * @param name * @param value */ - void updateConfiguration(long userId, String name, String category, String value); + void updateConfiguration(long userId, String name, String category, String value, String scope, Long id); /** * Creates a new service offering @@ -79,11 +79,10 @@ public interface ConfigurationManager extends ConfigurationService, Manager { * TODO * @param id * @param useVirtualNetwork - * @param deploymentPlanner * @return ID */ ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, VirtualMachine.Type vm_typeType, String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired, - boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner); + boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate); /** * Creates a new disk offering diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 5b6d81e8df8..b5734a290ce 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -39,6 +39,7 @@ import javax.naming.NamingException; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; +import com.cloud.dc.dao.*; import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.api.ApiConstants.LDAPParams; import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; @@ -78,20 +79,13 @@ import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.DataCenterIpAddressVO; import com.cloud.dc.DataCenterLinkLocalIpAddressVO; import com.cloud.dc.DataCenterVO; +import com.cloud.dc.DcDetailVO; import com.cloud.dc.HostPodVO; import com.cloud.dc.Pod; import com.cloud.dc.PodVlanMapVO; import com.cloud.dc.Vlan; import com.cloud.dc.Vlan.VlanType; import com.cloud.dc.VlanVO; -import com.cloud.dc.dao.AccountVlanMapDao; -import com.cloud.dc.dao.ClusterDao; -import com.cloud.dc.dao.DataCenterDao; -import com.cloud.dc.dao.DataCenterIpAddressDao; -import com.cloud.dc.dao.DataCenterLinkLocalIpAddressDao; -import com.cloud.dc.dao.HostPodDao; -import com.cloud.dc.dao.PodVlanMapDao; -import com.cloud.dc.dao.VlanDao; import com.cloud.deploy.DataCenterDeployment; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; @@ -188,6 +182,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Inject DataCenterDao _zoneDao; @Inject + DcDetailsDao _zoneDetailsDao; + @Inject DomainDao _domainDao; @Inject SwiftDao _swiftDao; @@ -327,15 +323,37 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override @DB - public void updateConfiguration(long userId, String name, String category, String value) { + public void updateConfiguration(long userId, String name, String category, String value, String scope, Long resourceId) { - String validationMsg = validateConfigurationValue(name, value); + String validationMsg = validateConfigurationValue(name, value, scope); if (validationMsg != null) { s_logger.error("Invalid configuration option, name: " + name + ", value:" + value); throw new InvalidParameterValueException(validationMsg); } + // If scope of the parameter is given then it needs to be updated in the corresponding details table, + // if scope is mentioned as global or not mentioned then it is normal global parameter updation + if (scope != null && !scope.isEmpty() && !Config.ConfigurationParameterScope.global.toString().equalsIgnoreCase(scope)) { + if (Config.ConfigurationParameterScope.zone.toString().equalsIgnoreCase(scope)) { + DataCenterVO zone = _zoneDao.findById(resourceId); + if (zone == null) { + throw new InvalidParameterValueException("unable to find zone by id " + resourceId); + } + DcDetailVO dcDetailVO = _zoneDetailsDao.findDetail(resourceId, name.toLowerCase()); + if (dcDetailVO == null) { + dcDetailVO = new DcDetailVO(dcDetailVO.getId(), name, value); + _zoneDetailsDao.persist(dcDetailVO); + } else { + dcDetailVO.setValue(value); + _zoneDetailsDao.update(resourceId, dcDetailVO); + } + } else { + s_logger.error("TO Do for the remaining levels (cluster/pool/account)"); + throw new InvalidParameterValueException("The scope "+ scope +" yet to be implemented"); + } + } + // Execute all updates in a single transaction Transaction txn = Transaction.currentTxn(); txn.start(); @@ -440,6 +458,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati Long userId = UserContext.current().getCallerUserId(); String name = cmd.getCfgName(); String value = cmd.getValue(); + String scope = cmd.getScope(); + Long id = cmd.getId(); UserContext.current().setEventDetails(" Name: " + name + " New Value: " + (((name.toLowerCase()).contains("password")) ? "*****" : (((value == null) ? "" : value)))); // check if config value exists @@ -456,7 +476,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati value = null; } - updateConfiguration(userId, name, config.getCategory(), value); + updateConfiguration(userId, name, config.getCategory(), value, scope, id); String updatedValue = _configDao.getValue(name); if ((value == null && updatedValue == null) || updatedValue.equalsIgnoreCase(value)) { return _configDao.findByName(name); @@ -466,13 +486,20 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } - private String validateConfigurationValue(String name, String value) { + private String validateConfigurationValue(String name, String value, String scope) { Config c = Config.getConfig(name); if (c == null) { s_logger.error("Missing configuration variable " + name + " in configuration table"); return "Invalid configuration variable."; } + String configScope = c.getScope(); + if (scope != null && !scope.isEmpty()) { + if (!configScope.contains(scope)) { + s_logger.error("Invalid scope " + scope + " for the parameter " + name); + return "Invalid scope for the parameter."; + } + } Class type = c.getType(); @@ -1823,16 +1850,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } return createServiceOffering(userId, cmd.getIsSystem(), vmType, cmd.getServiceOfferingName(), cpuNumber.intValue(), memory.intValue(), cpuSpeed.intValue(), cmd.getDisplayText(), - localStorageRequired, offerHA, limitCpuUse, volatileVm, cmd.getTags(), cmd.getDomainId(), cmd.getHostTag(), cmd.getNetworkRate(), cmd.getDeploymentPlanner()); + localStorageRequired, offerHA, limitCpuUse, volatileVm, cmd.getTags(), cmd.getDomainId(), cmd.getHostTag(), cmd.getNetworkRate()); } @Override @ActionEvent(eventType = EventTypes.EVENT_SERVICE_OFFERING_CREATE, eventDescription = "creating service offering") public ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, VirtualMachine.Type vm_type, String name, int cpu, int ramSize, int speed, String displayText, - boolean localStorageRequired, boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner) { + boolean localStorageRequired, boolean offerHA, boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate) { tags = cleanupTags(tags); ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, speed, networkRate, null, offerHA, limitResourceUse, volatileVm, displayText, localStorageRequired, false, tags, isSystem, vm_type, - domainId, hostTag, deploymentPlanner); + domainId, hostTag); if ((offering = _serviceOfferingDao.persist(offering)) != null) { UserContext.current().setEventDetails("Service offering id=" + offering.getId()); @@ -2154,6 +2181,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati vlanOwner = _accountDao.findActiveAccount(accountName, domainId); if (vlanOwner == null) { throw new InvalidParameterValueException("Please specify a valid account."); + } else if (vlanOwner.getId() == Account.ACCOUNT_ID_SYSTEM) { + // by default vlan is dedicated to system account + vlanOwner = null; } } @@ -2630,7 +2660,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (vlan == null) { throw new CloudRuntimeException("Unable to acquire vlan configuration: " + vlanDbId); } - + if (s_logger.isDebugEnabled()) { s_logger.debug("lock vlan " + vlanDbId + " is acquired"); } @@ -2643,9 +2673,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati " as ip " + ip + " belonging to the range is used for static nat purposes. Cleanup the rules first"); } - if (ip.isSourceNat() && _networkModel.getNetwork(ip.getAssociatedWithNetworkId()) != null) { - throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId + - " as ip " + ip + " belonging to the range is a source nat ip for the network id=" + ip.getSourceNetworkId() + + if (ip.isSourceNat()) { + throw new InvalidParameterValueException("Can't delete account specific vlan " + vlanDbId + + " as ip " + ip + " belonging to the range is a source nat ip for the network id=" + ip.getSourceNetworkId() + ". IP range with the source nat ip address can be removed either as a part of Network, or account removal"); } @@ -2705,14 +2735,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if ((accountName != null) && (domainId != null)) { vlanOwner = _accountDao.findActiveAccount(accountName, domainId); if (vlanOwner == null) { - throw new InvalidParameterValueException("Please specify a valid account"); + throw new InvalidParameterValueException("Unable to find account by name " + accountName); + } else if (vlanOwner.getId() == Account.ACCOUNT_ID_SYSTEM) { + throw new InvalidParameterValueException("Please specify a valid account. Cannot dedicate IP range to system account"); } } // Check if range is valid VlanVO vlan = _vlanDao.findById(vlanDbId); if (vlan == null) { - throw new InvalidParameterValueException("Please specify a valid Public IP range id"); + throw new InvalidParameterValueException("Unable to find vlan by id " + vlanDbId); } // Check if range has already been dedicated @@ -2742,7 +2774,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati if (allocatedToAccountId != null) { Account accountAllocatedTo = _accountMgr.getActiveAccountById(allocatedToAccountId); if (!accountAllocatedTo.getAccountName().equalsIgnoreCase(accountName)) - throw new InvalidParameterValueException("Public IP address in range is already allocated to another account"); + throw new InvalidParameterValueException(ip.getAddress() + " Public IP address in range is allocated to another account "); } } @@ -2797,8 +2829,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati List ips = _publicIpAddressDao.listByVlanId(vlanDbId); for (IPAddressVO ip : ips) { // Disassociate allocated IP's that are not in use - if ( !ip.isOneToOneNat() && !(ip.isSourceNat() && _networkModel.getNetwork(ip.getAssociatedWithNetworkId()) != null) && - !(_firewallDao.countRulesByIpId(ip.getId()) > 0) ) { + if ( !ip.isOneToOneNat() && !ip.isSourceNat() && !(_firewallDao.countRulesByIpId(ip.getId()) > 0) ) { if (s_logger.isDebugEnabled()) { s_logger.debug("Releasing Public IP addresses" + ip +" of vlan " + vlanDbId + " as part of Public IP" + " range release to the system pool"); @@ -3433,20 +3464,34 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati void validateStaticNatServiceCapablities(Map staticNatServiceCapabilityMap) { if (staticNatServiceCapabilityMap != null && !staticNatServiceCapabilityMap.isEmpty()) { - if (staticNatServiceCapabilityMap.keySet().size() > 1) { - throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " capability can be specified for static nat service"); + if (staticNatServiceCapabilityMap.keySet().size() > 2) { + throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " and " + Capability.AssociatePublicIP.getName() + " capabilitiy can be sepcified for static nat service"); } + boolean eipEnabled = false; + boolean eipDisabled = false; + boolean associatePublicIP = true; for (Capability capability : staticNatServiceCapabilityMap.keySet()) { String value = staticNatServiceCapabilityMap.get(capability); if (capability == Capability.ElasticIp) { - boolean enabled = value.contains("true"); - boolean disabled = value.contains("false"); - if (!enabled && !disabled) { + eipEnabled = value.contains("true"); + eipDisabled = value.contains("false"); + if (!eipEnabled && !eipDisabled) { throw new InvalidParameterValueException("Unknown specified value for " + Capability.ElasticIp.getName()); } + } else if (capability == Capability.AssociatePublicIP) { + if (value.contains("true")) { + associatePublicIP = true; + } else if (value.contains("false")) { + associatePublicIP = false; + } else { + throw new InvalidParameterValueException("Unknown specified value for " + Capability.AssociatePublicIP.getName()); + } } else { - throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " capability can be specified for static nat service"); + throw new InvalidParameterValueException("Only " + Capability.ElasticIp.getName() + " and " + Capability.AssociatePublicIP.getName() + " capabilitiy can be sepcified for static nat service"); + } + if (eipDisabled && associatePublicIP) { + throw new InvalidParameterValueException("Capability " + Capability.AssociatePublicIP.getName() + " can only be set when capability " + Capability.ElasticIp.getName() + " is true"); } } } @@ -3508,6 +3553,7 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati boolean sharedSourceNat = false; boolean redundantRouter = false; boolean elasticIp = false; + boolean associatePublicIp = false; boolean inline = false; if (serviceCapabilityMap != null && !serviceCapabilityMap.isEmpty()) { Map lbServiceCapabilityMap = serviceCapabilityMap.get(Service.Lb); @@ -3557,13 +3603,17 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati String param = staticNatServiceCapabilityMap.get(Capability.ElasticIp); if (param != null) { elasticIp = param.contains("true"); + String associatePublicIP = staticNatServiceCapabilityMap.get(Capability.AssociatePublicIP); + if (associatePublicIP != null) { + associatePublicIp = associatePublicIP.contains("true"); + } } } } NetworkOfferingVO offering = new NetworkOfferingVO(name, displayText, trafficType, systemOnly, specifyVlan, networkRate, multicastRate, isDefault, availability, tags, type, conserveMode, dedicatedLb, - sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline, isPersistent); + sharedSourceNat, redundantRouter, elasticIp, elasticLb, specifyIpRanges, inline, isPersistent, associatePublicIp); if (serviceOfferingId != null) { offering.setServiceOfferingId(serviceOfferingId); diff --git a/server/src/com/cloud/configuration/dao/ConfigurationDao.java b/server/src/com/cloud/configuration/dao/ConfigurationDao.java index c86c0243fae..2b099013430 100644 --- a/server/src/com/cloud/configuration/dao/ConfigurationDao.java +++ b/server/src/com/cloud/configuration/dao/ConfigurationDao.java @@ -17,6 +17,7 @@ package com.cloud.configuration.dao; import java.util.Map; +import java.util.List; import com.cloud.configuration.ConfigurationVO; import com.cloud.utils.db.GenericDao; diff --git a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java index ff6e64eca94..df53e0d7d81 100755 --- a/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java +++ b/server/src/com/cloud/consoleproxy/AgentBasedConsoleProxyManager.java @@ -33,6 +33,7 @@ import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.info.ConsoleProxyInfo; import com.cloud.keystore.KeystoreManager; +import com.cloud.server.ManagementServer; import com.cloud.utils.NumbersUtil; import com.cloud.utils.component.ManagerBase; import com.cloud.vm.ConsoleProxyVO; @@ -69,12 +70,13 @@ public class AgentBasedConsoleProxyManager extends ManagerBase implements Consol protected KeystoreManager _ksMgr; @Inject ConfigurationDao _configDao; + @Inject ManagementServer _ms; public class AgentBasedAgentHook extends AgentHookBase { public AgentBasedAgentHook(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, - KeystoreManager ksMgr, AgentManager agentMgr) { - super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr); + KeystoreManager ksMgr, AgentManager agentMgr, ManagementServer ms) { + super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr, ms); } @Override @@ -120,7 +122,7 @@ public class AgentBasedConsoleProxyManager extends ManagerBase implements Consol _consoleProxyUrlDomain = configs.get("consoleproxy.url.domain"); _listener = - new ConsoleProxyListener(new AgentBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr, _agentMgr)); + new ConsoleProxyListener(new AgentBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr, _agentMgr, _ms)); _agentMgr.registerForHostEvents(_listener, true, true, false); if (s_logger.isInfoEnabled()) { diff --git a/server/src/com/cloud/consoleproxy/AgentHookBase.java b/server/src/com/cloud/consoleproxy/AgentHookBase.java index b969f6da2ce..2748a8cb68c 100644 --- a/server/src/com/cloud/consoleproxy/AgentHookBase.java +++ b/server/src/com/cloud/consoleproxy/AgentHookBase.java @@ -42,10 +42,14 @@ import com.cloud.host.HostVO; import com.cloud.host.Status; import com.cloud.host.dao.HostDao; import com.cloud.keystore.KeystoreManager; +import com.cloud.server.ManagementServer; +import com.cloud.servlet.ConsoleProxyPasswordBasedEncryptor; import com.cloud.servlet.ConsoleProxyServlet; import com.cloud.utils.Ternary; import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.VMInstanceDao; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; /** * Utility class to manage interactions with agent-based console access @@ -60,28 +64,19 @@ public abstract class AgentHookBase implements AgentHook { ConfigurationDao _configDao; AgentManager _agentMgr; KeystoreManager _ksMgr; + ManagementServer _ms; final Random _random = new Random(System.currentTimeMillis()); private String _hashKey; public AgentHookBase(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, KeystoreManager ksMgr, - AgentManager agentMgr) { + AgentManager agentMgr, ManagementServer ms) { this._instanceDao = instanceDao; this._hostDao = hostDao; this._agentMgr = agentMgr; this._configDao = cfgDao; this._ksMgr = ksMgr; - } - - public String getHashKey() { - // although we may have race condition here, database transaction - // serialization should give us the same key - if (_hashKey == null) { - _hashKey = - _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), Config.HashKey.getCategory(), UUID - .randomUUID().toString()); - } - return _hashKey; + this._ms = ms; } public AgentControlAnswer onConsoleAccessAuthentication(ConsoleAccessAuthenticationCommand cmd) { @@ -212,10 +207,10 @@ public abstract class AgentHookBase implements AgentHook { s_logger.error("Could not find and construct a valid SSL certificate"); } cmd = new StartConsoleProxyAgentHttpHandlerCommand(ksBits, storePassword); - cmd.setEncryptorPassword(getHashKey()); + cmd.setEncryptorPassword(getEncryptorPassword()); } else { cmd = new StartConsoleProxyAgentHttpHandlerCommand(); - cmd.setEncryptorPassword(getHashKey()); + cmd.setEncryptorPassword(getEncryptorPassword()); } try { @@ -246,6 +241,33 @@ public abstract class AgentHookBase implements AgentHook { + startupCmd.getProxyVmId(), e); } } + + private String getEncryptorPassword() { + String key; + String iv; + ConsoleProxyPasswordBasedEncryptor.KeyIVPair keyIvPair = null; + + // if we failed after reset, something is definitely wrong + for(int i = 0; i < 2; i++) { + key = _ms.getEncryptionKey(); + iv = _ms.getEncryptionIV(); + + keyIvPair = new ConsoleProxyPasswordBasedEncryptor.KeyIVPair(key, iv); + + if(keyIvPair.getIvBytes() == null || keyIvPair.getIvBytes().length != 16 || + keyIvPair.getKeyBytes() == null || keyIvPair.getKeyBytes().length != 16) { + + s_logger.warn("Console access AES KeyIV sanity check failed, reset and regenerate"); + _ms.resetEncryptionKeyIV(); + } else { + break; + } + } + + Gson gson = new GsonBuilder().create(); + return gson.toJson(keyIvPair); + } + protected abstract HostVO findConsoleProxyHost(StartupProxyCommand cmd); diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index 9740d28a94f..c4ad8170d6d 100755 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -95,8 +95,10 @@ import com.cloud.resource.ResourceManager; import com.cloud.resource.ResourceStateAdapter; import com.cloud.resource.ServerResource; import com.cloud.resource.UnableDeleteHostException; +import com.cloud.server.ManagementServer; import com.cloud.service.ServiceOfferingVO; import com.cloud.service.dao.ServiceOfferingDao; +import com.cloud.servlet.ConsoleProxyPasswordBasedEncryptor; import com.cloud.storage.StorageManager; import com.cloud.storage.StoragePoolStatus; import com.cloud.storage.VMTemplateHostVO; @@ -220,6 +222,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy TemplateManager templateMgr; @Inject IPAddressDao _ipAddressDao; + @Inject + ManagementServer _ms; private ConsoleProxyListener _listener; @@ -254,7 +258,6 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy private Map _zoneProxyCountMap; // map private Map _zoneVmCountMap; // map - private String _hashKey; private String _staticPublicIp; private int _staticPort; @@ -448,8 +451,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy public class VmBasedAgentHook extends AgentHookBase { public VmBasedAgentHook(VMInstanceDao instanceDao, HostDao hostDao, ConfigurationDao cfgDao, - KeystoreManager ksMgr, AgentManager agentMgr) { - super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr); + KeystoreManager ksMgr, AgentManager agentMgr, ManagementServer ms) { + super(instanceDao, hostDao, cfgDao, ksMgr, agentMgr, ms); } @Override @@ -1439,7 +1442,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy _listener = new ConsoleProxyListener(new VmBasedAgentHook(_instanceDao, _hostDao, _configDao, _ksMgr, - _agentMgr)); + _agentMgr, _ms)); _agentMgr.registerForHostEvents(_listener, true, true, false); _itMgr.registerGuru(VirtualMachine.Type.ConsoleProxy, this); @@ -1884,15 +1887,6 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy return sc.find(); } - public String getHashKey() { - // although we may have race conditioning here, database transaction serialization should - // give us the same key - if (_hashKey == null) { - _hashKey = _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), Config.HashKey.getCategory(), UUID.randomUUID().toString()); - } - return _hashKey; - } - @Override public boolean plugNic(Network network, NicTO nic, VirtualMachineTO vm, ReservationContext context, DeployDestination dest) throws ConcurrentOperationException, ResourceUnavailableException, @@ -1912,4 +1906,5 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy @Override public void prepareStop(VirtualMachineProfile profile) { } + } diff --git a/server/src/com/cloud/dc/dao/DataCenterVnetDao.java b/server/src/com/cloud/dc/dao/DataCenterVnetDao.java index 79e91c4bca8..7fb68dcd7ac 100644 --- a/server/src/com/cloud/dc/dao/DataCenterVnetDao.java +++ b/server/src/com/cloud/dc/dao/DataCenterVnetDao.java @@ -20,9 +20,11 @@ import java.util.List; import com.cloud.dc.DataCenterVnetVO; import com.cloud.utils.db.GenericDao; +import com.cloud.utils.db.Transaction; public interface DataCenterVnetDao extends GenericDao { public List listAllocatedVnets(long physicalNetworkId); + public List listAllocatedVnetsInRange(long dcId, long physicalNetworkId, Integer start, Integer end); public List findVnet(long dcId, String vnet); public int countZoneVlans(long dcId, boolean onlyCountAllocated); public List findVnet(long dcId, long physicalNetworkId, String vnet); @@ -31,6 +33,10 @@ public interface DataCenterVnetDao extends GenericDao { public void delete(long physicalNetworkId); + public void deleteRange(Transaction txn, long dcId, long physicalNetworkId, int start, int end); + + public void lockRange(long dcId, long physicalNetworkId, Integer start, Integer end); + public DataCenterVnetVO take(long physicalNetworkId, long accountId, String reservationId); public void release(String vnet, long physicalNetworkId, long accountId, String reservationId); diff --git a/server/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java b/server/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java index 5ded0f4ecf5..2e044394ddc 100755 --- a/server/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java +++ b/server/src/com/cloud/dc/dao/DataCenterVnetDaoImpl.java @@ -21,6 +21,7 @@ import java.sql.SQLException; import java.util.Date; import java.util.List; +import com.cloud.exception.InvalidParameterValueException; import org.springframework.stereotype.Component; import com.cloud.dc.DataCenterVnetVO; @@ -46,8 +47,10 @@ public class DataCenterVnetDaoImpl extends GenericDaoBase VnetDcSearch; private final SearchBuilder VnetDcSearchAllocated; private final SearchBuilder DcSearchAllocated; + private final SearchBuilder DcSearchAllocatedInRange; private final GenericSearchBuilder countZoneVlans; private final GenericSearchBuilder countAllocatedZoneVlans; + private final SearchBuilder SearchRange; public List listAllocatedVnets(long physicalNetworkId) { SearchCriteria sc = DcSearchAllocated.create(); @@ -55,6 +58,22 @@ public class DataCenterVnetDaoImpl extends GenericDaoBase listAllocatedVnetsInRange(long dcId, long physicalNetworkId, Integer start, Integer end) { + SearchCriteria sc = DcSearchAllocatedInRange.create(); + sc.setParameters("dc",dcId); + sc.setParameters("physicalNetworkId", physicalNetworkId); + sc.setParameters("vnetRange", start.toString(), end.toString()); + return listBy(sc); + } + + public void lockRange(long dcId, long physicalNetworkId, Integer start, Integer end) { + SearchCriteria sc = SearchRange.create(); + sc.setParameters("dc",dcId); + sc.setParameters("physicalNetworkId", physicalNetworkId); + sc.setParameters("vnetRange", start.toString(), end.toString()); + lockRows(sc,null,true); + } + public List findVnet(long dcId, String vnet) { SearchCriteria sc = VnetDcSearch.create();; sc.setParameters("dc", dcId); @@ -93,11 +112,28 @@ public class DataCenterVnetDaoImpl extends GenericDaoBase sc = VnetDcSearch.create(); sc.setParameters("physicalNetworkId", physicalNetworkId); @@ -149,6 +185,18 @@ public class DataCenterVnetDaoImpl extends GenericDaoBase { List listVlansByNetworkId(long networkId); List listVlansByPhysicalNetworkId(long physicalNetworkId); + + List listZoneWideNonDedicatedVlans(long zoneId); } diff --git a/server/src/com/cloud/dc/dao/VlanDaoImpl.java b/server/src/com/cloud/dc/dao/VlanDaoImpl.java old mode 100644 new mode 100755 index c5a635fd0c0..100295b4b5f --- a/server/src/com/cloud/dc/dao/VlanDaoImpl.java +++ b/server/src/com/cloud/dc/dao/VlanDaoImpl.java @@ -58,6 +58,9 @@ public class VlanDaoImpl extends GenericDaoBase implements VlanDao protected SearchBuilder ZoneVlanSearch; protected SearchBuilder NetworkVlanSearch; protected SearchBuilder PhysicalNetworkVlanSearch; + protected SearchBuilder ZoneWideNonDedicatedVlanSearch; + + protected SearchBuilder AccountVlanMapSearch; @Inject protected PodVlanMapDao _podVlanMapDao; @Inject protected AccountVlanMapDao _accountVlanMapDao; @@ -198,6 +201,14 @@ public class VlanDaoImpl extends GenericDaoBase implements VlanDao PodVlanSearch2.done(); ZoneTypePodSearch.done(); + ZoneWideNonDedicatedVlanSearch = createSearchBuilder(); + ZoneWideNonDedicatedVlanSearch.and("zoneId", ZoneWideNonDedicatedVlanSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ); + AccountVlanMapSearch = _accountVlanMapDao.createSearchBuilder(); + AccountVlanMapSearch.and("accountId", AccountVlanMapSearch.entity().getAccountId(), SearchCriteria.Op.NULL); + ZoneWideNonDedicatedVlanSearch.join("AccountVlanMapSearch", AccountVlanMapSearch, ZoneWideNonDedicatedVlanSearch.entity().getId(), AccountVlanMapSearch.entity().getVlanDbId(), JoinBuilder.JoinType.LEFTOUTER); + ZoneWideNonDedicatedVlanSearch.done(); + AccountVlanMapSearch.done(); + return result; } @@ -312,4 +323,12 @@ public class VlanDaoImpl extends GenericDaoBase implements VlanDao sc.setParameters("physicalNetworkId", physicalNetworkId); return listBy(sc); } + + @Override + public List listZoneWideNonDedicatedVlans(long zoneId) { + SearchCriteria sc = ZoneWideNonDedicatedVlanSearch.create(); + sc.setParameters("ZoneWideNonDedicatedVlanSearch", "zoneId", zoneId); + return listBy(sc); + } + } diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java index 92aac3775a1..c7162a2003f 100644 --- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java +++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java @@ -50,11 +50,21 @@ public class DeploymentPlanningManagerImpl extends ManagerBase implements Deploy @Inject protected AffinityGroupVMMapDao _affinityGroupVMMapDao; - @Inject protected List _planners; + public List getPlanners() { + return _planners; + } + public void setPlanners(List _planners) { + this._planners = _planners; + } - @Inject protected List _affinityProcessors; + public List getAffinityGroupProcessors() { + return _affinityProcessors; + } + public void setAffinityGroupProcessors(List affinityProcessors) { + this._affinityProcessors = affinityProcessors; + } @Override public DeployDestination planDeployment(VirtualMachineProfile vmProfile, diff --git a/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java index c2038e5a85c..ac00bc14d36 100644 --- a/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalFirewallDeviceManagerImpl.java @@ -29,6 +29,7 @@ import javax.naming.ConfigurationException; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.response.ExternalFirewallResponse; import org.apache.cloudstack.network.ExternalNetworkDeviceManager.NetworkDevice; +import com.cloud.utils.Pair; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -715,8 +716,17 @@ public abstract class ExternalFirewallDeviceManagerImpl extends AdapterBase impl if (pNetwork.getVnet() == null) { throw new CloudRuntimeException("Could not find vlan range for physical Network " + physicalNetworkId + "."); } - String vlanRange[] = pNetwork.getVnet().split("-"); - int lowestVlanTag = Integer.valueOf(vlanRange[0]); + Integer lowestVlanTag = null; + List> vnetList = pNetwork.getVnet(); + //finding the vlanrange in which the vlanTag lies. + for (Pair vnet : vnetList){ + if (vlanTag >= vnet.first() && vlanTag <= vnet.second()){ + lowestVlanTag = vnet.first(); + } + } + if (lowestVlanTag == null) { + throw new InvalidParameterValueException ("The vlan tag dose not belong to any of the existing vlan ranges"); + } return vlanTag - lowestVlanTag; } diff --git a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java index 766639727c7..b4662d13df3 100644 --- a/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java +++ b/server/src/com/cloud/network/ExternalLoadBalancerDeviceManagerImpl.java @@ -269,11 +269,11 @@ public abstract class ExternalLoadBalancerDeviceManagerImpl extends AdapterBase txn.start(); lbDeviceVO = new ExternalLoadBalancerDeviceVO(host.getId(), pNetwork.getId(), ntwkDevice.getNetworkServiceProvder(), deviceName, capacity, dedicatedUse, gslbProvider); - _externalLoadBalancerDeviceDao.persist(lbDeviceVO); - if (!gslbProvider) { + if (gslbProvider) { lbDeviceVO.setGslbSitePrivateIP(gslbSitePublicIp); lbDeviceVO.setGslbSitePrivateIP(gslbSitePrivateIp); } + _externalLoadBalancerDeviceDao.persist(lbDeviceVO); DetailVO hostDetail = new DetailVO(host.getId(), ApiConstants.LOAD_BALANCER_DEVICE_ID, String.valueOf(lbDeviceVO.getId())); _hostDetailDao.persist(hostDetail); diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index 7332ef3e9cf..72ccac0ec7d 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -581,6 +581,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L VlanType vlanType = VlanType.VirtualNetwork; boolean assign = false; boolean allocateFromDedicatedRange = false; + List dedicatedVlanDbIds = new ArrayList(); + List nonDedicatedVlanDbIds = new ArrayList(); if (Grouping.AllocationState.Disabled == zone.getAllocationState() && !_accountMgr.isRootAdmin(caller.getType())) { // zone is of type DataCenter. See DataCenterVO.java. @@ -615,18 +617,17 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L txn.start(); // If account has dedicated Public IP ranges, allocate IP from the dedicated range - List vlanDbIds = new ArrayList(); List maps = _accountVlanMapDao.listAccountVlanMapsByAccount(ipOwner.getId()); for (AccountVlanMapVO map : maps) { - vlanDbIds.add(map.getVlanDbId()); + dedicatedVlanDbIds.add(map.getVlanDbId()); } - if (vlanDbIds != null && !vlanDbIds.isEmpty()) { + if (dedicatedVlanDbIds != null && !dedicatedVlanDbIds.isEmpty()) { allocateFromDedicatedRange = true; } try { if (allocateFromDedicatedRange) { - ip = fetchNewPublicIp(zone.getId(), null, vlanDbIds, ipOwner, vlanType, null, + ip = fetchNewPublicIp(zone.getId(), null, dedicatedVlanDbIds, ipOwner, vlanType, null, false, assign, null, isSystem, null); } } catch(InsufficientAddressCapacityException e) { @@ -637,12 +638,15 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L } if (!allocateFromDedicatedRange) { - ip = fetchNewPublicIp(zone.getId(), null, null, ipOwner, vlanType, null, false, assign, null, + List nonDedicatedVlans = _vlanDao.listZoneWideNonDedicatedVlans(zone.getId()); + for (VlanVO nonDedicatedVlan : nonDedicatedVlans) { + nonDedicatedVlanDbIds.add(nonDedicatedVlan.getId()); + } + ip = fetchNewPublicIp(zone.getId(), null, nonDedicatedVlanDbIds, ipOwner, vlanType, null, false, assign, null, isSystem, null); } if (ip == null) { - InsufficientAddressCapacityException ex = new InsufficientAddressCapacityException ("Unable to find available public IP addresses", DataCenter.class, zone.getId()); ex.addProxyObject(ApiDBUtils.findZoneById(zone.getId()).getUuid()); @@ -3632,8 +3636,8 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L //2) prepare nic if (prepare) { - NetworkVO networkVO = _networksDao.findById(network.getId()); - nic = prepareNic(vmProfile, dest, context, nic.getId(), networkVO); + Pair implemented = implementNetwork(nic.getNetworkId(), dest, context); + nic = prepareNic(vmProfile, dest, context, nic.getId(), implemented.second()); s_logger.debug("Nic is prepared successfully for vm " + vm + " in network " + network); } diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 70d1d0d432c..ac2ac456897 100755 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -19,16 +19,10 @@ package com.cloud.network; 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.*; import com.cloud.dc.DataCenter.NetworkType; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.Pod; import com.cloud.dc.Vlan.VlanType; -import com.cloud.dc.VlanVO; -import com.cloud.dc.dao.AccountVlanMapDao; -import com.cloud.dc.dao.DataCenterDao; -import com.cloud.dc.dao.HostPodDao; -import com.cloud.dc.dao.VlanDao; +import com.cloud.dc.dao.*; import com.cloud.deploy.DeployDestination; import com.cloud.domain.Domain; import com.cloud.domain.DomainVO; @@ -89,6 +83,7 @@ import com.cloud.utils.net.NetUtils; import com.cloud.vm.*; import com.cloud.vm.dao.*; import org.apache.cloudstack.acl.ControlledEntity.ACLType; +import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.command.admin.usage.ListTrafficTypeImplementorsCmd; import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd; @@ -206,6 +201,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { HostDao _hostDao; @Inject HostPodDao _hostPodDao; + @Inject + DataCenterVnetDao _datacneter_vnet; int _cidrLimit; boolean _allowSubdomainNetworkAccess; @@ -538,7 +535,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } else if (dc.getNetworkType() == NetworkType.Basic || ntwkOff.getGuestType() == Network.GuestType.Shared) { Account caller = UserContext.current().getCaller(); long callerUserId = UserContext.current().getCallerUserId(); - _accountMgr.checkAccess(caller, AccessType.UseNetwork, false, network); + _accountMgr.checkAccess(caller, SecurityChecker.AccessType.UseNetwork, false, network); //handle the basic networks here VirtualMachine vm = _userVmDao.findById(nicVO.getInstanceId()); if (vm == null) { @@ -758,18 +755,20 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { // in the zone when using external networking PhysicalNetworkVO pNetwork = _physicalNetworkDao.findById(physicalNetworkId); if (pNetwork.getVnet() != null) { - String vlanRange[] = pNetwork.getVnet().split("-"); - int lowestVlanTag = Integer.valueOf(vlanRange[0]); - int highestVlanTag = Integer.valueOf(vlanRange[1]); - for (int vlan=lowestVlanTag; vlan <= highestVlanTag; ++vlan) { - int offset = vlan - lowestVlanTag; - String globalVlanBits = _configDao.getValue(Config.GuestVlanBits.key()); - int cidrSize = 8 + Integer.parseInt(globalVlanBits); - String guestNetworkCidr = zone.getGuestNetworkCidr(); - String[] cidrTuple = guestNetworkCidr.split("\\/"); - long newCidrAddress = (NetUtils.ip2Long(cidrTuple[0]) & 0xff000000) | (offset << (32 - cidrSize)); - if (NetUtils.isNetworksOverlap(NetUtils.long2Ip(newCidrAddress), cidr)) { - throw new InvalidParameterValueException("Specified CIDR for shared network conflict with CIDR that is reserved for zone vlan " + vlan); + List > vlanList = pNetwork.getVnet(); + for (Pair vlanRange : vlanList){ + Integer lowestVlanTag = vlanRange.first(); + Integer highestVlanTag = vlanRange.second(); + for (int vlan=lowestVlanTag; vlan <= highestVlanTag; ++vlan) { + int offset = vlan - lowestVlanTag; + String globalVlanBits = _configDao.getValue(Config.GuestVlanBits.key()); + int cidrSize = 8 + Integer.parseInt(globalVlanBits); + String guestNetworkCidr = zone.getGuestNetworkCidr(); + String[] cidrTuple = guestNetworkCidr.split("\\/"); + long newCidrAddress = (NetUtils.ip2Long(cidrTuple[0]) & 0xff000000) | (offset << (32 - cidrSize)); + if (NetUtils.isNetworksOverlap(NetUtils.long2Ip(newCidrAddress), cidr)) { + throw new InvalidParameterValueException("Specified CIDR for shared network conflict with CIDR that is reserved for zone vlan " + vlan); + } } } } @@ -1869,11 +1868,13 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { // If networkCidr is null it implies that there was no prior IP reservation, so the network cidr is network.getCidr() // But in case networkCidr is a non null value (IP reservation already exists), it implies network cidr is networkCidr - if (networkCidr != null && ! NetUtils.isNetworkAWithinNetworkB(guestVmCidr, networkCidr)) { + if (networkCidr != null) { + if(! NetUtils.isNetworkAWithinNetworkB(guestVmCidr, networkCidr)) { throw new InvalidParameterValueException ("Invalid value of Guest VM CIDR. For IP Reservation, Guest VM CIDR should be a subset of network CIDR : " + networkCidr); + } } else { if (! NetUtils.isNetworkAWithinNetworkB(guestVmCidr, network.getCidr())) { - throw new InvalidParameterValueException ("Invalid value of Guest VM CIDR. For IP Reservation, Guest VM CIDR should be a subset of network CIDR : " + network.getCidr()); + throw new InvalidParameterValueException ("Invalid value of Guest VM CIDR. For IP Reservation, Guest VM CIDR should be a subset of network CIDR : " + network.getCidr()); } } @@ -1987,8 +1988,11 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { continue; } long isDefault = (nic.isDefaultNic()) ? 1 : 0; - UsageEventUtils.saveUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), null, oldNetworkOfferingId, null, 0L); - UsageEventUtils.saveUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName(), networkOfferingId, null, isDefault); + String nicIdString = Long.toString(nic.getId()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), + vm.getId(), nicIdString, oldNetworkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(), vm.getDataCenterId(), + vm.getId(), nicIdString, networkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid()); } txn.commit(); } else { @@ -2198,7 +2202,6 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } catch (NumberFormatException e) { throw new InvalidParameterValueException("Please specify valid integers for the vlan range."); } - if ((vnetStart > vnetEnd) || (vnetStart < 0) || (vnetEnd > 4096)) { s_logger.warn("Invalid vnet range: start range:" + vnetStart + " end range:" + vnetEnd); throw new InvalidParameterValueException("Vnet range should be between 0-4096 and start range should be lesser than or equal to end range"); @@ -2289,7 +2292,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { @Override @DB @ActionEvent(eventType = EventTypes.EVENT_PHYSICAL_NETWORK_UPDATE, eventDescription = "updating physical network", async = true) - public PhysicalNetwork updatePhysicalNetwork(Long id, String networkSpeed, List tags, String newVnetRangeString, String state) { + public PhysicalNetwork updatePhysicalNetwork(Long id, String networkSpeed, List tags, String newVnetRangeString, String state, String removeVlan) { // verify input parameters PhysicalNetworkVO network = _physicalNetworkDao.findById(id); @@ -2314,6 +2317,12 @@ 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) { throw new InvalidParameterException("Unable to support more than one tag on network yet"); } @@ -2340,90 +2349,209 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService { } // Vnet range can be extended only - boolean replaceVnet = false; - ArrayList> vnetsToAdd = new ArrayList>(2); + boolean AddVnet = true; + List> vnetsToAdd = new ArrayList>(); if (newVnetRangeString != null) { Integer newStartVnet = 0; Integer newEndVnet = 0; - String[] newVnetRange = newVnetRangeString.split("-"); - int maxVnet = 4096; - // for GRE phynets allow up to 32bits - // TODO: Not happy about this test. - // What about guru-like objects for physical networs? - s_logger.debug("ISOLATION METHODS:" + network.getIsolationMethods()); - // Java does not have unsigned types... - if (network.getIsolationMethods().contains("GRE")) { - maxVnet = (int)(Math.pow(2, 32)-1); - } - String rangeMessage = " between 0 and " + maxVnet; - if (newVnetRange.length < 2) { - throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage); - } + List tokens = processVlanRange(network, newVnetRangeString); + newStartVnet = tokens.get(0); + newEndVnet = tokens.get(1); + Integer j=0; + List > existingRanges = network.getVnet(); + if (!existingRanges.isEmpty()) { + for (; j < existingRanges.size(); j++){ + int existingStartVnet = existingRanges.get(j).first(); + int existingEndVnet = existingRanges.get(j).second(); - if (newVnetRange[0] == null || newVnetRange[1] == null) { - throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage); - } + // check if vnet is being extended + if (newStartVnet.intValue() >= existingStartVnet & newEndVnet.intValue() <= existingEndVnet) { + throw new InvalidParameterValueException("The vlan range you trying to add already exists."); + } - try { - newStartVnet = Integer.parseInt(newVnetRange[0]); - newEndVnet = Integer.parseInt(newVnetRange[1]); - } catch (NumberFormatException e) { - s_logger.warn("Unable to parse vnet range:", e); - throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage); - } - if (newStartVnet < 0 || newEndVnet > maxVnet) { - throw new InvalidParameterValueException("Vnet range has to be" + rangeMessage); - } + if (newStartVnet < existingStartVnet & newEndVnet+1 >= existingStartVnet & newEndVnet <= existingEndVnet) { + vnetsToAdd.add(new Pair(newStartVnet, existingStartVnet - 1)); + existingRanges.get(j).first(newStartVnet); + AddVnet = false; + break; + } - if (newStartVnet > newEndVnet) { - throw new InvalidParameterValueException("Vnet range has to be" + rangeMessage + " and start range should be lesser than or equal to stop range"); - } - - if (physicalNetworkHasAllocatedVnets(network.getDataCenterId(), network.getId())) { - String[] existingRange = network.getVnet().split("-"); - int existingStartVnet = Integer.parseInt(existingRange[0]); - int existingEndVnet = Integer.parseInt(existingRange[1]); + else if (newStartVnet > existingStartVnet & newStartVnet-1 <= existingEndVnet & newEndVnet >= existingEndVnet) { + vnetsToAdd.add(new Pair(existingEndVnet + 1, newEndVnet)); + existingRanges.get(j).second(newEndVnet); + AddVnet = false; + break; + } - // check if vnet is being extended - if (newStartVnet.intValue() > existingStartVnet || newEndVnet.intValue() < existingEndVnet) { - throw new InvalidParameterValueException("Can't shrink existing vnet range as it the range has vnets allocated. Only extending existing vnet is supported"); + else if (newStartVnet< existingStartVnet & newEndVnet > existingEndVnet){ + vnetsToAdd.add(new Pair(newStartVnet,existingStartVnet-1)); + vnetsToAdd.add(new Pair(existingEndVnet+1,newEndVnet)); + existingRanges.get(j).first(newStartVnet); + existingRanges.get(j).second(newEndVnet); + break; + } } - if (newStartVnet < existingStartVnet) { - vnetsToAdd.add(new Pair(newStartVnet, existingStartVnet - 1)); - } - - if (newEndVnet > existingEndVnet) { - vnetsToAdd.add(new Pair(existingEndVnet + 1, newEndVnet)); - } - - } else { - vnetsToAdd.add(new Pair(newStartVnet, newEndVnet)); - replaceVnet = true; } - } + if (AddVnet){ + vnetsToAdd.add(new Pair(newStartVnet, newEndVnet)); + existingRanges.add(new Pair(newStartVnet,newEndVnet)); + } - if (newVnetRangeString != null) { - network.setVnet(newVnetRangeString); + Map vnetMap = new HashMap(existingRanges.size()); + Map IndexMap = new HashMap(existingRanges.size()); + for (int i=0; i< existingRanges.size(); i++){ + vnetMap.put(existingRanges.get(i).first(),existingRanges.get(i).second()); + IndexMap.put(existingRanges.get(i).first(),i); + } + + Integer value; + Integer index; + String vnetString = ""; + for (int i=0; i < existingRanges.size(); i++){ + value = vnetMap.get((existingRanges.get(i).second()+1)); + if (value != null) { + vnetMap.remove((existingRanges.get(i).second()+1)); + vnetMap.remove(existingRanges.get(i).first()); + vnetMap.put(existingRanges.get(i).first(),value); + existingRanges.add(new Pair(existingRanges.get(i).first(),value)); + index = IndexMap.get(existingRanges.get(i).second()+1); + existingRanges.get(index).first(-1); + existingRanges.get(index).second(-1); + existingRanges.get(i).first(-1); + existingRanges.get(i).second(-1); + } + value = vnetMap.get((existingRanges.get(i).second())); + if (value != null) { + vnetMap.remove((existingRanges.get(i).second())); + vnetMap.remove(existingRanges.get(i).first()); + vnetMap.put(existingRanges.get(i).first(),value); + existingRanges.add(new Pair(existingRanges.get(i).first(),value)); + index = IndexMap.get(existingRanges.get(i).second()); + existingRanges.get(index).first(-1); + existingRanges.get(index).second(-1); + existingRanges.get(i).first(-1); + existingRanges.get(i).second(-1); + } + } + + + + if (newVnetRangeString != null) { + for (Pair vnetRange : existingRanges ){ + value=vnetMap.get(vnetRange.first()); + if (value != null){ + vnetString = vnetString+vnetRange.first().toString()+"-"+value.toString()+";"; + } + } + vnetString = vnetString+"*"; + vnetString = vnetString.replace(";*",""); + network.setVnet(vnetString); + } + + for (Pair vnetToAdd : vnetsToAdd) { + s_logger.debug("Adding vnet range " + vnetToAdd.first() + "-" + vnetToAdd.second() + " for the physicalNetwork id= " + id + " and zone id=" + network.getDataCenterId() + + " as a part of updatePhysicalNetwork call"); + _dcDao.addVnet(network.getDataCenterId(), network.getId(), vnetToAdd.first(), vnetToAdd.second()); + } } _physicalNetworkDao.update(id, network); - if (replaceVnet) { - s_logger.debug("Deleting existing vnet range for the physicalNetwork id= " + id + " and zone id=" + network.getDataCenterId() + " as a part of updatePhysicalNetwork call"); - _dcDao.deleteVnet(network.getId()); - } - - for (Pair vnetToAdd : vnetsToAdd) { - s_logger.debug("Adding vnet range " + vnetToAdd.first() + "-" + vnetToAdd.second() + " for the physicalNetwork id= " + id + " and zone id=" + network.getDataCenterId() - + " as a part of updatePhysicalNetwork call"); - _dcDao.addVnet(network.getDataCenterId(), network.getId(), vnetToAdd.first(), vnetToAdd.second()); - } - return network; } + private List processVlanRange(PhysicalNetworkVO network, String removeVlan) { + Integer StartVnet; + Integer EndVnet; + String[] VnetRange = removeVlan.split("-"); + int maxVnet = 4096; + // for GRE phynets allow up to 32bits + // TODO: Not happy about this test. + // What about guru-like objects for physical networs? + s_logger.debug("ISOLATION METHODS:" + network.getIsolationMethods()); + // Java does not have unsigned types... + if (network.getIsolationMethods().contains("GRE")) { + maxVnet = (int)(Math.pow(2, 32)-1); + } + String rangeMessage = " between 0 and " + maxVnet; + if (VnetRange.length < 2) { + throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage); + } + + if (VnetRange[0] == null || VnetRange[1] == null) { + throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage); + } + + try { + StartVnet = Integer.parseInt(VnetRange[0]); + EndVnet = Integer.parseInt(VnetRange[1]); + } catch (NumberFormatException e) { + s_logger.warn("Unable to parse vnet range:", e); + throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage); + } + if (StartVnet < 0 || EndVnet > maxVnet) { + throw new InvalidParameterValueException("Vnet range has to be" + rangeMessage); + } + + if (StartVnet > EndVnet) { + throw new InvalidParameterValueException("Vnet range has to be" + rangeMessage + " and start range should be lesser than or equal to stop range"); + } + List tokens = new ArrayList(); + tokens.add(StartVnet); + tokens.add(EndVnet); + return tokens; + + } + + + private boolean removeVlanRange( PhysicalNetworkVO network, Integer start, Integer end) { + Integer temp=0; + int i; + List > existingRanges = network.getVnet(); + Transaction txn = Transaction.currentTxn(); + txn.start(); + _physicalNetworkDao.acquireInLockTable(network.getId(),10); + _datacneter_vnet.lockRange(network.getDataCenterId(), network.getId(), start, end); + List result = _datacneter_vnet.listAllocatedVnetsInRange(network.getDataCenterId(), network.getId(), start, end); + if (!result.isEmpty()){ + txn.close(); + throw new InvalidParameterValueException("Some of the vnets from this range are allocated, can only remove a range which has no allocated vnets"); + } + for (i=0; i= end){ + temp = existingRanges.get(i).second(); + existingRanges.get(i).second(start - 1); + existingRanges.add(new Pair((end+1),temp)); + break; + } + } + + if (temp == 0){ + throw new InvalidParameterValueException("The vlan range you are trying to delete dose not exist."); + } + if(existingRanges.get(i).first() > existingRanges.get(i).second()){ + existingRanges.remove(i); + } + if(existingRanges.get(existingRanges.size()-1).first() > existingRanges.get(existingRanges.size()-1).second()){ + existingRanges.remove(existingRanges.size()-1); + } + _datacneter_vnet.deleteRange(txn, network.getDataCenterId(), network.getId(), start, end); + + String vnetString=""; + for (Pair vnetRange : existingRanges ){ + vnetString=vnetString+vnetRange.first().toString()+"-"+vnetRange.second().toString()+";"; + } + vnetString = vnetString+"*"; + vnetString = vnetString.replace(";*",""); + network.setVnet(vnetString); + _physicalNetworkDao.update(network.getId(), network); + txn.commit(); + _physicalNetworkDao.releaseFromLockTable(network.getId()); + return true; + } + private boolean physicalNetworkHasAllocatedVnets(long zoneId, long physicalNetworkId) { return !_dcDao.listAllocatedVnets(physicalNetworkId).isEmpty(); } diff --git a/server/src/com/cloud/network/addr/PublicIp.java b/server/src/com/cloud/network/addr/PublicIp.java index 8217e4e47b9..25e9d308b14 100644 --- a/server/src/com/cloud/network/addr/PublicIp.java +++ b/server/src/com/cloud/network/addr/PublicIp.java @@ -194,23 +194,12 @@ public class PublicIp implements PublicIpAddress { public boolean getSystem() { return _addr.getSystem(); } - - /* (non-Javadoc) - * @see com.cloud.network.IpAddress#getVpcId() - */ + @Override public Long getVpcId() { return _addr.getVpcId(); } - /* (non-Javadoc) - * @see com.cloud.network.IpAddress#setVpcId(java.lang.Long) - */ - @Override - public void setVpcId(Long vpcId) { - _addr.setVpcId(vpcId); - } - @Override public String getIp6Gateway() { return _vlan.getIp6Gateway(); @@ -230,9 +219,4 @@ public class PublicIp implements PublicIpAddress { public String getVmIp() { return _addr.getVmIp(); } - - @Override - public void setVmIp(String vmIp) { - _addr.setVmIp(vmIp); - } } diff --git a/server/src/com/cloud/network/dao/IPAddressVO.java b/server/src/com/cloud/network/dao/IPAddressVO.java index 8ce8d3382b2..c5c78e557ae 100644 --- a/server/src/com/cloud/network/dao/IPAddressVO.java +++ b/server/src/com/cloud/network/dao/IPAddressVO.java @@ -292,7 +292,6 @@ public class IPAddressVO implements IpAddress { return vpcId; } - @Override public void setVpcId(Long vpcId) { this.vpcId = vpcId; } @@ -302,7 +301,6 @@ public class IPAddressVO implements IpAddress { return vmIp; } - @Override public void setVmIp(String vmIp) { this.vmIp = vmIp; } diff --git a/server/src/com/cloud/network/dao/PhysicalNetworkVO.java b/server/src/com/cloud/network/dao/PhysicalNetworkVO.java index e5ffcfb7c0d..f68eee1de5c 100644 --- a/server/src/com/cloud/network/dao/PhysicalNetworkVO.java +++ b/server/src/com/cloud/network/dao/PhysicalNetworkVO.java @@ -34,11 +34,9 @@ import javax.persistence.Table; import javax.persistence.TableGenerator; import com.cloud.network.PhysicalNetwork; -import com.cloud.network.PhysicalNetwork.BroadcastDomainRange; -import com.cloud.network.PhysicalNetwork.State; import com.cloud.utils.NumbersUtil; +import com.cloud.utils.Pair; import com.cloud.utils.db.GenericDao; -import org.apache.cloudstack.api.InternalIdentity; /** * NetworkConfigurationVO contains information about a specific physical network. @@ -205,7 +203,21 @@ public class PhysicalNetworkVO implements PhysicalNetwork { } @Override - public String getVnet() { + public List> getVnet() { + List > vnetList = new ArrayList>(); + if (vnet != null) { + String [] Temp = vnet.split(";"); + String [] vnetSplit = null; + for (String vnetRange : Temp){ + vnetSplit = vnetRange.split("-"); + vnetList.add(new Pair(Integer.parseInt(vnetSplit[0]),Integer.parseInt(vnetSplit[1]))); + } + } + return vnetList; + } + + @Override + public String getVnetString() { return vnet; } diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index 169db3283e3..f601f4fa2e4 100755 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -876,8 +876,8 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl if (publicNetwork) { routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER); } else { - Long podId = dest.getPod().getId(); if (isPodBased) { + Long podId = dest.getPod().getId(); routers = _routerDao.listByNetworkAndPodAndRole(network.getId(), podId, Role.VIRTUAL_ROUTER); } else { routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER); diff --git a/server/src/com/cloud/network/guru/GuestNetworkGuru.java b/server/src/com/cloud/network/guru/GuestNetworkGuru.java index 9c0205a89b2..92607e2fcd0 100755 --- a/server/src/com/cloud/network/guru/GuestNetworkGuru.java +++ b/server/src/com/cloud/network/guru/GuestNetworkGuru.java @@ -26,6 +26,7 @@ import javax.ejb.Local; import javax.inject.Inject; import com.cloud.event.ActionEventUtils; +import com.cloud.utils.Pair; import org.apache.log4j.Logger; import com.cloud.configuration.Config; @@ -274,8 +275,17 @@ public abstract class GuestNetworkGuru extends AdapterBase implements NetworkGur if (pNetwork.getVnet() == null) { throw new CloudRuntimeException("Could not find vlan range for physical Network " + physicalNetworkId + "."); } - String vlanRange[] = pNetwork.getVnet().split("-"); - int lowestVlanTag = Integer.valueOf(vlanRange[0]); + Integer lowestVlanTag = null; + List> vnetList = pNetwork.getVnet(); + //finding the vlanrange in which the vlanTag lies. + for (Pair vnet : vnetList){ + if (vlanTag >= vnet.first() && vlanTag <= vnet.second()){ + lowestVlanTag = vnet.first(); + } + } + if (lowestVlanTag == null) { + throw new InvalidParameterValueException ("The vlan tag dose not belong to any of the existing vlan ranges"); + } return vlanTag - lowestVlanTag; } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index ab91059b0f3..4c7bc75b2d3 100755 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -40,6 +40,7 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.server.ConfigurationServer; import org.apache.cloudstack.api.command.admin.router.UpgradeRouterCmd; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -286,6 +287,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V @Inject ConfigurationManager _configMgr; @Inject + ConfigurationServer _configServer; + @Inject ServiceOfferingDao _serviceOfferingDao = null; @Inject UserVmDao _userVmDao; @@ -2094,7 +2097,7 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V boolean useExtDns = !dnsProvided; /* For backward compatibility */ - String use_external_dns = _configDao.getValue(Config.UseExternalDnsServers.key()); + String use_external_dns = _configServer.getConfigValue(Config.UseExternalDnsServers.key(), Config.ConfigurationParameterScope.zone.toString(), dc.getId()); if (use_external_dns != null && use_external_dns.equals("true")) { useExtDns = true; } diff --git a/server/src/com/cloud/network/rules/RulesManagerImpl.java b/server/src/com/cloud/network/rules/RulesManagerImpl.java index 29ed5f36d5e..8636d8503a3 100755 --- a/server/src/com/cloud/network/rules/RulesManagerImpl.java +++ b/server/src/com/cloud/network/rules/RulesManagerImpl.java @@ -1215,11 +1215,13 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules Network guestNetwork = _networkModel.getNetwork(ipAddress.getAssociatedWithNetworkId()); NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId()); if (offering.getElasticIp()) { - getSystemIpAndEnableStaticNatForVm(_vmDao.findById(vmId), true); - return true; - } else { - return disableStaticNat(ipId, caller, ctx.getCallerUserId(), false); + if (offering.getAssociatePublicIP()) { + getSystemIpAndEnableStaticNatForVm(_vmDao.findById(vmId), true); + return true; + } } + + return disableStaticNat(ipId, caller, ctx.getCallerUserId(), false); } @Override @@ -1410,6 +1412,11 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules Network guestNetwork = _networkModel.getNetwork(nic.getNetworkId()); NetworkOffering offering = _configMgr.getNetworkOffering(guestNetwork.getNetworkOfferingId()); if (offering.getElasticIp()) { + boolean isSystemVM = (vm.getType() == Type.ConsoleProxy || vm.getType() == Type.SecondaryStorageVm); + // for user VM's associate public IP only if offering is marked to associate a public IP by default on start of VM + if (!isSystemVM && !offering.getAssociatePublicIP()) { + continue; + } // check if there is already static nat enabled if (_ipAddressDao.findByAssociatedVmId(vm.getId()) != null && !getNewIp) { s_logger.debug("Vm " + vm + " already has ip associated with it in guest network " + guestNetwork); @@ -1424,7 +1431,6 @@ public class RulesManagerImpl extends ManagerBase implements RulesManager, Rules s_logger.debug("Allocated system ip " + ip + ", now enabling static nat on it for vm " + vm); - boolean isSystemVM = (vm.getType() == Type.ConsoleProxy || vm.getType() == Type.SecondaryStorageVm); try { success = enableStaticNat(ip.getId(), vm.getId(), guestNetwork.getId(), isSystemVM, null); } catch (NetworkRuleConflictException ex) { diff --git a/server/src/com/cloud/offerings/NetworkOfferingVO.java b/server/src/com/cloud/offerings/NetworkOfferingVO.java index 5de76a526b5..c015989c5c5 100755 --- a/server/src/com/cloud/offerings/NetworkOfferingVO.java +++ b/server/src/com/cloud/offerings/NetworkOfferingVO.java @@ -110,6 +110,9 @@ public class NetworkOfferingVO implements NetworkOffering { @Column(name = "elastic_ip_service") boolean elasticIp; + @Column(name = "eip_associate_public_ip") + boolean eipAssociatePublicIp; + @Column(name = "elastic_lb_service") boolean elasticLb; @@ -278,6 +281,7 @@ public class NetworkOfferingVO implements NetworkOffering { this.sharedSourceNat = false; this.redundantRouter = false; this.elasticIp = false; + this.eipAssociatePublicIp = true; this.elasticLb = false; this.inline = false; this.specifyIpRanges = specifyIpRanges; @@ -286,7 +290,7 @@ public class NetworkOfferingVO implements NetworkOffering { public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps, Integer multicastRateMbps, boolean isDefault, Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, boolean dedicatedLb, boolean sharedSourceNat, boolean redundantRouter, boolean elasticIp, boolean elasticLb, - boolean specifyIpRanges, boolean inline, boolean isPersistent) { + boolean specifyIpRanges, boolean inline, boolean isPersistent, boolean associatePublicIP) { this(name, displayText, trafficType, systemOnly, specifyVlan, rateMbps, multicastRateMbps, isDefault, availability, tags, guestType, conserveMode, specifyIpRanges, isPersistent); this.dedicatedLB = dedicatedLb; this.sharedSourceNat = sharedSourceNat; @@ -294,6 +298,7 @@ public class NetworkOfferingVO implements NetworkOffering { this.elasticIp = elasticIp; this.elasticLb = elasticLb; this.inline = inline; + this.eipAssociatePublicIp = associatePublicIP; } public NetworkOfferingVO() { @@ -355,6 +360,11 @@ public class NetworkOfferingVO implements NetworkOffering { return elasticIp; } + @Override + public boolean getAssociatePublicIP() { + return eipAssociatePublicIp; + } + @Override public boolean getElasticLb() { return elasticLb; diff --git a/server/src/com/cloud/server/ConfigurationServer.java b/server/src/com/cloud/server/ConfigurationServer.java index f441b1f5de6..c1306d5ec82 100644 --- a/server/src/com/cloud/server/ConfigurationServer.java +++ b/server/src/com/cloud/server/ConfigurationServer.java @@ -16,6 +16,9 @@ // under the License. package com.cloud.server; +import java.util.List; + +import com.cloud.configuration.ConfigurationVO; import com.cloud.exception.InternalErrorException; /** @@ -30,4 +33,6 @@ public interface ConfigurationServer { */ public void persistDefaultValues() throws InternalErrorException; public void updateKeyPairs(); + public String getConfigValue(String name, String scope, Long resourceId); + public List getConfigListByScope(String scope, Long resourceId); } diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 404afecf2cd..cd890ce8582 100755 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -36,28 +36,29 @@ 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.StoragePoolDetailVO; +import org.apache.cloudstack.storage.datastore.db.StoragePoolDetailsDao; 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.DataCenter.NetworkType; -import com.cloud.dc.DataCenterVO; -import com.cloud.dc.HostPodVO; -import com.cloud.dc.VlanVO; import com.cloud.dc.dao.DataCenterDao; import com.cloud.dc.dao.HostPodDao; import com.cloud.dc.dao.VlanDao; @@ -91,9 +92,6 @@ 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.AccountVO; -import com.cloud.user.User; import com.cloud.user.dao.AccountDao; import com.cloud.utils.PasswordGenerator; import com.cloud.utils.PropertiesUtil; @@ -127,6 +125,11 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio @Inject private ResourceCountDao _resourceCountDao; @Inject private NetworkOfferingServiceMapDao _ntwkOfferingServiceMapDao; @Inject private IdentityDao _identityDao; + @Inject private DcDetailsDao _dcDetailsDao; + @Inject private ClusterDetailsDao _clusterDetailsDao; + @Inject private StoragePoolDetailsDao _storagePoolDetailsDao; + @Inject private AccountDetailsDao _accountDetailsDao; + public ConfigurationServerImpl() { setRunLevel(ComponentLifecycle.RUN_LEVEL_FRAMEWORK_BOOTSTRAP); @@ -333,7 +336,7 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio @DB protected void saveUser() { // insert system account - String insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id) VALUES (1, UUID(), 'system', '1', '1')"; + String insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id, account.default) VALUES (1, UUID(), 'system', '1', '1', 1)"; Transaction txn = Transaction.currentTxn(); try { PreparedStatement stmt = txn.prepareAutoCloseStatement(insertSql); @@ -341,8 +344,8 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio } catch (SQLException ex) { } // insert system user - insertSql = "INSERT INTO `cloud`.`user` (id, uuid, username, password, account_id, firstname, lastname, created)" + - " VALUES (1, UUID(), 'system', RAND(), 1, 'system', 'cloud', now())"; + insertSql = "INSERT INTO `cloud`.`user` (id, uuid, username, password, account_id, firstname, lastname, created, user.default)" + + " VALUES (1, UUID(), 'system', RAND(), 1, 'system', 'cloud', now(), 1)"; txn = Transaction.currentTxn(); try { PreparedStatement stmt = txn.prepareAutoCloseStatement(insertSql); @@ -358,7 +361,7 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio String lastname = "cloud"; // create an account for the admin user first - insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id) VALUES (" + id + ", UUID(), '" + username + "', '1', '1')"; + insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id, account.default) VALUES (" + id + ", UUID(), '" + username + "', '1', '1', 1)"; txn = Transaction.currentTxn(); try { PreparedStatement stmt = txn.prepareAutoCloseStatement(insertSql); @@ -367,8 +370,8 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio } // now insert the user - insertSql = "INSERT INTO `cloud`.`user` (id, uuid, username, password, account_id, firstname, lastname, created, state) " + - "VALUES (" + id + ", UUID(), '" + username + "', RAND(), 2, '" + firstname + "','" + lastname + "',now(), 'disabled')"; + insertSql = "INSERT INTO `cloud`.`user` (id, uuid, username, password, account_id, firstname, lastname, created, state, user.default) " + + "VALUES (" + id + ", UUID(), '" + username + "', RAND(), 2, '" + firstname + "','" + lastname + "',now(), 'disabled', 1)"; txn = Transaction.currentTxn(); try { @@ -672,6 +675,76 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio } } + @Override + public String getConfigValue(String name, String scope, Long resourceId) { + // If either of scope or resourceId is null then return global config value otherwise return value at the scope + Config c = Config.getConfig(name); + if (c == null) { + throw new CloudRuntimeException("Missing configuration variable " + name + " in configuration table"); + } + String configScope = c.getScope(); + if (scope != null && !scope.isEmpty()) { + if (!configScope.contains(scope)) { + throw new CloudRuntimeException("Invalid scope " + scope + " for the parameter " + name ); + } + if (resourceId != null) { + switch (Config.ConfigurationParameterScope.valueOf(scope)) { + case zone: DataCenterVO zone = _zoneDao.findById(resourceId); + if (zone == null) { + throw new InvalidParameterValueException("unable to find zone by id " + resourceId); + } + DcDetailVO dcDetailVO = _dcDetailsDao.findDetail(resourceId, name); + if (dcDetailVO != null && dcDetailVO.getValue() != null) { + return dcDetailVO.getValue(); + } break; + + case cluster: ClusterDetailsVO cluster = _clusterDetailsDao.findById(resourceId); + if (cluster == null) { + throw new InvalidParameterValueException("unable to find cluster by id " + resourceId); + } + ClusterDetailsVO clusterDetailsVO = _clusterDetailsDao.findDetail(resourceId, name); + if (clusterDetailsVO != null && clusterDetailsVO.getValue() != null) { + return clusterDetailsVO.getValue(); + } break; + + case pool: StoragePoolDetailVO pool = _storagePoolDetailsDao.findById(resourceId); + if (pool == null) { + throw new InvalidParameterValueException("unable to find storage pool by id " + resourceId); + } + StoragePoolDetailVO storagePoolDetailVO = _storagePoolDetailsDao.findDetail(resourceId, name); + if (storagePoolDetailVO != null && storagePoolDetailVO.getValue() != null) { + return storagePoolDetailVO.getValue(); + } break; + + case account: AccountDetailVO account = _accountDetailsDao.findById(resourceId); + if (account == null) { + throw new InvalidParameterValueException("unable to find account by id " + resourceId); + } + AccountDetailVO accountDetailVO = _accountDetailsDao.findDetail(resourceId, name); + if (accountDetailVO != null && accountDetailVO.getValue() != null) { + return accountDetailVO.getValue(); + } break; + default: + } + } + } + return _configDao.getValue(name); + } + + @Override + public List getConfigListByScope(String scope, Long resourceId) { + + // Getting the list of parameters defined at the scope + List configList = Config.getConfigListByScope(scope); + List configVOList = new ArrayList(); + for (Config param:configList){ + ConfigurationVO configVo = _configDao.findByName(param.toString()); + configVo.setValue(getConfigValue(param.toString(), scope, resourceId)); + configVOList.add(configVo); + } + return configVOList; + } + private void writeKeyToDisk(String key, String keyPath) { File keyfile = new File(keyPath); if (!keyfile.exists()) { @@ -1008,7 +1081,7 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio "Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, false, true, null, null, true, Availability.Optional, - null, Network.GuestType.Shared, true, false, false, false, true, true, true, false, false); + null, Network.GuestType.Shared, true, false, false, false, true, true, true, false, false, true); defaultNetscalerNetworkOffering.setState(NetworkOffering.State.Enabled); defaultNetscalerNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNetscalerNetworkOffering); diff --git a/server/src/com/cloud/server/Criteria.java b/server/src/com/cloud/server/Criteria.java index 35186f89711..d54aaf59429 100755 --- a/server/src/com/cloud/server/Criteria.java +++ b/server/src/com/cloud/server/Criteria.java @@ -19,7 +19,7 @@ package com.cloud.server; import java.util.HashMap; public class Criteria { - + private Long offset; private Long limit; private String orderBy; @@ -82,6 +82,7 @@ public class Criteria { public static final String TEMPLATE_ID = "templateid"; public static final String ISO_ID = "isoid"; public static final String VPC_ID = "vpcId"; + public static final String AFFINITY_GROUP_ID = "affinitygroupid"; public Criteria(String orderBy, Boolean ascending, Long offset, Long limit) { this.offset = offset; @@ -90,7 +91,7 @@ public class Criteria { this.ascending = ascending; criteria = new HashMap(); } - + public Criteria() { criteria = new HashMap(); this.ascending = false; @@ -99,11 +100,11 @@ public class Criteria { public Long getOffset() { return offset; } - + public void addCriteria(String name, Object val) { criteria.put(name, val); } - + public Object getCriteria(String name) { return criteria.get(name); } @@ -135,5 +136,5 @@ public class Criteria { public void setAscending(Boolean ascending) { this.ascending = ascending; } - + } diff --git a/server/src/com/cloud/server/ManagementServer.java b/server/src/com/cloud/server/ManagementServer.java index 6773725f361..240464e4938 100755 --- a/server/src/com/cloud/server/ManagementServer.java +++ b/server/src/com/cloud/server/ManagementServer.java @@ -95,6 +95,9 @@ public interface ManagementServer extends ManagementService, PluggableService { Pair, Integer> searchForStoragePools(Criteria c); String getHashKey(); + String getEncryptionKey(); + String getEncryptionIV(); + void resetEncryptionKeyIV(); public void enableAdminUser(String password); } diff --git a/server/src/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index d9a4317d097..16127a22d95 100755 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -22,6 +22,8 @@ import java.net.InetAddress; import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.ArrayList; import java.util.Calendar; import java.util.Comparator; @@ -42,6 +44,7 @@ import javax.crypto.spec.SecretKeySpec; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.configuration.*; import com.cloud.storage.dao.*; import org.apache.cloudstack.acl.SecurityChecker.AccessType; import org.apache.cloudstack.api.ApiConstants; @@ -104,10 +107,6 @@ import com.cloud.capacity.CapacityVO; import com.cloud.capacity.dao.CapacityDao; import com.cloud.capacity.dao.CapacityDaoImpl.SummedCapacity; import com.cloud.cluster.ClusterManager; -import com.cloud.configuration.Config; -import com.cloud.configuration.Configuration; -import com.cloud.configuration.ConfigurationManager; -import com.cloud.configuration.ConfigurationVO; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.consoleproxy.ConsoleProxyManagementState; import com.cloud.consoleproxy.ConsoleProxyManager; @@ -215,6 +214,7 @@ import org.apache.cloudstack.api.command.admin.vlan.DeleteVlanIpRangeCmd; import org.apache.cloudstack.api.command.admin.vlan.ListVlanIpRangesCmd; import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd; import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd; +import org.apache.cloudstack.api.command.admin.vm.MigrateVirtualMachineWithVolumeCmd; import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd; import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd; @@ -257,6 +257,7 @@ import org.apache.cloudstack.api.command.user.vmsnapshot.ListVMSnapshotCmd; import org.apache.cloudstack.api.command.user.vmsnapshot.RevertToSnapshotCmd; import org.apache.cloudstack.api.command.user.zone.ListZonesByCmd; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; @@ -330,6 +331,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Inject private StorageManager _storageMgr; @Inject + private VolumeManager _volumeMgr; + @Inject private VirtualMachineManager _itMgr; @Inject private HostPodDao _hostPodDao; @@ -353,10 +356,10 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe private LoadBalancerDao _loadbalancerDao; @Inject private HypervisorCapabilitiesDao _hypervisorCapabilitiesDao; - private List _hostAllocators; - - @Inject + @Inject + private List _storagePoolAllocators; + @Inject private ConfigurationManager _configMgr; @Inject private ResourceTagDao _resourceTagDao; @@ -379,6 +382,9 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Inject S3Manager _s3Mgr; + @Inject + ConfigurationServer _configServer; + private final ScheduledExecutorService _eventExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("EventChecker")); private final ScheduledExecutorService _alertExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("AlertChecker")); private KeystoreManager _ksMgr; @@ -390,26 +396,30 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe private List _userAuthenticators; private List _userPasswordEncoders; - @Inject - protected List _planners; - @Inject ClusterManager _clusterMgr; private String _hashKey = null; - + private String _encryptionKey = null; + private String _encryptionIV = null; + @Inject protected AffinityGroupVMMapDao _affinityGroupVMMapDao; - @Inject protected List _affinityProcessors; + public List getAffinityGroupProcessors() { + return _affinityProcessors; + } + public void setAffinityGroupProcessors(List affinityProcessors) { + this._affinityProcessors = affinityProcessors; + } public ManagementServerImpl() { setRunLevel(ComponentLifecycle.RUN_LEVEL_APPLICATION_MAINLOOP); } - + public List getUserAuthenticators() { return _userAuthenticators; } - + public void setUserAuthenticators(List authenticators) { _userAuthenticators = authenticators; } @@ -673,12 +683,14 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe Object resourceState = cmd.getResourceState(); Object haHosts = cmd.getHaHost(); - Pair, Integer> result = searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), name, type, state, zoneId, pod, cluster, id, keyword, resourceState, haHosts); + Pair, Integer> result = searchForServers(cmd.getStartIndex(), cmd.getPageSizeVal(), name, type, + state, zoneId, pod, cluster, id, keyword, resourceState, haHosts, null, null); return new Pair, Integer>(result.first(), result.second()); } @Override - public Pair, Integer>, List> listHostsForMigrationOfVM(Long vmId, Long startIndex, Long pageSize) { + public Ternary, Integer>, List, Map> + listHostsForMigrationOfVM(Long vmId, Long startIndex, Long pageSize) { // access check - only root admin can migrate VM Account caller = UserContext.current().getCaller(); if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { @@ -694,12 +706,13 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe ex.addProxyObject(vm, vmId, "vmId"); throw ex; } - // business logic + if (vm.getState() != State.Running) { if (s_logger.isDebugEnabled()) { s_logger.debug("VM is not Running, unable to migrate the vm" + vm); } - InvalidParameterValueException ex = new InvalidParameterValueException("VM is not Running, unable to migrate the vm with specified id"); + InvalidParameterValueException ex = new InvalidParameterValueException("VM is not Running, unable to" + + " migrate the vm with specified id"); ex.addProxyObject(vm, vmId, "vmId"); throw ex; } @@ -709,17 +722,11 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (s_logger.isDebugEnabled()) { s_logger.debug(vm + " is not XenServer/VMware/KVM/OVM, cannot migrate this VM."); } - throw new InvalidParameterValueException("Unsupported Hypervisor Type for VM migration, we support XenServer/VMware/KVM only"); - } - ServiceOfferingVO svcOffering = _offeringsDao.findById(vm.getServiceOfferingId()); - if (svcOffering.getUseLocalStorage()) { - if (s_logger.isDebugEnabled()) { - s_logger.debug(vm + " is using Local Storage, cannot migrate this VM."); - } - throw new InvalidParameterValueException("Unsupported operation, VM uses Local storage, cannot migrate"); + throw new InvalidParameterValueException("Unsupported Hypervisor Type for VM migration, we support " + + "XenServer/VMware/KVM/Ovm only"); } + long srcHostId = vm.getHostId(); - // why is this not HostVO? Host srcHost = _hostDao.findById(srcHostId); if (srcHost == null) { if (s_logger.isDebugEnabled()) { @@ -731,32 +738,73 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe ex.addProxyObject(vm, vmId, "vmId"); throw ex; } - Long cluster = srcHost.getClusterId(); - Type hostType = srcHost.getType(); - if (s_logger.isDebugEnabled()) { - s_logger.debug("Searching for all hosts in cluster: " + cluster + " for migrating VM " + vm); + + // Check if the vm can be migrated with storage. + boolean canMigrateWithStorage = false; + HypervisorCapabilitiesVO capabilities = _hypervisorCapabilitiesDao.findByHypervisorTypeAndVersion( + srcHost.getHypervisorType(), srcHost.getHypervisorVersion()); + if (capabilities != null) { + canMigrateWithStorage = capabilities.isStorageMotionSupported(); } - Pair, Integer> allHostsInClusterPair = searchForServers(startIndex, pageSize, null, hostType, null, null, null, cluster, null, null, null, null); - - // filter out the current host - List allHostsInCluster = allHostsInClusterPair.first(); - allHostsInCluster.remove(srcHost); - Pair, Integer> otherHostsInCluster = new Pair, Integer>(allHostsInCluster, new Integer(allHostsInClusterPair.second().intValue()-1)); - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Other Hosts in this cluster: " + allHostsInCluster); - } - - if (s_logger.isDebugEnabled()) { - s_logger.debug("Calling HostAllocators to search for hosts in cluster: " + cluster + " having enough capacity and suitable for migration"); - } - - List suitableHosts = new ArrayList(); - + // Check if the vm is using any disks on local storage. VirtualMachineProfile vmProfile = new VirtualMachineProfileImpl(vm); + List volumes = _volumeDao.findCreatedByInstance(vmProfile.getId()); + boolean usesLocal = false; + for (VolumeVO volume : volumes) { + DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); + DiskProfile diskProfile = new DiskProfile(volume, diskOffering, vmProfile.getHypervisorType()); + if (diskProfile.useLocalStorage()) { + usesLocal = true; + break; + } + } - DataCenterDeployment plan = new DataCenterDeployment(srcHost.getDataCenterId(), srcHost.getPodId(), srcHost.getClusterId(), null, null, null); + if (!canMigrateWithStorage && usesLocal) { + throw new InvalidParameterValueException("Unsupported operation, VM uses Local storage, cannot migrate"); + } + + Type hostType = srcHost.getType(); + Pair, Integer> allHostsPair = null; + List allHosts = null; + Map requiresStorageMotion = new HashMap(); + DataCenterDeployment plan = null; + if (canMigrateWithStorage) { + allHostsPair = searchForServers(startIndex, pageSize, null, hostType, null, srcHost.getDataCenterId(), null, + null, null, null, null, null, srcHost.getHypervisorType(), srcHost.getHypervisorVersion()); + allHosts = allHostsPair.first(); + allHosts.remove(srcHost); + + // Check if the host has storage pools for all the volumes of the vm to be migrated. + for (Host host : allHosts) { + Map> volumePools = findSuitablePoolsForVolumes(vmProfile, host); + if (volumePools.isEmpty()) { + allHosts.remove(host); + } else { + if (host.getClusterId() != srcHost.getClusterId() || usesLocal) { + requiresStorageMotion.put(host, true); + } + } + } + + plan = new DataCenterDeployment(srcHost.getDataCenterId(), null, null, null, null, null); + } else { + Long cluster = srcHost.getClusterId(); + if (s_logger.isDebugEnabled()) { + s_logger.debug("Searching for all hosts in cluster " + cluster + " for migrating VM " + vm); + } + allHostsPair = searchForServers(startIndex, pageSize, null, hostType, null, null, null, cluster, null, null, + null, null, null, null); + // Filter out the current host. + allHosts = allHostsPair.first(); + allHosts.remove(srcHost); + plan = new DataCenterDeployment(srcHost.getDataCenterId(), srcHost.getPodId(), srcHost.getClusterId(), + null, null, null); + } + + Pair, Integer> otherHosts = new Pair, Integer>(allHosts, + new Integer(allHosts.size())); + List suitableHosts = new ArrayList(); ExcludeList excludes = new ExcludeList(); excludes.addHost(srcHostId); @@ -770,25 +818,174 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } for (HostAllocator allocator : _hostAllocators) { - suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, HostAllocator.RETURN_UPTO_ALL, false); + if (canMigrateWithStorage) { + suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, allHosts, + HostAllocator.RETURN_UPTO_ALL, false); + } else { + suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, + HostAllocator.RETURN_UPTO_ALL, false); + } + if (suitableHosts != null && !suitableHosts.isEmpty()) { break; } } - if (suitableHosts.isEmpty()) { - s_logger.debug("No suitable hosts found"); - } else { - if (s_logger.isDebugEnabled()) { + if (s_logger.isDebugEnabled()) { + if (suitableHosts.isEmpty()) { + s_logger.debug("No suitable hosts found"); + } else { s_logger.debug("Hosts having capacity and suitable for migration: " + suitableHosts); } } - return new Pair, Integer>, List>(otherHostsInCluster, suitableHosts); + return new Ternary, Integer>, List, Map> (otherHosts, + suitableHosts, requiresStorageMotion); + } + + private Map> findSuitablePoolsForVolumes(VirtualMachineProfile vmProfile, + Host host) { + List volumes = _volumeDao.findCreatedByInstance(vmProfile.getId()); + Map> suitableVolumeStoragePools = new HashMap>(); + + // For each volume find list of suitable storage pools by calling the allocators + for (VolumeVO volume : volumes) { + DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); + DiskProfile diskProfile = new DiskProfile(volume, diskOffering, vmProfile.getHypervisorType()); + DataCenterDeployment plan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(), + host.getClusterId(), host.getId(), null, null); + ExcludeList avoid = new ExcludeList(); + + boolean foundPools = false; + for (StoragePoolAllocator allocator : _storagePoolAllocators) { + List poolList = allocator.allocateToPool(diskProfile, vmProfile, plan, avoid, + StoragePoolAllocator.RETURN_UPTO_ALL); + if (poolList != null && !poolList.isEmpty()) { + suitableVolumeStoragePools.put(volume, poolList); + foundPools = true; + break; + } + } + + if (!foundPools) { + suitableVolumeStoragePools.clear(); + break; + } + } + + return suitableVolumeStoragePools; + } + + @Override + public Pair, List> listStoragePoolsForMigrationOfVolume(Long volumeId) { + // Access check - only root administrator can migrate volumes. + Account caller = UserContext.current().getCaller(); + if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Caller is not a root admin, permission denied to migrate the volume"); + } + throw new PermissionDeniedException("No permission to migrate volume, only root admin can migrate a volume"); + } + + VolumeVO volume = _volumeDao.findById(volumeId); + if (volume == null) { + InvalidParameterValueException ex = new InvalidParameterValueException("Unable to find volume with" + + " specified id."); + ex.addProxyObject(volume, volumeId, "volumeId"); + throw ex; + } + + // Volume must be attached to an instance for live migration. + List allPools = new ArrayList(); + List suitablePools = new ArrayList(); + Long instanceId = volume.getInstanceId(); + VMInstanceVO vm = null; + if (instanceId != null) { + vm = _vmInstanceDao.findById(instanceId); + } + + // Check that the VM is in correct state. + if (vm == null || vm.getState() != State.Running) { + s_logger.info("Volume " + volume + " isn't attached to any running vm. Only volumes attached to a running" + + " VM can be migrated."); + return new Pair, List>(allPools, suitablePools); + } + + // Volume must be in Ready state to be migrated. + if (!Volume.State.Ready.equals(volume.getState())) { + s_logger.info("Volume " + volume + " must be in ready state for migration."); + return new Pair, List>(allPools, suitablePools); + } + + if (!_volumeMgr.volumeOnSharedStoragePool(volume)) { + s_logger.info("Volume " + volume + " is on local storage. It cannot be migrated to another pool."); + return new Pair, List>(allPools, suitablePools); + } + + // Check if the underlying hypervisor supports storage motion. + boolean storageMotionSupported = false; + Long hostId = vm.getHostId(); + if (hostId != null) { + HostVO host = _hostDao.findById(hostId); + HypervisorCapabilitiesVO capabilities = null; + if (host != null) { + capabilities = _hypervisorCapabilitiesDao.findByHypervisorTypeAndVersion(host.getHypervisorType(), + host.getHypervisorVersion()); + } else { + s_logger.error("Details of the host on which the vm " + vm + ", to which volume "+ volume + " is " + + "attached, couldn't be retrieved."); + } + + if (capabilities != null) { + storageMotionSupported = capabilities.isStorageMotionSupported(); + } else { + s_logger.error("Capabilities for host " + host + " couldn't be retrieved."); + } + } + + if (storageMotionSupported) { + // Source pool of the volume. + StoragePoolVO srcVolumePool = _poolDao.findById(volume.getPoolId()); + + // Get all the pools available. Only shared pools are considered because only a volume on a shared pools + // can be live migrated while the virtual machine stays on the same host. + List storagePools = _poolDao.findPoolsByTags(volume.getDataCenterId(), + volume.getPodId(), srcVolumePool.getClusterId(), null); + storagePools.remove(srcVolumePool); + for (StoragePoolVO pool : storagePools) { + if (pool.isShared()) { + allPools.add((StoragePool)this.dataStoreMgr.getPrimaryDataStore(pool.getId())); + } + } + + // Get all the suitable pools. + // Exclude the current pool from the list of pools to which the volume can be migrated. + ExcludeList avoid = new ExcludeList(); + avoid.addPool(srcVolumePool.getId()); + + // Volume stays in the same cluster after migration. + DataCenterDeployment plan = new DataCenterDeployment(volume.getDataCenterId(), volume.getPodId(), + srcVolumePool.getClusterId(), null, null, null); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + + DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); + DiskProfile diskProfile = new DiskProfile(volume, diskOffering, profile.getHypervisorType()); + + // Call the storage pool allocator to find the list of storage pools. + for (StoragePoolAllocator allocator : _storagePoolAllocators) { + List pools = allocator.allocateToPool(diskProfile, profile, plan, avoid, + StoragePoolAllocator.RETURN_UPTO_ALL); + if (pools != null && !pools.isEmpty()) { + suitablePools.addAll(pools); + break; + } + } + } + return new Pair, List>(allPools, suitablePools); } private Pair, Integer> searchForServers(Long startIndex, Long pageSize, Object name, Object type, Object state, Object zone, Object pod, Object cluster, Object id, Object keyword, - Object resourceState, Object haHosts) { + Object resourceState, Object haHosts, Object hypervisorType, Object hypervisorVersion) { Filter searchFilter = new Filter(HostVO.class, "id", Boolean.TRUE, startIndex, pageSize); SearchBuilder sb = _hostDao.createSearchBuilder(); @@ -800,6 +997,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe sb.and("podId", sb.entity().getPodId(), SearchCriteria.Op.EQ); sb.and("clusterId", sb.entity().getClusterId(), SearchCriteria.Op.EQ); sb.and("resourceState", sb.entity().getResourceState(), SearchCriteria.Op.EQ); + sb.and("hypervisorType", sb.entity().getHypervisorType(), SearchCriteria.Op.EQ); + sb.and("hypervisorVersion", sb.entity().getHypervisorVersion(), SearchCriteria.Op.EQ); String haTag = _haMgr.getHaTag(); SearchBuilder hostTagSearch = null; @@ -849,6 +1048,12 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe if (cluster != null) { sc.setParameters("clusterId", cluster); } + if (hypervisorType != null) { + sc.setParameters("hypervisorType", hypervisorType); + } + if (hypervisorVersion != null) { + sc.setParameters("hypervisorVersion", hypervisorVersion); + } if (resourceState != null) { sc.setParameters("resourceState", resourceState); @@ -1032,6 +1237,22 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe Object name = cmd.getConfigName(); Object category = cmd.getCategory(); Object keyword = cmd.getKeyword(); + Long id = cmd.getId(); + String scope = cmd.getScope(); + + if (scope!= null && !scope.isEmpty()) { + // getting the list of parameters at requested scope + try { + Config.ConfigurationParameterScope.valueOf(scope.toLowerCase()); + } catch (Exception e ) { + throw new InvalidParameterValueException("Invalid scope " + scope + " while listing configuration parameters"); + } + if (id == null) { + throw new InvalidParameterValueException("Invalid id null, id is needed corresponding to the scope"); + } + List configList = _configServer.getConfigListByScope(scope, id); + return new Pair, Integer>(configList, configList.size()); + } if (keyword != null) { SearchCriteria ssc = _configDao.createSearchCriteria(); @@ -1947,6 +2168,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe cmdList.add(CancelMaintenanceCmd.class); cmdList.add(DeleteHostCmd.class); cmdList.add(ListHostsCmd.class); + cmdList.add(FindHostsForMigrationCmd.class); cmdList.add(PrepareForMaintenanceCmd.class); cmdList.add(ReconnectHostCmd.class); cmdList.add(UpdateHostCmd.class); @@ -2003,6 +2225,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe cmdList.add(DeletePoolCmd.class); cmdList.add(ListS3sCmd.class); cmdList.add(ListStoragePoolsCmd.class); + cmdList.add(FindStoragePoolsForMigrationCmd.class); cmdList.add(PreparePrimaryStorageForMaintenanceCmd.class); cmdList.add(UpdateStoragePoolCmd.class); cmdList.add(AddSwiftCmd.class); @@ -2042,6 +2265,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe cmdList.add(ReleasePublicIpRangeCmd.class); cmdList.add(AssignVMCmd.class); cmdList.add(MigrateVMCmd.class); + cmdList.add(MigrateVirtualMachineWithVolumeCmd.class); cmdList.add(RecoverVMCmd.class); cmdList.add(CreatePrivateGatewayCmd.class); cmdList.add(CreateVPCOfferingCmd.class); @@ -2990,15 +3214,66 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe @Override public String getHashKey() { - // although we may have race conditioning here, database transaction - // serialization should + // although we may have race conditioning here, database transaction serialization should // give us the same key if (_hashKey == null) { - _hashKey = _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), Config.HashKey.getCategory(), UUID.randomUUID().toString()); + _hashKey = _configDao.getValueAndInitIfNotExist(Config.HashKey.key(), Config.HashKey.getCategory(), + getBase64EncodedRandomKey(128)); } return _hashKey; } + @Override + public String getEncryptionKey() { + if (_encryptionKey == null) { + _encryptionKey = _configDao.getValueAndInitIfNotExist(Config.EncryptionKey.key(), + Config.EncryptionKey.getCategory(), + getBase64EncodedRandomKey(128)); + } + return _encryptionKey; + } + + @Override + public String getEncryptionIV() { + if (_encryptionIV == null) { + _encryptionIV = _configDao.getValueAndInitIfNotExist(Config.EncryptionIV.key(), + Config.EncryptionIV.getCategory(), + getBase64EncodedRandomKey(128)); + } + return _encryptionIV; + } + + @Override + @DB + public void resetEncryptionKeyIV() { + + SearchBuilder sb = _configDao.createSearchBuilder(); + sb.and("name1", sb.entity().getName(), SearchCriteria.Op.EQ); + sb.or("name2", sb.entity().getName(), SearchCriteria.Op.EQ); + sb.done(); + + SearchCriteria sc = sb.create(); + sc.setParameters("name1", Config.EncryptionKey.key()); + sc.setParameters("name2", Config.EncryptionIV.key()); + + _configDao.expunge(sc); + _encryptionKey = null; + _encryptionIV = null; + } + + private static String getBase64EncodedRandomKey(int nBits) { + SecureRandom random; + try { + random = SecureRandom.getInstance("SHA1PRNG"); + byte[] keyBytes = new byte[nBits/8]; + random.nextBytes(keyBytes); + return Base64.encodeBase64URLSafeString(keyBytes); + } catch (NoSuchAlgorithmException e) { + s_logger.error("Unhandled exception: ", e); + } + return null; + } + @Override public SSHKeyPair createSSHKeyPair(CreateSSHKeyPairCmd cmd) { Account caller = UserContext.current().getCaller(); @@ -3321,15 +3596,4 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe } } - - @Override - public List listDeploymentPlanners() { - List plannersAvailable = new ArrayList(); - for (DeploymentPlanner planner : _planners) { - plannersAvailable.add(planner.getName()); - } - - return plannersAvailable; - } - } diff --git a/server/src/com/cloud/service/ServiceOfferingVO.java b/server/src/com/cloud/service/ServiceOfferingVO.java index a3da904688c..94a73515e6a 100755 --- a/server/src/com/cloud/service/ServiceOfferingVO.java +++ b/server/src/com/cloud/service/ServiceOfferingVO.java @@ -68,9 +68,6 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering @Column(name="sort_key") int sortKey; - @Column(name = "deployment_planner") - private String deploymentPlanner = "FirstFitPlanner"; - protected ServiceOfferingVO() { super(); } @@ -87,7 +84,6 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering this.volatileVm = false; this.default_use = defaultUse; this.vm_type = vm_type == null ? null : vm_type.toString().toLowerCase(); - this.deploymentPlanner = "FirstFitPlanner"; } public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, boolean limitCpuUse, boolean volatileVm, String displayText, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, Long domainId) { @@ -101,26 +97,11 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering this.limitCpuUse = limitCpuUse; this.volatileVm = volatileVm; this.vm_type = vm_type == null ? null : vm_type.toString().toLowerCase(); - this.deploymentPlanner = "FirstFitPlanner"; } public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, Integer rateMbps, Integer multicastRateMbps, boolean offerHA, boolean limitResourceUse, boolean volatileVm, String displayText, boolean useLocalStorage, boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, Long domainId, String hostTag) { this(name, cpu, ramSize, speed, rateMbps, multicastRateMbps, offerHA, limitResourceUse, volatileVm, displayText, useLocalStorage, recreatable, tags, systemUse, vm_type, domainId); this.hostTag = hostTag; - this.deploymentPlanner = "FirstFitPlanner"; - } - - public ServiceOfferingVO(String name, int cpu, int ramSize, int speed, Integer rateMbps, Integer multicastRateMbps, - boolean offerHA, boolean limitResourceUse, boolean volatileVm, String displayText, boolean useLocalStorage, - boolean recreatable, String tags, boolean systemUse, VirtualMachine.Type vm_type, Long domainId, - String hostTag, String deploymentPlanner) { - this(name, cpu, ramSize, speed, rateMbps, multicastRateMbps, offerHA, limitResourceUse, volatileVm, - displayText, useLocalStorage, recreatable, tags, systemUse, vm_type, domainId, hostTag); - if (deploymentPlanner != null) { - this.deploymentPlanner = deploymentPlanner; - } else { - this.deploymentPlanner = "FirstFitPlanner"; - } } @Override @@ -227,8 +208,4 @@ public class ServiceOfferingVO extends DiskOfferingVO implements ServiceOffering return volatileVm; } - public String getDeploymentPlanner() { - return deploymentPlanner; - } - } diff --git a/server/src/com/cloud/servlet/ConsoleProxyPasswordBasedEncryptor.java b/server/src/com/cloud/servlet/ConsoleProxyPasswordBasedEncryptor.java index 2638c8b31b9..7463ec097f3 100644 --- a/server/src/com/cloud/servlet/ConsoleProxyPasswordBasedEncryptor.java +++ b/server/src/com/cloud/servlet/ConsoleProxyPasswordBasedEncryptor.java @@ -16,13 +16,16 @@ // under the License. package com.cloud.servlet; +import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; @@ -35,26 +38,26 @@ import com.google.gson.GsonBuilder; public class ConsoleProxyPasswordBasedEncryptor { private static final Logger s_logger = Logger.getLogger(ConsoleProxyPasswordBasedEncryptor.class); - private String password; private Gson gson; + // key/IV will be set in 128 bit strength + private KeyIVPair keyIvPair; + public ConsoleProxyPasswordBasedEncryptor(String password) { - this.password = password; gson = new GsonBuilder().create(); + keyIvPair = gson.fromJson(password, KeyIVPair.class); } public String encryptText(String text) { if(text == null || text.isEmpty()) return text; - assert(password != null); - assert(!password.isEmpty()); - try { - Cipher cipher = Cipher.getInstance("DES"); - int maxKeySize = 8; - SecretKeySpec keySpec = new SecretKeySpec(normalizeKey(password.getBytes(), maxKeySize), "DES"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKeySpec keySpec = new SecretKeySpec(keyIvPair.getKeyBytes(), "AES"); + + cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(keyIvPair.getIvBytes())); + byte[] encryptedBytes = cipher.doFinal(text.getBytes()); return Base64.encodeBase64URLSafeString(encryptedBytes); } catch (NoSuchAlgorithmException e) { @@ -72,6 +75,9 @@ public class ConsoleProxyPasswordBasedEncryptor { } catch (InvalidKeyException e) { s_logger.error("Unexpected exception ", e); return null; + } catch (InvalidAlgorithmParameterException e) { + s_logger.error("Unexpected exception ", e); + return null; } } @@ -79,14 +85,10 @@ public class ConsoleProxyPasswordBasedEncryptor { if(encryptedText == null || encryptedText.isEmpty()) return encryptedText; - assert(password != null); - assert(!password.isEmpty()); - try { - Cipher cipher = Cipher.getInstance("DES"); - int maxKeySize = 8; - SecretKeySpec keySpec = new SecretKeySpec(normalizeKey(password.getBytes(), maxKeySize), "DES"); - cipher.init(Cipher.DECRYPT_MODE, keySpec); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKeySpec keySpec = new SecretKeySpec(keyIvPair.getKeyBytes(), "AES"); + cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(keyIvPair.getIvBytes())); byte[] encryptedBytes = Base64.decodeBase64(encryptedText); return new String(cipher.doFinal(encryptedBytes)); @@ -105,6 +107,9 @@ public class ConsoleProxyPasswordBasedEncryptor { } catch (InvalidKeyException e) { s_logger.error("Unexpected exception ", e); return null; + } catch (InvalidAlgorithmParameterException e) { + s_logger.error("Unexpected exception ", e); + return null; } } @@ -125,13 +130,63 @@ public class ConsoleProxyPasswordBasedEncryptor { return (T)gson.fromJson(json, clz); } - private static byte[] normalizeKey(byte[] keyBytes, int keySize) { - assert(keySize > 0); - byte[] key = new byte[keySize]; + public static class KeyIVPair { + String base64EncodedKeyBytes; + String base64EncodedIvBytes; - for(int i = 0; i < keyBytes.length; i++) - key[i%keySize] ^= keyBytes[i]; + public KeyIVPair() { + } - return key; + public KeyIVPair(String base64EncodedKeyBytes, String base64EncodedIvBytes) { + this.base64EncodedKeyBytes = base64EncodedKeyBytes; + this.base64EncodedIvBytes = base64EncodedIvBytes; + } + + public byte[] getKeyBytes() { + return Base64.decodeBase64(base64EncodedKeyBytes); + } + + public void setKeyBytes(byte[] keyBytes) { + base64EncodedKeyBytes = Base64.encodeBase64URLSafeString(keyBytes); + } + + public byte[] getIvBytes() { + return Base64.decodeBase64(base64EncodedIvBytes); + } + + public void setIvBytes(byte[] ivBytes) { + base64EncodedIvBytes = Base64.encodeBase64URLSafeString(ivBytes); + } } + + public static void main(String[] args) { + SecureRandom random; + try { + random = SecureRandom.getInstance("SHA1PRNG"); + byte[] keyBytes = new byte[16]; + random.nextBytes(keyBytes); + + byte[] ivBytes = new byte[16]; + random.nextBytes(ivBytes); + + KeyIVPair keyIvPair = new KeyIVPair("8x/xUBgX0Up+3UEo39dSeG277JhVj31+ElHkN5+EC0Q=", "Y2SUiIN6JXTdKNK/ZMDyVtLB7gAM9MCCiyrP1xd3bSQ="); + //keyIvPair.setKeyBytes(keyBytes); + //keyIvPair.setIvBytes(ivBytes); + + Gson gson = new GsonBuilder().create(); + ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(gson.toJson(keyIvPair)); + + String encrypted = encryptor.encryptText("Hello, world"); + + System.out.println("Encrypted result: " + encrypted); + + String decrypted = encryptor.decryptText(encrypted); + + System.out.println("Decrypted result: " + decrypted); + + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + } } + diff --git a/server/src/com/cloud/servlet/ConsoleProxyServlet.java b/server/src/com/cloud/servlet/ConsoleProxyServlet.java index c4b93349080..ebb91746268 100644 --- a/server/src/com/cloud/servlet/ConsoleProxyServlet.java +++ b/server/src/com/cloud/servlet/ConsoleProxyServlet.java @@ -55,6 +55,8 @@ import com.cloud.utils.db.Transaction; import com.cloud.vm.VMInstanceVO; import com.cloud.vm.VirtualMachine; import com.cloud.vm.VirtualMachineManager; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; /** * Thumbnail access : /console?cmd=thumbnail&vm=xxx&w=xxx&h=xxx @@ -75,6 +77,8 @@ public class ConsoleProxyServlet extends HttpServlet { static ManagementServer s_ms; + private Gson _gson = new GsonBuilder().create(); + public ConsoleProxyServlet() { } @@ -327,6 +331,14 @@ public class ConsoleProxyServlet extends HttpServlet { return new Ternary(host, tunnelUrl, tunnelSession); } + private String getEncryptorPassword() { + String key = _ms.getEncryptionKey(); + String iv = _ms.getEncryptionIV(); + + ConsoleProxyPasswordBasedEncryptor.KeyIVPair keyIvPair = new ConsoleProxyPasswordBasedEncryptor.KeyIVPair(key, iv); + return _gson.toJson(keyIvPair); + } + private String composeThumbnailUrl(String rootUrl, VMInstanceVO vm, HostVO hostVo, int w, int h) { StringBuffer sb = new StringBuffer(rootUrl); @@ -340,7 +352,7 @@ public class ConsoleProxyServlet extends HttpServlet { tag = _identityService.getIdentityUuid("vm_instance", tag); String ticket = genAccessTicket(host, String.valueOf(portInfo.second()), sid, tag); - ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(_ms.getHashKey()); + ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(getEncryptorPassword()); ConsoleProxyClientParam param = new ConsoleProxyClientParam(); param.setClientHostAddress(parsedHostInfo.first()); param.setClientHostPort(portInfo.second()); @@ -376,7 +388,7 @@ public class ConsoleProxyServlet extends HttpServlet { String tag = String.valueOf(vm.getId()); tag = _identityService.getIdentityUuid("vm_instance", tag); String ticket = genAccessTicket(host, String.valueOf(portInfo.second()), sid, tag); - ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(_ms.getHashKey()); + ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(getEncryptorPassword()); ConsoleProxyClientParam param = new ConsoleProxyClientParam(); param.setClientHostAddress(parsedHostInfo.first()); param.setClientHostPort(portInfo.second()); diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 4e410e4b41e..a182e39dd86 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -963,9 +963,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C DataStoreLifeCycle lifeCycle = storeProvider.getDataStoreLifeCycle(); DataStore store = dataStoreMgr.getDataStore( sPool.getId(), DataStoreRole.Primary); - lifeCycle.deleteDataStore(store); - - return false; + return lifeCycle.deleteDataStore(store); } @Override diff --git a/server/src/com/cloud/storage/VolumeManager.java b/server/src/com/cloud/storage/VolumeManager.java index 2101038f8f3..d198e5dd7df 100644 --- a/server/src/com/cloud/storage/VolumeManager.java +++ b/server/src/com/cloud/storage/VolumeManager.java @@ -18,6 +18,8 @@ */ package com.cloud.storage; +import java.util.Map; + import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd; import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd; import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; @@ -25,12 +27,15 @@ import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd; import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; +import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.deploy.DeployDestination; import com.cloud.exception.ConcurrentOperationException; import com.cloud.exception.InsufficientStorageCapacityException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.StorageUnavailableException; +import com.cloud.host.Host; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.storage.Volume.Type; import com.cloud.user.Account; @@ -80,6 +85,9 @@ public interface VolumeManager extends VolumeApiService { Volume migrateVolume(MigrateVolumeCmd cmd); + void migrateVolumes(T vm, VirtualMachineTO vmTo, Host srcHost, Host destHost, + Map volumeToPool); + boolean storageMigration( VirtualMachineProfile vm, StoragePool destPool); diff --git a/server/src/com/cloud/storage/VolumeManagerImpl.java b/server/src/com/cloud/storage/VolumeManagerImpl.java index 1e8edafe4e2..e57d393eb2d 100644 --- a/server/src/com/cloud/storage/VolumeManagerImpl.java +++ b/server/src/com/cloud/storage/VolumeManagerImpl.java @@ -28,6 +28,7 @@ import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.HashMap; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutionException; @@ -42,6 +43,7 @@ import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd; import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd; import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd; +import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManager; @@ -68,6 +70,7 @@ import com.cloud.agent.AgentManager; import com.cloud.agent.api.Answer; import com.cloud.agent.api.AttachVolumeAnswer; import com.cloud.agent.api.AttachVolumeCommand; +import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VolumeTO; import com.cloud.alert.AlertManager; import com.cloud.api.ApiDBUtils; @@ -102,11 +105,13 @@ import com.cloud.exception.InvalidParameterValueException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.StorageUnavailableException; +import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.hypervisor.HypervisorGuruManager; import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao; +import com.cloud.hypervisor.HypervisorCapabilitiesVO; import com.cloud.network.NetworkModel; import com.cloud.org.Grouping; import com.cloud.resource.ResourceManager; @@ -2003,7 +2008,7 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { public Volume migrateVolume(MigrateVolumeCmd cmd) { Long volumeId = cmd.getVolumeId(); Long storagePoolId = cmd.getStoragePoolId(); - + VolumeVO vol = _volsDao.findById(volumeId); if (vol == null) { throw new InvalidParameterValueException( @@ -2015,9 +2020,39 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { "Volume must be in ready state"); } - if (vol.getInstanceId() != null) { - throw new InvalidParameterValueException( - "Volume needs to be dettached from VM"); + boolean liveMigrateVolume = false; + Long instanceId = vol.getInstanceId(); + VMInstanceVO vm = null; + if (instanceId != null) { + vm = _vmInstanceDao.findById(instanceId); + } + + if (vm != null && vm.getState() == State.Running) { + // Check if the underlying hypervisor supports storage motion. + Long hostId = vm.getHostId(); + if (hostId != null) { + HostVO host = _hostDao.findById(hostId); + HypervisorCapabilitiesVO capabilities = null; + if (host != null) { + capabilities = _hypervisorCapabilitiesDao.findByHypervisorTypeAndVersion(host.getHypervisorType(), + host.getHypervisorVersion()); + } + + if (capabilities != null) { + liveMigrateVolume = capabilities.isStorageMotionSupported(); + } + } + } + + // If the disk is not attached to any VM then it can be moved. Otherwise, it needs to be attached to a vm + // running on a hypervisor that supports storage motion so that it be be migrated. + if (instanceId != null && !liveMigrateVolume) { + throw new InvalidParameterValueException("Volume needs to be detached from VM"); + } + + if (liveMigrateVolume && !cmd.isLiveMigrate()) { + throw new InvalidParameterValueException("The volume " + vol + "is attached to a vm and for migrating it " + + "the parameter livemigrate should be specified"); } StoragePool destPool = (StoragePool)this.dataStoreMgr.getDataStore(storagePoolId, DataStoreRole.Primary); @@ -2032,12 +2067,15 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { "Migration of volume from local storage pool is not supported"); } - Volume newVol = migrateVolume(vol, destPool); + Volume newVol = null; + if (liveMigrateVolume) { + newVol = liveMigrateVolume(vol, destPool); + } else { + newVol = migrateVolume(vol, destPool); + } return newVol; } - - @DB protected Volume migrateVolume(Volume volume, StoragePool destPool) { VolumeInfo vol = this.volFactory.getVolume(volume.getId()); @@ -2058,6 +2096,66 @@ public class VolumeManagerImpl extends ManagerBase implements VolumeManager { } } + @DB + protected Volume liveMigrateVolume(Volume volume, StoragePool destPool) { + VolumeInfo vol = this.volFactory.getVolume(volume.getId()); + AsyncCallFuture future = this.volService.migrateVolume(vol, (DataStore)destPool); + try { + VolumeApiResult result = future.get(); + if (result.isFailed()) { + s_logger.debug("migrate volume failed:" + result.getResult()); + return null; + } + return result.getVolume(); + } catch (InterruptedException e) { + s_logger.debug("migrate volume failed", e); + return null; + } catch (ExecutionException e) { + s_logger.debug("migrate volume failed", e); + return null; + } + } + + @Override + public void migrateVolumes(T vm, VirtualMachineTO vmTo, Host srcHost, Host destHost, + Map volumeToPool) { + // Check if all the vms being migrated belong to the vm. + // Check if the storage pool is of the right type. + // Create a VolumeInfo to DataStore map too. + Map volumeMap = new HashMap(); + for (Map.Entry entry : volumeToPool.entrySet()) { + VolumeVO volume = entry.getKey(); + StoragePoolVO storagePool = entry.getValue(); + StoragePool destPool = (StoragePool)this.dataStoreMgr.getDataStore(storagePool.getId(), + DataStoreRole.Primary); + + if (volume.getInstanceId() != vm.getId()) { + throw new CloudRuntimeException("Volume " + volume + " that has to be migrated doesn't belong to the" + + " instance " + vm); + } + + if (destPool == null) { + throw new CloudRuntimeException("Failed to find the destination storage pool " + storagePool.getId()); + } + + volumeMap.put(this.volFactory.getVolume(volume.getId()), (DataStore)destPool); + } + + AsyncCallFuture future = this.volService.migrateVolumes(volumeMap, vmTo, srcHost, destHost); + try { + CommandResult result = future.get(); + if (result.isFailed()) { + s_logger.debug("Failed to migrated vm " + vm + " along with its volumes. " + result.getResult()); + throw new CloudRuntimeException("Failed to migrated vm " + vm + " along with its volumes. " + + result.getResult()); + } + } catch (InterruptedException e) { + s_logger.debug("Failed to migrated vm " + vm + " along with its volumes.", e); + } catch (ExecutionException e) { + s_logger.debug("Failed to migrated vm " + vm + " along with its volumes.", e); + } + } + @Override public boolean storageMigration( VirtualMachineProfile vm, diff --git a/server/src/com/cloud/storage/dao/StoragePoolDetailsDaoImpl.java b/server/src/com/cloud/storage/dao/StoragePoolDetailsDaoImpl.java index 0d797ed3545..a0d5d0e6e97 100644 --- a/server/src/com/cloud/storage/dao/StoragePoolDetailsDaoImpl.java +++ b/server/src/com/cloud/storage/dao/StoragePoolDetailsDaoImpl.java @@ -72,4 +72,13 @@ public class StoragePoolDetailsDaoImpl extends GenericDaoBase sc = PoolSearch.create(); + sc.setParameters("pool", poolId); + sc.setParameters("name", name); + + return findOneIncludingRemovedBy(sc); + } } diff --git a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java index 3a453d50a72..490948ba5ae 100755 --- a/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java +++ b/server/src/com/cloud/storage/snapshot/SnapshotManagerImpl.java @@ -181,9 +181,8 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, private ResourceTagDao _resourceTagDao; @Inject private ConfigurationDao _configDao; - - @Inject - private VMSnapshotDao _vmSnapshotDao; + @Inject + private PrimaryDataStoreDao _primaryDataStoreDao; String _name; @Inject TemplateManager templateMgr; @@ -694,11 +693,11 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, S3TO s3 = _s3Mgr.getS3TO(); checkObjectStorageConfiguration(swift, s3); - + StoragePoolVO pool = _primaryDataStoreDao.findById(volume.getPoolId()); if (swift == null && s3 == null) { for (HostVO ssHost : ssHosts) { DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand( - null, null, ssHost.getStorageUrl(), dcId, + pool,null, null, ssHost.getStorageUrl(), dcId, accountId, volumeId, "", true); Answer answer = null; try { @@ -717,7 +716,7 @@ public class SnapshotManagerImpl extends ManagerBase implements SnapshotManager, } } else { DeleteSnapshotBackupCommand cmd = new DeleteSnapshotBackupCommand( - swift, s3, "", dcId, accountId, volumeId, "", true); + pool,swift, s3, "", dcId, accountId, volumeId, "", true); Answer answer = null; try { answer = _agentMgr.sendToSSVM(dcId, cmd); diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index 576440a2ce7..c7eaa64335e 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -1716,8 +1716,17 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, try { TemplateInfo tmplInfo = this.tmplFactory.getTemplate(templateId); - snapshot = _snapshotDao.findById(snapshotId); - ZoneScope scope = new ZoneScope(snapshot.getDataCenterId()); + ZoneScope scope = null; + Long zoneId = null; + if (snapshotId != null) { + snapshot = _snapshotDao.findById(snapshotId); + zoneId = snapshot.getDataCenterId(); + + } else if (volumeId != null) { + volume = _volumeDao.findById(volumeId); + zoneId = volume.getDataCenterId(); + } + scope = new ZoneScope(zoneId); List store = this.dataStoreMgr.getImageStores(scope); if (store.size() > 1) { throw new CloudRuntimeException("muliple image data store, don't know which one to use"); @@ -1727,7 +1736,6 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, SnapshotInfo snapInfo = this.snapshotFactory.getSnapshot(snapshotId); future = this.imageSvr.createTemplateFromSnapshotAsync(snapInfo, tmplInfo, store.get(0)); } else if (volumeId != null) { - volume = _volumeDao.findById(volumeId); VolumeInfo volInfo = this.volFactory.getVolume(volumeId); future = this.imageSvr.createTemplateFromVolumeAsync(volInfo, tmplInfo, store.get(0)); } else { @@ -1748,7 +1756,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, UsageEventVO usageEvent = new UsageEventVO( EventTypes.EVENT_TEMPLATE_CREATE, privateTemplate.getAccountId(), - snapshot.getDataCenterId(), + zoneId, privateTemplate.getId(), privateTemplate.getName(), null, privateTemplate.getSourceTemplateId(), privateTemplate.getSize()); @@ -1971,6 +1979,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, } } privateTemplate.setSourceTemplateId(sourceTemplateId); + privateTemplate.setImageDataStoreId(1); VMTemplateVO template = this._tmpltDao.persist(privateTemplate); // Increment the number of templates diff --git a/server/src/com/cloud/upgrade/dao/Upgrade410to420.java b/server/src/com/cloud/upgrade/dao/Upgrade410to420.java index b43e494893b..05e2b49ffe4 100644 --- a/server/src/com/cloud/upgrade/dao/Upgrade410to420.java +++ b/server/src/com/cloud/upgrade/dao/Upgrade410to420.java @@ -17,6 +17,10 @@ package com.cloud.upgrade.dao; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.script.Script; +import org.apache.log4j.Logger; + import java.io.File; import java.sql.Connection; import java.sql.PreparedStatement; @@ -24,11 +28,6 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.UUID; -import org.apache.log4j.Logger; - -import com.cloud.utils.exception.CloudRuntimeException; -import com.cloud.utils.script.Script; - public class Upgrade410to420 implements DbUpgrade { final static Logger s_logger = Logger.getLogger(Upgrade410to420.class); @@ -66,6 +65,7 @@ public class Upgrade410to420 implements DbUpgrade { updateCluster_details(conn); updatePrimaryStore(conn); addEgressFwRulesForSRXGuestNw(conn); + upgradeEIPNetworkOfferings(conn); } private void updateSystemVmTemplates(Connection conn) { @@ -365,4 +365,38 @@ public class Upgrade410to420 implements DbUpgrade { } } } + + private void upgradeEIPNetworkOfferings(Connection conn) { + + PreparedStatement pstmt = null; + ResultSet rs = null; + + try { + pstmt = conn.prepareStatement("select id, elastic_ip_service from `cloud`.`network_offerings` where traffic_type='Guest'"); + rs = pstmt.executeQuery(); + while (rs.next()) { + long id = rs.getLong(1); + // check if elastic IP service is enabled for network offering + if (rs.getLong(2) != 0) { + //update network offering with eip_associate_public_ip set to true + pstmt = conn.prepareStatement("UPDATE `cloud`.`network_offerings` set eip_associate_public_ip=? where id=?"); + pstmt.setBoolean(1, true); + pstmt.setLong(2, id); + pstmt.executeUpdate(); + } + } + } catch (SQLException e) { + throw new CloudRuntimeException("Unable to set elastic_ip_service for network offerings with EIP service enabled.", e); + } finally { + try { + if (rs != null) { + rs.close(); + } + if (pstmt != null) { + pstmt.close(); + } + } catch (SQLException e) { + } + } + } } diff --git a/server/src/com/cloud/usage/UsageNetworkOfferingVO.java b/server/src/com/cloud/usage/UsageNetworkOfferingVO.java index 72903345fdc..fdf758bd4e4 100644 --- a/server/src/com/cloud/usage/UsageNetworkOfferingVO.java +++ b/server/src/com/cloud/usage/UsageNetworkOfferingVO.java @@ -53,11 +53,14 @@ public class UsageNetworkOfferingVO { @Column(name="deleted") @Temporal(value=TemporalType.TIMESTAMP) private Date deleted = null; + + @Column(name="nic_id") + private Long nicId; protected UsageNetworkOfferingVO() { } - public UsageNetworkOfferingVO(long zoneId, long accountId, long domainId, long vmInstanceId, long networkOfferingId, boolean isDefault, Date created, Date deleted) { + public UsageNetworkOfferingVO(long zoneId, long accountId, long domainId, long vmInstanceId, long networkOfferingId, long nicId, boolean isDefault, Date created, Date deleted) { this.zoneId = zoneId; this.accountId = accountId; this.domainId = domainId; @@ -66,6 +69,7 @@ public class UsageNetworkOfferingVO { this.isDefault = isDefault; this.created = created; this.deleted = deleted; + this.nicId = nicId; } public long getZoneId() { @@ -102,4 +106,12 @@ public class UsageNetworkOfferingVO { public void setDeleted(Date deleted) { this.deleted = deleted; } + + public Long getNicId() { + return nicId; + } + + public void setNicId(Long nicId) { + this.nicId = nicId; + } } diff --git a/server/src/com/cloud/usage/dao/UsageNetworkOfferingDaoImpl.java b/server/src/com/cloud/usage/dao/UsageNetworkOfferingDaoImpl.java index a6539dd6ebb..c3fc5a6f6c1 100644 --- a/server/src/com/cloud/usage/dao/UsageNetworkOfferingDaoImpl.java +++ b/server/src/com/cloud/usage/dao/UsageNetworkOfferingDaoImpl.java @@ -39,15 +39,15 @@ public class UsageNetworkOfferingDaoImpl extends GenericDaoBase= ?)))"; - protected static final String GET_USAGE_RECORDS_BY_DOMAIN = "SELECT zone_id, account_id, domain_id, vm_instance_id, network_offering_id, is_default, created, deleted " + + protected static final String GET_USAGE_RECORDS_BY_DOMAIN = "SELECT zone_id, account_id, domain_id, vm_instance_id, network_offering_id, nic_id, is_default, created, deleted " + "FROM usage_network_offering " + "WHERE domain_id = ? AND ((deleted IS NULL) OR (created BETWEEN ? AND ?) OR " + " (deleted BETWEEN ? AND ?) OR ((created <= ?) AND (deleted >= ?)))"; - protected static final String GET_ALL_USAGE_RECORDS = "SELECT zone_id, account_id, domain_id, vm_instance_id, network_offering_id, is_default, created, deleted " + + protected static final String GET_ALL_USAGE_RECORDS = "SELECT zone_id, account_id, domain_id, vm_instance_id, network_offering_id, nic_id, is_default, created, deleted " + "FROM usage_network_offering " + "WHERE (deleted IS NULL) OR (created BETWEEN ? AND ?) OR " + " (deleted BETWEEN ? AND ?) OR ((created <= ?) AND (deleted >= ?))"; @@ -124,6 +124,7 @@ public class UsageNetworkOfferingDaoImpl extends GenericDaoBase volumeToPool) throws ResourceUnavailableException, ConcurrentOperationException, + ManagementServerException, VirtualMachineMigrationException { + // Access check - only root administrator can migrate VM. + Account caller = UserContext.current().getCaller(); + if (caller.getType() != Account.ACCOUNT_TYPE_ADMIN) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Caller is not a root admin, permission denied to migrate the VM"); + } + throw new PermissionDeniedException("No permission to migrate VM, Only Root Admin can migrate a VM!"); + } + + VMInstanceVO vm = _vmInstanceDao.findById(vmId); + if (vm == null) { + throw new InvalidParameterValueException("Unable to find the vm by id " + vmId); + } + + if (vm.getState() != State.Running) { + if (s_logger.isDebugEnabled()) { + s_logger.debug("VM is not Running, unable to migrate the vm " + vm); + } + CloudRuntimeException ex = new CloudRuntimeException("VM is not Running, unable to migrate the vm with" + + " specified id"); + ex.addProxyObject(vm, vmId, "vmId"); + throw ex; + } + + if (!vm.getHypervisorType().equals(HypervisorType.XenServer) && + !vm.getHypervisorType().equals(HypervisorType.VMware) && + !vm.getHypervisorType().equals(HypervisorType.KVM) && + !vm.getHypervisorType().equals(HypervisorType.Ovm)) { + throw new InvalidParameterValueException("Unsupported hypervisor type for vm migration, we support" + + " XenServer/VMware/KVM only"); + } + + long srcHostId = vm.getHostId(); + Host srcHost = _resourceMgr.getHost(srcHostId); + // Check if src and destination hosts are valid and migrating to same host + if (destinationHost.getId() == srcHostId) { + throw new InvalidParameterValueException("Cannot migrate VM, VM is already present on this host, please" + + " specify valid destination host to migrate the VM"); + } + + // Check if the source and destination hosts are of the same type and support storage motion. + if (!(srcHost.getHypervisorType().equals(destinationHost.getHypervisorType()) && + srcHost.getHypervisorVersion().equals(destinationHost.getHypervisorVersion()))) { + throw new CloudRuntimeException("The source and destination hosts are not of the same type and version. " + + "Source hypervisor type and version: " + srcHost.getHypervisorType().toString() + " " + + srcHost.getHypervisorVersion() + ", Destination hypervisor type and version: " + + destinationHost.getHypervisorType().toString() + " " + destinationHost.getHypervisorVersion()); + } + + HypervisorCapabilitiesVO capabilities = _hypervisorCapabilitiesDao.findByHypervisorTypeAndVersion( + srcHost.getHypervisorType(), srcHost.getHypervisorVersion()); + if (!capabilities.isStorageMotionSupported()) { + throw new CloudRuntimeException("Migration with storage isn't supported on hypervisor " + + srcHost.getHypervisorType() + " of version " + srcHost.getHypervisorVersion()); + } + + // Check if destination host is up. + if (destinationHost.getStatus() != com.cloud.host.Status.Up || + destinationHost.getResourceState() != ResourceState.Enabled){ + throw new CloudRuntimeException("Cannot migrate VM, destination host is not in correct state, has " + + "status: " + destinationHost.getStatus() + ", state: " + destinationHost.getResourceState()); + } + + List vmVolumes = _volsDao.findUsableVolumesForInstance(vm.getId()); + Map volToPoolObjectMap = new HashMap(); + if (!isVMUsingLocalStorage(vm) && destinationHost.getClusterId() == srcHost.getClusterId()) { + if (volumeToPool.isEmpty()) { + // If the destination host is in the same cluster and volumes do not have to be migrated across pools + // then fail the call. migrateVirtualMachine api should have been used. + throw new InvalidParameterValueException("Migration of the vm " + vm + "from host " + srcHost + + " to destination host " + destinationHost + " doesn't involve migrating the volumes."); + } + } + + if (!volumeToPool.isEmpty()) { + // Check if all the volumes and pools passed as parameters are valid. + for (Map.Entry entry : volumeToPool.entrySet()) { + VolumeVO volume = _volsDao.findByUuid(entry.getKey()); + StoragePoolVO pool = _storagePoolDao.findByUuid(entry.getValue()); + if (volume == null) { + throw new InvalidParameterValueException("There is no volume present with the given id " + + entry.getKey()); + } else if (pool == null) { + throw new InvalidParameterValueException("There is no storage pool present with the given id " + + entry.getValue()); + } else { + // Verify the volume given belongs to the vm. + if (!vmVolumes.contains(volume)) { + throw new InvalidParameterValueException("There volume " + volume + " doesn't belong to " + + "the virtual machine "+ vm + " that has to be migrated"); + } + volToPoolObjectMap.put(volume, pool); + } + } + } + + // Check if all the volumes are in the correct state. + for (VolumeVO volume : vmVolumes) { + if (volume.getState() != Volume.State.Ready) { + throw new CloudRuntimeException("Volume " + volume + " of the VM is not in Ready state. Cannot " + + "migrate the vm with its volumes."); + } + } + + // Check max guest vm limit for the destinationHost. + HostVO destinationHostVO = _hostDao.findById(destinationHost.getId()); + if(_capacityMgr.checkIfHostReachMaxGuestLimit(destinationHostVO)){ + throw new VirtualMachineMigrationException("Host name: " + destinationHost.getName() + ", hostId: " + + destinationHost.getId() + " already has max running vms (count includes system VMs). Cannot" + + " migrate to this host"); + } + + VMInstanceVO migratedVm = _itMgr.migrateWithStorage(vm, srcHostId, destinationHost.getId(), volToPoolObjectMap); + return migratedVm; + } + @DB @Override @ActionEvent(eventType = EventTypes.EVENT_VM_MOVE, eventDescription = "move VM to another user", async = false) diff --git a/server/src/com/cloud/vm/UserVmStateListener.java b/server/src/com/cloud/vm/UserVmStateListener.java index 04aa8180b67..3feecbb05f6 100644 --- a/server/src/com/cloud/vm/UserVmStateListener.java +++ b/server/src/com/cloud/vm/UserVmStateListener.java @@ -72,21 +72,26 @@ public class UserVmStateListener implements StateListener nics = _nicDao.listByVmId(vo.getId()); for (NicVO nic : nics) { NetworkVO network = _networkDao.findById(nic.getNetworkId()); - UsageEventUtils.saveUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vo.getAccountId(), vo.getDataCenterId(), vo.getId(), null, network.getNetworkOfferingId(), null, 0L); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vo.getAccountId(), vo.getDataCenterId(), + vo.getId(), Long.toString(nic.getId()),network.getNetworkOfferingId(), null, 0L, vo.getClass().getName(), vo.getUuid()); } } else if (VirtualMachine.State.isVmDestroyed(oldState, event, newState)) { - UsageEventUtils.saveUsageEvent(EventTypes.EVENT_VM_DESTROY, vo.getAccountId(), vo.getDataCenterId(), vo.getId(), vo.getHostName(), vo.getServiceOfferingId(), - vo.getTemplateId(), vo.getHypervisorType().toString()); + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_DESTROY, vo.getAccountId(), vo.getDataCenterId(), vo.getId(), + vo.getHostName(), vo.getServiceOfferingId(),vo.getTemplateId(), vo.getHypervisorType().toString(), + vo.getClass().getName(), vo.getUuid()); } return true; } diff --git a/server/src/com/cloud/vm/VirtualMachineManager.java b/server/src/com/cloud/vm/VirtualMachineManager.java index 4a30d97cc54..ea9f7bbb2c9 100644 --- a/server/src/com/cloud/vm/VirtualMachineManager.java +++ b/server/src/com/cloud/vm/VirtualMachineManager.java @@ -20,6 +20,7 @@ import java.net.URI; import java.util.List; import java.util.Map; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; @@ -41,6 +42,7 @@ import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.StoragePool; import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.VolumeVO; import com.cloud.user.Account; import com.cloud.user.User; import com.cloud.utils.Pair; @@ -109,6 +111,8 @@ public interface VirtualMachineManager extends Manager { T migrate(T vm, long srcHostId, DeployDestination dest) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException; + T migrateWithStorage(T vm, long srcId, long destId, Map volumeToPool) throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException; + T reboot(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException; T advanceReboot(T vm, Map params, User caller, Account account) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException, OperationTimedoutException; diff --git a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java index 40725314f46..b613917edd7 100755 --- a/server/src/com/cloud/vm/VirtualMachineManagerImpl.java +++ b/server/src/com/cloud/vm/VirtualMachineManagerImpl.java @@ -38,7 +38,12 @@ import javax.naming.ConfigurationException; import com.cloud.capacity.CapacityManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import com.cloud.dc.*; import com.cloud.agent.api.*; @@ -50,6 +55,8 @@ import com.cloud.agent.Listener; import com.cloud.agent.api.StartupRoutingCommand.VmState; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.agent.api.to.StorageFilerTO; +import com.cloud.agent.api.to.VolumeTO; import com.cloud.agent.manager.Commands; import com.cloud.agent.manager.allocator.HostAllocator; import com.cloud.alert.AlertManager; @@ -57,6 +64,7 @@ import com.cloud.cluster.ClusterManager; import com.cloud.configuration.Config; import com.cloud.configuration.ConfigurationManager; import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.DataCenter; import com.cloud.dc.DataCenterVO; import com.cloud.dc.HostPodVO; @@ -70,6 +78,8 @@ import com.cloud.deploy.DeploymentPlanner; import com.cloud.deploy.DeploymentPlanner.ExcludeList; import com.cloud.deploy.DeploymentPlanningManager; import com.cloud.domain.dao.DomainDao; +import com.cloud.event.EventTypes; +import com.cloud.event.UsageEventUtils; import com.cloud.exception.AffinityConflictException; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConcurrentOperationException; @@ -111,10 +121,13 @@ import com.cloud.storage.Volume; import com.cloud.storage.Volume.Type; import com.cloud.storage.VolumeManager; import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.DiskOfferingDao; import com.cloud.storage.dao.GuestOSCategoryDao; import com.cloud.storage.dao.GuestOSDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.dao.StoragePoolHostDao; +import com.cloud.storage.snapshot.SnapshotManager; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.User; @@ -164,6 +177,8 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @Inject protected ServiceOfferingDao _offeringDao; @Inject + protected DiskOfferingDao _diskOfferingDao; + @Inject protected VMTemplateDao _templateDao; @Inject protected UserDao _userDao; @@ -202,13 +217,19 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac @Inject protected DataCenterDao _dcDao; @Inject + protected ClusterDao _clusterDao; + @Inject protected PrimaryDataStoreDao _storagePoolDao; @Inject protected HypervisorGuruManager _hvGuruMgr; @Inject protected NetworkDao _networkDao; @Inject + protected StoragePoolHostDao _poolHostDao; + @Inject protected VMSnapshotDao _vmSnapshotDao; + @Inject + protected VolumeDataFactory volFactory; protected List _planners; public List getPlanners() { @@ -226,9 +247,15 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac this._hostAllocators = _hostAllocators; } - @Inject + @Inject + protected List _storagePoolAllocators; + + @Inject protected ResourceManager _resourceMgr; + @Inject + protected SnapshotManager _snapshotMgr; + @Inject protected VMSnapshotManager _vmSnapshotMgr = null; @Inject @@ -866,6 +893,11 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } + if (startedVm == null) { + throw new CloudRuntimeException("Unable to start instance '" + vm.getHostName() + + "' (" + vm.getUuid() + "), see management server log for details"); + } + return startedVm; } @@ -1422,6 +1454,189 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac } } + private Map getPoolListForVolumesForMigration(VirtualMachineProfile profile, + Host host, Map volumeToPool) { + List allVolumes = _volsDao.findUsableVolumesForInstance(profile.getId()); + for (VolumeVO volume : allVolumes) { + StoragePoolVO pool = volumeToPool.get(volume); + DiskOfferingVO diskOffering = _diskOfferingDao.findById(volume.getDiskOfferingId()); + StoragePoolVO currentPool = _storagePoolDao.findById(volume.getPoolId()); + if (pool != null) { + // Check if pool is accessible from the destination host and disk offering with which the volume was + // created is compliant with the pool type. + if (_poolHostDao.findByPoolHost(pool.getId(), host.getId()) == null || + pool.isLocal() != diskOffering.getUseLocalStorage()) { + // Cannot find a pool for the volume. Throw an exception. + throw new CloudRuntimeException("Cannot migrate volume " + volume + " to storage pool " + pool + + " while migrating vm to host " + host + ". Either the pool is not accessible from the " + + "host or because of the offering with which the volume is created it cannot be placed on " + + "the given pool."); + } else if (pool.getId() == currentPool.getId()){ + // If the pool to migrate too is the same as current pool, remove the volume from the list of + // volumes to be migrated. + volumeToPool.remove(volume); + } + } else { + // Find a suitable pool for the volume. Call the storage pool allocator to find the list of pools. + DiskProfile diskProfile = new DiskProfile(volume, diskOffering, profile.getHypervisorType()); + DataCenterDeployment plan = new DataCenterDeployment(host.getDataCenterId(), host.getPodId(), + host.getClusterId(), host.getId(), null, null); + ExcludeList avoid = new ExcludeList(); + boolean currentPoolAvailable = false; + + for (StoragePoolAllocator allocator : _storagePoolAllocators) { + List poolList = allocator.allocateToPool(diskProfile, profile, plan, avoid, + StoragePoolAllocator.RETURN_UPTO_ALL); + if (poolList != null && !poolList.isEmpty()) { + // Volume needs to be migrated. Pick the first pool from the list. Add a mapping to migrate the + // volume to a pool only if it is required; that is the current pool on which the volume resides + // is not available on the destination host. + if (poolList.contains(currentPool)) { + currentPoolAvailable = true; + } else { + volumeToPool.put(volume, _storagePoolDao.findByUuid(poolList.get(0).getUuid())); + } + + break; + } + } + + if (!currentPoolAvailable && !volumeToPool.containsKey(volume)) { + // Cannot find a pool for the volume. Throw an exception. + throw new CloudRuntimeException("Cannot find a storage pool which is available for volume " + + volume + " while migrating virtual machine " + profile.getVirtualMachine() + " to host " + + host); + } + } + } + + return volumeToPool; + } + + private void moveVmToMigratingState(T vm, Long hostId, ItWorkVO work) + throws ConcurrentOperationException { + // Put the vm in migrating state. + try { + if (!changeState(vm, Event.MigrationRequested, hostId, work, Step.Migrating)) { + s_logger.info("Migration cancelled because state has changed: " + vm); + throw new ConcurrentOperationException("Migration cancelled because state has changed: " + vm); + } + } catch (NoTransitionException e) { + s_logger.info("Migration cancelled because " + e.getMessage()); + throw new ConcurrentOperationException("Migration cancelled because " + e.getMessage()); + } + } + + private void moveVmOutofMigratingStateOnSuccess(T vm, Long hostId, ItWorkVO work) + throws ConcurrentOperationException { + // Put the vm in running state. + try { + if (!changeState(vm, Event.OperationSucceeded, hostId, work, Step.Started)) { + s_logger.error("Unable to change the state for " + vm); + throw new ConcurrentOperationException("Unable to change the state for " + vm); + } + } catch (NoTransitionException e) { + s_logger.error("Unable to change state due to " + e.getMessage()); + throw new ConcurrentOperationException("Unable to change state due to " + e.getMessage()); + } + } + + @Override + public T migrateWithStorage(T vm, long srcHostId, long destHostId, + Map volumeToPool) throws ResourceUnavailableException, ConcurrentOperationException, + ManagementServerException, VirtualMachineMigrationException { + + HostVO srcHost = _hostDao.findById(srcHostId); + HostVO destHost = _hostDao.findById(destHostId); + VirtualMachineGuru vmGuru = getVmGuru(vm); + + DataCenterVO dc = _dcDao.findById(destHost.getDataCenterId()); + HostPodVO pod = _podDao.findById(destHost.getPodId()); + Cluster cluster = _clusterDao.findById(destHost.getClusterId()); + DeployDestination destination = new DeployDestination(dc, pod, cluster, destHost); + + // Create a map of which volume should go in which storage pool. + long vmId = vm.getId(); + vm = vmGuru.findById(vmId); + VirtualMachineProfile profile = new VirtualMachineProfileImpl(vm); + volumeToPool = getPoolListForVolumesForMigration(profile, destHost, volumeToPool); + + // If none of the volumes have to be migrated, fail the call. Administrator needs to make a call for migrating + // a vm and not migrating a vm with storage. + if (volumeToPool.isEmpty()) { + throw new InvalidParameterValueException("Migration of the vm " + vm + "from host " + srcHost + + " to destination host " + destHost + " doesn't involve migrating the volumes."); + } + + short alertType = AlertManager.ALERT_TYPE_USERVM_MIGRATE; + if (VirtualMachine.Type.DomainRouter.equals(vm.getType())) { + alertType = AlertManager.ALERT_TYPE_DOMAIN_ROUTER_MIGRATE; + } else if (VirtualMachine.Type.ConsoleProxy.equals(vm.getType())) { + alertType = AlertManager.ALERT_TYPE_CONSOLE_PROXY_MIGRATE; + } + + _networkMgr.prepareNicForMigration(profile, destination); + this.volumeMgr.prepareForMigration(profile, destination); + HypervisorGuru hvGuru = _hvGuruMgr.getGuru(vm.getHypervisorType()); + VirtualMachineTO to = hvGuru.implement(profile); + + ItWorkVO work = new ItWorkVO(UUID.randomUUID().toString(), _nodeId, State.Migrating, vm.getType(), vm.getId()); + work.setStep(Step.Prepare); + work.setResourceType(ItWorkVO.ResourceType.Host); + work.setResourceId(destHostId); + work = _workDao.persist(work); + + // Put the vm in migrating state. + vm.setLastHostId(srcHostId); + moveVmToMigratingState(vm, destHostId, work); + + boolean migrated = false; + try { + // Migrate the vm and its volume. + this.volumeMgr.migrateVolumes(vm, to, srcHost, destHost, volumeToPool); + + // Put the vm back to running state. + moveVmOutofMigratingStateOnSuccess(vm, destHost.getId(), work); + + try { + if (!checkVmOnHost(vm, destHostId)) { + s_logger.error("Vm not found on destination host. Unable to complete migration for " + vm); + try { + _agentMgr.send(srcHostId, new Commands(cleanup(vm.getInstanceName())), null); + } catch (AgentUnavailableException e) { + s_logger.error("AgentUnavailableException while cleanup on source host: " + srcHostId); + } + cleanup(vmGuru, new VirtualMachineProfileImpl(vm), work, Event.AgentReportStopped, true, + _accountMgr.getSystemUser(), _accountMgr.getSystemAccount()); + return null; + } + } catch (OperationTimedoutException e) { + s_logger.warn("Error while checking the vm " + vm + " is on host " + destHost, e); + } + + migrated = true; + return vm; + } finally { + if (!migrated) { + s_logger.info("Migration was unsuccessful. Cleaning up: " + vm); + _alertMgr.sendAlert(alertType, srcHost.getDataCenterId(), srcHost.getPodId(), "Unable to migrate vm " + + vm.getInstanceName() + " from host " + srcHost.getName() + " in zone " + dc.getName() + + " and pod " + dc.getName(), "Migrate Command failed. Please check logs."); + try { + _agentMgr.send(destHostId, new Commands(cleanup(vm.getInstanceName())), null); + stateTransitTo(vm, Event.OperationFailed, srcHostId); + } catch (AgentUnavailableException e) { + s_logger.warn("Looks like the destination Host is unavailable for cleanup.", e); + } catch (NoTransitionException e) { + s_logger.error("Error while transitioning vm from migrating to running state.", e); + } + } + + work.setStep(Step.Done); + _workDao.update(work.getId(), work); + } + } + @Override public VirtualMachineTO toVmTO(VirtualMachineProfile profile) { HypervisorGuru hvGuru = _hvGuruMgr.getGuru(profile.getVirtualMachine().getHypervisorType()); @@ -2532,13 +2747,27 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac VirtualMachineGuru vmGuru = getVmGuru(vmVO); s_logger.debug("Plugging nic for vm " + vm + " in network " + network); - if (vmGuru.plugNic(network, nicTO, vmTO, context, dest)) { - s_logger.debug("Nic is plugged successfully for vm " + vm + " in network " + network + ". Vm is a part of network now"); - return nic; - } else { - s_logger.warn("Failed to plug nic to the vm " + vm + " in network " + network); - return null; - } + + boolean result = false; + try{ + result = vmGuru.plugNic(network, nicTO, vmTO, context, dest); + if (result) { + s_logger.debug("Nic is plugged successfully for vm " + vm + " in network " + network + ". Vm is a part of network now"); + long isDefault = (nic.isDefaultNic()) ? 1 : 0; + // insert nic's Id into DB as resource_name + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vmVO.getAccountId(), + vmVO.getDataCenterId(), vmVO.getId(), Long.toString(nic.getId()), nic.getNetworkId(), + null, isDefault, VirtualMachine.class.getName(), vmVO.getUuid()); + return nic; + } else { + s_logger.warn("Failed to plug nic to the vm " + vm + " in network " + network); + return null; + } + }finally{ + if(!result){ + _networkMgr.removeNic(vmProfile, _nicsDao.findById(nic.getId())); + } + } } else if (vm.getState() == State.Stopped) { //1) allocate nic return _networkMgr.createNicForVm(network, requested, context, vmProfile, false); @@ -2592,6 +2821,10 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac boolean result = vmGuru.unplugNic(network, nicTO, vmTO, context, dest); if (result) { s_logger.debug("Nic is unplugged successfully for vm " + vm + " in network " + network ); + long isDefault = (nic.isDefaultNic()) ? 1 : 0; + UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), + vm.getId(), Long.toString(nic.getId()), network.getNetworkOfferingId(), null, + isDefault, VirtualMachine.class.getName(), vm.getUuid()); } else { s_logger.warn("Failed to unplug nic for the vm " + vm + " from network " + network); return false; diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java index 2b490efe6e5..fc2cfcf8d95 100644 --- a/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java +++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupServiceImpl.java @@ -295,7 +295,7 @@ public class AffinityGroupServiceImpl extends ManagerBase implements AffinityGro if (!status) { return false; } - if ((newState == State.Expunging)) { + if ((newState == State.Expunging) || (newState == State.Error)) { // cleanup all affinity groups associations of the Expunged VM SearchCriteria sc = _affinityGroupVMMapDao.createSearchCriteria(); sc.addAnd("instanceId", SearchCriteria.Op.EQ, vo.getId()); diff --git a/server/src/org/apache/cloudstack/affinity/AffinityGroupVO.java b/server/src/org/apache/cloudstack/affinity/AffinityGroupVO.java index b6c4a027484..f418cefd781 100644 --- a/server/src/org/apache/cloudstack/affinity/AffinityGroupVO.java +++ b/server/src/org/apache/cloudstack/affinity/AffinityGroupVO.java @@ -107,7 +107,7 @@ public class AffinityGroupVO implements AffinityGroup { @Override public String toString() { StringBuilder buf = new StringBuilder("AffinityGroup["); - buf.append(id).append("|").append(name).append("|").append(type).append("]"); + buf.append(uuid).append("]"); return buf.toString(); } diff --git a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java index 696e6e9aa48..1ed2618f6cb 100644 --- a/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java +++ b/server/src/org/apache/cloudstack/region/gslb/GlobalLoadBalancingRulesServiceImpl.java @@ -392,6 +392,7 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR //mark all the GSLB-LB mapping to be in revoke state for (GlobalLoadBalancerLbRuleMapVO gslbLbMap : gslbLbMapVos) { gslbLbMap.setRevoke(true); + _gslbLbMapDao.update(gslbLbMap.getId(), gslbLbMap); } } @@ -411,6 +412,16 @@ public class GlobalLoadBalancingRulesServiceImpl implements GlobalLoadBalancingR throw new CloudRuntimeException("Failed to update the gloabal load balancer"); } + txn.start(); + //remove all mappings between GSLB rule and load balancer rules + if (gslbLbMapVos != null) { + for (GlobalLoadBalancerLbRuleMapVO gslbLbMap : gslbLbMapVos) { + _gslbLbMapDao.remove(gslbLbMap.getId()); + } + } + //remove the GSLB rule itself + _gslbRuleDao.remove(gslbRuleId); + txn.commit(); return success; } diff --git a/server/test/com/cloud/configuration/ConfigurationManagerTest.java b/server/test/com/cloud/configuration/ConfigurationManagerTest.java index ee98d53c922..5c1cabfe774 100755 --- a/server/test/com/cloud/configuration/ConfigurationManagerTest.java +++ b/server/test/com/cloud/configuration/ConfigurationManagerTest.java @@ -224,7 +224,7 @@ public class ConfigurationManagerTest { try { configurationMgr.dedicatePublicIpRange(dedicatePublicIpRangesCmd); } catch (Exception e) { - Assert.assertTrue(e.getMessage().contains("Please specify a valid Public IP range id")); + Assert.assertTrue(e.getMessage().contains("Unable to find vlan by id")); } finally { txn.close("runDedicatePublicIpRangeInvalidRange"); } @@ -306,7 +306,7 @@ public class ConfigurationManagerTest { try { configurationMgr.dedicatePublicIpRange(dedicatePublicIpRangesCmd); } catch (Exception e) { - Assert.assertTrue(e.getMessage().contains("Public IP address in range is already allocated to another account")); + Assert.assertTrue(e.getMessage().contains("Public IP address in range is allocated to another account")); } finally { txn.close("runDedicatePublicIpRangeIPAdressAllocated"); } diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java b/server/test/com/cloud/network/MockNetworkManagerImpl.java index 9042f03d4a7..6a0263ee334 100755 --- a/server/test/com/cloud/network/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java @@ -322,7 +322,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage } @Override - public PhysicalNetwork updatePhysicalNetwork(Long id, String networkSpeed, List tags, String newVnetRangeString, String state) { + public PhysicalNetwork updatePhysicalNetwork(Long id, String networkSpeed, List tags, String newVnetRangeString, String state, String removeVlan) { // TODO Auto-generated method stub return null; } diff --git a/server/test/com/cloud/network/UpdatePhysicalNetworkTest.java b/server/test/com/cloud/network/UpdatePhysicalNetworkTest.java new file mode 100644 index 00000000000..ca9d149214f --- /dev/null +++ b/server/test/com/cloud/network/UpdatePhysicalNetworkTest.java @@ -0,0 +1,68 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.network; +import com.cloud.capacity.CapacityManagerImpl; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.network.NetworkServiceImpl; +import com.cloud.network.dao.PhysicalNetworkDao; +import com.cloud.network.dao.PhysicalNetworkVO; +import com.cloud.utils.Pair; +import org.junit.Test; +import org.junit.*; +import org.mockito.ArgumentCaptor; +import org.mockito.MockitoAnnotations.*; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + + +public class UpdatePhysicalNetworkTest { + private PhysicalNetworkDao _physicalNetworkDao = mock(PhysicalNetworkDao.class); + private DataCenterDao _datacenterDao = mock(DataCenterDao.class); + private DataCenterVO datacentervo = mock(DataCenterVO.class); + private PhysicalNetworkVO physicalNetworkVO = mock(PhysicalNetworkVO.class); + List> existingRange = new ArrayList>(); + ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(String.class); + + public NetworkServiceImpl setUp() { + NetworkServiceImpl networkService = new NetworkServiceImpl(); + ((NetworkServiceImpl)networkService)._dcDao= _datacenterDao; + networkService._physicalNetworkDao = _physicalNetworkDao; + return networkService; + } + + @Test + public void updatePhysicalNetworkTest(){ + NetworkServiceImpl networkService = setUp(); + existingRange.add(new Pair(520, 524)); + when(_physicalNetworkDao.findById(anyLong())).thenReturn(physicalNetworkVO); + when(_datacenterDao.findById(anyLong())).thenReturn(datacentervo); + when(_physicalNetworkDao.update(anyLong(), any(physicalNetworkVO.getClass()))).thenReturn(true); + when(physicalNetworkVO.getVnet()).thenReturn(existingRange); + networkService.updatePhysicalNetwork(1l, null, null, "525-530", null, null); + verify(physicalNetworkVO).setVnet(argumentCaptor.capture()); + assertEquals("520-530", argumentCaptor.getValue()); + } + +} diff --git a/server/test/com/cloud/vm/MockUserVmManagerImpl.java b/server/test/com/cloud/vm/MockUserVmManagerImpl.java index fd826d9e86e..0d0a8f4a323 100644 --- a/server/test/com/cloud/vm/MockUserVmManagerImpl.java +++ b/server/test/com/cloud/vm/MockUserVmManagerImpl.java @@ -366,6 +366,14 @@ public class MockUserVmManagerImpl extends ManagerBase implements UserVmManager, return null; } + @Override + public VirtualMachine migrateVirtualMachineWithVolume(Long vmId, Host destinationHost, Map volumeToPool) + throws ResourceUnavailableException, ConcurrentOperationException, ManagementServerException, + VirtualMachineMigrationException { + // TODO Auto-generated method stub + return null; + } + @Override public UserVm moveVMToUser(AssignVMCmd moveUserVMCmd) throws ResourceAllocationException, ConcurrentOperationException, diff --git a/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java b/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java index 4917e77cdef..94ddea68879 100755 --- a/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java +++ b/server/test/com/cloud/vm/MockVirtualMachineManagerImpl.java @@ -23,6 +23,7 @@ import java.util.Map; import javax.ejb.Local; import javax.naming.ConfigurationException; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.springframework.stereotype.Component; import com.cloud.agent.api.to.NicTO; @@ -45,6 +46,7 @@ import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.DiskOfferingVO; import com.cloud.storage.StoragePool; import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.VolumeVO; import com.cloud.user.Account; import com.cloud.user.User; import com.cloud.utils.Pair; @@ -142,6 +144,14 @@ public class MockVirtualMachineManagerImpl extends ManagerBase implements Virtua return null; } + @Override + public T migrateWithStorage(T vm, long srcHostId, long destHostId, + Map volumeToPool) throws ResourceUnavailableException, + ConcurrentOperationException, ManagementServerException, VirtualMachineMigrationException { + // TODO Auto-generated method stub + return null; + } + @Override public VMInstanceVO findByIdAndType(Type type, long vmId) { // TODO Auto-generated method stub diff --git a/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java b/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java index 322f051c675..dd51e74a618 100644 --- a/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java +++ b/server/test/com/cloud/vm/VirtualMachineManagerImplTest.java @@ -31,6 +31,41 @@ import com.cloud.service.ServiceOfferingVO; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VolumeManager; import com.cloud.storage.VolumeVO; +import com.cloud.agent.api.PrepareForMigrationAnswer; +import com.cloud.agent.api.PrepareForMigrationCommand; +import com.cloud.agent.api.MigrateWithStorageAnswer; +import com.cloud.agent.api.MigrateWithStorageCommand; +import com.cloud.agent.api.MigrateWithStorageReceiveAnswer; +import com.cloud.agent.api.MigrateWithStorageReceiveCommand; +import com.cloud.agent.api.MigrateWithStorageSendAnswer; +import com.cloud.agent.api.MigrateWithStorageSendCommand; +import com.cloud.agent.api.MigrateWithStorageCompleteAnswer; +import com.cloud.agent.api.MigrateWithStorageCompleteCommand; +import com.cloud.agent.api.CheckVirtualMachineAnswer; +import com.cloud.agent.api.CheckVirtualMachineCommand; +import com.cloud.capacity.CapacityManager; +import com.cloud.configuration.ConfigurationManager; +import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.dc.dao.HostPodDao; +import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.ManagementServerException; +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.exception.VirtualMachineMigrationException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.host.HostVO; +import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.HypervisorGuru; +import com.cloud.hypervisor.HypervisorGuruManager; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.network.NetworkManager; +import com.cloud.storage.DiskOfferingVO; +import com.cloud.storage.StoragePoolHostVO; +import com.cloud.storage.VolumeManager; +import com.cloud.storage.VolumeVO; +import com.cloud.storage.dao.DiskOfferingDao; +import com.cloud.storage.dao.StoragePoolHostDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VolumeDao; import com.cloud.user.*; @@ -41,20 +76,33 @@ import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; import org.apache.cloudstack.api.command.user.vm.RestoreVMCmd; import org.apache.cloudstack.api.command.user.vm.ScaleVMCmd; +import com.cloud.utils.Pair; +import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.vm.dao.UserVmDao; +import com.cloud.vm.dao.VMInstanceDao; +import com.cloud.vm.snapshot.VMSnapshotManager; +import com.cloud.vm.VirtualMachine.Event; +import com.cloud.vm.VirtualMachine.State; + +import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; + import org.junit.Test; import org.junit.Before; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import static org.mockito.Matchers.anyLong; import static org.mockito.Mockito.*; - import java.lang.reflect.Field; import java.util.List; +import java.util.Map; +import java.util.HashMap; +import java.util.Iterator; public class VirtualMachineManagerImplTest { - @Spy VirtualMachineManagerImpl _vmMgr = new VirtualMachineManagerImpl(); @Mock VolumeManager _storageMgr; @@ -106,6 +154,25 @@ public class VirtualMachineManagerImplTest { List _rootVols; @Mock ItWorkVO _work; + + @Mock ClusterDao _clusterDao; + @Mock HostPodDao _podDao; + @Mock DataCenterDao _dcDao; + @Mock DiskOfferingDao _diskOfferingDao; + @Mock PrimaryDataStoreDao _storagePoolDao; + @Mock StoragePoolHostDao _poolHostDao; + @Mock NetworkManager _networkMgr; + @Mock HypervisorGuruManager _hvGuruMgr; + @Mock VMSnapshotManager _vmSnapshotMgr; + + // Mock objects for vm migration with storage test. + @Mock DiskOfferingVO _diskOfferingMock; + @Mock StoragePoolVO _srcStoragePoolMock; + @Mock StoragePoolVO _destStoragePoolMock; + @Mock HostVO _srcHostMock; + @Mock HostVO _destHostMock; + @Mock Map _volumeToPoolMock; + @Before public void setup(){ MockitoAnnotations.initMocks(this); @@ -122,6 +189,16 @@ public class VirtualMachineManagerImplTest { _vmMgr._nodeId = 1L; _vmMgr._workDao = _workDao; _vmMgr._agentMgr = _agentMgr; + _vmMgr._podDao = _podDao; + _vmMgr._clusterDao = _clusterDao; + _vmMgr._dcDao = _dcDao; + _vmMgr._diskOfferingDao = _diskOfferingDao; + _vmMgr._storagePoolDao = _storagePoolDao; + _vmMgr._poolHostDao= _poolHostDao; + _vmMgr._networkMgr = _networkMgr; + _vmMgr._hvGuruMgr = _hvGuruMgr; + _vmMgr._vmSnapshotMgr = _vmSnapshotMgr; + _vmMgr._vmDao = _vmInstanceDao; when(_vmMock.getId()).thenReturn(314l); when(_vmInstance.getId()).thenReturn(1L); @@ -204,5 +281,155 @@ public class VirtualMachineManagerImplTest { return serviceOffering; } + private void initializeMockConfigForMigratingVmWithVolumes() throws OperationTimedoutException, + ResourceUnavailableException { + // Mock the source and destination hosts. + when(_srcHostMock.getId()).thenReturn(5L); + when(_destHostMock.getId()).thenReturn(6L); + when(_hostDao.findById(5L)).thenReturn(_srcHostMock); + when(_hostDao.findById(6L)).thenReturn(_destHostMock); + + // Mock the vm being migrated. + when(_vmMock.getId()).thenReturn(1L); + when(_vmMock.getHypervisorType()).thenReturn(HypervisorType.XenServer); + when(_vmMock.getState()).thenReturn(State.Running).thenReturn(State.Running).thenReturn(State.Migrating) + .thenReturn(State.Migrating); + when(_vmMock.getHostId()).thenReturn(5L); + when(_vmInstance.getId()).thenReturn(1L); + when(_vmInstance.getServiceOfferingId()).thenReturn(2L); + when(_vmInstance.getInstanceName()).thenReturn("myVm"); + when(_vmInstance.getHostId()).thenReturn(5L); + when(_vmInstance.getType()).thenReturn(VirtualMachine.Type.User); + when(_vmInstance.getState()).thenReturn(State.Running).thenReturn(State.Running).thenReturn(State.Migrating) + .thenReturn(State.Migrating); + + // Mock the work item. + when(_workDao.persist(any(ItWorkVO.class))).thenReturn(_work); + when(_workDao.update("1", _work)).thenReturn(true); + when(_work.getId()).thenReturn("1"); + doNothing().when(_work).setStep(ItWorkVO.Step.Done); + + // Mock the vm guru and the user vm object that gets returned. + _vmMgr._vmGurus = new HashMap>(); + UserVmManagerImpl userVmManager = mock(UserVmManagerImpl.class); + _vmMgr.registerGuru(VirtualMachine.Type.User, userVmManager); + when(userVmManager.findById(anyLong())).thenReturn(_vmMock); + + // Mock the iteration over all the volumes of an instance. + Iterator volumeIterator = mock(Iterator.class); + when(_volsDao.findUsableVolumesForInstance(anyLong())).thenReturn(_rootVols); + when(_rootVols.iterator()).thenReturn(volumeIterator); + when(volumeIterator.hasNext()).thenReturn(true, false); + when(volumeIterator.next()).thenReturn(_volumeMock); + + // Mock the disk offering and pool objects for a volume. + when(_volumeMock.getDiskOfferingId()).thenReturn(5L); + when(_volumeMock.getPoolId()).thenReturn(200L); + when(_diskOfferingDao.findById(anyLong())).thenReturn(_diskOfferingMock); + when(_storagePoolDao.findById(anyLong())).thenReturn(_srcStoragePoolMock); + + // Mock the volume to pool mapping. + when(_volumeToPoolMock.get(_volumeMock)).thenReturn(_destStoragePoolMock); + when(_destStoragePoolMock.getId()).thenReturn(201L); + when(_srcStoragePoolMock.getId()).thenReturn(200L); + when(_destStoragePoolMock.isLocal()).thenReturn(false); + when(_diskOfferingMock.getUseLocalStorage()).thenReturn(false); + when(_poolHostDao.findByPoolHost(anyLong(), anyLong())).thenReturn(mock(StoragePoolHostVO.class)); + + // Mock hypervisor guru. + HypervisorGuru guruMock = mock(HypervisorGuru.class); + when(_hvGuruMgr.getGuru(HypervisorType.XenServer)).thenReturn(guruMock); + + when(_srcHostMock.getClusterId()).thenReturn(3L); + when(_destHostMock.getClusterId()).thenReturn(3L); + + // Mock the commands and answers to the agent. + PrepareForMigrationAnswer prepAnswerMock = mock(PrepareForMigrationAnswer.class); + when(prepAnswerMock.getResult()).thenReturn(true); + when(_agentMgr.send(anyLong(), isA(PrepareForMigrationCommand.class))).thenReturn(prepAnswerMock); + + MigrateWithStorageAnswer migAnswerMock = mock(MigrateWithStorageAnswer.class); + when(migAnswerMock.getResult()).thenReturn(true); + when(_agentMgr.send(anyLong(), isA(MigrateWithStorageCommand.class))).thenReturn(migAnswerMock); + + MigrateWithStorageReceiveAnswer migRecAnswerMock = mock(MigrateWithStorageReceiveAnswer.class); + when(migRecAnswerMock.getResult()).thenReturn(true); + when(_agentMgr.send(anyLong(), isA(MigrateWithStorageReceiveCommand.class))).thenReturn(migRecAnswerMock); + + MigrateWithStorageSendAnswer migSendAnswerMock = mock(MigrateWithStorageSendAnswer.class); + when(migSendAnswerMock.getResult()).thenReturn(true); + when(_agentMgr.send(anyLong(), isA(MigrateWithStorageSendCommand.class))).thenReturn(migSendAnswerMock); + + MigrateWithStorageCompleteAnswer migCompleteAnswerMock = mock(MigrateWithStorageCompleteAnswer.class); + when(migCompleteAnswerMock.getResult()).thenReturn(true); + when(_agentMgr.send(anyLong(), isA(MigrateWithStorageCompleteCommand.class))).thenReturn(migCompleteAnswerMock); + + CheckVirtualMachineAnswer checkVmAnswerMock = mock(CheckVirtualMachineAnswer.class); + when(checkVmAnswerMock.getResult()).thenReturn(true); + when(checkVmAnswerMock.getState()).thenReturn(State.Running); + when(_agentMgr.send(anyLong(), isA(CheckVirtualMachineCommand.class))).thenReturn(checkVmAnswerMock); + + // Mock the state transitions of vm. + Pair opaqueMock = new Pair (_vmMock.getHostId(), _destHostMock.getId()); + when(_vmSnapshotMgr.hasActiveVMSnapshotTasks(anyLong())).thenReturn(false); + when(_vmInstanceDao.updateState(State.Running, Event.MigrationRequested, State.Migrating, _vmMock, opaqueMock)) + .thenReturn(true); + when(_vmInstanceDao.updateState(State.Migrating, Event.OperationSucceeded, State.Running, _vmMock, opaqueMock)) + .thenReturn(true); + } + + // Check migration of a vm with its volumes within a cluster. + @Test + public void testMigrateWithVolumeWithinCluster() throws ResourceUnavailableException, ConcurrentOperationException, + ManagementServerException, VirtualMachineMigrationException, OperationTimedoutException { + + initializeMockConfigForMigratingVmWithVolumes(); + when(_srcHostMock.getClusterId()).thenReturn(3L); + when(_destHostMock.getClusterId()).thenReturn(3L); + + _vmMgr.migrateWithStorage(_vmInstance, _srcHostMock.getId(), _destHostMock.getId(), _volumeToPoolMock); + } + + // Check migration of a vm with its volumes across a cluster. + @Test + public void testMigrateWithVolumeAcrossCluster() throws ResourceUnavailableException, ConcurrentOperationException, + ManagementServerException, VirtualMachineMigrationException, OperationTimedoutException { + + initializeMockConfigForMigratingVmWithVolumes(); + when(_srcHostMock.getClusterId()).thenReturn(3L); + when(_destHostMock.getClusterId()).thenReturn(4L); + + _vmMgr.migrateWithStorage(_vmInstance, _srcHostMock.getId(), _destHostMock.getId(), _volumeToPoolMock); + } + + // Check migration of a vm fails when src and destination pool are not of same type; that is, one is shared and + // other is local. + @Test(expected=CloudRuntimeException.class) + public void testMigrateWithVolumeFail1() throws ResourceUnavailableException, ConcurrentOperationException, + ManagementServerException, VirtualMachineMigrationException, OperationTimedoutException { + + initializeMockConfigForMigratingVmWithVolumes(); + when(_srcHostMock.getClusterId()).thenReturn(3L); + when(_destHostMock.getClusterId()).thenReturn(3L); + + when(_destStoragePoolMock.isLocal()).thenReturn(true); + when(_diskOfferingMock.getUseLocalStorage()).thenReturn(false); + + _vmMgr.migrateWithStorage(_vmInstance, _srcHostMock.getId(), _destHostMock.getId(), _volumeToPoolMock); + } + + // Check migration of a vm fails when vm is not in Running state. + @Test(expected=ConcurrentOperationException.class) + public void testMigrateWithVolumeFail2() throws ResourceUnavailableException, ConcurrentOperationException, + ManagementServerException, VirtualMachineMigrationException, OperationTimedoutException { + + initializeMockConfigForMigratingVmWithVolumes(); + when(_srcHostMock.getClusterId()).thenReturn(3L); + when(_destHostMock.getClusterId()).thenReturn(3L); + + when(_vmMock.getState()).thenReturn(State.Stopped); + + _vmMgr.migrateWithStorage(_vmInstance, _srcHostMock.getId(), _destHostMock.getId(), _volumeToPoolMock); + } } diff --git a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java index a03e361d8c1..6cda294fbe7 100755 --- a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java +++ b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java @@ -25,6 +25,7 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import javax.naming.NamingException; +import com.cloud.configuration.ConfigurationVO; import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; import org.apache.cloudstack.api.command.admin.ldap.LDAPConfigCmd; import org.apache.cloudstack.api.command.admin.ldap.LDAPRemoveCmd; @@ -425,9 +426,9 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu * @see com.cloud.configuration.ConfigurationManager#updateConfiguration(long, java.lang.String, java.lang.String, java.lang.String) */ @Override - public void updateConfiguration(long userId, String name, String category, String value) { + public void updateConfiguration(long userId, String name, String category, String value, String scope, Long resourceId) { // TODO Auto-generated method stub - + } /* (non-Javadoc) @@ -435,7 +436,7 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu */ @Override public ServiceOfferingVO createServiceOffering(long userId, boolean isSystem, Type vm_typeType, String name, int cpu, int ramSize, int speed, String displayText, boolean localStorageRequired, boolean offerHA, - boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate, String deploymentPlanner) { + boolean limitResourceUse, boolean volatileVm, String tags, Long domainId, String hostTag, Integer networkRate) { // TODO Auto-generated method stub return null; } diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java index 3a585ce708a..bfcccf54bf0 100644 --- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java +++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java @@ -328,7 +328,7 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkManage */ @Override public PhysicalNetwork updatePhysicalNetwork(Long id, String networkSpeed, List tags, - String newVnetRangeString, String state) { + String newVnetRangeString, String state, String removeVlan) { // TODO Auto-generated method stub return null; } diff --git a/server/test/com/cloud/vpc/Site2SiteVpnTest.java b/server/test/com/cloud/vpc/Site2SiteVpnTest.java index 8e1b09327bd..083cf252d7c 100644 --- a/server/test/com/cloud/vpc/Site2SiteVpnTest.java +++ b/server/test/com/cloud/vpc/Site2SiteVpnTest.java @@ -25,7 +25,7 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations="classpath:/testContext.xml") +@ContextConfiguration(locations="classpath:/VpcTestContext.xml") public class Site2SiteVpnTest { private final static Logger s_logger = Logger.getLogger(Site2SiteVpnTest.class); diff --git a/server/test/com/cloud/vpc/VpcApiUnitTest.java b/server/test/com/cloud/vpc/VpcApiUnitTest.java index d4d5b29812d..e141c9658b8 100644 --- a/server/test/com/cloud/vpc/VpcApiUnitTest.java +++ b/server/test/com/cloud/vpc/VpcApiUnitTest.java @@ -23,7 +23,6 @@ import javax.inject.Inject; import junit.framework.TestCase; -import org.apache.log4j.Logger; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -40,68 +39,18 @@ import com.cloud.utils.component.ComponentContext; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:/VpcTestContext.xml") public class VpcApiUnitTest extends TestCase{ - private static final Logger s_logger = Logger.getLogger(VpcApiUnitTest.class); @Inject VpcManagerImpl _vpcService = null; - @Override @Before public void setUp() throws Exception { ComponentContext.initComponentsLifeCycle(); } + @Test - public void test() { - s_logger.debug("Starting test for VpcService interface"); - //Vpc service methods - //getActiveVpc(); - //deleteVpc(); - - //Vpc manager methods - validateNtwkOffForVpc(); - //destroyVpc(); - - } - - protected void deleteVpc() { - //delete existing offering - boolean result = false; - String msg = null; - try { - List svcs = new ArrayList(); - svcs.add(Service.SourceNat.getName()); - result = _vpcService.deleteVpc(1); - } catch (Exception ex) { - msg = ex.getMessage(); - } finally { - if (result) { - s_logger.debug("Delete vpc: Test passed, vpc is deleted"); - } else { - s_logger.error("Delete vpc: TEST FAILED, vpc failed to delete " + msg); - } - } - - //delete non-existing offering - result = false; - msg = null; - try { - List svcs = new ArrayList(); - svcs.add(Service.SourceNat.getName()); - result = _vpcService.deleteVpc(100); - } catch (Exception ex) { - msg = ex.getMessage(); - } finally { - if (!result) { - s_logger.debug("Delete vpc: Test passed, non existing vpc failed to delete "); - } else { - s_logger.error("Delete vpc: TEST FAILED, true is returned when try to delete non existing vpc"); - } - } - } - - protected void getActiveVpc() { + public void getActiveVpc() { //test for active vpc boolean result = false; - String msg = null; Vpc vpc = null; try { List svcs = new ArrayList(); @@ -111,18 +60,12 @@ public class VpcApiUnitTest extends TestCase{ result = true; } } catch (Exception ex) { - msg = ex.getMessage(); } finally { - if (result) { - s_logger.debug("Get active Vpc: Test passed, active vpc is returned"); - } else { - s_logger.error("Get active Vpc: TEST FAILED, active vpc is not returned " + msg); - } + assertTrue("Get active Vpc: TEST FAILED, active vpc is not returned", result); } //test for inactive vpc result = false; - msg = null; vpc = null; try { List svcs = new ArrayList(); @@ -132,66 +75,43 @@ public class VpcApiUnitTest extends TestCase{ result = true; } } catch (Exception ex) { - msg = ex.getMessage(); } finally { - if (!result) { - s_logger.debug("Get active Vpc: Test passed, no vpc is returned"); - } else { - s_logger.error("Get active Vpc: TEST FAILED, non active vpc is returned"); - } + assertFalse("Get active Vpc: TEST FAILED, non active vpc is returned", result); } } - protected void destroyVpc() { - try { - _vpcService.destroyVpc(_vpcService.getVpc(1), new AccountVO(), 1L); - } catch (Exception ex) { - s_logger.error("Destroy VPC TEST FAILED due to exc ", ex); - } - } - protected void validateNtwkOffForVpc() { + @Test + public void validateNtwkOffForVpc() { //validate network offering //1) correct network offering boolean result = false; try { _vpcService.validateNtwkOffForNtwkInVpc(2L, 1, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO()); result = true; - s_logger.debug("Validate network offering: Test passed: the offering is valid for vpc creation"); } catch (Exception ex) { - s_logger.error("Validate network offering: TEST FAILED due to exc ", ex); + } finally { + assertTrue("Validate network offering: Test passed: the offering is valid for vpc creation", result); } //2) invalid offering - source nat is not included result = false; - String msg = null; try { _vpcService.validateNtwkOffForNtwkInVpc(2L, 2, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO()); result = true; } catch (InvalidParameterValueException ex) { - msg = ex.getMessage(); } finally { - if (!result) { - s_logger.debug("Validate network offering: Test passed: " + msg); - } else { - s_logger.error("Validate network offering: TEST FAILED, can't use network offering without SourceNat service"); - } + assertFalse("Validate network offering: TEST FAILED, can't use network offering without SourceNat service", result); } //3) invalid offering - conserve mode is off result = false; - msg = null; try { _vpcService.validateNtwkOffForNtwkInVpc(2L, 3, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO()); result = true; } catch (InvalidParameterValueException ex) { - msg = ex.getMessage(); } finally { - if (!result) { - s_logger.debug("Validate network offering: Test passed: " + msg); - } else { - s_logger.error("Validate network offering: TEST FAILED, can't use network offering without conserve mode = true"); - } + assertFalse("Validate network offering: TEST FAILED, can't use network offering without conserve mode = true", result); } //4) invalid offering - guest type shared @@ -200,13 +120,8 @@ public class VpcApiUnitTest extends TestCase{ _vpcService.validateNtwkOffForNtwkInVpc(2L, 4, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO()); result = true; } catch (InvalidParameterValueException ex) { - msg = ex.getMessage(); } finally { - if (!result) { - s_logger.debug("Validate network offering: Test passed: " + msg); - } else { - s_logger.error("Validate network offering: TEST FAILED, can't use network offering with guest type = Shared"); - } + assertFalse("Validate network offering: TEST FAILED, can't use network offering with guest type = Shared", result); } //5) Invalid offering - no redundant router support @@ -215,30 +130,44 @@ public class VpcApiUnitTest extends TestCase{ _vpcService.validateNtwkOffForNtwkInVpc(2L, 5, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO()); result = true; } catch (InvalidParameterValueException ex) { - msg = ex.getMessage(); } finally { - if (!result) { - s_logger.debug("Validate network offering: Test passed: " + msg); - } else { - s_logger.error("TEST FAILED, can't use network offering with guest type = Shared"); - } - } - - //6) Only one network in the VPC can support LB service - negative scenario - result = false; - try { - _vpcService.validateNtwkOffForNtwkInVpc(2L, 6, "0.0.0.0", "111-", _vpcService.getVpc(1), "10.1.1.1", new AccountVO()); - result = true; - s_logger.debug("Validate network offering: Test passed: the offering is valid for vpc creation"); - } catch (InvalidParameterValueException ex) { - msg = ex.getMessage(); - } finally { - if (!result) { - s_logger.debug("Test passed : " + msg); - } else { - s_logger.error("Validate network offering: TEST FAILED, can't use network offering with guest type = Shared"); - } + assertFalse("TEST FAILED, can't use network offering with guest type = Shared", result); } } - + + +// public void destroyVpc() { +// boolean result = false; +// try { +// result = _vpcService.destroyVpc(_vpcService.getVpc(1), new AccountVO(), 1L); +// } catch (Exception ex) { +// s_logger.debug(ex); +// } finally { +// assertTrue("Failed to destroy VPC", result); +// } +// } +// +// public void deleteVpc() { +// //delete existing offering +// boolean result = false; +// try { +// List svcs = new ArrayList(); +// svcs.add(Service.SourceNat.getName()); +// result = _vpcService.deleteVpc(1); +// } catch (Exception ex) { +// } finally { +// assertTrue("Delete vpc: TEST FAILED, vpc failed to delete" + result, result); +// } +// +// //delete non-existing offering +// result = false; +// try { +// List svcs = new ArrayList(); +// svcs.add(Service.SourceNat.getName()); +// result = _vpcService.deleteVpc(100); +// } catch (Exception ex) { +// } finally { +// assertFalse("Delete vpc: TEST FAILED, true is returned when try to delete non existing vpc" + result, result); +// } +// } } diff --git a/server/test/com/cloud/vpc/VpcTestConfiguration.java b/server/test/com/cloud/vpc/VpcTestConfiguration.java index df73a6ccfe8..b1f2f80c076 100644 --- a/server/test/com/cloud/vpc/VpcTestConfiguration.java +++ b/server/test/com/cloud/vpc/VpcTestConfiguration.java @@ -32,6 +32,7 @@ import org.springframework.core.type.filter.TypeFilter; import com.cloud.alert.AlertManager; import com.cloud.cluster.agentlb.dao.HostTransferMapDaoImpl; import com.cloud.configuration.dao.ConfigurationDaoImpl; +import com.cloud.configuration.dao.ResourceCountDaoImpl; import com.cloud.configuration.dao.ResourceLimitDaoImpl; import com.cloud.dao.EntityManagerImpl; import com.cloud.dc.dao.AccountVlanMapDaoImpl; @@ -44,14 +45,27 @@ import com.cloud.dc.dao.DcDetailsDaoImpl; import com.cloud.dc.dao.HostPodDaoImpl; import com.cloud.dc.dao.PodVlanDaoImpl; import com.cloud.dc.dao.PodVlanMapDaoImpl; +import com.cloud.dc.dao.VlanDaoImpl; import com.cloud.domain.dao.DomainDaoImpl; import com.cloud.event.dao.UsageEventDao; import com.cloud.host.dao.HostDaoImpl; import com.cloud.host.dao.HostDetailsDaoImpl; import com.cloud.host.dao.HostTagsDaoImpl; -import com.cloud.vpc.MockNetworkModelImpl; +import com.cloud.network.Ipv6AddressManagerImpl; import com.cloud.network.StorageNetworkManager; +import com.cloud.network.dao.FirewallRulesCidrsDaoImpl; +import com.cloud.network.dao.FirewallRulesDaoImpl; import com.cloud.network.dao.IPAddressDaoImpl; +import com.cloud.network.dao.LoadBalancerDaoImpl; +import com.cloud.network.dao.NetworkDao; +import com.cloud.network.dao.PhysicalNetworkDaoImpl; +import com.cloud.network.dao.PhysicalNetworkTrafficTypeDaoImpl; +import com.cloud.network.dao.RouterNetworkDaoImpl; +import com.cloud.network.dao.Site2SiteVpnGatewayDaoImpl; +import com.cloud.network.dao.UserIpv6AddressDaoImpl; +import com.cloud.network.dao.VirtualRouterProviderDaoImpl; +import com.cloud.network.element.NetworkElement; +import com.cloud.network.element.Site2SiteVpnServiceProvider; import com.cloud.network.lb.LoadBalancingRulesManager; import com.cloud.network.rules.RulesManager; import com.cloud.network.vpc.VpcManagerImpl; @@ -60,47 +74,37 @@ import com.cloud.network.vpc.dao.StaticRouteDaoImpl; import com.cloud.network.vpc.dao.VpcDao; import com.cloud.network.vpc.dao.VpcGatewayDaoImpl; import com.cloud.network.vpc.dao.VpcOfferingDao; -import com.cloud.utils.component.SpringComponentScanUtils; -import com.cloud.vm.UserVmManager; -import com.cloud.vm.dao.DomainRouterDaoImpl; -import com.cloud.vm.dao.NicDaoImpl; -import com.cloud.vm.dao.UserVmDaoImpl; -import com.cloud.vm.dao.UserVmDetailsDaoImpl; -import com.cloud.vm.dao.VMInstanceDaoImpl; -import com.cloud.vpc.dao.MockNetworkOfferingDaoImpl; -import com.cloud.vpc.dao.MockNetworkOfferingServiceMapDaoImpl; -import com.cloud.vpc.dao.MockNetworkServiceMapDaoImpl; -import com.cloud.vpc.dao.MockVpcOfferingDaoImpl; -import com.cloud.vpc.dao.MockVpcOfferingServiceMapDaoImpl; - - -import com.cloud.configuration.dao.ResourceCountDaoImpl; -import com.cloud.dc.dao.VlanDaoImpl; -import com.cloud.network.dao.FirewallRulesCidrsDaoImpl; -import com.cloud.network.dao.FirewallRulesDaoImpl; -import com.cloud.network.dao.LoadBalancerDaoImpl; -import com.cloud.network.dao.NetworkDao; -import com.cloud.network.dao.PhysicalNetworkDaoImpl; -import com.cloud.network.dao.PhysicalNetworkTrafficTypeDaoImpl; -import com.cloud.network.dao.RouterNetworkDaoImpl; -import com.cloud.network.dao.Site2SiteVpnGatewayDaoImpl; -import com.cloud.network.dao.VirtualRouterProviderDaoImpl; -import com.cloud.network.element.NetworkElement; -import com.cloud.network.element.Site2SiteVpnServiceProvider; +import com.cloud.network.vpc.dao.VpcServiceMapDaoImpl; import com.cloud.network.vpn.RemoteAccessVpnService; import com.cloud.network.vpn.Site2SiteVpnManager; import com.cloud.projects.dao.ProjectAccountDaoImpl; import com.cloud.projects.dao.ProjectDaoImpl; import com.cloud.resourcelimit.ResourceLimitManagerImpl; +import com.cloud.service.dao.ServiceOfferingDaoImpl; import com.cloud.storage.dao.SnapshotDaoImpl; import com.cloud.storage.dao.VMTemplateDaoImpl; import com.cloud.storage.dao.VMTemplateDetailsDaoImpl; +import com.cloud.storage.dao.VMTemplateHostDaoImpl; import com.cloud.storage.dao.VMTemplateZoneDaoImpl; import com.cloud.storage.dao.VolumeDaoImpl; import com.cloud.tags.dao.ResourceTagsDaoImpl; import com.cloud.user.AccountManager; import com.cloud.user.dao.AccountDaoImpl; import com.cloud.user.dao.UserStatisticsDaoImpl; +import com.cloud.utils.component.SpringComponentScanUtils; +import com.cloud.vm.UserVmManager; +import com.cloud.vm.dao.DomainRouterDaoImpl; +import com.cloud.vm.dao.NicDaoImpl; +import com.cloud.vm.dao.NicSecondaryIpDaoImpl; +import com.cloud.vm.dao.UserVmDaoImpl; +import com.cloud.vm.dao.UserVmDetailsDaoImpl; +import com.cloud.vm.dao.VMInstanceDaoImpl; +import com.cloud.vpc.dao.MockNetworkOfferingDaoImpl; +import com.cloud.vpc.dao.MockNetworkOfferingServiceMapDaoImpl; +import com.cloud.vpc.dao.MockNetworkServiceMapDaoImpl; +import com.cloud.vpc.dao.MockVpcDaoImpl; +import com.cloud.vpc.dao.MockVpcOfferingDaoImpl; +import com.cloud.vpc.dao.MockVpcOfferingServiceMapDaoImpl; @Configuration @@ -141,12 +145,18 @@ import com.cloud.user.dao.UserStatisticsDaoImpl; SnapshotDaoImpl.class, VMInstanceDaoImpl.class, VolumeDaoImpl.class, + UserIpv6AddressDaoImpl.class, + NicSecondaryIpDaoImpl.class, + VpcServiceMapDaoImpl.class, + ServiceOfferingDaoImpl.class, + VMTemplateHostDaoImpl.class, + MockVpcDaoImpl.class, VMTemplateDaoImpl.class,VMTemplateZoneDaoImpl.class,VMTemplateDetailsDaoImpl.class,DataCenterDaoImpl.class,DataCenterIpAddressDaoImpl.class,DataCenterLinkLocalIpAddressDaoImpl.class,DataCenterVnetDaoImpl.class,PodVlanDaoImpl.class, DcDetailsDaoImpl.class,MockNetworkManagerImpl.class,MockVpcVirtualNetworkApplianceManager.class, EntityManagerImpl.class,LoadBalancerDaoImpl.class,FirewallRulesCidrsDaoImpl.class,VirtualRouterProviderDaoImpl.class, ProjectDaoImpl.class,ProjectAccountDaoImpl.class,MockVpcOfferingDaoImpl.class, MockConfigurationManagerImpl.class, MockNetworkOfferingServiceMapDaoImpl.class, - MockNetworkServiceMapDaoImpl.class,MockVpcOfferingServiceMapDaoImpl.class,MockNetworkOfferingDaoImpl.class, MockNetworkModelImpl.class}, + MockNetworkServiceMapDaoImpl.class,MockVpcOfferingServiceMapDaoImpl.class,MockNetworkOfferingDaoImpl.class, MockNetworkModelImpl.class, Ipv6AddressManagerImpl.class}, includeFilters={@Filter(value=VpcTestConfiguration.VpcLibrary.class, type=FilterType.CUSTOM)}, useDefaultFilters=false ) @@ -210,15 +220,16 @@ public class VpcTestConfiguration { return Mockito.mock(RemoteAccessVpnService.class); } - @Bean - public VpcDao vpcDao() { - return Mockito.mock(VpcDao.class); - } +// @Bean +// public VpcDao vpcDao() { +// return Mockito.mock(VpcDao.class); +// } @Bean public NetworkDao networkDao() { return Mockito.mock(NetworkDao.class); } + public static class VpcLibrary implements TypeFilter { @Override diff --git a/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyPasswordBasedEncryptor.java b/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyPasswordBasedEncryptor.java index 29826f0ea92..5a7241ac7e5 100644 --- a/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyPasswordBasedEncryptor.java +++ b/services/console-proxy/server/src/com/cloud/consoleproxy/ConsoleProxyPasswordBasedEncryptor.java @@ -16,13 +16,16 @@ // under the License. package com.cloud.consoleproxy; +import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; @@ -33,110 +36,162 @@ import com.google.gson.GsonBuilder; /** * - * A simple password based encyrptor based on DES. It can serialize simple POJO object into URL safe string + * @author Kelven Yang + * A simple password based encyrptor based on AES/CBC. It can serialize simple POJO object into URL safe string * and deserialize it back. * */ public class ConsoleProxyPasswordBasedEncryptor { - private static final Logger s_logger = Logger.getLogger(ConsoleProxyPasswordBasedEncryptor.class); - - private String password; - private Gson gson; - - public ConsoleProxyPasswordBasedEncryptor(String password) { - this.password = password; - gson = new GsonBuilder().create(); - } - - public String encryptText(String text) { - if(text == null || text.isEmpty()) - return text; - - assert(password != null); - assert(!password.isEmpty()); - - try { - Cipher cipher = Cipher.getInstance("DES"); - int maxKeySize = 8; - SecretKeySpec keySpec = new SecretKeySpec(normalizeKey(password.getBytes(), maxKeySize), "DES"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec); - byte[] encryptedBytes = cipher.doFinal(text.getBytes()); - return Base64.encodeBase64URLSafeString(encryptedBytes); - } catch (NoSuchAlgorithmException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (NoSuchPaddingException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (IllegalBlockSizeException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (BadPaddingException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (InvalidKeyException e) { - s_logger.error("Unexpected exception ", e); - return null; - } - } + private static final Logger s_logger = Logger.getLogger(ConsoleProxyPasswordBasedEncryptor.class); + + private Gson gson; + + // key/IV will be set in 128 bit strength + private KeyIVPair keyIvPair; + + public ConsoleProxyPasswordBasedEncryptor(String password) { + gson = new GsonBuilder().create(); + keyIvPair = gson.fromJson(password, KeyIVPair.class); + } + + public String encryptText(String text) { + if(text == null || text.isEmpty()) + return text; + + try { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKeySpec keySpec = new SecretKeySpec(keyIvPair.getKeyBytes(), "AES"); - public String decryptText(String encryptedText) { - if(encryptedText == null || encryptedText.isEmpty()) - return encryptedText; + cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(keyIvPair.getIvBytes())); + + byte[] encryptedBytes = cipher.doFinal(text.getBytes()); + return Base64.encodeBase64URLSafeString(encryptedBytes); + } catch (NoSuchAlgorithmException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (NoSuchPaddingException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (IllegalBlockSizeException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (BadPaddingException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (InvalidKeyException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (InvalidAlgorithmParameterException e) { + s_logger.error("Unexpected exception ", e); + return null; + } + } - assert(password != null); - assert(!password.isEmpty()); + public String decryptText(String encryptedText) { + if(encryptedText == null || encryptedText.isEmpty()) + return encryptedText; - try { - Cipher cipher = Cipher.getInstance("DES"); - int maxKeySize = 8; - SecretKeySpec keySpec = new SecretKeySpec(normalizeKey(password.getBytes(), maxKeySize), "DES"); - cipher.init(Cipher.DECRYPT_MODE, keySpec); - - byte[] encryptedBytes = Base64.decodeBase64(encryptedText); - return new String(cipher.doFinal(encryptedBytes)); - } catch (NoSuchAlgorithmException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (NoSuchPaddingException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (IllegalBlockSizeException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (BadPaddingException e) { - s_logger.error("Unexpected exception ", e); - return null; - } catch (InvalidKeyException e) { - s_logger.error("Unexpected exception ", e); - return null; - } - } - - public String encryptObject(Class clz, T obj) { - if(obj == null) - return null; - - String json = gson.toJson(obj); - return encryptText(json); - } - - @SuppressWarnings("unchecked") - public T decryptObject(Class clz, String encrypted) { - if(encrypted == null || encrypted.isEmpty()) - return null; - - String json = decryptText(encrypted); - return (T)gson.fromJson(json, clz); - } - - private static byte[] normalizeKey(byte[] keyBytes, int keySize) { - assert(keySize > 0); - byte[] key = new byte[keySize]; - - for(int i = 0; i < keyBytes.length; i++) - key[i%keySize] ^= keyBytes[i]; - - return key; - } + try { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + SecretKeySpec keySpec = new SecretKeySpec(keyIvPair.getKeyBytes(), "AES"); + cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(keyIvPair.getIvBytes())); + + byte[] encryptedBytes = Base64.decodeBase64(encryptedText); + return new String(cipher.doFinal(encryptedBytes)); + } catch (NoSuchAlgorithmException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (NoSuchPaddingException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (IllegalBlockSizeException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (BadPaddingException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (InvalidKeyException e) { + s_logger.error("Unexpected exception ", e); + return null; + } catch (InvalidAlgorithmParameterException e) { + s_logger.error("Unexpected exception ", e); + return null; + } + } + + public String encryptObject(Class clz, T obj) { + if(obj == null) + return null; + + String json = gson.toJson(obj); + return encryptText(json); + } + + @SuppressWarnings("unchecked") + public T decryptObject(Class clz, String encrypted) { + if(encrypted == null || encrypted.isEmpty()) + return null; + + String json = decryptText(encrypted); + return (T)gson.fromJson(json, clz); + } + + public static class KeyIVPair { + String base64EncodedKeyBytes; + String base64EncodedIvBytes; + + public KeyIVPair() { + } + + public KeyIVPair(String base64EncodedKeyBytes, String base64EncodedIvBytes) { + this.base64EncodedKeyBytes = base64EncodedKeyBytes; + this.base64EncodedIvBytes = base64EncodedIvBytes; + } + + public byte[] getKeyBytes() { + return Base64.decodeBase64(base64EncodedKeyBytes); + } + + public void setKeyBytes(byte[] keyBytes) { + base64EncodedKeyBytes = Base64.encodeBase64URLSafeString(keyBytes); + } + + public byte[] getIvBytes() { + return Base64.decodeBase64(base64EncodedIvBytes); + } + + public void setIvBytes(byte[] ivBytes) { + base64EncodedIvBytes = Base64.encodeBase64URLSafeString(ivBytes); + } + } + + public static void main(String[] args) { + SecureRandom random; + try { + random = SecureRandom.getInstance("SHA1PRNG"); + byte[] keyBytes = new byte[16]; + random.nextBytes(keyBytes); + + byte[] ivBytes = new byte[16]; + random.nextBytes(ivBytes); + + KeyIVPair keyIvPair = new KeyIVPair("8x/xUBgX0Up+3UEo39dSeG277JhVj31+ElHkN5+EC0Q=", "Y2SUiIN6JXTdKNK/ZMDyVtLB7gAM9MCCiyrP1xd3bSQ="); + //keyIvPair.setKeyBytes(keyBytes); + //keyIvPair.setIvBytes(ivBytes); + + Gson gson = new GsonBuilder().create(); + ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(gson.toJson(keyIvPair)); + + String encrypted = encryptor.encryptText("Hello, world"); + + System.out.println("Encrypted result: " + encrypted); + + String decrypted = encryptor.decryptText(encrypted); + + System.out.println("Decrypted result: " + decrypted); + + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + } } diff --git a/setup/db/db/schema-40to410.sql b/setup/db/db/schema-40to410.sql index e2949d93e61..ff1d9085329 100644 --- a/setup/db/db/schema-40to410.sql +++ b/setup/db/db/schema-40to410.sql @@ -486,7 +486,7 @@ CREATE VIEW `cloud`.`user_vm_view` AS vm_instance.vm_type vm_type, data_center.id data_center_id, data_center.uuid data_center_uuid, - data_center.name data_center_name, + data_center.name data_center_name, data_center.is_security_group_enabled security_group_enabled, host.id host_id, host.uuid host_uuid, @@ -1455,7 +1455,7 @@ CREATE VIEW `cloud`.`storage_pool_view` AS cluster.cluster_type, data_center.id data_center_id, data_center.uuid data_center_uuid, - data_center.name data_center_name, + data_center.name data_center_name, host_pod_ref.id pod_id, host_pod_ref.uuid pod_uuid, host_pod_ref.name pod_name, diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql index fb760bf4824..10cdbbad6f9 100644 --- a/setup/db/db/schema-410to420.sql +++ b/setup/db/db/schema-410to420.sql @@ -23,7 +23,9 @@ 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); 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'); @@ -167,7 +169,6 @@ CREATE TABLE `cloud`.`affinity_group_vm_map` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -ALTER TABLE `cloud`.`service_offering` ADD COLUMN `deployment_planner` varchar(255) NOT NULL DEFAULT 'FirstFitPlanner' COMMENT 'Planner heuristics used to deploy a VM of this offering'; CREATE TABLE nic_secondary_ips ( `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT, @@ -280,148 +281,7 @@ INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Project Defaults', 'DEFAULT' INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Project Defaults', 'DEFAULT', 'management-server', 'max.project.primary.storage', '200', 'The default maximum primary storage space (in GiB) that can be used for a project'); INSERT IGNORE INTO `cloud`.`configuration` VALUES ('Project Defaults', 'DEFAULT', 'management-server', 'max.project.secondary.storage', '400', 'The default maximum secondary storage space (in GiB) that can be used for a project'); -DROP VIEW IF EXISTS `cloud`.`account_view`; -CREATE VIEW `cloud`.`account_view` AS - select - account.id, - account.uuid, - account.account_name, - account.type, - account.state, - account.removed, - account.cleanup_needed, - account.network_domain, - domain.id domain_id, - domain.uuid domain_uuid, - domain.name domain_name, - domain.path domain_path, - data_center.id data_center_id, - data_center.uuid data_center_uuid, - data_center.name data_center_name, - account_netstats_view.bytesReceived, - account_netstats_view.bytesSent, - vmlimit.max vmLimit, - vmcount.count vmTotal, - runningvm.vmcount runningVms, - stoppedvm.vmcount stoppedVms, - iplimit.max ipLimit, - ipcount.count ipTotal, - free_ip_view.free_ip ipFree, - volumelimit.max volumeLimit, - volumecount.count volumeTotal, - snapshotlimit.max snapshotLimit, - snapshotcount.count snapshotTotal, - templatelimit.max templateLimit, - templatecount.count templateTotal, - vpclimit.max vpcLimit, - vpccount.count vpcTotal, - projectlimit.max projectLimit, - projectcount.count projectTotal, - networklimit.max networkLimit, - networkcount.count networkTotal, - cpulimit.max cpuLimit, - cpucount.count cpuTotal, - memorylimit.max memoryLimit, - memorycount.count memoryTotal, - primary_storage_limit.max primaryStorageLimit, - primary_storage_count.count primaryStorageTotal, - secondary_storage_limit.max secondaryStorageLimit, - secondary_storage_count.count secondaryStorageTotal, - async_job.id job_id, - async_job.uuid job_uuid, - async_job.job_status job_status, - async_job.account_id job_account_id - from - `cloud`.`free_ip_view`, - `cloud`.`account` - inner join - `cloud`.`domain` ON account.domain_id = domain.id - left join - `cloud`.`data_center` ON account.default_zone_id = data_center.id - left join - `cloud`.`account_netstats_view` ON account.id = account_netstats_view.account_id - left join - `cloud`.`resource_limit` vmlimit ON account.id = vmlimit.account_id - and vmlimit.type = 'user_vm' - left join - `cloud`.`resource_count` vmcount ON account.id = vmcount.account_id - and vmcount.type = 'user_vm' - left join - `cloud`.`account_vmstats_view` runningvm ON account.id = runningvm.account_id - and runningvm.state = 'Running' - left join - `cloud`.`account_vmstats_view` stoppedvm ON account.id = stoppedvm.account_id - and stoppedvm.state = 'Stopped' - left join - `cloud`.`resource_limit` iplimit ON account.id = iplimit.account_id - and iplimit.type = 'public_ip' - left join - `cloud`.`resource_count` ipcount ON account.id = ipcount.account_id - and ipcount.type = 'public_ip' - left join - `cloud`.`resource_limit` volumelimit ON account.id = volumelimit.account_id - and volumelimit.type = 'volume' - left join - `cloud`.`resource_count` volumecount ON account.id = volumecount.account_id - and volumecount.type = 'volume' - left join - `cloud`.`resource_limit` snapshotlimit ON account.id = snapshotlimit.account_id - and snapshotlimit.type = 'snapshot' - left join - `cloud`.`resource_count` snapshotcount ON account.id = snapshotcount.account_id - and snapshotcount.type = 'snapshot' - left join - `cloud`.`resource_limit` templatelimit ON account.id = templatelimit.account_id - and templatelimit.type = 'template' - left join - `cloud`.`resource_count` templatecount ON account.id = templatecount.account_id - and templatecount.type = 'template' - left join - `cloud`.`resource_limit` vpclimit ON account.id = vpclimit.account_id - and vpclimit.type = 'vpc' - left join - `cloud`.`resource_count` vpccount ON account.id = vpccount.account_id - and vpccount.type = 'vpc' - left join - `cloud`.`resource_limit` projectlimit ON account.id = projectlimit.account_id - and projectlimit.type = 'project' - left join - `cloud`.`resource_count` projectcount ON account.id = projectcount.account_id - and projectcount.type = 'project' - left join - `cloud`.`resource_limit` networklimit ON account.id = networklimit.account_id - and networklimit.type = 'network' - left join - `cloud`.`resource_count` networkcount ON account.id = networkcount.account_id - and networkcount.type = 'network' - left join - `cloud`.`resource_limit` cpulimit ON account.id = cpulimit.account_id - and cpulimit.type = 'cpu' - left join - `cloud`.`resource_count` cpucount ON account.id = cpucount.account_id - and cpucount.type = 'cpu' - left join - `cloud`.`resource_limit` memorylimit ON account.id = memorylimit.account_id - and memorylimit.type = 'memory' - left join - `cloud`.`resource_count` memorycount ON account.id = memorycount.account_id - and memorycount.type = 'memory' - left join - `cloud`.`resource_limit` primary_storage_limit ON account.id = primary_storage_limit.account_id - and primary_storage_limit.type = 'primary_storage' - left join - `cloud`.`resource_count` primary_storage_count ON account.id = primary_storage_count.account_id - and primary_storage_count.type = 'primary_storage' - left join - `cloud`.`resource_limit` secondary_storage_limit ON account.id = secondary_storage_limit.account_id - and secondary_storage_limit.type = 'secondary_storage' - left join - `cloud`.`resource_count` secondary_storage_count ON account.id = secondary_storage_count.account_id - and secondary_storage_count.type = 'secondary_storage' - left join - `cloud`.`async_job` ON async_job.instance_id = account.id - and async_job.instance_type = 'Account' - and async_job.job_status = 0; + ALTER TABLE `cloud`.`remote_access_vpn` ADD COLUMN `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT 'id'; ALTER TABLE `cloud`.`remote_access_vpn` ADD COLUMN `uuid` varchar(40) UNIQUE; @@ -514,6 +374,7 @@ CREATE VIEW `cloud`.`user_vm_view` AS data_center.id data_center_id, data_center.uuid data_center_uuid, data_center.name data_center_name, + data_center.networktype data_center_type, data_center.is_security_group_enabled security_group_enabled, host.id host_id, host.uuid host_uuid, @@ -654,6 +515,7 @@ CREATE VIEW `cloud`.`affinity_group_view` AS select affinity_group.id id, affinity_group.name name, + affinity_group.type type, affinity_group.description description, affinity_group.uuid uuid, account.id account_id, @@ -715,6 +577,204 @@ CREATE TABLE `cloud`.`network_asa1000v_map` ( CONSTRAINT `fk_network_asa1000v_map__asa1000v_id` FOREIGN KEY (`asa1000v_id`) REFERENCES `external_cisco_asa1000v_devices`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +ALTER TABLE `cloud`.`network_offerings` ADD COLUMN `eip_associate_public_ip` int(1) unsigned NOT NULL DEFAULT 0 COMMENT 'true if public IP is associated with user VM creation by default when EIP service is enabled.' AFTER `elastic_ip_service`; + -- Re-enable foreign key checking, at the end of the upgrade path SET foreign_key_checks = 1; + +-- 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`.`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`.`user` SET `cloud`.`user`.`default`=1 WHERE id IN (1,2); + +ALTER VIEW `cloud`.`user_view` AS + select + user.id, + user.uuid, + user.username, + user.password, + user.firstname, + user.lastname, + user.email, + user.state, + user.api_key, + user.secret_key, + user.created, + user.removed, + user.timezone, + user.registration_token, + user.is_registered, + user.incorrect_login_attempts, + user.default, + account.id account_id, + account.uuid account_uuid, + account.account_name account_name, + account.type account_type, + domain.id domain_id, + domain.uuid domain_uuid, + domain.name domain_name, + domain.path domain_path, + async_job.id job_id, + async_job.uuid job_uuid, + async_job.job_status job_status, + async_job.account_id job_account_id + from + `cloud`.`user` + inner join + `cloud`.`account` ON user.account_id = account.id + inner join + `cloud`.`domain` ON account.domain_id = domain.id + left join + `cloud`.`async_job` ON async_job.instance_id = user.id + and async_job.instance_type = 'User' + and async_job.job_status = 0; + + +DROP VIEW IF EXISTS `cloud`.`account_view`; +CREATE VIEW `cloud`.`account_view` AS + select + account.id, + account.uuid, + account.account_name, + account.type, + account.state, + account.removed, + account.cleanup_needed, + account.network_domain, + account.default, + domain.id domain_id, + domain.uuid domain_uuid, + domain.name domain_name, + domain.path domain_path, + data_center.id data_center_id, + data_center.uuid data_center_uuid, + data_center.name data_center_name, + account_netstats_view.bytesReceived, + account_netstats_view.bytesSent, + vmlimit.max vmLimit, + vmcount.count vmTotal, + runningvm.vmcount runningVms, + stoppedvm.vmcount stoppedVms, + iplimit.max ipLimit, + ipcount.count ipTotal, + free_ip_view.free_ip ipFree, + volumelimit.max volumeLimit, + volumecount.count volumeTotal, + snapshotlimit.max snapshotLimit, + snapshotcount.count snapshotTotal, + templatelimit.max templateLimit, + templatecount.count templateTotal, + vpclimit.max vpcLimit, + vpccount.count vpcTotal, + projectlimit.max projectLimit, + projectcount.count projectTotal, + networklimit.max networkLimit, + networkcount.count networkTotal, + cpulimit.max cpuLimit, + cpucount.count cpuTotal, + memorylimit.max memoryLimit, + memorycount.count memoryTotal, + primary_storage_limit.max primaryStorageLimit, + primary_storage_count.count primaryStorageTotal, + secondary_storage_limit.max secondaryStorageLimit, + secondary_storage_count.count secondaryStorageTotal, + async_job.id job_id, + async_job.uuid job_uuid, + async_job.job_status job_status, + async_job.account_id job_account_id + from + `cloud`.`free_ip_view`, + `cloud`.`account` + inner join + `cloud`.`domain` ON account.domain_id = domain.id + left join + `cloud`.`data_center` ON account.default_zone_id = data_center.id + left join + `cloud`.`account_netstats_view` ON account.id = account_netstats_view.account_id + left join + `cloud`.`resource_limit` vmlimit ON account.id = vmlimit.account_id + and vmlimit.type = 'user_vm' + left join + `cloud`.`resource_count` vmcount ON account.id = vmcount.account_id + and vmcount.type = 'user_vm' + left join + `cloud`.`account_vmstats_view` runningvm ON account.id = runningvm.account_id + and runningvm.state = 'Running' + left join + `cloud`.`account_vmstats_view` stoppedvm ON account.id = stoppedvm.account_id + and stoppedvm.state = 'Stopped' + left join + `cloud`.`resource_limit` iplimit ON account.id = iplimit.account_id + and iplimit.type = 'public_ip' + left join + `cloud`.`resource_count` ipcount ON account.id = ipcount.account_id + and ipcount.type = 'public_ip' + left join + `cloud`.`resource_limit` volumelimit ON account.id = volumelimit.account_id + and volumelimit.type = 'volume' + left join + `cloud`.`resource_count` volumecount ON account.id = volumecount.account_id + and volumecount.type = 'volume' + left join + `cloud`.`resource_limit` snapshotlimit ON account.id = snapshotlimit.account_id + and snapshotlimit.type = 'snapshot' + left join + `cloud`.`resource_count` snapshotcount ON account.id = snapshotcount.account_id + and snapshotcount.type = 'snapshot' + left join + `cloud`.`resource_limit` templatelimit ON account.id = templatelimit.account_id + and templatelimit.type = 'template' + left join + `cloud`.`resource_count` templatecount ON account.id = templatecount.account_id + and templatecount.type = 'template' + left join + `cloud`.`resource_limit` vpclimit ON account.id = vpclimit.account_id + and vpclimit.type = 'vpc' + left join + `cloud`.`resource_count` vpccount ON account.id = vpccount.account_id + and vpccount.type = 'vpc' + left join + `cloud`.`resource_limit` projectlimit ON account.id = projectlimit.account_id + and projectlimit.type = 'project' + left join + `cloud`.`resource_count` projectcount ON account.id = projectcount.account_id + and projectcount.type = 'project' + left join + `cloud`.`resource_limit` networklimit ON account.id = networklimit.account_id + and networklimit.type = 'network' + left join + `cloud`.`resource_count` networkcount ON account.id = networkcount.account_id + and networkcount.type = 'network' + left join + `cloud`.`resource_limit` cpulimit ON account.id = cpulimit.account_id + and cpulimit.type = 'cpu' + left join + `cloud`.`resource_count` cpucount ON account.id = cpucount.account_id + and cpucount.type = 'cpu' + left join + `cloud`.`resource_limit` memorylimit ON account.id = memorylimit.account_id + and memorylimit.type = 'memory' + left join + `cloud`.`resource_count` memorycount ON account.id = memorycount.account_id + and memorycount.type = 'memory' + left join + `cloud`.`resource_limit` primary_storage_limit ON account.id = primary_storage_limit.account_id + and primary_storage_limit.type = 'primary_storage' + left join + `cloud`.`resource_count` primary_storage_count ON account.id = primary_storage_count.account_id + and primary_storage_count.type = 'primary_storage' + left join + `cloud`.`resource_limit` secondary_storage_limit ON account.id = secondary_storage_limit.account_id + and secondary_storage_limit.type = 'secondary_storage' + left join + `cloud`.`resource_count` secondary_storage_count ON account.id = secondary_storage_count.account_id + and secondary_storage_count.type = 'secondary_storage' + left join + `cloud`.`async_job` ON async_job.instance_id = account.id + and async_job.instance_type = 'Account' + and async_job.job_status = 0; + +alter table `cloud_usage`.`usage_network_offering` add column nic_id bigint(20) unsigned NOT NULL; \ No newline at end of file diff --git a/test/integration/component/test_accounts.py b/test/integration/component/test_accounts.py index cdb3e58dd94..459cfb3a251 100644 --- a/test/integration/component/test_accounts.py +++ b/test/integration/component/test_accounts.py @@ -95,7 +95,6 @@ class Services: # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, - "mode": 'advanced' } @@ -110,6 +109,7 @@ class TestAccounts(cloudstackTestCase): cls.services = Services().services # Get Zone, Domain and templates cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, @@ -239,6 +239,7 @@ class TestRemoveUserFromAccount(cloudstackTestCase): cls.services = Services().services # Get Zone, Domain and templates cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, @@ -506,7 +507,7 @@ class TestNonRootAdminsPrivileges(cloudstackTestCase): cls.services = Services().services # Get Zone settings cls.zone = get_zone(cls.api_client, cls.services) - + cls.services['mode'] = cls.zone.networktype # Create an account, domain etc cls.domain = Domain.create( cls.api_client, @@ -852,6 +853,7 @@ class TesttemplateHierarchy(cloudstackTestCase): cls.services = Services().services # Get Zone settings cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls.services["template"]["zoneid"] = cls.zone.id # Create domains, accounts and template @@ -1000,6 +1002,7 @@ class TestAddVmToSubDomain(cloudstackTestCase): cls.api_client, cls.services, ) + cls.services['mode'] = cls.zone.networktype cls.sub_domain = Domain.create( cls.api_client, cls.services["domain"], @@ -1145,6 +1148,7 @@ class TestUserDetails(cloudstackTestCase): # Get Zone, Domain etc cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls._cleanup = [] return @@ -1451,6 +1455,7 @@ class TestUserLogin(cloudstackTestCase): # Get Zone, Domain etc cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls._cleanup = [] return @@ -1615,6 +1620,7 @@ class TestDomainForceRemove(cloudstackTestCase): cls.api_client, cls.services, ) + cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, diff --git a/test/integration/component/test_allocation_states.py b/test/integration/component/test_allocation_states.py index 103cb10c0cc..fe4c35f3b9f 100644 --- a/test/integration/component/test_allocation_states.py +++ b/test/integration/component/test_allocation_states.py @@ -79,7 +79,6 @@ class Services: # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, - "mode": 'advanced', } @@ -94,6 +93,7 @@ class TestAllocationState(cloudstackTestCase): cls.services = Services().services # Get Zone, Domain and templates cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls._cleanup = [] return diff --git a/test/integration/component/test_asa1000v_fw.py b/test/integration/component/test_asa1000v_fw.py old mode 100755 new mode 100644 diff --git a/test/integration/component/test_blocker_bugs.py b/test/integration/component/test_blocker_bugs.py index 33e4a73f712..bfd1c13cb19 100644 --- a/test/integration/component/test_blocker_bugs.py +++ b/test/integration/component/test_blocker_bugs.py @@ -101,8 +101,6 @@ class Services: "ostype": 'CentOS 5.3 (64-bit)', # Cent OS 5.3 (64 bit) "sleep": 60, - "mode": 'advanced', - # Networking mode, Advanced, Basic } @@ -115,6 +113,7 @@ class TestSnapshots(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.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, cls.services["disk_offering"] @@ -422,6 +421,7 @@ class TestTemplate(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.zone.networktype cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.services["templates"]["zoneid"] = cls.zone.id @@ -543,6 +543,7 @@ class TestNATRules(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.zone.networktype template = get_template( cls.api_client, cls.zone.id, @@ -737,6 +738,7 @@ class TestRouters(cloudstackTestCase): cls.services = Services().services # Get Zone, Domain and templates cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, @@ -863,6 +865,7 @@ class TestRouterRestart(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.zone.networktype template = get_template( cls.api_client, cls.zone.id, @@ -992,6 +995,7 @@ class TestTemplates(cloudstackTestCase): # Get Zone, templates etc cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, diff --git a/test/integration/component/test_egress_rules.py b/test/integration/component/test_egress_rules.py index 6b9cd4f25fc..7972aa50639 100644 --- a/test/integration/component/test_egress_rules.py +++ b/test/integration/component/test_egress_rules.py @@ -122,8 +122,6 @@ class Services: # CentOS 5.3 (64-bit) "sleep": 60, "timeout": 10, - "mode": 'basic', - # Networking mode: Basic or Advanced } @@ -156,6 +154,7 @@ class TestDefaultSecurityGroupEgress(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.zone.networktype template = get_template( cls.api_client, @@ -314,6 +313,7 @@ class TestAuthorizeIngressRule(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.zone.networktype template = get_template( cls.api_client, @@ -471,6 +471,7 @@ class TestDefaultGroupEgress(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.zone.networktype template = get_template( cls.api_client, @@ -671,6 +672,7 @@ class TestDefaultGroupEgressAfterDeploy(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.zone.networktype template = get_template( cls.api_client, @@ -853,6 +855,7 @@ class TestRevokeEgressRule(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.zone.networktype template = get_template( cls.api_client, @@ -1114,6 +1117,7 @@ class TestInvalidAccountAuthroize(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.zone.networktype template = get_template( cls.api_client, @@ -1235,6 +1239,7 @@ class TestMultipleAccountsEgressRuleNeg(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.zone.networktype template = get_template( cls.api_client, @@ -1482,6 +1487,7 @@ class TestMultipleAccountsEgressRule(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.zone.networktype template = get_template( cls.api_client, @@ -1778,6 +1784,7 @@ class TestStartStopVMWithEgressRule(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.zone.networktype template = get_template( cls.api_client, @@ -1989,6 +1996,7 @@ class TestInvalidParametersForEgress(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.zone.networktype template = get_template( cls.api_client, @@ -2171,6 +2179,7 @@ class TestEgressAfterHostMaintainance(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.zone.networktype cls.pod = get_pod( cls.api_client, zoneid=cls.zone.id diff --git a/test/integration/component/test_eip_elb.py b/test/integration/component/test_eip_elb.py index 89fdd25fb25..c1ad50530b5 100644 --- a/test/integration/component/test_eip_elb.py +++ b/test/integration/component/test_eip_elb.py @@ -85,7 +85,6 @@ class Services: # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, - "mode": 'basic' } class TestEIP(cloudstackTestCase): @@ -97,6 +96,7 @@ class TestEIP(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.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, @@ -919,6 +919,7 @@ class TestELB(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.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/component/test_network_offering.py b/test/integration/component/test_network_offering.py index 0de03aa0938..8b12525103a 100644 --- a/test/integration/component/test_network_offering.py +++ b/test/integration/component/test_network_offering.py @@ -142,7 +142,6 @@ class Services: # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, - "mode": 'advanced' } @@ -158,6 +157,7 @@ class TestNOVirtualRouter(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.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, @@ -736,6 +736,7 @@ class TestNOWithNetscaler(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.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, @@ -1371,6 +1372,7 @@ class TestNetworkUpgrade(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.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, @@ -1827,6 +1829,7 @@ class TestSharedNetworkWithoutIp(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.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/component/test_project_configs.py b/test/integration/component/test_project_configs.py index 854b5a42853..f1469f22e52 100644 --- a/test/integration/component/test_project_configs.py +++ b/test/integration/component/test_project_configs.py @@ -102,7 +102,6 @@ class Services: # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, - "mode": 'advanced' } @@ -117,6 +116,7 @@ class TestUserProjectCreation(cloudstackTestCase): cls.services = Services().services # Get Zone cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype configs = Configurations.list( cls.api_client, @@ -282,6 +282,7 @@ class TestProjectCreationNegative(cloudstackTestCase): cls.services = Services().services # Get Zone cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype # Checking for prereqisits - global configs configs = Configurations.list( @@ -427,6 +428,7 @@ class TestProjectInviteRequired(cloudstackTestCase): cls.services = Services().services # Get Zone cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype # Create domains, account etc. cls.domain = get_domain(cls.api_client, cls.services) @@ -578,6 +580,7 @@ class TestProjectInviteRequiredTrue(cloudstackTestCase): cls.services = Services().services # Get Zone cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype # Create domains, account etc. cls.domain = get_domain(cls.api_client, cls.services) @@ -730,6 +733,7 @@ class TestProjectInviteTimeout(cloudstackTestCase): cls.services = Services().services # Get Zone cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype # Create domains, account etc. cls.domain = get_domain(cls.api_client, cls.services) diff --git a/test/integration/component/test_project_limits.py b/test/integration/component/test_project_limits.py index afae1808d04..ab13238e187 100644 --- a/test/integration/component/test_project_limits.py +++ b/test/integration/component/test_project_limits.py @@ -116,7 +116,6 @@ class Services: # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, - "mode": 'advanced', } @@ -131,6 +130,7 @@ class TestProjectLimits(cloudstackTestCase): cls.services = Services().services # Get Zone cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype # Create domains, account etc. cls.domain = Domain.create( @@ -481,6 +481,7 @@ class TestResourceLimitsProject(cloudstackTestCase): cls.services = Services().services # Get Zone, Domain and templates cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -921,6 +922,7 @@ class TestMaxProjectNetworks(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.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/component/test_project_resources.py b/test/integration/component/test_project_resources.py index 24091d2f89c..191ceb54cb6 100644 --- a/test/integration/component/test_project_resources.py +++ b/test/integration/component/test_project_resources.py @@ -134,7 +134,6 @@ class Services: # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, - "mode": 'advanced', } @@ -149,6 +148,7 @@ class TestOfferings(cloudstackTestCase): cls.services = Services().services # Get Zone and template cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, @@ -329,6 +329,7 @@ class TestNetwork(cloudstackTestCase): cls.services = Services().services # Get Zone and template cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, @@ -516,6 +517,7 @@ class TestTemplates(cloudstackTestCase): cls.services = Services().services # Get Zone, Domain and templates cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -745,6 +747,7 @@ class TestSnapshots(cloudstackTestCase): cls.services = Services().services # Get Zone, Domain and templates cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -891,6 +894,7 @@ class TestPublicIpAddress(cloudstackTestCase): cls.services = Services().services # Get Zone, Domain and templates cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -1190,6 +1194,7 @@ class TestSecurityGroup(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.zone.networktype template = get_template( cls.api_client, diff --git a/test/integration/component/test_project_usage.py b/test/integration/component/test_project_usage.py index 9f0488d20ce..03c42fd196f 100644 --- a/test/integration/component/test_project_usage.py +++ b/test/integration/component/test_project_usage.py @@ -109,7 +109,6 @@ class Services: # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, - "mode": 'advanced' } @@ -125,6 +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 template = get_template( cls.api_client, @@ -319,6 +319,7 @@ class TestPublicIPUsage(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.zone.networktype cls.template = get_template( cls.api_client, @@ -490,6 +491,7 @@ class TestVolumeUsage(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.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, cls.services["disk_offering"] @@ -674,6 +676,7 @@ class TestTemplateUsage(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.zone.networktype cls.services["server"]["zoneid"] = cls.zone.id template = get_template( cls.api_client, @@ -846,6 +849,7 @@ class TestISOUsage(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.zone.networktype cls.services["server"]["zoneid"] = cls.zone.id cls.services["iso"]["zoneid"] = cls.zone.id # Create Account, ISO image etc @@ -993,6 +997,7 @@ class TestLBRuleUsage(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.zone.networktype template = get_template( cls.api_client, cls.zone.id, @@ -1175,6 +1180,7 @@ class TestSnapshotUsage(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.zone.networktype template = get_template( cls.api_client, @@ -1352,6 +1358,7 @@ class TestNatRuleUsage(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.zone.networktype template = get_template( cls.api_client, cls.zone.id, @@ -1534,6 +1541,7 @@ class TestVpnUsage(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.zone.networktype template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/component/test_projects.py b/test/integration/component/test_projects.py index 3e45cae6651..95df5bf8c30 100644 --- a/test/integration/component/test_projects.py +++ b/test/integration/component/test_projects.py @@ -96,7 +96,6 @@ class Services: # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, - "mode": 'advanced' } @@ -111,6 +110,7 @@ class TestMultipleProjectCreation(cloudstackTestCase): cls.services = Services().services # Get Zone cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype # Create domains, account etc. cls.domain = get_domain( @@ -323,6 +323,7 @@ class TestCrossDomainAccountAdd(cloudstackTestCase): cls.services = Services().services # Get Zone cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls.domain = get_domain( cls.api_client, cls.services @@ -456,6 +457,7 @@ class TestDeleteAccountWithProject(cloudstackTestCase): cls.services = Services().services # Get Zone cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls.domain = get_domain( cls.api_client, cls.services @@ -569,6 +571,7 @@ class TestDeleteDomainWithProject(cloudstackTestCase): cls.services = Services().services # Get Zone cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype configs = Configurations.list( cls.api_client, @@ -713,6 +716,7 @@ class TestProjectOwners(cloudstackTestCase): cls.services ) cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype configs = Configurations.list( cls.api_client, @@ -1136,6 +1140,7 @@ class TestProjectResources(cloudstackTestCase): cls.services = Services().services # Get Zone cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls.domain = get_domain( cls.api_client, cls.services @@ -1444,6 +1449,7 @@ class TestProjectSuspendActivate(cloudstackTestCase): cls.services = Services().services # Get Zone, domain, template etc cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls.domain = get_domain( cls.api_client, cls.services diff --git a/test/integration/component/test_resource_limits.py b/test/integration/component/test_resource_limits.py index c20770ab24f..641825b4a0c 100644 --- a/test/integration/component/test_resource_limits.py +++ b/test/integration/component/test_resource_limits.py @@ -105,7 +105,6 @@ class Services: # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, - "mode": 'advanced', } @@ -118,6 +117,7 @@ class TestResourceLimitsAccount(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.zone.networktype cls.template = get_template( cls.api_client, @@ -881,6 +881,7 @@ class TestResourceLimitsDomain(cloudstackTestCase): cls.services = Services().services # Get Zone, Domain and templates cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype cls.template = get_template( cls.api_client, @@ -1338,6 +1339,7 @@ class TestMaxAccountNetworks(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.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/component/test_routers.py b/test/integration/component/test_routers.py index 02a08dee91c..452c034d5eb 100644 --- a/test/integration/component/test_routers.py +++ b/test/integration/component/test_routers.py @@ -91,7 +91,6 @@ class Services: }, "ostype": 'CentOS 5.3 (64-bit)', # Used for Get_Template : CentOS 5.3 (64 bit) - "mode": 'advanced', # Networking mode: Advanced, basic } @@ -105,6 +104,7 @@ class TestRouterServices(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.zone.networktype cls.template = get_template( cls.api_client, cls.zone.id, @@ -592,6 +592,7 @@ class TestRouterStopCreatePF(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.zone.networktype template = get_template( cls.api_client, cls.zone.id, @@ -803,6 +804,7 @@ class TestRouterStopCreateLB(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.zone.networktype template = get_template( cls.api_client, cls.zone.id, @@ -1014,6 +1016,7 @@ class TestRouterStopCreateFW(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.zone.networktype template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/component/test_security_groups.py b/test/integration/component/test_security_groups.py index 39f6d6fcd26..7459d2a2913 100644 --- a/test/integration/component/test_security_groups.py +++ b/test/integration/component/test_security_groups.py @@ -94,8 +94,6 @@ class Services: # CentOS 5.3 (64-bit) "sleep": 60, "timeout": 10, - "mode": 'basic', - # Networking mode: Basic or Advanced } @@ -125,6 +123,7 @@ class TestDefaultSecurityGroup(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.zone.networktype template = get_template( cls.api_client, @@ -397,6 +396,7 @@ class TestAuthorizeIngressRule(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.zone.networktype template = get_template( cls.api_client, @@ -532,6 +532,7 @@ class TestRevokeIngressRule(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.zone.networktype template = get_template( cls.api_client, @@ -690,6 +691,7 @@ class TestDhcpOnlyRouter(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.zone.networktype template = get_template( cls.api_client, @@ -826,6 +828,7 @@ class TestdeployVMWithUserData(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.zone.networktype template = get_template( cls.api_client, @@ -985,6 +988,7 @@ class TestDeleteSecurityGroup(cloudstackTestCase): # Get Zone, Domain and templates self.domain = get_domain(self.apiclient, self.services) self.zone = get_zone(self.apiclient, self.services) + self.services['mode'] = cls.zone.networktype template = get_template( self.apiclient, @@ -1230,6 +1234,7 @@ class TestIngressRule(cloudstackTestCase): # Get Zone, Domain and templates self.domain = get_domain(self.apiclient, self.services) self.zone = get_zone(self.apiclient, self.services) + self.services['mode'] = cls.zone.networktype template = get_template( self.apiclient, diff --git a/test/integration/component/test_snapshots.py b/test/integration/component/test_snapshots.py index 825b8c6877e..5567917371e 100644 --- a/test/integration/component/test_snapshots.py +++ b/test/integration/component/test_snapshots.py @@ -121,7 +121,6 @@ class Services: # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, - "mode": 'advanced', # Networking mode: Advanced, Basic } @@ -134,6 +133,7 @@ class TestSnapshotRootDisk(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.zone.networktype template = get_template( cls.api_client, @@ -356,6 +356,7 @@ class TestSnapshots(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.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, cls.services["disk_offering"] @@ -1190,6 +1191,7 @@ class TestCreateVMsnapshotTemplate(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.zone.networktype cls.template = get_template( cls.api_client, @@ -1485,6 +1487,7 @@ class TestAccountSnapshotClean(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.zone.networktype template = get_template( cls.api_client, @@ -1833,6 +1836,7 @@ class TestSnapshotDetachedDisk(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.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, @@ -2120,6 +2124,7 @@ class TestSnapshotLimit(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.zone.networktype template = get_template( cls.api_client, @@ -2378,6 +2383,7 @@ class TestSnapshotEvents(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.zone.networktype template = get_template( cls.api_client, diff --git a/test/integration/component/test_storage_motion.py b/test/integration/component/test_storage_motion.py new file mode 100644 index 00000000000..b893b8b7df4 --- /dev/null +++ b/test/integration/component/test_storage_motion.py @@ -0,0 +1,298 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +""" P1 tests for Storage motion +""" +#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 = { + "disk_offering":{ + "displaytext": "Small", + "name": "Small", + "disksize": 1 + }, + "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', + }, + "service_offerings": + { + "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, + } + }, + "template": { + "displaytext": "Cent OS Template", + "name": "Cent OS Template", + "passwordenabled": True, + }, + "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.3 (64-bit)', + # CentOS 5.3 (64-bit) + } + +class TestStorageMotion(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super(TestStorageMotion, 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'] = cls.zone.networktype + + template = get_template( + cls.api_client, + zone.id, + cls.services["ostype"] + ) + # Set Zones and disk offerings + cls.services["small"]["zoneid"] = zone.id + cls.services["small"]["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"] + ) + + #create a virtual machine + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["small"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.small_offering.id, + mode=cls.services["mode"] + ) + cls._cleanup = [ + cls.small_offering, + cls.account + ] + + @classmethod + def tearDownClass(cls): + cls.api_client = super(TestStorageMotion, 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", "basic", "multicluster", "storagemotion", "xenserver"]) + def test_01_migrate_vm_with_volume(self): + """Test migrate virtual machine with its volumes + """ + # Validate the following + # 1. List hosts for migration of a vm. Pick a host that + # requires storage motion too. + # 2. Migrate vm to a host. + # 3. listVM command should return this VM.State of this VM + # should be "Running" and the host should be the host + # to which the VM was migrated to in a different cluster + + hosts = Host.listForMigration( + self.apiclient, + virtualmachineid=self.virtual_machine.id + ) + + self.assertEqual( + isinstance(hosts, list), + True, + "Check the number of hosts in the zone" + ) + + # Migrate to a host that requires storage motion + hosts[:] = [host for host in hosts if host.requiresStorageMotion] + + host = hosts[0] + self.debug("Migrating VM-ID: %s to Host: %s" % ( + self.virtual_machine.id, + host.id + )) + + cmd = migrateVirtualMachineWithVolume.migrateVirtualMachineWithVolumeCmd() + cmd.hostid = host.id + cmd.virtualmachineid = self.virtual_machine.id + self.apiclient.migrateVirtualMachineWithVolume(cmd) + + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + + self.assertNotEqual( + list_vm_response, + None, + "Check virtual machine is listVirtualMachines" + ) + + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.id, + self.virtual_machine.id, + "Check virtual machine ID of migrated VM" + ) + + self.assertEqual( + vm_response.hostid, + host.id, + "Check destination hostID of migrated VM" + ) + + self.assertEqual( + vm_response.state, + 'Running', + "Check the state of VM" + ) + return + + @attr(tags = ["advanced", "basic", "multipool", "storagemotion", "xenserver"]) + def test_02_migrate_volume(self): + """Test migrate volume of a running vm + """ + # Validate the following + # 1. List all the volumes of a vm. For each volume do step 2 to 4. + # 2. List storage pools for migrating volume of a vm. Multiple + # storage pools should be present in the cluster. + # 3. Migrate volume of the vm to another pool. + # 4. Check volume is present in the new pool and is in Ready state. + + list_volumes_response = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(list_volumes_response, list), + True, + "Check list volumes response for valid list" + ) + self.assertNotEqual( + list_volumes_response, + None, + "Check if volume exists in ListVolumes" + ) + + for volume in list_volumes_response: + pools = StoragePool.listForMigration( + self.apiclient, + id=volume.id + ) + pool = pools[0] + self.debug("Migrating Volume-ID: %s to Pool: %s" % ( + volume.id, + pool.id + )) + Volume.migrate( + self.apiclient, + volumeid=volume.id, + storageid=pool.id, + livemigrate='true' + ) + migrated_volume_response = list_volumes( + self.apiclient, + id=volume.id + ) + self.assertEqual( + isinstance(migrated_volume_response, list), + True, + "Check list volumes response for valid list" + ) + self.assertNotEqual( + migrated_volume_response, + None, + "Check if volume exists in ListVolumes" + ) + migrated_volume = migrated_volume_response[0] + self.assertEqual( + migrated_volume.state, + 'Ready', + "Check migrated volume is in Ready state" + ) + self.assertEqual( + migrated_volume.storage, + pool.name, + "Check volume is on migrated pool" + ) + + return diff --git a/test/integration/component/test_templates.py b/test/integration/component/test_templates.py index 65d9fe0a764..a743bf7e690 100644 --- a/test/integration/component/test_templates.py +++ b/test/integration/component/test_templates.py @@ -97,7 +97,6 @@ class Services: "ostype": 'CentOS 5.3 (64-bit)', "sleep": 60, "timeout": 10, - "mode": 'advanced', # Networking mode: Advanced, basic } @@ -128,6 +127,7 @@ class TestCreateTemplate(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.zone.networktype cls.services["virtual_machine"]["zoneid"] = cls.zone.id cls.service_offering = ServiceOffering.create( @@ -283,6 +283,7 @@ class TestTemplates(cloudstackTestCase): # Get Zone, templates etc cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype #populate second zone id for iso copy cmd = listZones.listZonesCmd() zones = cls.api_client.listZones(cmd) diff --git a/test/integration/component/test_usage.py b/test/integration/component/test_usage.py index 82d13e5a9ff..39228ba3b7a 100644 --- a/test/integration/component/test_usage.py +++ b/test/integration/component/test_usage.py @@ -105,7 +105,6 @@ class Services: # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, - "mode": 'advanced' } @@ -118,6 +117,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.zone.networktype template = get_template( cls.api_client, @@ -301,6 +301,7 @@ class TestPublicIPUsage(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.zone.networktype template = get_template( cls.api_client, @@ -452,6 +453,7 @@ class TestVolumeUsage(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.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, cls.services["disk_offering"] @@ -625,6 +627,7 @@ class TestTemplateUsage(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.zone.networktype cls.services["server"]["zoneid"] = cls.zone.id template = get_template( cls.api_client, @@ -789,6 +792,7 @@ class TestISOUsage(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.zone.networktype cls.services["server"]["zoneid"] = cls.zone.id cls.services["iso"]["zoneid"] = cls.zone.id # Create Account, ISO image etc @@ -925,6 +929,7 @@ class TestLBRuleUsage(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.zone.networktype template = get_template( cls.api_client, cls.zone.id, @@ -1086,6 +1091,7 @@ class TestSnapshotUsage(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.zone.networktype template = get_template( cls.api_client, @@ -1252,6 +1258,7 @@ class TestNatRuleUsage(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.zone.networktype template = get_template( cls.api_client, cls.zone.id, @@ -1413,6 +1420,7 @@ class TestVpnUsage(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.zone.networktype template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/component/test_vm_passwdenabled.py b/test/integration/component/test_vm_passwdenabled.py index fb881708e2f..e3bcf678948 100644 --- a/test/integration/component/test_vm_passwdenabled.py +++ b/test/integration/component/test_vm_passwdenabled.py @@ -83,6 +83,7 @@ class TestVMPasswordEnabled(cloudstackTestCase): # Get Zone, Domain and templates domain = get_domain(cls.api_client, cls.services) zone = get_zone(cls.api_client, cls.services) + cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, zone.id, diff --git a/test/integration/component/test_volumes.py b/test/integration/component/test_volumes.py index bedf6efd8b4..f50113b1532 100644 --- a/test/integration/component/test_volumes.py +++ b/test/integration/component/test_volumes.py @@ -87,7 +87,6 @@ class Services: }, "sleep": 50, "ostype": 'CentOS 5.3 (64-bit)', - "mode": 'advanced', } @@ -101,6 +100,7 @@ class TestAttachVolume(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.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, cls.services["disk_offering"] @@ -371,6 +371,7 @@ class TestAttachDetachVolume(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.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, cls.services["disk_offering"] @@ -616,6 +617,7 @@ class TestAttachVolumeISO(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.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, cls.services["disk_offering"] @@ -807,6 +809,7 @@ class TestVolumes(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.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, cls.services["disk_offering"] @@ -1046,6 +1049,7 @@ class TestDeployVmWithCustomDisk(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.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, cls.services["disk_offering"], diff --git a/test/integration/smoke/test_global_settings.py b/test/integration/smoke/test_global_settings.py new file mode 100644 index 00000000000..12b35d774b7 --- /dev/null +++ b/test/integration/smoke/test_global_settings.py @@ -0,0 +1,72 @@ +# 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 updating the granular Configuration parameter with scope and resource id provided. +""" +#Import Local Modules +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 * +#Import System modules + +class TestUpdateConfigWithScope(cloudstackTestCase): + """ + Test to update a configuration (global setting) at various scopes + """ + def setUp(self): + self.apiClient = self.testClient.getApiClient() + + def test_UpdateConfigParamWithScope(self): + """ + test update configuration setting at zone level scope + @return: + """ + updateConfigurationCmd = updateConfiguration.updateConfigurationCmd() + updateConfigurationCmd.name = "use.external.dns" + updateConfigurationCmd.value = "true" + updateConfigurationCmd.scope = "zone" + updateConfigurationCmd.id = 1 + + updateConfigurationResponse = self.apiClient.updateConfiguration(updateConfigurationCmd) + self.debug("updated the parameter %s with value %s"%(updateConfigurationResponse.name, updateConfigurationResponse.value)) + + listConfigurationsCmd = listConfigurations.listConfigurationsCmd() + listConfigurationsCmd.cfgName = updateConfigurationResponse.name + listConfigurationsCmd.scope = "zone" + listConfigurationsCmd.id = 1 + listConfigurationsResponse = self.apiClient.listConfigurations(listConfigurationsCmd) + + self.assertNotEqual(len(listConfigurationsResponse), 0, "Check if the list API \ + returns a non-empty response") + + configParam = listConfigurationsResponse[0] + self.assertEqual(configParam.value, updateConfigurationResponse.value, "Check if the update API returned \ + is the same as the one we got in the list API") + + + def tearDown(self): + """ + Reset the configuration back to false + @return: + """ + updateConfigurationCmd = updateConfiguration.updateConfigurationCmd() + updateConfigurationCmd.name = "use.external.dns" + updateConfigurationCmd.value = "false" + updateConfigurationCmd.scope = "zone" + updateConfigurationCmd.id = 1 + self.apiClient.updateConfiguration(updateConfigurationCmd) diff --git a/test/integration/smoke/test_iso.py b/test/integration/smoke/test_iso.py index 3f8f11abdf9..0b7d2765775 100644 --- a/test/integration/smoke/test_iso.py +++ b/test/integration/smoke/test_iso.py @@ -91,7 +91,7 @@ class TestCreateIso(cloudstackTestCase): # Get Zone, Domain and templates self.domain = get_domain(self.apiclient, self.services) self.zone = get_zone(self.apiclient, self.services) - self.services['mode'] = zone.networktype + self.services['mode'] = self.zone.networktype self.services["domainid"] = self.domain.id self.services["iso_2"]["zoneid"] = self.zone.id diff --git a/test/integration/smoke/test_network.py b/test/integration/smoke/test_network.py index e2c63a4b5b4..df89eaaa695 100644 --- a/test/integration/smoke/test_network.py +++ b/test/integration/smoke/test_network.py @@ -118,7 +118,7 @@ class TestPublicIP(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'] = zone.networktype + cls.services['mode'] = cls.zone.networktype # Create Accounts & networks cls.account = Account.create( cls.api_client, diff --git a/test/integration/smoke/test_non_contigiousvlan.py b/test/integration/smoke/test_non_contigiousvlan.py new file mode 100644 index 00000000000..91b6325782c --- /dev/null +++ b/test/integration/smoke/test_non_contigiousvlan.py @@ -0,0 +1,86 @@ +# 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. + +from marvin import cloudstackTestCase +from marvin.cloudstackAPI import * +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.integration.lib.base import Account +from marvin.integration.lib.base import PhysicalNetwork +from nose.plugins.attrib import attr + +class Services(): + def __init__(self): + self.services = { + "vlan": { + "part": ["4090-4091", "4092-4096"], + "full": "4090-4096", + } + } + + +@attr(tags = ["simulator", "advanced"]) +class TestUpdatePhysicalNetwork(cloudstackTestCase): + """ + Test to extend physical network vlan range + """ + def setUp(self): + self.vlan = Services().services["vlan"] + self.apiClient = self.testClient.getApiClient() + + + def test_extendPhysicalNetworkVlan(self): + """ + Test to update a physical network and extend its vlan + """ + phy_networks = PhysicalNetwork.list(self.apiClient) + self.assertNotEqual(len(phy_networks), 0, + msg="There are no physical networks in the zone") + + self.network = phy_networks[0] + self.networkid = phy_networks[0].id + vlan1 = self.vlan["part"][0] + updatePhysicalNetworkResponse = self.network.update(self.apiClient, id = self.networkid, vlan = vlan1) + self.assert_(updatePhysicalNetworkResponse is not None, + msg="couldn't extend the physical network with vlan %s"%vlan1) + self.assert_(isinstance(self.network, PhysicalNetwork)) + + vlan2 = self.vlan["part"][1] + updatePhysicalNetworkResponse2 = self.network.update(self.apiClient, id = self.networkid, vlan = vlan2) + self.assert_(updatePhysicalNetworkResponse2 is not None, + msg="couldn't extend the physical network with vlan %s"%vlan2) + self.assert_(isinstance(self.network, PhysicalNetwork)) + + vlanranges= updatePhysicalNetworkResponse2.vlan + self.assert_(vlanranges is not None, + "No VLAN ranges found on the deployment") + self.assert_(vlanranges.find(self.vlan["full"]) > 0, "vlan ranges are not extended") + + + def tearDown(self): + """ + Teardown to update a physical network and shrink its vlan + @return: + """ + phy_networks = PhysicalNetwork.list(self.apiClient) + self.assertNotEqual(len(phy_networks), 0, + msg="There are no physical networks in the zone") + self.network = phy_networks[0] + self.networkid = phy_networks[0].id + updateResponse = self.network.update(self.apiClient, id = self.networkid, removevlan = self.vlan["full"]) + self.assert_(updateResponse.vlan.find(self.vlan["full"]) > 0, + "VLAN was not removed successfully") + diff --git a/test/integration/smoke/test_public_ip_range.py b/test/integration/smoke/test_public_ip_range.py index a7aad6b795c..7c965ea1d94 100644 --- a/test/integration/smoke/test_public_ip_range.py +++ b/test/integration/smoke/test_public_ip_range.py @@ -49,7 +49,7 @@ class Services: "endip": "10.102.197.73", "zoneid": "1", "podid": "", - "vlan": "101", + "vlan": "4444", } class TesDedicatePublicIPRange(cloudstackTestCase): diff --git a/test/integration/smoke/test_routers.py b/test/integration/smoke/test_routers.py index 93116bfd58a..7785576423a 100644 --- a/test/integration/smoke/test_routers.py +++ b/test/integration/smoke/test_routers.py @@ -80,7 +80,7 @@ class TestRouterServices(cloudstackTestCase): # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) - self.services['mode'] = zone.networktype + cls.services['mode'] = cls.zone.networktype template = get_template( cls.api_client, cls.zone.id, diff --git a/test/integration/smoke/test_ScaleVm.py b/test/integration/smoke/test_scale_vm.py similarity index 100% rename from test/integration/smoke/test_ScaleVm.py rename to test/integration/smoke/test_scale_vm.py diff --git a/test/integration/smoke/test_templates.py b/test/integration/smoke/test_templates.py index 2b0e2f5ce97..a648098079f 100644 --- a/test/integration/smoke/test_templates.py +++ b/test/integration/smoke/test_templates.py @@ -124,7 +124,7 @@ class TestCreateTemplate(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'] = zone.networktype + cls.services['mode'] = cls.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, cls.services["disk_offering"] diff --git a/test/integration/smoke/test_volumes.py b/test/integration/smoke/test_volumes.py index 9aa44eb6f1f..750f9856b22 100644 --- a/test/integration/smoke/test_volumes.py +++ b/test/integration/smoke/test_volumes.py @@ -99,7 +99,7 @@ class TestCreateVolume(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'] = zone.networktype + cls.services['mode'] = cls.zone.networktype cls.disk_offering = DiskOffering.create( cls.api_client, cls.services["disk_offering"] diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py index 5403adb99df..f8bdae281b2 100644 --- a/tools/apidoc/gen_toc.py +++ b/tools/apidoc/gen_toc.py @@ -56,6 +56,7 @@ dirname_to_dirname = { known_categories = { + 'Cisco' : 'External Device', 'SystemVm': 'System VM', 'VirtualMachine': 'Virtual Machine', 'VM': 'Virtual Machine', diff --git a/tools/appliance/definitions/systemvmtemplate/cleanup.sh b/tools/appliance/definitions/systemvmtemplate/cleanup.sh index 9e98ab03531..701d8d84000 100644 --- a/tools/appliance/definitions/systemvmtemplate/cleanup.sh +++ b/tools/appliance/definitions/systemvmtemplate/cleanup.sh @@ -12,7 +12,6 @@ rm /var/lib/dhcp/* # Make sure Udev doesn't block our network echo "cleaning up udev rules" rm /etc/udev/rules.d/70-persistent-net.rules -mkdir /etc/udev/rules.d/70-persistent-net.rules rm -rf /dev/.udev/ rm /lib/udev/rules.d/75-persistent-net-generator.rules diff --git a/tools/appliance/definitions/systemvmtemplate64/cleanup.sh b/tools/appliance/definitions/systemvmtemplate64/cleanup.sh index 9e98ab03531..701d8d84000 100644 --- a/tools/appliance/definitions/systemvmtemplate64/cleanup.sh +++ b/tools/appliance/definitions/systemvmtemplate64/cleanup.sh @@ -12,7 +12,6 @@ rm /var/lib/dhcp/* # Make sure Udev doesn't block our network echo "cleaning up udev rules" rm /etc/udev/rules.d/70-persistent-net.rules -mkdir /etc/udev/rules.d/70-persistent-net.rules rm -rf /dev/.udev/ rm /lib/udev/rules.d/75-persistent-net-generator.rules diff --git a/tools/build/build_asf.sh b/tools/build/build_asf.sh index c652a20bf42..a4a4706c6d0 100755 --- a/tools/build/build_asf.sh +++ b/tools/build/build_asf.sh @@ -17,34 +17,35 @@ # under the License. version='TESTBUILD' -sourcedir=~/incubator-cloudstack/ -outputdir=~/cs-asf-build/ +sourcedir=~/cloudstack/ +outputdir=/tmp/cloudstack-build/ branch='master' tag='no' certid='X' +committosvn='X' usage(){ - echo "usage: $0 -v version [-b branch] [-s source dir] [-o output dir] [-t [-u]] [-h]" + echo "usage: $0 -v version [-b branch] [-s source dir] [-o output dir] [-t] [-u] [-c] [-h]" echo " -v sets the version" echo " -b sets the branch (defaults to 'master')" echo " -s sets the source directory (defaults to $sourcedir)" echo " -o sets the output directory (defaults to $outputdir)" echo " -t tags the git repo with the version" - echo " -u sets the certificate ID to sign the tag with (if not provided, the default key is attempted)" - echo " -k sets the key to sign the tarball with" + echo " -u sets the certificate ID to sign with (if not provided, the default key is attempted)" + echo " -c commits build artifacts to cloudstack dev dist dir in svn" echo " -h" } -while getopts v:s:o:b:tu:k:h opt +while getopts v:s:o:b:u:tch opt do case "$opt" in v) version="$OPTARG";; s) sourcedir="$OPTARG";; o) outputdir="$OPTARG";; b) branch="$OPTARG";; - t) tag='yes';; + t) tag="yes";; u) certid="$OPTARG";; - k) keyid="--default-key $OPTARG";; + c) committosvn="yes";; h) usage exit 0;; /?) # unknown flag @@ -54,7 +55,7 @@ do done shift `expr $OPTIND - 1` -if [ $version == 'TESTBUILD' ]; then +if [ $version == "TESTBUILD" ]; then echo >&2 "A version must be specified with the -v option: build_asf.sh -v 4.0.0.RC1" exit 1 fi @@ -63,8 +64,8 @@ echo "Using version: $version" echo "Using source directory: $sourcedir" echo "Using output directory: $outputdir" echo "Using branch: $branch" -if [ $tag == 'yes' ]; then - if [ $certid == 'X' ]; then +if [ "$tag" == "yes" ]; then + if [ "$certid" == "X" ]; then echo "Tagging the branch with the version number, and signing the branch with your default certificate." else echo "Tagging the branch with the version number, and signing the branch with certificate ID $certid." @@ -80,29 +81,81 @@ else fi cd $sourcedir + +echo 'checking out correct branch' +git checkout $branch + +echo 'determining current mvn version' +export currentversion=`mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\['` +echo "found $currentversion" + +echo 'setting version numbers' +mvn versions:set -DnewVersion=$version -P vmware -P developer -P systemvm -P simulator -P baremetal -P ucs -Dnonoss +mv deps/XenServerJava/pom.xml.versionsBackup deps/XenServerJava/pom.xml +perl -pi -e 's/$ENV{'currentversion'}/$ENV{'version'}/' deps/XenServerJava/pom.xml +perl -pi -e 's/$ENV{'currentversion'}/$ENV{'version'}/' tools/apidoc/pom.xml +git clean -f + +echo 'commit changes' +git commit -a -s -m "Updating pom.xml version numbers for release $version" +export commitsh=`git show HEAD | head -n 1 | cut -d ' ' -f 2` + +echo "committed as $commitsh" + echo 'archiving' -git archive --format=tar --prefix=apache-cloudstack-$version-incubating-src/ $branch > $outputdir/apache-cloudstack-$version-incubating-src.tar -bzip2 $outputdir/apache-cloudstack-$version-incubating-src.tar +git archive --format=tar --prefix=apache-cloudstack-$version-src/ $branch > $outputdir/apache-cloudstack-$version-src.tar +bzip2 $outputdir/apache-cloudstack-$version-src.tar cd $outputdir echo 'armor' -gpg -v $keyid --armor --output apache-cloudstack-$version-incubating-src.tar.bz2.asc --detach-sig apache-cloudstack-$version-incubating-src.tar.bz2 +if [ "$certid" == "X" ]; then + gpg -v --armor --output apache-cloudstack-$version-src.tar.bz2.asc --detach-sig apache-cloudstack-$version-src.tar.bz2 +else + gpg -v --default-key $certid --armor --output apache-cloudstack-$version-src.tar.bz2.asc --detach-sig apache-cloudstack-$version-src.tar.bz2 +fi echo 'md5' -gpg -v --print-md MD5 apache-cloudstack-$version-incubating-src.tar.bz2 > apache-cloudstack-$version-incubating-src.tar.bz2.md5 +gpg -v --print-md MD5 apache-cloudstack-$version-src.tar.bz2 > apache-cloudstack-$version-src.tar.bz2.md5 echo 'sha' -gpg -v --print-md SHA512 apache-cloudstack-$version-incubating-src.tar.bz2 > apache-cloudstack-$version-incubating-src.tar.bz2.sha +gpg -v --print-md SHA512 apache-cloudstack-$version-src.tar.bz2 > apache-cloudstack-$version-src.tar.bz2.sha echo 'verify' -gpg -v --verify apache-cloudstack-$version-incubating-src.tar.bz2.asc apache-cloudstack-$version-incubating-src.tar.bz2 +gpg -v --verify apache-cloudstack-$version-src.tar.bz2.asc apache-cloudstack-$version-src.tar.bz2 -if [ $tag == 'yes' ]; then +if [ "$tag" == "yes" ]; then echo 'tag' cd $sourcedir - if [ $certid == 'X' ]; then + if [ "$certid" == "X" ]; then git tag -s $version -m "Tagging release $version on branch $branch." else git tag -u $certid -s $version -m "Tagging release $version on branch $branch." fi fi + +if [ "$committosvn" == "yes" ]; then + echo 'committing artifacts to svn' + rm -Rf /tmp/cloudstack-dev-dist + cd /tmp + svn co https://dist.apache.org/repos/dist/dev/cloudstack/ cloudstack-dev-dist + cd cloudstack-dev-dist + if [ -d "$version" ]; then + cd $version + svn rm * + else + mkdir $version + svn add $version + cd $version + fi + cp $outputdir/apache-cloudstack-$version-src.tar.bz2 . + cp $outputdir/apache-cloudstack-$version-src.tar.bz2.asc . + cp $outputdir/apache-cloudstack-$version-src.tar.bz2.md5 . + cp $outputdir/apache-cloudstack-$version-src.tar.bz2.sha . + svn add apache-cloudstack-$version-src.tar.bz2 + svn add apache-cloudstack-$version-src.tar.bz2.asc + svn add apache-cloudstack-$version-src.tar.bz2.md5 + svn add apache-cloudstack-$version-src.tar.bz2.sha + svn commit -m "Committing release candidate artifacts for $version to dist/dev/cloudstack in preparation for release vote" +fi + +echo "completed. use commit-sh of $commitsh when starting the VOTE thread" diff --git a/tools/build/setnextversion.sh b/tools/build/setnextversion.sh new file mode 100755 index 00000000000..71173a3a08c --- /dev/null +++ b/tools/build/setnextversion.sh @@ -0,0 +1,75 @@ +#!/bin/sh +# 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. + +version='TESTBUILD' +sourcedir=~/cloudstack/ +branch='master' + +usage(){ + echo "usage: $0 -v version [-b branch] [-s source dir] [-h]" + echo " -v sets the version" + echo " -b sets the branch (defaults to 'master')" + echo " -s sets the source directory (defaults to $sourcedir)" + echo " -h" +} + +while getopts v:s:b:h opt +do + case "$opt" in + v) version="$OPTARG";; + s) sourcedir="$OPTARG";; + b) branch="$OPTARG";; + h) usage + exit 0;; + /?) # unknown flag + usage + exit 1;; + esac +done +shift `expr $OPTIND - 1` + +if [ $version == 'TESTBUILD' ]; then + echo >&2 "A version must be specified with the -v option: $0 -v 4.0.0.RC1" + exit 1 +fi + +echo "Using version: $version" +echo "Using source directory: $sourcedir" +echo "Using branch: $branch" + +cd $sourcedir + +echo 'checking out correct branch' +git checkout $branch + +echo 'determining current mvn version' +export currentversion=`mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\['` +echo "found $currentversion" + +echo 'setting version numbers' +mvn versions:set -DnewVersion=$version -P vmware -P developer -P systemvm -P simulator -P baremetal -P ucs -Dnonoss +mv deps/XenServerJava/pom.xml.versionsBackup deps/XenServerJava/pom.xml +perl -pi -e 's/$ENV{'currentversion'}/$ENV{'version'}/' deps/XenServerJava/pom.xml +perl -pi -e 's/$ENV{'currentversion'}/$ENV{'version'}/' tools/apidoc/pom.xml +git clean -f + +echo 'commit changes' +git commit -a -s -m "Updating pom.xml version numbers for release $version" +export commitsh=`git show HEAD | head -n 1 | cut -d ' ' -f 2` + +echo "committed as $commitsh" diff --git a/tools/cli/cloudmonkey/requester.py b/tools/cli/cloudmonkey/requester.py index 88967fed74d..d2dae6dfc3f 100644 --- a/tools/cli/cloudmonkey/requester.py +++ b/tools/cli/cloudmonkey/requester.py @@ -61,11 +61,11 @@ def make_request(command, args, logger, host, port, args["apiKey"] = apikey args["response"] = "json" request = zip(args.keys(), args.values()) - request.sort(key=lambda x: str.lower(x[0])) + request.sort(key=lambda x: x[0].lower()) request_url = "&".join(["=".join([r[0], urllib.quote_plus(str(r[1]))]) for r in request]) - hashStr = "&".join(["=".join([str.lower(r[0]), + hashStr = "&".join(["=".join([r[0].lower(), str.lower(urllib.quote_plus(str(r[1]))).replace("+", "%20")]) for r in request]) diff --git a/tools/marvin/marvin/asyncJobMgr.py b/tools/marvin/marvin/asyncJobMgr.py index 935bebe4d7a..40304fa4141 100644 --- a/tools/marvin/marvin/asyncJobMgr.py +++ b/tools/marvin/marvin/asyncJobMgr.py @@ -54,7 +54,7 @@ class workThread(threading.Thread): try: self.lock.acquire() - result = self.connection.pollAsyncJob(job.jobId, job.responsecls).jobresult + result = self.connection.poll(job.jobId, job.responsecls).jobresult except cloudstackException.cloudstackAPIException, e: result = str(e) finally: diff --git a/tools/marvin/marvin/cloudstackConnection.py b/tools/marvin/marvin/cloudstackConnection.py index 1caeef35ff2..214a8783263 100644 --- a/tools/marvin/marvin/cloudstackConnection.py +++ b/tools/marvin/marvin/cloudstackConnection.py @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -15,141 +15,166 @@ # specific language governing permissions and limitations # under the License. -import urllib2 +import requests import urllib -import httplib import base64 import hmac import hashlib -import json -import xml.dom.minidom -import types import time -import inspect import cloudstackException -from cloudstackAPI import * +from cloudstackAPI import * import jsonHelper +from requests import ConnectionError +from requests import HTTPError +from requests import Timeout +from requests import RequestException + class cloudConnection(object): - def __init__(self, mgtSvr, port=8096, apiKey = None, securityKey = None, asyncTimeout=3600, logging=None, protocol='http', path='/client/api'): + """ Connections to make API calls to the cloudstack management server + """ + def __init__(self, mgtSvr, port=8096, apiKey=None, securityKey=None, + asyncTimeout=3600, logging=None, scheme='http', + path='client/api'): self.apiKey = apiKey self.securityKey = securityKey self.mgtSvr = mgtSvr self.port = port self.logging = logging - if protocol != 'http' and protocol != 'https': - raise ValueError("Protocol must be 'http' or 'https'.") - else: - self.protocol=protocol self.path = path - if port == 8096 or (self.apiKey == None and self.securityKey == None): - self.auth = False - else: - self.auth = True self.retries = 5 self.asyncTimeout = asyncTimeout - - def close(self): - try: - self.connection.close() - except: - pass - + self.auth = True + if port == 8096 or \ + (self.apiKey is None and self.securityKey is None): + self.auth = False + if scheme not in ['http', 'https']: + raise RequestException("Protocol must be HTTP") + self.protocol = scheme + self.baseurl = "%s://%s:%d/%s"\ + % (self.protocol, self.mgtSvr, self.port, self.path) + def __copy__(self): - return cloudConnection(self.mgtSvr, self.port, self.apiKey, self.securityKey, self.asyncTimeout, self.logging, self.protocol, self.path) - - def make_request_with_auth(self, command, requests={}): - requests["command"] = command - requests["apiKey"] = self.apiKey - requests["response"] = "json" - request = zip(requests.keys(), requests.values()) - request.sort(key=lambda x: str.lower(x[0])) - - requestUrl = "&".join(["=".join([r[0], urllib.quote_plus(str(r[1]))]) for r in request]) - hashStr = "&".join(["=".join([str.lower(r[0]), str.lower(urllib.quote_plus(str(r[1]))).replace("+", "%20")]) for r in request]) + return cloudConnection(self.mgtSvr, self.port, self.apiKey, + self.securityKey, self.asyncTimeout, + self.logging, self.protocol, self.path) - sig = urllib.quote_plus(base64.encodestring(hmac.new(self.securityKey, hashStr, hashlib.sha1).digest()).strip()) - requestUrl += "&signature=%s"%sig - - try: - self.connection = urllib2.urlopen("%s://%s:%d%s?%s"%(self.protocol, self.mgtSvr, self.port, self.path, requestUrl)) - if self.logging is not None: - self.logging.debug("sending GET request: %s"%requestUrl) - response = self.connection.read() - if self.logging is not None: - self.logging.info("got response: %s"%response) - except IOError, e: - if hasattr(e, 'reason'): - if self.logging is not None: - self.logging.critical("failed to reach %s because of %s"%(self.mgtSvr, e.reason)) - elif hasattr(e, 'code'): - if self.logging is not None: - self.logging.critical("server returned %d error code"%e.code) - raise e - except httplib.HTTPException, h: - if self.logging is not None: - self.logging.debug("encountered http Exception %s"%h.args) - if self.retries > 0: - self.retries = self.retries - 1 - self.make_request_with_auth(command, requests) - else: - self.retries = 5 - raise h - else: - return response - - def make_request_without_auth(self, command, requests={}): - requests["command"] = command - requests["response"] = "json" - requests = zip(requests.keys(), requests.values()) - requestUrl = "&".join(["=".join([request[0], urllib.quote_plus(str(request[1]))]) for request in requests]) - - self.connection = urllib2.urlopen("%s://%s:%d%s?%s"%(self.protocol, self.mgtSvr, self.port, self.path, requestUrl)) - if self.logging is not None: - self.logging.debug("sending GET request without auth: %s"%requestUrl) - response = self.connection.read() - if self.logging is not None: - self.logging.info("got response: %s"%response) - return response - - def pollAsyncJob(self, jobId, response): + def poll(self, jobid, response): + """ + polls the completion of a given jobid + @param jobid: + @param response: + @return: + """ cmd = queryAsyncJobResult.queryAsyncJobResultCmd() - cmd.jobid = jobId + cmd.jobid = jobid timeout = self.asyncTimeout - + while timeout > 0: - asyncResonse = self.make_request(cmd, response, True) - + asyncResonse = self.marvin_request(cmd, response_type=response) + if asyncResonse.jobstatus == 2: - raise cloudstackException.cloudstackAPIException("asyncquery", asyncResonse.jobresult) + raise cloudstackException.cloudstackAPIException( + "asyncquery", asyncResonse.jobresult) elif asyncResonse.jobstatus == 1: return asyncResonse - + time.sleep(5) if self.logging is not None: - self.logging.debug("job: %s still processing, will timeout in %ds"%(jobId, timeout)) + self.logging.debug("job: %s still processing," + " will timeout in %ds" % (jobid, timeout)) timeout = timeout - 5 - - raise cloudstackException.cloudstackAPIException("asyncquery", "Async job timeout %s"%jobId) - - def make_request(self, cmd, response = None, raw=False): - commandName = cmd.__class__.__name__.replace("Cmd", "") - isAsync = "false" + + raise cloudstackException.cloudstackAPIException( + "asyncquery", "Async job timeout %s" % jobid) + + def sign(self, payload): + """ + signs a given request URL when the apiKey and secretKey are known + + @param payload: dict of GET params to be signed + @return: the signature of the payload + """ + params = zip(payload.keys(), payload.values()) + params.sort(key=lambda k: str.lower(k[0])) + hashStr = "&".join( + ["=".join( + [str.lower(r[0]), + str.lower( + urllib.quote_plus(str(r[1])) + ).replace("+", "%20")] + ) for r in params] + ) + signature = base64.encodestring(hmac.new( + self.securityKey, hashStr, hashlib.sha1).digest()).strip() + self.logging.info("Computed Signature by Marvin: %s" % signature) + return signature + + def request(self, command, auth=True, payload={}, data={}): + """ + Makes requests using auth or over integration port + @param command: cloudstack API command name + eg: deployVirtualMachineCommand + @param auth: Authentication (apikey,secretKey) => True + else False for integration.api.port + @param payload: GET param data composed as a dictionary + of key,value pairs + @param data: POST data as a dictionary + @return: + """ + payload["command"] = command + payload["response"] = "json" + + if auth: + payload["apiKey"] = self.apiKey + signature = self.sign(payload) + payload["signature"] = signature + + try: + if data: + response = requests.get(self.baseurl, params=payload, + data=data) + else: + response = requests.get(self.baseurl, params=payload) + except ConnectionError, c: + self.logging.debug("Connection refused. Reason: %s : %s" % + (self.baseurl, c)) + raise c + except HTTPError, h: + self.logging.debug("Server returned error code: %s" % h) + raise h + except Timeout, t: + self.logging.debug("Connection timed out with %s" % t) + raise t + except RequestException, r: + self.logging.debug("Error returned by server %s" % r) + raise r + else: + return response + + def sanitize_command(self, cmd): + """ + Removes None values, Validates all required params are present + @param cmd: Cmd object eg: createPhysicalNetwork + @return: + """ requests = {} required = [] for attribute in dir(cmd): - if attribute != "__doc__" and attribute != "__init__" and attribute != "__module__": + if attribute != "__doc__" and attribute != "__init__" and \ + attribute != "__module__": if attribute == "isAsync": isAsync = getattr(cmd, attribute) elif attribute == "required": required = getattr(cmd, attribute) else: requests[attribute] = getattr(cmd, attribute) - + + cmdname = cmd.__class__.__name__.replace("Cmd", "") for requiredPara in required: if requests[requiredPara] is None: - raise cloudstackException.cloudstackAPIException(commandName, "%s is required"%requiredPara) - '''remove none value''' + raise cloudstackException.cloudstackAPIException( + cmdname, "%s is required" % requiredPara) for param, value in requests.items(): if value is None: requests.pop(param) @@ -163,31 +188,36 @@ class cloudConnection(object): requests.pop(param) i = 0 for val in value: - for k,v in val.iteritems(): - requests["%s[%d].%s"%(param,i,k)] = v + for k, v in val.iteritems(): + requests["%s[%d].%s" % (param, i, k)] = v i = i + 1 - - if self.logging is not None: - self.logging.info("sending command: %s %s"%(commandName, str(requests))) - result = None + return cmdname, isAsync, requests + + def marvin_request(self, cmd, data={}, response_type=None): + """ + Requester for marvin command objects + @param cmd: marvin's command from cloudstackAPI + @param data: any data to be sent in as POST + @param response_type: response type of the command in cmd + @param raw: + @return: + """ + cmdname, isAsync, payload = self.sanitize_command(cmd) + self.logging.info("sending command: %s %s" % (cmdname, str(payload))) if self.auth: - result = self.make_request_with_auth(commandName, requests) + response = self.request( + cmdname, auth=True, payload=payload, data=data) else: - result = self.make_request_without_auth(commandName, requests) - - if result is None: - return None - - result = jsonHelper.getResultObj(result, response) - if raw or isAsync == "false": - return result + response = self.request( + cmdname, auth=False, payload=payload, data=data) + + self.logging.info("Request: %s Response: %s" % + (response.url, response.text)) + response = jsonHelper.getResultObj(response.json(), response_type) + + if isAsync == "false": + return response else: - asynJobId = result.jobid - result = self.pollAsyncJob(asynJobId, response) - return result.jobresult - -if __name__ == '__main__': - xml = '407i-1-407-RS3i-1-407-RS3system1ROOT2011-07-30T14:45:19-0700Runningfalse1CA13kvm-50-2054CentOS 5.5(64-bit) no GUI (KVM)CentOS 5.5(64-bit) no GUI (KVM)false1Small Instance15005121120NetworkFilesystem380203255.255.255.065.19.181.165.19.181.110vlan://65vlan://65GuestDirecttrue06:52:da:00:00:08KVM' - conn = cloudConnection(None) - - print conn.paraseReturnXML(xml, deployVirtualMachine.deployVirtualMachineResponse()) + asyncJobId = response.jobid + response = self.poll(asyncJobId, response_type) + return response.jobresult diff --git a/tools/marvin/marvin/cloudstackTestClient.py b/tools/marvin/marvin/cloudstackTestClient.py index e4735e453db..85552ed5523 100644 --- a/tools/marvin/marvin/cloudstackTestClient.py +++ b/tools/marvin/marvin/cloudstackTestClient.py @@ -111,7 +111,8 @@ class cloudstackTestClient(object): apiKey = registerUserRes.apikey securityKey = registerUserRes.secretkey - newUserConnection = cloudstackConnection.cloudConnection(self.connection.mgtSvr, self.connection.port, apiKey, securityKey, self.connection.asyncTimeout, self.connection.logging) + newUserConnection = cloudstackConnection.cloudConnection(self.connection.mgtSvr, self.connection.port, + apiKey, securityKey, self.connection.asyncTimeout, self.connection.logging) self.userApiClient = cloudstackAPIClient.CloudStackAPIClient(newUserConnection) self.userApiClient.connection = newUserConnection return self.userApiClient diff --git a/tools/marvin/marvin/codegenerator.py b/tools/marvin/marvin/codegenerator.py index 0622e5dbc9e..b3b2a863029 100644 --- a/tools/marvin/marvin/codegenerator.py +++ b/tools/marvin/marvin/codegenerator.py @@ -184,9 +184,9 @@ class codeGenerator: body += "\n" for cmdName in self.cmdsName: - body += self.space + 'def %s(self,command):\n'%cmdName + body += self.space + 'def %s(self, command, postdata={}):\n'%cmdName body += self.space + self.space + 'response = %sResponse()\n'%cmdName - body += self.space + self.space + 'response = self.connection.make_request(command, response)\n' + body += self.space + self.space + 'response = self.connection.marvin_request(command, data=postdata, response_type=response)\n' body += self.space + self.space + 'return response\n' body += '\n' diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py index 2e270a7cd58..d358789d8da 100644 --- a/tools/marvin/marvin/deployDataCenter.py +++ b/tools/marvin/marvin/deployDataCenter.py @@ -407,7 +407,6 @@ class deployDataCenters(): logging=self.testClientLogger) if mgt.apiKey is None: apiKey, securityKey = self.registerApiKey() - self.testClient.close() self.testClient = \ cloudstackTestClient.cloudstackTestClient(mgt.mgtSvrIp, 8080, \ apiKey, securityKey, \ diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py index 0185c87fed9..92cdf81fa91 100755 --- a/tools/marvin/marvin/integration/lib/base.py +++ b/tools/marvin/marvin/integration/lib/base.py @@ -539,6 +539,13 @@ class Volume: [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.resizeVolume(cmd)) + @classmethod + def migrate(cls, apiclient, **kwargs): + """Migrate a volume""" + cmd = migrateVolume.migrateVolumeCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.migrateVolume(cmd)) + class Snapshot: """Manage Snapshot Lifecycle """ @@ -1493,6 +1500,14 @@ class Host: [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listHosts(cmd)) + @classmethod + def listForMigration(cls, apiclient, **kwargs): + """List all Hosts for migration matching criteria""" + + cmd = findHostsForMigration.findHostsForMigrationCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.findHostsForMigration(cmd)) + class StoragePool: """Manage Storage pools (Primary Storage)""" @@ -1554,6 +1569,13 @@ class StoragePool: [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listStoragePools(cmd)) + @classmethod + def listForMigration(cls, apiclient, **kwargs): + """List all storage pools for migration matching criteria""" + + cmd = findStoragePoolsForMigration.findStoragePoolsForMigrationCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.findStoragePoolsForMigration(cmd)) class Network: """Manage Network pools""" @@ -1972,7 +1994,7 @@ class PhysicalNetwork: cmd = listPhysicalNetworks.listPhysicalNetworksCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] - return(apiclient.listPhysicalNetworks(cmd)) + return map(lambda pn : PhysicalNetwork(pn.__dict__), apiclient.listPhysicalNetworks(cmd)) class SecurityGroup: """Manage Security Groups""" diff --git a/tools/marvin/marvin/integration/lib/common.py b/tools/marvin/marvin/integration/lib/common.py index 69aa733420e..e78f64a52de 100644 --- a/tools/marvin/marvin/integration/lib/common.py +++ b/tools/marvin/marvin/integration/lib/common.py @@ -134,6 +134,8 @@ def get_template(apiclient, zoneid, ostype, services=None): for template in list_templates: if template.ostypeid == ostypeid: return template + elif template.isready: + return template raise Exception("Exception: Failed to find template with OSTypeID: %s" % ostypeid) @@ -566,4 +568,4 @@ def list_vpc_offerings(apiclient, **kwargs): cmd = listVPCOfferings.listVPCOfferingsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] - return(apiclient.listVPCOfferings(cmd)) \ No newline at end of file + return(apiclient.listVPCOfferings(cmd)) diff --git a/tools/marvin/marvin/jsonHelper.py b/tools/marvin/marvin/jsonHelper.py index 652cce0bf9e..37363bc8c91 100644 --- a/tools/marvin/marvin/jsonHelper.py +++ b/tools/marvin/marvin/jsonHelper.py @@ -19,7 +19,6 @@ import cloudstackException import json import inspect from cloudstackAPI import * -import pdb class jsonLoader: '''The recursive class for building and representing objects with.''' @@ -113,12 +112,8 @@ def finalizeResultObj(result, responseName, responsecls): return result else: return result - - - + def getResultObj(returnObj, responsecls=None): - returnObj = json.loads(returnObj) - if len(returnObj) == 0: return None responseName = filter(lambda a: a!=u'cloudstack-version', returnObj.keys())[0] diff --git a/tools/marvin/setup.py b/tools/marvin/setup.py index ab5eb6f7c24..da138ce162b 100644 --- a/tools/marvin/setup.py +++ b/tools/marvin/setup.py @@ -45,6 +45,7 @@ setup(name="Marvin", license="LICENSE.txt", install_requires=[ "mysql-connector-python", + "requests", "paramiko", "nose" ], diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 0f1041a5cbe..f7ca3b36e59 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -2280,6 +2280,34 @@ div.detail-group.actions td { top: 13px; } +/** Zone filter (mixed zone management)*/ +#header .zone-filter { + float: left; + width: 111px; + margin: 9px 20px 0 2px; +} + +#header .zone-filter label { + position: absolute; + top: -3px; + color: #FFFFFF; + font-size: 11px; +} + +#header .zone-filter select { + width: 100%; + font-size: 12px; + border: 1px solid #000000; + border-bottom: #FFFFFF; + /*+border-radius:4px;*/ + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; + background: #ECECEC; + margin-top: 2px; +} + /*Navigation*/ #navigation, #browser { @@ -4371,6 +4399,17 @@ Dialogs*/ display: block; clear: both; font-size: 11px; + float: left; + height: 10px; + max-width: 287px; + margin-top: 1px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.dashboard.admin .dashboard-container.sub.alerts ul li p br { + display: none; } /*** User*/ @@ -8863,6 +8902,7 @@ div.ui-dialog div.multi-edit-add-list div.view div.data-table table.body tbody t left: 0px; top: -10px; margin-right: 9px; + display: none; } #header div.view-switcher.alt { @@ -8929,6 +8969,34 @@ div.ui-dialog div.multi-edit-add-list div.view div.data-table table.body tbody t padding: 3px 0 4px; } +/*** View switcher (drop-down)*/ +.project-switcher { + float: left; + width: 141px; + padding: 9px 17px 0 0; +} + +.project-switcher label { + position: absolute; + top: -2px; + color: #FFFFFF; + font-size: 11px; +} + +.project-switcher select { + width: 100%; + font-size: 12px; + border: 1px solid #000000; + border-bottom: #FFFFFF; + /*+border-radius:4px;*/ + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + -khtml-border-radius: 4px; + border-radius: 4px; + background: #ECECEC; + margin-top: 2px; +} + /*** Select project*/ .project-selector { display: inline-block; @@ -11394,7 +11462,7 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it border-bottom: 1px solid #FFFFFF; height: 28px; float: left; - margin: 4px 13px 0 0; + margin: 5px 13px 0 0; cursor: pointer; /*+box-shadow:inset 0px 1px 1px #000000;*/ -moz-box-shadow: inset 0px 1px 1px #000000; @@ -11612,6 +11680,17 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it background-position: 0px -707px; } +.migrate .icon, +.migrateVolume .icon { + background-position: 0px -125px; +} + +.migrate:hover .icon, +.migrateVolume:hover .icon { + background-position: 0px -707px; +} + + .attach .icon, .attachISO .icon, .attachDisk .icon { diff --git a/ui/index.jsp b/ui/index.jsp index ed18645ab72..1fbd6622194 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -1689,11 +1689,14 @@ under the License. - + + + - - + + + diff --git a/ui/modules/modules.js b/ui/modules/modules.js new file mode 100644 index 00000000000..490749ff085 --- /dev/null +++ b/ui/modules/modules.js @@ -0,0 +1,20 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +(function($, cloudStack) { + cloudStack.modules = [ + ]; +}(jQuery, cloudStack)); diff --git a/ui/scripts/accounts.js b/ui/scripts/accounts.js index 8353d70536e..7e82c0fc163 100644 --- a/ui/scripts/accounts.js +++ b/ui/scripts/accounts.js @@ -1372,6 +1372,9 @@ if (jsonObj.state == 'Destroyed') return []; + if( isAdmin() && jsonObj.isdefault == false) + allowedActions.push("remove"); + if(isAdmin()) { allowedActions.push("edit"); //updating networkdomain is allowed on any account, including system-generated default admin account if(!(jsonObj.domain == "ROOT" && jsonObj.name == "admin" && jsonObj.accounttype == 1)) { //if not system-generated default admin account @@ -1393,6 +1396,10 @@ var userActionfilter = function(args) { var jsonObj = args.context.item; var allowedActions = []; + + if( isAdmin() && jsonObj.isdefault == false) + allowedActions.push("remove"); + if(isAdmin()) { allowedActions.push("edit"); allowedActions.push("changePassword"); diff --git a/ui/scripts/cloudStack.js b/ui/scripts/cloudStack.js index 3e9bef00382..b943a946c8f 100644 --- a/ui/scripts/cloudStack.js +++ b/ui/scripts/cloudStack.js @@ -25,13 +25,13 @@ sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "domains", "events", "system", "global-settings", "configuration", "projects", "regions", "affinityGroups"]; } else if(isDomainAdmin()) { - sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "domains", "events", "projects", "affinityGroups"]; + sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "domains", "events", "projects", "regions", "affinityGroups"]; } else if (g_userProjectsEnabled) { - sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "events", "projects", "affinityGroups"]; + sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "events", "projects", "regions", "affinityGroups"]; } else { //normal user - sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "events", "affinityGroups"]; + sections = ["dashboard", "instances", "storage", "network", "templates", "accounts", "events", "regions", "affinityGroups"]; } if (cloudStack.plugins.length) { diff --git a/ui/scripts/instanceWizard.js b/ui/scripts/instanceWizard.js index e7aa673e28e..f3deb66d6ba 100644 --- a/ui/scripts/instanceWizard.js +++ b/ui/scripts/instanceWizard.js @@ -68,7 +68,6 @@ // Data providers for each wizard step steps: [ - // Step 1: Setup function(args) { if(args.initArgs.pluginForm != null && args.initArgs.pluginForm.name == "vpcTierInstanceWizard") { //from VPC Tier chart diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js index b497a78b7dc..b1c3e2e938b 100644 --- a/ui/scripts/instances.js +++ b/ui/scripts/instances.js @@ -15,6 +15,7 @@ // specific language governing permissions and limitations // under the License. (function($, cloudStack) { + var requiresStorageMotion = false; cloudStack.sections.instances = { title: 'label.instances', id: 'instances', @@ -1082,17 +1083,31 @@ validation: { required: true }, select: function(args) { $.ajax({ - url: createURL("listHosts&VirtualMachineId=" + args.context.instances[0].id), + url: createURL("findHostsForMigration&VirtualMachineId=" + args.context.instances[0].id), //url: createURL("listHosts"), //for testing only, comment it out before checking in. dataType: "json", async: true, success: function(json) { - var hosts = json.listhostsresponse.host; + if(json.findhostsformigrationresponse.host != undefined){ + var hosts = json.findhostsformigrationresponse.host; + requiresStorageMotion = json.findhostsformigrationresponse.host[0].requiresStorageMotion; var items = []; $(hosts).each(function() { - items.push({id: this.id, description: (this.name + " (" + (this.suitableformigration? "Suitable": "Not Suitable") + ")")}); - }); + if(this.requiresStorageMotion == true){ + items.push({id: this.id, description: (this.name + " (" + (this.suitableformigration? "Suitable, ": "Not Suitable, ") + "Storage migration required)" )}); + + } + else { + + items.push({id: this.id, description: (this.name + " (" + (this.suitableformigration? "Suitable": "Not Suitable") + ")" )}); + + } + }); args.response.success({data: items}); + } + else + cloudStack.dialog.notice({ message: _l('No Hosts are avaialble for Migration') }); //Only a single host in the set up + } }); } @@ -1100,7 +1115,31 @@ } }, action: function(args) { + + if(requiresStorageMotion == true){ $.ajax({ + url: createURL("migrateVirtualMachineWithVolume&hostid=" + args.data.hostId + "&virtualmachineid=" + args.context.instances[0].id), + dataType: "json", + async: true, + success: function(json) { + var jid = json.migratevirtualmachinewithvolumeresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.virtualmachine; + }, + getActionFilter: function() { + return vmActionfilter; + } + } + } + ); + } + }); + } + else{ + $.ajax({ url: createURL("migrateVirtualMachine&hostid=" + args.data.hostId + "&virtualmachineid=" + args.context.instances[0].id), dataType: "json", async: true, @@ -1111,21 +1150,6 @@ {jobId: jid, getUpdatedItem: function(json) { return json.queryasyncjobresultresponse.jobresult.virtualmachine; - /* - var vmObj; - $.ajax({ - url: createURL("listVirtualMachines&id=" + args.context.instances[0].id), - dataType: "json", - async: false, - success: function(json) { - var items = json.listvirtualmachinesresponse.virtualmachine; - if(items != null && items.length > 0) { - vmObj = items[0]; - } - } - }); - return vmObj; - */ }, getActionFilter: function() { return vmActionfilter; @@ -1135,6 +1159,8 @@ ); } }); + + } }, notification: { poll: pollAsyncJobResult @@ -1239,7 +1265,7 @@ dataType: "json", async: true, success: function(json) { - var jid = json.scaleupvirtualmachineresponse.jobid; + var jid = json.scalevirtualmachineresponse.jobid; args.response.success( {_custom: {jobId: jid, diff --git a/ui/scripts/network.js b/ui/scripts/network.js index a759fb29211..9ba725a8574 100755 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -281,29 +281,7 @@ id: 'network', sectionSelect: { preFilter: function(args) { - var havingSecurityGroupNetwork = false; - var havingBasicZones = false; - var havingAdvancedZones = true; - - // Get zone types - $.ajax({ - url: createURL('listZones'), - async: false, - success: function(json) { - var zones = json.listzonesresponse.zone ? - json.listzonesresponse.zone : []; - var basicZones = $.grep(zones, function(zone) { - return zone.networktype == 'Basic'; - }); - var advancedZones = $.grep(zones, function(zone) { - return zone.networktype == 'Advanced'; - }); - - - havingBasicZones = basicZones.length ? true : false; - havingAdvancedZones = advancedZones.length ? true : false; - } - }); + var havingSecurityGroupNetwork = false; $.ajax({ url: createURL('listNetworks', { ignoreProject: true }), @@ -322,11 +300,10 @@ var sectionsToShow = ['networks']; - if (havingAdvancedZones) { + if(args.context.zoneType != 'Basic') { //Advanced type or all types sectionsToShow.push('vpc'); sectionsToShow.push('vpnCustomerGateway'); } - if(havingSecurityGroupNetwork == true) sectionsToShow.push('securityGroups'); @@ -343,21 +320,14 @@ title: 'label.guest.networks', listView: { actions: { - add: { + add: { //add Isolated guest network (can't add Shared guest network here) label: 'label.add.guest.network', - preFilter: function(args) { - var advSgDisabledZones; - $.ajax({ - url: createURL('listZones'), - async: false, - success: function(json) { - advSgDisabledZones = $.grep(json.listzonesresponse.zone, function(zone) { - return (zone.networktype == 'Advanced' && zone.securitygroupsenabled != true); //Isolated networks can only be created in Advanced SG-disabled zone (but not in Basic zone nor Advanced SG-enabled zone) - }); - } - }); - return (advSgDisabledZones != null && advSgDisabledZones.length > 0); + preFilter: function(args) { //Isolated networks is only supported in Advanced (SG-disabled) zone + if(args.context.zoneType != 'Basic') + return true; + else + return false; }, createForm: { @@ -1061,6 +1031,11 @@ networkcidr:{label:'Network CIDR'}, + ip6gateway: { label: 'IPv6 Gateway' }, + + ip6cidr: { label: 'IPv6 CIDR' }, + + reservediprange:{label:'Reserved IP Range'}, diff --git a/ui/scripts/plugins.js b/ui/scripts/plugins.js index 5a33d56ef9f..122f4a03491 100644 --- a/ui/scripts/plugins.js +++ b/ui/scripts/plugins.js @@ -15,6 +15,10 @@ // specific language governing permissions and limitations // under the License. (function($, cloudStack, require) { + if (!cloudStack.pluginAPI) { + cloudStack.pluginAPI = {}; + } + var loadCSS = function(path) { var $link = $(''); @@ -27,50 +31,69 @@ $('head').append($link); }; - var pluginAPI = { - pollAsyncJob: pollAsyncJobResult, - apiCall: function(command, args) { - $.ajax({ - url: createURL(command), - data: args.data, - success: args.success, - error: function(json) { - args.error(parseXMLHttpResponse(json)); - } - }) - }, - addSection: function(section) { - cloudStack.sections[section.id] = $.extend(section, { - customIcon: 'plugins/' + section.id + '/icon.png' - }); - }, - extend: function(obj) { - $.extend(true, cloudStack, obj); + $.extend(cloudStack.pluginAPI, { + ui: { + pollAsyncJob: pollAsyncJobResult, + apiCall: function(command, args) { + $.ajax({ + url: createURL(command), + data: args.data, + success: args.success, + error: function(json) { + args.error(parseXMLHttpResponse(json)); + } + }); + }, + addSection: function(section) { + cloudStack.sections[section.id] = $.extend(section, { + customIcon: 'plugins/' + section.id + '/icon.png' + }); + }, + extend: function(obj) { + $.extend(true, cloudStack, obj); + } } - }; + }); cloudStack.sections.plugins = { title: 'label.plugins', - show: cloudStack.uiCustom.plugins + show: cloudStack.uiCustom.pluginListing }; - // Load plugins - $(cloudStack.plugins).map(function(index, pluginID) { - var basePath = 'plugins/' + pluginID + '/'; - var pluginJS = basePath + pluginID + '.js'; - var configJS = basePath + 'config.js'; - var pluginCSS = basePath + pluginID + '.css'; + // Load + $(['modules', 'plugins']).each(function() { + var type = this; + var paths = $(cloudStack[type]).map(function(index, id) { + return type + '/' + id + '/' + id; + }).toArray(); - require([pluginJS], function() { - require([configJS]); - loadCSS(pluginCSS); + // Load modules + require( + paths, + function() { + $(cloudStack[type]).map(function(index, id) { + var basePath = type + '/' + id + '/'; + var css = basePath + id + '.css'; + var configJS = type == 'plugins' ? basePath + 'config' : null; - // Execute plugin - cloudStack.plugins[pluginID]({ - ui: pluginAPI - }); - }); + if (configJS) { + // Load config metadata + require([configJS]); + } - // Load CSS + // Execute module + cloudStack[type][id]( + $.extend(true, {}, cloudStack.pluginAPI, { + pluginAPI: { + extend: function(api) { + cloudStack.pluginAPI[id] = api; + } + } + }) + ); + loadCSS(css); + }); + } + ); }); }(jQuery, cloudStack, require)); diff --git a/ui/scripts/regions.js b/ui/scripts/regions.js index ec5e21b7d4c..ef6f976b014 100644 --- a/ui/scripts/regions.js +++ b/ui/scripts/regions.js @@ -246,8 +246,30 @@ }, description: { label: 'label.description' - }, - /* + }, + gslbdomainname: { + label: 'GSLB Domain Name', + validation: { required: true } + }, + gslblbmethod: { + label: 'Algorithm', + select: function(args) { + var array1 = [{id: 'roundrobin', description: 'roundrobin'}, {id: 'leastconn', description: 'leastconn'}, {id: 'proximity', description: 'proximity'}]; + args.response.success({ + data: array1 + }); + } + }, + gslbservicetype: { + label: 'Service Type', + select: function(args) { + var array1 = [{id: 'tcp', description: 'tcp'}, {id: 'udp', description: 'udp'}]; + args.response.success({ + data: array1 + }); + }, + validation: { required: true } + }, domainid: { label: 'Domain', select: function(args) { @@ -293,31 +315,7 @@ else return true; } - }, - */ - gslblbmethod: { - label: 'Algorithm', - select: function(args) { - var array1 = [{id: 'roundrobin', description: 'roundrobin'}, {id: 'leastconn', description: 'leastconn'}, {id: 'proximity', description: 'proximity'}]; - args.response.success({ - data: array1 - }); - } - }, - gslbdomainname: { - label: 'GSLB Domain Name', - validation: { required: true } - }, - gslbservicetype: { - label: 'Service Type', - select: function(args) { - var array1 = [{id: 'tcp', description: 'tcp'}, {id: 'udp', description: 'udp'}]; - args.response.success({ - data: array1 - }); - }, - validation: { required: true } - } + } } }, action: function(args) { @@ -330,23 +328,22 @@ gslbservicetype: args.data.gslbservicetype }; if(args.data.description != null && args.data.description.length > 0) - $.extend(data, { description: args.data.description }); - /* + $.extend(data, { description: args.data.description }); if(args.data.domainid != null && args.data.domainid.length > 0) $.extend(data, { domainid: args.data.domainid }); if(args.data.account != null && args.data.account.length > 0) $.extend(data, { account: args.data.account }); - */ + $.ajax({ url: createURL('createGlobalLoadBalancerRule'), data: data, success: function(json) { - var jid = json.creategloballoadbalancerruleresponse.jobid; + var jid = json.creategloballoadbalancerruleresponse.jobid; args.response.success( {_custom: {jobId: jid, - getUpdatedItem: function(json) { - return json.queryasyncjobresultresponse.jobresult.globalloadbalancerrule; + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.globalloadbalancer; } } } @@ -355,9 +352,7 @@ }); }, notification: { - poll: function(args) { - poll: pollAsyncJobResult - } + poll: pollAsyncJobResult } } }, @@ -383,9 +378,246 @@ data: null }); } - } + }, + + detailView: { + name: 'GSLB details', + viewAll: { path: 'regions.lbUnderGSLB', label: 'load balancer rules' }, + actions: { + remove: { + label: 'delete GSLB', + messages: { + confirm: function(args) { + return 'Please confirm you want to delete this GSLB'; + }, + notification: function(args) { + return 'delete GSLB'; + } + }, + action: function(args) { + var data = { + id: args.context.GSLB[0].id + }; + $.ajax({ + url: createURL("deleteGlobalLoadBalancerRule"), + data: data, + success: function(json) { + var jid = json.deletegloballoadbalancerruleresponse.jobid; + args.response.success({ + _custom: { + jobId: jid + } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + tabs: { + details: { + title: 'label.details', + fields: [ + { + name: { label: 'label.name' } + }, + { + description: { label: 'label.description' }, + gslbdomainname: { label: 'GSLB Domain Name' }, + gslblbmethod: { label: 'Algorithm' }, + gslbservicetype: { label: 'Service Type' }, + id: { label: 'ID' } + } + ], + dataProvider: function(args) { + var data = { + id: args.context.GSLB[0].id + }; + $.ajax({ + url: createURL('listGlobalLoadBalancerRules'), + data: data, + success: function(json) { + var item = json.listgloballoadbalancerrulesresponse.globalloadbalancerrule[0]; + args.response.success({ + data: item + }); + } + }); + } + } + } + } } - } + }, + + lbUnderGSLB: { + id: 'lbUnderGSLB', + type: 'select', + title: 'assigned load balancer rules', + listView: { + section: 'lbUnderGSLB', + id: 'lbUnderGSLB', + label: 'assigned load balancer rules', + fields: { + name: { label: 'label.name' }, + publicport: { label: 'label.public.port' }, + privateport: { label: 'label.private.port' }, + algorithm: { label: 'label.algorithm' } + }, + dataProvider: function(args) { + var data = { + globalloadbalancerruleid: args.context.GSLB[0].id, + listAll: true + }; + $.ajax({ + url: createURL('listLoadBalancerRules'), + data: data, + success: function(json) { + var items = json.listloadbalancerrulesresponse.loadbalancerrule; + args.response.success({ + data: items + }); + } + }); + }, + actions: { + add: { + label: 'assign load balancer rule to GSLB', + messages: { + confirm: function(args) { + return 'Please confirm you want to assign load balancer rule to GSLB'; + }, + notification: function(args) { + return 'assign load balancer rule to GSLB'; + } + }, + createForm: { + title: 'assign load balancer rule to GSLB', + fields: { + loadbalancerrule: { + label: 'load balancer rule', + select: function(args) { + var data = { + globalloadbalancerruleid: args.context.GSLB[0].id, + listAll: true + }; + $.ajax({ + url: createURL('listLoadBalancerRules'), + data: data, + success: function(json) { + var items = json.listloadbalancerrulesresponse.loadbalancerrule; + args.response.success({ + data: items, + descriptionField: 'name' + }); + } + }); + } + } + } + }, + action: function(args) { + var data = { + id: args.context.GSLB[0].id, + loadbalancerrulelist: args.data.loadbalancerrule + }; + $.ajax({ + url: createURL('assignToGlobalLoadBalancerRule'), + data: data, + success: function(json) { + var jid = json.assigntogloballoadbalancerruleresponse.jobid; + args.response.success( + {_custom: + {jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.loadbalancerrule; + } + } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + + detailView: { + name: 'load balancer rule details', + actions: { + remove: { + label: 'remove load balancer rule from this GSLB', + messages: { + notification: function() { + return 'remove load balancer rule from GSLB'; + }, + confirm: function() { + return 'Please confirm you want to remove load balancer rule from GSLB'; + } + }, + action: function(args) { + $.ajax({ + url: createURL('removeFromGlobalLoadBalancerRule'), + data: { + id: args.context.lbUnderGSLB[0].id + }, + success: function(json) { + var jid = json.removefromloadbalancerruleresponse.jobid; + args.response.success({ + _custom: { + jobId: jid + } + }); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + } + }, + tabs: { + details: { + title: 'label.details', + fields: [ + { + name: { label: 'label.name' } + }, + { + publicport: { label: 'label.public.port' }, + privateport: { label: 'label.private.port' }, + algorithm: { label: 'label.algorithm' }, + publicip: { label: 'label.public.ip' }, + state: { label: 'label.state' }, + id: { label: 'label.id' }, + cidrlist: { label: 'label.cidr' }, + domain: { label: 'label.domain' }, + account: { label: 'label.account' } + } + ], + dataProvider: function(args) { + $.ajax({ + url: createURL('listLoadBalancerRules'), + data: { + id: args.context.lbUnderGSLB[0].id + }, + success: function(json) { + var item = json.listloadbalancerrulesresponse.loadbalancerrule[0]; + args.response.success({ + data: item + }); + } + }); + } + } + } + } + } + } } }; diff --git a/ui/scripts/storage.js b/ui/scripts/storage.js index 54605e266ae..1acc9c792e4 100644 --- a/ui/scripts/storage.js +++ b/ui/scripts/storage.js @@ -88,9 +88,22 @@ url: createURL("listZones&available=true"), dataType: "json", async: true, - success: function(json) { - var items = json.listzonesresponse.zone; - args.response.success({descriptionField: 'name', data: items}); + success: function(json) { + var zoneObjs; + if(args.context.zoneType == null || args.context.zoneType == '') { //all types + zoneObjs = json.listzonesresponse.zone; + } + else { //Basic type or Advanced type + zoneObjs = []; + var items = json.listzonesresponse.zone; + if(items != null) { + for(var i = 0; i < items.length; i++) { + if(items[i].networktype == args.context.zoneType) + zoneObjs.push(items[i]); + } + } + } + args.response.success({descriptionField: 'name', data: zoneObjs}); } }); } @@ -208,16 +221,29 @@ availabilityZone: { label: 'label.availability.zone', docID: 'helpUploadVolumeZone', - select: function(args) { - $.ajax({ + select: function(args) { + $.ajax({ url: createURL("listZones&available=true"), dataType: "json", async: true, - success: function(json) { - var items = json.listzonesresponse.zone; - args.response.success({descriptionField: 'name', data: items}); + success: function(json) { + var zoneObjs; + if(args.context.zoneType == null || args.context.zoneType == '') { //all types + zoneObjs = json.listzonesresponse.zone; + } + else { //Basic type or Advanced type + zoneObjs = []; + var items = json.listzonesresponse.zone; + if(items != null) { + for(var i = 0; i < items.length; i++) { + if(items[i].networktype == args.context.zoneType) + zoneObjs.push(items[i]); + } + } + } + args.response.success({descriptionField: 'name', data: zoneObjs}); } - }); + }); } }, format: { @@ -395,6 +421,69 @@ name: 'Volume details', viewAll: { path: 'storage.snapshots', label: 'label.snapshots' }, actions: { + + migrateVolume:{ + label:'Migrate Volume', + messages: { + confirm: function(args) { + return 'Do you want to migrate this volume ?' ; + }, + notification: function(args) { + return 'Volume migrated'; + } + }, + + createForm: { + title: 'Migrate Volume', + desc: '', + fields: { + storagePool: { + label: 'Storage Pool', + validation: { required: true }, + select: function(args) { + $.ajax({ + url: createURL("findStoragePoolsForMigration&id=" + args.context.volumes[0].id), + dataType: "json", + async: true, + success: function(json) { + var pools = json.findstoragepoolsformigrationresponse.storagepool; + var items = []; + $(pools).each(function() { + items.push({id: this.id, description: this.name + " (" + (this.suitableformigration? "Suitable": "Not Suitable")+")" }); + }); + args.response.success({data: items}); + + } + }); + } + } + } + + }, + + action: function(args) { + $.ajax({ + url: createURL("migrateVolume&livemigrate=true&storageid=" + args.data.storagePool + "&volumeid=" + args.context.volumes[0].id ), + dataType: "json", + async: true, + success: function(json) { + var jid = json.migratevolumeresponse.jobid; + args.response.success( + {_custom: + { + jobId: jid + } + } + ); + } + }); + }, + notification: { + poll: pollAsyncJobResult + } + + }, + takeSnapshot: { label: 'label.action.take.snapshot', messages: { @@ -961,7 +1050,7 @@ }, action: function(args) { $.ajax({ - url: createURL("migrateVolume&storageid=" + args.data.storageId + "&volumeid=" + args.context.volumes[0].id), + url: createURL("migrateVolume&storageid=" + args.data.storagePool + "&volumeid=" + args.context.volumes[0].id), dataType: "json", async: true, success: function(json) { @@ -1538,6 +1627,7 @@ var jsonObj = args.context.item; var allowedActions = []; + if (jsonObj.state == 'Destroyed' || jsonObj.state == 'Migrating' || jsonObj.state == 'Uploading') { return []; } @@ -1557,6 +1647,13 @@ allowedActions.push("downloadVolume"); } } + + if(jsonObj.type == "ROOT" || jsonObj.type =="DATADISK"){ + if(jsonObj.state == "Ready" && isAdmin() && jsonObj.virtualmachineid != null ){ + allowedActions.push("migrateVolume"); + } + } + if(jsonObj.state != "Creating") { if(jsonObj.type == "ROOT") { if (jsonObj.vmstate == "Stopped") { diff --git a/ui/scripts/system.js b/ui/scripts/system.js index f74711d273d..a92506bb2b2 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -597,7 +597,7 @@ }); } }, - /* + releaseFromAccount: { label: 'Release from Account', action: function(args) { @@ -622,6 +622,7 @@ }); } }, + addAccount: { label: 'Add Account', createForm: { @@ -675,7 +676,7 @@ }); } } - */ + }, dataProvider: function(args) { $.ajax({ @@ -2409,15 +2410,13 @@ select: function(args) { $.ajax({ url: createURL("listHosts&VirtualMachineId=" + args.context.routers[0].id), - //url: createURL("listHosts"), //for testing only, comment it out before checking in. dataType: "json", async: true, success: function(json) { var hostObjs = json.listhostsresponse.host; var items = []; $(hostObjs).each(function() { - //items.push({id: this.id, description: (this.name + ": " +(this.hasEnoughCapacity? "Available" : "Full"))}); //listHosts API no longer returns hasEnoughCapacity proprety - items.push({id: this.id, description: this.name}); + items.push({id: this.id, description: (this.name + " (" + (this.suitableformigration? "Suitable": "Not Suitable") + ")")}); }); args.response.success({data: items}); } @@ -2985,15 +2984,13 @@ select: function(args) { $.ajax({ url: createURL("listHosts&VirtualMachineId=" + args.context.routers[0].id), - //url: createURL("listHosts"), //for testing only, comment it out before checking in. dataType: "json", async: true, success: function(json) { var hostObjs = json.listhostsresponse.host; var items = []; $(hostObjs).each(function() { - //items.push({id: this.id, description: (this.name + ": " +(this.hasEnoughCapacity? "Available" : "Full"))}); //listHosts API no longer returns hasEnoughCapacity proprety - items.push({id: this.id, description: this.name}); + items.push({id: this.id, description: (this.name + " (" + (this.suitableformigration? "Suitable": "Not Suitable") + ")")}); }); args.response.success({data: items}); } @@ -3263,6 +3260,19 @@ label: 'label.private.interface', docID: 'helpNetScalerPrivateInterface' }, + + gslbprovider: { + label: 'GSLB service', + isBoolean: true, + isChecked: true + }, + gslbproviderpublicip: { + label: 'GSLB service Public IP' + }, + gslbproviderprivateip: { + label: 'GSLB service Private IP' + }, + numretries: { label: 'label.numretries', defaultValue: '2', @@ -5257,16 +5267,16 @@ validation: { required: true }, select: function(args) { $.ajax({ - url: createURL("listHosts&VirtualMachineId=" + args.context.systemVMs[0].id), - //url: createURL("listHosts"), //for testing only, comment it out before checking in. + url: createURL("findHostsForMigration&VirtualMachineId=" + args.context.systemVMs[0].id), dataType: "json", async: true, success: function(json) { var hostObjs = json.listhostsresponse.host; var items = []; $(hostObjs).each(function() { - //items.push({id: this.id, description: (this.name + ": " +(this.hasEnoughCapacity? "Available" : "Full"))}); //listHosts API no longer returns hasEnoughCapacity proprety - items.push({id: this.id, description: this.name}); + if(this.requiresStorageMotion == false){ + items.push({id: this.id, description: (this.name + " (" + (this.suitableformigration? "Suitable": "Not Suitable") + ")")}); + } }); args.response.success({data: items}); } @@ -5997,15 +6007,13 @@ select: function(args) { $.ajax({ url: createURL("listHosts&VirtualMachineId=" + args.context.routers[0].id), - //url: createURL("listHosts"), //for testing only, comment it out before checking in. dataType: "json", async: true, success: function(json) { var hostObjs = json.listhostsresponse.host; var items = []; $(hostObjs).each(function() { - //items.push({id: this.id, description: (this.name + ": " +(this.hasEnoughCapacity? "Available" : "Full"))}); //listHosts API no longer returns hasEnoughCapacity proprety - items.push({id: this.id, description: this.name}); + items.push({id: this.id, description: (this.name + " (" + (this.suitableformigration? "Suitable": "Not Suitable") + ")")}); }); args.response.success({data: items}); } @@ -6458,16 +6466,16 @@ validation: { required: true }, select: function(args) { $.ajax({ - url: createURL("listHosts&VirtualMachineId=" + args.context.systemVMs[0].id), - //url: createURL("listHosts"), //for testing only, comment it out before checking in. + url: createURL("findHostsForMigration&VirtualMachineId=" + args.context.systemVMs[0].id), dataType: "json", async: true, success: function(json) { var hostObjs = json.listhostsresponse.host; var items = []; $(hostObjs).each(function() { - //items.push({id: this.id, description: (this.name + ": " +(this.hasEnoughCapacity? "Available" : "Full"))}); //listHosts API no longer returns hasEnoughCapacity proprety - items.push({id: this.id, description: this.name}); + if(this.requiresStorageMotion == false){ + items.push({id: this.id, description: (this.name + " (" + (this.suitableformigration? "Suitable": "Not Suitable") + ")")}); + } }); args.response.success({data: items}); } @@ -6643,6 +6651,19 @@ privateinterface: { label: 'label.private.interface' }, + + gslbprovider: { + label: 'GSLB service', + isBoolean: true, + isChecked: true + }, + gslbproviderpublicip: { + label: 'GSLB service Public IP' + }, + gslbproviderprivateip: { + label: 'GSLB service Private IP' + }, + numretries: { label: 'label.numretries', defaultValue: '2' @@ -10707,6 +10728,12 @@ array1.push("&username=" + todb(args.data.username)); array1.push("&password=" + todb(args.data.password)); array1.push("&networkdevicetype=" + todb(args.data.networkdevicetype)); + + if(apiCmd == "addNetscalerLoadBalancer") { + array1.push("&gslbprovider=" + (args.data.gslbprovider == "on")); + array1.push("&gslbproviderpublicip=" + todb(args.data.gslbproviderpublicip)); + array1.push("&gslbproviderprivateip=" + todb(args.data.gslbproviderprivateip)); + } //construct URL starts here var url = []; diff --git a/ui/scripts/templates.js b/ui/scripts/templates.js index 6268f6b29b5..52e1135c681 100644 --- a/ui/scripts/templates.js +++ b/ui/scripts/templates.js @@ -115,16 +115,32 @@ url: createURL("listZones&available=true"), dataType: "json", async: true, - success: function(json) { - var zoneObjs = json.listzonesresponse.zone; - var items = []; - if (isAdmin() && !(cloudStack.context.projects && - cloudStack.context.projects[0])) - items.push({id: -1, description: "All Zones"}); - $(zoneObjs).each(function() { - items.push({id: this.id, description: this.name}); - }); - args.response.success({data: items}); + success: function(json) { + var zoneObjs; + if(args.context.zoneType == null || args.context.zoneType == '') { //all types + zoneObjs = []; + var items = json.listzonesresponse.zone; + if(items != null) { + for(var i = 0; i < items.length; i++) { + zoneObjs.push({id: items[i].id, description: items[i].name}); + } + } + } + else { //Basic type or Advanced type + zoneObjs = []; + var items = json.listzonesresponse.zone; + if(items != null) { + for(var i = 0; i < items.length; i++) { + if(items[i].networktype == args.context.zoneType) { + zoneObjs.push({id: items[i].id, description: items[i].name}); + } + } + } + } + if (isAdmin() && !(cloudStack.context.projects && cloudStack.context.projects[0])){ + zoneObjs.unshift({id: -1, description: "All Zones"}); + } + args.response.success({data: zoneObjs}); } }); } @@ -531,13 +547,29 @@ dataType: "json", async: true, success: function(json) { - var zoneObjs = json.listzonesresponse.zone; - var items = []; - $(zoneObjs).each(function() { - if(this.id != args.context.templates[0].zoneid) - items.push({id: this.id, description: this.name}); - }); - args.response.success({data: items}); + var zoneObjs = []; + var items = json.listzonesresponse.zone; + if(args.context.zoneType == null || args.context.zoneType == '') { //all types + if(items != null) { + for(var i = 0; i < items.length; i++) { + if(items[i].id != args.context.templates[0].zoneid) { //destination zone must be different from source zone + zoneObjs.push({id: items[i].id, description: items[i].name}); + } + } + } + } + else { //Basic type or Advanced type + if(items != null) { + for(var i = 0; i < items.length; i++) { + if(items[i].networktype == args.context.zoneType) { //type must be matched + if(items[i].id != args.context.templates[0].zoneid) { //destination zone must be different from source zone + zoneObjs.push({id: items[i].id, description: items[i].name}); + } + } + } + } + } + args.response.success({data: zoneObjs}); } }); } @@ -861,16 +893,32 @@ url: createURL("listZones&available=true"), dataType: "json", async: true, - success: function(json) { - var zoneObjs = json.listzonesresponse.zone; - var items = []; - if (isAdmin() && !(cloudStack.context.projects && - cloudStack.context.projects[0])) - items.push({id: -1, description: "All Zones"}); - $(zoneObjs).each(function() { - items.push({id: this.id, description: this.name}); - }); - args.response.success({data: items}); + success: function(json) { + var zoneObjs; + if(args.context.zoneType == null || args.context.zoneType == '') { //all types + zoneObjs = []; + var items = json.listzonesresponse.zone; + if(items != null) { + for(var i = 0; i < items.length; i++) { + zoneObjs.push({id: items[i].id, description: items[i].name}); + } + } + } + else { //Basic type or Advanced type + zoneObjs = []; + var items = json.listzonesresponse.zone; + if(items != null) { + for(var i = 0; i < items.length; i++) { + if(items[i].networktype == args.context.zoneType) { + zoneObjs.push({id: items[i].id, description: items[i].name}); + } + } + } + } + if (isAdmin() && !(cloudStack.context.projects && cloudStack.context.projects[0])){ + zoneObjs.unshift({id: -1, description: "All Zones"}); + } + args.response.success({data: zoneObjs}); } }); } @@ -1174,14 +1222,30 @@ url: createURL("listZones&available=true"), dataType: "json", async: true, - success: function(json) { - var zoneObjs = json.listzonesresponse.zone; - var items = []; - $(zoneObjs).each(function() { - if(this.id != args.context.isos[0].zoneid) - items.push({id: this.id, description: this.name}); - }); - args.response.success({data: items}); + success: function(json) { + var zoneObjs = []; + var items = json.listzonesresponse.zone; + if(args.context.zoneType == null || args.context.zoneType == '') { //all types + if(items != null) { + for(var i = 0; i < items.length; i++) { + if(items[i].id != args.context.isos[0].zoneid) { //destination zone must be different from source zone + zoneObjs.push({id: items[i].id, description: items[i].name}); + } + } + } + } + else { //Basic type or Advanced type + if(items != null) { + for(var i = 0; i < items.length; i++) { + if(items[i].networktype == args.context.zoneType) { //type must be matched + if(items[i].id != args.context.isos[0].zoneid) { //destination zone must be different from source zone + zoneObjs.push({id: items[i].id, description: items[i].name}); + } + } + } + } + } + args.response.success({data: zoneObjs}); } }); } diff --git a/ui/scripts/ui-custom/plugins.js b/ui/scripts/ui-custom/pluginListing.js similarity index 98% rename from ui/scripts/ui-custom/plugins.js rename to ui/scripts/ui-custom/pluginListing.js index aaf95319da1..3dcce983943 100644 --- a/ui/scripts/ui-custom/plugins.js +++ b/ui/scripts/ui-custom/pluginListing.js @@ -95,7 +95,7 @@ } }; - cloudStack.uiCustom.plugins = function() { + cloudStack.uiCustom.pluginListing = function() { var plugins = cloudStack.plugins; return elems.pluginListing({ diff --git a/ui/scripts/ui-custom/projectSelect.js b/ui/scripts/ui-custom/projectSelect.js new file mode 100644 index 00000000000..82d02c174b7 --- /dev/null +++ b/ui/scripts/ui-custom/projectSelect.js @@ -0,0 +1,66 @@ +// 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) { + $(window).bind('cloudStack.ready', function() { + var $header = $('#header .controls'); + var $projectSwitcher = $('
').addClass('project-switcher'); + var $projectSelect = $('').append( + $('